1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /*
4  * Copyright (C) 2001 Havoc Pennington
5  * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
6  * Copyright (C) 2003, 2004 Rob Adams
7  * Copyright (C) 2004-2006 Elijah Newren
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 /**
24  * SECTION:x11-display
25  * @title: MetaX11Display
26  * @short_description: Mutter X display handler
27  *
28  * The X11 display is represented as a #MetaX11Display struct.
29  */
30 
31 #include "config.h"
32 
33 #include "core/display-private.h"
34 #include "x11/meta-x11-display-private.h"
35 
36 #include <gdk/gdk.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <X11/Xatom.h>
41 #include <X11/XKBlib.h>
42 #include <X11/extensions/shape.h>
43 #include <X11/Xcursor/Xcursor.h>
44 #include <X11/extensions/Xcomposite.h>
45 #include <X11/extensions/Xdamage.h>
46 #include <X11/extensions/Xfixes.h>
47 #include <X11/extensions/Xinerama.h>
48 #include <X11/extensions/Xrandr.h>
49 
50 #include "backends/meta-backend-private.h"
51 #include "backends/meta-dnd-private.h"
52 #include "backends/meta-cursor-sprite-xcursor.h"
53 #include "backends/meta-logical-monitor.h"
54 #include "backends/meta-settings-private.h"
55 #include "backends/x11/meta-backend-x11.h"
56 #include "backends/x11/meta-stage-x11.h"
57 #include "core/frame.h"
58 #include "core/meta-workspace-manager-private.h"
59 #include "core/util-private.h"
60 #include "core/workspace-private.h"
61 #include "meta/main.h"
62 #include "meta/meta-x11-errors.h"
63 
64 #include "x11/events.h"
65 #include "x11/group-props.h"
66 #include "x11/meta-x11-selection-private.h"
67 #include "x11/window-props.h"
68 #include "x11/xprops.h"
69 
70 #ifdef HAVE_WAYLAND
71 #include "wayland/meta-xwayland-private.h"
72 #endif
73 
74 G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT)
75 
76 static GQuark quark_x11_display_logical_monitor_data = 0;
77 
78 typedef struct _MetaX11DisplayLogicalMonitorData
79 {
80   int xinerama_index;
81 } MetaX11DisplayLogicalMonitorData;
82 
83 static GdkDisplay *prepared_gdk_display = NULL;
84 
85 static char *get_screen_name (Display *xdisplay,
86                               int      number);
87 
88 static void on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
89                                           MetaX11Display     *x11_display);
90 
91 static void update_cursor_theme (MetaX11Display *x11_display);
92 static void unset_wm_check_hint (MetaX11Display *x11_display);
93 
94 static void prefs_changed_callback (MetaPreference pref,
95                                     void          *data);
96 
97 static void
meta_x11_display_unmanage_windows(MetaX11Display * x11_display)98 meta_x11_display_unmanage_windows (MetaX11Display *x11_display)
99 {
100   GList *windows, *l;
101 
102   if (!x11_display->xids)
103     return;
104 
105   windows = g_hash_table_get_values (x11_display->xids);
106   g_list_foreach (windows, (GFunc) g_object_ref, NULL);
107 
108   for (l = windows; l; l = l->next)
109     {
110       if (META_IS_WINDOW (l->data))
111         {
112           MetaWindow *window = l->data;
113 
114           if (!window->unmanaging)
115             meta_window_unmanage (window, META_CURRENT_TIME);
116         }
117       else if (META_IS_BARRIER (l->data))
118         meta_barrier_destroy (META_BARRIER (l->data));
119       else
120         g_assert_not_reached ();
121     }
122   g_list_free_full (windows, g_object_unref);
123 }
124 
125 static void
meta_x11_display_dispose(GObject * object)126 meta_x11_display_dispose (GObject *object)
127 {
128   MetaX11Display *x11_display = META_X11_DISPLAY (object);
129 
130   x11_display->closing = TRUE;
131 
132   if (x11_display->empty_region != None)
133     {
134       XFixesDestroyRegion (x11_display->xdisplay,
135                            x11_display->empty_region);
136       x11_display->empty_region = None;
137     }
138 
139   meta_x11_startup_notification_release (x11_display);
140 
141   meta_prefs_remove_listener (prefs_changed_callback, x11_display);
142 
143   meta_x11_display_ungrab_keys (x11_display);
144 
145   g_clear_object (&x11_display->x11_stack);
146 
147   meta_x11_selection_shutdown (x11_display);
148   meta_x11_display_unmanage_windows (x11_display);
149 
150   if (x11_display->ui)
151     {
152       meta_ui_free (x11_display->ui);
153       x11_display->ui = NULL;
154     }
155 
156   if (x11_display->no_focus_window != None)
157     {
158       XUnmapWindow (x11_display->xdisplay, x11_display->no_focus_window);
159       XDestroyWindow (x11_display->xdisplay, x11_display->no_focus_window);
160 
161       x11_display->no_focus_window = None;
162     }
163 
164   if (x11_display->composite_overlay_window != None)
165     {
166       XCompositeReleaseOverlayWindow (x11_display->xdisplay,
167                                       x11_display->composite_overlay_window);
168 
169       x11_display->composite_overlay_window = None;
170     }
171 
172   if (x11_display->wm_sn_selection_window != None)
173     {
174       XDestroyWindow (x11_display->xdisplay, x11_display->wm_sn_selection_window);
175       x11_display->wm_sn_selection_window = None;
176     }
177 
178   if (x11_display->timestamp_pinging_window != None)
179     {
180       XDestroyWindow (x11_display->xdisplay, x11_display->timestamp_pinging_window);
181       x11_display->timestamp_pinging_window = None;
182     }
183 
184   if (x11_display->leader_window != None)
185     {
186       XDestroyWindow (x11_display->xdisplay, x11_display->leader_window);
187       x11_display->leader_window = None;
188     }
189 
190   if (x11_display->guard_window != None)
191     {
192       XUnmapWindow (x11_display->xdisplay, x11_display->guard_window);
193       XDestroyWindow (x11_display->xdisplay, x11_display->guard_window);
194       x11_display->guard_window = None;
195     }
196 
197   if (x11_display->prop_hooks)
198     {
199       meta_x11_display_free_window_prop_hooks (x11_display);
200       x11_display->prop_hooks = NULL;
201     }
202 
203   if (x11_display->group_prop_hooks)
204     {
205       meta_x11_display_free_group_prop_hooks (x11_display);
206       x11_display->group_prop_hooks = NULL;
207     }
208 
209   if (x11_display->xids)
210     {
211       /* Must be after all calls to meta_window_unmanage() since they
212        * unregister windows
213        */
214       g_hash_table_destroy (x11_display->xids);
215       x11_display->xids = NULL;
216     }
217 
218   if (x11_display->xroot != None)
219     {
220       unset_wm_check_hint (x11_display);
221 
222       meta_x11_error_trap_push (x11_display);
223       XSelectInput (x11_display->xdisplay, x11_display->xroot, 0);
224       if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
225         meta_warning ("Could not release screen %d on display \"%s\"",
226                       DefaultScreen (x11_display->xdisplay),
227                       x11_display->name);
228 
229       x11_display->xroot = None;
230     }
231 
232 
233   if (x11_display->xdisplay)
234     {
235       meta_x11_display_free_events (x11_display);
236 
237       x11_display->xdisplay = NULL;
238     }
239 
240   if (x11_display->gdk_display)
241     {
242       gdk_display_close (x11_display->gdk_display);
243       x11_display->gdk_display = NULL;
244     }
245 
246   g_clear_handle_id (&x11_display->display_close_idle, g_source_remove);
247 
248   g_free (x11_display->name);
249   x11_display->name = NULL;
250 
251   g_free (x11_display->screen_name);
252   x11_display->screen_name = NULL;
253 
254   G_OBJECT_CLASS (meta_x11_display_parent_class)->dispose (object);
255 }
256 
257 static void
meta_x11_display_class_init(MetaX11DisplayClass * klass)258 meta_x11_display_class_init (MetaX11DisplayClass *klass)
259 {
260   GObjectClass *object_class = G_OBJECT_CLASS (klass);
261 
262   object_class->dispose = meta_x11_display_dispose;
263 }
264 
265 static void
meta_x11_display_init(MetaX11Display * x11_display)266 meta_x11_display_init (MetaX11Display *x11_display)
267 {
268   quark_x11_display_logical_monitor_data =
269     g_quark_from_static_string ("-meta-x11-display-logical-monitor-data");
270 }
271 
272 static void
query_xsync_extension(MetaX11Display * x11_display)273 query_xsync_extension (MetaX11Display *x11_display)
274 {
275   int major, minor;
276 
277   x11_display->have_xsync = FALSE;
278 
279   x11_display->xsync_error_base = 0;
280   x11_display->xsync_event_base = 0;
281 
282   /* I don't think we really have to fill these in */
283   major = SYNC_MAJOR_VERSION;
284   minor = SYNC_MINOR_VERSION;
285 
286   if (!XSyncQueryExtension (x11_display->xdisplay,
287                             &x11_display->xsync_event_base,
288                             &x11_display->xsync_error_base) ||
289       !XSyncInitialize (x11_display->xdisplay,
290                         &major, &minor))
291     {
292       x11_display->xsync_error_base = 0;
293       x11_display->xsync_event_base = 0;
294     }
295   else
296     {
297       x11_display->have_xsync = TRUE;
298       XSyncSetPriority (x11_display->xdisplay, None, 10);
299     }
300 
301   meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d",
302                 major, minor,
303                 x11_display->xsync_error_base,
304                 x11_display->xsync_event_base);
305 }
306 
307 static void
query_xshape_extension(MetaX11Display * x11_display)308 query_xshape_extension (MetaX11Display *x11_display)
309 {
310   x11_display->have_shape = FALSE;
311 
312   x11_display->shape_error_base = 0;
313   x11_display->shape_event_base = 0;
314 
315   if (!XShapeQueryExtension (x11_display->xdisplay,
316                              &x11_display->shape_event_base,
317                              &x11_display->shape_error_base))
318     {
319       x11_display->shape_error_base = 0;
320       x11_display->shape_event_base = 0;
321     }
322   else
323     x11_display->have_shape = TRUE;
324 
325   meta_verbose ("Attempted to init Shape, found error base %d event base %d",
326                 x11_display->shape_error_base,
327                 x11_display->shape_event_base);
328 }
329 
330 static void
query_xcomposite_extension(MetaX11Display * x11_display)331 query_xcomposite_extension (MetaX11Display *x11_display)
332 {
333   x11_display->have_composite = FALSE;
334 
335   x11_display->composite_error_base = 0;
336   x11_display->composite_event_base = 0;
337 
338   if (!XCompositeQueryExtension (x11_display->xdisplay,
339                                  &x11_display->composite_event_base,
340                                  &x11_display->composite_error_base))
341     {
342       x11_display->composite_error_base = 0;
343       x11_display->composite_event_base = 0;
344     }
345   else
346     {
347       x11_display->composite_major_version = 0;
348       x11_display->composite_minor_version = 0;
349       if (XCompositeQueryVersion (x11_display->xdisplay,
350                                   &x11_display->composite_major_version,
351                                   &x11_display->composite_minor_version))
352         {
353           x11_display->have_composite = TRUE;
354         }
355       else
356         {
357           x11_display->composite_major_version = 0;
358           x11_display->composite_minor_version = 0;
359         }
360     }
361 
362   meta_verbose ("Attempted to init Composite, found error base %d event base %d "
363                 "extn ver %d %d",
364                 x11_display->composite_error_base,
365                 x11_display->composite_event_base,
366                 x11_display->composite_major_version,
367                 x11_display->composite_minor_version);
368 }
369 
370 static void
query_xdamage_extension(MetaX11Display * x11_display)371 query_xdamage_extension (MetaX11Display *x11_display)
372 {
373   x11_display->have_damage = FALSE;
374 
375   x11_display->damage_error_base = 0;
376   x11_display->damage_event_base = 0;
377 
378   if (!XDamageQueryExtension (x11_display->xdisplay,
379                               &x11_display->damage_event_base,
380                               &x11_display->damage_error_base))
381     {
382       x11_display->damage_error_base = 0;
383       x11_display->damage_event_base = 0;
384     }
385   else
386     x11_display->have_damage = TRUE;
387 
388   meta_verbose ("Attempted to init Damage, found error base %d event base %d",
389                 x11_display->damage_error_base,
390                 x11_display->damage_event_base);
391 }
392 
393 static void
query_xfixes_extension(MetaX11Display * x11_display)394 query_xfixes_extension (MetaX11Display *x11_display)
395 {
396   x11_display->xfixes_error_base = 0;
397   x11_display->xfixes_event_base = 0;
398 
399   if (XFixesQueryExtension (x11_display->xdisplay,
400                             &x11_display->xfixes_event_base,
401                             &x11_display->xfixes_error_base))
402     {
403       int xfixes_major, xfixes_minor;
404 
405       XFixesQueryVersion (x11_display->xdisplay, &xfixes_major, &xfixes_minor);
406 
407       if (xfixes_major * 100 + xfixes_minor < 500)
408         meta_fatal ("Mutter requires XFixes 5.0");
409     }
410   else
411     {
412       meta_fatal ("Mutter requires XFixes 5.0");
413     }
414 
415   meta_verbose ("Attempted to init XFixes, found error base %d event base %d",
416                 x11_display->xfixes_error_base,
417                 x11_display->xfixes_event_base);
418 }
419 
420 static void
query_xi_extension(MetaX11Display * x11_display)421 query_xi_extension (MetaX11Display *x11_display)
422 {
423   int major = 2, minor = 3;
424   gboolean has_xi = FALSE;
425 
426   if (XQueryExtension (x11_display->xdisplay,
427                        "XInputExtension",
428                        &x11_display->xinput_opcode,
429                        &x11_display->xinput_error_base,
430                        &x11_display->xinput_event_base))
431     {
432         if (XIQueryVersion (x11_display->xdisplay, &major, &minor) == Success)
433         {
434           int version = (major * 10) + minor;
435           if (version >= 22)
436             has_xi = TRUE;
437 
438           if (version >= 23)
439             x11_display->have_xinput_23 = TRUE;
440         }
441     }
442 
443   if (!has_xi)
444     meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer");
445 }
446 
447 /*
448  * Initialises the bell subsystem. This involves initialising
449  * XKB (which, despite being a keyboard extension, is the
450  * place to look for bell notifications), then asking it
451  * to send us bell notifications, and then also switching
452  * off the audible bell if we're using a visual one ourselves.
453  *
454  * \bug There is a line of code that's never run that tells
455  * XKB to reset the bell status after we quit. Bill H said
456  * (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)
457  * that XFree86's implementation is broken so we shouldn't
458  * call it, but that was in 2002. Is it working now?
459  */
460 static void
init_x11_bell(MetaX11Display * x11_display)461 init_x11_bell (MetaX11Display *x11_display)
462 {
463   int xkb_base_error_type, xkb_opcode;
464 
465   if (!XkbQueryExtension (x11_display->xdisplay, &xkb_opcode,
466                           &x11_display->xkb_base_event_type,
467                           &xkb_base_error_type,
468                           NULL, NULL))
469     {
470       x11_display->xkb_base_event_type = -1;
471       meta_warning ("could not find XKB extension.");
472     }
473   else
474     {
475       unsigned int mask = XkbBellNotifyMask;
476       gboolean visual_bell_auto_reset = FALSE;
477       /* TRUE if and when non-broken version is available */
478       XkbSelectEvents (x11_display->xdisplay,
479                        XkbUseCoreKbd,
480                        XkbBellNotifyMask,
481                        XkbBellNotifyMask);
482 
483       if (visual_bell_auto_reset)
484         {
485           XkbSetAutoResetControls (x11_display->xdisplay,
486                                    XkbAudibleBellMask,
487                                    &mask,
488                                    &mask);
489         }
490     }
491 
492   /* We are playing sounds using libcanberra support, we handle the
493    * bell whether its an audible bell or a visible bell */
494   XkbChangeEnabledControls (x11_display->xdisplay,
495                             XkbUseCoreKbd,
496                             XkbAudibleBellMask,
497                             0);
498 }
499 
500 /*
501  * \bug This is never called! If we had XkbSetAutoResetControls
502  * enabled in meta_x11_bell_init(), this wouldn't be a problem,
503  * but we don't.
504  */
505 G_GNUC_UNUSED static void
shutdown_x11_bell(MetaX11Display * x11_display)506 shutdown_x11_bell (MetaX11Display *x11_display)
507 {
508   /* TODO: persist initial bell state in display, reset here */
509   XkbChangeEnabledControls (x11_display->xdisplay,
510                             XkbUseCoreKbd,
511                             XkbAudibleBellMask,
512                             XkbAudibleBellMask);
513 }
514 
515 static void
set_desktop_geometry_hint(MetaX11Display * x11_display)516 set_desktop_geometry_hint (MetaX11Display *x11_display)
517 {
518   unsigned long data[2];
519   int monitor_width, monitor_height;
520 
521   if (x11_display->display->closing > 0)
522     return;
523 
524   meta_display_get_size (x11_display->display, &monitor_width, &monitor_height);
525 
526   data[0] = monitor_width;
527   data[1] = monitor_height;
528 
529   meta_verbose ("Setting _NET_DESKTOP_GEOMETRY to %lu, %lu", data[0], data[1]);
530 
531   meta_x11_error_trap_push (x11_display);
532   XChangeProperty (x11_display->xdisplay,
533                    x11_display->xroot,
534                    x11_display->atom__NET_DESKTOP_GEOMETRY,
535                    XA_CARDINAL,
536                    32, PropModeReplace, (guchar*) data, 2);
537   meta_x11_error_trap_pop (x11_display);
538 }
539 
540 static void
set_desktop_viewport_hint(MetaX11Display * x11_display)541 set_desktop_viewport_hint (MetaX11Display *x11_display)
542 {
543   unsigned long data[2];
544 
545   if (x11_display->display->closing > 0)
546     return;
547 
548   /*
549    * Mutter does not implement viewports, so this is a fixed 0,0
550    */
551   data[0] = 0;
552   data[1] = 0;
553 
554   meta_verbose ("Setting _NET_DESKTOP_VIEWPORT to 0, 0");
555 
556   meta_x11_error_trap_push (x11_display);
557   XChangeProperty (x11_display->xdisplay,
558                    x11_display->xroot,
559                    x11_display->atom__NET_DESKTOP_VIEWPORT,
560                    XA_CARDINAL,
561                    32, PropModeReplace, (guchar*) data, 2);
562   meta_x11_error_trap_pop (x11_display);
563 }
564 
565 static int
set_wm_check_hint(MetaX11Display * x11_display)566 set_wm_check_hint (MetaX11Display *x11_display)
567 {
568   unsigned long data[1];
569 
570   g_return_val_if_fail (x11_display->leader_window != None, 0);
571 
572   data[0] = x11_display->leader_window;
573 
574   XChangeProperty (x11_display->xdisplay,
575                    x11_display->xroot,
576                    x11_display->atom__NET_SUPPORTING_WM_CHECK,
577                    XA_WINDOW,
578                    32, PropModeReplace, (guchar*) data, 1);
579 
580   return Success;
581 }
582 
583 static void
unset_wm_check_hint(MetaX11Display * x11_display)584 unset_wm_check_hint (MetaX11Display *x11_display)
585 {
586   XDeleteProperty (x11_display->xdisplay,
587                    x11_display->xroot,
588                    x11_display->atom__NET_SUPPORTING_WM_CHECK);
589 }
590 
591 static int
set_supported_hint(MetaX11Display * x11_display)592 set_supported_hint (MetaX11Display *x11_display)
593 {
594   Atom atoms[] = {
595 #define EWMH_ATOMS_ONLY
596 #define item(x)  x11_display->atom_##x,
597 #include "x11/atomnames.h"
598 #undef item
599 #undef EWMH_ATOMS_ONLY
600 
601     x11_display->atom__GTK_FRAME_EXTENTS,
602     x11_display->atom__GTK_SHOW_WINDOW_MENU,
603     x11_display->atom__GTK_EDGE_CONSTRAINTS,
604     x11_display->atom__GTK_WORKAREAS,
605   };
606 
607   XChangeProperty (x11_display->xdisplay,
608                    x11_display->xroot,
609                    x11_display->atom__NET_SUPPORTED,
610                    XA_ATOM,
611                    32, PropModeReplace,
612                    (guchar*) atoms, G_N_ELEMENTS(atoms));
613 
614   return Success;
615 }
616 
617 static int
set_wm_icon_size_hint(MetaX11Display * x11_display)618 set_wm_icon_size_hint (MetaX11Display *x11_display)
619 {
620 #define N_VALS 6
621   gulong vals[N_VALS];
622 
623   /* We've bumped the real icon size up to 96x96, but
624    * we really should not add these sorts of constraints
625    * on clients still using the legacy WM_HINTS interface.
626    */
627 #define LEGACY_ICON_SIZE 32
628 
629   /* min width, min height, max w, max h, width inc, height inc */
630   vals[0] = LEGACY_ICON_SIZE;
631   vals[1] = LEGACY_ICON_SIZE;
632   vals[2] = LEGACY_ICON_SIZE;
633   vals[3] = LEGACY_ICON_SIZE;
634   vals[4] = 0;
635   vals[5] = 0;
636 #undef LEGACY_ICON_SIZE
637 
638   XChangeProperty (x11_display->xdisplay,
639                    x11_display->xroot,
640                    x11_display->atom_WM_ICON_SIZE,
641                    XA_CARDINAL,
642                    32, PropModeReplace, (guchar*) vals, N_VALS);
643 
644   return Success;
645 #undef N_VALS
646 }
647 
648 static Window
take_manager_selection(MetaX11Display * x11_display,Window xroot,Atom manager_atom,int timestamp,gboolean should_replace)649 take_manager_selection (MetaX11Display *x11_display,
650                         Window          xroot,
651                         Atom            manager_atom,
652                         int             timestamp,
653                         gboolean        should_replace)
654 {
655   Window current_owner, new_owner;
656 
657   current_owner = XGetSelectionOwner (x11_display->xdisplay, manager_atom);
658   if (current_owner != None)
659     {
660       XSetWindowAttributes attrs;
661 
662       if (should_replace)
663         {
664           /* We want to find out when the current selection owner dies */
665           meta_x11_error_trap_push (x11_display);
666           attrs.event_mask = StructureNotifyMask;
667           XChangeWindowAttributes (x11_display->xdisplay, current_owner, CWEventMask, &attrs);
668           if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
669             current_owner = None; /* don't wait for it to die later on */
670         }
671       else
672         {
673           meta_warning (_("Display “%s” already has a window manager; try using the --replace option to replace the current window manager."),
674                         x11_display->name);
675           return None;
676         }
677     }
678 
679   /* We need SelectionClear and SelectionRequest events on the new owner,
680    * but those cannot be masked, so we only need NoEventMask.
681    */
682   new_owner = meta_x11_display_create_offscreen_window (x11_display, xroot, NoEventMask);
683 
684   XSetSelectionOwner (x11_display->xdisplay, manager_atom, new_owner, timestamp);
685 
686   if (XGetSelectionOwner (x11_display->xdisplay, manager_atom) != new_owner)
687     {
688       meta_warning ("Could not acquire selection: %s", XGetAtomName (x11_display->xdisplay, manager_atom));
689       return None;
690     }
691 
692   {
693     /* Send client message indicating that we are now the selection owner */
694     XClientMessageEvent ev;
695 
696     ev.type = ClientMessage;
697     ev.window = xroot;
698     ev.message_type = x11_display->atom_MANAGER;
699     ev.format = 32;
700     ev.data.l[0] = timestamp;
701     ev.data.l[1] = manager_atom;
702 
703     XSendEvent (x11_display->xdisplay, xroot, False, StructureNotifyMask, (XEvent *) &ev);
704   }
705 
706   /* Wait for old window manager to go away */
707   if (current_owner != None)
708     {
709       XEvent event;
710 
711       /* We sort of block infinitely here which is probably lame. */
712 
713       meta_verbose ("Waiting for old window manager to exit");
714       do
715         XWindowEvent (x11_display->xdisplay, current_owner, StructureNotifyMask, &event);
716       while (event.type != DestroyNotify);
717     }
718 
719   return new_owner;
720 }
721 
722 /* Create the leader window here. Set its properties and
723  * use the timestamp from one of the PropertyNotify events
724  * that will follow.
725  */
726 static void
init_leader_window(MetaX11Display * x11_display,guint32 * timestamp)727 init_leader_window (MetaX11Display *x11_display,
728                     guint32        *timestamp)
729 {
730   MetaContext *context = meta_display_get_context (x11_display->display);
731   const char *gnome_wm_keybindings;
732   gulong data[1];
733   XEvent event;
734 
735   /* We only care about the PropertyChangeMask in the next 30 or so lines of
736    * code.  Note that gdk will at some point unset the PropertyChangeMask for
737    * this window, so we can't rely on it still being set later.  See bug
738    * 354213 for details.
739    */
740   x11_display->leader_window =
741     meta_x11_display_create_offscreen_window (x11_display,
742                                               x11_display->xroot,
743                                               PropertyChangeMask);
744 
745   meta_prop_set_utf8_string_hint (x11_display,
746                                   x11_display->leader_window,
747                                   x11_display->atom__NET_WM_NAME,
748                                   meta_context_get_name (context));
749 
750   gnome_wm_keybindings = meta_context_get_gnome_wm_keybindings (context);
751   meta_prop_set_utf8_string_hint (x11_display,
752                                   x11_display->leader_window,
753                                   x11_display->atom__GNOME_WM_KEYBINDINGS,
754                                   gnome_wm_keybindings);
755 
756   meta_prop_set_utf8_string_hint (x11_display,
757                                   x11_display->leader_window,
758                                   x11_display->atom__MUTTER_VERSION,
759                                   VERSION);
760 
761   data[0] = x11_display->leader_window;
762   XChangeProperty (x11_display->xdisplay,
763                    x11_display->leader_window,
764                    x11_display->atom__NET_SUPPORTING_WM_CHECK,
765                    XA_WINDOW,
766                    32, PropModeReplace, (guchar*) data, 1);
767 
768   XWindowEvent (x11_display->xdisplay,
769                 x11_display->leader_window,
770                 PropertyChangeMask,
771                 &event);
772 
773   if (timestamp)
774    *timestamp = event.xproperty.time;
775 
776   /* Make it painfully clear that we can't rely on PropertyNotify events on
777    * this window, as per bug 354213.
778    */
779   XSelectInput (x11_display->xdisplay,
780                 x11_display->leader_window,
781                 NoEventMask);
782 }
783 
784 static void
init_event_masks(MetaX11Display * x11_display)785 init_event_masks (MetaX11Display *x11_display)
786 {
787   long event_mask;
788   unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
789   XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
790 
791   XISetMask (mask.mask, XI_Enter);
792   XISetMask (mask.mask, XI_Leave);
793   XISetMask (mask.mask, XI_FocusIn);
794   XISetMask (mask.mask, XI_FocusOut);
795   if (META_X11_DISPLAY_HAS_XINPUT_23 (x11_display))
796     {
797       XISetMask (mask.mask, XI_BarrierHit);
798       XISetMask (mask.mask, XI_BarrierLeave);
799     }
800   XISelectEvents (x11_display->xdisplay, x11_display->xroot, &mask, 1);
801 
802   event_mask = (SubstructureRedirectMask | SubstructureNotifyMask |
803                 StructureNotifyMask | ColormapChangeMask | PropertyChangeMask);
804   XSelectInput (x11_display->xdisplay, x11_display->xroot, event_mask);
805 }
806 
807 static void
set_active_workspace_hint(MetaWorkspaceManager * workspace_manager,MetaX11Display * x11_display)808 set_active_workspace_hint (MetaWorkspaceManager *workspace_manager,
809                            MetaX11Display       *x11_display)
810 {
811   unsigned long data[1];
812 
813   /* this is because we destroy the spaces in order,
814    * so we always end up setting a current desktop of
815    * 0 when closing a screen, so lose the current desktop
816    * on restart. By doing this we keep the current
817    * desktop on restart.
818    */
819   if (x11_display->display->closing > 0)
820     return;
821 
822   data[0] = meta_workspace_index (workspace_manager->active_workspace);
823 
824   meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu", data[0]);
825 
826   meta_x11_error_trap_push (x11_display);
827   XChangeProperty (x11_display->xdisplay,
828                    x11_display->xroot,
829                    x11_display->atom__NET_CURRENT_DESKTOP,
830                    XA_CARDINAL,
831                    32, PropModeReplace, (guchar*) data, 1);
832   meta_x11_error_trap_pop (x11_display);
833 }
834 
835 static void
set_number_of_spaces_hint(MetaWorkspaceManager * workspace_manager,GParamSpec * pspec,gpointer user_data)836 set_number_of_spaces_hint (MetaWorkspaceManager *workspace_manager,
837                            GParamSpec           *pspec,
838                            gpointer              user_data)
839 {
840   MetaX11Display *x11_display = user_data;
841   unsigned long data[1];
842 
843   if (x11_display->display->closing > 0)
844     return;
845 
846   data[0] = meta_workspace_manager_get_n_workspaces (workspace_manager);
847 
848   meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu", data[0]);
849 
850   meta_x11_error_trap_push (x11_display);
851   XChangeProperty (x11_display->xdisplay,
852                    x11_display->xroot,
853                    x11_display->atom__NET_NUMBER_OF_DESKTOPS,
854                    XA_CARDINAL,
855                    32, PropModeReplace, (guchar*) data, 1);
856   meta_x11_error_trap_pop (x11_display);
857 }
858 
859 static void
set_showing_desktop_hint(MetaWorkspaceManager * workspace_manager,MetaX11Display * x11_display)860 set_showing_desktop_hint (MetaWorkspaceManager *workspace_manager,
861                           MetaX11Display       *x11_display)
862 {
863   unsigned long data[1];
864 
865   data[0] = workspace_manager->active_workspace->showing_desktop ? 1 : 0;
866 
867   meta_x11_error_trap_push (x11_display);
868   XChangeProperty (x11_display->xdisplay,
869                    x11_display->xroot,
870                    x11_display->atom__NET_SHOWING_DESKTOP,
871                    XA_CARDINAL,
872                    32, PropModeReplace, (guchar*) data, 1);
873   meta_x11_error_trap_pop (x11_display);
874 }
875 
876 static void
set_workspace_names(MetaX11Display * x11_display)877 set_workspace_names (MetaX11Display *x11_display)
878 {
879   MetaWorkspaceManager *workspace_manager;
880   GString *flattened;
881   int i;
882   int n_spaces;
883 
884   workspace_manager = x11_display->display->workspace_manager;
885 
886   /* flatten to nul-separated list */
887   n_spaces = meta_workspace_manager_get_n_workspaces (workspace_manager);
888   flattened = g_string_new ("");
889   i = 0;
890   while (i < n_spaces)
891     {
892       const char *name;
893 
894       name = meta_prefs_get_workspace_name (i);
895 
896       if (name)
897         g_string_append_len (flattened, name,
898                              strlen (name) + 1);
899       else
900         g_string_append_len (flattened, "", 1);
901 
902       ++i;
903     }
904 
905   meta_x11_error_trap_push (x11_display);
906   XChangeProperty (x11_display->xdisplay,
907                    x11_display->xroot,
908                    x11_display->atom__NET_DESKTOP_NAMES,
909                    x11_display->atom_UTF8_STRING,
910                    8, PropModeReplace,
911                    (unsigned char *)flattened->str, flattened->len);
912   meta_x11_error_trap_pop (x11_display);
913 
914   g_string_free (flattened, TRUE);
915 }
916 
917 static void
set_workspace_work_area_hint(MetaWorkspace * workspace,MetaX11Display * x11_display)918 set_workspace_work_area_hint (MetaWorkspace  *workspace,
919                               MetaX11Display *x11_display)
920 {
921   MetaMonitorManager *monitor_manager;
922   GList *logical_monitors;
923   GList *l;
924   int num_monitors;
925   unsigned long *data;
926   unsigned long *tmp;
927   g_autofree char *workarea_name = NULL;
928   Atom workarea_atom;
929 
930   monitor_manager = meta_backend_get_monitor_manager (meta_get_backend ());
931   logical_monitors = meta_monitor_manager_get_logical_monitors (monitor_manager);
932   num_monitors = meta_monitor_manager_get_num_logical_monitors (monitor_manager);
933 
934   data = g_new (unsigned long, num_monitors * 4);
935   tmp = data;
936 
937   for (l = logical_monitors; l; l = l->next)
938     {
939       MetaRectangle area;
940 
941       meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, &area);
942 
943       tmp[0] = area.x;
944       tmp[1] = area.y;
945       tmp[2] = area.width;
946       tmp[3] = area.height;
947 
948       tmp += 4;
949     }
950 
951   workarea_name = g_strdup_printf ("_GTK_WORKAREAS_D%d",
952                                    meta_workspace_index (workspace));
953 
954   workarea_atom = XInternAtom (x11_display->xdisplay, workarea_name, False);
955 
956   meta_x11_error_trap_push (x11_display);
957   XChangeProperty (x11_display->xdisplay,
958                    x11_display->xroot,
959                    workarea_atom,
960                    XA_CARDINAL, 32, PropModeReplace,
961                    (guchar*) data, num_monitors * 4);
962   meta_x11_error_trap_pop (x11_display);
963 
964   g_free (data);
965 }
966 
967 static void
set_work_area_hint(MetaDisplay * display,MetaX11Display * x11_display)968 set_work_area_hint (MetaDisplay    *display,
969                     MetaX11Display *x11_display)
970 {
971   MetaWorkspaceManager *workspace_manager = display->workspace_manager;
972   int num_workspaces;
973   GList *l;
974   unsigned long *data, *tmp;
975   MetaRectangle area;
976 
977   num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager);
978   data = g_new (unsigned long, num_workspaces * 4);
979   tmp = data;
980 
981   for (l = workspace_manager->workspaces; l; l = l->next)
982     {
983       MetaWorkspace *workspace = l->data;
984 
985       meta_workspace_get_work_area_all_monitors (workspace, &area);
986       set_workspace_work_area_hint (workspace, x11_display);
987 
988       tmp[0] = area.x;
989       tmp[1] = area.y;
990       tmp[2] = area.width;
991       tmp[3] = area.height;
992 
993       tmp += 4;
994     }
995 
996   meta_x11_error_trap_push (x11_display);
997   XChangeProperty (x11_display->xdisplay,
998                    x11_display->xroot,
999                    x11_display->atom__NET_WORKAREA,
1000                    XA_CARDINAL, 32, PropModeReplace,
1001                    (guchar*) data, num_workspaces*4);
1002   meta_x11_error_trap_pop (x11_display);
1003 
1004   g_free (data);
1005 }
1006 
1007 const gchar *
meta_x11_get_display_name(void)1008 meta_x11_get_display_name (void)
1009 {
1010 #ifdef HAVE_WAYLAND
1011   if (meta_is_wayland_compositor ())
1012     {
1013       MetaWaylandCompositor *compositor;
1014 
1015       compositor = meta_wayland_compositor_get_default ();
1016 
1017       return meta_wayland_get_private_xwayland_display_name (compositor);
1018     }
1019   else
1020 #endif
1021     {
1022       return g_getenv ("DISPLAY");
1023     }
1024 }
1025 
1026 gboolean
meta_x11_init_gdk_display(GError ** error)1027 meta_x11_init_gdk_display (GError **error)
1028 {
1029   const char *xdisplay_name;
1030   GdkDisplay *gdk_display;
1031   const char *gdk_gl_env = NULL;
1032   const char *old_no_at_bridge;
1033   Display *xdisplay;
1034 
1035   xdisplay_name = meta_x11_get_display_name ();
1036   if (!xdisplay_name)
1037     {
1038       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1039                    "Unable to open display, DISPLAY not set");
1040       return FALSE;
1041     }
1042 
1043   gdk_set_allowed_backends ("x11");
1044 
1045   gdk_gl_env = g_getenv ("GDK_GL");
1046   g_setenv ("GDK_GL", "disable", TRUE);
1047 
1048   gdk_parse_args (NULL, NULL);
1049   if (!gtk_parse_args (NULL, NULL))
1050     {
1051       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1052                    "Failed to initialize gtk");
1053       return FALSE;
1054     }
1055 
1056   old_no_at_bridge = g_getenv ("NO_AT_BRIDGE");
1057   g_setenv ("NO_AT_BRIDGE", "1", TRUE);
1058   gdk_display = gdk_display_open (xdisplay_name);
1059 
1060   if (old_no_at_bridge)
1061     g_setenv ("NO_AT_BRIDGE", old_no_at_bridge, TRUE);
1062   else
1063     g_unsetenv ("NO_AT_BRIDGE");
1064 
1065   if (!gdk_display)
1066     {
1067       meta_warning (_("Failed to initialize GDK"));
1068 
1069       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1070                    "Failed to initialize GDK");
1071 
1072       return FALSE;
1073     }
1074 
1075   if (gdk_gl_env)
1076     g_setenv("GDK_GL", gdk_gl_env, TRUE);
1077   else
1078     unsetenv("GDK_GL");
1079 
1080   /* We need to be able to fully trust that the window and monitor sizes
1081      that Gdk reports corresponds to the X ones, so we disable the automatic
1082      scale handling */
1083   gdk_x11_display_set_window_scale (gdk_display, 1);
1084 
1085   meta_verbose ("Opening display '%s'", XDisplayName (NULL));
1086 
1087   xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display);
1088 
1089   if (xdisplay == NULL)
1090     {
1091       meta_warning (_("Failed to open X Window System display “%s”"),
1092                     XDisplayName (NULL));
1093 
1094       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1095                    "Failed to open X11 display");
1096 
1097       gdk_display_close (gdk_display);
1098 
1099       return FALSE;
1100     }
1101 
1102   prepared_gdk_display = gdk_display;
1103 
1104   return TRUE;
1105 }
1106 
1107 /**
1108  * meta_x11_display_new:
1109  *
1110  * Opens a new X11 display, sets it up, initialises all the X extensions
1111  * we will need.
1112  *
1113  * Returns: #MetaX11Display if the display was opened successfully,
1114  * and %NULL otherwise-- that is, if the display doesn't exist or
1115  * it already has a window manager, and sets the error appropriately.
1116  */
1117 MetaX11Display *
meta_x11_display_new(MetaDisplay * display,GError ** error)1118 meta_x11_display_new (MetaDisplay *display, GError **error)
1119 {
1120   MetaX11Display *x11_display;
1121   Display *xdisplay;
1122   Screen *xscreen;
1123   Window xroot;
1124   int i, number;
1125   Window new_wm_sn_owner;
1126   gboolean replace_current_wm;
1127   Atom wm_sn_atom;
1128   char buf[128];
1129   guint32 timestamp;
1130   Atom atom_restart_helper;
1131   Window restart_helper_window = None;
1132   GdkDisplay *gdk_display;
1133   MetaBackend *backend = meta_get_backend ();
1134   MetaMonitorManager *monitor_manager =
1135     meta_backend_get_monitor_manager (backend);
1136 
1137   /* A list of all atom names, so that we can intern them in one go. */
1138   const char *atom_names[] = {
1139 #define item(x) #x,
1140 #include "x11/atomnames.h"
1141 #undef item
1142   };
1143   Atom atoms[G_N_ELEMENTS(atom_names)];
1144 
1145   if (!meta_x11_init_gdk_display (error))
1146     return NULL;
1147 
1148   g_assert (prepared_gdk_display);
1149   gdk_display = g_steal_pointer (&prepared_gdk_display);
1150   xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display);
1151 
1152 #ifdef HAVE_WAYLAND
1153   if (meta_is_wayland_compositor ())
1154     meta_xwayland_complete_init (display, xdisplay);
1155 #endif
1156 
1157   if (meta_is_syncing ())
1158     XSynchronize (xdisplay, True);
1159 
1160   replace_current_wm =
1161     meta_context_is_replacing (meta_backend_get_context (backend));
1162 
1163   /* According to _gdk_x11_display_open (), this will be returned
1164    * by gdk_display_get_default_screen ()
1165    */
1166   number = DefaultScreen (xdisplay);
1167 
1168   xroot = RootWindow (xdisplay, number);
1169 
1170   /* FVWM checks for None here, I don't know if this
1171    * ever actually happens
1172    */
1173   if (xroot == None)
1174     {
1175       meta_warning (_("Screen %d on display “%s” is invalid"),
1176                     number, XDisplayName (NULL));
1177 
1178       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1179                    "Failed to open default X11 screen");
1180 
1181       XFlush (xdisplay);
1182       XCloseDisplay (xdisplay);
1183 
1184       gdk_display_close (gdk_display);
1185 
1186       return NULL;
1187     }
1188 
1189   xscreen = ScreenOfDisplay (xdisplay, number);
1190 
1191   atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
1192   restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper);
1193   if (restart_helper_window)
1194     meta_set_is_restart (TRUE);
1195 
1196   x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL);
1197   x11_display->gdk_display = gdk_display;
1198   x11_display->display = display;
1199 
1200   /* here we use XDisplayName which is what the user
1201    * probably put in, vs. DisplayString(display) which is
1202    * canonicalized by XOpenDisplay()
1203    */
1204   x11_display->xdisplay = xdisplay;
1205   x11_display->xroot = xroot;
1206 
1207   x11_display->name = g_strdup (XDisplayName (NULL));
1208   x11_display->screen_name = get_screen_name (xdisplay, number);
1209   x11_display->default_xvisual = DefaultVisualOfScreen (xscreen);
1210   x11_display->default_depth = DefaultDepthOfScreen (xscreen);
1211 
1212   meta_verbose ("Creating %d atoms", (int) G_N_ELEMENTS (atom_names));
1213   XInternAtoms (xdisplay, (char **)atom_names, G_N_ELEMENTS (atom_names),
1214                 False, atoms);
1215 
1216   i = 0;
1217 #define item(x) x11_display->atom_##x = atoms[i++];
1218 #include "x11/atomnames.h"
1219 #undef item
1220 
1221   query_xsync_extension (x11_display);
1222   query_xshape_extension (x11_display);
1223   query_xcomposite_extension (x11_display);
1224   query_xdamage_extension (x11_display);
1225   query_xfixes_extension (x11_display);
1226   query_xi_extension (x11_display);
1227 
1228   g_signal_connect_object (display,
1229                            "cursor-updated",
1230                            G_CALLBACK (update_cursor_theme),
1231                            x11_display,
1232                            G_CONNECT_SWAPPED);
1233 
1234   update_cursor_theme (x11_display);
1235 
1236   x11_display->xids = g_hash_table_new (meta_unsigned_long_hash,
1237                                         meta_unsigned_long_equal);
1238 
1239   x11_display->groups_by_leader = NULL;
1240   x11_display->ui = NULL;
1241   x11_display->composite_overlay_window = None;
1242   x11_display->guard_window = None;
1243   x11_display->leader_window = None;
1244   x11_display->timestamp_pinging_window = None;
1245   x11_display->wm_sn_selection_window = None;
1246 
1247   x11_display->display_close_idle = 0;
1248   x11_display->xselectionclear_timestamp = 0;
1249 
1250   x11_display->last_bell_time = 0;
1251   x11_display->focus_serial = 0;
1252   x11_display->server_focus_window = None;
1253   x11_display->server_focus_serial = 0;
1254 
1255   x11_display->prop_hooks = NULL;
1256   meta_x11_display_init_window_prop_hooks (x11_display);
1257   x11_display->group_prop_hooks = NULL;
1258   meta_x11_display_init_group_prop_hooks (x11_display);
1259 
1260   g_signal_connect_object (monitor_manager,
1261                            "monitors-changed-internal",
1262                            G_CALLBACK (on_monitors_changed_internal),
1263                            x11_display,
1264                            0);
1265 
1266   init_leader_window (x11_display, &timestamp);
1267   x11_display->timestamp = timestamp;
1268 
1269   /* Make a little window used only for pinging the server for timestamps; note
1270    * that meta_create_offscreen_window already selects for PropertyChangeMask.
1271    */
1272   x11_display->timestamp_pinging_window =
1273     meta_x11_display_create_offscreen_window (x11_display,
1274                                               xroot,
1275                                               PropertyChangeMask);
1276 
1277   sprintf (buf, "WM_S%d", number);
1278 
1279   wm_sn_atom = XInternAtom (xdisplay, buf, False);
1280   new_wm_sn_owner = take_manager_selection (x11_display, xroot, wm_sn_atom, timestamp, replace_current_wm);
1281   if (new_wm_sn_owner == None)
1282     {
1283       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
1284                    "Failed to acquire window manager ownership");
1285 
1286       g_object_run_dispose (G_OBJECT (x11_display));
1287       g_clear_object (&x11_display);
1288 
1289       return NULL;
1290     }
1291 
1292   x11_display->wm_sn_selection_window = new_wm_sn_owner;
1293   x11_display->wm_sn_atom = wm_sn_atom;
1294   x11_display->wm_sn_timestamp = timestamp;
1295 
1296   init_event_masks (x11_display);
1297 
1298   /* Select for cursor changes so the cursor tracker is up to date. */
1299   XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask);
1300 
1301   /* If we're a Wayland compositor, then we don't grab the COW, since it
1302    * will map it. */
1303   if (!meta_is_wayland_compositor ())
1304     x11_display->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
1305 
1306   /* Now that we've gotten taken a reference count on the COW, we
1307    * can close the helper that is holding on to it */
1308   if (meta_is_restart ())
1309     XSetSelectionOwner (xdisplay, atom_restart_helper, None, META_CURRENT_TIME);
1310 
1311   /* Handle creating a no_focus_window for this screen */
1312   x11_display->no_focus_window =
1313     meta_x11_display_create_offscreen_window (x11_display,
1314                                               xroot,
1315                                               FocusChangeMask|KeyPressMask|KeyReleaseMask);
1316   XMapWindow (xdisplay, x11_display->no_focus_window);
1317   /* Done with no_focus_window stuff */
1318 
1319   meta_x11_display_init_events (x11_display);
1320 
1321   set_wm_icon_size_hint (x11_display);
1322 
1323   set_supported_hint (x11_display);
1324 
1325   set_wm_check_hint (x11_display);
1326 
1327   set_desktop_viewport_hint (x11_display);
1328 
1329   set_desktop_geometry_hint (x11_display);
1330 
1331   x11_display->ui = meta_ui_new (x11_display);
1332   x11_display->x11_stack = meta_x11_stack_new (x11_display);
1333 
1334   x11_display->keys_grabbed = FALSE;
1335   meta_x11_display_grab_keys (x11_display);
1336 
1337   meta_x11_display_update_workspace_layout (x11_display);
1338 
1339   if (meta_prefs_get_dynamic_workspaces ())
1340     {
1341       int num = 0;
1342       int n_items = 0;
1343       uint32_t *list = NULL;
1344 
1345       if (meta_prop_get_cardinal_list (x11_display,
1346                                        x11_display->xroot,
1347                                        x11_display->atom__NET_NUMBER_OF_DESKTOPS,
1348                                        &list, &n_items))
1349         {
1350           num = list[0];
1351           g_free (list);
1352         }
1353 
1354         if (num > meta_workspace_manager_get_n_workspaces (display->workspace_manager))
1355           meta_workspace_manager_update_num_workspaces (display->workspace_manager, timestamp, num);
1356     }
1357 
1358   g_signal_connect_object (display->workspace_manager, "active-workspace-changed",
1359                            G_CALLBACK (set_active_workspace_hint),
1360                            x11_display, 0);
1361 
1362   set_number_of_spaces_hint (display->workspace_manager, NULL, x11_display);
1363 
1364   g_signal_connect_object (display->workspace_manager, "notify::n-workspaces",
1365                            G_CALLBACK (set_number_of_spaces_hint),
1366                            x11_display, 0);
1367 
1368   set_showing_desktop_hint (display->workspace_manager, x11_display);
1369 
1370   g_signal_connect_object (display->workspace_manager, "showing-desktop-changed",
1371                            G_CALLBACK (set_showing_desktop_hint),
1372                            x11_display, 0);
1373 
1374   set_workspace_names (x11_display);
1375 
1376   meta_prefs_add_listener (prefs_changed_callback, x11_display);
1377 
1378   set_work_area_hint (display, x11_display);
1379 
1380   g_signal_connect_object (display, "workareas-changed",
1381                            G_CALLBACK (set_work_area_hint),
1382                            x11_display, 0);
1383 
1384   init_x11_bell (x11_display);
1385 
1386   meta_x11_startup_notification_init (x11_display);
1387   meta_x11_selection_init (x11_display);
1388 
1389   if (!meta_is_wayland_compositor ())
1390     meta_dnd_init_xdnd (x11_display);
1391 
1392   return x11_display;
1393 }
1394 
1395 void
meta_x11_display_restore_active_workspace(MetaX11Display * x11_display)1396 meta_x11_display_restore_active_workspace (MetaX11Display *x11_display)
1397 {
1398   MetaDisplay *display;
1399   MetaWorkspace *current_workspace;
1400   uint32_t current_workspace_index = 0;
1401   guint32 timestamp;
1402 
1403   g_return_if_fail (META_IS_X11_DISPLAY (x11_display));
1404 
1405   display = x11_display->display;
1406   timestamp = x11_display->timestamp;
1407 
1408   /* Get current workspace */
1409   if (meta_prop_get_cardinal (x11_display,
1410                               x11_display->xroot,
1411                               x11_display->atom__NET_CURRENT_DESKTOP,
1412                               &current_workspace_index))
1413     {
1414       meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d",
1415                     (int) current_workspace_index);
1416 
1417       /* Switch to the _NET_CURRENT_DESKTOP workspace */
1418       current_workspace = meta_workspace_manager_get_workspace_by_index (display->workspace_manager,
1419                                                                          current_workspace_index);
1420 
1421       if (current_workspace != NULL)
1422         meta_workspace_activate (current_workspace, timestamp);
1423     }
1424   else
1425     {
1426       meta_verbose ("No _NET_CURRENT_DESKTOP present");
1427     }
1428 
1429   set_active_workspace_hint (display->workspace_manager, x11_display);
1430 }
1431 
1432 int
meta_x11_display_get_screen_number(MetaX11Display * x11_display)1433 meta_x11_display_get_screen_number (MetaX11Display *x11_display)
1434 {
1435   return DefaultScreen (x11_display->xdisplay);
1436 }
1437 
1438 MetaDisplay *
meta_x11_display_get_display(MetaX11Display * x11_display)1439 meta_x11_display_get_display (MetaX11Display *x11_display)
1440 {
1441   return x11_display->display;
1442 }
1443 
1444 /**
1445  * meta_x11_display_get_xdisplay: (skip)
1446  * @x11_display: a #MetaX11Display
1447  *
1448  */
1449 Display *
meta_x11_display_get_xdisplay(MetaX11Display * x11_display)1450 meta_x11_display_get_xdisplay (MetaX11Display *x11_display)
1451 {
1452   return x11_display->xdisplay;
1453 }
1454 
1455 /**
1456  * meta_x11_display_get_xroot: (skip)
1457  * @x11_display: A #MetaX11Display
1458  *
1459  */
1460 Window
meta_x11_display_get_xroot(MetaX11Display * x11_display)1461 meta_x11_display_get_xroot (MetaX11Display *x11_display)
1462 {
1463   return x11_display->xroot;
1464 }
1465 
1466 /**
1467  * meta_x11_display_get_xinput_opcode: (skip)
1468  * @x11_display: a #MetaX11Display
1469  *
1470  */
1471 int
meta_x11_display_get_xinput_opcode(MetaX11Display * x11_display)1472 meta_x11_display_get_xinput_opcode (MetaX11Display *x11_display)
1473 {
1474   return x11_display->xinput_opcode;
1475 }
1476 
1477 int
meta_x11_display_get_damage_event_base(MetaX11Display * x11_display)1478 meta_x11_display_get_damage_event_base (MetaX11Display *x11_display)
1479 {
1480   return x11_display->damage_event_base;
1481 }
1482 
1483 int
meta_x11_display_get_shape_event_base(MetaX11Display * x11_display)1484 meta_x11_display_get_shape_event_base (MetaX11Display *x11_display)
1485 {
1486   return x11_display->shape_event_base;
1487 }
1488 
1489 gboolean
meta_x11_display_has_shape(MetaX11Display * x11_display)1490 meta_x11_display_has_shape (MetaX11Display *x11_display)
1491 {
1492   return META_X11_DISPLAY_HAS_SHAPE (x11_display);
1493 }
1494 
1495 Window
meta_x11_display_create_offscreen_window(MetaX11Display * x11_display,Window parent,long valuemask)1496 meta_x11_display_create_offscreen_window (MetaX11Display *x11_display,
1497                                           Window          parent,
1498                                           long            valuemask)
1499 {
1500   XSetWindowAttributes attrs;
1501 
1502   /* we want to be override redirect because sometimes we
1503    * create a window on a screen we aren't managing.
1504    * (but on a display we are managing at least one screen for)
1505    */
1506   attrs.override_redirect = True;
1507   attrs.event_mask = valuemask;
1508 
1509   return XCreateWindow (x11_display->xdisplay,
1510                         parent,
1511                         -100, -100, 1, 1,
1512                         0,
1513                         CopyFromParent,
1514                         CopyFromParent,
1515                         (Visual *)CopyFromParent,
1516                         CWOverrideRedirect | CWEventMask,
1517                         &attrs);
1518 }
1519 
1520 Cursor
meta_x11_display_create_x_cursor(MetaX11Display * x11_display,MetaCursor cursor)1521 meta_x11_display_create_x_cursor (MetaX11Display *x11_display,
1522                                   MetaCursor      cursor)
1523 {
1524   return meta_create_x_cursor (x11_display->xdisplay, cursor);
1525 }
1526 
1527 static char *
get_screen_name(Display * xdisplay,int number)1528 get_screen_name (Display *xdisplay,
1529                  int      number)
1530 {
1531   char *p;
1532   char *dname;
1533   char *scr;
1534 
1535   /* DisplayString gives us a sort of canonical display,
1536    * vs. the user-entered name from XDisplayName()
1537    */
1538   dname = g_strdup (DisplayString (xdisplay));
1539 
1540   /* Change display name to specify this screen.
1541    */
1542   p = strrchr (dname, ':');
1543   if (p)
1544     {
1545       p = strchr (p, '.');
1546       if (p)
1547         *p = '\0';
1548     }
1549 
1550   scr = g_strdup_printf ("%s.%d", dname, number);
1551 
1552   g_free (dname);
1553 
1554   return scr;
1555 }
1556 
1557 void
meta_x11_display_reload_cursor(MetaX11Display * x11_display)1558 meta_x11_display_reload_cursor (MetaX11Display *x11_display)
1559 {
1560   Cursor xcursor;
1561   MetaCursor cursor = x11_display->display->current_cursor;
1562 
1563   /* Set a cursor for X11 applications that don't specify their own */
1564   xcursor = meta_x11_display_create_x_cursor (x11_display, cursor);
1565 
1566   XDefineCursor (x11_display->xdisplay, x11_display->xroot, xcursor);
1567   XFlush (x11_display->xdisplay);
1568 
1569   if (xcursor)
1570     XFreeCursor (x11_display->xdisplay, xcursor);
1571 }
1572 
1573 static void
set_cursor_theme(Display * xdisplay)1574 set_cursor_theme (Display *xdisplay)
1575 {
1576   MetaBackend *backend = meta_get_backend ();
1577   MetaSettings *settings = meta_backend_get_settings (backend);
1578   int scale;
1579 
1580   scale = meta_settings_get_ui_scaling_factor (settings);
1581   XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ());
1582   XcursorSetDefaultSize (xdisplay, meta_prefs_get_cursor_size () * scale);
1583 }
1584 
1585 static void
update_cursor_theme(MetaX11Display * x11_display)1586 update_cursor_theme (MetaX11Display *x11_display)
1587 {
1588   MetaBackend *backend = meta_get_backend ();
1589 
1590   set_cursor_theme (x11_display->xdisplay);
1591   meta_x11_display_reload_cursor (x11_display);
1592 
1593   if (META_IS_BACKEND_X11 (backend))
1594     {
1595       MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend);
1596       Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11);
1597 
1598       set_cursor_theme (xdisplay);
1599       meta_backend_x11_reload_cursor (backend_x11);
1600     }
1601 }
1602 
1603 MetaWindow *
meta_x11_display_lookup_x_window(MetaX11Display * x11_display,Window xwindow)1604 meta_x11_display_lookup_x_window (MetaX11Display *x11_display,
1605                                   Window          xwindow)
1606 {
1607   return g_hash_table_lookup (x11_display->xids, &xwindow);
1608 }
1609 
1610 void
meta_x11_display_register_x_window(MetaX11Display * x11_display,Window * xwindowp,MetaWindow * window)1611 meta_x11_display_register_x_window (MetaX11Display *x11_display,
1612                                     Window         *xwindowp,
1613                                     MetaWindow     *window)
1614 {
1615   g_return_if_fail (g_hash_table_lookup (x11_display->xids, xwindowp) == NULL);
1616 
1617   g_hash_table_insert (x11_display->xids, xwindowp, window);
1618 }
1619 
1620 void
meta_x11_display_unregister_x_window(MetaX11Display * x11_display,Window xwindow)1621 meta_x11_display_unregister_x_window (MetaX11Display *x11_display,
1622                                       Window          xwindow)
1623 {
1624   g_return_if_fail (g_hash_table_lookup (x11_display->xids, &xwindow) != NULL);
1625 
1626   g_hash_table_remove (x11_display->xids, &xwindow);
1627 }
1628 
1629 
1630 /* We store sync alarms in the window ID hash table, because they are
1631  * just more types of XIDs in the same global space, but we have
1632  * typesafe functions to register/unregister for readability.
1633  */
1634 
1635 MetaWindow *
meta_x11_display_lookup_sync_alarm(MetaX11Display * x11_display,XSyncAlarm alarm)1636 meta_x11_display_lookup_sync_alarm (MetaX11Display *x11_display,
1637                                     XSyncAlarm      alarm)
1638 {
1639   return g_hash_table_lookup (x11_display->xids, &alarm);
1640 }
1641 
1642 void
meta_x11_display_register_sync_alarm(MetaX11Display * x11_display,XSyncAlarm * alarmp,MetaWindow * window)1643 meta_x11_display_register_sync_alarm (MetaX11Display *x11_display,
1644                                       XSyncAlarm     *alarmp,
1645                                       MetaWindow     *window)
1646 {
1647   g_return_if_fail (g_hash_table_lookup (x11_display->xids, alarmp) == NULL);
1648 
1649   g_hash_table_insert (x11_display->xids, alarmp, window);
1650 }
1651 
1652 void
meta_x11_display_unregister_sync_alarm(MetaX11Display * x11_display,XSyncAlarm alarm)1653 meta_x11_display_unregister_sync_alarm (MetaX11Display *x11_display,
1654                                         XSyncAlarm      alarm)
1655 {
1656   g_return_if_fail (g_hash_table_lookup (x11_display->xids, &alarm) != NULL);
1657 
1658   g_hash_table_remove (x11_display->xids, &alarm);
1659 }
1660 
1661 void
meta_x11_display_set_alarm_filter(MetaX11Display * x11_display,MetaAlarmFilter filter,gpointer data)1662 meta_x11_display_set_alarm_filter (MetaX11Display *x11_display,
1663                                    MetaAlarmFilter filter,
1664                                    gpointer        data)
1665 {
1666   g_return_if_fail (filter == NULL || x11_display->alarm_filter == NULL);
1667 
1668   x11_display->alarm_filter = filter;
1669   x11_display->alarm_filter_data = data;
1670 }
1671 
1672 /* The guard window allows us to leave minimized windows mapped so
1673  * that compositor code may provide live previews of them.
1674  * Instead of being unmapped/withdrawn, they get pushed underneath
1675  * the guard window. We also select events on the guard window, which
1676  * should effectively be forwarded to events on the background actor,
1677  * providing that the scene graph is set up correctly.
1678  */
1679 static Window
create_guard_window(MetaX11Display * x11_display)1680 create_guard_window (MetaX11Display *x11_display)
1681 {
1682   XSetWindowAttributes attributes;
1683   Window guard_window;
1684   gulong create_serial;
1685   int display_width, display_height;
1686 
1687   meta_display_get_size (x11_display->display,
1688                          &display_width,
1689                          &display_height);
1690 
1691   attributes.event_mask = NoEventMask;
1692   attributes.override_redirect = True;
1693 
1694   /* We have to call record_add() after we have the new window ID,
1695    * so save the serial for the CreateWindow request until then */
1696   create_serial = XNextRequest (x11_display->xdisplay);
1697   guard_window =
1698     XCreateWindow (x11_display->xdisplay,
1699                    x11_display->xroot,
1700                    0, /* x */
1701                    0, /* y */
1702                    display_width,
1703                    display_height,
1704                    0, /* border width */
1705                    0, /* depth */
1706                    InputOnly, /* class */
1707                    CopyFromParent, /* visual */
1708                    CWEventMask | CWOverrideRedirect,
1709                    &attributes);
1710 
1711   /* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
1712   XStoreName (x11_display->xdisplay, guard_window, "mutter guard window");
1713 
1714   {
1715     if (!meta_is_wayland_compositor ())
1716       {
1717         MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
1718         Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
1719         unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
1720         XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
1721 
1722         XISetMask (mask.mask, XI_ButtonPress);
1723         XISetMask (mask.mask, XI_ButtonRelease);
1724         XISetMask (mask.mask, XI_Motion);
1725 
1726         /* Sync on the connection we created the window on to
1727          * make sure it's created before we select on it on the
1728          * backend connection. */
1729         XSync (x11_display->xdisplay, False);
1730 
1731         XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
1732       }
1733   }
1734 
1735   meta_stack_tracker_record_add (x11_display->display->stack_tracker,
1736                                  guard_window,
1737                                  create_serial);
1738 
1739   meta_stack_tracker_lower (x11_display->display->stack_tracker,
1740                             guard_window);
1741 
1742   XMapWindow (x11_display->xdisplay, guard_window);
1743   return guard_window;
1744 }
1745 
1746 void
meta_x11_display_create_guard_window(MetaX11Display * x11_display)1747 meta_x11_display_create_guard_window (MetaX11Display *x11_display)
1748 {
1749   if (x11_display->guard_window == None)
1750     x11_display->guard_window = create_guard_window (x11_display);
1751 }
1752 
1753 static void
on_monitors_changed_internal(MetaMonitorManager * monitor_manager,MetaX11Display * x11_display)1754 on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
1755                               MetaX11Display     *x11_display)
1756 {
1757   int display_width, display_height;
1758 
1759   meta_monitor_manager_get_screen_size (monitor_manager,
1760                                         &display_width,
1761                                         &display_height);
1762 
1763   set_desktop_geometry_hint (x11_display);
1764 
1765   /* Resize the guard window to fill the screen again. */
1766   if (x11_display->guard_window != None)
1767     {
1768       XWindowChanges changes;
1769 
1770       changes.x = 0;
1771       changes.y = 0;
1772       changes.width = display_width;
1773       changes.height = display_height;
1774 
1775       XConfigureWindow (x11_display->xdisplay,
1776                         x11_display->guard_window,
1777                         CWX | CWY | CWWidth | CWHeight,
1778                         &changes);
1779     }
1780 
1781   x11_display->has_xinerama_indices = FALSE;
1782 }
1783 
1784 void
meta_x11_display_set_cm_selection(MetaX11Display * x11_display)1785 meta_x11_display_set_cm_selection (MetaX11Display *x11_display)
1786 {
1787   char selection[32];
1788   Atom a;
1789   guint32 timestamp;
1790 
1791   timestamp = meta_x11_display_get_current_time_roundtrip (x11_display);
1792   g_snprintf (selection, sizeof (selection), "_NET_WM_CM_S%d",
1793               DefaultScreen (x11_display->xdisplay));
1794   a = XInternAtom (x11_display->xdisplay, selection, False);
1795 
1796   x11_display->wm_cm_selection_window = take_manager_selection (x11_display, x11_display->xroot, a, timestamp, TRUE);
1797 }
1798 
1799 static Bool
find_timestamp_predicate(Display * xdisplay,XEvent * ev,XPointer arg)1800 find_timestamp_predicate (Display  *xdisplay,
1801                           XEvent   *ev,
1802                           XPointer  arg)
1803 {
1804   MetaX11Display *x11_display = (MetaX11Display *) arg;
1805 
1806   return (ev->type == PropertyNotify &&
1807           ev->xproperty.atom == x11_display->atom__MUTTER_TIMESTAMP_PING);
1808 }
1809 
1810 /* Get a timestamp, even if it means a roundtrip */
1811 guint32
meta_x11_display_get_current_time_roundtrip(MetaX11Display * x11_display)1812 meta_x11_display_get_current_time_roundtrip (MetaX11Display *x11_display)
1813 {
1814   guint32 timestamp;
1815 
1816   timestamp = meta_display_get_current_time (x11_display->display);
1817   if (timestamp == META_CURRENT_TIME)
1818     {
1819       XEvent property_event;
1820 
1821       XChangeProperty (x11_display->xdisplay,
1822                        x11_display->timestamp_pinging_window,
1823                        x11_display->atom__MUTTER_TIMESTAMP_PING,
1824                        XA_STRING, 8, PropModeAppend, NULL, 0);
1825       XIfEvent (x11_display->xdisplay,
1826                 &property_event,
1827                 find_timestamp_predicate,
1828                 (XPointer) x11_display);
1829       timestamp = property_event.xproperty.time;
1830     }
1831 
1832   meta_display_sanity_check_timestamps (x11_display->display, timestamp);
1833 
1834   return timestamp;
1835 }
1836 
1837 /**
1838  * meta_x11_display_xwindow_is_a_no_focus_window:
1839  * @x11_display: A #MetaX11Display
1840  * @xwindow: An X11 window
1841  *
1842  * Returns: %TRUE iff window is one of mutter's internal "no focus" windows
1843  * which will have the focus when there is no actual client window focused.
1844  */
1845 gboolean
meta_x11_display_xwindow_is_a_no_focus_window(MetaX11Display * x11_display,Window xwindow)1846 meta_x11_display_xwindow_is_a_no_focus_window (MetaX11Display *x11_display,
1847                                                Window xwindow)
1848 {
1849   return xwindow == x11_display->no_focus_window;
1850 }
1851 
1852 void
meta_x11_display_increment_event_serial(MetaX11Display * x11_display)1853 meta_x11_display_increment_event_serial (MetaX11Display *x11_display)
1854 
1855 {
1856   /* We just make some random X request */
1857   XDeleteProperty (x11_display->xdisplay,
1858                    x11_display->leader_window,
1859                    x11_display->atom__MOTIF_WM_HINTS);
1860 }
1861 
1862 static void
meta_x11_display_update_active_window_hint(MetaX11Display * x11_display)1863 meta_x11_display_update_active_window_hint (MetaX11Display *x11_display)
1864 {
1865   MetaWindow *focus_window;
1866   gulong data[1];
1867 
1868   if (x11_display->display->closing)
1869     return; /* Leave old value for a replacement */
1870 
1871   focus_window = meta_x11_display_lookup_x_window (x11_display,
1872                                                    x11_display->focus_xwindow);
1873 
1874   if (focus_window)
1875     data[0] = focus_window->xwindow;
1876   else
1877     data[0] = None;
1878 
1879   meta_x11_error_trap_push (x11_display);
1880   XChangeProperty (x11_display->xdisplay,
1881                    x11_display->xroot,
1882                    x11_display->atom__NET_ACTIVE_WINDOW,
1883                    XA_WINDOW,
1884                    32, PropModeReplace, (guchar*) data, 1);
1885   meta_x11_error_trap_pop (x11_display);
1886 }
1887 
1888 void
meta_x11_display_update_focus_window(MetaX11Display * x11_display,Window xwindow,gulong serial,gboolean focused_by_us)1889 meta_x11_display_update_focus_window (MetaX11Display *x11_display,
1890                                       Window          xwindow,
1891                                       gulong          serial,
1892                                       gboolean        focused_by_us)
1893 {
1894   x11_display->focus_serial = serial;
1895   x11_display->focused_by_us = !!focused_by_us;
1896 
1897   if (x11_display->focus_xwindow == xwindow)
1898     return;
1899 
1900   x11_display->focus_xwindow = xwindow;
1901   meta_x11_display_update_active_window_hint (x11_display);
1902 }
1903 
1904 static void
meta_x11_display_set_input_focus_internal(MetaX11Display * x11_display,Window xwindow,uint32_t timestamp)1905 meta_x11_display_set_input_focus_internal (MetaX11Display *x11_display,
1906                                            Window          xwindow,
1907                                            uint32_t        timestamp)
1908 {
1909   meta_x11_error_trap_push (x11_display);
1910 
1911   /* In order for mutter to know that the focus request succeeded, we track
1912    * the serial of the "focus request" we made, but if we take the serial
1913    * of the XSetInputFocus request, then there's no way to determine the
1914    * difference between focus events as a result of the SetInputFocus and
1915    * focus events that other clients send around the same time. Ensure that
1916    * we know which is which by making two requests that the server will
1917    * process at the same time.
1918    */
1919   XGrabServer (x11_display->xdisplay);
1920 
1921   XSetInputFocus (x11_display->xdisplay,
1922                   xwindow,
1923                   RevertToPointerRoot,
1924                   timestamp);
1925 
1926   XChangeProperty (x11_display->xdisplay,
1927                    x11_display->timestamp_pinging_window,
1928                    x11_display->atom__MUTTER_FOCUS_SET,
1929                    XA_STRING, 8, PropModeAppend, NULL, 0);
1930 
1931   XUngrabServer (x11_display->xdisplay);
1932   XFlush (x11_display->xdisplay);
1933 
1934   meta_x11_error_trap_pop (x11_display);
1935 }
1936 
1937 void
meta_x11_display_set_input_focus(MetaX11Display * x11_display,MetaWindow * window,gboolean focus_frame,uint32_t timestamp)1938 meta_x11_display_set_input_focus (MetaX11Display *x11_display,
1939                                   MetaWindow     *window,
1940                                   gboolean        focus_frame,
1941                                   uint32_t        timestamp)
1942 {
1943   Window xwindow;
1944   gulong serial;
1945 
1946   if (window)
1947     xwindow = focus_frame ? window->frame->xwindow : window->xwindow;
1948   else
1949     xwindow = x11_display->no_focus_window;
1950 
1951   meta_x11_error_trap_push (x11_display);
1952   meta_x11_display_set_input_focus_internal (x11_display, xwindow, timestamp);
1953   serial = XNextRequest (x11_display->xdisplay);
1954   meta_x11_display_update_focus_window (x11_display, xwindow, serial, TRUE);
1955   meta_x11_error_trap_pop (x11_display);
1956 }
1957 
1958 void
meta_x11_display_set_input_focus_xwindow(MetaX11Display * x11_display,Window window,guint32 timestamp)1959 meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display,
1960                                           Window          window,
1961                                           guint32         timestamp)
1962 {
1963   gulong serial;
1964 
1965   if (meta_display_timestamp_too_old (x11_display->display, &timestamp))
1966     return;
1967 
1968   meta_x11_display_set_input_focus_internal (x11_display, window, timestamp);
1969   serial = XNextRequest (x11_display->xdisplay);
1970   meta_x11_display_update_focus_window (x11_display, window, serial, TRUE);
1971   meta_display_update_focus_window (x11_display->display, NULL);
1972   meta_display_remove_autoraise_callback (x11_display->display);
1973   x11_display->display->last_focus_time = timestamp;
1974 }
1975 
1976 static MetaX11DisplayLogicalMonitorData *
get_x11_display_logical_monitor_data(MetaLogicalMonitor * logical_monitor)1977 get_x11_display_logical_monitor_data (MetaLogicalMonitor *logical_monitor)
1978 {
1979   return g_object_get_qdata (G_OBJECT (logical_monitor),
1980                              quark_x11_display_logical_monitor_data);
1981 }
1982 
1983 static MetaX11DisplayLogicalMonitorData *
ensure_x11_display_logical_monitor_data(MetaLogicalMonitor * logical_monitor)1984 ensure_x11_display_logical_monitor_data (MetaLogicalMonitor *logical_monitor)
1985 {
1986   MetaX11DisplayLogicalMonitorData *data;
1987 
1988   data = get_x11_display_logical_monitor_data (logical_monitor);
1989   if (data)
1990     return data;
1991 
1992   data = g_new0 (MetaX11DisplayLogicalMonitorData, 1);
1993   g_object_set_qdata_full (G_OBJECT (logical_monitor),
1994                            quark_x11_display_logical_monitor_data,
1995                            data,
1996                            g_free);
1997 
1998   return data;
1999 }
2000 
2001 static void
meta_x11_display_ensure_xinerama_indices(MetaX11Display * x11_display)2002 meta_x11_display_ensure_xinerama_indices (MetaX11Display *x11_display)
2003 {
2004   MetaBackend *backend = meta_get_backend ();
2005   MetaMonitorManager *monitor_manager =
2006     meta_backend_get_monitor_manager (backend);
2007   GList *logical_monitors, *l;
2008   XineramaScreenInfo *infos;
2009   int n_infos, j;
2010 
2011   if (x11_display->has_xinerama_indices)
2012     return;
2013 
2014   x11_display->has_xinerama_indices = TRUE;
2015 
2016   if (!XineramaIsActive (x11_display->xdisplay))
2017     return;
2018 
2019   infos = XineramaQueryScreens (x11_display->xdisplay,
2020                                 &n_infos);
2021   if (n_infos <= 0 || infos == NULL)
2022     {
2023       meta_XFree (infos);
2024       return;
2025     }
2026 
2027   logical_monitors =
2028     meta_monitor_manager_get_logical_monitors (monitor_manager);
2029 
2030   for (l = logical_monitors; l; l = l->next)
2031     {
2032       MetaLogicalMonitor *logical_monitor = l->data;
2033 
2034       for (j = 0; j < n_infos; ++j)
2035         {
2036           if (logical_monitor->rect.x == infos[j].x_org &&
2037               logical_monitor->rect.y == infos[j].y_org &&
2038               logical_monitor->rect.width == infos[j].width &&
2039               logical_monitor->rect.height == infos[j].height)
2040             {
2041               MetaX11DisplayLogicalMonitorData *logical_monitor_data;
2042 
2043               logical_monitor_data =
2044                 ensure_x11_display_logical_monitor_data (logical_monitor);
2045               logical_monitor_data->xinerama_index = j;
2046             }
2047         }
2048     }
2049 
2050   meta_XFree (infos);
2051 }
2052 
2053 int
meta_x11_display_logical_monitor_to_xinerama_index(MetaX11Display * x11_display,MetaLogicalMonitor * logical_monitor)2054 meta_x11_display_logical_monitor_to_xinerama_index (MetaX11Display     *x11_display,
2055                                                     MetaLogicalMonitor *logical_monitor)
2056 {
2057   MetaX11DisplayLogicalMonitorData *logical_monitor_data;
2058 
2059   g_return_val_if_fail (logical_monitor, -1);
2060 
2061   meta_x11_display_ensure_xinerama_indices (x11_display);
2062 
2063   logical_monitor_data = get_x11_display_logical_monitor_data (logical_monitor);
2064 
2065   return logical_monitor_data->xinerama_index;
2066 }
2067 
2068 MetaLogicalMonitor *
meta_x11_display_xinerama_index_to_logical_monitor(MetaX11Display * x11_display,int xinerama_index)2069 meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display,
2070                                                     int             xinerama_index)
2071 {
2072   MetaBackend *backend = meta_get_backend ();
2073   MetaMonitorManager *monitor_manager =
2074     meta_backend_get_monitor_manager (backend);
2075   GList *logical_monitors, *l;
2076 
2077   meta_x11_display_ensure_xinerama_indices (x11_display);
2078 
2079   logical_monitors =
2080     meta_monitor_manager_get_logical_monitors (monitor_manager);
2081 
2082   for (l = logical_monitors; l; l = l->next)
2083     {
2084       MetaLogicalMonitor *logical_monitor = l->data;
2085       MetaX11DisplayLogicalMonitorData *logical_monitor_data;
2086 
2087       logical_monitor_data =
2088         ensure_x11_display_logical_monitor_data (logical_monitor);
2089 
2090       if (logical_monitor_data->xinerama_index == xinerama_index)
2091         return logical_monitor;
2092     }
2093 
2094   return NULL;
2095 }
2096 
2097 void
meta_x11_display_update_workspace_names(MetaX11Display * x11_display)2098 meta_x11_display_update_workspace_names (MetaX11Display *x11_display)
2099 {
2100   char **names;
2101   int n_names;
2102   int i;
2103 
2104   /* this updates names in prefs when the root window property changes,
2105    * iff the new property contents don't match what's already in prefs
2106    */
2107 
2108   names = NULL;
2109   n_names = 0;
2110   if (!meta_prop_get_utf8_list (x11_display,
2111                                 x11_display->xroot,
2112                                 x11_display->atom__NET_DESKTOP_NAMES,
2113                                 &names, &n_names))
2114     {
2115       meta_verbose ("Failed to get workspace names from root window");
2116       return;
2117     }
2118 
2119   i = 0;
2120   while (i < n_names)
2121     {
2122       meta_topic (META_DEBUG_PREFS,
2123                   "Setting workspace %d name to \"%s\" due to _NET_DESKTOP_NAMES change",
2124                   i, names[i] ? names[i] : "null");
2125       meta_prefs_change_workspace_name (i, names[i]);
2126 
2127       ++i;
2128     }
2129 
2130   g_strfreev (names);
2131 }
2132 
2133 #define _NET_WM_ORIENTATION_HORZ 0
2134 #define _NET_WM_ORIENTATION_VERT 1
2135 
2136 #define _NET_WM_TOPLEFT     0
2137 #define _NET_WM_TOPRIGHT    1
2138 #define _NET_WM_BOTTOMRIGHT 2
2139 #define _NET_WM_BOTTOMLEFT  3
2140 
2141 void
meta_x11_display_update_workspace_layout(MetaX11Display * x11_display)2142 meta_x11_display_update_workspace_layout (MetaX11Display *x11_display)
2143 {
2144   MetaWorkspaceManager *workspace_manager = x11_display->display->workspace_manager;
2145   gboolean vertical_layout = FALSE;
2146   int n_rows = 1;
2147   int n_columns = -1;
2148   MetaDisplayCorner starting_corner = META_DISPLAY_TOPLEFT;
2149   uint32_t *list;
2150   int n_items;
2151 
2152   if (workspace_manager->workspace_layout_overridden)
2153     return;
2154 
2155   list = NULL;
2156   n_items = 0;
2157 
2158   if (meta_prop_get_cardinal_list (x11_display,
2159                                    x11_display->xroot,
2160                                    x11_display->atom__NET_DESKTOP_LAYOUT,
2161                                    &list, &n_items))
2162     {
2163       if (n_items == 3 || n_items == 4)
2164         {
2165           int cols, rows;
2166 
2167           switch (list[0])
2168             {
2169             case _NET_WM_ORIENTATION_HORZ:
2170               vertical_layout = FALSE;
2171               break;
2172             case _NET_WM_ORIENTATION_VERT:
2173               vertical_layout = TRUE;
2174               break;
2175             default:
2176               meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT");
2177               break;
2178             }
2179 
2180           cols = list[1];
2181           rows = list[2];
2182 
2183           if (rows <= 0 && cols <= 0)
2184             {
2185               meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense", rows, cols);
2186             }
2187           else
2188             {
2189               if (rows > 0)
2190                 n_rows = rows;
2191               else
2192                 n_rows = -1;
2193 
2194               if (cols > 0)
2195                 n_columns = cols;
2196               else
2197                 n_columns = -1;
2198             }
2199 
2200           if (n_items == 4)
2201             {
2202               switch (list[3])
2203                 {
2204                 case _NET_WM_TOPLEFT:
2205                   starting_corner = META_DISPLAY_TOPLEFT;
2206                   break;
2207                 case _NET_WM_TOPRIGHT:
2208                   starting_corner = META_DISPLAY_TOPRIGHT;
2209                   break;
2210                 case _NET_WM_BOTTOMRIGHT:
2211                   starting_corner = META_DISPLAY_BOTTOMRIGHT;
2212                   break;
2213                 case _NET_WM_BOTTOMLEFT:
2214                   starting_corner = META_DISPLAY_BOTTOMLEFT;
2215                   break;
2216                 default:
2217                   meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT");
2218                   break;
2219                 }
2220             }
2221         }
2222       else
2223         {
2224           meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 "
2225                         "(3 is accepted for backwards compat)", n_items);
2226         }
2227 
2228       g_free (list);
2229 
2230       meta_workspace_manager_update_workspace_layout (workspace_manager,
2231                                                       starting_corner,
2232                                                       vertical_layout,
2233                                                       n_rows,
2234                                                       n_columns);
2235     }
2236 }
2237 
2238 static void
prefs_changed_callback(MetaPreference pref,void * data)2239 prefs_changed_callback (MetaPreference pref,
2240                         void          *data)
2241 {
2242   MetaX11Display *x11_display = data;
2243 
2244   if (pref == META_PREF_WORKSPACE_NAMES)
2245     {
2246       set_workspace_names (x11_display);
2247     }
2248 }
2249 
2250 void
meta_x11_display_increment_focus_sentinel(MetaX11Display * x11_display)2251 meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display)
2252 {
2253   unsigned long data[1];
2254 
2255   data[0] = meta_display_get_current_time (x11_display->display);
2256 
2257   XChangeProperty (x11_display->xdisplay,
2258                    x11_display->xroot,
2259                    x11_display->atom__MUTTER_SENTINEL,
2260                    XA_CARDINAL,
2261                    32, PropModeReplace, (guchar*) data, 1);
2262 
2263   x11_display->sentinel_counter += 1;
2264 }
2265 
2266 void
meta_x11_display_decrement_focus_sentinel(MetaX11Display * x11_display)2267 meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display)
2268 {
2269   x11_display->sentinel_counter -= 1;
2270 
2271   if (x11_display->sentinel_counter < 0)
2272     x11_display->sentinel_counter = 0;
2273 }
2274 
2275 gboolean
meta_x11_display_focus_sentinel_clear(MetaX11Display * x11_display)2276 meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display)
2277 {
2278   return (x11_display->sentinel_counter == 0);
2279 }
2280 
2281 void
meta_x11_display_set_stage_input_region(MetaX11Display * x11_display,XserverRegion region)2282 meta_x11_display_set_stage_input_region (MetaX11Display *x11_display,
2283                                          XserverRegion   region)
2284 {
2285   Display *xdisplay = x11_display->xdisplay;
2286   MetaBackend *backend = meta_get_backend ();
2287   ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
2288   Window stage_xwindow;
2289 
2290   g_return_if_fail (!meta_is_wayland_compositor ());
2291 
2292   stage_xwindow = meta_x11_get_stage_window (stage);
2293   XFixesSetWindowShapeRegion (xdisplay, stage_xwindow,
2294                               ShapeInput, 0, 0, region);
2295 
2296   /*
2297    * It's generally a good heuristic that when a crossing event is generated
2298    * because we reshape the overlay, we don't want it to affect
2299    * focus-follows-mouse focus - it's not the user doing something, it's the
2300    * environment changing under the user.
2301    */
2302   meta_display_add_ignored_crossing_serial (x11_display->display,
2303                                             XNextRequest (xdisplay));
2304   XFixesSetWindowShapeRegion (xdisplay,
2305                               x11_display->composite_overlay_window,
2306                               ShapeInput, 0, 0, region);
2307 }
2308 
2309 void
meta_x11_display_clear_stage_input_region(MetaX11Display * x11_display)2310 meta_x11_display_clear_stage_input_region (MetaX11Display *x11_display)
2311 {
2312   if (x11_display->empty_region == None)
2313     {
2314       x11_display->empty_region = XFixesCreateRegion (x11_display->xdisplay,
2315                                                       NULL, 0);
2316     }
2317 
2318   meta_x11_display_set_stage_input_region (x11_display,
2319                                            x11_display->empty_region);
2320 }
2321