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:display
25 * @title: MetaDisplay
26 * @short_description: Mutter display representation
27 *
28 * The display is represented as a #MetaDisplay struct.
29 */
30
31 #include "config.h"
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <X11/Xatom.h>
37 #include <X11/Xcursor/Xcursor.h>
38 #include <X11/extensions/shape.h>
39 #include <X11/extensions/Xcomposite.h>
40 #include <X11/extensions/Xdamage.h>
41 #include <X11/extensions/Xfixes.h>
42
43 #include "backends/meta-backend-private.h"
44 #include "backends/meta-cursor-sprite-xcursor.h"
45 #include "backends/meta-cursor-tracker-private.h"
46 #include "backends/meta-input-device-private.h"
47 #include "backends/meta-input-mapper-private.h"
48 #include "backends/meta-stage-private.h"
49 #include "backends/x11/meta-backend-x11.h"
50 #include "backends/x11/meta-clutter-backend-x11.h"
51 #include "backends/x11/meta-event-x11.h"
52 #include "backends/x11/cm/meta-backend-x11-cm.h"
53 #include "backends/x11/nested/meta-backend-x11-nested.h"
54 #include "compositor/compositor-private.h"
55 #include "compositor/meta-compositor-x11.h"
56 #include "cogl/cogl.h"
57 #include "core/bell.h"
58 #include "core/boxes-private.h"
59 #include "core/display-private.h"
60 #include "core/events.h"
61 #include "core/frame.h"
62 #include "core/keybindings-private.h"
63 #include "core/meta-clipboard-manager.h"
64 #include "core/meta-workspace-manager-private.h"
65 #include "core/util-private.h"
66 #include "core/window-private.h"
67 #include "core/workspace-private.h"
68 #include "meta/compositor-mutter.h"
69 #include "meta/compositor.h"
70 #include "meta/main.h"
71 #include "meta/meta-backend.h"
72 #include "meta/meta-enum-types.h"
73 #include "meta/meta-sound-player.h"
74 #include "meta/meta-x11-errors.h"
75 #include "meta/prefs.h"
76 #include "x11/meta-startup-notification-x11.h"
77 #include "x11/meta-x11-display-private.h"
78 #include "x11/window-x11.h"
79 #include "x11/xprops.h"
80
81 #ifdef HAVE_WAYLAND
82 #include "compositor/meta-compositor-native.h"
83 #include "compositor/meta-compositor-server.h"
84 #include "wayland/meta-xwayland-private.h"
85 #include "wayland/meta-wayland-tablet-seat.h"
86 #include "wayland/meta-wayland-tablet-pad.h"
87 #endif
88
89 #ifdef HAVE_NATIVE_BACKEND
90 #include "backends/native/meta-backend-native.h"
91 #endif
92
93 /*
94 * SECTION:pings
95 *
96 * Sometimes we want to see whether a window is responding,
97 * so we send it a "ping" message and see whether it sends us back a "pong"
98 * message within a reasonable time. Here we have a system which lets us
99 * nominate one function to be called if we get the pong in time and another
100 * function if we don't. The system is rather more complicated than it needs
101 * to be, since we only ever use it to destroy windows which are asked to
102 * close themselves and don't do so within a reasonable amount of time, and
103 * therefore we always use the same callbacks. It's possible that we might
104 * use it for other things in future, or on the other hand we might decide
105 * that we're never going to do so and simplify it a bit.
106 */
107
108 /**
109 * MetaPingData:
110 *
111 * Describes a ping on a window. When we send a ping to a window, we build
112 * one of these structs, and it eventually gets passed to the timeout function
113 * or to the function which handles the response from the window. If the window
114 * does or doesn't respond to the ping, we use this information to deal with
115 * these facts; we have a handler function for each.
116 */
117 typedef struct
118 {
119 MetaWindow *window;
120 guint32 serial;
121 guint ping_timeout_id;
122 } MetaPingData;
123
124 typedef struct _MetaDisplayPrivate
125 {
126 MetaContext *context;
127 } MetaDisplayPrivate;
128
129 G_DEFINE_TYPE_WITH_PRIVATE (MetaDisplay, meta_display, G_TYPE_OBJECT)
130
131 /* Signals */
132 enum
133 {
134 CURSOR_UPDATED,
135 X11_DISPLAY_SETUP,
136 X11_DISPLAY_OPENED,
137 X11_DISPLAY_CLOSING,
138 OVERLAY_KEY,
139 ACCELERATOR_ACTIVATED,
140 MODIFIERS_ACCELERATOR_ACTIVATED,
141 FOCUS_WINDOW,
142 WINDOW_CREATED,
143 WINDOW_DEMANDS_ATTENTION,
144 WINDOW_MARKED_URGENT,
145 GRAB_OP_BEGIN,
146 GRAB_OP_END,
147 SHOW_RESTART_MESSAGE,
148 RESTART,
149 SHOW_RESIZE_POPUP,
150 GL_VIDEO_MEMORY_PURGED,
151 SHOW_PAD_OSD,
152 SHOW_OSD,
153 PAD_MODE_SWITCH,
154 WINDOW_ENTERED_MONITOR,
155 WINDOW_LEFT_MONITOR,
156 WORKSPACE_ADDED,
157 WORKSPACE_REMOVED,
158 WORKSPACE_SWITCHED,
159 ACTIVE_WORKSPACE_CHANGED,
160 IN_FULLSCREEN_CHANGED,
161 SHOWING_DESKTOP_CHANGED,
162 RESTACKED,
163 WORKAREAS_CHANGED,
164 CLOSING,
165 INIT_XSERVER,
166 LAST_SIGNAL
167 };
168
169 enum
170 {
171 PROP_0,
172
173 PROP_COMPOSITOR_MODIFIERS,
174 PROP_FOCUS_WINDOW
175 };
176
177 static guint display_signals [LAST_SIGNAL] = { 0 };
178
179 #define META_GRAB_OP_GET_BASE_TYPE(op) (op & 0x00FF)
180
181 /*
182 * The display we're managing. This is a singleton object. (Historically,
183 * this was a list of displays, but there was never any way to add more
184 * than one element to it.) The goofy name is because we don't want it
185 * to shadow the parameter in its object methods.
186 */
187 static MetaDisplay *the_display = NULL;
188
189 static void on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
190 MetaDisplay *display);
191
192 static void prefs_changed_callback (MetaPreference pref,
193 void *data);
194
195 static int mru_cmp (gconstpointer a,
196 gconstpointer b);
197
198 static void
meta_display_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)199 meta_display_get_property(GObject *object,
200 guint prop_id,
201 GValue *value,
202 GParamSpec *pspec)
203 {
204 MetaDisplay *display = META_DISPLAY (object);
205
206 switch (prop_id)
207 {
208 case PROP_COMPOSITOR_MODIFIERS:
209 g_value_set_flags (value, meta_display_get_compositor_modifiers (display));
210 break;
211 case PROP_FOCUS_WINDOW:
212 g_value_set_object (value, display->focus_window);
213 break;
214 default:
215 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
216 break;
217 }
218 }
219
220 static void
meta_display_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)221 meta_display_set_property(GObject *object,
222 guint prop_id,
223 const GValue *value,
224 GParamSpec *pspec)
225 {
226 switch (prop_id)
227 {
228 default:
229 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
230 break;
231 }
232 }
233
234 static void
meta_display_class_init(MetaDisplayClass * klass)235 meta_display_class_init (MetaDisplayClass *klass)
236 {
237 GObjectClass *object_class = G_OBJECT_CLASS (klass);
238
239 object_class->get_property = meta_display_get_property;
240 object_class->set_property = meta_display_set_property;
241
242 display_signals[CURSOR_UPDATED] =
243 g_signal_new ("cursor-updated",
244 G_TYPE_FROM_CLASS (klass),
245 G_SIGNAL_RUN_LAST,
246 0,
247 NULL, NULL, NULL,
248 G_TYPE_NONE, 0);
249
250 display_signals[X11_DISPLAY_SETUP] =
251 g_signal_new ("x11-display-setup",
252 G_TYPE_FROM_CLASS (klass),
253 G_SIGNAL_RUN_LAST,
254 0,
255 NULL, NULL, NULL,
256 G_TYPE_NONE, 0);
257
258 display_signals[X11_DISPLAY_OPENED] =
259 g_signal_new ("x11-display-opened",
260 G_TYPE_FROM_CLASS (klass),
261 G_SIGNAL_RUN_LAST,
262 0,
263 NULL, NULL, NULL,
264 G_TYPE_NONE, 0);
265
266 display_signals[X11_DISPLAY_CLOSING] =
267 g_signal_new ("x11-display-closing",
268 G_TYPE_FROM_CLASS (klass),
269 G_SIGNAL_RUN_LAST,
270 0,
271 NULL, NULL, NULL,
272 G_TYPE_NONE, 0);
273
274 display_signals[OVERLAY_KEY] =
275 g_signal_new ("overlay-key",
276 G_TYPE_FROM_CLASS (klass),
277 G_SIGNAL_RUN_LAST,
278 0,
279 NULL, NULL, NULL,
280 G_TYPE_NONE, 0);
281
282 display_signals[ACCELERATOR_ACTIVATED] =
283 g_signal_new ("accelerator-activated",
284 G_TYPE_FROM_CLASS (klass),
285 G_SIGNAL_RUN_LAST,
286 0,
287 NULL, NULL, NULL,
288 G_TYPE_NONE, 3, G_TYPE_UINT, CLUTTER_TYPE_INPUT_DEVICE, G_TYPE_UINT);
289
290 /**
291 * MetaDisplay::modifiers-accelerator-activated:
292 * @display: the #MetaDisplay instance
293 *
294 * The ::modifiers-accelerator-activated signal will be emitted when
295 * a special modifiers-only keybinding is activated.
296 *
297 * Returns: %TRUE means that the keyboard device should remain
298 * frozen and %FALSE for the default behavior of unfreezing the
299 * keyboard.
300 */
301 display_signals[MODIFIERS_ACCELERATOR_ACTIVATED] =
302 g_signal_new ("modifiers-accelerator-activated",
303 G_TYPE_FROM_CLASS (klass),
304 G_SIGNAL_RUN_LAST,
305 0,
306 g_signal_accumulator_first_wins, NULL, NULL,
307 G_TYPE_BOOLEAN, 0);
308
309 display_signals[WINDOW_CREATED] =
310 g_signal_new ("window-created",
311 G_TYPE_FROM_CLASS (klass),
312 G_SIGNAL_RUN_LAST,
313 0,
314 NULL, NULL, NULL,
315 G_TYPE_NONE, 1, META_TYPE_WINDOW);
316
317 display_signals[WINDOW_DEMANDS_ATTENTION] =
318 g_signal_new ("window-demands-attention",
319 G_TYPE_FROM_CLASS (klass),
320 G_SIGNAL_RUN_LAST,
321 0,
322 NULL, NULL, NULL,
323 G_TYPE_NONE, 1, META_TYPE_WINDOW);
324
325 display_signals[WINDOW_MARKED_URGENT] =
326 g_signal_new ("window-marked-urgent",
327 G_TYPE_FROM_CLASS (klass),
328 G_SIGNAL_RUN_LAST,
329 0,
330 NULL, NULL, NULL,
331 G_TYPE_NONE, 1,
332 META_TYPE_WINDOW);
333
334 display_signals[GRAB_OP_BEGIN] =
335 g_signal_new ("grab-op-begin",
336 G_TYPE_FROM_CLASS (klass),
337 G_SIGNAL_RUN_LAST,
338 0,
339 NULL, NULL, NULL,
340 G_TYPE_NONE, 2,
341 META_TYPE_WINDOW,
342 META_TYPE_GRAB_OP);
343
344 display_signals[GRAB_OP_END] =
345 g_signal_new ("grab-op-end",
346 G_TYPE_FROM_CLASS (klass),
347 G_SIGNAL_RUN_LAST,
348 0,
349 NULL, NULL, NULL,
350 G_TYPE_NONE, 2,
351 META_TYPE_WINDOW,
352 META_TYPE_GRAB_OP);
353
354 /**
355 * MetaDisplay::show-restart-message:
356 * @display: the #MetaDisplay instance
357 * @message: (allow-none): The message to display, or %NULL
358 * to clear a previous restart message.
359 *
360 * The ::show-restart-message signal will be emitted to indicate
361 * that the compositor should show a message during restart. This is
362 * emitted when meta_restart() is called, either by Mutter
363 * internally or by the embedding compositor. The message should be
364 * immediately added to the Clutter stage in its final form -
365 * ::restart will be emitted to exit the application and leave the
366 * stage contents frozen as soon as the the stage is painted again.
367 *
368 * On case of failure to restart, this signal will be emitted again
369 * with %NULL for @message.
370 *
371 * Returns: %TRUE means the message was added to the stage; %FALSE
372 * indicates that the compositor did not show the message.
373 */
374 display_signals[SHOW_RESTART_MESSAGE] =
375 g_signal_new ("show-restart-message",
376 G_TYPE_FROM_CLASS (klass),
377 G_SIGNAL_RUN_LAST,
378 0,
379 g_signal_accumulator_true_handled,
380 NULL, NULL,
381 G_TYPE_BOOLEAN, 1,
382 G_TYPE_STRING);
383
384 /**
385 * MetaDisplay::restart:
386 * @display: the #MetaDisplay instance
387 *
388 * The ::restart signal is emitted to indicate that compositor
389 * should reexec the process. This is
390 * emitted when meta_restart() is called, either by Mutter
391 * internally or by the embedding compositor. See also
392 * ::show-restart-message.
393 *
394 * Returns: %FALSE to indicate that the compositor could not
395 * be restarted. When the compositor is restarted, the signal
396 * should not return.
397 */
398 display_signals[RESTART] =
399 g_signal_new ("restart",
400 G_TYPE_FROM_CLASS (klass),
401 G_SIGNAL_RUN_LAST,
402 0,
403 g_signal_accumulator_true_handled,
404 NULL, NULL,
405 G_TYPE_BOOLEAN, 0);
406
407 display_signals[SHOW_RESIZE_POPUP] =
408 g_signal_new ("show-resize-popup",
409 G_TYPE_FROM_CLASS (klass),
410 G_SIGNAL_RUN_LAST,
411 0,
412 g_signal_accumulator_true_handled,
413 NULL, NULL,
414 G_TYPE_BOOLEAN, 4,
415 G_TYPE_BOOLEAN, META_TYPE_RECTANGLE, G_TYPE_INT, G_TYPE_INT);
416
417 display_signals[GL_VIDEO_MEMORY_PURGED] =
418 g_signal_new ("gl-video-memory-purged",
419 G_TYPE_FROM_CLASS (klass),
420 G_SIGNAL_RUN_LAST,
421 0,
422 NULL, NULL, NULL,
423 G_TYPE_NONE, 0);
424
425 /**
426 * MetaDisplay::show-pad-osd:
427 * @display: the #MetaDisplay instance
428 * @pad: the pad device
429 * @settings: the pad device settings
430 * @layout_path: path to the layout image
431 * @edition_mode: Whether the OSD should be shown in edition mode
432 * @monitor_idx: Monitor to show the OSD on
433 *
434 * Requests the pad button mapping OSD to be shown.
435 *
436 * Returns: (transfer none) (nullable): The OSD actor
437 */
438 display_signals[SHOW_PAD_OSD] =
439 g_signal_new ("show-pad-osd",
440 G_TYPE_FROM_CLASS (klass),
441 G_SIGNAL_RUN_LAST,
442 0, NULL, NULL, NULL,
443 CLUTTER_TYPE_ACTOR, 5, CLUTTER_TYPE_INPUT_DEVICE,
444 G_TYPE_SETTINGS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT);
445
446 display_signals[SHOW_OSD] =
447 g_signal_new ("show-osd",
448 G_TYPE_FROM_CLASS (klass),
449 G_SIGNAL_RUN_LAST,
450 0, NULL, NULL, NULL,
451 G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING);
452
453 display_signals[PAD_MODE_SWITCH] =
454 g_signal_new ("pad-mode-switch",
455 G_TYPE_FROM_CLASS (klass),
456 G_SIGNAL_RUN_LAST,
457 0, NULL, NULL, NULL,
458 G_TYPE_NONE, 3, CLUTTER_TYPE_INPUT_DEVICE,
459 G_TYPE_UINT, G_TYPE_UINT);
460
461 display_signals[WINDOW_ENTERED_MONITOR] =
462 g_signal_new ("window-entered-monitor",
463 G_TYPE_FROM_CLASS (klass),
464 G_SIGNAL_RUN_LAST,
465 0, NULL, NULL, NULL,
466 G_TYPE_NONE, 2,
467 G_TYPE_INT,
468 META_TYPE_WINDOW);
469
470 display_signals[WINDOW_LEFT_MONITOR] =
471 g_signal_new ("window-left-monitor",
472 G_TYPE_FROM_CLASS (klass),
473 G_SIGNAL_RUN_LAST,
474 0, NULL, NULL, NULL,
475 G_TYPE_NONE, 2,
476 G_TYPE_INT,
477 META_TYPE_WINDOW);
478
479 display_signals[IN_FULLSCREEN_CHANGED] =
480 g_signal_new ("in-fullscreen-changed",
481 G_TYPE_FROM_CLASS (klass),
482 G_SIGNAL_RUN_LAST,
483 0, NULL, NULL, NULL,
484 G_TYPE_NONE, 0);
485
486 display_signals[SHOWING_DESKTOP_CHANGED] =
487 g_signal_new ("showing-desktop-changed",
488 G_TYPE_FROM_CLASS (klass),
489 G_SIGNAL_RUN_LAST,
490 0,
491 NULL, NULL, NULL,
492 G_TYPE_NONE, 0);
493
494 display_signals[RESTACKED] =
495 g_signal_new ("restacked",
496 G_TYPE_FROM_CLASS (klass),
497 G_SIGNAL_RUN_LAST,
498 0, NULL, NULL, NULL,
499 G_TYPE_NONE, 0);
500
501 display_signals[WORKAREAS_CHANGED] =
502 g_signal_new ("workareas-changed",
503 G_TYPE_FROM_CLASS (klass),
504 G_SIGNAL_RUN_LAST,
505 0, NULL, NULL, NULL,
506 G_TYPE_NONE, 0);
507 display_signals[CLOSING] =
508 g_signal_new ("closing",
509 G_TYPE_FROM_CLASS (klass),
510 G_SIGNAL_RUN_LAST,
511 0, NULL, NULL, NULL,
512 G_TYPE_NONE, 0);
513
514 display_signals[INIT_XSERVER] =
515 g_signal_new ("init-xserver",
516 G_TYPE_FROM_CLASS (klass),
517 G_SIGNAL_RUN_LAST,
518 0, g_signal_accumulator_first_wins,
519 NULL, NULL,
520 G_TYPE_BOOLEAN, 1, G_TYPE_TASK);
521
522 g_object_class_install_property (object_class,
523 PROP_COMPOSITOR_MODIFIERS,
524 g_param_spec_flags ("compositor-modifiers",
525 "Compositor modifiers",
526 "Modifiers reserved for compositor actions",
527 CLUTTER_TYPE_MODIFIER_TYPE,
528 0,
529 G_PARAM_READABLE));
530
531 g_object_class_install_property (object_class,
532 PROP_FOCUS_WINDOW,
533 g_param_spec_object ("focus-window",
534 "Focus window",
535 "Currently focused window",
536 META_TYPE_WINDOW,
537 G_PARAM_READABLE));
538
539 }
540
541
542 /**
543 * ping_data_free:
544 *
545 * Destructor for #MetaPingData structs. Will destroy the
546 * event source for the struct as well.
547 */
548 static void
ping_data_free(MetaPingData * ping_data)549 ping_data_free (MetaPingData *ping_data)
550 {
551 /* Remove the timeout */
552 g_clear_handle_id (&ping_data->ping_timeout_id, g_source_remove);
553
554 g_free (ping_data);
555 }
556
557 void
meta_display_remove_pending_pings_for_window(MetaDisplay * display,MetaWindow * window)558 meta_display_remove_pending_pings_for_window (MetaDisplay *display,
559 MetaWindow *window)
560 {
561 GSList *tmp;
562 GSList *dead;
563
564 /* could obviously be more efficient, don't care */
565
566 /* build list to be removed */
567 dead = NULL;
568 for (tmp = display->pending_pings; tmp; tmp = tmp->next)
569 {
570 MetaPingData *ping_data = tmp->data;
571
572 if (ping_data->window == window)
573 dead = g_slist_prepend (dead, ping_data);
574 }
575
576 /* remove what we found */
577 for (tmp = dead; tmp; tmp = tmp->next)
578 {
579 MetaPingData *ping_data = tmp->data;
580
581 display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
582 ping_data_free (ping_data);
583 }
584
585 g_slist_free (dead);
586 }
587
588 static MetaCompositor *
create_compositor(MetaDisplay * display)589 create_compositor (MetaDisplay *display)
590 {
591 MetaBackend *backend = meta_get_backend ();
592
593 #ifdef HAVE_WAYLAND
594 #ifdef HAVE_NATIVE_BACKEND
595 if (META_IS_BACKEND_NATIVE (backend))
596 return META_COMPOSITOR (meta_compositor_native_new (display, backend));
597 #endif
598 if (META_IS_BACKEND_X11_NESTED (backend))
599 return META_COMPOSITOR (meta_compositor_server_new (display, backend));
600 #endif
601 return META_COMPOSITOR (meta_compositor_x11_new (display, backend));
602 }
603
604 static void
meta_display_init(MetaDisplay * disp)605 meta_display_init (MetaDisplay *disp)
606 {
607 /* Some stuff could go in here that's currently in _open,
608 * but it doesn't really matter. */
609 }
610
611 void
meta_display_cancel_touch(MetaDisplay * display)612 meta_display_cancel_touch (MetaDisplay *display)
613 {
614 #ifdef HAVE_WAYLAND
615 MetaWaylandCompositor *compositor;
616
617 if (!meta_is_wayland_compositor ())
618 return;
619
620 compositor = meta_wayland_compositor_get_default ();
621 meta_wayland_touch_cancel (compositor->seat->touch);
622 #endif
623 }
624
625 static void
gesture_tracker_state_changed(MetaGestureTracker * tracker,ClutterEventSequence * sequence,MetaSequenceState state,MetaDisplay * display)626 gesture_tracker_state_changed (MetaGestureTracker *tracker,
627 ClutterEventSequence *sequence,
628 MetaSequenceState state,
629 MetaDisplay *display)
630 {
631 switch (state)
632 {
633 case META_SEQUENCE_NONE:
634 case META_SEQUENCE_PENDING_END:
635 return;
636 case META_SEQUENCE_ACCEPTED:
637 meta_display_cancel_touch (display);
638
639 G_GNUC_FALLTHROUGH;
640 case META_SEQUENCE_REJECTED:
641 {
642 MetaBackend *backend;
643
644 backend = meta_get_backend ();
645 meta_backend_finish_touch_sequence (backend, sequence, state);
646 break;
647 }
648 }
649 }
650
651 static void
on_ui_scaling_factor_changed(MetaSettings * settings,MetaDisplay * display)652 on_ui_scaling_factor_changed (MetaSettings *settings,
653 MetaDisplay *display)
654 {
655 meta_display_reload_cursor (display);
656 }
657
658 static gboolean
meta_display_init_x11_display(MetaDisplay * display,GError ** error)659 meta_display_init_x11_display (MetaDisplay *display,
660 GError **error)
661 {
662 MetaX11Display *x11_display;
663
664 x11_display = meta_x11_display_new (display, error);
665 if (!x11_display)
666 return FALSE;
667
668 display->x11_display = x11_display;
669 g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0);
670
671 meta_x11_display_create_guard_window (x11_display);
672
673 if (!display->display_opening)
674 {
675 g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
676 meta_display_manage_all_xwindows (display);
677 meta_compositor_redirect_x11_windows (display->compositor);
678 }
679
680 return TRUE;
681 }
682
683 #ifdef HAVE_WAYLAND
684 gboolean
meta_display_init_x11_finish(MetaDisplay * display,GAsyncResult * result,GError ** error)685 meta_display_init_x11_finish (MetaDisplay *display,
686 GAsyncResult *result,
687 GError **error)
688 {
689 MetaX11Display *x11_display;
690
691 g_assert (g_task_get_source_tag (G_TASK (result)) == meta_display_init_x11);
692
693 if (!g_task_propagate_boolean (G_TASK (result), error))
694 {
695 if (*error == NULL)
696 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown error");
697
698 return FALSE;
699 }
700
701 if (display->x11_display)
702 return TRUE;
703
704 x11_display = meta_x11_display_new (display, error);
705 if (!x11_display)
706 return FALSE;
707
708 display->x11_display = x11_display;
709 g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0);
710
711 meta_x11_display_create_guard_window (x11_display);
712
713 if (!display->display_opening)
714 {
715 g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
716 meta_x11_display_set_cm_selection (x11_display);
717 meta_display_manage_all_xwindows (display);
718 meta_compositor_redirect_x11_windows (display->compositor);
719 }
720
721 return TRUE;
722 }
723
724 static void
on_xserver_started(MetaXWaylandManager * manager,GAsyncResult * result,gpointer user_data)725 on_xserver_started (MetaXWaylandManager *manager,
726 GAsyncResult *result,
727 gpointer user_data)
728 {
729 g_autoptr (GTask) task = user_data;
730 MetaDisplay *display = g_task_get_source_object (task);
731 GError *error = NULL;
732 gboolean retval = FALSE;
733
734 if (!meta_xwayland_start_xserver_finish (manager, result, &error))
735 {
736 if (error)
737 g_task_return_error (task, error);
738 else
739 g_task_return_boolean (task, FALSE);
740
741 return;
742 }
743
744 g_signal_emit (display, display_signals[INIT_XSERVER], 0, task, &retval);
745
746 if (!retval)
747 {
748 /* No handlers for this signal, proceed right away */
749 g_task_return_boolean (task, TRUE);
750 }
751 }
752
753 void
meta_display_init_x11(MetaDisplay * display,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)754 meta_display_init_x11 (MetaDisplay *display,
755 GCancellable *cancellable,
756 GAsyncReadyCallback callback,
757 gpointer user_data)
758 {
759 MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
760
761 g_autoptr (GTask) task = NULL;
762
763 task = g_task_new (display, cancellable, callback, user_data);
764 g_task_set_source_tag (task, meta_display_init_x11);
765
766 meta_xwayland_start_xserver (&compositor->xwayland_manager,
767 cancellable,
768 (GAsyncReadyCallback) on_xserver_started,
769 g_steal_pointer (&task));
770 }
771
772 static void
on_x11_initialized(MetaDisplay * display,GAsyncResult * result,gpointer user_data)773 on_x11_initialized (MetaDisplay *display,
774 GAsyncResult *result,
775 gpointer user_data)
776 {
777 g_autoptr (GError) error = NULL;
778
779 if (!meta_display_init_x11_finish (display, result, &error))
780 g_critical ("Failed to init X11 display: %s", error->message);
781 }
782 #endif
783
784 void
meta_display_shutdown_x11(MetaDisplay * display)785 meta_display_shutdown_x11 (MetaDisplay *display)
786 {
787 if (!display->x11_display)
788 return;
789
790 g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0);
791 g_object_run_dispose (G_OBJECT (display->x11_display));
792 g_clear_object (&display->x11_display);
793 }
794
795 MetaDisplay *
meta_display_new(MetaContext * context,GError ** error)796 meta_display_new (MetaContext *context,
797 GError **error)
798 {
799 MetaDisplay *display;
800 MetaDisplayPrivate *priv;
801 int i;
802 guint32 timestamp;
803 Window old_active_xwindow = None;
804 MetaBackend *backend = meta_get_backend ();
805 MetaMonitorManager *monitor_manager;
806 MetaSettings *settings;
807
808 g_assert (the_display == NULL);
809 display = the_display = g_object_new (META_TYPE_DISPLAY, NULL);
810
811 priv = meta_display_get_instance_private (display);
812 priv->context = context;
813
814 display->closing = 0;
815 display->display_opening = TRUE;
816
817 display->pending_pings = NULL;
818 display->autoraise_timeout_id = 0;
819 display->autoraise_window = NULL;
820 display->focus_window = NULL;
821 display->workspace_manager = NULL;
822 display->x11_display = NULL;
823
824 display->current_cursor = -1; /* invalid/unset */
825 display->tile_preview_timeout_id = 0;
826 display->check_fullscreen_later = 0;
827 display->work_area_later = 0;
828
829 display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
830 display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
831 terminal has the focus */
832
833 i = 0;
834 while (i < N_IGNORED_CROSSING_SERIALS)
835 {
836 display->ignored_crossing_serials[i] = 0;
837 ++i;
838 }
839
840 display->current_time = META_CURRENT_TIME;
841
842 display->grab_resize_timeout_id = 0;
843 display->grab_have_keyboard = FALSE;
844
845 display->grab_op = META_GRAB_OP_NONE;
846 display->grab_window = NULL;
847 display->grab_tile_mode = META_TILE_NONE;
848 display->grab_tile_monitor_number = -1;
849
850 meta_display_cleanup_edges (display);
851
852 meta_display_init_keys (display);
853
854 meta_prefs_add_listener (prefs_changed_callback, display);
855
856 /* Get events */
857 meta_display_init_events (display);
858
859 display->stamps = g_hash_table_new (g_int64_hash,
860 g_int64_equal);
861 display->wayland_windows = g_hash_table_new (NULL, NULL);
862
863 monitor_manager = meta_backend_get_monitor_manager (backend);
864 g_signal_connect (monitor_manager, "monitors-changed-internal",
865 G_CALLBACK (on_monitors_changed_internal), display);
866
867 display->pad_action_mapper = meta_pad_action_mapper_new (monitor_manager);
868
869 settings = meta_backend_get_settings (backend);
870 g_signal_connect (settings, "ui-scaling-factor-changed",
871 G_CALLBACK (on_ui_scaling_factor_changed), display);
872
873 display->compositor = create_compositor (display);
874
875 meta_display_set_cursor (display, META_CURSOR_DEFAULT);
876
877 display->stack = meta_stack_new (display);
878 display->stack_tracker = meta_stack_tracker_new (display);
879
880 display->workspace_manager = meta_workspace_manager_new (display);
881
882 display->startup_notification = meta_startup_notification_new (display);
883
884 display->bell = meta_bell_new (display);
885
886 display->selection = meta_selection_new (display);
887 meta_clipboard_manager_init (display);
888
889 #ifdef HAVE_WAYLAND
890 if (meta_is_wayland_compositor ())
891 {
892 MetaX11DisplayPolicy x11_display_policy;
893
894 x11_display_policy = meta_context_get_x11_display_policy (context);
895 if (x11_display_policy == META_X11_DISPLAY_POLICY_MANDATORY)
896 {
897 meta_display_init_x11 (display, NULL,
898 (GAsyncReadyCallback) on_x11_initialized,
899 NULL);
900 }
901
902 timestamp = meta_display_get_current_time_roundtrip (display);
903 }
904 else
905 #endif
906 {
907 if (!meta_display_init_x11_display (display, error))
908 {
909 g_object_unref (display);
910 return NULL;
911 }
912
913 timestamp = display->x11_display->timestamp;
914 }
915
916 display->last_focus_time = timestamp;
917 display->last_user_time = timestamp;
918
919 if (!meta_is_wayland_compositor ())
920 meta_prop_get_window (display->x11_display,
921 display->x11_display->xroot,
922 display->x11_display->atom__NET_ACTIVE_WINDOW,
923 &old_active_xwindow);
924
925 if (!meta_compositor_do_manage (display->compositor, error))
926 {
927 g_object_unref (display);
928 return NULL;
929 }
930
931 if (display->x11_display)
932 {
933 g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
934 meta_x11_display_restore_active_workspace (display->x11_display);
935 meta_x11_display_create_guard_window (display->x11_display);
936 }
937
938 /* Set up touch support */
939 display->gesture_tracker = meta_gesture_tracker_new ();
940 g_signal_connect (display->gesture_tracker, "state-changed",
941 G_CALLBACK (gesture_tracker_state_changed), display);
942
943 /* We know that if mutter is running as a Wayland compositor,
944 * we start out with no windows.
945 */
946 if (!meta_is_wayland_compositor ())
947 meta_display_manage_all_xwindows (display);
948
949 if (old_active_xwindow != None)
950 {
951 MetaWindow *old_active_window;
952 old_active_window = meta_x11_display_lookup_x_window (display->x11_display,
953 old_active_xwindow);
954 if (old_active_window)
955 meta_window_focus (old_active_window, timestamp);
956 else
957 meta_display_unset_input_focus (display, timestamp);
958 }
959 else
960 {
961 meta_display_unset_input_focus (display, timestamp);
962 }
963
964 display->sound_player = g_object_new (META_TYPE_SOUND_PLAYER, NULL);
965
966 /* Done opening new display */
967 display->display_opening = FALSE;
968
969 return display;
970 }
971
972 static gint
ptrcmp(gconstpointer a,gconstpointer b)973 ptrcmp (gconstpointer a, gconstpointer b)
974 {
975 if (a < b)
976 return -1;
977 else if (a > b)
978 return 1;
979 else
980 return 0;
981 }
982
983 /**
984 * meta_display_list_windows:
985 * @display: a #MetaDisplay
986 * @flags: options for listing
987 *
988 * Lists windows for the display, the @flags parameter for
989 * now determines whether override-redirect windows will be
990 * included.
991 *
992 * Return value: (transfer container): the list of windows.
993 */
994 GSList*
meta_display_list_windows(MetaDisplay * display,MetaListWindowsFlags flags)995 meta_display_list_windows (MetaDisplay *display,
996 MetaListWindowsFlags flags)
997 {
998 GSList *winlist;
999 GSList *prev;
1000 GSList *tmp;
1001 GHashTableIter iter;
1002 gpointer key, value;
1003
1004 winlist = NULL;
1005
1006 if (display->x11_display)
1007 {
1008 g_hash_table_iter_init (&iter, display->x11_display->xids);
1009 while (g_hash_table_iter_next (&iter, &key, &value))
1010 {
1011 MetaWindow *window = value;
1012
1013 if (!META_IS_WINDOW (window) || window->unmanaging)
1014 continue;
1015
1016 if (!window->override_redirect ||
1017 (flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0)
1018 winlist = g_slist_prepend (winlist, window);
1019 }
1020 }
1021
1022 g_hash_table_iter_init (&iter, display->wayland_windows);
1023 while (g_hash_table_iter_next (&iter, &key, &value))
1024 {
1025 MetaWindow *window = value;
1026
1027 if (!META_IS_WINDOW (window) || window->unmanaging)
1028 continue;
1029
1030 if (!window->override_redirect ||
1031 (flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0)
1032 winlist = g_slist_prepend (winlist, window);
1033 }
1034
1035 /* Uniquify the list, since both frame windows and plain
1036 * windows are in the hash
1037 */
1038 winlist = g_slist_sort (winlist, ptrcmp);
1039
1040 prev = NULL;
1041 tmp = winlist;
1042 while (tmp != NULL)
1043 {
1044 GSList *next;
1045
1046 next = tmp->next;
1047
1048 if (next &&
1049 next->data == tmp->data)
1050 {
1051 /* Delete tmp from list */
1052
1053 if (prev)
1054 prev->next = next;
1055
1056 if (tmp == winlist)
1057 winlist = next;
1058
1059 g_slist_free_1 (tmp);
1060
1061 /* leave prev unchanged */
1062 }
1063 else
1064 {
1065 prev = tmp;
1066 }
1067
1068 tmp = next;
1069 }
1070
1071 if (flags & META_LIST_SORTED)
1072 winlist = g_slist_sort (winlist, mru_cmp);
1073
1074 return winlist;
1075 }
1076
1077 void
meta_display_close(MetaDisplay * display,guint32 timestamp)1078 meta_display_close (MetaDisplay *display,
1079 guint32 timestamp)
1080 {
1081 g_assert (display != NULL);
1082
1083 if (display->closing != 0)
1084 {
1085 /* The display's already been closed. */
1086 return;
1087 }
1088
1089 g_assert (display == the_display);
1090
1091 display->closing += 1;
1092
1093 g_signal_emit (display, display_signals[CLOSING], 0);
1094
1095 meta_compositor_unmanage (display->compositor);
1096
1097 meta_display_unmanage_windows (display, timestamp);
1098
1099 meta_prefs_remove_listener (prefs_changed_callback, display);
1100
1101 meta_display_remove_autoraise_callback (display);
1102
1103 g_clear_object (&display->gesture_tracker);
1104
1105 g_clear_handle_id (&display->focus_timeout_id, g_source_remove);
1106 g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove);
1107
1108 if (display->work_area_later != 0)
1109 meta_later_remove (display->work_area_later);
1110 if (display->check_fullscreen_later != 0)
1111 meta_later_remove (display->check_fullscreen_later);
1112
1113 /* Stop caring about events */
1114 meta_display_free_events (display);
1115
1116 g_clear_pointer (&display->compositor, meta_compositor_destroy);
1117
1118 meta_display_shutdown_x11 (display);
1119
1120 g_clear_object (&display->stack);
1121 g_clear_pointer (&display->stack_tracker,
1122 meta_stack_tracker_free);
1123
1124 /* Must be after all calls to meta_window_unmanage() since they
1125 * unregister windows
1126 */
1127 g_hash_table_destroy (display->wayland_windows);
1128 g_hash_table_destroy (display->stamps);
1129
1130 meta_display_shutdown_keys (display);
1131
1132 g_clear_object (&display->bell);
1133 g_clear_object (&display->startup_notification);
1134 g_clear_object (&display->workspace_manager);
1135 g_clear_object (&display->sound_player);
1136
1137 meta_clipboard_manager_shutdown (display);
1138 g_clear_object (&display->selection);
1139 g_clear_object (&display->pad_action_mapper);
1140
1141 the_display = NULL;
1142 }
1143
1144 /**
1145 * meta_display_for_x_display:
1146 * @xdisplay: An X display
1147 *
1148 * Returns the singleton MetaDisplay if @xdisplay matches the X display it's
1149 * managing; otherwise gives a warning and returns %NULL. When we were claiming
1150 * to be able to manage multiple displays, this was supposed to find the
1151 * display out of the list which matched that display. Now it's merely an
1152 * extra sanity check.
1153 *
1154 * Returns: The singleton X display, or %NULL if @xdisplay isn't the one
1155 * we're managing.
1156 */
1157 MetaDisplay*
meta_display_for_x_display(Display * xdisplay)1158 meta_display_for_x_display (Display *xdisplay)
1159 {
1160 if (the_display->x11_display->xdisplay == xdisplay)
1161 return the_display;
1162
1163 meta_warning ("Could not find display for X display %p, probably going to crash",
1164 xdisplay);
1165
1166 return NULL;
1167 }
1168
1169 /**
1170 * meta_get_display:
1171 *
1172 * Accessor for the singleton MetaDisplay.
1173 *
1174 * Returns: The only #MetaDisplay there is. This can be %NULL, but only
1175 * during startup.
1176 */
1177 MetaDisplay*
meta_get_display(void)1178 meta_get_display (void)
1179 {
1180 return the_display;
1181 }
1182
1183 static inline gboolean
grab_op_is_window(MetaGrabOp op)1184 grab_op_is_window (MetaGrabOp op)
1185 {
1186 return META_GRAB_OP_GET_BASE_TYPE (op) == META_GRAB_OP_WINDOW_BASE;
1187 }
1188
1189 gboolean
meta_grab_op_is_mouse(MetaGrabOp op)1190 meta_grab_op_is_mouse (MetaGrabOp op)
1191 {
1192 if (!grab_op_is_window (op))
1193 return FALSE;
1194
1195 return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) == 0;
1196 }
1197
1198 gboolean
meta_grab_op_is_keyboard(MetaGrabOp op)1199 meta_grab_op_is_keyboard (MetaGrabOp op)
1200 {
1201 if (!grab_op_is_window (op))
1202 return FALSE;
1203
1204 return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) != 0;
1205 }
1206
1207 gboolean
meta_grab_op_is_resizing(MetaGrabOp op)1208 meta_grab_op_is_resizing (MetaGrabOp op)
1209 {
1210 if (!grab_op_is_window (op))
1211 return FALSE;
1212
1213 return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0 || op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN;
1214 }
1215
1216 gboolean
meta_grab_op_is_moving(MetaGrabOp op)1217 meta_grab_op_is_moving (MetaGrabOp op)
1218 {
1219 if (!grab_op_is_window (op))
1220 return FALSE;
1221
1222 return !meta_grab_op_is_resizing (op);
1223 }
1224
1225 /**
1226 * meta_display_windows_are_interactable:
1227 * @op: A #MetaGrabOp
1228 *
1229 * Whether windows can be interacted with.
1230 */
1231 gboolean
meta_display_windows_are_interactable(MetaDisplay * display)1232 meta_display_windows_are_interactable (MetaDisplay *display)
1233 {
1234 switch (display->event_route)
1235 {
1236 case META_EVENT_ROUTE_NORMAL:
1237 case META_EVENT_ROUTE_WAYLAND_POPUP:
1238 return TRUE;
1239 default:
1240 return FALSE;
1241 }
1242 }
1243
1244 /**
1245 * meta_display_xserver_time_is_before:
1246 * @display: a #MetaDisplay
1247 * @time1: An event timestamp
1248 * @time2: An event timestamp
1249 *
1250 * Xserver time can wraparound, thus comparing two timestamps needs to take
1251 * this into account. If no wraparound has occurred, this is equivalent to
1252 * time1 < time2
1253 * Otherwise, we need to account for the fact that wraparound can occur
1254 * and the fact that a timestamp of 0 must be special-cased since it
1255 * means "older than anything else".
1256 *
1257 * Note that this is NOT an equivalent for time1 <= time2; if that's what
1258 * you need then you'll need to swap the order of the arguments and negate
1259 * the result.
1260 */
1261 gboolean
meta_display_xserver_time_is_before(MetaDisplay * display,guint32 time1,guint32 time2)1262 meta_display_xserver_time_is_before (MetaDisplay *display,
1263 guint32 time1,
1264 guint32 time2)
1265 {
1266 return XSERVER_TIME_IS_BEFORE(time1, time2);
1267 }
1268
1269 /**
1270 * meta_display_get_last_user_time:
1271 * @display: a #MetaDisplay
1272 *
1273 * Returns: Timestamp of the last user interaction event with a window
1274 */
1275 guint32
meta_display_get_last_user_time(MetaDisplay * display)1276 meta_display_get_last_user_time (MetaDisplay *display)
1277 {
1278 return display->last_user_time;
1279 }
1280
1281 /* Get time of current event, or CurrentTime if none. */
1282 guint32
meta_display_get_current_time(MetaDisplay * display)1283 meta_display_get_current_time (MetaDisplay *display)
1284 {
1285 return display->current_time;
1286 }
1287
1288 guint32
meta_display_get_current_time_roundtrip(MetaDisplay * display)1289 meta_display_get_current_time_roundtrip (MetaDisplay *display)
1290 {
1291 if (meta_is_wayland_compositor ())
1292 /* Xwayland uses monotonic clock, so lets use it here as well */
1293 return (guint32) (g_get_monotonic_time () / 1000);
1294 else
1295 return meta_x11_display_get_current_time_roundtrip (display->x11_display);
1296 }
1297
1298 /**
1299 * meta_display_add_ignored_crossing_serial:
1300 * @display: a #MetaDisplay
1301 * @serial: the serial to ignore
1302 *
1303 * Save the specified serial and ignore crossing events with that
1304 * serial for the purpose of focus-follows-mouse. This can be used
1305 * for certain changes to the window hierarchy that we don't want
1306 * to change the focus window, even if they cause the pointer to
1307 * end up in a new window.
1308 */
1309 void
meta_display_add_ignored_crossing_serial(MetaDisplay * display,unsigned long serial)1310 meta_display_add_ignored_crossing_serial (MetaDisplay *display,
1311 unsigned long serial)
1312 {
1313 int i;
1314
1315 /* don't add the same serial more than once */
1316 if (display->ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS-1] == serial)
1317 return;
1318
1319 /* shift serials to the left */
1320 i = 0;
1321 while (i < (N_IGNORED_CROSSING_SERIALS - 1))
1322 {
1323 display->ignored_crossing_serials[i] = display->ignored_crossing_serials[i+1];
1324 ++i;
1325 }
1326 /* put new one on the end */
1327 display->ignored_crossing_serials[i] = serial;
1328 }
1329
1330 static gboolean
window_raise_with_delay_callback(void * data)1331 window_raise_with_delay_callback (void *data)
1332 {
1333 MetaWindow *window = data;
1334
1335 window->display->autoraise_timeout_id = 0;
1336 window->display->autoraise_window = NULL;
1337
1338 /* If we aren't already on top, check whether the pointer is inside
1339 * the window and raise the window if so.
1340 */
1341 if (meta_stack_get_top (window->display->stack) != window)
1342 {
1343 if (meta_window_has_pointer (window))
1344 meta_window_raise (window);
1345 else
1346 meta_topic (META_DEBUG_FOCUS,
1347 "Pointer not inside window, not raising %s",
1348 window->desc);
1349 }
1350
1351 return G_SOURCE_REMOVE;
1352 }
1353
1354 void
meta_display_queue_autoraise_callback(MetaDisplay * display,MetaWindow * window)1355 meta_display_queue_autoraise_callback (MetaDisplay *display,
1356 MetaWindow *window)
1357 {
1358 meta_topic (META_DEBUG_FOCUS,
1359 "Queuing an autoraise timeout for %s with delay %d",
1360 window->desc,
1361 meta_prefs_get_auto_raise_delay ());
1362
1363 g_clear_handle_id (&display->autoraise_timeout_id, g_source_remove);
1364
1365 display->autoraise_timeout_id =
1366 g_timeout_add_full (G_PRIORITY_DEFAULT,
1367 meta_prefs_get_auto_raise_delay (),
1368 window_raise_with_delay_callback,
1369 window, NULL);
1370 g_source_set_name_by_id (display->autoraise_timeout_id, "[mutter] window_raise_with_delay_callback");
1371 display->autoraise_window = window;
1372 }
1373
1374 void
meta_display_sync_wayland_input_focus(MetaDisplay * display)1375 meta_display_sync_wayland_input_focus (MetaDisplay *display)
1376 {
1377 #ifdef HAVE_WAYLAND
1378 MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
1379 MetaWindow *focus_window = NULL;
1380 MetaBackend *backend = meta_get_backend ();
1381 ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
1382 ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
1383 MetaStage *stage = META_STAGE (meta_backend_get_stage (backend));
1384 gboolean is_no_focus_xwindow = FALSE;
1385
1386 if (display->x11_display)
1387 is_no_focus_xwindow = meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display,
1388 display->x11_display->focus_xwindow);
1389
1390 if (!meta_display_windows_are_interactable (display))
1391 focus_window = NULL;
1392 else if (is_no_focus_xwindow)
1393 focus_window = NULL;
1394 else if (display->focus_window && display->focus_window->surface)
1395 focus_window = display->focus_window;
1396 else
1397 meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
1398
1399 meta_stage_set_active (stage, focus_window == NULL);
1400 meta_wayland_compositor_set_input_focus (compositor, focus_window);
1401
1402 clutter_stage_repick_device (CLUTTER_STAGE (stage),
1403 clutter_seat_get_pointer (seat));
1404 #endif
1405 }
1406
1407 static void
meta_window_set_inactive_since(MetaWindow * window,int64_t inactive_since_us)1408 meta_window_set_inactive_since (MetaWindow *window,
1409 int64_t inactive_since_us)
1410 {
1411 GFile *file = NULL;
1412 g_autoptr (GFileInfo) file_info = NULL;
1413 g_autofree char *timestamp = NULL;
1414
1415 timestamp = g_strdup_printf ("%" G_GINT64_FORMAT, inactive_since_us);
1416
1417 file = meta_window_get_unit_cgroup (window);
1418 if (!file)
1419 return;
1420
1421 file_info = g_file_info_new ();
1422 g_file_info_set_attribute_string (file_info,
1423 "xattr::xdg.inactive-since", timestamp);
1424
1425 if (!g_file_set_attributes_from_info (file, file_info,
1426 G_FILE_QUERY_INFO_NONE,
1427 NULL, NULL))
1428 return;
1429 }
1430
1431 void
meta_display_update_focus_window(MetaDisplay * display,MetaWindow * window)1432 meta_display_update_focus_window (MetaDisplay *display,
1433 MetaWindow *window)
1434 {
1435 MetaWindow *previous = NULL;
1436
1437 if (display->focus_window == window)
1438 return;
1439
1440 if (display->focus_window)
1441 {
1442 meta_topic (META_DEBUG_FOCUS,
1443 "%s is now the previous focus window due to being focused out or unmapped",
1444 display->focus_window->desc);
1445
1446 /* Make sure that signals handlers invoked by
1447 * meta_window_set_focused_internal() don't see
1448 * display->focus_window->has_focus == FALSE
1449 */
1450 previous = display->focus_window;
1451 display->focus_window = NULL;
1452
1453 meta_window_set_focused_internal (previous, FALSE);
1454 }
1455
1456 display->focus_window = window;
1457
1458 if (display->focus_window)
1459 {
1460 meta_topic (META_DEBUG_FOCUS, "* Focus --> %s",
1461 display->focus_window->desc);
1462 meta_window_set_focused_internal (display->focus_window, TRUE);
1463 }
1464 else
1465 meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL");
1466
1467 if (!previous || !display->focus_window ||
1468 !meta_window_unit_cgroup_equal (previous, display->focus_window))
1469 {
1470 if (previous)
1471 meta_window_set_inactive_since (previous, g_get_monotonic_time ());
1472 if (display->focus_window)
1473 meta_window_set_inactive_since (display->focus_window, -1);
1474 }
1475
1476 if (meta_is_wayland_compositor ())
1477 meta_display_sync_wayland_input_focus (display);
1478
1479 g_object_notify (G_OBJECT (display), "focus-window");
1480 }
1481
1482 gboolean
meta_display_timestamp_too_old(MetaDisplay * display,guint32 * timestamp)1483 meta_display_timestamp_too_old (MetaDisplay *display,
1484 guint32 *timestamp)
1485 {
1486 /* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
1487 * us to sanity check the timestamp here and ensure it doesn't correspond to
1488 * a future time (though we would want to rename to
1489 * timestamp_too_old_or_in_future).
1490 */
1491
1492 if (*timestamp == META_CURRENT_TIME)
1493 {
1494 *timestamp = meta_display_get_current_time_roundtrip (display);
1495 return FALSE;
1496 }
1497 else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
1498 {
1499 if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
1500 return TRUE;
1501 else
1502 {
1503 *timestamp = display->last_focus_time;
1504 return FALSE;
1505 }
1506 }
1507
1508 return FALSE;
1509 }
1510
1511 void
meta_display_set_input_focus(MetaDisplay * display,MetaWindow * window,gboolean focus_frame,guint32 timestamp)1512 meta_display_set_input_focus (MetaDisplay *display,
1513 MetaWindow *window,
1514 gboolean focus_frame,
1515 guint32 timestamp)
1516 {
1517 if (meta_display_timestamp_too_old (display, ×tamp))
1518 return;
1519
1520 if (display->x11_display)
1521 {
1522 meta_x11_display_set_input_focus (display->x11_display, window,
1523 focus_frame, timestamp);
1524 }
1525
1526 meta_display_update_focus_window (display, window);
1527
1528 display->last_focus_time = timestamp;
1529
1530 if (window == NULL || window != display->autoraise_window)
1531 meta_display_remove_autoraise_callback (display);
1532 }
1533
1534 void
meta_display_unset_input_focus(MetaDisplay * display,guint32 timestamp)1535 meta_display_unset_input_focus (MetaDisplay *display,
1536 guint32 timestamp)
1537 {
1538 meta_display_set_input_focus (display, NULL, FALSE, timestamp);
1539 }
1540
1541 void
meta_display_register_wayland_window(MetaDisplay * display,MetaWindow * window)1542 meta_display_register_wayland_window (MetaDisplay *display,
1543 MetaWindow *window)
1544 {
1545 g_hash_table_add (display->wayland_windows, window);
1546 }
1547
1548 void
meta_display_unregister_wayland_window(MetaDisplay * display,MetaWindow * window)1549 meta_display_unregister_wayland_window (MetaDisplay *display,
1550 MetaWindow *window)
1551 {
1552 g_hash_table_remove (display->wayland_windows, window);
1553 }
1554
1555 MetaWindow*
meta_display_lookup_stamp(MetaDisplay * display,guint64 stamp)1556 meta_display_lookup_stamp (MetaDisplay *display,
1557 guint64 stamp)
1558 {
1559 return g_hash_table_lookup (display->stamps, &stamp);
1560 }
1561
1562 void
meta_display_register_stamp(MetaDisplay * display,guint64 * stampp,MetaWindow * window)1563 meta_display_register_stamp (MetaDisplay *display,
1564 guint64 *stampp,
1565 MetaWindow *window)
1566 {
1567 g_return_if_fail (g_hash_table_lookup (display->stamps, stampp) == NULL);
1568
1569 g_hash_table_insert (display->stamps, stampp, window);
1570 }
1571
1572 void
meta_display_unregister_stamp(MetaDisplay * display,guint64 stamp)1573 meta_display_unregister_stamp (MetaDisplay *display,
1574 guint64 stamp)
1575 {
1576 g_return_if_fail (g_hash_table_lookup (display->stamps, &stamp) != NULL);
1577
1578 g_hash_table_remove (display->stamps, &stamp);
1579 }
1580
1581 MetaWindow*
meta_display_lookup_stack_id(MetaDisplay * display,guint64 stack_id)1582 meta_display_lookup_stack_id (MetaDisplay *display,
1583 guint64 stack_id)
1584 {
1585 if (META_STACK_ID_IS_X11 (stack_id))
1586 {
1587 if (!display->x11_display)
1588 return NULL;
1589 return meta_x11_display_lookup_x_window (display->x11_display,
1590 (Window)stack_id);
1591 }
1592 else
1593 {
1594 return meta_display_lookup_stamp (display, stack_id);
1595 }
1596 }
1597
1598 /* We return a pointer into a ring of static buffers. This is to make
1599 * using this function for debug-logging convenient and avoid temporary
1600 * strings that must be freed. */
1601 const char *
meta_display_describe_stack_id(MetaDisplay * display,guint64 stack_id)1602 meta_display_describe_stack_id (MetaDisplay *display,
1603 guint64 stack_id)
1604 {
1605 /* 0x<64-bit: 16 characters> (<10 characters of title>)\0' */
1606 static char buffer[5][32];
1607 MetaWindow *window;
1608 static int pos = 0;
1609 char *result;
1610
1611 result = buffer[pos];
1612 pos = (pos + 1) % 5;
1613
1614 window = meta_display_lookup_stack_id (display, stack_id);
1615
1616 if (window && window->title)
1617 snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x (%.10s)", stack_id, window->title);
1618 else
1619 snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x", stack_id);
1620
1621 return result;
1622 }
1623
1624 void
meta_display_notify_window_created(MetaDisplay * display,MetaWindow * window)1625 meta_display_notify_window_created (MetaDisplay *display,
1626 MetaWindow *window)
1627 {
1628 COGL_TRACE_BEGIN_SCOPED (MetaDisplayNotifyWindowCreated,
1629 "Display (notify window created)");
1630 g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
1631 }
1632
1633 static MetaCursor
meta_cursor_for_grab_op(MetaGrabOp op)1634 meta_cursor_for_grab_op (MetaGrabOp op)
1635 {
1636 switch (op)
1637 {
1638 case META_GRAB_OP_RESIZING_SE:
1639 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
1640 return META_CURSOR_SE_RESIZE;
1641 break;
1642 case META_GRAB_OP_RESIZING_S:
1643 case META_GRAB_OP_KEYBOARD_RESIZING_S:
1644 return META_CURSOR_SOUTH_RESIZE;
1645 break;
1646 case META_GRAB_OP_RESIZING_SW:
1647 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
1648 return META_CURSOR_SW_RESIZE;
1649 break;
1650 case META_GRAB_OP_RESIZING_N:
1651 case META_GRAB_OP_KEYBOARD_RESIZING_N:
1652 return META_CURSOR_NORTH_RESIZE;
1653 break;
1654 case META_GRAB_OP_RESIZING_NE:
1655 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
1656 return META_CURSOR_NE_RESIZE;
1657 break;
1658 case META_GRAB_OP_RESIZING_NW:
1659 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
1660 return META_CURSOR_NW_RESIZE;
1661 break;
1662 case META_GRAB_OP_RESIZING_W:
1663 case META_GRAB_OP_KEYBOARD_RESIZING_W:
1664 return META_CURSOR_WEST_RESIZE;
1665 break;
1666 case META_GRAB_OP_RESIZING_E:
1667 case META_GRAB_OP_KEYBOARD_RESIZING_E:
1668 return META_CURSOR_EAST_RESIZE;
1669 break;
1670 case META_GRAB_OP_MOVING:
1671 case META_GRAB_OP_KEYBOARD_MOVING:
1672 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
1673 return META_CURSOR_MOVE_OR_RESIZE_WINDOW;
1674 break;
1675 default:
1676 break;
1677 }
1678
1679 return META_CURSOR_DEFAULT;
1680 }
1681
1682 static void
root_cursor_prepare_at(MetaCursorSpriteXcursor * sprite_xcursor,float best_scale,int x,int y,MetaDisplay * display)1683 root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
1684 float best_scale,
1685 int x,
1686 int y,
1687 MetaDisplay *display)
1688 {
1689 MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
1690 MetaBackend *backend = meta_get_backend ();
1691
1692 if (meta_is_stage_views_scaled ())
1693 {
1694 if (best_scale != 0.0f)
1695 {
1696 float ceiled_scale;
1697
1698 ceiled_scale = ceilf (best_scale);
1699 meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
1700 (int) ceiled_scale);
1701 meta_cursor_sprite_set_texture_scale (cursor_sprite,
1702 1.0 / ceiled_scale);
1703 }
1704 }
1705 else
1706 {
1707 MetaMonitorManager *monitor_manager =
1708 meta_backend_get_monitor_manager (backend);
1709 MetaLogicalMonitor *logical_monitor;
1710
1711 logical_monitor =
1712 meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
1713
1714 /* Reload the cursor texture if the scale has changed. */
1715 if (logical_monitor)
1716 {
1717 meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
1718 logical_monitor->scale);
1719 meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0);
1720 }
1721 }
1722 }
1723
1724 static void
manage_root_cursor_sprite_scale(MetaDisplay * display,MetaCursorSpriteXcursor * sprite_xcursor)1725 manage_root_cursor_sprite_scale (MetaDisplay *display,
1726 MetaCursorSpriteXcursor *sprite_xcursor)
1727 {
1728 g_signal_connect_object (sprite_xcursor,
1729 "prepare-at",
1730 G_CALLBACK (root_cursor_prepare_at),
1731 display,
1732 0);
1733 }
1734
1735 void
meta_display_reload_cursor(MetaDisplay * display)1736 meta_display_reload_cursor (MetaDisplay *display)
1737 {
1738 MetaCursor cursor = display->current_cursor;
1739 MetaCursorSpriteXcursor *sprite_xcursor;
1740 MetaBackend *backend = meta_get_backend ();
1741 MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
1742
1743 sprite_xcursor = meta_cursor_sprite_xcursor_new (cursor);
1744
1745 if (meta_is_wayland_compositor ())
1746 manage_root_cursor_sprite_scale (display, sprite_xcursor);
1747
1748 meta_cursor_tracker_set_root_cursor (cursor_tracker,
1749 META_CURSOR_SPRITE (sprite_xcursor));
1750 g_object_unref (sprite_xcursor);
1751
1752 g_signal_emit (display, display_signals[CURSOR_UPDATED], 0, display);
1753 }
1754
1755 void
meta_display_set_cursor(MetaDisplay * display,MetaCursor cursor)1756 meta_display_set_cursor (MetaDisplay *display,
1757 MetaCursor cursor)
1758 {
1759 if (cursor == display->current_cursor)
1760 return;
1761
1762 display->current_cursor = cursor;
1763 meta_display_reload_cursor (display);
1764 }
1765
1766 void
meta_display_update_cursor(MetaDisplay * display)1767 meta_display_update_cursor (MetaDisplay *display)
1768 {
1769 meta_display_set_cursor (display, meta_cursor_for_grab_op (display->grab_op));
1770 }
1771
1772 static MetaWindow *
get_first_freefloating_window(MetaWindow * window)1773 get_first_freefloating_window (MetaWindow *window)
1774 {
1775 while (meta_window_is_attached_dialog (window))
1776 window = meta_window_get_transient_for (window);
1777
1778 /* Attached dialogs should always have a non-NULL transient-for */
1779 g_assert (window != NULL);
1780
1781 return window;
1782 }
1783
1784 static MetaEventRoute
get_event_route_from_grab_op(MetaGrabOp op)1785 get_event_route_from_grab_op (MetaGrabOp op)
1786 {
1787 switch (META_GRAB_OP_GET_BASE_TYPE (op))
1788 {
1789 case META_GRAB_OP_NONE:
1790 /* begin_grab_op shouldn't be called with META_GRAB_OP_NONE. */
1791 g_assert_not_reached ();
1792
1793 case META_GRAB_OP_WINDOW_BASE:
1794 return META_EVENT_ROUTE_WINDOW_OP;
1795
1796 case META_GRAB_OP_COMPOSITOR:
1797 /* begin_grab_op shouldn't be called with META_GRAB_OP_COMPOSITOR. */
1798 g_assert_not_reached ();
1799
1800 case META_GRAB_OP_WAYLAND_POPUP:
1801 return META_EVENT_ROUTE_WAYLAND_POPUP;
1802
1803 case META_GRAB_OP_FRAME_BUTTON:
1804 return META_EVENT_ROUTE_FRAME_BUTTON;
1805
1806 default:
1807 g_assert_not_reached ();
1808 return 0;
1809 }
1810 }
1811
1812 gboolean
meta_display_begin_grab_op(MetaDisplay * display,MetaWindow * window,MetaGrabOp op,gboolean pointer_already_grabbed,gboolean frame_action,int button,gulong modmask,guint32 timestamp,int root_x,int root_y)1813 meta_display_begin_grab_op (MetaDisplay *display,
1814 MetaWindow *window,
1815 MetaGrabOp op,
1816 gboolean pointer_already_grabbed,
1817 gboolean frame_action,
1818 int button,
1819 gulong modmask, /* XXX - ignored */
1820 guint32 timestamp,
1821 int root_x,
1822 int root_y)
1823 {
1824 MetaBackend *backend = meta_get_backend ();
1825 MetaWindow *grab_window = NULL;
1826 MetaEventRoute event_route;
1827
1828 g_assert (window != NULL);
1829
1830 meta_topic (META_DEBUG_WINDOW_OPS,
1831 "Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d",
1832 op, window->desc, button, pointer_already_grabbed,
1833 root_x, root_y);
1834
1835 if (display->grab_op != META_GRAB_OP_NONE)
1836 {
1837 meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect",
1838 op, window->desc, display->grab_op,
1839 display->grab_window ? display->grab_window->desc : "none");
1840 return FALSE;
1841 }
1842
1843 event_route = get_event_route_from_grab_op (op);
1844
1845 if (event_route == META_EVENT_ROUTE_WINDOW_OP)
1846 {
1847 if (meta_prefs_get_raise_on_click ())
1848 meta_window_raise (window);
1849 else
1850 {
1851 display->grab_initial_x = root_x;
1852 display->grab_initial_y = root_y;
1853 display->grab_threshold_movement_reached = FALSE;
1854 }
1855 }
1856
1857 grab_window = window;
1858
1859 /* If we're trying to move a window, move the first
1860 * non-attached dialog instead.
1861 */
1862 if (meta_grab_op_is_moving (op))
1863 grab_window = get_first_freefloating_window (window);
1864
1865 g_assert (grab_window != NULL);
1866 g_assert (op != META_GRAB_OP_NONE);
1867
1868 display->grab_have_pointer = FALSE;
1869
1870 if (pointer_already_grabbed)
1871 display->grab_have_pointer = TRUE;
1872
1873 if (META_IS_BACKEND_X11 (meta_get_backend ()) && display->x11_display)
1874 {
1875 /* Since grab operations often happen as a result of implicit
1876 * pointer operations on the display X11 connection, we need
1877 * to ungrab here to ensure that the backend's X11 can take
1878 * the device grab. */
1879 XIUngrabDevice (display->x11_display->xdisplay,
1880 META_VIRTUAL_CORE_POINTER_ID,
1881 timestamp);
1882 XSync (display->x11_display->xdisplay, False);
1883 }
1884
1885 if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
1886 display->grab_have_pointer = TRUE;
1887
1888 if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op))
1889 {
1890 meta_topic (META_DEBUG_WINDOW_OPS, "XIGrabDevice() failed");
1891 return FALSE;
1892 }
1893
1894 /* Grab keys when beginning window ops; see #126497 */
1895 if (event_route == META_EVENT_ROUTE_WINDOW_OP)
1896 {
1897 display->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp);
1898
1899 if (!display->grab_have_keyboard)
1900 {
1901 meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer");
1902 meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
1903 display->grab_have_pointer = FALSE;
1904 return FALSE;
1905 }
1906 }
1907
1908 display->event_route = event_route;
1909 display->grab_op = op;
1910 display->grab_window = grab_window;
1911 display->grab_button = button;
1912 display->grab_tile_mode = grab_window->tile_mode;
1913 display->grab_tile_monitor_number = grab_window->tile_monitor_number;
1914 display->grab_anchor_root_x = root_x;
1915 display->grab_anchor_root_y = root_y;
1916 display->grab_latest_motion_x = root_x;
1917 display->grab_latest_motion_y = root_y;
1918 display->grab_last_moveresize_time = 0;
1919 display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT;
1920 display->grab_frame_action = frame_action;
1921
1922 meta_display_update_cursor (display);
1923
1924 g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove);
1925
1926 meta_topic (META_DEBUG_WINDOW_OPS,
1927 "Grab op %u on window %s successful",
1928 display->grab_op, window ? window->desc : "(null)");
1929
1930 meta_window_get_frame_rect (display->grab_window,
1931 &display->grab_initial_window_pos);
1932 display->grab_anchor_window_pos = display->grab_initial_window_pos;
1933
1934 if (meta_is_wayland_compositor ())
1935 {
1936 meta_display_sync_wayland_input_focus (display);
1937 meta_display_cancel_touch (display);
1938 }
1939
1940 g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0,
1941 display->grab_window, display->grab_op);
1942
1943 if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
1944 meta_window_grab_op_began (display->grab_window, display->grab_op);
1945
1946 return TRUE;
1947 }
1948
1949 void
meta_display_end_grab_op(MetaDisplay * display,guint32 timestamp)1950 meta_display_end_grab_op (MetaDisplay *display,
1951 guint32 timestamp)
1952 {
1953 MetaWindow *grab_window = display->grab_window;
1954 MetaGrabOp grab_op = display->grab_op;
1955
1956 meta_topic (META_DEBUG_WINDOW_OPS,
1957 "Ending grab op %u at time %u", grab_op, timestamp);
1958
1959 if (display->event_route == META_EVENT_ROUTE_NORMAL ||
1960 display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
1961 return;
1962
1963 g_assert (grab_window != NULL);
1964
1965 /* We need to reset this early, since the
1966 * meta_window_grab_op_ended callback relies on this being
1967 * up to date. */
1968 display->grab_op = META_GRAB_OP_NONE;
1969
1970 if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
1971 {
1972 /* Clear out the edge cache */
1973 meta_display_cleanup_edges (display);
1974
1975 /* Only raise the window in orthogonal raise
1976 * ('do-not-raise-on-click') mode if the user didn't try to move
1977 * or resize the given window by at least a threshold amount.
1978 * For raise on click mode, the window was raised at the
1979 * beginning of the grab_op.
1980 */
1981 if (!meta_prefs_get_raise_on_click () &&
1982 !display->grab_threshold_movement_reached)
1983 meta_window_raise (display->grab_window);
1984
1985 meta_window_grab_op_ended (grab_window, grab_op);
1986 }
1987
1988 if (display->grab_have_pointer)
1989 {
1990 MetaBackend *backend = meta_get_backend ();
1991 meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
1992 }
1993
1994 if (display->grab_have_keyboard)
1995 {
1996 meta_topic (META_DEBUG_WINDOW_OPS,
1997 "Ungrabbing all keys timestamp %u", timestamp);
1998 meta_window_ungrab_all_keys (grab_window, timestamp);
1999 }
2000
2001 display->event_route = META_EVENT_ROUTE_NORMAL;
2002 display->grab_window = NULL;
2003 display->grab_button = 0;
2004 display->grab_tile_mode = META_TILE_NONE;
2005 display->grab_tile_monitor_number = -1;
2006 display->grab_anchor_root_x = 0;
2007 display->grab_anchor_root_y = 0;
2008 display->grab_latest_motion_x = 0;
2009 display->grab_latest_motion_y = 0;
2010 display->grab_last_moveresize_time = 0;
2011 display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT;
2012 display->grab_frame_action = FALSE;
2013
2014 meta_display_update_cursor (display);
2015
2016 g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove);
2017
2018 if (meta_is_wayland_compositor ())
2019 meta_display_sync_wayland_input_focus (display);
2020
2021 g_signal_emit (display, display_signals[GRAB_OP_END], 0,
2022 grab_window, grab_op);
2023 }
2024
2025 /**
2026 * meta_display_get_grab_op:
2027 * @display: The #MetaDisplay that the window is on
2028
2029 * Gets the current grab operation, if any.
2030 *
2031 * Return value: the current grab operation, or %META_GRAB_OP_NONE if
2032 * Mutter doesn't currently have a grab. %META_GRAB_OP_COMPOSITOR will
2033 * be returned if a compositor-plugin modal operation is in effect
2034 * (See mutter_begin_modal_for_plugin())
2035 */
2036 MetaGrabOp
meta_display_get_grab_op(MetaDisplay * display)2037 meta_display_get_grab_op (MetaDisplay *display)
2038 {
2039 return display->grab_op;
2040 }
2041
2042 void
meta_display_check_threshold_reached(MetaDisplay * display,int x,int y)2043 meta_display_check_threshold_reached (MetaDisplay *display,
2044 int x,
2045 int y)
2046 {
2047 /* Don't bother doing the check again if we've already reached the threshold */
2048 if (meta_prefs_get_raise_on_click () ||
2049 display->grab_threshold_movement_reached)
2050 return;
2051
2052 if (ABS (display->grab_initial_x - x) >= 8 ||
2053 ABS (display->grab_initial_y - y) >= 8)
2054 display->grab_threshold_movement_reached = TRUE;
2055 }
2056
2057 void
meta_display_queue_retheme_all_windows(MetaDisplay * display)2058 meta_display_queue_retheme_all_windows (MetaDisplay *display)
2059 {
2060 GSList* windows;
2061 GSList *tmp;
2062
2063 windows = meta_display_list_windows (display, META_LIST_DEFAULT);
2064 tmp = windows;
2065 while (tmp != NULL)
2066 {
2067 MetaWindow *window = tmp->data;
2068
2069 meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
2070 meta_window_frame_size_changed (window);
2071 if (window->frame)
2072 {
2073 meta_frame_queue_draw (window->frame);
2074 }
2075
2076 tmp = tmp->next;
2077 }
2078
2079 g_slist_free (windows);
2080 }
2081
2082 /*
2083 * Stores whether syncing is currently enabled.
2084 */
2085 static gboolean is_syncing = FALSE;
2086
2087 /**
2088 * meta_is_syncing:
2089 *
2090 * Returns whether X synchronisation is currently enabled.
2091 *
2092 * FIXME: This is *only* called by meta_display_open(), but by that time
2093 * we have already turned syncing on or off on startup, and we don't
2094 * have any way to do so while Mutter is running, so it's rather
2095 * pointless.
2096 *
2097 * Returns: %TRUE if we must wait for events whenever we send X requests;
2098 * %FALSE otherwise.
2099 */
2100 gboolean
meta_is_syncing(void)2101 meta_is_syncing (void)
2102 {
2103 return is_syncing;
2104 }
2105
2106 /**
2107 * meta_set_syncing:
2108 * @setting: whether to turn syncing on or off
2109 *
2110 * A handy way to turn on synchronisation on or off for every display.
2111 */
2112 void
meta_set_syncing(gboolean setting)2113 meta_set_syncing (gboolean setting)
2114 {
2115 if (setting != is_syncing)
2116 {
2117 is_syncing = setting;
2118 if (meta_get_display ())
2119 XSynchronize (meta_get_display ()->x11_display->xdisplay, is_syncing);
2120 }
2121 }
2122
2123 /**
2124 * meta_display_ping_timeout:
2125 * @data: All the information about this ping. It is a #MetaPingData
2126 * cast to a #gpointer in order to be passable to a timeout function.
2127 * This function will also free this parameter.
2128 *
2129 * Does whatever it is we decided to do when a window didn't respond
2130 * to a ping. We also remove the ping from the display's list of
2131 * pending pings. This function is called by the event loop when the timeout
2132 * times out which we created at the start of the ping.
2133 *
2134 * Returns: Always returns %FALSE, because this function is called as a
2135 * timeout and we don't want to run the timer again.
2136 */
2137 static gboolean
meta_display_ping_timeout(gpointer data)2138 meta_display_ping_timeout (gpointer data)
2139 {
2140 MetaPingData *ping_data = data;
2141 MetaWindow *window = ping_data->window;
2142 MetaDisplay *display = window->display;
2143
2144 meta_window_set_alive (window, FALSE);
2145
2146 ping_data->ping_timeout_id = 0;
2147
2148 meta_topic (META_DEBUG_PING,
2149 "Ping %u on window %s timed out",
2150 ping_data->serial, ping_data->window->desc);
2151
2152 display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
2153 ping_data_free (ping_data);
2154
2155 return FALSE;
2156 }
2157
2158 /**
2159 * meta_display_ping_window:
2160 * @display: The #MetaDisplay that the window is on
2161 * @window: The #MetaWindow to send the ping to
2162 * @timestamp: The timestamp of the ping. Used for uniqueness.
2163 * Cannot be CurrentTime; use a real timestamp!
2164 *
2165 * Sends a ping request to a window. The window must respond to
2166 * the request within a certain amount of time. If it does, we
2167 * will call one callback; if the time passes and we haven't had
2168 * a response, we call a different callback. The window must have
2169 * the hint showing that it can respond to a ping; if it doesn't,
2170 * we call the "got a response" callback immediately and return.
2171 * This function returns straight away after setting things up;
2172 * the callbacks will be called from the event loop.
2173 */
2174 void
meta_display_ping_window(MetaWindow * window,guint32 serial)2175 meta_display_ping_window (MetaWindow *window,
2176 guint32 serial)
2177 {
2178 GSList *l;
2179 MetaDisplay *display = window->display;
2180 MetaPingData *ping_data;
2181 unsigned int check_alive_timeout;
2182
2183 check_alive_timeout = meta_prefs_get_check_alive_timeout ();
2184 if (check_alive_timeout == 0)
2185 return;
2186
2187 if (serial == 0)
2188 {
2189 meta_warning ("Tried to ping window %s with a bad serial! Not allowed.",
2190 window->desc);
2191 return;
2192 }
2193
2194 if (!meta_window_can_ping (window))
2195 return;
2196
2197 for (l = display->pending_pings; l; l = l->next)
2198 {
2199 MetaPingData *ping_data = l->data;
2200
2201 if (window == ping_data->window)
2202 {
2203 meta_topic (META_DEBUG_PING,
2204 "Window %s already is being pinged with serial %u",
2205 window->desc, ping_data->serial);
2206 return;
2207 }
2208
2209 if (serial == ping_data->serial)
2210 {
2211 meta_warning ("Ping serial %u was reused for window %s, "
2212 "previous use was for window %s.",
2213 serial, window->desc, ping_data->window->desc);
2214 return;
2215 }
2216 }
2217
2218 ping_data = g_new (MetaPingData, 1);
2219 ping_data->window = window;
2220 ping_data->serial = serial;
2221 ping_data->ping_timeout_id =
2222 g_timeout_add (check_alive_timeout,
2223 meta_display_ping_timeout,
2224 ping_data);
2225 g_source_set_name_by_id (ping_data->ping_timeout_id, "[mutter] meta_display_ping_timeout");
2226
2227 display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
2228
2229 meta_topic (META_DEBUG_PING,
2230 "Sending ping with serial %u to window %s",
2231 serial, window->desc);
2232
2233 META_WINDOW_GET_CLASS (window)->ping (window, serial);
2234 }
2235
2236 /**
2237 * meta_display_pong_for_serial:
2238 * @display: the display we got the pong from
2239 * @serial: the serial in the pong response
2240 *
2241 * Process the pong (the response message) from the ping we sent
2242 * to the window. This involves removing the timeout, calling the
2243 * reply handler function, and freeing memory.
2244 */
2245 void
meta_display_pong_for_serial(MetaDisplay * display,guint32 serial)2246 meta_display_pong_for_serial (MetaDisplay *display,
2247 guint32 serial)
2248 {
2249 GSList *tmp;
2250
2251 meta_topic (META_DEBUG_PING, "Received a pong with serial %u", serial);
2252
2253 for (tmp = display->pending_pings; tmp; tmp = tmp->next)
2254 {
2255 MetaPingData *ping_data = tmp->data;
2256
2257 if (serial == ping_data->serial)
2258 {
2259 meta_topic (META_DEBUG_PING,
2260 "Matching ping found for pong %u",
2261 ping_data->serial);
2262
2263 /* Remove the ping data from the list */
2264 display->pending_pings = g_slist_remove (display->pending_pings,
2265 ping_data);
2266
2267 /* Remove the timeout */
2268 g_clear_handle_id (&ping_data->ping_timeout_id, g_source_remove);
2269
2270 meta_window_set_alive (ping_data->window, TRUE);
2271 ping_data_free (ping_data);
2272 break;
2273 }
2274 }
2275 }
2276
2277 static MetaGroup *
get_focused_group(MetaDisplay * display)2278 get_focused_group (MetaDisplay *display)
2279 {
2280 if (display->focus_window)
2281 return display->focus_window->group;
2282 else
2283 return NULL;
2284 }
2285
2286 #define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
2287 || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
2288 || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focused_group (w->display))) \
2289 || ((t) == META_TAB_LIST_NORMAL_ALL && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w)))
2290
2291 static MetaWindow*
find_tab_forward(MetaDisplay * display,MetaTabList type,MetaWorkspace * workspace,GList * start,gboolean skip_first)2292 find_tab_forward (MetaDisplay *display,
2293 MetaTabList type,
2294 MetaWorkspace *workspace,
2295 GList *start,
2296 gboolean skip_first)
2297 {
2298 GList *tmp;
2299
2300 g_return_val_if_fail (start != NULL, NULL);
2301 g_return_val_if_fail (workspace != NULL, NULL);
2302
2303 tmp = start;
2304 if (skip_first)
2305 tmp = tmp->next;
2306
2307 while (tmp != NULL)
2308 {
2309 MetaWindow *window = tmp->data;
2310
2311 if (IN_TAB_CHAIN (window, type))
2312 return window;
2313
2314 tmp = tmp->next;
2315 }
2316
2317 tmp = workspace->mru_list;
2318 while (tmp != start)
2319 {
2320 MetaWindow *window = tmp->data;
2321
2322 if (IN_TAB_CHAIN (window, type))
2323 return window;
2324
2325 tmp = tmp->next;
2326 }
2327
2328 return NULL;
2329 }
2330
2331 static MetaWindow*
find_tab_backward(MetaDisplay * display,MetaTabList type,MetaWorkspace * workspace,GList * start,gboolean skip_last)2332 find_tab_backward (MetaDisplay *display,
2333 MetaTabList type,
2334 MetaWorkspace *workspace,
2335 GList *start,
2336 gboolean skip_last)
2337 {
2338 GList *tmp;
2339
2340 g_return_val_if_fail (start != NULL, NULL);
2341 g_return_val_if_fail (workspace != NULL, NULL);
2342
2343 tmp = start;
2344 if (skip_last)
2345 tmp = tmp->prev;
2346 while (tmp != NULL)
2347 {
2348 MetaWindow *window = tmp->data;
2349
2350 if (IN_TAB_CHAIN (window, type))
2351 return window;
2352
2353 tmp = tmp->prev;
2354 }
2355
2356 tmp = g_list_last (workspace->mru_list);
2357 while (tmp != start)
2358 {
2359 MetaWindow *window = tmp->data;
2360
2361 if (IN_TAB_CHAIN (window, type))
2362 return window;
2363
2364 tmp = tmp->prev;
2365 }
2366
2367 return NULL;
2368 }
2369
2370 static int
mru_cmp(gconstpointer a,gconstpointer b)2371 mru_cmp (gconstpointer a,
2372 gconstpointer b)
2373 {
2374 guint32 time_a, time_b;
2375
2376 time_a = meta_window_get_user_time ((MetaWindow *)a);
2377 time_b = meta_window_get_user_time ((MetaWindow *)b);
2378
2379 if (time_a > time_b)
2380 return -1;
2381 else if (time_a < time_b)
2382 return 1;
2383 else
2384 return 0;
2385 }
2386
2387 /**
2388 * meta_display_get_tab_list:
2389 * @display: a #MetaDisplay
2390 * @type: type of tab list
2391 * @workspace: (nullable): origin workspace
2392 *
2393 * Determine the list of windows that should be displayed for Alt-TAB
2394 * functionality. The windows are returned in most recently used order.
2395 * If @workspace is not %NULL, the list only contains windows that are on
2396 * @workspace or have the demands-attention hint set; otherwise it contains
2397 * all windows.
2398 *
2399 * Returns: (transfer container) (element-type Meta.Window): List of windows
2400 */
2401 GList*
meta_display_get_tab_list(MetaDisplay * display,MetaTabList type,MetaWorkspace * workspace)2402 meta_display_get_tab_list (MetaDisplay *display,
2403 MetaTabList type,
2404 MetaWorkspace *workspace)
2405 {
2406 GList *tab_list = NULL;
2407 GList *global_mru_list = NULL;
2408 GList *mru_list, *tmp;
2409 GSList *windows = meta_display_list_windows (display, META_LIST_DEFAULT);
2410 GSList *w;
2411
2412 if (workspace == NULL)
2413 {
2414 /* Yay for mixing GList and GSList in the API */
2415 for (w = windows; w; w = w->next)
2416 global_mru_list = g_list_prepend (global_mru_list, w->data);
2417 global_mru_list = g_list_sort (global_mru_list, mru_cmp);
2418 }
2419
2420 mru_list = workspace ? workspace->mru_list : global_mru_list;
2421
2422 /* Windows sellout mode - MRU order. Collect unminimized windows
2423 * then minimized so minimized windows aren't in the way so much.
2424 */
2425 for (tmp = mru_list; tmp; tmp = tmp->next)
2426 {
2427 MetaWindow *window = tmp->data;
2428
2429 if (!window->minimized && IN_TAB_CHAIN (window, type))
2430 tab_list = g_list_prepend (tab_list, window);
2431 }
2432
2433 for (tmp = mru_list; tmp; tmp = tmp->next)
2434 {
2435 MetaWindow *window = tmp->data;
2436
2437 if (window->minimized && IN_TAB_CHAIN (window, type))
2438 tab_list = g_list_prepend (tab_list, window);
2439 }
2440
2441 tab_list = g_list_reverse (tab_list);
2442
2443 /* If filtering by workspace, include windows from
2444 * other workspaces that demand attention
2445 */
2446 if (workspace)
2447 for (w = windows; w; w = w->next)
2448 {
2449 MetaWindow *l_window = w->data;
2450
2451 if (l_window->wm_state_demands_attention &&
2452 !meta_window_located_on_workspace (l_window, workspace) &&
2453 IN_TAB_CHAIN (l_window, type))
2454 tab_list = g_list_prepend (tab_list, l_window);
2455 }
2456
2457 g_list_free (global_mru_list);
2458 g_slist_free (windows);
2459
2460 return tab_list;
2461 }
2462
2463 /**
2464 * meta_display_get_tab_next:
2465 * @display: a #MetaDisplay
2466 * @type: type of tab list
2467 * @workspace: origin workspace
2468 * @window: (nullable): starting window
2469 * @backward: If %TRUE, look for the previous window.
2470 *
2471 * Determine the next window that should be displayed for Alt-TAB
2472 * functionality.
2473 *
2474 * Returns: (transfer none): Next window
2475 *
2476 */
2477 MetaWindow*
meta_display_get_tab_next(MetaDisplay * display,MetaTabList type,MetaWorkspace * workspace,MetaWindow * window,gboolean backward)2478 meta_display_get_tab_next (MetaDisplay *display,
2479 MetaTabList type,
2480 MetaWorkspace *workspace,
2481 MetaWindow *window,
2482 gboolean backward)
2483 {
2484 gboolean skip;
2485 GList *tab_list;
2486 MetaWindow *ret;
2487 tab_list = meta_display_get_tab_list (display, type, workspace);
2488
2489 if (tab_list == NULL)
2490 return NULL;
2491
2492 if (window != NULL)
2493 {
2494 g_assert (window->display == display);
2495
2496 if (backward)
2497 ret = find_tab_backward (display, type, workspace, g_list_find (tab_list, window), TRUE);
2498 else
2499 ret = find_tab_forward (display, type, workspace, g_list_find (tab_list, window), TRUE);
2500 }
2501 else
2502 {
2503 skip = display->focus_window != NULL &&
2504 tab_list->data == display->focus_window;
2505 if (backward)
2506 ret = find_tab_backward (display, type, workspace, tab_list, skip);
2507 else
2508 ret = find_tab_forward (display, type, workspace, tab_list, skip);
2509 }
2510
2511 g_list_free (tab_list);
2512 return ret;
2513 }
2514
2515 /**
2516 * meta_display_get_tab_current:
2517 * @display: a #MetaDisplay
2518 * @type: type of tab list
2519 * @workspace: origin workspace
2520 *
2521 * Determine the active window that should be displayed for Alt-TAB.
2522 *
2523 * Returns: (transfer none): Current window
2524 *
2525 */
2526 MetaWindow*
meta_display_get_tab_current(MetaDisplay * display,MetaTabList type,MetaWorkspace * workspace)2527 meta_display_get_tab_current (MetaDisplay *display,
2528 MetaTabList type,
2529 MetaWorkspace *workspace)
2530 {
2531 MetaWindow *window;
2532
2533 window = display->focus_window;
2534
2535 if (window != NULL &&
2536 IN_TAB_CHAIN (window, type) &&
2537 (workspace == NULL ||
2538 meta_window_located_on_workspace (window, workspace)))
2539 return window;
2540 else
2541 return NULL;
2542 }
2543
2544 MetaGravity
meta_resize_gravity_from_grab_op(MetaGrabOp op)2545 meta_resize_gravity_from_grab_op (MetaGrabOp op)
2546 {
2547 MetaGravity gravity;
2548
2549 gravity = -1;
2550 switch (op)
2551 {
2552 case META_GRAB_OP_RESIZING_SE:
2553 case META_GRAB_OP_KEYBOARD_RESIZING_SE:
2554 gravity = META_GRAVITY_NORTH_WEST;
2555 break;
2556 case META_GRAB_OP_KEYBOARD_RESIZING_S:
2557 case META_GRAB_OP_RESIZING_S:
2558 gravity = META_GRAVITY_NORTH;
2559 break;
2560 case META_GRAB_OP_KEYBOARD_RESIZING_SW:
2561 case META_GRAB_OP_RESIZING_SW:
2562 gravity = META_GRAVITY_NORTH_EAST;
2563 break;
2564 case META_GRAB_OP_KEYBOARD_RESIZING_N:
2565 case META_GRAB_OP_RESIZING_N:
2566 gravity = META_GRAVITY_SOUTH;
2567 break;
2568 case META_GRAB_OP_KEYBOARD_RESIZING_NE:
2569 case META_GRAB_OP_RESIZING_NE:
2570 gravity = META_GRAVITY_SOUTH_WEST;
2571 break;
2572 case META_GRAB_OP_KEYBOARD_RESIZING_NW:
2573 case META_GRAB_OP_RESIZING_NW:
2574 gravity = META_GRAVITY_SOUTH_EAST;
2575 break;
2576 case META_GRAB_OP_KEYBOARD_RESIZING_E:
2577 case META_GRAB_OP_RESIZING_E:
2578 gravity = META_GRAVITY_WEST;
2579 break;
2580 case META_GRAB_OP_KEYBOARD_RESIZING_W:
2581 case META_GRAB_OP_RESIZING_W:
2582 gravity = META_GRAVITY_EAST;
2583 break;
2584 case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
2585 gravity = META_GRAVITY_CENTER;
2586 break;
2587 default:
2588 break;
2589 }
2590
2591 return gravity;
2592 }
2593
2594 void
meta_display_manage_all_xwindows(MetaDisplay * display)2595 meta_display_manage_all_xwindows (MetaDisplay *display)
2596 {
2597 guint64 *_children;
2598 guint64 *children;
2599 int n_children, i;
2600
2601 meta_stack_freeze (display->stack);
2602 meta_stack_tracker_get_stack (display->stack_tracker, &_children, &n_children);
2603
2604 /* Copy the stack as it will be modified as part of the loop */
2605 children = g_memdup2 (_children, sizeof (uint64_t) * n_children);
2606
2607 for (i = 0; i < n_children; ++i)
2608 {
2609 if (!META_STACK_ID_IS_X11 (children[i]))
2610 continue;
2611 meta_window_x11_new (display, children[i], TRUE,
2612 META_COMP_EFFECT_NONE);
2613 }
2614
2615 g_free (children);
2616 meta_stack_thaw (display->stack);
2617 }
2618
2619 void
meta_display_unmanage_windows(MetaDisplay * display,guint32 timestamp)2620 meta_display_unmanage_windows (MetaDisplay *display,
2621 guint32 timestamp)
2622 {
2623 GSList *tmp;
2624 GSList *winlist;
2625
2626 winlist = meta_display_list_windows (display,
2627 META_LIST_INCLUDE_OVERRIDE_REDIRECT);
2628 winlist = g_slist_sort (winlist, meta_display_stack_cmp);
2629 g_slist_foreach (winlist, (GFunc)g_object_ref, NULL);
2630
2631 /* Unmanage all windows */
2632 tmp = winlist;
2633 while (tmp != NULL)
2634 {
2635 MetaWindow *window = tmp->data;
2636
2637 /* Check if already unmanaged for safety - in particular, catch
2638 * the case where unmanaging a parent window can cause attached
2639 * dialogs to be (temporarily) unmanaged.
2640 */
2641 if (!window->unmanaging)
2642 meta_window_unmanage (window, timestamp);
2643 g_object_unref (window);
2644
2645 tmp = tmp->next;
2646 }
2647 g_slist_free (winlist);
2648 }
2649
2650 int
meta_display_stack_cmp(const void * a,const void * b)2651 meta_display_stack_cmp (const void *a,
2652 const void *b)
2653 {
2654 MetaWindow *aw = (void*) a;
2655 MetaWindow *bw = (void*) b;
2656
2657 return meta_stack_windows_cmp (aw->display->stack, aw, bw);
2658 }
2659
2660 /**
2661 * meta_display_sort_windows_by_stacking:
2662 * @display: a #MetaDisplay
2663 * @windows: (element-type MetaWindow): Set of windows
2664 *
2665 * Sorts a set of windows according to their current stacking order. If windows
2666 * from multiple screens are present in the set of input windows, then all the
2667 * windows on screen 0 are sorted below all the windows on screen 1, and so forth.
2668 * Since the stacking order of override-redirect windows isn't controlled by
2669 * Metacity, if override-redirect windows are in the input, the result may not
2670 * correspond to the actual stacking order in the X server.
2671 *
2672 * An example of using this would be to sort the list of transient dialogs for a
2673 * window into their current stacking order.
2674 *
2675 * Returns: (transfer container) (element-type MetaWindow): Input windows sorted by stacking order, from lowest to highest
2676 */
2677 GSList *
meta_display_sort_windows_by_stacking(MetaDisplay * display,GSList * windows)2678 meta_display_sort_windows_by_stacking (MetaDisplay *display,
2679 GSList *windows)
2680 {
2681 GSList *copy = g_slist_copy (windows);
2682
2683 copy = g_slist_sort (copy, meta_display_stack_cmp);
2684
2685 return copy;
2686 }
2687
2688 static void
prefs_changed_callback(MetaPreference pref,void * data)2689 prefs_changed_callback (MetaPreference pref,
2690 void *data)
2691 {
2692 MetaDisplay *display = data;
2693
2694 switch (pref)
2695 {
2696 case META_PREF_DRAGGABLE_BORDER_WIDTH:
2697 meta_display_queue_retheme_all_windows (display);
2698 break;
2699 case META_PREF_CURSOR_THEME:
2700 case META_PREF_CURSOR_SIZE:
2701 meta_display_reload_cursor (display);
2702 break;
2703 default:
2704 break;
2705 }
2706 }
2707
2708 void
meta_display_sanity_check_timestamps(MetaDisplay * display,guint32 timestamp)2709 meta_display_sanity_check_timestamps (MetaDisplay *display,
2710 guint32 timestamp)
2711 {
2712 if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
2713 {
2714 meta_warning ("last_focus_time (%u) is greater than comparison "
2715 "timestamp (%u). This most likely represents a buggy "
2716 "client sending inaccurate timestamps in messages such as "
2717 "_NET_ACTIVE_WINDOW. Trying to work around...",
2718 display->last_focus_time, timestamp);
2719 display->last_focus_time = timestamp;
2720 }
2721 if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
2722 {
2723 GSList *windows;
2724 GSList *tmp;
2725
2726 meta_warning ("last_user_time (%u) is greater than comparison "
2727 "timestamp (%u). This most likely represents a buggy "
2728 "client sending inaccurate timestamps in messages such as "
2729 "_NET_ACTIVE_WINDOW. Trying to work around...",
2730 display->last_user_time, timestamp);
2731 display->last_user_time = timestamp;
2732
2733 windows = meta_display_list_windows (display, META_LIST_DEFAULT);
2734 tmp = windows;
2735 while (tmp != NULL)
2736 {
2737 MetaWindow *window = tmp->data;
2738
2739 if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))
2740 {
2741 meta_warning ("%s appears to be one of the offending windows "
2742 "with a timestamp of %u. Working around...",
2743 window->desc, window->net_wm_user_time);
2744 meta_window_set_user_time (window, timestamp);
2745 }
2746
2747 tmp = tmp->next;
2748 }
2749
2750 g_slist_free (windows);
2751 }
2752 }
2753
2754 void
meta_display_remove_autoraise_callback(MetaDisplay * display)2755 meta_display_remove_autoraise_callback (MetaDisplay *display)
2756 {
2757 g_clear_handle_id (&display->autoraise_timeout_id, g_source_remove);
2758 display->autoraise_window = NULL;
2759 }
2760
2761 void
meta_display_overlay_key_activate(MetaDisplay * display)2762 meta_display_overlay_key_activate (MetaDisplay *display)
2763 {
2764 g_signal_emit (display, display_signals[OVERLAY_KEY], 0);
2765 }
2766
2767 void
meta_display_accelerator_activate(MetaDisplay * display,guint action,ClutterKeyEvent * event)2768 meta_display_accelerator_activate (MetaDisplay *display,
2769 guint action,
2770 ClutterKeyEvent *event)
2771 {
2772 g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED], 0,
2773 action,
2774 clutter_event_get_source_device ((ClutterEvent *) event),
2775 event->time);
2776 }
2777
2778 gboolean
meta_display_modifiers_accelerator_activate(MetaDisplay * display)2779 meta_display_modifiers_accelerator_activate (MetaDisplay *display)
2780 {
2781 gboolean freeze;
2782
2783 g_signal_emit (display, display_signals[MODIFIERS_ACCELERATOR_ACTIVATED], 0, &freeze);
2784
2785 return freeze;
2786 }
2787
2788 /**
2789 * meta_display_supports_extended_barriers:
2790 * @display: a #MetaDisplay
2791 *
2792 * Returns: whether pointer barriers can be supported.
2793 *
2794 * When running as an X compositor the X server needs XInput 2
2795 * version 2.3. When running as a display server it is supported
2796 * when running on the native backend.
2797 *
2798 * Clients should use this method to determine whether their
2799 * interfaces should depend on new barrier features.
2800 */
2801 gboolean
meta_display_supports_extended_barriers(MetaDisplay * display)2802 meta_display_supports_extended_barriers (MetaDisplay *display)
2803 {
2804 #ifdef HAVE_NATIVE_BACKEND
2805 if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
2806 return TRUE;
2807 #endif
2808
2809 if (META_IS_BACKEND_X11_CM (meta_get_backend ()))
2810 {
2811 if (meta_is_wayland_compositor())
2812 return FALSE;
2813
2814 return META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display);
2815 }
2816
2817 return FALSE;
2818 }
2819
2820 /**
2821 * meta_display_get_context:
2822 * @display: a #MetaDisplay
2823 *
2824 * Returns: (transfer none): the #MetaContext
2825 */
2826 MetaContext *
meta_display_get_context(MetaDisplay * display)2827 meta_display_get_context (MetaDisplay *display)
2828 {
2829 MetaDisplayPrivate *priv = meta_display_get_instance_private (display);
2830
2831 return priv->context;
2832 }
2833
2834 /**
2835 * meta_display_get_compositor: (skip)
2836 * @display: a #MetaDisplay
2837 *
2838 */
2839 MetaCompositor *
meta_display_get_compositor(MetaDisplay * display)2840 meta_display_get_compositor (MetaDisplay *display)
2841 {
2842 return display->compositor;
2843 }
2844
2845 /**
2846 * meta_display_get_x11_display: (skip)
2847 * @display: a #MetaDisplay
2848 *
2849 */
2850 MetaX11Display *
meta_display_get_x11_display(MetaDisplay * display)2851 meta_display_get_x11_display (MetaDisplay *display)
2852 {
2853 return display->x11_display;
2854 }
2855
2856 /**
2857 * meta_display_get_size:
2858 * @display: A #MetaDisplay
2859 * @width: (out): The width of the screen
2860 * @height: (out): The height of the screen
2861 *
2862 * Retrieve the size of the display.
2863 */
2864 void
meta_display_get_size(MetaDisplay * display,int * width,int * height)2865 meta_display_get_size (MetaDisplay *display,
2866 int *width,
2867 int *height)
2868 {
2869 MetaBackend *backend = meta_get_backend ();
2870 MetaMonitorManager *monitor_manager =
2871 meta_backend_get_monitor_manager (backend);
2872 int display_width, display_height;
2873
2874 meta_monitor_manager_get_screen_size (monitor_manager,
2875 &display_width,
2876 &display_height);
2877
2878 if (width != NULL)
2879 *width = display_width;
2880
2881 if (height != NULL)
2882 *height = display_height;
2883 }
2884
2885 /**
2886 * meta_display_get_focus_window:
2887 * @display: a #MetaDisplay
2888 *
2889 * Get our best guess as to the "currently" focused window (that is,
2890 * the window that we expect will be focused at the point when the X
2891 * server processes our next request).
2892 *
2893 * Return Value: (transfer none): The current focus window
2894 */
2895 MetaWindow *
meta_display_get_focus_window(MetaDisplay * display)2896 meta_display_get_focus_window (MetaDisplay *display)
2897 {
2898 return display->focus_window;
2899 }
2900
2901 /**
2902 * meta_display_clear_mouse_mode:
2903 * @display: a #MetaDisplay
2904 *
2905 * Sets the mouse-mode flag to %FALSE, which means that motion events are
2906 * no longer ignored in mouse or sloppy focus.
2907 * This is an internal function. It should be used only for reimplementing
2908 * keybindings, and only in a manner compatible with core code.
2909 */
2910 void
meta_display_clear_mouse_mode(MetaDisplay * display)2911 meta_display_clear_mouse_mode (MetaDisplay *display)
2912 {
2913 display->mouse_mode = FALSE;
2914 }
2915
2916 MetaGestureTracker *
meta_display_get_gesture_tracker(MetaDisplay * display)2917 meta_display_get_gesture_tracker (MetaDisplay *display)
2918 {
2919 return display->gesture_tracker;
2920 }
2921
2922 gboolean
meta_display_show_restart_message(MetaDisplay * display,const char * message)2923 meta_display_show_restart_message (MetaDisplay *display,
2924 const char *message)
2925 {
2926 gboolean result = FALSE;
2927
2928 g_signal_emit (display,
2929 display_signals[SHOW_RESTART_MESSAGE], 0,
2930 message, &result);
2931
2932 return result;
2933 }
2934
2935 gboolean
meta_display_request_restart(MetaDisplay * display)2936 meta_display_request_restart (MetaDisplay *display)
2937 {
2938 gboolean result = FALSE;
2939
2940 g_signal_emit (display,
2941 display_signals[RESTART], 0,
2942 &result);
2943
2944 return result;
2945 }
2946
2947 gboolean
meta_display_show_resize_popup(MetaDisplay * display,gboolean show,MetaRectangle * rect,int display_w,int display_h)2948 meta_display_show_resize_popup (MetaDisplay *display,
2949 gboolean show,
2950 MetaRectangle *rect,
2951 int display_w,
2952 int display_h)
2953 {
2954 gboolean result = FALSE;
2955
2956 g_signal_emit (display,
2957 display_signals[SHOW_RESIZE_POPUP], 0,
2958 show, rect, display_w, display_h, &result);
2959
2960 return result;
2961 }
2962
2963 /**
2964 * meta_display_is_pointer_emulating_sequence:
2965 * @display: the display
2966 * @sequence: (nullable): a #ClutterEventSequence
2967 *
2968 * Tells whether the event sequence is the used for pointer emulation
2969 * and single-touch interaction.
2970 *
2971 * Returns: #TRUE if the sequence emulates pointer behavior
2972 **/
2973 gboolean
meta_display_is_pointer_emulating_sequence(MetaDisplay * display,ClutterEventSequence * sequence)2974 meta_display_is_pointer_emulating_sequence (MetaDisplay *display,
2975 ClutterEventSequence *sequence)
2976 {
2977 if (!sequence)
2978 return FALSE;
2979
2980 return display->pointer_emulating_sequence == sequence;
2981 }
2982
2983 void
meta_display_request_pad_osd(MetaDisplay * display,ClutterInputDevice * pad,gboolean edition_mode)2984 meta_display_request_pad_osd (MetaDisplay *display,
2985 ClutterInputDevice *pad,
2986 gboolean edition_mode)
2987 {
2988 MetaBackend *backend = meta_get_backend ();
2989 MetaInputMapper *input_mapper;
2990 const gchar *layout_path = NULL;
2991 ClutterActor *osd;
2992 MetaLogicalMonitor *logical_monitor;
2993 GSettings *settings;
2994 #ifdef HAVE_LIBWACOM
2995 WacomDevice *wacom_device;
2996 #endif
2997
2998 /* Avoid emitting the signal while there is an OSD being currently
2999 * displayed, the first OSD will have to be dismissed before showing
3000 * any other one.
3001 */
3002 if (display->current_pad_osd)
3003 return;
3004
3005 input_mapper = meta_backend_get_input_mapper (meta_get_backend ());
3006
3007 if (input_mapper)
3008 {
3009 settings = meta_input_mapper_get_tablet_settings (input_mapper, pad);
3010 logical_monitor =
3011 meta_input_mapper_get_device_logical_monitor (input_mapper, pad);
3012 #ifdef HAVE_LIBWACOM
3013 wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad));
3014 layout_path = libwacom_get_layout_filename (wacom_device);
3015 #endif
3016 }
3017
3018 if (!layout_path || !settings)
3019 return;
3020
3021 if (!logical_monitor)
3022 logical_monitor = meta_backend_get_current_logical_monitor (backend);
3023
3024 g_signal_emit (display, display_signals[SHOW_PAD_OSD], 0,
3025 pad, settings, layout_path,
3026 edition_mode, logical_monitor->number, &osd);
3027
3028 if (osd)
3029 {
3030 display->current_pad_osd = osd;
3031 g_object_add_weak_pointer (G_OBJECT (display->current_pad_osd),
3032 (gpointer *) &display->current_pad_osd);
3033 }
3034 }
3035
3036 gchar *
meta_display_get_pad_action_label(MetaDisplay * display,ClutterInputDevice * pad,MetaPadActionType action_type,guint action_number)3037 meta_display_get_pad_action_label (MetaDisplay *display,
3038 ClutterInputDevice *pad,
3039 MetaPadActionType action_type,
3040 guint action_number)
3041 {
3042 gchar *label;
3043
3044 /* First, lookup the action, as imposed by settings */
3045 label = meta_pad_action_mapper_get_action_label (display->pad_action_mapper,
3046 pad, action_type,
3047 action_number);
3048 if (label)
3049 return label;
3050
3051 #ifdef HAVE_WAYLAND
3052 /* Second, if this wayland, lookup the actions set by the clients */
3053 if (meta_is_wayland_compositor ())
3054 {
3055 MetaWaylandCompositor *compositor;
3056 MetaWaylandTabletSeat *tablet_seat;
3057 MetaWaylandTabletPad *tablet_pad = NULL;
3058
3059 compositor = meta_wayland_compositor_get_default ();
3060 tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager,
3061 compositor->seat);
3062 if (tablet_seat)
3063 tablet_pad = meta_wayland_tablet_seat_lookup_pad (tablet_seat, pad);
3064
3065 if (tablet_pad)
3066 {
3067 label = meta_wayland_tablet_pad_get_label (tablet_pad, action_type,
3068 action_number);
3069 }
3070
3071 if (label)
3072 return label;
3073 }
3074 #endif
3075
3076 return NULL;
3077 }
3078
3079 static void
meta_display_show_osd(MetaDisplay * display,gint monitor_idx,const gchar * icon_name,const gchar * message)3080 meta_display_show_osd (MetaDisplay *display,
3081 gint monitor_idx,
3082 const gchar *icon_name,
3083 const gchar *message)
3084 {
3085 g_signal_emit (display, display_signals[SHOW_OSD], 0,
3086 monitor_idx, icon_name, message);
3087 }
3088
3089 static gint
lookup_tablet_monitor(MetaDisplay * display,ClutterInputDevice * device)3090 lookup_tablet_monitor (MetaDisplay *display,
3091 ClutterInputDevice *device)
3092 {
3093 MetaInputMapper *input_mapper;
3094 MetaLogicalMonitor *monitor;
3095 gint monitor_idx = -1;
3096
3097 input_mapper = meta_backend_get_input_mapper (meta_get_backend ());
3098 if (!input_mapper)
3099 return -1;
3100
3101 monitor = meta_input_mapper_get_device_logical_monitor (input_mapper, device);
3102
3103 if (monitor)
3104 {
3105 monitor_idx = meta_display_get_monitor_index_for_rect (display,
3106 &monitor->rect);
3107 }
3108
3109 return monitor_idx;
3110 }
3111
3112 void
meta_display_show_tablet_mapping_notification(MetaDisplay * display,ClutterInputDevice * pad,const gchar * pretty_name)3113 meta_display_show_tablet_mapping_notification (MetaDisplay *display,
3114 ClutterInputDevice *pad,
3115 const gchar *pretty_name)
3116 {
3117 if (!pretty_name)
3118 pretty_name = clutter_input_device_get_device_name (pad);
3119 meta_display_show_osd (display, lookup_tablet_monitor (display, pad),
3120 "input-tablet-symbolic", pretty_name);
3121 }
3122
3123 void
meta_display_notify_pad_group_switch(MetaDisplay * display,ClutterInputDevice * pad,const gchar * pretty_name,guint n_group,guint n_mode,guint n_modes)3124 meta_display_notify_pad_group_switch (MetaDisplay *display,
3125 ClutterInputDevice *pad,
3126 const gchar *pretty_name,
3127 guint n_group,
3128 guint n_mode,
3129 guint n_modes)
3130 {
3131 GString *message;
3132 guint i;
3133
3134 if (!pretty_name)
3135 pretty_name = clutter_input_device_get_device_name (pad);
3136
3137 message = g_string_new (pretty_name);
3138 g_string_append (message, "\n\n");
3139 for (i = 0; i < n_modes; i++)
3140 {
3141 if (i > 0)
3142 g_string_append_c (message, ' ');
3143 g_string_append (message, (i == n_mode) ? "●" : "○");
3144 }
3145
3146 meta_display_show_osd (display, lookup_tablet_monitor (display, pad),
3147 "input-tablet-symbolic", message->str);
3148
3149 g_signal_emit (display, display_signals[PAD_MODE_SWITCH], 0, pad,
3150 n_group, n_mode);
3151
3152 g_string_free (message, TRUE);
3153 }
3154
3155 void
meta_display_foreach_window(MetaDisplay * display,MetaListWindowsFlags flags,MetaDisplayWindowFunc func,gpointer data)3156 meta_display_foreach_window (MetaDisplay *display,
3157 MetaListWindowsFlags flags,
3158 MetaDisplayWindowFunc func,
3159 gpointer data)
3160 {
3161 GSList *windows;
3162
3163 /* If we end up doing this often, just keeping a list
3164 * of windows might be sensible.
3165 */
3166
3167 windows = meta_display_list_windows (display, flags);
3168
3169 g_slist_foreach (windows, (GFunc) func, data);
3170
3171 g_slist_free (windows);
3172 }
3173
3174 static void
meta_display_resize_func(MetaWindow * window,gpointer user_data)3175 meta_display_resize_func (MetaWindow *window,
3176 gpointer user_data)
3177 {
3178 if (window->struts)
3179 {
3180 meta_window_update_struts (window);
3181 }
3182 meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
3183
3184 meta_window_recalc_features (window);
3185 }
3186
3187 static void
on_monitors_changed_internal(MetaMonitorManager * monitor_manager,MetaDisplay * display)3188 on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
3189 MetaDisplay *display)
3190 {
3191 meta_workspace_manager_reload_work_areas (display->workspace_manager);
3192
3193 /* Fix up monitor for all windows on this display */
3194 meta_display_foreach_window (display, META_LIST_INCLUDE_OVERRIDE_REDIRECT,
3195 (MetaDisplayWindowFunc)
3196 meta_window_update_for_monitors_changed, 0);
3197
3198 /* Queue a resize on all the windows */
3199 meta_display_foreach_window (display, META_LIST_DEFAULT,
3200 meta_display_resize_func, 0);
3201
3202 meta_display_queue_check_fullscreen (display);
3203 }
3204
3205 void
meta_display_restacked(MetaDisplay * display)3206 meta_display_restacked (MetaDisplay *display)
3207 {
3208 g_signal_emit (display, display_signals[RESTACKED], 0);
3209 }
3210
3211 static gboolean
meta_display_update_tile_preview_timeout(gpointer data)3212 meta_display_update_tile_preview_timeout (gpointer data)
3213 {
3214 MetaDisplay *display = data;
3215 MetaWindow *window = display->grab_window;
3216 gboolean needs_preview = FALSE;
3217
3218 display->tile_preview_timeout_id = 0;
3219
3220 if (window)
3221 {
3222 switch (display->preview_tile_mode)
3223 {
3224 case META_TILE_LEFT:
3225 case META_TILE_RIGHT:
3226 if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
3227 needs_preview = TRUE;
3228 break;
3229
3230 case META_TILE_MAXIMIZED:
3231 if (!META_WINDOW_MAXIMIZED (window))
3232 needs_preview = TRUE;
3233 break;
3234
3235 default:
3236 needs_preview = FALSE;
3237 break;
3238 }
3239 }
3240
3241 if (needs_preview)
3242 {
3243 MetaRectangle tile_rect;
3244 int monitor;
3245
3246 monitor = meta_window_get_current_tile_monitor_number (window);
3247 meta_window_get_tile_area (window, display->preview_tile_mode,
3248 &tile_rect);
3249 meta_compositor_show_tile_preview (display->compositor,
3250 window, &tile_rect, monitor);
3251 }
3252 else
3253 meta_compositor_hide_tile_preview (display->compositor);
3254
3255 return FALSE;
3256 }
3257
3258 #define TILE_PREVIEW_TIMEOUT_MS 200
3259
3260 void
meta_display_update_tile_preview(MetaDisplay * display,gboolean delay)3261 meta_display_update_tile_preview (MetaDisplay *display,
3262 gboolean delay)
3263 {
3264 if (delay)
3265 {
3266 if (display->tile_preview_timeout_id > 0)
3267 return;
3268
3269 display->tile_preview_timeout_id =
3270 g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
3271 meta_display_update_tile_preview_timeout,
3272 display);
3273 g_source_set_name_by_id (display->tile_preview_timeout_id,
3274 "[mutter] meta_display_update_tile_preview_timeout");
3275 }
3276 else
3277 {
3278 g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove);
3279
3280 meta_display_update_tile_preview_timeout ((gpointer)display);
3281 }
3282 }
3283
3284 void
meta_display_hide_tile_preview(MetaDisplay * display)3285 meta_display_hide_tile_preview (MetaDisplay *display)
3286 {
3287 g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove);
3288
3289 display->preview_tile_mode = META_TILE_NONE;
3290 meta_compositor_hide_tile_preview (display->compositor);
3291 }
3292
3293 static MetaStartupSequence *
find_startup_sequence_by_wmclass(MetaDisplay * display,MetaWindow * window)3294 find_startup_sequence_by_wmclass (MetaDisplay *display,
3295 MetaWindow *window)
3296 {
3297 GSList *startup_sequences, *l;
3298
3299 startup_sequences =
3300 meta_startup_notification_get_sequences (display->startup_notification);
3301
3302 for (l = startup_sequences; l; l = l->next)
3303 {
3304 MetaStartupSequence *sequence = l->data;
3305 const char *wmclass;
3306
3307 wmclass = meta_startup_sequence_get_wmclass (sequence);
3308
3309 if (wmclass != NULL &&
3310 ((window->res_class &&
3311 strcmp (wmclass, window->res_class) == 0) ||
3312 (window->res_name &&
3313 strcmp (wmclass, window->res_name) == 0)))
3314 return sequence;
3315 }
3316
3317 return NULL;
3318 }
3319
3320 /* Sets the initial_timestamp and initial_workspace properties
3321 * of a window according to information given us by the
3322 * startup-notification library.
3323 *
3324 * Returns TRUE if startup properties have been applied, and
3325 * FALSE if they have not (for example, if they had already
3326 * been applied.)
3327 */
3328 gboolean
meta_display_apply_startup_properties(MetaDisplay * display,MetaWindow * window)3329 meta_display_apply_startup_properties (MetaDisplay *display,
3330 MetaWindow *window)
3331 {
3332 const char *startup_id;
3333 MetaStartupSequence *sequence = NULL;
3334
3335 /* Does the window have a startup ID stored? */
3336 startup_id = meta_window_get_startup_id (window);
3337
3338 meta_topic (META_DEBUG_STARTUP,
3339 "Applying startup props to %s id \"%s\"",
3340 window->desc,
3341 startup_id ? startup_id : "(none)");
3342
3343 if (!startup_id)
3344 {
3345 /* No startup ID stored for the window. Let's ask the
3346 * startup-notification library whether there's anything
3347 * stored for the resource name or resource class hints.
3348 */
3349 sequence = find_startup_sequence_by_wmclass (display, window);
3350
3351 if (sequence)
3352 {
3353 g_assert (window->startup_id == NULL);
3354 window->startup_id = g_strdup (meta_startup_sequence_get_id (sequence));
3355 startup_id = window->startup_id;
3356
3357 meta_topic (META_DEBUG_STARTUP,
3358 "Ending legacy sequence %s due to window %s",
3359 meta_startup_sequence_get_id (sequence),
3360 window->desc);
3361
3362 meta_startup_sequence_complete (sequence);
3363 }
3364 }
3365
3366 /* Still no startup ID? Bail. */
3367 if (!startup_id)
3368 return FALSE;
3369
3370 /* We might get this far and not know the sequence ID (if the window
3371 * already had a startup ID stored), so let's look for one if we don't
3372 * already know it.
3373 */
3374 if (sequence == NULL)
3375 {
3376 sequence =
3377 meta_startup_notification_lookup_sequence (display->startup_notification,
3378 startup_id);
3379 }
3380
3381 if (sequence != NULL)
3382 {
3383 gboolean changed_something = FALSE;
3384
3385 meta_topic (META_DEBUG_STARTUP,
3386 "Found startup sequence for window %s ID \"%s\"",
3387 window->desc, startup_id);
3388
3389 if (!window->initial_workspace_set)
3390 {
3391 int space = meta_startup_sequence_get_workspace (sequence);
3392 if (space >= 0)
3393 {
3394 meta_topic (META_DEBUG_STARTUP,
3395 "Setting initial window workspace to %d based on startup info",
3396 space);
3397
3398 window->initial_workspace_set = TRUE;
3399 window->initial_workspace = space;
3400 changed_something = TRUE;
3401 }
3402 }
3403
3404 if (!window->initial_timestamp_set)
3405 {
3406 guint32 timestamp = meta_startup_sequence_get_timestamp (sequence);
3407 meta_topic (META_DEBUG_STARTUP,
3408 "Setting initial window timestamp to %u based on startup info",
3409 timestamp);
3410
3411 window->initial_timestamp_set = TRUE;
3412 window->initial_timestamp = timestamp;
3413 changed_something = TRUE;
3414 }
3415
3416 return changed_something;
3417 }
3418 else
3419 {
3420 meta_topic (META_DEBUG_STARTUP,
3421 "Did not find startup sequence for window %s ID \"%s\"",
3422 window->desc, startup_id);
3423 }
3424
3425 return FALSE;
3426 }
3427
3428 static gboolean
set_work_area_later_func(MetaDisplay * display)3429 set_work_area_later_func (MetaDisplay *display)
3430 {
3431 meta_topic (META_DEBUG_WORKAREA,
3432 "Running work area hint computation function");
3433
3434 display->work_area_later = 0;
3435
3436 g_signal_emit (display, display_signals[WORKAREAS_CHANGED], 0);
3437
3438 return FALSE;
3439 }
3440
3441 void
meta_display_queue_workarea_recalc(MetaDisplay * display)3442 meta_display_queue_workarea_recalc (MetaDisplay *display)
3443 {
3444 /* Recompute work area later before redrawing */
3445 if (display->work_area_later == 0)
3446 {
3447 meta_topic (META_DEBUG_WORKAREA,
3448 "Adding work area hint computation function");
3449 display->work_area_later =
3450 meta_later_add (META_LATER_BEFORE_REDRAW,
3451 (GSourceFunc) set_work_area_later_func,
3452 display,
3453 NULL);
3454 }
3455 }
3456
3457 static gboolean
check_fullscreen_func(gpointer data)3458 check_fullscreen_func (gpointer data)
3459 {
3460 MetaDisplay *display = data;
3461 MetaBackend *backend = meta_get_backend ();
3462 MetaMonitorManager *monitor_manager =
3463 meta_backend_get_monitor_manager (backend);
3464 GList *logical_monitors, *l;
3465 MetaWindow *window;
3466 GSList *fullscreen_monitors = NULL;
3467 GSList *obscured_monitors = NULL;
3468 gboolean in_fullscreen_changed = FALSE;
3469
3470 display->check_fullscreen_later = 0;
3471
3472 logical_monitors =
3473 meta_monitor_manager_get_logical_monitors (monitor_manager);
3474
3475 /* We consider a monitor in fullscreen if it contains a fullscreen window;
3476 * however we make an exception for maximized windows above the fullscreen
3477 * one, as in that case window+chrome fully obscure the fullscreen window.
3478 */
3479 for (window = meta_stack_get_top (display->stack);
3480 window;
3481 window = meta_stack_get_below (display->stack, window, FALSE))
3482 {
3483 gboolean covers_monitors = FALSE;
3484
3485 if (window->hidden)
3486 continue;
3487
3488 if (window->fullscreen)
3489 {
3490 covers_monitors = TRUE;
3491 }
3492 else if (window->override_redirect)
3493 {
3494 /* We want to handle the case where an application is creating an
3495 * override-redirect window the size of the screen (monitor) and treat
3496 * it similarly to a fullscreen window, though it doesn't have fullscreen
3497 * window management behavior. (Being O-R, it's not managed at all.)
3498 */
3499 if (meta_window_is_monitor_sized (window))
3500 covers_monitors = TRUE;
3501 }
3502 else if (window->maximized_horizontally &&
3503 window->maximized_vertically)
3504 {
3505 MetaLogicalMonitor *logical_monitor;
3506
3507 logical_monitor = meta_window_get_main_logical_monitor (window);
3508 if (!g_slist_find (obscured_monitors, logical_monitor))
3509 obscured_monitors = g_slist_prepend (obscured_monitors,
3510 logical_monitor);
3511 }
3512
3513 if (covers_monitors)
3514 {
3515 MetaRectangle window_rect;
3516
3517 meta_window_get_frame_rect (window, &window_rect);
3518
3519 for (l = logical_monitors; l; l = l->next)
3520 {
3521 MetaLogicalMonitor *logical_monitor = l->data;
3522
3523 if (meta_rectangle_overlap (&window_rect,
3524 &logical_monitor->rect) &&
3525 !g_slist_find (fullscreen_monitors, logical_monitor) &&
3526 !g_slist_find (obscured_monitors, logical_monitor))
3527 fullscreen_monitors = g_slist_prepend (fullscreen_monitors,
3528 logical_monitor);
3529 }
3530 }
3531 }
3532
3533 g_slist_free (obscured_monitors);
3534
3535 for (l = logical_monitors; l; l = l->next)
3536 {
3537 MetaLogicalMonitor *logical_monitor = l->data;
3538 gboolean in_fullscreen;
3539
3540 in_fullscreen = g_slist_find (fullscreen_monitors,
3541 logical_monitor) != NULL;
3542 if (in_fullscreen != logical_monitor->in_fullscreen)
3543 {
3544 logical_monitor->in_fullscreen = in_fullscreen;
3545 in_fullscreen_changed = TRUE;
3546 }
3547 }
3548
3549 g_slist_free (fullscreen_monitors);
3550
3551 if (in_fullscreen_changed)
3552 {
3553 /* DOCK window stacking depends on the monitor's fullscreen
3554 status so we need to trigger a re-layering. */
3555 MetaWindow *window = meta_stack_get_top (display->stack);
3556 if (window)
3557 meta_stack_update_layer (display->stack, window);
3558
3559 g_signal_emit (display, display_signals[IN_FULLSCREEN_CHANGED], 0, NULL);
3560 }
3561
3562 return FALSE;
3563 }
3564
3565 void
meta_display_queue_check_fullscreen(MetaDisplay * display)3566 meta_display_queue_check_fullscreen (MetaDisplay *display)
3567 {
3568 if (!display->check_fullscreen_later)
3569 display->check_fullscreen_later = meta_later_add (META_LATER_CHECK_FULLSCREEN,
3570 check_fullscreen_func,
3571 display, NULL);
3572 }
3573
3574 int
meta_display_get_monitor_index_for_rect(MetaDisplay * display,MetaRectangle * rect)3575 meta_display_get_monitor_index_for_rect (MetaDisplay *display,
3576 MetaRectangle *rect)
3577 {
3578 MetaBackend *backend = meta_get_backend ();
3579 MetaMonitorManager *monitor_manager =
3580 meta_backend_get_monitor_manager (backend);
3581 MetaLogicalMonitor *logical_monitor;
3582
3583 logical_monitor =
3584 meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, rect);
3585 if (!logical_monitor)
3586 return -1;
3587
3588 return logical_monitor->number;
3589 }
3590
3591 int
meta_display_get_monitor_neighbor_index(MetaDisplay * display,int which_monitor,MetaDisplayDirection direction)3592 meta_display_get_monitor_neighbor_index (MetaDisplay *display,
3593 int which_monitor,
3594 MetaDisplayDirection direction)
3595 {
3596 MetaBackend *backend = meta_get_backend ();
3597 MetaMonitorManager *monitor_manager =
3598 meta_backend_get_monitor_manager (backend);
3599 MetaLogicalMonitor *logical_monitor;
3600 MetaLogicalMonitor *neighbor;
3601
3602 logical_monitor =
3603 meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
3604 which_monitor);
3605 neighbor = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
3606 logical_monitor,
3607 direction);
3608 return neighbor ? neighbor->number : -1;
3609 }
3610
3611 /**
3612 * meta_display_get_current_monitor:
3613 * @display: a #MetaDisplay
3614 *
3615 * Gets the index of the monitor that currently has the mouse pointer.
3616 *
3617 * Return value: a monitor index
3618 */
3619 int
meta_display_get_current_monitor(MetaDisplay * display)3620 meta_display_get_current_monitor (MetaDisplay *display)
3621 {
3622 MetaBackend *backend = meta_get_backend ();
3623 MetaLogicalMonitor *logical_monitor;
3624
3625 logical_monitor = meta_backend_get_current_logical_monitor (backend);
3626
3627 /* Pretend its the first when there is no actual current monitor. */
3628 if (!logical_monitor)
3629 return 0;
3630
3631 return logical_monitor->number;
3632 }
3633
3634 /**
3635 * meta_display_get_n_monitors:
3636 * @display: a #MetaDisplay
3637 *
3638 * Gets the number of monitors that are joined together to form @display.
3639 *
3640 * Return value: the number of monitors
3641 */
3642 int
meta_display_get_n_monitors(MetaDisplay * display)3643 meta_display_get_n_monitors (MetaDisplay *display)
3644 {
3645 MetaBackend *backend = meta_get_backend ();
3646 MetaMonitorManager *monitor_manager =
3647 meta_backend_get_monitor_manager (backend);
3648
3649 g_return_val_if_fail (META_IS_DISPLAY (display), 0);
3650
3651 return meta_monitor_manager_get_num_logical_monitors (monitor_manager);
3652 }
3653
3654 /**
3655 * meta_display_get_primary_monitor:
3656 * @display: a #MetaDisplay
3657 *
3658 * Gets the index of the primary monitor on this @display.
3659 *
3660 * Return value: a monitor index
3661 */
3662 int
meta_display_get_primary_monitor(MetaDisplay * display)3663 meta_display_get_primary_monitor (MetaDisplay *display)
3664 {
3665 MetaBackend *backend = meta_get_backend ();
3666 MetaMonitorManager *monitor_manager =
3667 meta_backend_get_monitor_manager (backend);
3668 MetaLogicalMonitor *logical_monitor;
3669
3670 g_return_val_if_fail (META_IS_DISPLAY (display), 0);
3671
3672 logical_monitor =
3673 meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
3674 if (logical_monitor)
3675 return logical_monitor->number;
3676 else
3677 return 0;
3678 }
3679
3680 /**
3681 * meta_display_get_monitor_geometry:
3682 * @display: a #MetaDisplay
3683 * @monitor: the monitor number
3684 * @geometry: (out): location to store the monitor geometry
3685 *
3686 * Stores the location and size of the indicated @monitor in @geometry.
3687 */
3688 void
meta_display_get_monitor_geometry(MetaDisplay * display,int monitor,MetaRectangle * geometry)3689 meta_display_get_monitor_geometry (MetaDisplay *display,
3690 int monitor,
3691 MetaRectangle *geometry)
3692 {
3693 MetaBackend *backend = meta_get_backend ();
3694 MetaMonitorManager *monitor_manager =
3695 meta_backend_get_monitor_manager (backend);
3696 MetaLogicalMonitor *logical_monitor;
3697 #ifndef G_DISABLE_CHECKS
3698 int n_logical_monitors =
3699 meta_monitor_manager_get_num_logical_monitors (monitor_manager);
3700 #endif
3701
3702 g_return_if_fail (META_IS_DISPLAY (display));
3703 g_return_if_fail (monitor >= 0 && monitor < n_logical_monitors);
3704 g_return_if_fail (geometry != NULL);
3705
3706 logical_monitor =
3707 meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
3708 monitor);
3709 *geometry = logical_monitor->rect;
3710 }
3711
3712 /**
3713 * meta_display_get_monitor_scale:
3714 * @display: a #MetaDisplay
3715 * @monitor: the monitor number
3716 *
3717 * Gets the monitor scaling value for the given @monitor.
3718 *
3719 * Return value: the monitor scaling value
3720 */
3721 float
meta_display_get_monitor_scale(MetaDisplay * display,int monitor)3722 meta_display_get_monitor_scale (MetaDisplay *display,
3723 int monitor)
3724 {
3725 MetaBackend *backend = meta_get_backend ();
3726 MetaMonitorManager *monitor_manager =
3727 meta_backend_get_monitor_manager (backend);
3728 MetaLogicalMonitor *logical_monitor;
3729 #ifndef G_DISABLE_CHECKS
3730 int n_logical_monitors =
3731 meta_monitor_manager_get_num_logical_monitors (monitor_manager);
3732 #endif
3733
3734 g_return_val_if_fail (META_IS_DISPLAY (display), 1.0f);
3735 g_return_val_if_fail (monitor >= 0 && monitor < n_logical_monitors, 1.0f);
3736
3737 logical_monitor =
3738 meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
3739 monitor);
3740 return logical_monitor->scale;
3741 }
3742
3743 /**
3744 * meta_display_get_monitor_in_fullscreen:
3745 * @display: a #MetaDisplay
3746 * @monitor: the monitor number
3747 *
3748 * Determines whether there is a fullscreen window obscuring the specified
3749 * monitor. If there is a fullscreen window, the desktop environment will
3750 * typically hide any controls that might obscure the fullscreen window.
3751 *
3752 * You can get notification when this changes by connecting to
3753 * MetaDisplay::in-fullscreen-changed.
3754 *
3755 * Returns: %TRUE if there is a fullscreen window covering the specified monitor.
3756 */
3757 gboolean
meta_display_get_monitor_in_fullscreen(MetaDisplay * display,int monitor)3758 meta_display_get_monitor_in_fullscreen (MetaDisplay *display,
3759 int monitor)
3760 {
3761 MetaBackend *backend = meta_get_backend ();
3762 MetaMonitorManager *monitor_manager =
3763 meta_backend_get_monitor_manager (backend);
3764 MetaLogicalMonitor *logical_monitor;
3765 #ifndef G_DISABLE_CHECKS
3766 int n_logical_monitors =
3767 meta_monitor_manager_get_num_logical_monitors (monitor_manager);
3768 #endif
3769
3770 g_return_val_if_fail (META_IS_DISPLAY (display), FALSE);
3771 g_return_val_if_fail (monitor >= 0 &&
3772 monitor < n_logical_monitors, FALSE);
3773
3774 logical_monitor =
3775 meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
3776 monitor);
3777
3778 /* We use -1 as a flag to mean "not known yet" for notification
3779 purposes */ return logical_monitor->in_fullscreen == TRUE;
3780 }
3781
3782 MetaWindow *
meta_display_get_pointer_window(MetaDisplay * display,MetaWindow * not_this_one)3783 meta_display_get_pointer_window (MetaDisplay *display,
3784 MetaWindow *not_this_one)
3785 {
3786 MetaWorkspaceManager *workspace_manager = display->workspace_manager;
3787 MetaBackend *backend = meta_get_backend ();
3788 MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
3789 MetaWindow *window;
3790 graphene_point_t point;
3791
3792 if (not_this_one)
3793 meta_topic (META_DEBUG_FOCUS,
3794 "Focusing mouse window excluding %s", not_this_one->desc);
3795
3796 meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
3797
3798 window = meta_stack_get_default_focus_window_at_point (display->stack,
3799 workspace_manager->active_workspace,
3800 not_this_one,
3801 point.x, point.y);
3802
3803 return window;
3804 }
3805
3806 void
meta_display_focus_default_window(MetaDisplay * display,guint32 timestamp)3807 meta_display_focus_default_window (MetaDisplay *display,
3808 guint32 timestamp)
3809 {
3810 MetaWorkspaceManager *workspace_manager = display->workspace_manager;
3811
3812 meta_workspace_focus_default_window (workspace_manager->active_workspace,
3813 NULL,
3814 timestamp);
3815 }
3816
3817 /**
3818 * meta_display_get_workspace_manager:
3819 * @display: a #MetaDisplay
3820 *
3821 * Returns: (transfer none): The workspace manager of the display
3822 */
3823 MetaWorkspaceManager *
meta_display_get_workspace_manager(MetaDisplay * display)3824 meta_display_get_workspace_manager (MetaDisplay *display)
3825 {
3826 return display->workspace_manager;
3827 }
3828
3829 MetaStartupNotification *
meta_display_get_startup_notification(MetaDisplay * display)3830 meta_display_get_startup_notification (MetaDisplay *display)
3831 {
3832 return display->startup_notification;
3833 }
3834
3835 MetaWindow *
meta_display_get_window_from_id(MetaDisplay * display,uint64_t window_id)3836 meta_display_get_window_from_id (MetaDisplay *display,
3837 uint64_t window_id)
3838 {
3839 g_autoptr (GSList) windows = NULL;
3840 GSList *l;
3841
3842 windows = meta_display_list_windows (display, META_LIST_DEFAULT);
3843 for (l = windows; l; l = l->next)
3844 {
3845 MetaWindow *window = l->data;
3846
3847 if (window->id == window_id)
3848 return window;
3849 }
3850
3851 return NULL;
3852 }
3853
3854 uint64_t
meta_display_generate_window_id(MetaDisplay * display)3855 meta_display_generate_window_id (MetaDisplay *display)
3856 {
3857 static uint64_t base_window_id;
3858 static uint64_t last_window_id;
3859
3860 if (!base_window_id)
3861 base_window_id = g_random_int () + 1;
3862
3863 /* We can overflow here, that's fine */
3864 return (base_window_id + last_window_id++);
3865 }
3866
3867 /**
3868 * meta_display_get_sound_player:
3869 * @display: a #MetaDisplay
3870 *
3871 * Returns: (transfer none): The sound player of the display
3872 */
3873 MetaSoundPlayer *
meta_display_get_sound_player(MetaDisplay * display)3874 meta_display_get_sound_player (MetaDisplay *display)
3875 {
3876 return display->sound_player;
3877 }
3878
3879 /**
3880 * meta_display_get_selection:
3881 * @display: a #MetaDisplay
3882 *
3883 * Returns: (transfer none): The selection manager of the display
3884 */
3885 MetaSelection *
meta_display_get_selection(MetaDisplay * display)3886 meta_display_get_selection (MetaDisplay *display)
3887 {
3888 return display->selection;
3889 }
3890