1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_VCL_INC_UNX_SALDISP_HXX
21 #define INCLUDED_VCL_INC_UNX_SALDISP_HXX
22 
23 class   SalDisplay;
24 class   SalColormap;
25 class   SalVisual;
26 class   SalXLib;
27 
28 #include <X11/Xlib.h>
29 #include <X11/Xutil.h>
30 #include <X11/extensions/render.h>
31 #include <epoxy/glx.h>
32 
33 #include <rtl/string.hxx>
34 #include <unx/saltype.h>
35 #include <vcl/opengl/OpenGLContext.hxx>
36 #include <vcl/ptrstyle.hxx>
37 #include <sal/types.h>
38 #include <cassert>
39 #include <list>
40 #include <unordered_map>
41 #include <vector>
42 #include <tools/gen.hxx>
43 #include <salwtype.hxx>
44 #include <unx/gendata.hxx>
45 #include <unx/gendisp.hxx>
46 #include <o3tl/enumarray.hxx>
47 
48 #include <vclpluginapi.h>
49 
50 /* From <X11/Intrinsic.h> */
51 typedef unsigned long Pixel;
52 
53 class   BitmapPalette;
54 class   SalFrame;
55 class   ColorMask;
56 
57 namespace vcl_sal { class WMAdaptor; }
58 
59 // server vendor
60 
61 typedef enum  {
62     vendor_none = 0,
63     vendor_sun,
64     vendor_unknown
65 } srv_vendor_t;
66 
67 extern "C" srv_vendor_t sal_GetServerVendor( Display *p_display );
68 
69 // MSB/Bigendian view (Color == RGB, r=0xFF0000, g=0xFF00, b=0xFF)
70 
71 enum class SalRGB { RGB,  RBG,
72               GBR,  GRB,
73               BGR,  BRG,
74               otherSalRGB };
75 
76 class SalVisual : public XVisualInfo
77 {
78     SalRGB          eRGBMode_;
79     int             nRedShift_;
80     int             nGreenShift_;
81     int             nBlueShift_;
82     int             nRedBits_;
83     int             nGreenBits_;
84     int             nBlueBits_;
85 public:
86                             SalVisual();
87                             SalVisual( const XVisualInfo* pXVI );
88 
GetVisualId() const89     VisualID        GetVisualId() const { return visualid; }
GetVisual() const90     Visual         *GetVisual() const { return visual; }
GetClass() const91     int             GetClass() const { return c_class; }
GetDepth() const92     int             GetDepth() const { return depth; }
93 
94             Pixel           GetTCPixel( Color nColor ) const;
95             Color           GetTCColor( Pixel nPixel ) const;
96 };
97 
98 // A move-only flag, used by SalColormap to track ownership of its m_aVisual.visual:
99 struct OwnershipFlag {
100     bool owner = false;
101 
102     OwnershipFlag() = default;
103 
OwnershipFlagOwnershipFlag104     OwnershipFlag(OwnershipFlag && other) noexcept: owner(other.owner) { other.owner = false; }
105 
operator =OwnershipFlag106     OwnershipFlag & operator =(OwnershipFlag && other) noexcept {
107         assert(&other != this);
108         owner = other.owner;
109         other.owner = false;
110         return *this;
111     }
112 };
113 
114 class SalColormap
115 {
116     const SalDisplay*       m_pDisplay;
117     Colormap                m_hColormap;
118     std::vector<Color>      m_aPalette;         // Pseudocolor
119     SalVisual               m_aVisual;
120     OwnershipFlag           m_aVisualOwnership;
121     std::vector<sal_uInt16>     m_aLookupTable;     // Pseudocolor: 12bit reduction
122     Pixel                   m_nWhitePixel;
123     Pixel                   m_nBlackPixel;
124     Pixel                   m_nUsed;            // Pseudocolor
125     SalX11Screen            m_nXScreen;
126 
127     void            GetPalette();
128     void            GetLookupTable();
129 public:
130     SalColormap( const SalDisplay*  pSalDisplay,
131                  Colormap           hColormap,
132                  SalX11Screen       nXScreen );
133     SalColormap( sal_uInt16         nDepth );
134     SalColormap();
135 
136     ~SalColormap();
137 
138     SalColormap(SalColormap &&) = default;
139     SalColormap & operator =(SalColormap &&) = default;
140 
GetXColormap() const141     Colormap            GetXColormap() const { return m_hColormap; }
GetDisplay() const142     const SalDisplay*   GetDisplay() const { return m_pDisplay; }
143     inline  Display*            GetXDisplay() const;
GetVisual() const144     const SalVisual&    GetVisual() const { return m_aVisual; }
GetXVisual() const145     Visual*             GetXVisual() const { return m_aVisual.GetVisual(); }
GetWhitePixel() const146     Pixel               GetWhitePixel() const { return m_nWhitePixel; }
GetBlackPixel() const147     Pixel               GetBlackPixel() const { return m_nBlackPixel; }
GetUsed() const148     Pixel               GetUsed() const { return m_nUsed; }
149 
150     bool            GetXPixels( XColor  &rColor,
151                                     int      r,
152                                     int      g,
153                                     int      b ) const;
154     inline  bool            GetXPixel( XColor  &rColor,
155                                            int      r,
156                                            int      g,
157                                            int      b ) const;
158     Pixel           GetPixel( Color nColor ) const;
159     Color           GetColor( Pixel nPixel ) const;
160 };
161 
162 class SalI18N_InputMethod;
163 
164 typedef int(*YieldFunc)(int fd, void* data);
165 
166 class SalXLib
167 {
168 protected:
169     timeval         m_aTimeout;
170     sal_uLong       m_nTimeoutMS;
171     int             m_pTimeoutFDS[2];
172 
173     int             nFDs_;
174     fd_set          aReadFDS_;
175     fd_set          aExceptionFDS_;
176 
177     Display             *m_pDisplay;
178     std::unique_ptr<SalI18N_InputMethod> m_pInputMethod;
179 
180 public:
181     SalXLib();
182     virtual         ~SalXLib();
183     virtual void    Init();
184 
185     virtual bool    Yield( bool bWait, bool bHandleAllCurrentEvents );
186     virtual void    Wakeup();
187     void            TriggerUserEventProcessing();
188 
189     virtual void    Insert( int fd, void* data,
190                             YieldFunc   pending,
191                             YieldFunc   queued,
192                             YieldFunc   handle );
193     virtual void    Remove( int fd );
194 
195     virtual void    StartTimer( sal_uInt64 nMS );
196     virtual void    StopTimer();
197 
198     virtual bool    CheckTimeout( bool bExecuteTimers = true );
199 
GetInputMethod() const200     SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod.get(); }
GetDisplay() const201     Display*             GetDisplay() const { return m_pDisplay; }
202 };
203 
204 class SalI18N_KeyboardExtension;
205 class AttributeProvider;
206 
207 extern "C" {
208     typedef Bool(*X_if_predicate)(Display*,XEvent*,XPointer);
209 }
210 
211 class GLX11Window : public GLWindow
212 {
213 public:
214     Display*           dpy;
215     int                screen;
216     Window             win;
217     XVisualInfo*       vi;
218     GLXContext         ctx;
219     OString            GLXExtensions;
220 
221     bool HasGLXExtension(const char* name) const;
222 
223     GLX11Window();
224     virtual bool Synchronize(bool bOnoff) const override;
225     virtual ~GLX11Window() override;
226 };
227 
228 class VCLPLUG_GEN_PUBLIC SalDisplay : public SalGenericDisplay
229 {
230 public:
231     struct RenderEntry
232     {
233         Pixmap      m_aPixmap;
234         Picture     m_aPicture;
235 
RenderEntrySalDisplay::RenderEntry236         RenderEntry() : m_aPixmap( 0 ), m_aPicture( 0 ) {}
237     };
238 
239     typedef std::unordered_map<int,RenderEntry> RenderEntryMap;
240 
241     struct ScreenData
242     {
243         bool                m_bInit;
244 
245         ::Window            m_aRoot;
246         ::Window            m_aRefWindow;
247         Size                m_aSize;
248         SalVisual           m_aVisual;
249         SalColormap         m_aColormap;
250         GC                  m_aMonoGC;
251         GC                  m_aCopyGC;
252         GC                  m_aAndInvertedGC;
253         GC                  m_aAndGC;
254         GC                  m_aOrGC;
255         GC                  m_aStippleGC;
256         Pixmap              m_hInvert50;
257         mutable RenderEntryMap m_aRenderData;
258 
ScreenDataSalDisplay::ScreenData259         ScreenData() :
260         m_bInit( false ),
261         m_aRoot( None ),
262         m_aRefWindow( None ),
263         m_aMonoGC( None ),
264         m_aCopyGC( None ),
265         m_aAndInvertedGC( None ),
266         m_aAndGC( None ),
267         m_aOrGC( None ),
268         m_aStippleGC( None ),
269         m_hInvert50( None ),
270         m_aRenderData( 1 )
271         {}
272     };
273 
274 protected:
275     SalXLib        *pXLib_;
276     SalI18N_KeyboardExtension   *mpKbdExtension;
277 
278     Display        *pDisp_;             // X Display
279 
280     SalX11Screen                 m_nXDefaultScreen;
281     std::vector< ScreenData >    m_aScreens;
282     ScreenData const      m_aInvalidScreenData;
283     Pair            aResolution_;       // [dpi]
284     sal_uLong       nMaxRequestSize_;   // [byte]
285 
286     srv_vendor_t    meServerVendor;
287 
288     // until x bytes
289 
290     o3tl::enumarray<PointerStyle, Cursor> aPointerCache_;
291 
292     // Keyboard
293     bool            bNumLockFromXS_;    // Num Lock handled by X Server
294     int             nNumLockIndex_;     // modifier index in modmap
295     KeySym          nShiftKeySym_;      // first shift modifier
296     KeySym          nCtrlKeySym_;       // first control modifier
297     KeySym          nMod1KeySym_;       // first mod1 modifier
298 
299     std::unique_ptr<vcl_sal::WMAdaptor> m_pWMAdaptor;
300 
301     bool            m_bXinerama;
302     std::vector< tools::Rectangle > m_aXineramaScreens;
303     std::vector< int > m_aXineramaScreenIndexMap;
304     std::list<SalObject*> m_aSalObjects;
305 
306     mutable Time    m_nLastUserEventTime; // mutable because changed on first access
307 
308     virtual bool    Dispatch( XEvent *pEvent ) = 0;
309     void            InitXinerama();
310     void            InitRandR( ::Window aRoot ) const;
311     static void     DeInitRandR();
312     void            processRandREvent( XEvent* );
313 
314     void            doDestruct();
315     void            addXineramaScreenUnique( int i, long i_nX, long i_nY, long i_nWidth, long i_nHeight );
316     Time            GetEventTimeImpl( bool bAlwaysReget = false ) const;
317 public:
318     static bool BestOpenGLVisual(Display* pDisplay, int nScreen, XVisualInfo& rVI);
319     static bool BestVisual(Display *pDisp, int nScreen, XVisualInfo &rVI);
320 
321                     SalDisplay( Display* pDisp );
322 
323     virtual        ~SalDisplay() override;
324 
325     void            Init();
326 
327 #ifdef DBG_UTIL
328     void            PrintInfo() const;
329     void            DbgPrintDisplayEvent(const char *pComment, XEvent *pEvent) const;
330 #endif
331 
332     void            Beep() const;
333 
334     void            ModifierMapping();
335     void            SimulateKeyPress( sal_uInt16 nKeyCode );
336     KeyIndicatorState  GetIndicatorState() const;
337     OUString        GetKeyNameFromKeySym( KeySym keysym ) const;
338     OUString        GetKeyName( sal_uInt16 nKeyCode ) const;
339     sal_uInt16      GetKeyCode( KeySym keysym, char*pcPrintable ) const;
340     KeySym          GetKeySym( XKeyEvent      *pEvent,
341                                char           *pPrintable,
342                                int            *pLen,
343                                KeySym         *pUnmodifiedKeySym,
344                                Status         *pStatus,
345                                XIC = nullptr ) const;
346 
347     Cursor                GetPointer( PointerStyle ePointerStyle );
348     int             CaptureMouse( SalFrame *pCapture );
349 
350     ScreenData*     initScreen( SalX11Screen nXScreen ) const;
getDataForScreen(SalX11Screen nXScreen) const351     const ScreenData&     getDataForScreen( SalX11Screen nXScreen ) const
352     {
353         if( nXScreen.getXScreen() >= m_aScreens.size() )
354             return m_aInvalidScreenData;
355         if( ! m_aScreens[nXScreen.getXScreen()].m_bInit )
356             initScreen( nXScreen );
357         return m_aScreens[nXScreen.getXScreen()];
358     }
359 
GetDrawable(SalX11Screen nXScreen) const360     ::Window         GetDrawable( SalX11Screen nXScreen ) const { return getDataForScreen( nXScreen ).m_aRefWindow; }
GetDisplay() const361     Display        *GetDisplay() const { return pDisp_; }
GetDefaultXScreen() const362     const SalX11Screen& GetDefaultXScreen() const { return m_nXDefaultScreen; }
GetScreenSize(SalX11Screen nXScreen) const363     const Size&     GetScreenSize( SalX11Screen nXScreen ) const { return getDataForScreen( nXScreen ).m_aSize; }
GetServerVendor() const364     srv_vendor_t    GetServerVendor() const { return meServerVendor; }
IsDisplay() const365     bool            IsDisplay() const { return !!pXLib_; }
GetCopyGC(SalX11Screen nXScreen) const366     GC              GetCopyGC( SalX11Screen nXScreen ) const { return getDataForScreen(nXScreen).m_aCopyGC; }
GetInvert50(SalX11Screen nXScreen) const367     Pixmap          GetInvert50( SalX11Screen nXScreen ) const { return getDataForScreen(nXScreen).m_hInvert50; }
GetColormap(SalX11Screen nXScreen) const368     const SalColormap&    GetColormap( SalX11Screen nXScreen ) const { return getDataForScreen(nXScreen).m_aColormap; }
GetVisual(SalX11Screen nXScreen) const369     const SalVisual&      GetVisual( SalX11Screen nXScreen ) const { return getDataForScreen(nXScreen).m_aVisual; }
GetRenderEntries(SalX11Screen nXScreen) const370     RenderEntryMap&       GetRenderEntries( SalX11Screen nXScreen ) const { return getDataForScreen(nXScreen).m_aRenderData; }
GetResolution() const371     const Pair     &GetResolution() const { return aResolution_; }
GetMaxRequestSize() const372     sal_uLong       GetMaxRequestSize() const { return nMaxRequestSize_; }
GetLastUserEventTime() const373     Time            GetLastUserEventTime() const { return GetEventTimeImpl(); }
374     // this is an equivalent of gdk_x11_get_server_time()
GetX11ServerTime() const375     Time            GetX11ServerTime() const { return GetEventTimeImpl( true ); }
376 
377     bool            XIfEventWithTimeout( XEvent*, XPointer, X_if_predicate ) const;
GetXLib() const378     SalXLib*        GetXLib() const { return pXLib_; }
379 
GetInputMethod() const380     SalI18N_InputMethod*        GetInputMethod()  const { return pXLib_->GetInputMethod();  }
GetKbdExtension() const381     SalI18N_KeyboardExtension*  GetKbdExtension() const { return mpKbdExtension; }
SetKbdExtension(SalI18N_KeyboardExtension * pKbdExtension)382     void            SetKbdExtension(SalI18N_KeyboardExtension *pKbdExtension)
383     { mpKbdExtension = pKbdExtension; }
getWMAdaptor() const384     ::vcl_sal::WMAdaptor* getWMAdaptor() const { return m_pWMAdaptor.get(); }
IsXinerama() const385     bool            IsXinerama() const { return m_bXinerama; }
GetXineramaScreens() const386     const std::vector< tools::Rectangle >& GetXineramaScreens() const { return m_aXineramaScreens; }
GetRootWindow(SalX11Screen nXScreen) const387     ::Window        GetRootWindow( SalX11Screen nXScreen ) const
388             { return getDataForScreen( nXScreen ).m_aRoot; }
GetXScreenCount() const389     unsigned int GetXScreenCount() const { return m_aScreens.size(); }
390 
getFrames() const391     const SalFrameSet& getFrames() const { return m_aFrames; }
392 
getSalObjects()393     std::list< SalObject* >& getSalObjects() { return m_aSalObjects; }
394 };
395 
GetXDisplay() const396 inline  Display *SalColormap::GetXDisplay() const
397 { return m_pDisplay->GetDisplay(); }
398 
399 class SalX11Display : public SalDisplay
400 {
401 public:
402              SalX11Display( Display* pDisp );
403     virtual ~SalX11Display() override;
404 
405     virtual bool        Dispatch( XEvent *pEvent ) override;
406     virtual void        Yield();
407     virtual void        TriggerUserEventProcessing() override;
408 
409     bool                IsEvent();
410     void                SetupInput();
411 };
412 
413 namespace vcl_sal {
414     // get foreign key names
415     OUString getKeysymReplacementName(
416         const OUString& pLang,
417         KeySym nSymbol );
418 
getSalDisplay(GenericUnixSalData const * data)419     inline SalDisplay *getSalDisplay(GenericUnixSalData const * data)
420     {
421         assert(data != nullptr);
422         assert(data->GetType() != SAL_DATA_GTK3);
423         return static_cast<SalDisplay *>(data->GetDisplay());
424     }
425 }
426 
427 #endif // INCLUDED_VCL_INC_UNX_SALDISP_HXX
428 
429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
430