1 //========================================================================
2 // GLFW 3.3 X11 - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
6 //
7 // This software is provided 'as-is', without any express or implied
8 // warranty. In no event will the authors be held liable for any damages
9 // arising from the use of this software.
10 //
11 // Permission is granted to anyone to use this software for any purpose,
12 // including commercial applications, and to alter it and redistribute it
13 // freely, subject to the following restrictions:
14 //
15 // 1. The origin of this software must not be misrepresented; you must not
16 //    claim that you wrote the original software. If you use this software
17 //    in a product, an acknowledgment in the product documentation would
18 //    be appreciated but is not required.
19 //
20 // 2. Altered source versions must be plainly marked as such, and must not
21 //    be misrepresented as being the original software.
22 //
23 // 3. This notice may not be removed or altered from any source
24 //    distribution.
25 //
26 //========================================================================
27 
28 #include <unistd.h>
29 #include <signal.h>
30 #include <stdint.h>
31 #include <dlfcn.h>
32 
33 #include <X11/Xlib.h>
34 #include <X11/keysym.h>
35 #include <X11/Xatom.h>
36 #include <X11/Xcursor/Xcursor.h>
37 
38 // The XRandR extension provides mode setting and gamma control
39 #include <X11/extensions/Xrandr.h>
40 
41 // The Xkb extension provides improved keyboard support
42 #include <X11/XKBlib.h>
43 
44 // The Xinerama extension provides legacy monitor indices
45 #include <X11/extensions/Xinerama.h>
46 
47 // The XInput extension provides raw mouse motion input
48 #include <X11/extensions/XInput2.h>
49 
50 typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
51 typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
52 typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
53 typedef void (* PFN_XRRFreeOutputInfo)(XRROutputInfo*);
54 typedef void (* PFN_XRRFreeScreenResources)(XRRScreenResources*);
55 typedef XRRCrtcGamma* (* PFN_XRRGetCrtcGamma)(Display*,RRCrtc);
56 typedef int (* PFN_XRRGetCrtcGammaSize)(Display*,RRCrtc);
57 typedef XRRCrtcInfo* (* PFN_XRRGetCrtcInfo) (Display*,XRRScreenResources*,RRCrtc);
58 typedef XRROutputInfo* (* PFN_XRRGetOutputInfo)(Display*,XRRScreenResources*,RROutput);
59 typedef RROutput (* PFN_XRRGetOutputPrimary)(Display*,Window);
60 typedef XRRScreenResources* (* PFN_XRRGetScreenResourcesCurrent)(Display*,Window);
61 typedef Bool (* PFN_XRRQueryExtension)(Display*,int*,int*);
62 typedef Status (* PFN_XRRQueryVersion)(Display*,int*,int*);
63 typedef void (* PFN_XRRSelectInput)(Display*,Window,int);
64 typedef Status (* PFN_XRRSetCrtcConfig)(Display*,XRRScreenResources*,RRCrtc,Time,int,int,RRMode,Rotation,RROutput*,int);
65 typedef void (* PFN_XRRSetCrtcGamma)(Display*,RRCrtc,XRRCrtcGamma*);
66 typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
67 #define XRRAllocGamma _glfw.x11.randr.AllocGamma
68 #define XRRFreeCrtcInfo _glfw.x11.randr.FreeCrtcInfo
69 #define XRRFreeGamma _glfw.x11.randr.FreeGamma
70 #define XRRFreeOutputInfo _glfw.x11.randr.FreeOutputInfo
71 #define XRRFreeScreenResources _glfw.x11.randr.FreeScreenResources
72 #define XRRGetCrtcGamma _glfw.x11.randr.GetCrtcGamma
73 #define XRRGetCrtcGammaSize _glfw.x11.randr.GetCrtcGammaSize
74 #define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
75 #define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
76 #define XRRGetOutputPrimary _glfw.x11.randr.GetOutputPrimary
77 #define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
78 #define XRRQueryExtension _glfw.x11.randr.QueryExtension
79 #define XRRQueryVersion _glfw.x11.randr.QueryVersion
80 #define XRRSelectInput _glfw.x11.randr.SelectInput
81 #define XRRSetCrtcConfig _glfw.x11.randr.SetCrtcConfig
82 #define XRRSetCrtcGamma _glfw.x11.randr.SetCrtcGamma
83 #define XRRUpdateConfiguration _glfw.x11.randr.UpdateConfiguration
84 
85 typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
86 typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
87 typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
88 #define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
89 #define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
90 #define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
91 
92 typedef Bool (* PFN_XineramaIsActive)(Display*);
93 typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
94 typedef XineramaScreenInfo* (* PFN_XineramaQueryScreens)(Display*,int*);
95 #define XineramaIsActive _glfw.x11.xinerama.IsActive
96 #define XineramaQueryExtension _glfw.x11.xinerama.QueryExtension
97 #define XineramaQueryScreens _glfw.x11.xinerama.QueryScreens
98 
99 typedef XID xcb_window_t;
100 typedef XID xcb_visualid_t;
101 typedef struct xcb_connection_t xcb_connection_t;
102 typedef xcb_connection_t* (* PFN_XGetXCBConnection)(Display*);
103 #define XGetXCBConnection _glfw.x11.x11xcb.GetXCBConnection
104 
105 typedef Bool (* PFN_XF86VidModeQueryExtension)(Display*,int*,int*);
106 typedef Bool (* PFN_XF86VidModeGetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
107 typedef Bool (* PFN_XF86VidModeSetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
108 typedef Bool (* PFN_XF86VidModeGetGammaRampSize)(Display*,int,int*);
109 #define XF86VidModeQueryExtension _glfw.x11.vidmode.QueryExtension
110 #define XF86VidModeGetGammaRamp _glfw.x11.vidmode.GetGammaRamp
111 #define XF86VidModeSetGammaRamp _glfw.x11.vidmode.SetGammaRamp
112 #define XF86VidModeGetGammaRampSize _glfw.x11.vidmode.GetGammaRampSize
113 
114 typedef Status (* PFN_XIQueryVersion)(Display*,int*,int*);
115 typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
116 #define XIQueryVersion _glfw.x11.xi.QueryVersion
117 #define XISelectEvents _glfw.x11.xi.SelectEvents
118 
119 typedef Bool (* PFN_XRenderQueryExtension)(Display*,int*,int*);
120 typedef Status (* PFN_XRenderQueryVersion)(Display*dpy,int*,int*);
121 typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const*);
122 #define XRenderQueryExtension _glfw.x11.xrender.QueryExtension
123 #define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
124 #define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
125 
126 typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
127 typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
128 
129 typedef struct VkXlibSurfaceCreateInfoKHR
130 {
131     VkStructureType             sType;
132     const void*                 pNext;
133     VkXlibSurfaceCreateFlagsKHR flags;
134     Display*                    dpy;
135     Window                      window;
136 } VkXlibSurfaceCreateInfoKHR;
137 
138 typedef struct VkXcbSurfaceCreateInfoKHR
139 {
140     VkStructureType             sType;
141     const void*                 pNext;
142     VkXcbSurfaceCreateFlagsKHR  flags;
143     xcb_connection_t*           connection;
144     xcb_window_t                window;
145 } VkXcbSurfaceCreateInfoKHR;
146 
147 typedef VkResult (APIENTRY *PFN_vkCreateXlibSurfaceKHR)(VkInstance,const VkXlibSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
148 typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice,uint32_t,Display*,VisualID);
149 typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
150 typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
151 
152 #include "posix_thread.h"
153 #include "posix_time.h"
154 #include "xkb_unicode.h"
155 #include "glx_context.h"
156 #include "egl_context.h"
157 #include "osmesa_context.h"
158 #if defined(__linux__)
159 #include "linux_joystick.h"
160 #else
161 #include "null_joystick.h"
162 #endif
163 
164 #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
165 #define _glfw_dlclose(handle) dlclose(handle)
166 #define _glfw_dlsym(handle, name) dlsym(handle, name)
167 
168 #define _GLFW_EGL_NATIVE_WINDOW  ((EGLNativeWindowType) window->x11.handle)
169 #define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
170 
171 #define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowX11  x11
172 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
173 #define _GLFW_PLATFORM_MONITOR_STATE        _GLFWmonitorX11 x11
174 #define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorX11  x11
175 
176 
177 // X11-specific per-window data
178 //
179 typedef struct _GLFWwindowX11
180 {
181     Colormap        colormap;
182     Window          handle;
183     Window          parent;
184     XIC             ic;
185 
186     GLFWbool        overrideRedirect;
187     GLFWbool        iconified;
188     GLFWbool        maximized;
189 
190     // Whether the visual supports framebuffer transparency
191     GLFWbool        transparent;
192 
193     // Cached position and size used to filter out duplicate events
194     int             width, height;
195     int             xpos, ypos;
196 
197     // The last received cursor position, regardless of source
198     int             lastCursorPosX, lastCursorPosY;
199     // The last position the cursor was warped to by GLFW
200     int             warpCursorPosX, warpCursorPosY;
201 
202     // The time of the last KeyPress event per keycode, for discarding
203     // duplicate key events generated for some keys by ibus
204     Time            keyPressTimes[256];
205 
206 } _GLFWwindowX11;
207 
208 // X11-specific global data
209 //
210 typedef struct _GLFWlibraryX11
211 {
212     Display*        display;
213     int             screen;
214     Window          root;
215 
216     // System content scale
217     float           contentScaleX, contentScaleY;
218     // Helper window for IPC
219     Window          helperWindowHandle;
220     // Invisible cursor for hidden cursor mode
221     Cursor          hiddenCursorHandle;
222     // Context for mapping window XIDs to _GLFWwindow pointers
223     XContext        context;
224     // XIM input method
225     XIM             im;
226     // Most recent error code received by X error handler
227     int             errorCode;
228     // Primary selection string (while the primary selection is owned)
229     char*           primarySelectionString;
230     // Clipboard string (while the selection is owned)
231     char*           clipboardString;
232     // Key name string
233     char            keynames[GLFW_KEY_LAST + 1][5];
234     // X11 keycode to GLFW key LUT
235     short int       keycodes[256];
236     // GLFW key to X11 keycode LUT
237     short int       scancodes[GLFW_KEY_LAST + 1];
238     // Where to place the cursor when re-enabled
239     double          restoreCursorPosX, restoreCursorPosY;
240     // The window whose disabled cursor mode is active
241     _GLFWwindow*    disabledCursorWindow;
242 
243     // Window manager atoms
244     Atom            NET_SUPPORTED;
245     Atom            NET_SUPPORTING_WM_CHECK;
246     Atom            WM_PROTOCOLS;
247     Atom            WM_STATE;
248     Atom            WM_DELETE_WINDOW;
249     Atom            NET_WM_NAME;
250     Atom            NET_WM_ICON_NAME;
251     Atom            NET_WM_ICON;
252     Atom            NET_WM_PID;
253     Atom            NET_WM_PING;
254     Atom            NET_WM_WINDOW_TYPE;
255     Atom            NET_WM_WINDOW_TYPE_NORMAL;
256     Atom            NET_WM_STATE;
257     Atom            NET_WM_STATE_ABOVE;
258     Atom            NET_WM_STATE_FULLSCREEN;
259     Atom            NET_WM_STATE_MAXIMIZED_VERT;
260     Atom            NET_WM_STATE_MAXIMIZED_HORZ;
261     Atom            NET_WM_STATE_DEMANDS_ATTENTION;
262     Atom            NET_WM_BYPASS_COMPOSITOR;
263     Atom            NET_WM_FULLSCREEN_MONITORS;
264     Atom            NET_WM_WINDOW_OPACITY;
265     Atom            NET_WM_CM_Sx;
266     Atom            NET_WORKAREA;
267     Atom            NET_CURRENT_DESKTOP;
268     Atom            NET_ACTIVE_WINDOW;
269     Atom            NET_FRAME_EXTENTS;
270     Atom            NET_REQUEST_FRAME_EXTENTS;
271     Atom            MOTIF_WM_HINTS;
272 
273     // Xdnd (drag and drop) atoms
274     Atom            XdndAware;
275     Atom            XdndEnter;
276     Atom            XdndPosition;
277     Atom            XdndStatus;
278     Atom            XdndActionCopy;
279     Atom            XdndDrop;
280     Atom            XdndFinished;
281     Atom            XdndSelection;
282     Atom            XdndTypeList;
283     Atom            text_uri_list;
284 
285     // Selection (clipboard) atoms
286     Atom            TARGETS;
287     Atom            MULTIPLE;
288     Atom            INCR;
289     Atom            CLIPBOARD;
290     Atom            PRIMARY;
291     Atom            CLIPBOARD_MANAGER;
292     Atom            SAVE_TARGETS;
293     Atom            NULL_;
294     Atom            UTF8_STRING;
295     Atom            COMPOUND_STRING;
296     Atom            ATOM_PAIR;
297     Atom            GLFW_SELECTION;
298 
299     struct {
300         GLFWbool    available;
301         void*       handle;
302         int         eventBase;
303         int         errorBase;
304         int         major;
305         int         minor;
306         GLFWbool    gammaBroken;
307         GLFWbool    monitorBroken;
308         PFN_XRRAllocGamma AllocGamma;
309         PFN_XRRFreeCrtcInfo FreeCrtcInfo;
310         PFN_XRRFreeGamma FreeGamma;
311         PFN_XRRFreeOutputInfo FreeOutputInfo;
312         PFN_XRRFreeScreenResources FreeScreenResources;
313         PFN_XRRGetCrtcGamma GetCrtcGamma;
314         PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
315         PFN_XRRGetCrtcInfo GetCrtcInfo;
316         PFN_XRRGetOutputInfo GetOutputInfo;
317         PFN_XRRGetOutputPrimary GetOutputPrimary;
318         PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
319         PFN_XRRQueryExtension QueryExtension;
320         PFN_XRRQueryVersion QueryVersion;
321         PFN_XRRSelectInput SelectInput;
322         PFN_XRRSetCrtcConfig SetCrtcConfig;
323         PFN_XRRSetCrtcGamma SetCrtcGamma;
324         PFN_XRRUpdateConfiguration UpdateConfiguration;
325     } randr;
326 
327     struct {
328         GLFWbool     available;
329         GLFWbool     detectable;
330         int          majorOpcode;
331         int          eventBase;
332         int          errorBase;
333         int          major;
334         int          minor;
335         unsigned int group;
336     } xkb;
337 
338     struct {
339         int         count;
340         int         timeout;
341         int         interval;
342         int         blanking;
343         int         exposure;
344     } saver;
345 
346     struct {
347         int         version;
348         Window      source;
349         Atom        format;
350     } xdnd;
351 
352     struct {
353         void*       handle;
354         PFN_XcursorImageCreate ImageCreate;
355         PFN_XcursorImageDestroy ImageDestroy;
356         PFN_XcursorImageLoadCursor ImageLoadCursor;
357     } xcursor;
358 
359     struct {
360         GLFWbool    available;
361         void*       handle;
362         int         major;
363         int         minor;
364         PFN_XineramaIsActive IsActive;
365         PFN_XineramaQueryExtension QueryExtension;
366         PFN_XineramaQueryScreens QueryScreens;
367     } xinerama;
368 
369     struct {
370         void*       handle;
371         PFN_XGetXCBConnection GetXCBConnection;
372     } x11xcb;
373 
374     struct {
375         GLFWbool    available;
376         void*       handle;
377         int         eventBase;
378         int         errorBase;
379         PFN_XF86VidModeQueryExtension QueryExtension;
380         PFN_XF86VidModeGetGammaRamp GetGammaRamp;
381         PFN_XF86VidModeSetGammaRamp SetGammaRamp;
382         PFN_XF86VidModeGetGammaRampSize GetGammaRampSize;
383     } vidmode;
384 
385     struct {
386         GLFWbool    available;
387         void*       handle;
388         int         majorOpcode;
389         int         eventBase;
390         int         errorBase;
391         int         major;
392         int         minor;
393         PFN_XIQueryVersion QueryVersion;
394         PFN_XISelectEvents SelectEvents;
395     } xi;
396 
397     struct {
398         GLFWbool    available;
399         void*       handle;
400         int         major;
401         int         minor;
402         int         eventBase;
403         int         errorBase;
404         PFN_XRenderQueryExtension QueryExtension;
405         PFN_XRenderQueryVersion QueryVersion;
406         PFN_XRenderFindVisualFormat FindVisualFormat;
407     } xrender;
408 
409 } _GLFWlibraryX11;
410 
411 // X11-specific per-monitor data
412 //
413 typedef struct _GLFWmonitorX11
414 {
415     RROutput        output;
416     RRCrtc          crtc;
417     RRMode          oldMode;
418 
419     // Index of corresponding Xinerama screen,
420     // for EWMH full screen window placement
421     int             index;
422 
423 } _GLFWmonitorX11;
424 
425 // X11-specific per-cursor data
426 //
427 typedef struct _GLFWcursorX11
428 {
429     Cursor handle;
430 
431 } _GLFWcursorX11;
432 
433 
434 void _glfwPollMonitorsX11(void);
435 void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
436 void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
437 
438 Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);
439 
440 unsigned long _glfwGetWindowPropertyX11(Window window,
441                                         Atom property,
442                                         Atom type,
443                                         unsigned char** value);
444 GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
445 
446 void _glfwGrabErrorHandlerX11(void);
447 void _glfwReleaseErrorHandlerX11(void);
448 void _glfwInputErrorX11(int error, const char* message);
449 
450 void _glfwPushSelectionToManagerX11(void);
451 
452