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, &timestamp))
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