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, ×tamp);
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 ¤t_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, ×tamp))
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