1 /* GDK - The GIMP Drawing Kit
2  * gdkdisplay-x11.c
3  *
4  * Copyright 2001 Sun Microsystems Inc.
5  * Copyright (C) 2004 Nokia Corporation
6  *
7  * Erwann Chenede <erwann.chenede@sun.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "config.h"
24 
25 #define VK_USE_PLATFORM_XLIB_KHR
26 
27 #include "gdkdisplay-x11.h"
28 #include "gdkdisplayprivate.h"
29 
30 #include "gdkasync.h"
31 #include "gdkdisplay.h"
32 #include "gdkeventsource.h"
33 #include "gdkeventtranslator.h"
34 #include "gdkframeclockprivate.h"
35 #include "gdkinternals.h"
36 #include "gdkdeviceprivate.h"
37 #include "gdksurfaceprivate.h"
38 #include "gdkkeysprivate.h"
39 #include "gdkmarshalers.h"
40 #include "xsettings-client.h"
41 
42 #include "gdkcairocontext-x11.h"
43 #include "gdkclipboard-x11.h"
44 #include "gdkglcontext-x11.h"
45 #include "gdkkeys-x11.h"
46 #include "gdkprivate-x11.h"
47 #include "gdkscreen-x11.h"
48 #include "gdkvulkancontext-x11.h"
49 
50 #include "gdk-private.h"
51 
52 #include <glib.h>
53 #include <glib/gprintf.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <errno.h>
57 #include <unistd.h>
58 
59 #include <X11/Xatom.h>
60 #include <X11/Xlibint.h>
61 
62 #ifdef HAVE_XKB
63 #include <X11/XKBlib.h>
64 #endif
65 
66 #ifdef HAVE_XFIXES
67 #include <X11/extensions/Xfixes.h>
68 #endif
69 
70 #include <X11/extensions/shape.h>
71 
72 #ifdef HAVE_RANDR
73 #include <X11/extensions/Xrandr.h>
74 #endif
75 
76 enum {
77   XEVENT,
78   LAST_SIGNAL
79 };
80 
81 typedef struct _GdkErrorTrap  GdkErrorTrap;
82 
83 struct _GdkErrorTrap
84 {
85   /* Next sequence when trap was pushed, i.e. first sequence to
86    * ignore
87    */
88   gulong start_sequence;
89 
90   /* Next sequence when trap was popped, i.e. first sequence
91    * to not ignore. 0 if trap is still active.
92    */
93   gulong end_sequence;
94 
95   /* Most recent error code within the sequence */
96   int error_code;
97 };
98 
99 static void   gdk_x11_display_dispose            (GObject            *object);
100 static void   gdk_x11_display_finalize           (GObject            *object);
101 
102 static void     gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface);
103 
104 static GdkEvent * gdk_x11_display_translate_event (GdkEventTranslator *translator,
105                                                    GdkDisplay         *display,
106                                                    const XEvent       *xevent);
107 
108 static void gdk_internal_connection_watch (Display  *display,
109 					   XPointer  arg,
110 					   int       fd,
111 					   gboolean  opening,
112 					   XPointer *watch_data);
113 
114 typedef struct _GdkEventTypeX11 GdkEventTypeX11;
115 
116 struct _GdkEventTypeX11
117 {
118   int base;
119   int n_events;
120 };
121 
122 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
123  * but including them here has the side-effect of getting them
124  * into the internal Xlib cache
125  */
126 static const char *const precache_atoms[] = {
127   "UTF8_STRING",
128   "WM_CLIENT_LEADER",
129   "WM_DELETE_WINDOW",
130   "WM_ICON_NAME",
131   "WM_LOCALE_NAME",
132   "WM_NAME",
133   "WM_PROTOCOLS",
134   "WM_TAKE_FOCUS",
135   "WM_WINDOW_ROLE",
136   "WM_STATE",
137   "_NET_ACTIVE_WINDOW",
138   "_NET_CURRENT_DESKTOP",
139   "_NET_FRAME_EXTENTS",
140   "_NET_STARTUP_ID",
141   "_NET_WM_CM_S0",
142   "_NET_WM_DESKTOP",
143   "_NET_WM_ICON",
144   "_NET_WM_ICON_NAME",
145   "_NET_WM_NAME",
146   "_NET_WM_PID",
147   "_NET_WM_PING",
148   "_NET_WM_STATE",
149   "_NET_WM_STATE_ABOVE",
150   "_NET_WM_STATE_BELOW",
151   "_NET_WM_STATE_FULLSCREEN",
152   "_NET_WM_STATE_HIDDEN",
153   "_NET_WM_STATE_MODAL",
154   "_NET_WM_STATE_MAXIMIZED_VERT",
155   "_NET_WM_STATE_MAXIMIZED_HORZ",
156   "_NET_WM_STATE_SKIP_TASKBAR",
157   "_NET_WM_STATE_SKIP_PAGER",
158   "_NET_WM_STATE_STICKY",
159   "_NET_WM_SYNC_REQUEST",
160   "_NET_WM_SYNC_REQUEST_COUNTER",
161   "_NET_WM_WINDOW_TYPE",
162   "_NET_WM_WINDOW_TYPE_COMBO",
163   "_NET_WM_WINDOW_TYPE_DIALOG",
164   "_NET_WM_WINDOW_TYPE_DND",
165   "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
166   "_NET_WM_WINDOW_TYPE_MENU",
167   "_NET_WM_WINDOW_TYPE_NORMAL",
168   "_NET_WM_WINDOW_TYPE_POPUP_MENU",
169   "_NET_WM_WINDOW_TYPE_TOOLTIP",
170   "_NET_WM_WINDOW_TYPE_UTILITY",
171   "_NET_WM_USER_TIME",
172   "_NET_WM_USER_TIME_WINDOW",
173   "_NET_VIRTUAL_ROOTS",
174   "GDK_SELECTION",
175   "_NET_WM_STATE_FOCUSED",
176   "GDK_VISUALS",
177   "XdndAware",
178   "XdndProxy",
179   "XdndActionAsk",
180   "XdndActionCopy",
181   "XdndActionLink",
182   "XdndActionList",
183   "XdndActionMove",
184   "XdndActionPrivate",
185   "XdndDrop",
186   "XdndEnter",
187   "XdndFinished",
188   "XdndLeave",
189   "XdndPosition",
190   "XdndSelection",
191   "XdndStatus",
192   "XdndTypeList"
193 };
194 
195 static char *gdk_sm_client_id;
196 
197 static guint signals[LAST_SIGNAL] = { 0 };
198 
G_DEFINE_TYPE_WITH_CODE(GdkX11Display,gdk_x11_display,GDK_TYPE_DISPLAY,G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,gdk_x11_display_event_translator_init))199 G_DEFINE_TYPE_WITH_CODE (GdkX11Display, gdk_x11_display, GDK_TYPE_DISPLAY,
200                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
201                                                 gdk_x11_display_event_translator_init))
202 
203 static void
204 gdk_x11_display_init (GdkX11Display *self)
205 {
206   self->monitors = g_list_store_new (GDK_TYPE_MONITOR);
207 }
208 
209 static void
gdk_x11_display_event_translator_init(GdkEventTranslatorIface * iface)210 gdk_x11_display_event_translator_init (GdkEventTranslatorIface *iface)
211 {
212   iface->translate_event = gdk_x11_display_translate_event;
213 }
214 
215 #define ANY_EDGE_TILED (GDK_TOPLEVEL_STATE_LEFT_TILED | \
216                         GDK_TOPLEVEL_STATE_RIGHT_TILED | \
217                         GDK_TOPLEVEL_STATE_TOP_TILED | \
218                         GDK_TOPLEVEL_STATE_BOTTOM_TILED)
219 
220 static void
do_edge_constraint_state_check(GdkSurface * surface,GdkToplevelState old_state,GdkToplevelState * set,GdkToplevelState * unset)221 do_edge_constraint_state_check (GdkSurface      *surface,
222                                 GdkToplevelState  old_state,
223                                 GdkToplevelState *set,
224                                 GdkToplevelState *unset)
225 {
226   GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface);
227   GdkToplevelState local_set, local_unset;
228   guint edge_constraints;
229 
230   local_set = *set;
231   local_unset = *unset;
232   edge_constraints = toplevel->edge_constraints;
233 
234   /* If the WM doesn't support _GTK_EDGE_CONSTRAINTS, rely on the fallback
235    * implementation. If it supports _GTK_EDGE_CONSTRAINTS, arrange for
236    * GDK_TOPLEVEL_STATE_TILED to be set if any edge is tiled, and cleared
237    * if no edge is tiled.
238    */
239   if (!gdk_x11_surface_supports_edge_constraints (surface))
240     {
241       /* FIXME: we rely on implementation details of mutter here:
242        * mutter only tiles horizontally, and sets maxvert when it does
243        * and if it tiles, it always affects all edges
244        */
245       if (old_state & GDK_TOPLEVEL_STATE_TILED)
246         {
247           if (!toplevel->have_maxvert)
248             local_unset |= GDK_TOPLEVEL_STATE_TILED;
249         }
250       else
251         {
252           if (toplevel->have_maxvert && !toplevel->have_maxhorz)
253             local_set |= GDK_TOPLEVEL_STATE_TILED;
254         }
255     }
256   else
257     {
258       if (old_state & GDK_TOPLEVEL_STATE_TILED)
259         {
260           if (!(edge_constraints & ANY_EDGE_TILED))
261             local_unset |= GDK_TOPLEVEL_STATE_TILED;
262         }
263       else
264         {
265           if (edge_constraints & ANY_EDGE_TILED)
266             local_set |= GDK_TOPLEVEL_STATE_TILED;
267         }
268     }
269 
270   /* Top edge */
271   if (old_state & GDK_TOPLEVEL_STATE_TOP_TILED)
272     {
273       if ((edge_constraints & GDK_TOPLEVEL_STATE_TOP_TILED) == 0)
274         local_unset |= GDK_TOPLEVEL_STATE_TOP_TILED;
275     }
276   else
277     {
278       if (edge_constraints & GDK_TOPLEVEL_STATE_TOP_TILED)
279         local_set |= GDK_TOPLEVEL_STATE_TOP_TILED;
280     }
281 
282   if (old_state & GDK_TOPLEVEL_STATE_TOP_RESIZABLE)
283     {
284       if ((edge_constraints & GDK_TOPLEVEL_STATE_TOP_RESIZABLE) == 0)
285         local_unset |= GDK_TOPLEVEL_STATE_TOP_RESIZABLE;
286     }
287   else
288     {
289       if (edge_constraints & GDK_TOPLEVEL_STATE_TOP_RESIZABLE)
290         local_set |= GDK_TOPLEVEL_STATE_TOP_RESIZABLE;
291     }
292 
293   /* Right edge */
294   if (old_state & GDK_TOPLEVEL_STATE_RIGHT_TILED)
295     {
296       if ((edge_constraints & GDK_TOPLEVEL_STATE_RIGHT_TILED) == 0)
297         local_unset |= GDK_TOPLEVEL_STATE_RIGHT_TILED;
298     }
299   else
300     {
301       if (edge_constraints & GDK_TOPLEVEL_STATE_RIGHT_TILED)
302         local_set |= GDK_TOPLEVEL_STATE_RIGHT_TILED;
303     }
304 
305   if (old_state & GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE)
306     {
307       if ((edge_constraints & GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE) == 0)
308         local_unset |= GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE;
309     }
310   else
311     {
312       if (edge_constraints & GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE)
313         local_set |= GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE;
314     }
315 
316   /* Bottom edge */
317   if (old_state & GDK_TOPLEVEL_STATE_BOTTOM_TILED)
318     {
319       if ((edge_constraints & GDK_TOPLEVEL_STATE_BOTTOM_TILED) == 0)
320         local_unset |= GDK_TOPLEVEL_STATE_BOTTOM_TILED;
321     }
322   else
323     {
324       if (edge_constraints & GDK_TOPLEVEL_STATE_BOTTOM_TILED)
325         local_set |= GDK_TOPLEVEL_STATE_BOTTOM_TILED;
326     }
327 
328   if (old_state & GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE)
329     {
330       if ((edge_constraints & GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE) == 0)
331         local_unset |= GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE;
332     }
333   else
334     {
335       if (edge_constraints & GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE)
336         local_set |= GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE;
337     }
338 
339   /* Left edge */
340   if (old_state & GDK_TOPLEVEL_STATE_LEFT_TILED)
341     {
342       if ((edge_constraints & GDK_TOPLEVEL_STATE_LEFT_TILED) == 0)
343         local_unset |= GDK_TOPLEVEL_STATE_LEFT_TILED;
344     }
345   else
346     {
347       if (edge_constraints & GDK_TOPLEVEL_STATE_LEFT_TILED)
348         local_set |= GDK_TOPLEVEL_STATE_LEFT_TILED;
349     }
350 
351   if (old_state & GDK_TOPLEVEL_STATE_LEFT_RESIZABLE)
352     {
353       if ((edge_constraints & GDK_TOPLEVEL_STATE_LEFT_RESIZABLE) == 0)
354         local_unset |= GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
355     }
356   else
357     {
358       if (edge_constraints & GDK_TOPLEVEL_STATE_LEFT_RESIZABLE)
359         local_set |= GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
360     }
361 
362   *set = local_set;
363   *unset = local_unset;
364 }
365 
366 static void
do_net_wm_state_changes(GdkSurface * surface)367 do_net_wm_state_changes (GdkSurface *surface)
368 {
369   GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface);
370   GdkToplevelState old_state, set, unset;
371 
372   if (GDK_SURFACE_DESTROYED (surface) ||
373       !GDK_IS_TOPLEVEL (surface))
374     return;
375 
376   old_state = gdk_toplevel_get_state (GDK_TOPLEVEL (surface));
377 
378   set = unset = 0;
379 
380   if (old_state & GDK_TOPLEVEL_STATE_FULLSCREEN)
381     {
382       if (!toplevel->have_fullscreen)
383         unset |= GDK_TOPLEVEL_STATE_FULLSCREEN;
384     }
385   else
386     {
387       if (toplevel->have_fullscreen)
388         set |= GDK_TOPLEVEL_STATE_FULLSCREEN;
389     }
390 
391   /* Our "maximized" means both vertical and horizontal; if only one,
392    * we don't expose that via GDK
393    */
394   if (old_state & GDK_TOPLEVEL_STATE_MAXIMIZED)
395     {
396       if (!(toplevel->have_maxvert && toplevel->have_maxhorz))
397         unset |= GDK_TOPLEVEL_STATE_MAXIMIZED;
398     }
399   else
400     {
401       if (toplevel->have_maxvert && toplevel->have_maxhorz)
402         set |= GDK_TOPLEVEL_STATE_MAXIMIZED;
403     }
404 
405   if (old_state & GDK_TOPLEVEL_STATE_FOCUSED)
406     {
407       if (!toplevel->have_focused)
408         unset |= GDK_TOPLEVEL_STATE_FOCUSED;
409     }
410   else
411     {
412       if (toplevel->have_focused)
413         set |= GDK_TOPLEVEL_STATE_FOCUSED;
414     }
415 
416   if (old_state & GDK_TOPLEVEL_STATE_MINIMIZED)
417     {
418       if (!toplevel->have_hidden)
419         unset |= GDK_TOPLEVEL_STATE_MINIMIZED;
420     }
421   else
422     {
423       if (toplevel->have_hidden)
424         set |= GDK_TOPLEVEL_STATE_MINIMIZED;
425     }
426 
427   /* Update edge constraints and tiling */
428   do_edge_constraint_state_check (surface, old_state, &set, &unset);
429 
430   gdk_synthesize_surface_state (surface, unset, set);
431 }
432 
433 static void
gdk_check_wm_desktop_changed(GdkSurface * surface)434 gdk_check_wm_desktop_changed (GdkSurface *surface)
435 {
436   GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface);
437   GdkDisplay *display = GDK_SURFACE_DISPLAY (surface);
438 
439   Atom type;
440   int format;
441   gulong nitems;
442   gulong bytes_after;
443   guchar *data;
444   gulong *desktop;
445 
446   type = None;
447   gdk_x11_display_error_trap_push (display);
448   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
449                       GDK_SURFACE_XID (surface),
450                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
451                       0, G_MAXLONG, False, XA_CARDINAL, &type,
452                       &format, &nitems,
453                       &bytes_after, &data);
454   gdk_x11_display_error_trap_pop_ignored (display);
455 
456   if (type != None)
457     {
458       desktop = (gulong *)data;
459       toplevel->on_all_desktops = ((*desktop & 0xFFFFFFFF) == 0xFFFFFFFF);
460       XFree (desktop);
461     }
462   else
463     toplevel->on_all_desktops = FALSE;
464 
465   do_net_wm_state_changes (surface);
466 }
467 
468 static void
gdk_check_wm_state_changed(GdkSurface * surface)469 gdk_check_wm_state_changed (GdkSurface *surface)
470 {
471   GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface);
472   GdkDisplay *display = GDK_SURFACE_DISPLAY (surface);
473   GdkX11Screen *screen = GDK_SURFACE_SCREEN (surface);
474 
475   Atom type;
476   int format;
477   gulong nitems;
478   gulong bytes_after;
479   guchar *data;
480   Atom *atoms = NULL;
481   gulong i;
482 
483   toplevel->have_maxvert = FALSE;
484   toplevel->have_maxhorz = FALSE;
485   toplevel->have_fullscreen = FALSE;
486   toplevel->have_focused = FALSE;
487   toplevel->have_hidden = FALSE;
488 
489   type = None;
490   gdk_x11_display_error_trap_push (display);
491   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_SURFACE_XID (surface),
492 		      gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
493 		      0, G_MAXLONG, False, XA_ATOM, &type, &format, &nitems,
494 		      &bytes_after, &data);
495   gdk_x11_display_error_trap_pop_ignored (display);
496 
497   if (type != None)
498     {
499       Atom maxvert_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_VERT");
500       Atom maxhorz_atom	= gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_MAXIMIZED_HORZ");
501       Atom fullscreen_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FULLSCREEN");
502       Atom focused_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_FOCUSED");
503       Atom hidden_atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_HIDDEN");
504 
505       atoms = (Atom *)data;
506 
507       i = 0;
508       while (i < nitems)
509         {
510           if (atoms[i] == maxvert_atom)
511             toplevel->have_maxvert = TRUE;
512           else if (atoms[i] == maxhorz_atom)
513             toplevel->have_maxhorz = TRUE;
514           else if (atoms[i] == fullscreen_atom)
515             toplevel->have_fullscreen = TRUE;
516           else if (atoms[i] == focused_atom)
517             toplevel->have_focused = TRUE;
518           else if (atoms[i] == hidden_atom)
519             toplevel->have_hidden = TRUE;
520 
521           ++i;
522         }
523 
524       XFree (atoms);
525     }
526 
527   if (!gdk_x11_screen_supports_net_wm_hint (screen,
528                                             g_intern_static_string ("_NET_WM_STATE_FOCUSED")))
529     toplevel->have_focused = TRUE;
530 
531   do_net_wm_state_changes (surface);
532 }
533 
534 static void
gdk_check_edge_constraints_changed(GdkSurface * surface)535 gdk_check_edge_constraints_changed (GdkSurface *surface)
536 {
537   GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface);
538   GdkDisplay *display = GDK_SURFACE_DISPLAY (surface);
539 
540   Atom type;
541   int format;
542   gulong nitems;
543   gulong bytes_after;
544   guchar *data;
545   gulong *constraints;
546 
547   type = None;
548   gdk_x11_display_error_trap_push (display);
549   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
550                       GDK_SURFACE_XID (surface),
551                       gdk_x11_get_xatom_by_name_for_display (display, "_GTK_EDGE_CONSTRAINTS"),
552                       0, G_MAXLONG, False, XA_CARDINAL, &type,
553                       &format, &nitems,
554                       &bytes_after, &data);
555   gdk_x11_display_error_trap_pop_ignored (display);
556 
557   if (type != None)
558     {
559       constraints = (gulong *)data;
560 
561       /* The GDK enum for these states does not begin at zero so, to avoid
562        * messing around with shifts, just make the passed value and GDK's
563        * enum values match by shifting to the first tiled state.
564        */
565       toplevel->edge_constraints = constraints[0] << 8;
566 
567       XFree (constraints);
568     }
569   else
570     {
571       toplevel->edge_constraints = 0;
572     }
573 
574   do_net_wm_state_changes (surface);
575 }
576 
577 static Window
get_event_xwindow(const XEvent * xevent)578 get_event_xwindow (const XEvent *xevent)
579 {
580   Window xwindow;
581 
582   switch (xevent->type)
583     {
584     case DestroyNotify:
585       xwindow = xevent->xdestroywindow.window;
586       break;
587     case UnmapNotify:
588       xwindow = xevent->xunmap.window;
589       break;
590     case MapNotify:
591       xwindow = xevent->xmap.window;
592       break;
593     case ConfigureNotify:
594       xwindow = xevent->xconfigure.window;
595       break;
596     case ReparentNotify:
597       xwindow = xevent->xreparent.window;
598       break;
599     case GravityNotify:
600       xwindow = xevent->xgravity.window;
601       break;
602     case CirculateNotify:
603       xwindow = xevent->xcirculate.window;
604       break;
605     default:
606       xwindow = xevent->xany.window;
607     }
608 
609   return xwindow;
610 }
611 
612 static GdkEvent *
gdk_x11_display_translate_event(GdkEventTranslator * translator,GdkDisplay * display,const XEvent * xevent)613 gdk_x11_display_translate_event (GdkEventTranslator *translator,
614                                  GdkDisplay         *display,
615                                  const XEvent       *xevent)
616 {
617   Window xwindow;
618   GdkSurface *surface;
619   GdkX11Surface *surface_impl = NULL;
620   GdkX11Screen *x11_screen = NULL;
621   GdkToplevelX11 *toplevel = NULL;
622   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
623   GdkEvent *event;
624 
625   event = NULL;
626 
627   xwindow = get_event_xwindow (xevent);
628   if (xwindow != xevent->xany.window)
629     return NULL;
630 
631   surface = gdk_x11_surface_lookup_for_display (display, xwindow);
632   if (surface)
633     {
634       /* We may receive events such as NoExpose/GraphicsExpose
635        * and ShmCompletion for pixmaps
636        */
637       if (!GDK_IS_SURFACE (surface))
638         return NULL;
639 
640       x11_screen = GDK_SURFACE_SCREEN (surface);
641       toplevel = _gdk_x11_surface_get_toplevel (surface);
642       surface_impl = GDK_X11_SURFACE (surface);
643 
644       g_object_ref (surface);
645     }
646 
647   if (surface && GDK_SURFACE_DESTROYED (surface))
648     {
649       if (xevent->type != DestroyNotify)
650         goto done;
651     }
652 
653   if (xevent->type == DestroyNotify)
654     {
655       x11_screen = GDK_X11_DISPLAY (display)->screen;
656 
657       if (x11_screen->wmspec_check_window == xevent->xdestroywindow.window)
658         {
659           x11_screen->wmspec_check_window = None;
660           x11_screen->last_wmspec_check_time = 0;
661           g_free (x11_screen->window_manager_name);
662           x11_screen->window_manager_name = g_strdup ("unknown");
663 
664           /* careful, reentrancy */
665           _gdk_x11_screen_window_manager_changed (x11_screen);
666 
667           goto done;
668         }
669     }
670 
671   /* We do a "manual" conversion of the XEvent to a
672    *  GdkEvent. The structures are mostly the same so
673    *  the conversion is fairly straightforward. We also
674    *  optionally print debugging info regarding events
675    *  received.
676    */
677 
678   switch (xevent->type)
679     {
680     case KeymapNotify:
681       GDK_DISPLAY_NOTE (display, EVENTS, g_message ("keymap notify"));
682 
683       /* Not currently handled */
684       break;
685 
686     case Expose:
687       GDK_DISPLAY_NOTE (display, EVENTS,
688 		g_message ("expose:\t\twindow: %ld  %d	x,y: %d %d  w,h: %d %d",
689 			   xevent->xexpose.window, xevent->xexpose.count,
690 			   xevent->xexpose.x, xevent->xexpose.y,
691 			   xevent->xexpose.width, xevent->xexpose.height));
692 
693       if (surface == NULL)
694         break;
695 
696       {
697 	GdkRectangle expose_rect;
698         int x2, y2;
699 
700         expose_rect.x = xevent->xexpose.x / surface_impl->surface_scale;
701         expose_rect.y = xevent->xexpose.y / surface_impl->surface_scale;
702 
703         x2 = (xevent->xexpose.x + xevent->xexpose.width + surface_impl->surface_scale -1) / surface_impl->surface_scale;
704         expose_rect.width = x2 - expose_rect.x;
705 
706         y2 = (xevent->xexpose.y + xevent->xexpose.height + surface_impl->surface_scale -1) / surface_impl->surface_scale;
707         expose_rect.height = y2 - expose_rect.y;
708 
709         gdk_surface_invalidate_rect (surface, &expose_rect);
710       }
711 
712       break;
713 
714     case GraphicsExpose:
715       {
716 	GdkRectangle expose_rect;
717         int x2, y2;
718 
719         GDK_DISPLAY_NOTE (display, EVENTS,
720 		  g_message ("graphics expose:\tdrawable: %ld",
721 			     xevent->xgraphicsexpose.drawable));
722 
723         if (surface == NULL)
724           break;
725 
726         expose_rect.x = xevent->xgraphicsexpose.x / surface_impl->surface_scale;
727         expose_rect.y = xevent->xgraphicsexpose.y / surface_impl->surface_scale;
728 
729         x2 = (xevent->xgraphicsexpose.x + xevent->xgraphicsexpose.width + surface_impl->surface_scale -1) / surface_impl->surface_scale;
730         expose_rect.width = x2 - expose_rect.x;
731 
732         y2 = (xevent->xgraphicsexpose.y + xevent->xgraphicsexpose.height + surface_impl->surface_scale -1) / surface_impl->surface_scale;
733         expose_rect.height = y2 - expose_rect.y;
734 
735         gdk_surface_invalidate_rect (surface, &expose_rect);
736       }
737       break;
738 
739     case VisibilityNotify:
740 #ifdef G_ENABLE_DEBUG
741       if (GDK_DISPLAY_DEBUG_CHECK (display, EVENTS))
742 	switch (xevent->xvisibility.state)
743 	  {
744 	  case VisibilityFullyObscured:
745 	    g_message ("visibility notify:\twindow: %ld	 none",
746 		       xevent->xvisibility.window);
747 	    break;
748 	  case VisibilityPartiallyObscured:
749 	    g_message ("visibility notify:\twindow: %ld	 partial",
750 		       xevent->xvisibility.window);
751 	    break;
752 	  case VisibilityUnobscured:
753 	    g_message ("visibility notify:\twindow: %ld	 full",
754 		       xevent->xvisibility.window);
755 	    break;
756           default:
757             break;
758 	  }
759 #endif /* G_ENABLE_DEBUG */
760       /* not handled */
761       break;
762 
763     case CreateNotify:
764       GDK_DISPLAY_NOTE (display, EVENTS,
765 		g_message ("create notify:\twindow: %ld  x,y: %d %d	w,h: %d %d  b-w: %d  parent: %ld	 ovr: %d",
766 			   xevent->xcreatewindow.window,
767 			   xevent->xcreatewindow.x,
768 			   xevent->xcreatewindow.y,
769 			   xevent->xcreatewindow.width,
770 			   xevent->xcreatewindow.height,
771 			   xevent->xcreatewindow.border_width,
772 			   xevent->xcreatewindow.parent,
773 			   xevent->xcreatewindow.override_redirect));
774       /* not really handled */
775       break;
776 
777     case DestroyNotify:
778       GDK_DISPLAY_NOTE (display, EVENTS,
779 		g_message ("destroy notify:\twindow: %ld",
780 			   xevent->xdestroywindow.window));
781 
782       if (surface)
783         event = gdk_delete_event_new (surface);
784 
785       if (surface && GDK_SURFACE_XID (surface) != x11_screen->xroot_window)
786         gdk_surface_destroy_notify (surface);
787 
788       break;
789 
790     case UnmapNotify:
791       GDK_DISPLAY_NOTE (display, EVENTS,
792 		g_message ("unmap notify:\t\twindow: %ld",
793 			   xevent->xmap.window));
794 
795       if (surface)
796 	{
797           /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to
798            * interpret UnmapNotify events as implying iconic state.
799            * http://bugzilla.gnome.org/show_bug.cgi?id=590726.
800            */
801           if (x11_screen &&
802               !gdk_x11_screen_supports_net_wm_hint (x11_screen,
803                                                     g_intern_static_string ("_NET_WM_STATE_HIDDEN")))
804             {
805               /* If we are shown (not withdrawn) and get an unmap, it means we were
806                * iconified in the X sense. If we are withdrawn, and get an unmap, it
807                * means we hid the window ourselves, so we will have already flipped
808                * the minimized bit off.
809                */
810               if (GDK_SURFACE_IS_MAPPED (surface))
811                 gdk_synthesize_surface_state (surface,
812                                               0,
813                                               GDK_TOPLEVEL_STATE_MINIMIZED);
814             }
815 
816           if (surface_impl->toplevel &&
817               surface_impl->toplevel->frame_pending)
818             {
819               surface_impl->toplevel->frame_pending = FALSE;
820               gdk_surface_thaw_updates (surface);
821             }
822 
823 	  if (toplevel)
824             gdk_surface_freeze_updates (surface);
825 
826           _gdk_x11_surface_grab_check_unmap (surface, xevent->xany.serial);
827 
828           gdk_profiler_add_markf (GDK_PROFILER_CURRENT_TIME, 0, "unmapped window", "0x%lx", GDK_SURFACE_XID (surface));
829         }
830 
831       break;
832 
833     case MapNotify:
834       GDK_DISPLAY_NOTE (display, EVENTS,
835 		g_message ("map notify:\t\twindow: %ld",
836 			   xevent->xmap.window));
837 
838       if (surface)
839 	{
840 	  /* Unset minimized if it was set */
841 	  if (surface->state & GDK_TOPLEVEL_STATE_MINIMIZED)
842 	    gdk_synthesize_surface_state (surface,
843 				 	  GDK_TOPLEVEL_STATE_MINIMIZED,
844 					  0);
845 
846 	  if (toplevel)
847 	    gdk_surface_thaw_updates (surface);
848 
849           if (GDK_PROFILER_IS_RUNNING)
850             {
851               gdk_profiler_end_markf (surface_impl->map_time, "mapped window", "0x%lx", GDK_SURFACE_XID (surface));
852               surface_impl->map_time = 0;
853             }
854 	}
855 
856       break;
857 
858     case ReparentNotify:
859       GDK_DISPLAY_NOTE (display, EVENTS,
860 		g_message ("reparent notify:\twindow: %ld  x,y: %d %d  parent: %ld	ovr: %d",
861 			   xevent->xreparent.window,
862 			   xevent->xreparent.x,
863 			   xevent->xreparent.y,
864 			   xevent->xreparent.parent,
865 			   xevent->xreparent.override_redirect));
866 
867       /* Not currently handled */
868       break;
869 
870     case ConfigureNotify:
871       GDK_DISPLAY_NOTE (display, EVENTS,
872 		g_message ("configure notify:\twindow: %ld  x,y: %d %d	w,h: %d %d  b-w: %d  above: %ld	 ovr: %d%s",
873 			   xevent->xconfigure.window,
874 			   xevent->xconfigure.x,
875 			   xevent->xconfigure.y,
876 			   xevent->xconfigure.width,
877 			   xevent->xconfigure.height,
878 			   xevent->xconfigure.border_width,
879 			   xevent->xconfigure.above,
880 			   xevent->xconfigure.override_redirect,
881 			   !surface ? " (discarding)" : ""));
882       if (_gdk_x11_display_is_root_window (display, xevent->xconfigure.window))
883         {
884 	  _gdk_x11_screen_size_changed (x11_screen, xevent);
885         }
886 
887 #ifdef HAVE_XSYNC
888       if (toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0)
889 	{
890 	  toplevel->configure_counter_value = toplevel->pending_counter_value;
891 	  toplevel->configure_counter_value_is_extended = toplevel->pending_counter_value_is_extended;
892 	  toplevel->pending_counter_value = 0;
893 	}
894 #endif
895 
896     if (surface &&
897 	xevent->xconfigure.event == xevent->xconfigure.window)
898         {
899           int x, y;
900           int configured_width;
901           int configured_height;
902           int new_abs_x, new_abs_y;
903 
904           configured_width =
905             (xevent->xconfigure.width + surface_impl->surface_scale - 1) /
906             surface_impl->surface_scale;
907           configured_height =
908             (xevent->xconfigure.height + surface_impl->surface_scale - 1) /
909             surface_impl->surface_scale;
910 
911 	  if (!xevent->xconfigure.send_event &&
912 	      !xevent->xconfigure.override_redirect &&
913 	      !GDK_SURFACE_DESTROYED (surface))
914 	    {
915 	      int tx = 0;
916 	      int ty = 0;
917 	      Window child_window = 0;
918 
919               x = y = 0;
920 	      gdk_x11_display_error_trap_push (display);
921 	      if (XTranslateCoordinates (GDK_SURFACE_XDISPLAY (surface),
922 					 GDK_SURFACE_XID (surface),
923 					 x11_screen->xroot_window,
924 					 0, 0,
925 					 &tx, &ty,
926 					 &child_window))
927 		{
928 		  x = tx / surface_impl->surface_scale;
929 		  y = ty / surface_impl->surface_scale;
930 		}
931 	      gdk_x11_display_error_trap_pop_ignored (display);
932 	    }
933 	  else
934 	    {
935 	      x = xevent->xconfigure.x / surface_impl->surface_scale;
936 	      y = xevent->xconfigure.y / surface_impl->surface_scale;
937 	    }
938 
939           new_abs_x = x;
940           new_abs_y = y;
941 
942           surface_impl->abs_x = new_abs_x;
943           surface_impl->abs_y = new_abs_y;
944 
945           if (surface->parent)
946             {
947               GdkX11Surface *parent_impl =
948                 GDK_X11_SURFACE (surface->parent);
949 
950               surface->x = new_abs_x - parent_impl->abs_x;
951               surface->y = new_abs_y - parent_impl->abs_y;
952             }
953 
954           if (surface_impl->unscaled_width != xevent->xconfigure.width ||
955               surface_impl->unscaled_height != xevent->xconfigure.height)
956             {
957               surface_impl->unscaled_width = xevent->xconfigure.width;
958               surface_impl->unscaled_height = xevent->xconfigure.height;
959 
960               surface_impl->next_layout.configured_width = configured_width;
961               surface_impl->next_layout.configured_height = configured_height;
962               surface_impl->next_layout.surface_geometry_dirty = TRUE;
963               surface_impl->next_layout.configure_pending = TRUE;
964               gdk_surface_request_layout (surface);
965             }
966 
967           if (surface->resize_count >= 1)
968             {
969               surface->resize_count -= 1;
970 
971               if (surface->resize_count == 0)
972                 _gdk_x11_moveresize_configure_done (display, surface);
973             }
974 
975           gdk_x11_surface_update_popups (surface);
976           gdk_x11_surface_enter_leave_monitors (surface);
977         }
978       break;
979 
980     case PropertyNotify:
981       GDK_DISPLAY_NOTE (display, EVENTS,
982 		g_message ("property notify:\twindow: %ld, atom(%ld): %s%s%s",
983 			   xevent->xproperty.window,
984 			   xevent->xproperty.atom,
985 			   "\"",
986 			   gdk_x11_get_xatom_name_for_display (display, xevent->xproperty.atom),
987 			   "\""));
988 
989       if (surface == NULL)
990         break;
991 
992       /* We compare with the serial of the last time we mapped the
993        * window to avoid refetching properties that we set ourselves
994        */
995       if (toplevel &&
996 	  xevent->xproperty.serial >= toplevel->map_serial)
997 	{
998 	  if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"))
999 	    gdk_check_wm_state_changed (surface);
1000 
1001 	  if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"))
1002 	    gdk_check_wm_desktop_changed (surface);
1003 
1004 	  if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_GTK_EDGE_CONSTRAINTS"))
1005 	    gdk_check_edge_constraints_changed (surface);
1006 	}
1007       break;
1008 
1009     case ColormapNotify:
1010       GDK_DISPLAY_NOTE (display, EVENTS,
1011 		g_message ("colormap notify:\twindow: %ld",
1012 			   xevent->xcolormap.window));
1013 
1014       /* Not currently handled */
1015       break;
1016 
1017     case ClientMessage:
1018       GDK_DISPLAY_NOTE (display, EVENTS,
1019                 g_message ("client message:\twindow: %ld",
1020                            xevent->xclient.window));
1021 
1022       /* Not currently handled */
1023       break;
1024 
1025     case MappingNotify:
1026       GDK_DISPLAY_NOTE (display, EVENTS,
1027 		g_message ("mapping notify"));
1028 
1029       /* Let XLib know that there is a new keyboard mapping.
1030        */
1031       XRefreshKeyboardMapping ((XMappingEvent *) xevent);
1032       _gdk_x11_keymap_keys_changed (display);
1033       break;
1034 
1035     default:
1036 #ifdef HAVE_RANDR
1037       if (xevent->type - display_x11->xrandr_event_base == RRScreenChangeNotify ||
1038           xevent->type - display_x11->xrandr_event_base == RRNotify)
1039 	{
1040           if (display_x11->screen)
1041             _gdk_x11_screen_size_changed (display_x11->screen, xevent);
1042 	}
1043       else
1044 #endif
1045 #ifdef HAVE_XKB
1046       if (xevent->type == display_x11->xkb_event_type)
1047 	{
1048 	  XkbEvent *xkb_event = (XkbEvent *) xevent;
1049 
1050 	  switch (xkb_event->any.xkb_type)
1051 	    {
1052 	    case XkbNewKeyboardNotify:
1053 	    case XkbMapNotify:
1054 	      _gdk_x11_keymap_keys_changed (display);
1055 	      break;
1056 
1057 	    case XkbStateNotify:
1058 	      _gdk_x11_keymap_state_changed (display, xevent);
1059 	      break;
1060             default:
1061               break;
1062 	    }
1063 	}
1064 #endif
1065     }
1066 
1067  done:
1068   if (surface)
1069     g_object_unref (surface);
1070 
1071   return event;
1072 }
1073 
1074 static GdkFrameTimings *
find_frame_timings(GdkFrameClock * clock,guint64 serial)1075 find_frame_timings (GdkFrameClock *clock,
1076                     guint64        serial)
1077 {
1078   gint64 start_frame, end_frame, i;
1079 
1080   start_frame = gdk_frame_clock_get_history_start (clock);
1081   end_frame = gdk_frame_clock_get_frame_counter (clock);
1082   for (i = end_frame; i >= start_frame; i--)
1083     {
1084       GdkFrameTimings *timings = gdk_frame_clock_get_timings (clock, i);
1085 
1086       if (timings->cookie == serial)
1087         return timings;
1088     }
1089 
1090   return NULL;
1091 }
1092 
1093 /* _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages represent time
1094  * as a "high resolution server time" - this is the server time interpolated
1095  * to microsecond resolution. The advantage of this time representation
1096  * is that if  X server is running on the same computer as a client, and
1097  * the Xserver uses 'clock_gettime(CLOCK_MONOTONIC, ...)' for the server
1098  * time, the client can detect this, and all such clients will share a
1099  * a time representation with high accuracy. If there is not a common
1100  * time source, then the time synchronization will be less accurate.
1101  */
1102 static gint64
server_time_to_monotonic_time(GdkX11Display * display_x11,gint64 server_time)1103 server_time_to_monotonic_time (GdkX11Display *display_x11,
1104                                gint64         server_time)
1105 {
1106   if (display_x11->server_time_query_time == 0 ||
1107       (!display_x11->server_time_is_monotonic_time &&
1108        server_time > display_x11->server_time_query_time + 10*1000*1000)) /* 10 seconds */
1109     {
1110       gint64 current_server_time = gdk_x11_get_server_time (display_x11->leader_gdk_surface);
1111       gint64 current_server_time_usec = (gint64)current_server_time * 1000;
1112       gint64 current_monotonic_time = g_get_monotonic_time ();
1113       display_x11->server_time_query_time = current_monotonic_time;
1114 
1115       /* If the server time is within a second of the monotonic time,
1116        * we assume that they are identical. This seems like a big margin,
1117        * but we want to be as robust as possible even if the system
1118        * is under load and our processing of the server response is
1119        * delayed.
1120        */
1121       if (current_server_time_usec > current_monotonic_time - 1000*1000 &&
1122           current_server_time_usec < current_monotonic_time + 1000*1000)
1123         display_x11->server_time_is_monotonic_time = TRUE;
1124 
1125       display_x11->server_time_offset = current_server_time_usec - current_monotonic_time;
1126     }
1127 
1128   if (display_x11->server_time_is_monotonic_time)
1129     return server_time;
1130   else
1131     return server_time - display_x11->server_time_offset;
1132 }
1133 
1134 GdkFilterReturn
_gdk_wm_protocols_filter(const XEvent * xevent,GdkSurface * win,GdkEvent ** event,gpointer data)1135 _gdk_wm_protocols_filter (const XEvent  *xevent,
1136                           GdkSurface    *win,
1137                           GdkEvent     **event,
1138                           gpointer       data)
1139 {
1140   GdkDisplay *display;
1141   Atom atom;
1142 
1143   if (!GDK_IS_X11_SURFACE (win) || GDK_SURFACE_DESTROYED (win))
1144     return GDK_FILTER_CONTINUE;
1145 
1146   if (xevent->type != ClientMessage)
1147     return GDK_FILTER_CONTINUE;
1148 
1149   display = GDK_SURFACE_DISPLAY (win);
1150 
1151   /* This isn't actually WM_PROTOCOLS because that wouldn't leave enough space
1152    * in the message for everything that gets stuffed in */
1153   if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_DRAWN"))
1154     {
1155       GdkX11Surface *surface_impl;
1156       surface_impl = GDK_X11_SURFACE (win);
1157       if (surface_impl->toplevel)
1158         {
1159           guint32 d0 = xevent->xclient.data.l[0];
1160           guint32 d1 = xevent->xclient.data.l[1];
1161           guint32 d2 = xevent->xclient.data.l[2];
1162           guint32 d3 = xevent->xclient.data.l[3];
1163 
1164           guint64 serial = ((guint64)d1 << 32) | d0;
1165           gint64 frame_drawn_time = server_time_to_monotonic_time (GDK_X11_DISPLAY (display), ((guint64)d3 << 32) | d2);
1166           gint64 refresh_interval, presentation_time;
1167 
1168           GdkFrameClock *clock = gdk_surface_get_frame_clock (win);
1169           GdkFrameTimings *timings = find_frame_timings (clock, serial);
1170 
1171           if (timings)
1172             timings->drawn_time = frame_drawn_time;
1173 
1174           if (!surface_impl->toplevel->frame_still_painting && surface_impl->toplevel->frame_pending)
1175             {
1176               surface_impl->toplevel->frame_pending = FALSE;
1177               gdk_surface_thaw_updates (win);
1178             }
1179 
1180           gdk_frame_clock_get_refresh_info (clock,
1181                                             frame_drawn_time,
1182                                             &refresh_interval,
1183                                             &presentation_time);
1184           if (presentation_time != 0)
1185             surface_impl->toplevel->throttled_presentation_time = presentation_time + refresh_interval;
1186         }
1187 
1188       return GDK_FILTER_REMOVE;
1189     }
1190 
1191   if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_FRAME_TIMINGS"))
1192     {
1193       GdkX11Surface *surface_impl;
1194       surface_impl = GDK_X11_SURFACE (win);
1195       if (surface_impl->toplevel)
1196         {
1197           guint32 d0 = xevent->xclient.data.l[0];
1198           guint32 d1 = xevent->xclient.data.l[1];
1199           guint32 d2 = xevent->xclient.data.l[2];
1200           guint32 d3 = xevent->xclient.data.l[3];
1201 
1202           guint64 serial = ((guint64)d1 << 32) | d0;
1203 
1204           GdkFrameClock *clock = gdk_surface_get_frame_clock (win);
1205           GdkFrameTimings *timings = find_frame_timings (clock, serial);
1206 
1207           if (timings)
1208             {
1209               gint32 presentation_time_offset = (gint32)d2;
1210               gint32 refresh_interval = d3;
1211 
1212               if (timings->drawn_time && presentation_time_offset)
1213                 timings->presentation_time = timings->drawn_time + presentation_time_offset;
1214 
1215               if (refresh_interval)
1216                 timings->refresh_interval = refresh_interval;
1217 
1218               timings->complete = TRUE;
1219 #ifdef G_ENABLE_DEBUG
1220               if (GDK_DISPLAY_DEBUG_CHECK (display, FRAMES))
1221                 _gdk_frame_clock_debug_print_timings (clock, timings);
1222 
1223               if (GDK_PROFILER_IS_RUNNING)
1224                 _gdk_frame_clock_add_timings_to_profiler (clock, timings);
1225 #endif /* G_ENABLE_DEBUG */
1226             }
1227         }
1228     }
1229 
1230   if (xevent->xclient.message_type != gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS"))
1231     return GDK_FILTER_CONTINUE;
1232 
1233   atom = (Atom) xevent->xclient.data.l[0];
1234 
1235   if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
1236     {
1237       /* The delete window request specifies a window
1238        *  to delete. We don't actually destroy the
1239        *  window because "it is only a request". (The
1240        *  window might contain vital data that the
1241        *  program does not want destroyed). Instead
1242        *  the event is passed along to the program,
1243        *  which should then destroy the window.
1244        */
1245       GDK_DISPLAY_NOTE (display, EVENTS,
1246 		g_message ("delete window:\t\twindow: %ld",
1247 			   xevent->xclient.window));
1248 
1249       *event = gdk_delete_event_new (win);
1250 
1251       gdk_x11_surface_set_user_time (win, xevent->xclient.data.l[1]);
1252 
1253       return GDK_FILTER_TRANSLATE;
1254     }
1255   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"))
1256     {
1257       GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (win);
1258 
1259       /* There is no way of knowing reliably whether we are viewable;
1260        * so trap errors asynchronously around the XSetInputFocus call
1261        */
1262       if (toplevel)
1263         {
1264           gdk_x11_display_error_trap_push (display);
1265           XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
1266                           toplevel->focus_window,
1267                           RevertToParent,
1268                           xevent->xclient.data.l[1]);
1269           gdk_x11_display_error_trap_pop_ignored (display);
1270        }
1271 
1272       return GDK_FILTER_REMOVE;
1273     }
1274   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING") &&
1275 	   !_gdk_x11_display_is_root_window (display, xevent->xclient.window))
1276     {
1277       XClientMessageEvent xclient = xevent->xclient;
1278 
1279       xclient.window = GDK_SURFACE_XROOTWIN (win);
1280       XSendEvent (GDK_SURFACE_XDISPLAY (win),
1281 		  xclient.window,
1282 		  False,
1283 		  SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient);
1284 
1285       return GDK_FILTER_REMOVE;
1286     }
1287   else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST") &&
1288 	   GDK_X11_DISPLAY (display)->use_sync)
1289     {
1290       GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (win);
1291       if (toplevel)
1292 	{
1293 #ifdef HAVE_XSYNC
1294 	  toplevel->pending_counter_value = xevent->xclient.data.l[2] + ((gint64)xevent->xclient.data.l[3] << 32);
1295 	  toplevel->pending_counter_value_is_extended = xevent->xclient.data.l[4] != 0;
1296 #endif
1297 	}
1298       return GDK_FILTER_REMOVE;
1299     }
1300 
1301   return GDK_FILTER_CONTINUE;
1302 }
1303 
1304 static void
gdk_event_init(GdkDisplay * display)1305 gdk_event_init (GdkDisplay *display)
1306 {
1307   GdkX11Display *display_x11;
1308 
1309   display_x11 = GDK_X11_DISPLAY (display);
1310   display_x11->event_source = gdk_x11_event_source_new (display);
1311 
1312   gdk_x11_event_source_add_translator ((GdkEventSource *) display_x11->event_source,
1313                                        GDK_EVENT_TRANSLATOR (display));
1314 
1315   gdk_x11_event_source_add_translator ((GdkEventSource *) display_x11->event_source,
1316                                         GDK_EVENT_TRANSLATOR (display_x11->device_manager));
1317 }
1318 
1319 static void
set_sm_client_id(GdkDisplay * display,const char * sm_client_id)1320 set_sm_client_id (GdkDisplay  *display,
1321                   const char *sm_client_id)
1322 {
1323   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
1324 
1325   if (gdk_display_is_closed (display))
1326     return;
1327 
1328   if (sm_client_id && strcmp (sm_client_id, ""))
1329     XChangeProperty (display_x11->xdisplay, display_x11->leader_window,
1330                      gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"),
1331                      XA_STRING, 8, PropModeReplace, (guchar *)sm_client_id,
1332                      strlen (sm_client_id));
1333   else
1334     XDeleteProperty (display_x11->xdisplay, display_x11->leader_window,
1335                      gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"));
1336 }
1337 
1338 static void
gdk_x11_display_query_default_visual(GdkX11Display * self,Visual ** out_visual,int * out_depth)1339 gdk_x11_display_query_default_visual (GdkX11Display  *self,
1340                                       Visual        **out_visual,
1341                                       int            *out_depth)
1342 {
1343   XVisualInfo template, *visinfo;
1344   int n_visuals;
1345   Display *dpy;
1346 
1347   dpy = gdk_x11_display_get_xdisplay (GDK_DISPLAY (self));
1348 
1349   template.screen = self->screen->screen_num;
1350   template.depth = 32;
1351   template.red_mask  = 0xff0000;
1352   template.green_mask = 0x00ff00;
1353   template.blue_mask = 0x0000ff;
1354 
1355   visinfo = XGetVisualInfo (dpy,
1356                             VisualScreenMask | VisualDepthMask
1357                             | VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
1358                             &template,
1359                             &n_visuals);
1360   if (visinfo != NULL)
1361     {
1362       *out_visual = visinfo[0].visual;
1363       *out_depth = visinfo[0].depth;
1364       XFree (visinfo);
1365       return;
1366     }
1367 
1368   *out_visual = DefaultVisual (dpy, self->screen->screen_num);
1369   *out_depth = DefaultDepth (dpy, self->screen->screen_num);
1370 }
1371 
1372 static void
gdk_x11_display_init_leader_surface(GdkX11Display * self)1373 gdk_x11_display_init_leader_surface (GdkX11Display *self)
1374 {
1375   GdkDisplay *display = GDK_DISPLAY (self);
1376   Display *xdisplay = gdk_x11_display_get_xdisplay (display);
1377 
1378   self->window_colormap = XCreateColormap (xdisplay,
1379                                            DefaultRootWindow (xdisplay),
1380                                            self->window_visual,
1381                                            AllocNone);
1382   gdk_display_set_rgba (display, self->window_depth == 32);
1383 
1384   /* We need to initialize events after we have the screen
1385    * structures in places
1386    */
1387   _gdk_x11_xsettings_init (GDK_X11_SCREEN (self->screen));
1388 
1389   self->device_manager = _gdk_x11_device_manager_new (display);
1390 
1391   gdk_event_init (display);
1392 
1393   self->leader_gdk_surface =
1394       _gdk_x11_display_create_surface (display,
1395                                        GDK_SURFACE_TEMP,
1396                                        NULL,
1397                                        -100, -100, 1, 1);
1398 
1399   (_gdk_x11_surface_get_toplevel (self->leader_gdk_surface))->is_leader = TRUE;
1400   self->leader_window = GDK_SURFACE_XID (self->leader_gdk_surface);
1401   self->leader_window_title_set = FALSE;
1402 }
1403 
1404 /**
1405  * gdk_x11_display_open:
1406  * @display_name: (nullable): name of the X display.
1407  *   See the XOpenDisplay() for details.
1408  *
1409  * Tries to open a new display to the X server given by
1410  * @display_name. If opening the display fails, %NULL is
1411  * returned.
1412  *
1413  * Returns: (nullable) (transfer full): The new display
1414  */
1415 GdkDisplay *
gdk_x11_display_open(const char * display_name)1416 gdk_x11_display_open (const char *display_name)
1417 {
1418   Display *xdisplay;
1419   GdkDisplay *display;
1420   GdkX11Display *display_x11;
1421   int argc;
1422   char *argv[1];
1423   XClassHint *class_hint;
1424   int ignore;
1425   int maj, min;
1426   char *cm_name;
1427 
1428   XInitThreads ();
1429 
1430   xdisplay = XOpenDisplay (display_name);
1431   if (!xdisplay)
1432     return NULL;
1433 
1434   display = g_object_new (GDK_TYPE_X11_DISPLAY, NULL);
1435   display_x11 = GDK_X11_DISPLAY (display);
1436 
1437   display_x11->xdisplay = xdisplay;
1438 
1439   /* Set up handlers for Xlib internal connections */
1440   XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
1441 
1442   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
1443 
1444   /* RandR must be initialized before we initialize the screens */
1445   display_x11->have_randr12 = FALSE;
1446   display_x11->have_randr13 = FALSE;
1447   display_x11->have_randr15 = FALSE;
1448 #ifdef HAVE_RANDR
1449   if (XRRQueryExtension (display_x11->xdisplay,
1450 			 &display_x11->xrandr_event_base, &ignore))
1451   {
1452       int major, minor;
1453 
1454       XRRQueryVersion (display_x11->xdisplay, &major, &minor);
1455 
1456       if ((major == 1 && minor >= 2) || major > 1) {
1457 	  display_x11->have_randr12 = TRUE;
1458 	  if (minor >= 3 || major > 1)
1459 	      display_x11->have_randr13 = TRUE;
1460 #ifdef HAVE_RANDR15
1461 	  if (minor >= 5 || major > 1)
1462 	      display_x11->have_randr15 = TRUE;
1463 #endif
1464       }
1465   }
1466 #endif
1467 
1468   /* initialize the display's screens */
1469   display_x11->screen = _gdk_x11_screen_new (display, DefaultScreen (display_x11->xdisplay));
1470 
1471   /* If GL is available we want to pick better default/rgba visuals,
1472    * as we care about GLX details such as alpha/depth/stencil depth,
1473    * stereo and double buffering
1474    *
1475    * Note that this also sets up the leader surface while creating the inital
1476    * GL context.
1477    */
1478   if (!gdk_display_prepare_gl (display, NULL))
1479     {
1480       gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth);
1481       gdk_x11_display_init_leader_surface (display_x11);
1482     }
1483 
1484 #ifdef HAVE_XFIXES
1485   if (XFixesQueryExtension (display_x11->xdisplay,
1486 			    &display_x11->xfixes_event_base,
1487 			    &ignore))
1488     {
1489       display_x11->have_xfixes = TRUE;
1490     }
1491   else
1492 #endif
1493     display_x11->have_xfixes = FALSE;
1494 
1495   display_x11->have_shapes = FALSE;
1496   display_x11->have_input_shapes = FALSE;
1497 
1498   if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &display_x11->shape_event_base, &ignore))
1499     {
1500       display_x11->have_shapes = TRUE;
1501 #ifdef ShapeInput
1502       if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
1503 	display_x11->have_input_shapes = (maj == 1 && min >= 1);
1504 #endif
1505     }
1506 
1507   gdk_display_set_input_shapes (display, display_x11->have_input_shapes);
1508 
1509   display_x11->trusted_client = TRUE;
1510   {
1511     Window root, child;
1512     int rootx, rooty, winx, winy;
1513     unsigned int xmask;
1514 
1515     gdk_x11_display_error_trap_push (display);
1516     XQueryPointer (display_x11->xdisplay,
1517 		   GDK_X11_SCREEN (display_x11->screen)->xroot_window,
1518 		   &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
1519     if (G_UNLIKELY (gdk_x11_display_error_trap_pop (display) == BadWindow))
1520       {
1521 	g_warning ("Connection to display %s appears to be untrusted. Pointer and keyboard grabs and inter-client communication may not work as expected.", gdk_display_get_name (display));
1522 	display_x11->trusted_client = FALSE;
1523       }
1524   }
1525 
1526   if (g_getenv ("GDK_SYNCHRONIZE"))
1527     XSynchronize (display_x11->xdisplay, True);
1528 
1529   class_hint = XAllocClassHint();
1530   class_hint->res_name = (char *) g_get_prgname ();
1531   class_hint->res_class = (char *) g_get_prgname ();
1532 
1533   /* XmbSetWMProperties sets the RESOURCE_NAME environment variable
1534    * from argv[0], so we just synthesize an argument array here.
1535    */
1536   argc = 1;
1537   argv[0] = (char *) g_get_prgname ();
1538 
1539   XmbSetWMProperties (display_x11->xdisplay,
1540 		      display_x11->leader_window,
1541 		      NULL, NULL, argv, argc, NULL, NULL,
1542 		      class_hint);
1543   XFree (class_hint);
1544 
1545   if (gdk_sm_client_id)
1546     set_sm_client_id (display, gdk_sm_client_id);
1547 
1548   if (!gdk_running_in_sandbox ())
1549     {
1550       /* if sandboxed, we're likely in a pid namespace and would only confuse the wm with this */
1551       long pid = getpid ();
1552       XChangeProperty (display_x11->xdisplay,
1553                        display_x11->leader_window,
1554                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
1555                        XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
1556     }
1557 
1558   /* We don't yet know a valid time. */
1559   display_x11->user_time = 0;
1560 
1561 #ifdef HAVE_XKB
1562   {
1563     int xkb_major = XkbMajorVersion;
1564     int xkb_minor = XkbMinorVersion;
1565     if (XkbLibraryVersion (&xkb_major, &xkb_minor))
1566       {
1567         xkb_major = XkbMajorVersion;
1568         xkb_minor = XkbMinorVersion;
1569 
1570         if (XkbQueryExtension (display_x11->xdisplay,
1571 			       NULL, &display_x11->xkb_event_type, NULL,
1572                                &xkb_major, &xkb_minor))
1573           {
1574 	    Bool detectable_autorepeat_supported;
1575 
1576 	    display_x11->use_xkb = TRUE;
1577 
1578             XkbSelectEvents (display_x11->xdisplay,
1579                              XkbUseCoreKbd,
1580                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
1581                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
1582 
1583 	    /* keep this in sync with _gdk_x11_keymap_state_changed() */
1584 	    XkbSelectEventDetails (display_x11->xdisplay,
1585 				   XkbUseCoreKbd, XkbStateNotify,
1586 				   XkbAllStateComponentsMask,
1587                                    XkbModifierStateMask|XkbGroupStateMask);
1588 
1589 	    XkbSetDetectableAutoRepeat (display_x11->xdisplay,
1590 					True,
1591 					&detectable_autorepeat_supported);
1592 
1593 	    GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
1594 				       detectable_autorepeat_supported ?
1595 				       "supported" : "not supported"));
1596 
1597 	    display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
1598           }
1599       }
1600   }
1601 #endif
1602 
1603   display_x11->use_sync = FALSE;
1604 #ifdef HAVE_XSYNC
1605   {
1606     int major, minor;
1607     int error_base, event_base;
1608 
1609     if (XSyncQueryExtension (display_x11->xdisplay,
1610 			     &event_base, &error_base) &&
1611         XSyncInitialize (display_x11->xdisplay,
1612                          &major, &minor))
1613       display_x11->use_sync = TRUE;
1614   }
1615 #endif
1616 
1617 #ifdef HAVE_XDAMAGE
1618   display_x11->have_damage = FALSE;
1619   if (XDamageQueryExtension (display_x11->xdisplay,
1620                              &display_x11->damage_event_base,
1621                              &display_x11->damage_error_base))
1622     display_x11->have_damage = TRUE;
1623 #endif
1624 
1625   display->clipboard = gdk_x11_clipboard_new (display, "CLIPBOARD");
1626   display->primary_clipboard = gdk_x11_clipboard_new (display, "PRIMARY");
1627 
1628   /*
1629    * It is important that we first request the selection
1630    * notification, and then setup the initial state of
1631    * is_composited to avoid a race condition here.
1632    */
1633   cm_name = g_strdup_printf ("_NET_WM_CM_S%d", DefaultScreen (GDK_DISPLAY_XDISPLAY (display)));
1634   gdk_x11_display_request_selection_notification (display, cm_name);
1635   gdk_display_set_composited (GDK_DISPLAY (display),
1636                               XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
1637                                                   gdk_x11_get_xatom_by_name_for_display (display, cm_name)) != None);
1638   g_free (cm_name);
1639 
1640   gdk_display_emit_opened (display);
1641 
1642   return display;
1643 }
1644 
1645 /**
1646  * gdk_x11_display_set_program_class:
1647  * @display: a `GdkDisplay`
1648  * @program_class: a string
1649  *
1650  * Sets the program class.
1651  *
1652  * The X11 backend uses the program class to set the class name part
1653  * of the `WM_CLASS` property on toplevel windows; see the ICCCM.
1654  */
1655 void
gdk_x11_display_set_program_class(GdkDisplay * display,const char * program_class)1656 gdk_x11_display_set_program_class (GdkDisplay *display,
1657                                    const char *program_class)
1658 {
1659   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
1660   XClassHint *class_hint;
1661 
1662   g_free (display_x11->program_class);
1663   display_x11->program_class = g_strdup (program_class);
1664 
1665   class_hint = XAllocClassHint();
1666   class_hint->res_name = (char *) g_get_prgname ();
1667   class_hint->res_class = (char *) program_class;
1668   XSetClassHint (display_x11->xdisplay, display_x11->leader_window, class_hint);
1669   XFree (class_hint);
1670 }
1671 
1672 /*
1673  * XLib internal connection handling
1674  */
1675 typedef struct _GdkInternalConnection GdkInternalConnection;
1676 
1677 struct _GdkInternalConnection
1678 {
1679   int	         fd;
1680   GSource	*source;
1681   Display	*display;
1682 };
1683 
1684 static gboolean
process_internal_connection(GIOChannel * gioc,GIOCondition cond,gpointer data)1685 process_internal_connection (GIOChannel  *gioc,
1686 			     GIOCondition cond,
1687 			     gpointer     data)
1688 {
1689   GdkInternalConnection *connection = (GdkInternalConnection *)data;
1690 
1691   XProcessInternalConnection ((Display*)connection->display, connection->fd);
1692 
1693   return TRUE;
1694 }
1695 
1696 static gulong
gdk_x11_display_get_next_serial(GdkDisplay * display)1697 gdk_x11_display_get_next_serial (GdkDisplay *display)
1698 {
1699   return NextRequest (GDK_DISPLAY_XDISPLAY (display));
1700 }
1701 
1702 
1703 static GdkInternalConnection *
gdk_add_connection_handler(Display * display,guint fd)1704 gdk_add_connection_handler (Display *display,
1705 			    guint    fd)
1706 {
1707   GIOChannel *io_channel;
1708   GdkInternalConnection *connection;
1709 
1710   connection = g_new (GdkInternalConnection, 1);
1711 
1712   connection->fd = fd;
1713   connection->display = display;
1714 
1715   io_channel = g_io_channel_unix_new (fd);
1716 
1717   connection->source = g_io_create_watch (io_channel, G_IO_IN);
1718   g_source_set_callback (connection->source,
1719 			 (GSourceFunc)process_internal_connection, connection, NULL);
1720   g_source_attach (connection->source, NULL);
1721 
1722   g_io_channel_unref (io_channel);
1723 
1724   return connection;
1725 }
1726 
1727 static void
gdk_remove_connection_handler(GdkInternalConnection * connection)1728 gdk_remove_connection_handler (GdkInternalConnection *connection)
1729 {
1730   g_source_destroy (connection->source);
1731   g_free (connection);
1732 }
1733 
1734 static void
gdk_internal_connection_watch(Display * display,XPointer arg,int fd,gboolean opening,XPointer * watch_data)1735 gdk_internal_connection_watch (Display  *display,
1736 			       XPointer  arg,
1737 			       int       fd,
1738 			       gboolean  opening,
1739 			       XPointer *watch_data)
1740 {
1741   if (opening)
1742     *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
1743   else
1744     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
1745 }
1746 
1747 static const char *
gdk_x11_display_get_name(GdkDisplay * display)1748 gdk_x11_display_get_name (GdkDisplay *display)
1749 {
1750   return (char *) DisplayString (GDK_X11_DISPLAY (display)->xdisplay);
1751 }
1752 
1753 gboolean
_gdk_x11_display_is_root_window(GdkDisplay * display,Window xroot_window)1754 _gdk_x11_display_is_root_window (GdkDisplay *display,
1755 				 Window      xroot_window)
1756 {
1757   GdkX11Display *display_x11;
1758 
1759   display_x11 = GDK_X11_DISPLAY (display);
1760 
1761   return GDK_SCREEN_XROOTWIN (display_x11->screen) == xroot_window;
1762 }
1763 
1764 struct XPointerUngrabInfo {
1765   GdkDisplay *display;
1766   guint32 time;
1767 };
1768 
1769 static void
device_grab_update_callback(GdkDisplay * display,gpointer data,gulong serial)1770 device_grab_update_callback (GdkDisplay *display,
1771                              gpointer    data,
1772                              gulong      serial)
1773 {
1774   GdkDevice *device = data;
1775 
1776   _gdk_display_device_grab_update (display, device, serial);
1777 }
1778 
1779 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
1780   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
1781     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
1782   )
1783 
1784 void
_gdk_x11_display_update_grab_info(GdkDisplay * display,GdkDevice * device,int status)1785 _gdk_x11_display_update_grab_info (GdkDisplay *display,
1786                                    GdkDevice  *device,
1787                                    int         status)
1788 {
1789   if (status == GrabSuccess)
1790     _gdk_x11_roundtrip_async (display, device_grab_update_callback, device);
1791 }
1792 
1793 void
_gdk_x11_display_update_grab_info_ungrab(GdkDisplay * display,GdkDevice * device,guint32 time,gulong serial)1794 _gdk_x11_display_update_grab_info_ungrab (GdkDisplay *display,
1795                                           GdkDevice  *device,
1796                                           guint32     time,
1797                                           gulong      serial)
1798 {
1799   GdkDeviceGrabInfo *grab;
1800 
1801   XFlush (GDK_DISPLAY_XDISPLAY (display));
1802 
1803   grab = _gdk_display_get_last_device_grab (display, device);
1804   if (grab &&
1805       (time == GDK_CURRENT_TIME ||
1806        grab->time == GDK_CURRENT_TIME ||
1807        !XSERVER_TIME_IS_LATER (grab->time, time)))
1808     {
1809       grab->serial_end = serial;
1810       _gdk_x11_roundtrip_async (display, device_grab_update_callback, device);
1811     }
1812 }
1813 
1814 static void
gdk_x11_display_beep(GdkDisplay * display)1815 gdk_x11_display_beep (GdkDisplay *display)
1816 {
1817   if (!GDK_X11_DISPLAY (display)->trusted_client)
1818     return;
1819 
1820 #ifdef HAVE_XKB
1821   XkbBell (GDK_DISPLAY_XDISPLAY (display), None, 0, None);
1822 #else
1823   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
1824 #endif
1825 }
1826 
1827 static void
gdk_x11_display_sync(GdkDisplay * display)1828 gdk_x11_display_sync (GdkDisplay *display)
1829 {
1830   XSync (GDK_DISPLAY_XDISPLAY (display), False);
1831 }
1832 
1833 static void
gdk_x11_display_flush(GdkDisplay * display)1834 gdk_x11_display_flush (GdkDisplay *display)
1835 {
1836   if (!display->closed)
1837     XFlush (GDK_DISPLAY_XDISPLAY (display));
1838 }
1839 
1840 static gboolean
gdk_x11_display_has_pending(GdkDisplay * display)1841 gdk_x11_display_has_pending (GdkDisplay *display)
1842 {
1843   return XPending (GDK_DISPLAY_XDISPLAY (display));
1844 }
1845 
1846 /**
1847  * gdk_x11_display_get_default_group:
1848  * @display: (type GdkX11Display): a `GdkDisplay`
1849  *
1850  * Returns the default group leader surface for all toplevel surfaces
1851  * on @display. This surface is implicitly created by GDK.
1852  * See gdk_x11_surface_set_group().
1853  *
1854  * Returns: (transfer none): The default group leader surface
1855  * for @display
1856  */
1857 GdkSurface *
gdk_x11_display_get_default_group(GdkDisplay * display)1858 gdk_x11_display_get_default_group (GdkDisplay *display)
1859 {
1860   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1861 
1862   return GDK_X11_DISPLAY (display)->leader_gdk_surface;
1863 }
1864 
1865 /**
1866  * gdk_x11_display_grab:
1867  * @display: (type GdkX11Display): a `GdkDisplay`
1868  *
1869  * Call XGrabServer() on @display.
1870  * To ungrab the display again, use gdk_x11_display_ungrab().
1871  *
1872  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
1873  **/
1874 void
gdk_x11_display_grab(GdkDisplay * display)1875 gdk_x11_display_grab (GdkDisplay *display)
1876 {
1877   GdkX11Display *display_x11;
1878 
1879   g_return_if_fail (GDK_IS_DISPLAY (display));
1880 
1881   display_x11 = GDK_X11_DISPLAY (display);
1882 
1883   if (display_x11->grab_count == 0)
1884     XGrabServer (display_x11->xdisplay);
1885   display_x11->grab_count++;
1886 }
1887 
1888 /**
1889  * gdk_x11_display_ungrab:
1890  * @display: (type GdkX11Display): a `GdkDisplay`
1891  *
1892  * Ungrab @display after it has been grabbed with
1893  * gdk_x11_display_grab().
1894  **/
1895 void
gdk_x11_display_ungrab(GdkDisplay * display)1896 gdk_x11_display_ungrab (GdkDisplay *display)
1897 {
1898   GdkX11Display *display_x11;
1899 
1900   g_return_if_fail (GDK_IS_DISPLAY (display));
1901 
1902   display_x11 = GDK_X11_DISPLAY (display);;
1903   g_return_if_fail (display_x11->grab_count > 0);
1904 
1905   display_x11->grab_count--;
1906   if (display_x11->grab_count == 0)
1907     {
1908       XUngrabServer (display_x11->xdisplay);
1909       XFlush (display_x11->xdisplay);
1910     }
1911 }
1912 
1913 static void
gdk_x11_display_dispose(GObject * object)1914 gdk_x11_display_dispose (GObject *object)
1915 {
1916   GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
1917 
1918   if (display_x11->event_source)
1919     {
1920       g_source_destroy (display_x11->event_source);
1921       g_source_unref (display_x11->event_source);
1922       display_x11->event_source = NULL;
1923     }
1924 
1925   G_OBJECT_CLASS (gdk_x11_display_parent_class)->dispose (object);
1926 }
1927 
1928 static void
gdk_x11_display_finalize(GObject * object)1929 gdk_x11_display_finalize (GObject *object)
1930 {
1931   GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
1932 
1933   /* Keymap */
1934   if (display_x11->keymap)
1935     g_object_unref (display_x11->keymap);
1936 
1937   _gdk_x11_cursor_display_finalize (GDK_DISPLAY (display_x11));
1938 
1939   /* Get rid of pending streams */
1940   g_slist_free_full (display_x11->streams, g_object_unref);
1941 
1942   /* Atom Hashtable */
1943   g_hash_table_destroy (display_x11->atom_from_string);
1944   g_hash_table_destroy (display_x11->atom_to_string);
1945 
1946   /* Leader Window */
1947   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
1948 
1949   /* Free all GdkX11Screens */
1950   g_object_unref (display_x11->screen);
1951 
1952   g_list_store_remove_all (display_x11->monitors);
1953   g_object_unref (display_x11->monitors);
1954 
1955   g_free (display_x11->startup_notification_id);
1956 
1957   /* X ID hashtable */
1958   g_hash_table_destroy (display_x11->xid_ht);
1959 
1960   XCloseDisplay (display_x11->xdisplay);
1961 
1962   g_clear_error (&display_x11->gl_error);
1963 
1964   /* error traps */
1965   while (display_x11->error_traps != NULL)
1966     {
1967       GdkErrorTrap *trap = display_x11->error_traps->data;
1968 
1969       display_x11->error_traps =
1970         g_slist_delete_link (display_x11->error_traps,
1971                              display_x11->error_traps);
1972 
1973       if (trap->end_sequence == 0)
1974         g_warning ("Display finalized with an unpopped error trap");
1975 
1976       g_slice_free (GdkErrorTrap, trap);
1977     }
1978 
1979   g_free (display_x11->program_class);
1980 
1981   G_OBJECT_CLASS (gdk_x11_display_parent_class)->finalize (object);
1982 }
1983 
1984 /**
1985  * gdk_x11_lookup_xdisplay:
1986  * @xdisplay: a pointer to an X Display
1987  *
1988  * Find the `GdkDisplay` corresponding to @xdisplay, if any exists.
1989 *
1990  * Returns: (transfer none) (type GdkX11Display): the `GdkDisplay`, if found, otherwise %NULL.
1991  **/
1992 GdkDisplay *
gdk_x11_lookup_xdisplay(Display * xdisplay)1993 gdk_x11_lookup_xdisplay (Display *xdisplay)
1994 {
1995   GSList *list, *l;
1996   GdkDisplay *display;
1997 
1998   display = NULL;
1999 
2000   list = gdk_display_manager_list_displays (gdk_display_manager_get ());
2001 
2002   for (l = list; l; l = l->next)
2003     {
2004       if (GDK_IS_X11_DISPLAY (l->data) &&
2005           GDK_DISPLAY_XDISPLAY (l->data) == xdisplay)
2006         {
2007           display = l->data;
2008           break;
2009         }
2010     }
2011 
2012   g_slist_free (list);
2013 
2014   return display;
2015 }
2016 
2017 /**
2018  * gdk_x11_display_get_xdisplay:
2019  * @display: (type GdkX11Display): a `GdkDisplay`
2020  *
2021  * Returns the X display of a `GdkDisplay`.
2022  *
2023  * Returns: (transfer none): an X display
2024  */
2025 Display *
gdk_x11_display_get_xdisplay(GdkDisplay * display)2026 gdk_x11_display_get_xdisplay (GdkDisplay *display)
2027 {
2028   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2029 
2030   return GDK_X11_DISPLAY (display)->xdisplay;
2031 }
2032 
2033 /**
2034  * gdk_x11_display_get_xscreen:
2035  * @display: (type GdkX11Display): a `GdkDisplay`
2036  *
2037  * Returns the X Screen used by `GdkDisplay`.
2038  *
2039  * Returns: (transfer none): an X Screen
2040  */
2041 Screen *
gdk_x11_display_get_xscreen(GdkDisplay * display)2042 gdk_x11_display_get_xscreen (GdkDisplay *display)
2043 {
2044   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2045 
2046   return GDK_X11_SCREEN (GDK_X11_DISPLAY (display)->screen)->xscreen;
2047 }
2048 
2049 /**
2050  * gdk_x11_display_get_xrootwindow:
2051  * @display: (type GdkX11Display): a `GdkDisplay`
2052  *
2053  * Returns the root X window used by `GdkDisplay`.
2054  *
2055  * Returns: an X Window
2056  */
2057 Window
gdk_x11_display_get_xrootwindow(GdkDisplay * display)2058 gdk_x11_display_get_xrootwindow (GdkDisplay *display)
2059 {
2060   g_return_val_if_fail (GDK_IS_DISPLAY (display), None);
2061 
2062   return GDK_SCREEN_XROOTWIN (GDK_X11_DISPLAY (display)->screen);
2063 }
2064 
2065 static void
gdk_x11_display_make_default(GdkDisplay * display)2066 gdk_x11_display_make_default (GdkDisplay *display)
2067 {
2068   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
2069   const char *startup_id;
2070 
2071   g_free (display_x11->startup_notification_id);
2072   display_x11->startup_notification_id = NULL;
2073 
2074   startup_id = gdk_get_startup_notification_id ();
2075   if (startup_id)
2076     gdk_x11_display_set_startup_notification_id (display, startup_id);
2077 }
2078 
2079 static void
broadcast_xmessage(GdkDisplay * display,const char * message_type,const char * message_type_begin,const char * message)2080 broadcast_xmessage (GdkDisplay *display,
2081 		    const char *message_type,
2082 		    const char *message_type_begin,
2083 		    const char *message)
2084 {
2085   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
2086   Window xroot_window = GDK_DISPLAY_XROOTWIN (display);
2087 
2088   Atom type_atom;
2089   Atom type_atom_begin;
2090   Window xwindow;
2091 
2092   if (!G_LIKELY (GDK_X11_DISPLAY (display)->trusted_client))
2093     return;
2094 
2095   {
2096     XSetWindowAttributes attrs;
2097 
2098     attrs.override_redirect = True;
2099     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
2100 
2101     xwindow =
2102       XCreateWindow (xdisplay,
2103                      xroot_window,
2104                      -100, -100, 1, 1,
2105                      0,
2106                      CopyFromParent,
2107                      CopyFromParent,
2108                      (Visual *)CopyFromParent,
2109                      CWOverrideRedirect | CWEventMask,
2110                      &attrs);
2111   }
2112 
2113   type_atom = gdk_x11_get_xatom_by_name_for_display (display, message_type);
2114   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display, message_type_begin);
2115 
2116   {
2117     XClientMessageEvent xclient;
2118     const char *src;
2119     const char *src_end;
2120     char *dest;
2121     char *dest_end;
2122 
2123     memset(&xclient, 0, sizeof (xclient));
2124     xclient.type = ClientMessage;
2125     xclient.message_type = type_atom_begin;
2126     xclient.display =xdisplay;
2127     xclient.window = xwindow;
2128     xclient.format = 8;
2129 
2130     src = message;
2131     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
2132 
2133     while (src != src_end)
2134       {
2135         dest = &xclient.data.b[0];
2136         dest_end = dest + 20;
2137 
2138         while (dest != dest_end &&
2139                src != src_end)
2140           {
2141             *dest = *src;
2142             ++dest;
2143             ++src;
2144           }
2145 
2146 	while (dest != dest_end)
2147 	  {
2148 	    *dest = 0;
2149 	    ++dest;
2150 	  }
2151 
2152         XSendEvent (xdisplay,
2153                     xroot_window,
2154                     False,
2155                     PropertyChangeMask,
2156                     (XEvent *)&xclient);
2157 
2158         xclient.message_type = type_atom;
2159       }
2160   }
2161 
2162   XDestroyWindow (xdisplay, xwindow);
2163   XFlush (xdisplay);
2164 }
2165 
2166 /**
2167  * gdk_x11_display_broadcast_startup_message:
2168  * @display: (type GdkX11Display): a `GdkDisplay`
2169  * @message_type: startup notification message type ("new", "change",
2170  * or "remove")
2171  * @...: a list of key/value pairs (as strings), terminated by a
2172  * %NULL key. (A %NULL value for a key will cause that key to be
2173  * skipped in the output.)
2174  *
2175  * Sends a startup notification message of type @message_type to
2176  * @display.
2177  *
2178  * This is a convenience function for use by code that implements the
2179  * freedesktop startup notification specification. Applications should
2180  * not normally need to call it directly. See the
2181  * [Startup Notification Protocol specification](http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt)
2182  * for definitions of the message types and keys that can be used.
2183  **/
2184 void
gdk_x11_display_broadcast_startup_message(GdkDisplay * display,const char * message_type,...)2185 gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
2186 					   const char *message_type,
2187 					   ...)
2188 {
2189   GString *message;
2190   va_list ap;
2191   const char *key, *value, *p;
2192 
2193   message = g_string_new (message_type);
2194   g_string_append_c (message, ':');
2195 
2196   va_start (ap, message_type);
2197   while ((key = va_arg (ap, const char *)))
2198     {
2199       value = va_arg (ap, const char *);
2200       if (!value)
2201 	continue;
2202 
2203       g_string_append_printf (message, " %s=\"", key);
2204       for (p = value; *p; p++)
2205 	{
2206 	  switch (*p)
2207 	    {
2208 	    case ' ':
2209 	    case '"':
2210 	    case '\\':
2211 	      g_string_append_c (message, '\\');
2212 	      break;
2213             default:
2214               break;
2215 	    }
2216 
2217 	  g_string_append_c (message, *p);
2218 	}
2219       g_string_append_c (message, '\"');
2220     }
2221   va_end (ap);
2222 
2223   broadcast_xmessage (display,
2224                       "_NET_STARTUP_INFO",
2225                       "_NET_STARTUP_INFO_BEGIN",
2226                       message->str);
2227 
2228   g_string_free (message, TRUE);
2229 }
2230 
2231 static void
gdk_x11_display_notify_startup_complete(GdkDisplay * display,const char * startup_id)2232 gdk_x11_display_notify_startup_complete (GdkDisplay  *display,
2233                                          const char *startup_id)
2234 {
2235   char *free_this = NULL;
2236 
2237   if (startup_id == NULL)
2238     {
2239       GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
2240 
2241       startup_id = free_this = display_x11->startup_notification_id;
2242       display_x11->startup_notification_id = NULL;
2243 
2244       if (startup_id == NULL)
2245         return;
2246     }
2247 
2248   gdk_x11_display_broadcast_startup_message (display, "remove",
2249                                              "ID", startup_id,
2250                                              NULL);
2251 
2252   g_free (free_this);
2253 }
2254 
2255 gboolean
gdk_x11_display_request_selection_notification(GdkDisplay * display,const char * selection)2256 gdk_x11_display_request_selection_notification (GdkDisplay *display,
2257 						const char *selection)
2258 
2259 {
2260 #ifdef HAVE_XFIXES
2261   GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
2262   Atom atom;
2263 
2264   if (display_x11->have_xfixes)
2265     {
2266       atom = gdk_x11_get_xatom_by_name_for_display (display, selection);
2267       XFixesSelectSelectionInput (display_x11->xdisplay,
2268 				  display_x11->leader_window,
2269 				  atom,
2270 				  XFixesSetSelectionOwnerNotifyMask |
2271 				  XFixesSelectionWindowDestroyNotifyMask |
2272 				  XFixesSelectionClientCloseNotifyMask);
2273       return TRUE;
2274     }
2275   else
2276 #endif
2277     return FALSE;
2278 }
2279 
2280 /**
2281  * gdk_x11_display_get_user_time:
2282  * @display: (type GdkX11Display): a `GdkDisplay`
2283  *
2284  * Returns the timestamp of the last user interaction on
2285  * @display. The timestamp is taken from events caused
2286  * by user interaction such as key presses or pointer
2287  * movements. See gdk_x11_surface_set_user_time().
2288  *
2289  * Returns: the timestamp of the last user interaction
2290  */
2291 guint32
gdk_x11_display_get_user_time(GdkDisplay * display)2292 gdk_x11_display_get_user_time (GdkDisplay *display)
2293 {
2294   return GDK_X11_DISPLAY (display)->user_time;
2295 }
2296 
2297 /**
2298  * gdk_x11_display_get_startup_notification_id:
2299  * @display: (type GdkX11Display): a `GdkDisplay`
2300  *
2301  * Gets the startup notification ID for a display.
2302  *
2303  * Returns: the startup notification ID for @display
2304  */
2305 const char *
gdk_x11_display_get_startup_notification_id(GdkDisplay * display)2306 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
2307 {
2308   return GDK_X11_DISPLAY (display)->startup_notification_id;
2309 }
2310 
2311 /**
2312  * gdk_x11_display_set_startup_notification_id:
2313  * @display: (type GdkX11Display): a `GdkDisplay`
2314  * @startup_id: the startup notification ID (must be valid utf8)
2315  *
2316  * Sets the startup notification ID for a display.
2317  *
2318  * This is usually taken from the value of the DESKTOP_STARTUP_ID
2319  * environment variable, but in some cases (such as the application not
2320  * being launched using exec()) it can come from other sources.
2321  *
2322  * If the ID contains the string "_TIME" then the portion following that
2323  * string is taken to be the X11 timestamp of the event that triggered
2324  * the application to be launched and the GDK current event time is set
2325  * accordingly.
2326  *
2327  * The startup ID is also what is used to signal that the startup is
2328  * complete (for example, when opening a window or when calling
2329  * gdk_display_notify_startup_complete()).
2330  **/
2331 void
gdk_x11_display_set_startup_notification_id(GdkDisplay * display,const char * startup_id)2332 gdk_x11_display_set_startup_notification_id (GdkDisplay  *display,
2333                                              const char *startup_id)
2334 {
2335   GdkX11Display *display_x11;
2336   char *time_str;
2337 
2338   display_x11 = GDK_X11_DISPLAY (display);
2339 
2340   g_free (display_x11->startup_notification_id);
2341   display_x11->startup_notification_id = g_strdup (startup_id);
2342 
2343   if (startup_id != NULL)
2344     {
2345       /* Find the launch time from the startup_id, if it's there.  Newer spec
2346        * states that the startup_id is of the form <unique>_TIME<timestamp>
2347        */
2348       time_str = g_strrstr (startup_id, "_TIME");
2349       if (time_str != NULL)
2350         {
2351           gulong retval;
2352           char *end;
2353           errno = 0;
2354 
2355           /* Skip past the "_TIME" part */
2356           time_str += 5;
2357 
2358           retval = strtoul (time_str, &end, 0);
2359           if (end != time_str && errno == 0)
2360             display_x11->user_time = retval;
2361         }
2362       else
2363         display_x11->user_time = 0;
2364 
2365       /* Set the startup id on the leader window so it
2366        * applies to all windows we create on this display
2367        */
2368       XChangeProperty (display_x11->xdisplay,
2369                        display_x11->leader_window,
2370                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2371                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2372                        PropModeReplace,
2373                        (guchar *)startup_id, strlen (startup_id));
2374     }
2375   else
2376     {
2377       XDeleteProperty (display_x11->xdisplay, display_x11->leader_window,
2378                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2379       display_x11->user_time = 0;
2380     }
2381 }
2382 
2383 /* look up the extension name for a given major opcode.  grubs around in
2384  * xlib to do it since a) it’s already cached there b) XQueryExtension
2385  * emits protocol so we can’t use it in an error handler.
2386  */
2387 static const char *
_gdk_x11_decode_request_code(Display * dpy,int code)2388 _gdk_x11_decode_request_code(Display *dpy, int code)
2389 {
2390   _XExtension *ext;
2391 
2392   if (code < 128)
2393     return "core protocol";
2394 
2395   for (ext = dpy->ext_procs; ext; ext = ext->next)
2396     {
2397       if (ext->codes.major_opcode == code)
2398         return ext->name;
2399     }
2400 
2401   return "unknown";
2402 }
2403 
2404 /* compare X sequence numbers handling wraparound */
2405 #define SEQUENCE_COMPARE(a,op,b) (((long) (a) - (long) (b)) op 0)
2406 
2407 /* delivers an error event from the error handler in gdkmain-x11.c */
2408 void
_gdk_x11_display_error_event(GdkDisplay * display,XErrorEvent * error)2409 _gdk_x11_display_error_event (GdkDisplay  *display,
2410                               XErrorEvent *error)
2411 {
2412   GdkX11Display *display_x11;
2413   GSList *tmp_list;
2414   gboolean ignore;
2415 
2416   display_x11 = GDK_X11_DISPLAY (display);
2417 
2418   ignore = FALSE;
2419   for (tmp_list = display_x11->error_traps;
2420        tmp_list != NULL;
2421        tmp_list = tmp_list->next)
2422     {
2423       GdkErrorTrap *trap;
2424 
2425       trap = tmp_list->data;
2426 
2427       if (SEQUENCE_COMPARE (trap->start_sequence, <=, error->serial) &&
2428           (trap->end_sequence == 0 ||
2429            SEQUENCE_COMPARE (trap->end_sequence, >, error->serial)))
2430         {
2431           ignore = TRUE;
2432           trap->error_code = error->error_code;
2433           break; /* only innermost trap gets the error code */
2434         }
2435     }
2436 
2437   if (!ignore)
2438     {
2439       char buf[64];
2440       char *msg;
2441 
2442       XGetErrorText (display_x11->xdisplay, error->error_code, buf, 63);
2443 
2444       msg =
2445         g_strdup_printf ("The program '%s' received an X Window System error.\n"
2446                          "This probably reflects a bug in the program.\n"
2447                          "The error was '%s'.\n"
2448                          "  (Details: serial %ld error_code %d request_code %d (%s) minor_code %d)\n"
2449                          "  (Note to programmers: normally, X errors are reported asynchronously;\n"
2450                          "   that is, you will receive the error a while after causing it.\n"
2451                          "   To debug your program, run it with the GDK_SYNCHRONIZE environment\n"
2452                          "   variable to change this behavior. You can then get a meaningful\n"
2453                          "   backtrace from your debugger if you break on the gdk_x_error() function.)",
2454                          g_get_prgname (),
2455                          buf,
2456                          error->serial,
2457                          error->error_code,
2458                          error->request_code,
2459                          _gdk_x11_decode_request_code(display_x11->xdisplay,
2460                                                       error->request_code),
2461                          error->minor_code);
2462 
2463 #ifdef G_ENABLE_DEBUG
2464       g_error ("%s", msg);
2465 #else /* !G_ENABLE_DEBUG */
2466       g_warning ("%s", msg);
2467 
2468       _exit (1);
2469 #endif /* G_ENABLE_DEBUG */
2470     }
2471 }
2472 
2473 static void
delete_outdated_error_traps(GdkX11Display * display_x11)2474 delete_outdated_error_traps (GdkX11Display *display_x11)
2475 {
2476   GSList *tmp_list;
2477   gulong processed_sequence;
2478 
2479   processed_sequence = XLastKnownRequestProcessed (display_x11->xdisplay);
2480 
2481   tmp_list = display_x11->error_traps;
2482   while (tmp_list != NULL)
2483     {
2484       GdkErrorTrap *trap = tmp_list->data;
2485 
2486       if (trap->end_sequence != 0 &&
2487           SEQUENCE_COMPARE (trap->end_sequence, <=, processed_sequence))
2488         {
2489           GSList *free_me = tmp_list;
2490 
2491           tmp_list = tmp_list->next;
2492           display_x11->error_traps =
2493             g_slist_delete_link (display_x11->error_traps, free_me);
2494           g_slice_free (GdkErrorTrap, trap);
2495         }
2496       else
2497         {
2498           tmp_list = tmp_list->next;
2499         }
2500     }
2501 }
2502 
2503 /**
2504  * gdk_x11_display_error_trap_push:
2505  * @display: (type GdkX11Display): a `GdkDisplay`
2506  *
2507  * Begins a range of X requests on @display for which X error events
2508  * will be ignored. Unignored errors (when no trap is pushed) will abort
2509  * the application. Use gdk_x11_display_error_trap_pop() or
2510  * gdk_x11_display_error_trap_pop_ignored()to lift a trap pushed
2511  * with this function.
2512  */
2513 void
gdk_x11_display_error_trap_push(GdkDisplay * display)2514 gdk_x11_display_error_trap_push (GdkDisplay *display)
2515 {
2516   GdkX11Display *display_x11;
2517   GdkErrorTrap *trap;
2518 
2519   display_x11 = GDK_X11_DISPLAY (display);
2520 
2521   delete_outdated_error_traps (display_x11);
2522 
2523   /* set up the Xlib callback to tell us about errors */
2524   _gdk_x11_error_handler_push ();
2525 
2526   trap = g_slice_new0 (GdkErrorTrap);
2527 
2528   trap->start_sequence = XNextRequest (display_x11->xdisplay);
2529   trap->error_code = Success;
2530 
2531   display_x11->error_traps =
2532     g_slist_prepend (display_x11->error_traps, trap);
2533 }
2534 
2535 static int
gdk_x11_display_error_trap_pop_internal(GdkDisplay * display,gboolean need_code)2536 gdk_x11_display_error_trap_pop_internal (GdkDisplay *display,
2537                                          gboolean    need_code)
2538 {
2539   GdkX11Display *display_x11;
2540   GdkErrorTrap *trap;
2541   GSList *tmp_list;
2542   int result;
2543 
2544   display_x11 = GDK_X11_DISPLAY (display);
2545 
2546   g_return_val_if_fail (display_x11->error_traps != NULL, Success);
2547 
2548   /* Find the first trap that hasn't been popped already */
2549   trap = NULL; /* quiet gcc */
2550   for (tmp_list = display_x11->error_traps;
2551        tmp_list != NULL;
2552        tmp_list = tmp_list->next)
2553     {
2554       trap = tmp_list->data;
2555 
2556       if (trap->end_sequence == 0)
2557         break;
2558     }
2559 
2560   if (trap == NULL)
2561     {
2562       g_critical ("gdk_x11_display_error_trap_pop() called without gdk_x11_display_error_trap_push()");
2563       return Success;
2564     }
2565   g_assert (trap->end_sequence == 0);
2566 
2567   /* May need to sync to fill in trap->error_code if we care about
2568    * getting an error code.
2569    */
2570   if (need_code)
2571     {
2572       gulong processed_sequence;
2573       gulong next_sequence;
2574 
2575       next_sequence = XNextRequest (display_x11->xdisplay);
2576       processed_sequence = XLastKnownRequestProcessed (display_x11->xdisplay);
2577 
2578       /* If our last request was already processed, there is no point
2579        * in syncing. i.e. if last request was a round trip (or even if
2580        * we got an event with the serial of a non-round-trip)
2581        */
2582       if ((next_sequence - 1) != processed_sequence)
2583         {
2584           XSync (display_x11->xdisplay, False);
2585         }
2586 
2587       result = trap->error_code;
2588     }
2589   else
2590     {
2591       result = Success;
2592     }
2593 
2594   /* record end of trap, giving us a range of
2595    * error sequences we'll ignore.
2596    */
2597   trap->end_sequence = XNextRequest (display_x11->xdisplay);
2598 
2599   /* remove the Xlib callback */
2600   _gdk_x11_error_handler_pop ();
2601 
2602   /* we may already be outdated */
2603   delete_outdated_error_traps (display_x11);
2604 
2605   return result;
2606 }
2607 
2608 /**
2609  * gdk_x11_display_set_surface_scale:
2610  * @display: (type GdkX11Display): the display
2611  * @scale: The new scale value
2612  *
2613  * Forces a specific window scale for all windows on this display,
2614  * instead of using the default or user configured scale. This
2615  * is can be used to disable scaling support by setting @scale to
2616  * 1, or to programmatically set the window scale.
2617  *
2618  * Once the scale is set by this call it will not change in response
2619  * to later user configuration changes.
2620  */
2621 void
gdk_x11_display_set_surface_scale(GdkDisplay * display,int scale)2622 gdk_x11_display_set_surface_scale (GdkDisplay *display,
2623                                   int         scale)
2624 {
2625   GdkX11Screen *x11_screen;
2626   gboolean need_reread_settings = FALSE;
2627 
2628   g_return_if_fail (GDK_IS_X11_DISPLAY (display));
2629 
2630   scale = MAX (scale, 1);
2631 
2632   x11_screen = GDK_X11_SCREEN (GDK_X11_DISPLAY (display)->screen);
2633 
2634   if (!x11_screen->fixed_surface_scale)
2635     {
2636       x11_screen->fixed_surface_scale = TRUE;
2637 
2638       /* We treat screens with a window scale set differently when
2639        * reading xsettings, so we need to reread
2640        */
2641       need_reread_settings = TRUE;
2642     }
2643 
2644   _gdk_x11_screen_set_surface_scale (x11_screen, scale);
2645 
2646   if (need_reread_settings)
2647     _gdk_x11_settings_force_reread (x11_screen);
2648 }
2649 
2650 
2651 /**
2652  * gdk_x11_display_error_trap_pop:
2653  * @display: (type GdkX11Display): the display
2654  *
2655  * Pops the error trap pushed by gdk_x11_display_error_trap_push().
2656  * Will XSync() if necessary and will always block until
2657  * the error is known to have occurred or not occurred,
2658  * so the error code can be returned.
2659  *
2660  * If you don’t need to use the return value,
2661  * gdk_x11_display_error_trap_pop_ignored() would be more efficient.
2662  *
2663  * Returns: X error code or 0 on success
2664  */
2665 int
gdk_x11_display_error_trap_pop(GdkDisplay * display)2666 gdk_x11_display_error_trap_pop (GdkDisplay *display)
2667 {
2668   g_return_val_if_fail (GDK_IS_X11_DISPLAY (display), Success);
2669 
2670   return gdk_x11_display_error_trap_pop_internal (display, TRUE);
2671 }
2672 
2673 /**
2674  * gdk_x11_display_error_trap_pop_ignored:
2675  * @display: (type GdkX11Display): the display
2676  *
2677  * Pops the error trap pushed by gdk_x11_display_error_trap_push().
2678  * Does not block to see if an error occurred; merely records the
2679  * range of requests to ignore errors for, and ignores those errors
2680  * if they arrive asynchronously.
2681  */
2682 void
gdk_x11_display_error_trap_pop_ignored(GdkDisplay * display)2683 gdk_x11_display_error_trap_pop_ignored (GdkDisplay *display)
2684 {
2685   g_return_if_fail (GDK_IS_X11_DISPLAY (display));
2686 
2687   gdk_x11_display_error_trap_pop_internal (display, FALSE);
2688 }
2689 
2690 /**
2691  * gdk_x11_set_sm_client_id:
2692  * @sm_client_id: (nullable): the client id assigned by the session manager
2693  *    when the connection was opened, or %NULL to remove the property.
2694  *
2695  * Sets the `SM_CLIENT_ID` property on the application’s leader window so that
2696  * the window manager can save the application’s state using the X11R6 ICCCM
2697  * session management protocol.
2698  *
2699  * See the X Session Management Library documentation for more information on
2700  * session management and the Inter-Client Communication Conventions Manual
2701  */
2702 void
gdk_x11_set_sm_client_id(const char * sm_client_id)2703 gdk_x11_set_sm_client_id (const char *sm_client_id)
2704 {
2705  GSList *displays, *l;
2706 
2707   g_free (gdk_sm_client_id);
2708   gdk_sm_client_id = g_strdup (sm_client_id);
2709 
2710   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
2711   for (l = displays; l; l = l->next)
2712     {
2713       if (GDK_IS_X11_DISPLAY (l->data))
2714         set_sm_client_id (l->data, sm_client_id);
2715     }
2716 
2717   g_slist_free (displays);
2718 }
2719 
2720 gsize
gdk_x11_display_get_max_request_size(GdkDisplay * display)2721 gdk_x11_display_get_max_request_size (GdkDisplay *display)
2722 {
2723   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
2724   gsize size;
2725 
2726   size = XExtendedMaxRequestSize (xdisplay);
2727   if (size <= 0)
2728     size = XMaxRequestSize (xdisplay);
2729 
2730   size = MIN (262144, size - 100);
2731   return size;
2732 }
2733 
2734 /**
2735  * gdk_x11_display_get_screen:
2736  * @display: (type GdkX11Display): a `GdkX11Display`
2737  *
2738  * Retrieves the `GdkX11Screen` of the @display.
2739  *
2740  * Returns: (transfer none): the `GdkX11Screen`
2741  */
2742 GdkX11Screen *
gdk_x11_display_get_screen(GdkDisplay * display)2743 gdk_x11_display_get_screen (GdkDisplay *display)
2744 {
2745   return GDK_X11_DISPLAY (display)->screen;
2746 }
2747 
2748 static GdkKeymap *
gdk_x11_display_get_keymap(GdkDisplay * display)2749 gdk_x11_display_get_keymap (GdkDisplay *display)
2750 {
2751   GdkX11Display *display_x11;
2752   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
2753   display_x11 = GDK_X11_DISPLAY (display);
2754 
2755   if (!display_x11->keymap)
2756     {
2757       display_x11->keymap = g_object_new (GDK_TYPE_X11_KEYMAP, NULL);
2758       display_x11->keymap->display = display; /* beware of ref cycle */
2759     }
2760 
2761   return display_x11->keymap;
2762 }
2763 
2764 static GdkSeat *
gdk_x11_display_get_default_seat(GdkDisplay * display)2765 gdk_x11_display_get_default_seat (GdkDisplay *display)
2766 {
2767   GList *seats, *l;
2768   int device_id;
2769   gboolean result = FALSE;
2770 
2771   seats = gdk_display_list_seats (display);
2772 
2773   gdk_x11_display_error_trap_push (display);
2774   result = XIGetClientPointer (GDK_DISPLAY_XDISPLAY (display),
2775                                None, &device_id);
2776   gdk_x11_display_error_trap_pop_ignored (display);
2777 
2778   for (l = seats; l; l = l->next)
2779     {
2780       GdkDevice *pointer;
2781 
2782       pointer = gdk_seat_get_pointer (l->data);
2783 
2784       if (gdk_x11_device_get_id (pointer) == device_id || !result)
2785         {
2786           GdkSeat *seat = l->data;
2787           g_list_free (seats);
2788 
2789           return seat;
2790         }
2791     }
2792 
2793   g_list_free (seats);
2794 
2795   return NULL;
2796 }
2797 
2798 static GListModel *
gdk_x11_display_get_monitors(GdkDisplay * display)2799 gdk_x11_display_get_monitors (GdkDisplay *display)
2800 {
2801   GdkX11Display *self = GDK_X11_DISPLAY (display);
2802 
2803   return G_LIST_MODEL (self->monitors);
2804 }
2805 
2806 /**
2807  * gdk_x11_display_get_primary_monitor:
2808  * @display: (type GdkX11Display): a `GdkDisplay`
2809  *
2810  * Gets the primary monitor for the display.
2811  *
2812  * The primary monitor is considered the monitor where the “main desktop”
2813  * lives. While normal application surfaces typically allow the window
2814  * manager to place the surfaces, specialized desktop applications
2815  * such as panels should place themselves on the primary monitor.
2816  *
2817  * If no monitor is the designated primary monitor, any monitor
2818  * (usually the first) may be returned.
2819  *
2820  * Returns: (transfer none): the primary monitor, or any monitor if no
2821  *   primary monitor is configured by the user
2822  */
2823 GdkMonitor *
gdk_x11_display_get_primary_monitor(GdkDisplay * display)2824 gdk_x11_display_get_primary_monitor (GdkDisplay *display)
2825 {
2826   GdkX11Display *self = GDK_X11_DISPLAY (display);
2827   GdkMonitor *monitor;
2828 
2829   monitor = g_list_model_get_item (G_LIST_MODEL (self->monitors), self->primary_monitor);
2830   if (monitor == NULL)
2831     monitor = g_list_model_get_item (G_LIST_MODEL (self->monitors), 0);
2832 
2833   /* because g_list_model_get_item() returns a ref */
2834   if (monitor)
2835     g_object_unref (monitor);
2836 
2837   return monitor;
2838 }
2839 
2840 int
gdk_x11_display_get_window_depth(GdkX11Display * display)2841 gdk_x11_display_get_window_depth (GdkX11Display *display)
2842 {
2843   return display->window_depth;
2844 }
2845 
2846 Visual *
gdk_x11_display_get_window_visual(GdkX11Display * display)2847 gdk_x11_display_get_window_visual (GdkX11Display *display)
2848 {
2849   return display->window_visual;
2850 }
2851 
2852 Colormap
gdk_x11_display_get_window_colormap(GdkX11Display * display)2853 gdk_x11_display_get_window_colormap (GdkX11Display *display)
2854 {
2855   return display->window_colormap;
2856 }
2857 
2858 static gboolean
gdk_x11_display_get_setting(GdkDisplay * display,const char * name,GValue * value)2859 gdk_x11_display_get_setting (GdkDisplay  *display,
2860                              const char *name,
2861                              GValue      *value)
2862 {
2863   return gdk_x11_screen_get_setting (GDK_X11_DISPLAY (display)->screen, name, value);
2864 }
2865 
2866 GList *
gdk_x11_display_get_toplevel_windows(GdkDisplay * display)2867 gdk_x11_display_get_toplevel_windows (GdkDisplay *display)
2868 {
2869   return GDK_X11_DISPLAY (display)->toplevels;
2870 }
2871 
2872 static gboolean
gdk_boolean_handled_accumulator(GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,gpointer dummy)2873 gdk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2874                                  GValue                *return_accu,
2875                                  const GValue          *handler_return,
2876                                  gpointer               dummy)
2877 {
2878   gboolean continue_emission;
2879   gboolean signal_handled;
2880 
2881   signal_handled = g_value_get_boolean (handler_return);
2882   g_value_set_boolean (return_accu, signal_handled);
2883   continue_emission = !signal_handled;
2884 
2885   return continue_emission;
2886 }
2887 
2888 static gboolean
gdk_x11_display_init_gl_backend(GdkX11Display * self,Visual ** out_visual,int * out_depth,GError ** error)2889 gdk_x11_display_init_gl_backend (GdkX11Display  *self,
2890                                  Visual        **out_visual,
2891                                  int            *out_depth,
2892                                  GError        **error)
2893 {
2894   GdkDisplay *display G_GNUC_UNUSED = GDK_DISPLAY (self);
2895 
2896   if (GDK_DISPLAY_DEBUG_CHECK (display, GL_EGL))
2897     return gdk_x11_display_init_egl (self, TRUE, out_visual, out_depth, error);
2898   if (GDK_DISPLAY_DEBUG_CHECK (display, GL_GLX))
2899     return gdk_x11_display_init_glx (self, out_visual, out_depth, error);
2900 
2901   /* No env vars set, do the regular GL initialization.
2902    *
2903    * We try EGL first, but are very picky about what we accept.
2904    * If that fails, we try to go with GLX instead.
2905    * And if that also fails, we try EGL again, but this time accept anything.
2906    *
2907    * The idea here is that EGL is the preferred method going forward, but GLX is
2908    * the tried and tested method that we know works. So if we detect issues with
2909    * EGL, we want to avoid using it in favor of GLX.
2910    */
2911 
2912   if (gdk_x11_display_init_egl (self, FALSE, out_visual, out_depth, error))
2913     return TRUE;
2914   g_clear_error (error);
2915 
2916   if (gdk_x11_display_init_glx (self, out_visual, out_depth, error))
2917     return TRUE;
2918   g_clear_error (error);
2919 
2920   return gdk_x11_display_init_egl (self, TRUE, out_visual, out_depth, error);
2921 }
2922 
2923 static GdkGLContext *
gdk_x11_display_init_gl(GdkDisplay * display,GError ** error)2924 gdk_x11_display_init_gl (GdkDisplay  *display,
2925                          GError     **error)
2926 {
2927   GdkX11Display *self = GDK_X11_DISPLAY (display);
2928 
2929   if (!gdk_x11_display_init_gl_backend (self, &self->window_visual, &self->window_depth, error))
2930     return FALSE;
2931 
2932   gdk_x11_display_init_leader_surface (self);
2933 
2934   if (self->egl_display)
2935     return g_object_new (GDK_TYPE_X11_GL_CONTEXT_EGL, "surface", self->leader_gdk_surface, NULL);
2936   else if (self->glx_config != NULL)
2937     return g_object_new (GDK_TYPE_X11_GL_CONTEXT_GLX, "surface", self->leader_gdk_surface, NULL);
2938   else
2939     g_return_val_if_reached (NULL);
2940 }
2941 
2942 static void
gdk_x11_display_class_init(GdkX11DisplayClass * class)2943 gdk_x11_display_class_init (GdkX11DisplayClass * class)
2944 {
2945   GObjectClass *object_class = G_OBJECT_CLASS (class);
2946   GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
2947 
2948   object_class->dispose = gdk_x11_display_dispose;
2949   object_class->finalize = gdk_x11_display_finalize;
2950 
2951   display_class->cairo_context_type = GDK_TYPE_X11_CAIRO_CONTEXT;
2952 #ifdef GDK_RENDERING_VULKAN
2953   display_class->vk_context_type = GDK_TYPE_X11_VULKAN_CONTEXT;
2954   display_class->vk_extension_name = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
2955 #endif
2956 
2957   display_class->get_name = gdk_x11_display_get_name;
2958   display_class->beep = gdk_x11_display_beep;
2959   display_class->sync = gdk_x11_display_sync;
2960   display_class->flush = gdk_x11_display_flush;
2961   display_class->make_default = gdk_x11_display_make_default;
2962   display_class->has_pending = gdk_x11_display_has_pending;
2963   display_class->queue_events = _gdk_x11_display_queue_events;
2964   display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
2965 
2966   display_class->get_next_serial = gdk_x11_display_get_next_serial;
2967   display_class->get_startup_notification_id = gdk_x11_display_get_startup_notification_id;
2968   display_class->notify_startup_complete = gdk_x11_display_notify_startup_complete;
2969   display_class->create_surface = _gdk_x11_display_create_surface;
2970   display_class->get_keymap = gdk_x11_display_get_keymap;
2971 
2972   display_class->init_gl = gdk_x11_display_init_gl;
2973 
2974   display_class->get_default_seat = gdk_x11_display_get_default_seat;
2975 
2976   display_class->get_monitors = gdk_x11_display_get_monitors;
2977   display_class->get_setting = gdk_x11_display_get_setting;
2978   display_class->set_cursor_theme = gdk_x11_display_set_cursor_theme;
2979 
2980   class->xevent = gdk_event_source_xevent;
2981 
2982   /**
2983    * GdkX11Display::xevent:
2984    * @display: (type GdkX11Display): the object on which the signal is emitted
2985    * @xevent: a pointer to the XEvent to process
2986    *
2987    * The ::xevent signal is a low level signal that is emitted
2988    * whenever an XEvent has been received.
2989    *
2990    * When handlers to this signal return %TRUE, no other handlers will be
2991    * invoked. In particular, the default handler for this function is
2992    * GDK's own event handling mechanism, so by returning %TRUE for an event
2993    * that GDK expects to translate, you may break GDK and/or GTK+ in
2994    * interesting ways. You have been warned.
2995    *
2996    * If you want this signal handler to queue a `GdkEvent`, you can use
2997    * gdk_display_put_event().
2998    *
2999    * If you are interested in X GenericEvents, bear in mind that
3000    * XGetEventData() has been already called on the event, and
3001    * XFreeEventData() will be called afterwards.
3002    *
3003    * Returns: %TRUE to stop other handlers from being invoked for the event.
3004    *   %FALSE to propagate the event further.
3005    */
3006   signals[XEVENT] =
3007     g_signal_new (g_intern_static_string ("xevent"),
3008 		  G_OBJECT_CLASS_TYPE (object_class),
3009                   G_SIGNAL_RUN_LAST,
3010 		  G_STRUCT_OFFSET (GdkX11DisplayClass, xevent),
3011                   gdk_boolean_handled_accumulator, NULL,
3012                   _gdk_marshal_BOOLEAN__POINTER,
3013                   G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
3014 
3015   _gdk_x11_surfaceing_init ();
3016 }
3017