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     XIC             ic;
184 
185     GLFWbool        overrideRedirect;
186     GLFWbool        iconified;
187     GLFWbool        maximized;
188 
189     // Whether the visual supports framebuffer transparency
190     GLFWbool        transparent;
191 
192     // Cached position and size used to filter out duplicate events
193     int             width, height;
194     int             xpos, ypos;
195 
196     // The last received cursor position, regardless of source
197     int             lastCursorPosX, lastCursorPosY;
198     // The last position the cursor was warped to by GLFW
199     int             warpCursorPosX, warpCursorPosY;
200 
201     // The time of the last KeyPress event
202     Time            lastKeyTime;
203 
204 } _GLFWwindowX11;
205 
206 // X11-specific global data
207 //
208 typedef struct _GLFWlibraryX11
209 {
210     Display*        display;
211     int             screen;
212     Window          root;
213 
214     // System content scale
215     float           contentScaleX, contentScaleY;
216     // Helper window for IPC
217     Window          helperWindowHandle;
218     // Invisible cursor for hidden cursor mode
219     Cursor          hiddenCursorHandle;
220     // Context for mapping window XIDs to _GLFWwindow pointers
221     XContext        context;
222     // XIM input method
223     XIM             im;
224     // Most recent error code received by X error handler
225     int             errorCode;
226     // Primary selection string (while the primary selection is owned)
227     char*           primarySelectionString;
228     // Clipboard string (while the selection is owned)
229     char*           clipboardString;
230     // Key name string
231     char            keyName[5];
232     // X11 keycode to GLFW key LUT
233     short int       keycodes[256];
234     // GLFW key to X11 keycode LUT
235     short int       scancodes[GLFW_KEY_LAST + 1];
236     // Where to place the cursor when re-enabled
237     double          restoreCursorPosX, restoreCursorPosY;
238     // The window whose disabled cursor mode is active
239     _GLFWwindow*    disabledCursorWindow;
240 
241     // Window manager atoms
242     Atom            WM_PROTOCOLS;
243     Atom            WM_STATE;
244     Atom            WM_DELETE_WINDOW;
245     Atom            NET_WM_NAME;
246     Atom            NET_WM_ICON_NAME;
247     Atom            NET_WM_ICON;
248     Atom            NET_WM_PID;
249     Atom            NET_WM_PING;
250     Atom            NET_WM_WINDOW_TYPE;
251     Atom            NET_WM_WINDOW_TYPE_NORMAL;
252     Atom            NET_WM_STATE;
253     Atom            NET_WM_STATE_ABOVE;
254     Atom            NET_WM_STATE_FULLSCREEN;
255     Atom            NET_WM_STATE_MAXIMIZED_VERT;
256     Atom            NET_WM_STATE_MAXIMIZED_HORZ;
257     Atom            NET_WM_STATE_DEMANDS_ATTENTION;
258     Atom            NET_WM_BYPASS_COMPOSITOR;
259     Atom            NET_WM_FULLSCREEN_MONITORS;
260     Atom            NET_WM_WINDOW_OPACITY;
261     Atom            NET_WM_CM_Sx;
262     Atom            NET_WORKAREA;
263     Atom            NET_CURRENT_DESKTOP;
264     Atom            NET_ACTIVE_WINDOW;
265     Atom            NET_FRAME_EXTENTS;
266     Atom            NET_REQUEST_FRAME_EXTENTS;
267     Atom            MOTIF_WM_HINTS;
268 
269     // Xdnd (drag and drop) atoms
270     Atom            XdndAware;
271     Atom            XdndEnter;
272     Atom            XdndPosition;
273     Atom            XdndStatus;
274     Atom            XdndActionCopy;
275     Atom            XdndDrop;
276     Atom            XdndFinished;
277     Atom            XdndSelection;
278     Atom            XdndTypeList;
279     Atom            text_uri_list;
280 
281     // Selection (clipboard) atoms
282     Atom            TARGETS;
283     Atom            MULTIPLE;
284     Atom            INCR;
285     Atom            CLIPBOARD;
286     Atom            PRIMARY;
287     Atom            CLIPBOARD_MANAGER;
288     Atom            SAVE_TARGETS;
289     Atom            NULL_;
290     Atom            UTF8_STRING;
291     Atom            COMPOUND_STRING;
292     Atom            ATOM_PAIR;
293     Atom            GLFW_SELECTION;
294 
295     struct {
296         GLFWbool    available;
297         void*       handle;
298         int         eventBase;
299         int         errorBase;
300         int         major;
301         int         minor;
302         GLFWbool    gammaBroken;
303         GLFWbool    monitorBroken;
304         PFN_XRRAllocGamma AllocGamma;
305         PFN_XRRFreeCrtcInfo FreeCrtcInfo;
306         PFN_XRRFreeGamma FreeGamma;
307         PFN_XRRFreeOutputInfo FreeOutputInfo;
308         PFN_XRRFreeScreenResources FreeScreenResources;
309         PFN_XRRGetCrtcGamma GetCrtcGamma;
310         PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
311         PFN_XRRGetCrtcInfo GetCrtcInfo;
312         PFN_XRRGetOutputInfo GetOutputInfo;
313         PFN_XRRGetOutputPrimary GetOutputPrimary;
314         PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
315         PFN_XRRQueryExtension QueryExtension;
316         PFN_XRRQueryVersion QueryVersion;
317         PFN_XRRSelectInput SelectInput;
318         PFN_XRRSetCrtcConfig SetCrtcConfig;
319         PFN_XRRSetCrtcGamma SetCrtcGamma;
320         PFN_XRRUpdateConfiguration UpdateConfiguration;
321     } randr;
322 
323     struct {
324         GLFWbool    available;
325         GLFWbool    detectable;
326         int         majorOpcode;
327         int         eventBase;
328         int         errorBase;
329         int         major;
330         int         minor;
331     } xkb;
332 
333     struct {
334         int         count;
335         int         timeout;
336         int         interval;
337         int         blanking;
338         int         exposure;
339     } saver;
340 
341     struct {
342         int         version;
343         Window      source;
344         Atom        format;
345     } xdnd;
346 
347     struct {
348         void*       handle;
349         PFN_XcursorImageCreate ImageCreate;
350         PFN_XcursorImageDestroy ImageDestroy;
351         PFN_XcursorImageLoadCursor ImageLoadCursor;
352     } xcursor;
353 
354     struct {
355         GLFWbool    available;
356         void*       handle;
357         int         major;
358         int         minor;
359         PFN_XineramaIsActive IsActive;
360         PFN_XineramaQueryExtension QueryExtension;
361         PFN_XineramaQueryScreens QueryScreens;
362     } xinerama;
363 
364     struct {
365         void*       handle;
366         PFN_XGetXCBConnection GetXCBConnection;
367     } x11xcb;
368 
369     struct {
370         GLFWbool    available;
371         void*       handle;
372         int         eventBase;
373         int         errorBase;
374         PFN_XF86VidModeQueryExtension QueryExtension;
375         PFN_XF86VidModeGetGammaRamp GetGammaRamp;
376         PFN_XF86VidModeSetGammaRamp SetGammaRamp;
377         PFN_XF86VidModeGetGammaRampSize GetGammaRampSize;
378     } vidmode;
379 
380     struct {
381         GLFWbool    available;
382         void*       handle;
383         int         majorOpcode;
384         int         eventBase;
385         int         errorBase;
386         int         major;
387         int         minor;
388         PFN_XIQueryVersion QueryVersion;
389         PFN_XISelectEvents SelectEvents;
390     } xi;
391 
392     struct {
393         GLFWbool    available;
394         void*       handle;
395         int         major;
396         int         minor;
397         int         eventBase;
398         int         errorBase;
399         PFN_XRenderQueryExtension QueryExtension;
400         PFN_XRenderQueryVersion QueryVersion;
401         PFN_XRenderFindVisualFormat FindVisualFormat;
402     } xrender;
403 
404 } _GLFWlibraryX11;
405 
406 // X11-specific per-monitor data
407 //
408 typedef struct _GLFWmonitorX11
409 {
410     RROutput        output;
411     RRCrtc          crtc;
412     RRMode          oldMode;
413 
414     // Index of corresponding Xinerama screen,
415     // for EWMH full screen window placement
416     int             index;
417 
418 } _GLFWmonitorX11;
419 
420 // X11-specific per-cursor data
421 //
422 typedef struct _GLFWcursorX11
423 {
424     Cursor handle;
425 
426 } _GLFWcursorX11;
427 
428 
429 void _glfwPollMonitorsX11(void);
430 void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
431 void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
432 
433 Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);
434 
435 unsigned long _glfwGetWindowPropertyX11(Window window,
436                                         Atom property,
437                                         Atom type,
438                                         unsigned char** value);
439 GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
440 
441 void _glfwGrabErrorHandlerX11(void);
442 void _glfwReleaseErrorHandlerX11(void);
443 void _glfwInputErrorX11(int error, const char* message);
444 
445 void _glfwPushSelectionToManagerX11(void);
446 
447