summaryrefslogtreecommitdiff
path: root/src/core/display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/display.c')
-rw-r--r--src/core/display.c3852
1 files changed, 0 insertions, 3852 deletions
diff --git a/src/core/display.c b/src/core/display.c
deleted file mode 100644
index 5d4a4da21..000000000
--- a/src/core/display.c
+++ /dev/null
@@ -1,3852 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
- * Copyright (C) 2003, 2004 Rob Adams
- * Copyright (C) 2004-2006 Elijah Newren
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * SECTION:display
- * @title: MetaDisplay
- * @short_description: Mutter display representation
- *
- * The display is represented as a #MetaDisplay struct.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <X11/Xatom.h>
-#include <X11/Xcursor/Xcursor.h>
-#include <X11/extensions/shape.h>
-#include <X11/extensions/Xcomposite.h>
-#include <X11/extensions/Xdamage.h>
-#include <X11/extensions/Xfixes.h>
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-cursor-sprite-xcursor.h"
-#include "backends/meta-cursor-tracker-private.h"
-#include "backends/meta-input-device-private.h"
-#include "backends/meta-input-mapper-private.h"
-#include "backends/meta-stage-private.h"
-#include "backends/x11/meta-backend-x11.h"
-#include "backends/x11/meta-clutter-backend-x11.h"
-#include "backends/x11/meta-event-x11.h"
-#include "backends/x11/cm/meta-backend-x11-cm.h"
-#include "backends/x11/nested/meta-backend-x11-nested.h"
-#include "compositor/compositor-private.h"
-#include "compositor/meta-compositor-x11.h"
-#include "cogl/cogl.h"
-#include "core/bell.h"
-#include "core/boxes-private.h"
-#include "core/display-private.h"
-#include "core/events.h"
-#include "core/frame.h"
-#include "core/keybindings-private.h"
-#include "core/meta-clipboard-manager.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/util-private.h"
-#include "core/window-private.h"
-#include "core/workspace-private.h"
-#include "meta/compositor-mutter.h"
-#include "meta/compositor.h"
-#include "meta/main.h"
-#include "meta/meta-backend.h"
-#include "meta/meta-enum-types.h"
-#include "meta/meta-sound-player.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/prefs.h"
-#include "x11/meta-startup-notification-x11.h"
-#include "x11/meta-x11-display-private.h"
-#include "x11/window-x11.h"
-#include "x11/xprops.h"
-
-#ifdef HAVE_WAYLAND
-#include "compositor/meta-compositor-native.h"
-#include "compositor/meta-compositor-server.h"
-#include "wayland/meta-xwayland-private.h"
-#include "wayland/meta-wayland-tablet-seat.h"
-#include "wayland/meta-wayland-tablet-pad.h"
-#endif
-
-#ifdef HAVE_NATIVE_BACKEND
-#include "backends/native/meta-backend-native.h"
-#endif
-
-/*
- * SECTION:pings
- *
- * Sometimes we want to see whether a window is responding,
- * so we send it a "ping" message and see whether it sends us back a "pong"
- * message within a reasonable time. Here we have a system which lets us
- * nominate one function to be called if we get the pong in time and another
- * function if we don't. The system is rather more complicated than it needs
- * to be, since we only ever use it to destroy windows which are asked to
- * close themselves and don't do so within a reasonable amount of time, and
- * therefore we always use the same callbacks. It's possible that we might
- * use it for other things in future, or on the other hand we might decide
- * that we're never going to do so and simplify it a bit.
- */
-
-/**
- * MetaPingData:
- *
- * Describes a ping on a window. When we send a ping to a window, we build
- * one of these structs, and it eventually gets passed to the timeout function
- * or to the function which handles the response from the window. If the window
- * does or doesn't respond to the ping, we use this information to deal with
- * these facts; we have a handler function for each.
- */
-typedef struct
-{
- MetaWindow *window;
- guint32 serial;
- guint ping_timeout_id;
-} MetaPingData;
-
-typedef struct _MetaDisplayPrivate
-{
- MetaContext *context;
-} MetaDisplayPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (MetaDisplay, meta_display, G_TYPE_OBJECT)
-
-/* Signals */
-enum
-{
- CURSOR_UPDATED,
- X11_DISPLAY_SETUP,
- X11_DISPLAY_OPENED,
- X11_DISPLAY_CLOSING,
- OVERLAY_KEY,
- ACCELERATOR_ACTIVATED,
- MODIFIERS_ACCELERATOR_ACTIVATED,
- FOCUS_WINDOW,
- WINDOW_CREATED,
- WINDOW_DEMANDS_ATTENTION,
- WINDOW_MARKED_URGENT,
- GRAB_OP_BEGIN,
- GRAB_OP_END,
- SHOW_RESTART_MESSAGE,
- RESTART,
- SHOW_RESIZE_POPUP,
- GL_VIDEO_MEMORY_PURGED,
- SHOW_PAD_OSD,
- SHOW_OSD,
- PAD_MODE_SWITCH,
- WINDOW_ENTERED_MONITOR,
- WINDOW_LEFT_MONITOR,
- WORKSPACE_ADDED,
- WORKSPACE_REMOVED,
- WORKSPACE_SWITCHED,
- ACTIVE_WORKSPACE_CHANGED,
- IN_FULLSCREEN_CHANGED,
- SHOWING_DESKTOP_CHANGED,
- RESTACKED,
- WORKAREAS_CHANGED,
- CLOSING,
- INIT_XSERVER,
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
-
- PROP_COMPOSITOR_MODIFIERS,
- PROP_FOCUS_WINDOW
-};
-
-static guint display_signals [LAST_SIGNAL] = { 0 };
-
-#define META_GRAB_OP_GET_BASE_TYPE(op) (op & 0x00FF)
-
-/*
- * The display we're managing. This is a singleton object. (Historically,
- * this was a list of displays, but there was never any way to add more
- * than one element to it.) The goofy name is because we don't want it
- * to shadow the parameter in its object methods.
- */
-static MetaDisplay *the_display = NULL;
-
-static void on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
- MetaDisplay *display);
-
-static void prefs_changed_callback (MetaPreference pref,
- void *data);
-
-static int mru_cmp (gconstpointer a,
- gconstpointer b);
-
-static void
-meta_display_get_property(GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaDisplay *display = META_DISPLAY (object);
-
- switch (prop_id)
- {
- case PROP_COMPOSITOR_MODIFIERS:
- g_value_set_flags (value, meta_display_get_compositor_modifiers (display));
- break;
- case PROP_FOCUS_WINDOW:
- g_value_set_object (value, display->focus_window);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_display_set_property(GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (prop_id)
- {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_display_class_init (MetaDisplayClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = meta_display_get_property;
- object_class->set_property = meta_display_set_property;
-
- display_signals[CURSOR_UPDATED] =
- g_signal_new ("cursor-updated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[X11_DISPLAY_SETUP] =
- g_signal_new ("x11-display-setup",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[X11_DISPLAY_OPENED] =
- g_signal_new ("x11-display-opened",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[X11_DISPLAY_CLOSING] =
- g_signal_new ("x11-display-closing",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[OVERLAY_KEY] =
- g_signal_new ("overlay-key",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[ACCELERATOR_ACTIVATED] =
- g_signal_new ("accelerator-activated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 3, G_TYPE_UINT, CLUTTER_TYPE_INPUT_DEVICE, G_TYPE_UINT);
-
- /**
- * MetaDisplay::modifiers-accelerator-activated:
- * @display: the #MetaDisplay instance
- *
- * The ::modifiers-accelerator-activated signal will be emitted when
- * a special modifiers-only keybinding is activated.
- *
- * Returns: %TRUE means that the keyboard device should remain
- * frozen and %FALSE for the default behavior of unfreezing the
- * keyboard.
- */
- display_signals[MODIFIERS_ACCELERATOR_ACTIVATED] =
- g_signal_new ("modifiers-accelerator-activated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- g_signal_accumulator_first_wins, NULL, NULL,
- G_TYPE_BOOLEAN, 0);
-
- display_signals[WINDOW_CREATED] =
- g_signal_new ("window-created",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1, META_TYPE_WINDOW);
-
- display_signals[WINDOW_DEMANDS_ATTENTION] =
- g_signal_new ("window-demands-attention",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1, META_TYPE_WINDOW);
-
- display_signals[WINDOW_MARKED_URGENT] =
- g_signal_new ("window-marked-urgent",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- META_TYPE_WINDOW);
-
- display_signals[GRAB_OP_BEGIN] =
- g_signal_new ("grab-op-begin",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 2,
- META_TYPE_WINDOW,
- META_TYPE_GRAB_OP);
-
- display_signals[GRAB_OP_END] =
- g_signal_new ("grab-op-end",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 2,
- META_TYPE_WINDOW,
- META_TYPE_GRAB_OP);
-
- /**
- * MetaDisplay::show-restart-message:
- * @display: the #MetaDisplay instance
- * @message: (allow-none): The message to display, or %NULL
- * to clear a previous restart message.
- *
- * The ::show-restart-message signal will be emitted to indicate
- * that the compositor should show a message during restart. This is
- * emitted when meta_restart() is called, either by Mutter
- * internally or by the embedding compositor. The message should be
- * immediately added to the Clutter stage in its final form -
- * ::restart will be emitted to exit the application and leave the
- * stage contents frozen as soon as the the stage is painted again.
- *
- * On case of failure to restart, this signal will be emitted again
- * with %NULL for @message.
- *
- * Returns: %TRUE means the message was added to the stage; %FALSE
- * indicates that the compositor did not show the message.
- */
- display_signals[SHOW_RESTART_MESSAGE] =
- g_signal_new ("show-restart-message",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- g_signal_accumulator_true_handled,
- NULL, NULL,
- G_TYPE_BOOLEAN, 1,
- G_TYPE_STRING);
-
- /**
- * MetaDisplay::restart:
- * @display: the #MetaDisplay instance
- *
- * The ::restart signal is emitted to indicate that compositor
- * should reexec the process. This is
- * emitted when meta_restart() is called, either by Mutter
- * internally or by the embedding compositor. See also
- * ::show-restart-message.
- *
- * Returns: %FALSE to indicate that the compositor could not
- * be restarted. When the compositor is restarted, the signal
- * should not return.
- */
- display_signals[RESTART] =
- g_signal_new ("restart",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- g_signal_accumulator_true_handled,
- NULL, NULL,
- G_TYPE_BOOLEAN, 0);
-
- display_signals[SHOW_RESIZE_POPUP] =
- g_signal_new ("show-resize-popup",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- g_signal_accumulator_true_handled,
- NULL, NULL,
- G_TYPE_BOOLEAN, 4,
- G_TYPE_BOOLEAN, META_TYPE_RECTANGLE, G_TYPE_INT, G_TYPE_INT);
-
- display_signals[GL_VIDEO_MEMORY_PURGED] =
- g_signal_new ("gl-video-memory-purged",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- /**
- * MetaDisplay::show-pad-osd:
- * @display: the #MetaDisplay instance
- * @pad: the pad device
- * @settings: the pad device settings
- * @layout_path: path to the layout image
- * @edition_mode: Whether the OSD should be shown in edition mode
- * @monitor_idx: Monitor to show the OSD on
- *
- * Requests the pad button mapping OSD to be shown.
- *
- * Returns: (transfer none) (nullable): The OSD actor
- */
- display_signals[SHOW_PAD_OSD] =
- g_signal_new ("show-pad-osd",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- CLUTTER_TYPE_ACTOR, 5, CLUTTER_TYPE_INPUT_DEVICE,
- G_TYPE_SETTINGS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT);
-
- display_signals[SHOW_OSD] =
- g_signal_new ("show-osd",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING);
-
- display_signals[PAD_MODE_SWITCH] =
- g_signal_new ("pad-mode-switch",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 3, CLUTTER_TYPE_INPUT_DEVICE,
- G_TYPE_UINT, G_TYPE_UINT);
-
- display_signals[WINDOW_ENTERED_MONITOR] =
- g_signal_new ("window-entered-monitor",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 2,
- G_TYPE_INT,
- META_TYPE_WINDOW);
-
- display_signals[WINDOW_LEFT_MONITOR] =
- g_signal_new ("window-left-monitor",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 2,
- G_TYPE_INT,
- META_TYPE_WINDOW);
-
- display_signals[IN_FULLSCREEN_CHANGED] =
- g_signal_new ("in-fullscreen-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[SHOWING_DESKTOP_CHANGED] =
- g_signal_new ("showing-desktop-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[RESTACKED] =
- g_signal_new ("restacked",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[WORKAREAS_CHANGED] =
- g_signal_new ("workareas-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
- display_signals[CLOSING] =
- g_signal_new ("closing",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- display_signals[INIT_XSERVER] =
- g_signal_new ("init-xserver",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, g_signal_accumulator_first_wins,
- NULL, NULL,
- G_TYPE_BOOLEAN, 1, G_TYPE_TASK);
-
- g_object_class_install_property (object_class,
- PROP_COMPOSITOR_MODIFIERS,
- g_param_spec_flags ("compositor-modifiers",
- "Compositor modifiers",
- "Modifiers reserved for compositor actions",
- CLUTTER_TYPE_MODIFIER_TYPE,
- 0,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class,
- PROP_FOCUS_WINDOW,
- g_param_spec_object ("focus-window",
- "Focus window",
- "Currently focused window",
- META_TYPE_WINDOW,
- G_PARAM_READABLE));
-
-}
-
-
-/**
- * ping_data_free:
- *
- * Destructor for #MetaPingData structs. Will destroy the
- * event source for the struct as well.
- */
-static void
-ping_data_free (MetaPingData *ping_data)
-{
- /* Remove the timeout */
- g_clear_handle_id (&ping_data->ping_timeout_id, g_source_remove);
-
- g_free (ping_data);
-}
-
-void
-meta_display_remove_pending_pings_for_window (MetaDisplay *display,
- MetaWindow *window)
-{
- GSList *tmp;
- GSList *dead;
-
- /* could obviously be more efficient, don't care */
-
- /* build list to be removed */
- dead = NULL;
- for (tmp = display->pending_pings; tmp; tmp = tmp->next)
- {
- MetaPingData *ping_data = tmp->data;
-
- if (ping_data->window == window)
- dead = g_slist_prepend (dead, ping_data);
- }
-
- /* remove what we found */
- for (tmp = dead; tmp; tmp = tmp->next)
- {
- MetaPingData *ping_data = tmp->data;
-
- display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
- ping_data_free (ping_data);
- }
-
- g_slist_free (dead);
-}
-
-static MetaCompositor *
-create_compositor (MetaDisplay *display)
-{
- MetaBackend *backend = meta_get_backend ();
-
-#ifdef HAVE_WAYLAND
-#ifdef HAVE_NATIVE_BACKEND
- if (META_IS_BACKEND_NATIVE (backend))
- return META_COMPOSITOR (meta_compositor_native_new (display, backend));
-#endif
- if (META_IS_BACKEND_X11_NESTED (backend))
- return META_COMPOSITOR (meta_compositor_server_new (display, backend));
-#endif
- return META_COMPOSITOR (meta_compositor_x11_new (display, backend));
-}
-
-static void
-meta_display_init (MetaDisplay *disp)
-{
- /* Some stuff could go in here that's currently in _open,
- * but it doesn't really matter. */
-}
-
-void
-meta_display_cancel_touch (MetaDisplay *display)
-{
-#ifdef HAVE_WAYLAND
- MetaWaylandCompositor *compositor;
-
- if (!meta_is_wayland_compositor ())
- return;
-
- compositor = meta_wayland_compositor_get_default ();
- meta_wayland_touch_cancel (compositor->seat->touch);
-#endif
-}
-
-static void
-gesture_tracker_state_changed (MetaGestureTracker *tracker,
- ClutterEventSequence *sequence,
- MetaSequenceState state,
- MetaDisplay *display)
-{
- switch (state)
- {
- case META_SEQUENCE_NONE:
- case META_SEQUENCE_PENDING_END:
- return;
- case META_SEQUENCE_ACCEPTED:
- meta_display_cancel_touch (display);
-
- G_GNUC_FALLTHROUGH;
- case META_SEQUENCE_REJECTED:
- {
- MetaBackend *backend;
-
- backend = meta_get_backend ();
- meta_backend_finish_touch_sequence (backend, sequence, state);
- break;
- }
- }
-}
-
-static void
-on_ui_scaling_factor_changed (MetaSettings *settings,
- MetaDisplay *display)
-{
- meta_display_reload_cursor (display);
-}
-
-static gboolean
-meta_display_init_x11_display (MetaDisplay *display,
- GError **error)
-{
- MetaX11Display *x11_display;
-
- x11_display = meta_x11_display_new (display, error);
- if (!x11_display)
- return FALSE;
-
- display->x11_display = x11_display;
- g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0);
-
- meta_x11_display_create_guard_window (x11_display);
-
- if (!display->display_opening)
- {
- g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
- meta_display_manage_all_xwindows (display);
- meta_compositor_redirect_x11_windows (display->compositor);
- }
-
- return TRUE;
-}
-
-#ifdef HAVE_WAYLAND
-gboolean
-meta_display_init_x11_finish (MetaDisplay *display,
- GAsyncResult *result,
- GError **error)
-{
- MetaX11Display *x11_display;
-
- g_assert (g_task_get_source_tag (G_TASK (result)) == meta_display_init_x11);
-
- if (!g_task_propagate_boolean (G_TASK (result), error))
- {
- if (*error == NULL)
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown error");
-
- return FALSE;
- }
-
- if (display->x11_display)
- return TRUE;
-
- x11_display = meta_x11_display_new (display, error);
- if (!x11_display)
- return FALSE;
-
- display->x11_display = x11_display;
- g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0);
-
- meta_x11_display_create_guard_window (x11_display);
-
- if (!display->display_opening)
- {
- g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
- meta_x11_display_set_cm_selection (x11_display);
- meta_display_manage_all_xwindows (display);
- meta_compositor_redirect_x11_windows (display->compositor);
- }
-
- return TRUE;
-}
-
-static void
-on_xserver_started (MetaXWaylandManager *manager,
- GAsyncResult *result,
- gpointer user_data)
-{
- g_autoptr (GTask) task = user_data;
- MetaDisplay *display = g_task_get_source_object (task);
- GError *error = NULL;
- gboolean retval = FALSE;
-
- if (!meta_xwayland_start_xserver_finish (manager, result, &error))
- {
- if (error)
- g_task_return_error (task, error);
- else
- g_task_return_boolean (task, FALSE);
-
- return;
- }
-
- g_signal_emit (display, display_signals[INIT_XSERVER], 0, task, &retval);
-
- if (!retval)
- {
- /* No handlers for this signal, proceed right away */
- g_task_return_boolean (task, TRUE);
- }
-}
-
-void
-meta_display_init_x11 (MetaDisplay *display,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
-
- g_autoptr (GTask) task = NULL;
-
- task = g_task_new (display, cancellable, callback, user_data);
- g_task_set_source_tag (task, meta_display_init_x11);
-
- meta_xwayland_start_xserver (&compositor->xwayland_manager,
- cancellable,
- (GAsyncReadyCallback) on_xserver_started,
- g_steal_pointer (&task));
-}
-
-static void
-on_x11_initialized (MetaDisplay *display,
- GAsyncResult *result,
- gpointer user_data)
-{
- g_autoptr (GError) error = NULL;
-
- if (!meta_display_init_x11_finish (display, result, &error))
- g_critical ("Failed to init X11 display: %s", error->message);
-}
-#endif
-
-void
-meta_display_shutdown_x11 (MetaDisplay *display)
-{
- if (!display->x11_display)
- return;
-
- g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0);
- g_object_run_dispose (G_OBJECT (display->x11_display));
- g_clear_object (&display->x11_display);
-}
-
-MetaDisplay *
-meta_display_new (MetaContext *context,
- GError **error)
-{
- MetaDisplay *display;
- MetaDisplayPrivate *priv;
- int i;
- guint32 timestamp;
- Window old_active_xwindow = None;
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager;
- MetaSettings *settings;
-
- g_assert (the_display == NULL);
- display = the_display = g_object_new (META_TYPE_DISPLAY, NULL);
-
- priv = meta_display_get_instance_private (display);
- priv->context = context;
-
- display->closing = 0;
- display->display_opening = TRUE;
-
- display->pending_pings = NULL;
- display->autoraise_timeout_id = 0;
- display->autoraise_window = NULL;
- display->focus_window = NULL;
- display->workspace_manager = NULL;
- display->x11_display = NULL;
-
- display->current_cursor = -1; /* invalid/unset */
- display->tile_preview_timeout_id = 0;
- display->check_fullscreen_later = 0;
- display->work_area_later = 0;
-
- display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
- display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
- terminal has the focus */
-
- i = 0;
- while (i < N_IGNORED_CROSSING_SERIALS)
- {
- display->ignored_crossing_serials[i] = 0;
- ++i;
- }
-
- display->current_time = META_CURRENT_TIME;
-
- display->grab_resize_timeout_id = 0;
- display->grab_have_keyboard = FALSE;
-
- display->grab_op = META_GRAB_OP_NONE;
- display->grab_window = NULL;
- display->grab_tile_mode = META_TILE_NONE;
- display->grab_tile_monitor_number = -1;
-
- meta_display_cleanup_edges (display);
-
- meta_display_init_keys (display);
-
- meta_prefs_add_listener (prefs_changed_callback, display);
-
- /* Get events */
- meta_display_init_events (display);
-
- display->stamps = g_hash_table_new (g_int64_hash,
- g_int64_equal);
- display->wayland_windows = g_hash_table_new (NULL, NULL);
-
- monitor_manager = meta_backend_get_monitor_manager (backend);
- g_signal_connect (monitor_manager, "monitors-changed-internal",
- G_CALLBACK (on_monitors_changed_internal), display);
-
- display->pad_action_mapper = meta_pad_action_mapper_new (monitor_manager);
-
- settings = meta_backend_get_settings (backend);
- g_signal_connect (settings, "ui-scaling-factor-changed",
- G_CALLBACK (on_ui_scaling_factor_changed), display);
-
- display->compositor = create_compositor (display);
-
- meta_display_set_cursor (display, META_CURSOR_DEFAULT);
-
- display->stack = meta_stack_new (display);
- display->stack_tracker = meta_stack_tracker_new (display);
-
- display->workspace_manager = meta_workspace_manager_new (display);
-
- display->startup_notification = meta_startup_notification_new (display);
-
- display->bell = meta_bell_new (display);
-
- display->selection = meta_selection_new (display);
- meta_clipboard_manager_init (display);
-
-#ifdef HAVE_WAYLAND
- if (meta_is_wayland_compositor ())
- {
- MetaX11DisplayPolicy x11_display_policy;
-
- x11_display_policy = meta_context_get_x11_display_policy (context);
- if (x11_display_policy == META_X11_DISPLAY_POLICY_MANDATORY)
- {
- meta_display_init_x11 (display, NULL,
- (GAsyncReadyCallback) on_x11_initialized,
- NULL);
- }
-
- timestamp = meta_display_get_current_time_roundtrip (display);
- }
- else
-#endif
- {
- if (!meta_display_init_x11_display (display, error))
- {
- g_object_unref (display);
- return NULL;
- }
-
- timestamp = display->x11_display->timestamp;
- }
-
- display->last_focus_time = timestamp;
- display->last_user_time = timestamp;
-
- if (!meta_is_wayland_compositor ())
- meta_prop_get_window (display->x11_display,
- display->x11_display->xroot,
- display->x11_display->atom__NET_ACTIVE_WINDOW,
- &old_active_xwindow);
-
- if (!meta_compositor_do_manage (display->compositor, error))
- {
- g_object_unref (display);
- return NULL;
- }
-
- if (display->x11_display)
- {
- g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
- meta_x11_display_restore_active_workspace (display->x11_display);
- meta_x11_display_create_guard_window (display->x11_display);
- }
-
- /* Set up touch support */
- display->gesture_tracker = meta_gesture_tracker_new ();
- g_signal_connect (display->gesture_tracker, "state-changed",
- G_CALLBACK (gesture_tracker_state_changed), display);
-
- /* We know that if mutter is running as a Wayland compositor,
- * we start out with no windows.
- */
- if (!meta_is_wayland_compositor ())
- meta_display_manage_all_xwindows (display);
-
- if (old_active_xwindow != None)
- {
- MetaWindow *old_active_window;
- old_active_window = meta_x11_display_lookup_x_window (display->x11_display,
- old_active_xwindow);
- if (old_active_window)
- meta_window_focus (old_active_window, timestamp);
- else
- meta_display_unset_input_focus (display, timestamp);
- }
- else
- {
- meta_display_unset_input_focus (display, timestamp);
- }
-
- display->sound_player = g_object_new (META_TYPE_SOUND_PLAYER, NULL);
-
- /* Done opening new display */
- display->display_opening = FALSE;
-
- return display;
-}
-
-static gint
-ptrcmp (gconstpointer a, gconstpointer b)
-{
- if (a < b)
- return -1;
- else if (a > b)
- return 1;
- else
- return 0;
-}
-
-/**
- * meta_display_list_windows:
- * @display: a #MetaDisplay
- * @flags: options for listing
- *
- * Lists windows for the display, the @flags parameter for
- * now determines whether override-redirect windows will be
- * included.
- *
- * Return value: (transfer container): the list of windows.
- */
-GSList*
-meta_display_list_windows (MetaDisplay *display,
- MetaListWindowsFlags flags)
-{
- GSList *winlist;
- GSList *prev;
- GSList *tmp;
- GHashTableIter iter;
- gpointer key, value;
-
- winlist = NULL;
-
- if (display->x11_display)
- {
- g_hash_table_iter_init (&iter, display->x11_display->xids);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- MetaWindow *window = value;
-
- if (!META_IS_WINDOW (window) || window->unmanaging)
- continue;
-
- if (!window->override_redirect ||
- (flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0)
- winlist = g_slist_prepend (winlist, window);
- }
- }
-
- g_hash_table_iter_init (&iter, display->wayland_windows);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- MetaWindow *window = value;
-
- if (!META_IS_WINDOW (window) || window->unmanaging)
- continue;
-
- if (!window->override_redirect ||
- (flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0)
- winlist = g_slist_prepend (winlist, window);
- }
-
- /* Uniquify the list, since both frame windows and plain
- * windows are in the hash
- */
- winlist = g_slist_sort (winlist, ptrcmp);
-
- prev = NULL;
- tmp = winlist;
- while (tmp != NULL)
- {
- GSList *next;
-
- next = tmp->next;
-
- if (next &&
- next->data == tmp->data)
- {
- /* Delete tmp from list */
-
- if (prev)
- prev->next = next;
-
- if (tmp == winlist)
- winlist = next;
-
- g_slist_free_1 (tmp);
-
- /* leave prev unchanged */
- }
- else
- {
- prev = tmp;
- }
-
- tmp = next;
- }
-
- if (flags & META_LIST_SORTED)
- winlist = g_slist_sort (winlist, mru_cmp);
-
- return winlist;
-}
-
-void
-meta_display_close (MetaDisplay *display,
- guint32 timestamp)
-{
- g_assert (display != NULL);
-
- if (display->closing != 0)
- {
- /* The display's already been closed. */
- return;
- }
-
- g_assert (display == the_display);
-
- display->closing += 1;
-
- g_signal_emit (display, display_signals[CLOSING], 0);
-
- meta_compositor_unmanage (display->compositor);
-
- meta_display_unmanage_windows (display, timestamp);
-
- meta_prefs_remove_listener (prefs_changed_callback, display);
-
- meta_display_remove_autoraise_callback (display);
-
- g_clear_object (&display->gesture_tracker);
-
- g_clear_handle_id (&display->focus_timeout_id, g_source_remove);
- g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove);
-
- if (display->work_area_later != 0)
- meta_later_remove (display->work_area_later);
- if (display->check_fullscreen_later != 0)
- meta_later_remove (display->check_fullscreen_later);
-
- /* Stop caring about events */
- meta_display_free_events (display);
-
- g_clear_pointer (&display->compositor, meta_compositor_destroy);
-
- meta_display_shutdown_x11 (display);
-
- g_clear_object (&display->stack);
- g_clear_pointer (&display->stack_tracker,
- meta_stack_tracker_free);
-
- /* Must be after all calls to meta_window_unmanage() since they
- * unregister windows
- */
- g_hash_table_destroy (display->wayland_windows);
- g_hash_table_destroy (display->stamps);
-
- meta_display_shutdown_keys (display);
-
- g_clear_object (&display->bell);
- g_clear_object (&display->startup_notification);
- g_clear_object (&display->workspace_manager);
- g_clear_object (&display->sound_player);
-
- meta_clipboard_manager_shutdown (display);
- g_clear_object (&display->selection);
- g_clear_object (&display->pad_action_mapper);
-
- the_display = NULL;
-}
-
-/**
- * meta_display_for_x_display:
- * @xdisplay: An X display
- *
- * Returns the singleton MetaDisplay if @xdisplay matches the X display it's
- * managing; otherwise gives a warning and returns %NULL. When we were claiming
- * to be able to manage multiple displays, this was supposed to find the
- * display out of the list which matched that display. Now it's merely an
- * extra sanity check.
- *
- * Returns: The singleton X display, or %NULL if @xdisplay isn't the one
- * we're managing.
- */
-MetaDisplay*
-meta_display_for_x_display (Display *xdisplay)
-{
- if (the_display->x11_display->xdisplay == xdisplay)
- return the_display;
-
- meta_warning ("Could not find display for X display %p, probably going to crash",
- xdisplay);
-
- return NULL;
-}
-
-/**
- * meta_get_display:
- *
- * Accessor for the singleton MetaDisplay.
- *
- * Returns: The only #MetaDisplay there is. This can be %NULL, but only
- * during startup.
- */
-MetaDisplay*
-meta_get_display (void)
-{
- return the_display;
-}
-
-static inline gboolean
-grab_op_is_window (MetaGrabOp op)
-{
- return META_GRAB_OP_GET_BASE_TYPE (op) == META_GRAB_OP_WINDOW_BASE;
-}
-
-gboolean
-meta_grab_op_is_mouse (MetaGrabOp op)
-{
- if (!grab_op_is_window (op))
- return FALSE;
-
- return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) == 0;
-}
-
-gboolean
-meta_grab_op_is_keyboard (MetaGrabOp op)
-{
- if (!grab_op_is_window (op))
- return FALSE;
-
- return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) != 0;
-}
-
-gboolean
-meta_grab_op_is_resizing (MetaGrabOp op)
-{
- if (!grab_op_is_window (op))
- return FALSE;
-
- return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0 || op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN;
-}
-
-gboolean
-meta_grab_op_is_moving (MetaGrabOp op)
-{
- if (!grab_op_is_window (op))
- return FALSE;
-
- return !meta_grab_op_is_resizing (op);
-}
-
-/**
- * meta_display_windows_are_interactable:
- * @op: A #MetaGrabOp
- *
- * Whether windows can be interacted with.
- */
-gboolean
-meta_display_windows_are_interactable (MetaDisplay *display)
-{
- switch (display->event_route)
- {
- case META_EVENT_ROUTE_NORMAL:
- case META_EVENT_ROUTE_WAYLAND_POPUP:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-/**
- * meta_display_xserver_time_is_before:
- * @display: a #MetaDisplay
- * @time1: An event timestamp
- * @time2: An event timestamp
- *
- * Xserver time can wraparound, thus comparing two timestamps needs to take
- * this into account. If no wraparound has occurred, this is equivalent to
- * time1 < time2
- * Otherwise, we need to account for the fact that wraparound can occur
- * and the fact that a timestamp of 0 must be special-cased since it
- * means "older than anything else".
- *
- * Note that this is NOT an equivalent for time1 <= time2; if that's what
- * you need then you'll need to swap the order of the arguments and negate
- * the result.
- */
-gboolean
-meta_display_xserver_time_is_before (MetaDisplay *display,
- guint32 time1,
- guint32 time2)
-{
- return XSERVER_TIME_IS_BEFORE(time1, time2);
-}
-
-/**
- * meta_display_get_last_user_time:
- * @display: a #MetaDisplay
- *
- * Returns: Timestamp of the last user interaction event with a window
- */
-guint32
-meta_display_get_last_user_time (MetaDisplay *display)
-{
- return display->last_user_time;
-}
-
-/* Get time of current event, or CurrentTime if none. */
-guint32
-meta_display_get_current_time (MetaDisplay *display)
-{
- return display->current_time;
-}
-
-guint32
-meta_display_get_current_time_roundtrip (MetaDisplay *display)
-{
- if (meta_is_wayland_compositor ())
- /* Xwayland uses monotonic clock, so lets use it here as well */
- return (guint32) (g_get_monotonic_time () / 1000);
- else
- return meta_x11_display_get_current_time_roundtrip (display->x11_display);
-}
-
-/**
- * meta_display_add_ignored_crossing_serial:
- * @display: a #MetaDisplay
- * @serial: the serial to ignore
- *
- * Save the specified serial and ignore crossing events with that
- * serial for the purpose of focus-follows-mouse. This can be used
- * for certain changes to the window hierarchy that we don't want
- * to change the focus window, even if they cause the pointer to
- * end up in a new window.
- */
-void
-meta_display_add_ignored_crossing_serial (MetaDisplay *display,
- unsigned long serial)
-{
- int i;
-
- /* don't add the same serial more than once */
- if (display->ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS-1] == serial)
- return;
-
- /* shift serials to the left */
- i = 0;
- while (i < (N_IGNORED_CROSSING_SERIALS - 1))
- {
- display->ignored_crossing_serials[i] = display->ignored_crossing_serials[i+1];
- ++i;
- }
- /* put new one on the end */
- display->ignored_crossing_serials[i] = serial;
-}
-
-static gboolean
-window_raise_with_delay_callback (void *data)
-{
- MetaWindow *window = data;
-
- window->display->autoraise_timeout_id = 0;
- window->display->autoraise_window = NULL;
-
- /* If we aren't already on top, check whether the pointer is inside
- * the window and raise the window if so.
- */
- if (meta_stack_get_top (window->display->stack) != window)
- {
- if (meta_window_has_pointer (window))
- meta_window_raise (window);
- else
- meta_topic (META_DEBUG_FOCUS,
- "Pointer not inside window, not raising %s",
- window->desc);
- }
-
- return G_SOURCE_REMOVE;
-}
-
-void
-meta_display_queue_autoraise_callback (MetaDisplay *display,
- MetaWindow *window)
-{
- meta_topic (META_DEBUG_FOCUS,
- "Queuing an autoraise timeout for %s with delay %d",
- window->desc,
- meta_prefs_get_auto_raise_delay ());
-
- g_clear_handle_id (&display->autoraise_timeout_id, g_source_remove);
-
- display->autoraise_timeout_id =
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- meta_prefs_get_auto_raise_delay (),
- window_raise_with_delay_callback,
- window, NULL);
- g_source_set_name_by_id (display->autoraise_timeout_id, "[mutter] window_raise_with_delay_callback");
- display->autoraise_window = window;
-}
-
-void
-meta_display_sync_wayland_input_focus (MetaDisplay *display)
-{
-#ifdef HAVE_WAYLAND
- MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
- MetaWindow *focus_window = NULL;
- MetaBackend *backend = meta_get_backend ();
- ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
- ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
- MetaStage *stage = META_STAGE (meta_backend_get_stage (backend));
- gboolean is_no_focus_xwindow = FALSE;
-
- if (display->x11_display)
- is_no_focus_xwindow = meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display,
- display->x11_display->focus_xwindow);
-
- if (!meta_display_windows_are_interactable (display))
- focus_window = NULL;
- else if (is_no_focus_xwindow)
- focus_window = NULL;
- else if (display->focus_window && display->focus_window->surface)
- focus_window = display->focus_window;
- else
- meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
-
- meta_stage_set_active (stage, focus_window == NULL);
- meta_wayland_compositor_set_input_focus (compositor, focus_window);
-
- clutter_stage_repick_device (CLUTTER_STAGE (stage),
- clutter_seat_get_pointer (seat));
-#endif
-}
-
-void
-meta_display_update_focus_window (MetaDisplay *display,
- MetaWindow *window)
-{
- if (display->focus_window == window)
- return;
-
- if (display->focus_window)
- {
- MetaWindow *previous;
-
- meta_topic (META_DEBUG_FOCUS,
- "%s is now the previous focus window due to being focused out or unmapped",
- display->focus_window->desc);
-
- /* Make sure that signals handlers invoked by
- * meta_window_set_focused_internal() don't see
- * display->focus_window->has_focus == FALSE
- */
- previous = display->focus_window;
- display->focus_window = NULL;
-
- meta_window_set_focused_internal (previous, FALSE);
- }
-
- display->focus_window = window;
-
- if (display->focus_window)
- {
- meta_topic (META_DEBUG_FOCUS, "* Focus --> %s",
- display->focus_window->desc);
- meta_window_set_focused_internal (display->focus_window, TRUE);
- }
- else
- meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL");
-
- if (meta_is_wayland_compositor ())
- meta_display_sync_wayland_input_focus (display);
-
- g_object_notify (G_OBJECT (display), "focus-window");
-}
-
-gboolean
-meta_display_timestamp_too_old (MetaDisplay *display,
- guint32 *timestamp)
-{
- /* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
- * us to sanity check the timestamp here and ensure it doesn't correspond to
- * a future time (though we would want to rename to
- * timestamp_too_old_or_in_future).
- */
-
- if (*timestamp == META_CURRENT_TIME)
- {
- *timestamp = meta_display_get_current_time_roundtrip (display);
- return FALSE;
- }
- else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
- {
- if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
- return TRUE;
- else
- {
- *timestamp = display->last_focus_time;
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
-void
-meta_display_set_input_focus (MetaDisplay *display,
- MetaWindow *window,
- gboolean focus_frame,
- guint32 timestamp)
-{
- if (meta_display_timestamp_too_old (display, &timestamp))
- return;
-
- if (display->x11_display)
- {
- meta_x11_display_set_input_focus (display->x11_display, window,
- focus_frame, timestamp);
- }
-
- meta_display_update_focus_window (display, window);
-
- display->last_focus_time = timestamp;
-
- if (window == NULL || window != display->autoraise_window)
- meta_display_remove_autoraise_callback (display);
-}
-
-void
-meta_display_unset_input_focus (MetaDisplay *display,
- guint32 timestamp)
-{
- meta_display_set_input_focus (display, NULL, FALSE, timestamp);
-}
-
-void
-meta_display_register_wayland_window (MetaDisplay *display,
- MetaWindow *window)
-{
- g_hash_table_add (display->wayland_windows, window);
-}
-
-void
-meta_display_unregister_wayland_window (MetaDisplay *display,
- MetaWindow *window)
-{
- g_hash_table_remove (display->wayland_windows, window);
-}
-
-MetaWindow*
-meta_display_lookup_stamp (MetaDisplay *display,
- guint64 stamp)
-{
- return g_hash_table_lookup (display->stamps, &stamp);
-}
-
-void
-meta_display_register_stamp (MetaDisplay *display,
- guint64 *stampp,
- MetaWindow *window)
-{
- g_return_if_fail (g_hash_table_lookup (display->stamps, stampp) == NULL);
-
- g_hash_table_insert (display->stamps, stampp, window);
-}
-
-void
-meta_display_unregister_stamp (MetaDisplay *display,
- guint64 stamp)
-{
- g_return_if_fail (g_hash_table_lookup (display->stamps, &stamp) != NULL);
-
- g_hash_table_remove (display->stamps, &stamp);
-}
-
-MetaWindow*
-meta_display_lookup_stack_id (MetaDisplay *display,
- guint64 stack_id)
-{
- if (META_STACK_ID_IS_X11 (stack_id))
- {
- if (!display->x11_display)
- return NULL;
- return meta_x11_display_lookup_x_window (display->x11_display,
- (Window)stack_id);
- }
- else
- {
- return meta_display_lookup_stamp (display, stack_id);
- }
-}
-
-/* We return a pointer into a ring of static buffers. This is to make
- * using this function for debug-logging convenient and avoid temporary
- * strings that must be freed. */
-const char *
-meta_display_describe_stack_id (MetaDisplay *display,
- guint64 stack_id)
-{
- /* 0x<64-bit: 16 characters> (<10 characters of title>)\0' */
- static char buffer[5][32];
- MetaWindow *window;
- static int pos = 0;
- char *result;
-
- result = buffer[pos];
- pos = (pos + 1) % 5;
-
- window = meta_display_lookup_stack_id (display, stack_id);
-
- if (window && window->title)
- snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x (%.10s)", stack_id, window->title);
- else
- snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x", stack_id);
-
- return result;
-}
-
-void
-meta_display_notify_window_created (MetaDisplay *display,
- MetaWindow *window)
-{
- COGL_TRACE_BEGIN_SCOPED (MetaDisplayNotifyWindowCreated,
- "Display (notify window created)");
- g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
-}
-
-static MetaCursor
-meta_cursor_for_grab_op (MetaGrabOp op)
-{
- switch (op)
- {
- case META_GRAB_OP_RESIZING_SE:
- case META_GRAB_OP_KEYBOARD_RESIZING_SE:
- return META_CURSOR_SE_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_S:
- case META_GRAB_OP_KEYBOARD_RESIZING_S:
- return META_CURSOR_SOUTH_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_SW:
- case META_GRAB_OP_KEYBOARD_RESIZING_SW:
- return META_CURSOR_SW_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_N:
- case META_GRAB_OP_KEYBOARD_RESIZING_N:
- return META_CURSOR_NORTH_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_NE:
- case META_GRAB_OP_KEYBOARD_RESIZING_NE:
- return META_CURSOR_NE_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_NW:
- case META_GRAB_OP_KEYBOARD_RESIZING_NW:
- return META_CURSOR_NW_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_W:
- case META_GRAB_OP_KEYBOARD_RESIZING_W:
- return META_CURSOR_WEST_RESIZE;
- break;
- case META_GRAB_OP_RESIZING_E:
- case META_GRAB_OP_KEYBOARD_RESIZING_E:
- return META_CURSOR_EAST_RESIZE;
- break;
- case META_GRAB_OP_MOVING:
- case META_GRAB_OP_KEYBOARD_MOVING:
- case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
- return META_CURSOR_MOVE_OR_RESIZE_WINDOW;
- break;
- default:
- break;
- }
-
- return META_CURSOR_DEFAULT;
-}
-
-static void
-root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
- float best_scale,
- int x,
- int y,
- MetaDisplay *display)
-{
- MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
- MetaBackend *backend = meta_get_backend ();
-
- if (meta_is_stage_views_scaled ())
- {
- if (best_scale != 0.0f)
- {
- float ceiled_scale;
-
- ceiled_scale = ceilf (best_scale);
- meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
- (int) ceiled_scale);
- meta_cursor_sprite_set_texture_scale (cursor_sprite,
- 1.0 / ceiled_scale);
- }
- }
- else
- {
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
-
- /* Reload the cursor texture if the scale has changed. */
- if (logical_monitor)
- {
- meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
- logical_monitor->scale);
- meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0);
- }
- }
-}
-
-static void
-manage_root_cursor_sprite_scale (MetaDisplay *display,
- MetaCursorSpriteXcursor *sprite_xcursor)
-{
- g_signal_connect_object (sprite_xcursor,
- "prepare-at",
- G_CALLBACK (root_cursor_prepare_at),
- display,
- 0);
-}
-
-void
-meta_display_reload_cursor (MetaDisplay *display)
-{
- MetaCursor cursor = display->current_cursor;
- MetaCursorSpriteXcursor *sprite_xcursor;
- MetaBackend *backend = meta_get_backend ();
- MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
-
- sprite_xcursor = meta_cursor_sprite_xcursor_new (cursor);
-
- if (meta_is_wayland_compositor ())
- manage_root_cursor_sprite_scale (display, sprite_xcursor);
-
- meta_cursor_tracker_set_root_cursor (cursor_tracker,
- META_CURSOR_SPRITE (sprite_xcursor));
- g_object_unref (sprite_xcursor);
-
- g_signal_emit (display, display_signals[CURSOR_UPDATED], 0, display);
-}
-
-void
-meta_display_set_cursor (MetaDisplay *display,
- MetaCursor cursor)
-{
- if (cursor == display->current_cursor)
- return;
-
- display->current_cursor = cursor;
- meta_display_reload_cursor (display);
-}
-
-void
-meta_display_update_cursor (MetaDisplay *display)
-{
- meta_display_set_cursor (display, meta_cursor_for_grab_op (display->grab_op));
-}
-
-static MetaWindow *
-get_first_freefloating_window (MetaWindow *window)
-{
- while (meta_window_is_attached_dialog (window))
- window = meta_window_get_transient_for (window);
-
- /* Attached dialogs should always have a non-NULL transient-for */
- g_assert (window != NULL);
-
- return window;
-}
-
-static MetaEventRoute
-get_event_route_from_grab_op (MetaGrabOp op)
-{
- switch (META_GRAB_OP_GET_BASE_TYPE (op))
- {
- case META_GRAB_OP_NONE:
- /* begin_grab_op shouldn't be called with META_GRAB_OP_NONE. */
- g_assert_not_reached ();
-
- case META_GRAB_OP_WINDOW_BASE:
- return META_EVENT_ROUTE_WINDOW_OP;
-
- case META_GRAB_OP_COMPOSITOR:
- /* begin_grab_op shouldn't be called with META_GRAB_OP_COMPOSITOR. */
- g_assert_not_reached ();
-
- case META_GRAB_OP_WAYLAND_POPUP:
- return META_EVENT_ROUTE_WAYLAND_POPUP;
-
- case META_GRAB_OP_FRAME_BUTTON:
- return META_EVENT_ROUTE_FRAME_BUTTON;
-
- default:
- g_assert_not_reached ();
- return 0;
- }
-}
-
-gboolean
-meta_display_begin_grab_op (MetaDisplay *display,
- MetaWindow *window,
- MetaGrabOp op,
- gboolean pointer_already_grabbed,
- gboolean frame_action,
- int button,
- gulong modmask, /* XXX - ignored */
- guint32 timestamp,
- int root_x,
- int root_y)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaWindow *grab_window = NULL;
- MetaEventRoute event_route;
-
- g_assert (window != NULL);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d",
- op, window->desc, button, pointer_already_grabbed,
- root_x, root_y);
-
- if (display->grab_op != META_GRAB_OP_NONE)
- {
- meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect",
- op, window->desc, display->grab_op,
- display->grab_window ? display->grab_window->desc : "none");
- return FALSE;
- }
-
- event_route = get_event_route_from_grab_op (op);
-
- if (event_route == META_EVENT_ROUTE_WINDOW_OP)
- {
- if (meta_prefs_get_raise_on_click ())
- meta_window_raise (window);
- else
- {
- display->grab_initial_x = root_x;
- display->grab_initial_y = root_y;
- display->grab_threshold_movement_reached = FALSE;
- }
- }
-
- grab_window = window;
-
- /* If we're trying to move a window, move the first
- * non-attached dialog instead.
- */
- if (meta_grab_op_is_moving (op))
- grab_window = get_first_freefloating_window (window);
-
- g_assert (grab_window != NULL);
- g_assert (op != META_GRAB_OP_NONE);
-
- display->grab_have_pointer = FALSE;
-
- if (pointer_already_grabbed)
- display->grab_have_pointer = TRUE;
-
- if (META_IS_BACKEND_X11 (meta_get_backend ()) && display->x11_display)
- {
- /* Since grab operations often happen as a result of implicit
- * pointer operations on the display X11 connection, we need
- * to ungrab here to ensure that the backend's X11 can take
- * the device grab. */
- XIUngrabDevice (display->x11_display->xdisplay,
- META_VIRTUAL_CORE_POINTER_ID,
- timestamp);
- XSync (display->x11_display->xdisplay, False);
- }
-
- if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
- display->grab_have_pointer = TRUE;
-
- if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op))
- {
- meta_topic (META_DEBUG_WINDOW_OPS, "XIGrabDevice() failed");
- return FALSE;
- }
-
- /* Grab keys when beginning window ops; see #126497 */
- if (event_route == META_EVENT_ROUTE_WINDOW_OP)
- {
- display->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp);
-
- if (!display->grab_have_keyboard)
- {
- meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer");
- meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
- display->grab_have_pointer = FALSE;
- return FALSE;
- }
- }
-
- display->event_route = event_route;
- display->grab_op = op;
- display->grab_window = grab_window;
- display->grab_button = button;
- display->grab_tile_mode = grab_window->tile_mode;
- display->grab_tile_monitor_number = grab_window->tile_monitor_number;
- display->grab_anchor_root_x = root_x;
- display->grab_anchor_root_y = root_y;
- display->grab_latest_motion_x = root_x;
- display->grab_latest_motion_y = root_y;
- display->grab_last_moveresize_time = 0;
- display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT;
- display->grab_frame_action = frame_action;
-
- meta_display_update_cursor (display);
-
- g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Grab op %u on window %s successful",
- display->grab_op, window ? window->desc : "(null)");
-
- meta_window_get_frame_rect (display->grab_window,
- &display->grab_initial_window_pos);
- display->grab_anchor_window_pos = display->grab_initial_window_pos;
-
- if (meta_is_wayland_compositor ())
- {
- meta_display_sync_wayland_input_focus (display);
- meta_display_cancel_touch (display);
- }
-
- g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0,
- display->grab_window, display->grab_op);
-
- if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
- meta_window_grab_op_began (display->grab_window, display->grab_op);
-
- return TRUE;
-}
-
-void
-meta_display_end_grab_op (MetaDisplay *display,
- guint32 timestamp)
-{
- MetaWindow *grab_window = display->grab_window;
- MetaGrabOp grab_op = display->grab_op;
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Ending grab op %u at time %u", grab_op, timestamp);
-
- if (display->event_route == META_EVENT_ROUTE_NORMAL ||
- display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
- return;
-
- g_assert (grab_window != NULL);
-
- /* We need to reset this early, since the
- * meta_window_grab_op_ended callback relies on this being
- * up to date. */
- display->grab_op = META_GRAB_OP_NONE;
-
- if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
- {
- /* Clear out the edge cache */
- meta_display_cleanup_edges (display);
-
- /* Only raise the window in orthogonal raise
- * ('do-not-raise-on-click') mode if the user didn't try to move
- * or resize the given window by at least a threshold amount.
- * For raise on click mode, the window was raised at the
- * beginning of the grab_op.
- */
- if (!meta_prefs_get_raise_on_click () &&
- !display->grab_threshold_movement_reached)
- meta_window_raise (display->grab_window);
-
- meta_window_grab_op_ended (grab_window, grab_op);
- }
-
- if (display->grab_have_pointer)
- {
- MetaBackend *backend = meta_get_backend ();
- meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
- }
-
- if (display->grab_have_keyboard)
- {
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Ungrabbing all keys timestamp %u", timestamp);
- meta_window_ungrab_all_keys (grab_window, timestamp);
- }
-
- display->event_route = META_EVENT_ROUTE_NORMAL;
- display->grab_window = NULL;
- display->grab_button = 0;
- display->grab_tile_mode = META_TILE_NONE;
- display->grab_tile_monitor_number = -1;
- display->grab_anchor_root_x = 0;
- display->grab_anchor_root_y = 0;
- display->grab_latest_motion_x = 0;
- display->grab_latest_motion_y = 0;
- display->grab_last_moveresize_time = 0;
- display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT;
- display->grab_frame_action = FALSE;
-
- meta_display_update_cursor (display);
-
- g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove);
-
- if (meta_is_wayland_compositor ())
- meta_display_sync_wayland_input_focus (display);
-
- g_signal_emit (display, display_signals[GRAB_OP_END], 0,
- grab_window, grab_op);
-}
-
-/**
- * meta_display_get_grab_op:
- * @display: The #MetaDisplay that the window is on
-
- * Gets the current grab operation, if any.
- *
- * Return value: the current grab operation, or %META_GRAB_OP_NONE if
- * Mutter doesn't currently have a grab. %META_GRAB_OP_COMPOSITOR will
- * be returned if a compositor-plugin modal operation is in effect
- * (See mutter_begin_modal_for_plugin())
- */
-MetaGrabOp
-meta_display_get_grab_op (MetaDisplay *display)
-{
- return display->grab_op;
-}
-
-void
-meta_display_check_threshold_reached (MetaDisplay *display,
- int x,
- int y)
-{
- /* Don't bother doing the check again if we've already reached the threshold */
- if (meta_prefs_get_raise_on_click () ||
- display->grab_threshold_movement_reached)
- return;
-
- if (ABS (display->grab_initial_x - x) >= 8 ||
- ABS (display->grab_initial_y - y) >= 8)
- display->grab_threshold_movement_reached = TRUE;
-}
-
-void
-meta_display_queue_retheme_all_windows (MetaDisplay *display)
-{
- GSList* windows;
- GSList *tmp;
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
- meta_window_frame_size_changed (window);
- if (window->frame)
- {
- meta_frame_queue_draw (window->frame);
- }
-
- tmp = tmp->next;
- }
-
- g_slist_free (windows);
-}
-
-/*
- * Stores whether syncing is currently enabled.
- */
-static gboolean is_syncing = FALSE;
-
-/**
- * meta_is_syncing:
- *
- * Returns whether X synchronisation is currently enabled.
- *
- * FIXME: This is *only* called by meta_display_open(), but by that time
- * we have already turned syncing on or off on startup, and we don't
- * have any way to do so while Mutter is running, so it's rather
- * pointless.
- *
- * Returns: %TRUE if we must wait for events whenever we send X requests;
- * %FALSE otherwise.
- */
-gboolean
-meta_is_syncing (void)
-{
- return is_syncing;
-}
-
-/**
- * meta_set_syncing:
- * @setting: whether to turn syncing on or off
- *
- * A handy way to turn on synchronisation on or off for every display.
- */
-void
-meta_set_syncing (gboolean setting)
-{
- if (setting != is_syncing)
- {
- is_syncing = setting;
- if (meta_get_display ())
- XSynchronize (meta_get_display ()->x11_display->xdisplay, is_syncing);
- }
-}
-
-/**
- * meta_display_ping_timeout:
- * @data: All the information about this ping. It is a #MetaPingData
- * cast to a #gpointer in order to be passable to a timeout function.
- * This function will also free this parameter.
- *
- * Does whatever it is we decided to do when a window didn't respond
- * to a ping. We also remove the ping from the display's list of
- * pending pings. This function is called by the event loop when the timeout
- * times out which we created at the start of the ping.
- *
- * Returns: Always returns %FALSE, because this function is called as a
- * timeout and we don't want to run the timer again.
- */
-static gboolean
-meta_display_ping_timeout (gpointer data)
-{
- MetaPingData *ping_data = data;
- MetaWindow *window = ping_data->window;
- MetaDisplay *display = window->display;
-
- meta_window_set_alive (window, FALSE);
-
- ping_data->ping_timeout_id = 0;
-
- meta_topic (META_DEBUG_PING,
- "Ping %u on window %s timed out",
- ping_data->serial, ping_data->window->desc);
-
- display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
- ping_data_free (ping_data);
-
- return FALSE;
-}
-
-/**
- * meta_display_ping_window:
- * @display: The #MetaDisplay that the window is on
- * @window: The #MetaWindow to send the ping to
- * @timestamp: The timestamp of the ping. Used for uniqueness.
- * Cannot be CurrentTime; use a real timestamp!
- *
- * Sends a ping request to a window. The window must respond to
- * the request within a certain amount of time. If it does, we
- * will call one callback; if the time passes and we haven't had
- * a response, we call a different callback. The window must have
- * the hint showing that it can respond to a ping; if it doesn't,
- * we call the "got a response" callback immediately and return.
- * This function returns straight away after setting things up;
- * the callbacks will be called from the event loop.
- */
-void
-meta_display_ping_window (MetaWindow *window,
- guint32 serial)
-{
- GSList *l;
- MetaDisplay *display = window->display;
- MetaPingData *ping_data;
- unsigned int check_alive_timeout;
-
- check_alive_timeout = meta_prefs_get_check_alive_timeout ();
- if (check_alive_timeout == 0)
- return;
-
- if (serial == 0)
- {
- meta_warning ("Tried to ping window %s with a bad serial! Not allowed.",
- window->desc);
- return;
- }
-
- if (!meta_window_can_ping (window))
- return;
-
- for (l = display->pending_pings; l; l = l->next)
- {
- MetaPingData *ping_data = l->data;
-
- if (window == ping_data->window)
- {
- meta_topic (META_DEBUG_PING,
- "Window %s already is being pinged with serial %u",
- window->desc, ping_data->serial);
- return;
- }
-
- if (serial == ping_data->serial)
- {
- meta_warning ("Ping serial %u was reused for window %s, "
- "previous use was for window %s.",
- serial, window->desc, ping_data->window->desc);
- return;
- }
- }
-
- ping_data = g_new (MetaPingData, 1);
- ping_data->window = window;
- ping_data->serial = serial;
- ping_data->ping_timeout_id =
- g_timeout_add (check_alive_timeout,
- meta_display_ping_timeout,
- ping_data);
- g_source_set_name_by_id (ping_data->ping_timeout_id, "[mutter] meta_display_ping_timeout");
-
- display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
-
- meta_topic (META_DEBUG_PING,
- "Sending ping with serial %u to window %s",
- serial, window->desc);
-
- META_WINDOW_GET_CLASS (window)->ping (window, serial);
-}
-
-/**
- * meta_display_pong_for_serial:
- * @display: the display we got the pong from
- * @serial: the serial in the pong response
- *
- * Process the pong (the response message) from the ping we sent
- * to the window. This involves removing the timeout, calling the
- * reply handler function, and freeing memory.
- */
-void
-meta_display_pong_for_serial (MetaDisplay *display,
- guint32 serial)
-{
- GSList *tmp;
-
- meta_topic (META_DEBUG_PING, "Received a pong with serial %u", serial);
-
- for (tmp = display->pending_pings; tmp; tmp = tmp->next)
- {
- MetaPingData *ping_data = tmp->data;
-
- if (serial == ping_data->serial)
- {
- meta_topic (META_DEBUG_PING,
- "Matching ping found for pong %u",
- ping_data->serial);
-
- /* Remove the ping data from the list */
- display->pending_pings = g_slist_remove (display->pending_pings,
- ping_data);
-
- /* Remove the timeout */
- g_clear_handle_id (&ping_data->ping_timeout_id, g_source_remove);
-
- meta_window_set_alive (ping_data->window, TRUE);
- ping_data_free (ping_data);
- break;
- }
- }
-}
-
-static MetaGroup *
-get_focused_group (MetaDisplay *display)
-{
- if (display->focus_window)
- return display->focus_window->group;
- else
- return NULL;
-}
-
-#define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
- || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
- || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focused_group (w->display))) \
- || ((t) == META_TAB_LIST_NORMAL_ALL && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w)))
-
-static MetaWindow*
-find_tab_forward (MetaDisplay *display,
- MetaTabList type,
- MetaWorkspace *workspace,
- GList *start,
- gboolean skip_first)
-{
- GList *tmp;
-
- g_return_val_if_fail (start != NULL, NULL);
- g_return_val_if_fail (workspace != NULL, NULL);
-
- tmp = start;
- if (skip_first)
- tmp = tmp->next;
-
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- if (IN_TAB_CHAIN (window, type))
- return window;
-
- tmp = tmp->next;
- }
-
- tmp = workspace->mru_list;
- while (tmp != start)
- {
- MetaWindow *window = tmp->data;
-
- if (IN_TAB_CHAIN (window, type))
- return window;
-
- tmp = tmp->next;
- }
-
- return NULL;
-}
-
-static MetaWindow*
-find_tab_backward (MetaDisplay *display,
- MetaTabList type,
- MetaWorkspace *workspace,
- GList *start,
- gboolean skip_last)
-{
- GList *tmp;
-
- g_return_val_if_fail (start != NULL, NULL);
- g_return_val_if_fail (workspace != NULL, NULL);
-
- tmp = start;
- if (skip_last)
- tmp = tmp->prev;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- if (IN_TAB_CHAIN (window, type))
- return window;
-
- tmp = tmp->prev;
- }
-
- tmp = g_list_last (workspace->mru_list);
- while (tmp != start)
- {
- MetaWindow *window = tmp->data;
-
- if (IN_TAB_CHAIN (window, type))
- return window;
-
- tmp = tmp->prev;
- }
-
- return NULL;
-}
-
-static int
-mru_cmp (gconstpointer a,
- gconstpointer b)
-{
- guint32 time_a, time_b;
-
- time_a = meta_window_get_user_time ((MetaWindow *)a);
- time_b = meta_window_get_user_time ((MetaWindow *)b);
-
- if (time_a > time_b)
- return -1;
- else if (time_a < time_b)
- return 1;
- else
- return 0;
-}
-
-/**
- * meta_display_get_tab_list:
- * @display: a #MetaDisplay
- * @type: type of tab list
- * @workspace: (nullable): origin workspace
- *
- * Determine the list of windows that should be displayed for Alt-TAB
- * functionality. The windows are returned in most recently used order.
- * If @workspace is not %NULL, the list only contains windows that are on
- * @workspace or have the demands-attention hint set; otherwise it contains
- * all windows.
- *
- * Returns: (transfer container) (element-type Meta.Window): List of windows
- */
-GList*
-meta_display_get_tab_list (MetaDisplay *display,
- MetaTabList type,
- MetaWorkspace *workspace)
-{
- GList *tab_list = NULL;
- GList *global_mru_list = NULL;
- GList *mru_list, *tmp;
- GSList *windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- GSList *w;
-
- if (workspace == NULL)
- {
- /* Yay for mixing GList and GSList in the API */
- for (w = windows; w; w = w->next)
- global_mru_list = g_list_prepend (global_mru_list, w->data);
- global_mru_list = g_list_sort (global_mru_list, mru_cmp);
- }
-
- mru_list = workspace ? workspace->mru_list : global_mru_list;
-
- /* Windows sellout mode - MRU order. Collect unminimized windows
- * then minimized so minimized windows aren't in the way so much.
- */
- for (tmp = mru_list; tmp; tmp = tmp->next)
- {
- MetaWindow *window = tmp->data;
-
- if (!window->minimized && IN_TAB_CHAIN (window, type))
- tab_list = g_list_prepend (tab_list, window);
- }
-
- for (tmp = mru_list; tmp; tmp = tmp->next)
- {
- MetaWindow *window = tmp->data;
-
- if (window->minimized && IN_TAB_CHAIN (window, type))
- tab_list = g_list_prepend (tab_list, window);
- }
-
- tab_list = g_list_reverse (tab_list);
-
- /* If filtering by workspace, include windows from
- * other workspaces that demand attention
- */
- if (workspace)
- for (w = windows; w; w = w->next)
- {
- MetaWindow *l_window = w->data;
-
- if (l_window->wm_state_demands_attention &&
- !meta_window_located_on_workspace (l_window, workspace) &&
- IN_TAB_CHAIN (l_window, type))
- tab_list = g_list_prepend (tab_list, l_window);
- }
-
- g_list_free (global_mru_list);
- g_slist_free (windows);
-
- return tab_list;
-}
-
-/**
- * meta_display_get_tab_next:
- * @display: a #MetaDisplay
- * @type: type of tab list
- * @workspace: origin workspace
- * @window: (nullable): starting window
- * @backward: If %TRUE, look for the previous window.
- *
- * Determine the next window that should be displayed for Alt-TAB
- * functionality.
- *
- * Returns: (transfer none): Next window
- *
- */
-MetaWindow*
-meta_display_get_tab_next (MetaDisplay *display,
- MetaTabList type,
- MetaWorkspace *workspace,
- MetaWindow *window,
- gboolean backward)
-{
- gboolean skip;
- GList *tab_list;
- MetaWindow *ret;
- tab_list = meta_display_get_tab_list (display, type, workspace);
-
- if (tab_list == NULL)
- return NULL;
-
- if (window != NULL)
- {
- g_assert (window->display == display);
-
- if (backward)
- ret = find_tab_backward (display, type, workspace, g_list_find (tab_list, window), TRUE);
- else
- ret = find_tab_forward (display, type, workspace, g_list_find (tab_list, window), TRUE);
- }
- else
- {
- skip = display->focus_window != NULL &&
- tab_list->data == display->focus_window;
- if (backward)
- ret = find_tab_backward (display, type, workspace, tab_list, skip);
- else
- ret = find_tab_forward (display, type, workspace, tab_list, skip);
- }
-
- g_list_free (tab_list);
- return ret;
-}
-
-/**
- * meta_display_get_tab_current:
- * @display: a #MetaDisplay
- * @type: type of tab list
- * @workspace: origin workspace
- *
- * Determine the active window that should be displayed for Alt-TAB.
- *
- * Returns: (transfer none): Current window
- *
- */
-MetaWindow*
-meta_display_get_tab_current (MetaDisplay *display,
- MetaTabList type,
- MetaWorkspace *workspace)
-{
- MetaWindow *window;
-
- window = display->focus_window;
-
- if (window != NULL &&
- IN_TAB_CHAIN (window, type) &&
- (workspace == NULL ||
- meta_window_located_on_workspace (window, workspace)))
- return window;
- else
- return NULL;
-}
-
-MetaGravity
-meta_resize_gravity_from_grab_op (MetaGrabOp op)
-{
- MetaGravity gravity;
-
- gravity = -1;
- switch (op)
- {
- case META_GRAB_OP_RESIZING_SE:
- case META_GRAB_OP_KEYBOARD_RESIZING_SE:
- gravity = META_GRAVITY_NORTH_WEST;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_S:
- case META_GRAB_OP_RESIZING_S:
- gravity = META_GRAVITY_NORTH;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_SW:
- case META_GRAB_OP_RESIZING_SW:
- gravity = META_GRAVITY_NORTH_EAST;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_N:
- case META_GRAB_OP_RESIZING_N:
- gravity = META_GRAVITY_SOUTH;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_NE:
- case META_GRAB_OP_RESIZING_NE:
- gravity = META_GRAVITY_SOUTH_WEST;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_NW:
- case META_GRAB_OP_RESIZING_NW:
- gravity = META_GRAVITY_SOUTH_EAST;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_E:
- case META_GRAB_OP_RESIZING_E:
- gravity = META_GRAVITY_WEST;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_W:
- case META_GRAB_OP_RESIZING_W:
- gravity = META_GRAVITY_EAST;
- break;
- case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
- gravity = META_GRAVITY_CENTER;
- break;
- default:
- break;
- }
-
- return gravity;
-}
-
-void
-meta_display_manage_all_xwindows (MetaDisplay *display)
-{
- guint64 *_children;
- guint64 *children;
- int n_children, i;
-
- meta_stack_freeze (display->stack);
- meta_stack_tracker_get_stack (display->stack_tracker, &_children, &n_children);
-
- /* Copy the stack as it will be modified as part of the loop */
- children = g_memdup2 (_children, sizeof (uint64_t) * n_children);
-
- for (i = 0; i < n_children; ++i)
- {
- if (!META_STACK_ID_IS_X11 (children[i]))
- continue;
- meta_window_x11_new (display, children[i], TRUE,
- META_COMP_EFFECT_NONE);
- }
-
- g_free (children);
- meta_stack_thaw (display->stack);
-}
-
-void
-meta_display_unmanage_windows (MetaDisplay *display,
- guint32 timestamp)
-{
- GSList *tmp;
- GSList *winlist;
-
- winlist = meta_display_list_windows (display,
- META_LIST_INCLUDE_OVERRIDE_REDIRECT);
- winlist = g_slist_sort (winlist, meta_display_stack_cmp);
- g_slist_foreach (winlist, (GFunc)g_object_ref, NULL);
-
- /* Unmanage all windows */
- tmp = winlist;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- /* Check if already unmanaged for safety - in particular, catch
- * the case where unmanaging a parent window can cause attached
- * dialogs to be (temporarily) unmanaged.
- */
- if (!window->unmanaging)
- meta_window_unmanage (window, timestamp);
- g_object_unref (window);
-
- tmp = tmp->next;
- }
- g_slist_free (winlist);
-}
-
-int
-meta_display_stack_cmp (const void *a,
- const void *b)
-{
- MetaWindow *aw = (void*) a;
- MetaWindow *bw = (void*) b;
-
- return meta_stack_windows_cmp (aw->display->stack, aw, bw);
-}
-
-/**
- * meta_display_sort_windows_by_stacking:
- * @display: a #MetaDisplay
- * @windows: (element-type MetaWindow): Set of windows
- *
- * Sorts a set of windows according to their current stacking order. If windows
- * from multiple screens are present in the set of input windows, then all the
- * windows on screen 0 are sorted below all the windows on screen 1, and so forth.
- * Since the stacking order of override-redirect windows isn't controlled by
- * Metacity, if override-redirect windows are in the input, the result may not
- * correspond to the actual stacking order in the X server.
- *
- * An example of using this would be to sort the list of transient dialogs for a
- * window into their current stacking order.
- *
- * Returns: (transfer container) (element-type MetaWindow): Input windows sorted by stacking order, from lowest to highest
- */
-GSList *
-meta_display_sort_windows_by_stacking (MetaDisplay *display,
- GSList *windows)
-{
- GSList *copy = g_slist_copy (windows);
-
- copy = g_slist_sort (copy, meta_display_stack_cmp);
-
- return copy;
-}
-
-static void
-prefs_changed_callback (MetaPreference pref,
- void *data)
-{
- MetaDisplay *display = data;
-
- switch (pref)
- {
- case META_PREF_DRAGGABLE_BORDER_WIDTH:
- meta_display_queue_retheme_all_windows (display);
- break;
- case META_PREF_CURSOR_THEME:
- case META_PREF_CURSOR_SIZE:
- meta_display_reload_cursor (display);
- break;
- default:
- break;
- }
-}
-
-void
-meta_display_sanity_check_timestamps (MetaDisplay *display,
- guint32 timestamp)
-{
- if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
- {
- meta_warning ("last_focus_time (%u) is greater than comparison "
- "timestamp (%u). This most likely represents a buggy "
- "client sending inaccurate timestamps in messages such as "
- "_NET_ACTIVE_WINDOW. Trying to work around...",
- display->last_focus_time, timestamp);
- display->last_focus_time = timestamp;
- }
- if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
- {
- GSList *windows;
- GSList *tmp;
-
- meta_warning ("last_user_time (%u) is greater than comparison "
- "timestamp (%u). This most likely represents a buggy "
- "client sending inaccurate timestamps in messages such as "
- "_NET_ACTIVE_WINDOW. Trying to work around...",
- display->last_user_time, timestamp);
- display->last_user_time = timestamp;
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))
- {
- meta_warning ("%s appears to be one of the offending windows "
- "with a timestamp of %u. Working around...",
- window->desc, window->net_wm_user_time);
- meta_window_set_user_time (window, timestamp);
- }
-
- tmp = tmp->next;
- }
-
- g_slist_free (windows);
- }
-}
-
-void
-meta_display_remove_autoraise_callback (MetaDisplay *display)
-{
- g_clear_handle_id (&display->autoraise_timeout_id, g_source_remove);
- display->autoraise_window = NULL;
-}
-
-void
-meta_display_overlay_key_activate (MetaDisplay *display)
-{
- g_signal_emit (display, display_signals[OVERLAY_KEY], 0);
-}
-
-void
-meta_display_accelerator_activate (MetaDisplay *display,
- guint action,
- ClutterKeyEvent *event)
-{
- g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED], 0,
- action,
- clutter_event_get_source_device ((ClutterEvent *) event),
- event->time);
-}
-
-gboolean
-meta_display_modifiers_accelerator_activate (MetaDisplay *display)
-{
- gboolean freeze;
-
- g_signal_emit (display, display_signals[MODIFIERS_ACCELERATOR_ACTIVATED], 0, &freeze);
-
- return freeze;
-}
-
-/**
- * meta_display_supports_extended_barriers:
- * @display: a #MetaDisplay
- *
- * Returns: whether pointer barriers can be supported.
- *
- * When running as an X compositor the X server needs XInput 2
- * version 2.3. When running as a display server it is supported
- * when running on the native backend.
- *
- * Clients should use this method to determine whether their
- * interfaces should depend on new barrier features.
- */
-gboolean
-meta_display_supports_extended_barriers (MetaDisplay *display)
-{
-#ifdef HAVE_NATIVE_BACKEND
- if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
- return TRUE;
-#endif
-
- if (META_IS_BACKEND_X11_CM (meta_get_backend ()))
- {
- if (meta_is_wayland_compositor())
- return FALSE;
-
- return META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display);
- }
-
- return FALSE;
-}
-
-/**
- * meta_display_get_context:
- * @display: a #MetaDisplay
- *
- * Returns: (transfer none): the #MetaContext
- */
-MetaContext *
-meta_display_get_context (MetaDisplay *display)
-{
- MetaDisplayPrivate *priv = meta_display_get_instance_private (display);
-
- return priv->context;
-}
-
-/**
- * meta_display_get_compositor: (skip)
- * @display: a #MetaDisplay
- *
- */
-MetaCompositor *
-meta_display_get_compositor (MetaDisplay *display)
-{
- return display->compositor;
-}
-
-/**
- * meta_display_get_x11_display: (skip)
- * @display: a #MetaDisplay
- *
- */
-MetaX11Display *
-meta_display_get_x11_display (MetaDisplay *display)
-{
- return display->x11_display;
-}
-
-/**
- * meta_display_get_size:
- * @display: A #MetaDisplay
- * @width: (out): The width of the screen
- * @height: (out): The height of the screen
- *
- * Retrieve the size of the display.
- */
-void
-meta_display_get_size (MetaDisplay *display,
- int *width,
- int *height)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- int display_width, display_height;
-
- meta_monitor_manager_get_screen_size (monitor_manager,
- &display_width,
- &display_height);
-
- if (width != NULL)
- *width = display_width;
-
- if (height != NULL)
- *height = display_height;
-}
-
-/**
- * meta_display_get_focus_window:
- * @display: a #MetaDisplay
- *
- * Get our best guess as to the "currently" focused window (that is,
- * the window that we expect will be focused at the point when the X
- * server processes our next request).
- *
- * Return Value: (transfer none): The current focus window
- */
-MetaWindow *
-meta_display_get_focus_window (MetaDisplay *display)
-{
- return display->focus_window;
-}
-
-/**
- * meta_display_clear_mouse_mode:
- * @display: a #MetaDisplay
- *
- * Sets the mouse-mode flag to %FALSE, which means that motion events are
- * no longer ignored in mouse or sloppy focus.
- * This is an internal function. It should be used only for reimplementing
- * keybindings, and only in a manner compatible with core code.
- */
-void
-meta_display_clear_mouse_mode (MetaDisplay *display)
-{
- display->mouse_mode = FALSE;
-}
-
-MetaGestureTracker *
-meta_display_get_gesture_tracker (MetaDisplay *display)
-{
- return display->gesture_tracker;
-}
-
-gboolean
-meta_display_show_restart_message (MetaDisplay *display,
- const char *message)
-{
- gboolean result = FALSE;
-
- g_signal_emit (display,
- display_signals[SHOW_RESTART_MESSAGE], 0,
- message, &result);
-
- return result;
-}
-
-gboolean
-meta_display_request_restart (MetaDisplay *display)
-{
- gboolean result = FALSE;
-
- g_signal_emit (display,
- display_signals[RESTART], 0,
- &result);
-
- return result;
-}
-
-gboolean
-meta_display_show_resize_popup (MetaDisplay *display,
- gboolean show,
- MetaRectangle *rect,
- int display_w,
- int display_h)
-{
- gboolean result = FALSE;
-
- g_signal_emit (display,
- display_signals[SHOW_RESIZE_POPUP], 0,
- show, rect, display_w, display_h, &result);
-
- return result;
-}
-
-/**
- * meta_display_is_pointer_emulating_sequence:
- * @display: the display
- * @sequence: (nullable): a #ClutterEventSequence
- *
- * Tells whether the event sequence is the used for pointer emulation
- * and single-touch interaction.
- *
- * Returns: #TRUE if the sequence emulates pointer behavior
- **/
-gboolean
-meta_display_is_pointer_emulating_sequence (MetaDisplay *display,
- ClutterEventSequence *sequence)
-{
- if (!sequence)
- return FALSE;
-
- return display->pointer_emulating_sequence == sequence;
-}
-
-void
-meta_display_request_pad_osd (MetaDisplay *display,
- ClutterInputDevice *pad,
- gboolean edition_mode)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaInputMapper *input_mapper;
- const gchar *layout_path = NULL;
- ClutterActor *osd;
- MetaLogicalMonitor *logical_monitor;
- GSettings *settings;
-#ifdef HAVE_LIBWACOM
- WacomDevice *wacom_device;
-#endif
-
- /* Avoid emitting the signal while there is an OSD being currently
- * displayed, the first OSD will have to be dismissed before showing
- * any other one.
- */
- if (display->current_pad_osd)
- return;
-
- input_mapper = meta_backend_get_input_mapper (meta_get_backend ());
-
- if (input_mapper)
- {
- settings = meta_input_mapper_get_tablet_settings (input_mapper, pad);
- logical_monitor =
- meta_input_mapper_get_device_logical_monitor (input_mapper, pad);
-#ifdef HAVE_LIBWACOM
- wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad));
- layout_path = libwacom_get_layout_filename (wacom_device);
-#endif
- }
-
- if (!layout_path || !settings)
- return;
-
- if (!logical_monitor)
- logical_monitor = meta_backend_get_current_logical_monitor (backend);
-
- g_signal_emit (display, display_signals[SHOW_PAD_OSD], 0,
- pad, settings, layout_path,
- edition_mode, logical_monitor->number, &osd);
-
- if (osd)
- {
- display->current_pad_osd = osd;
- g_object_add_weak_pointer (G_OBJECT (display->current_pad_osd),
- (gpointer *) &display->current_pad_osd);
- }
-}
-
-gchar *
-meta_display_get_pad_action_label (MetaDisplay *display,
- ClutterInputDevice *pad,
- MetaPadActionType action_type,
- guint action_number)
-{
- gchar *label;
-
- /* First, lookup the action, as imposed by settings */
- label = meta_pad_action_mapper_get_action_label (display->pad_action_mapper,
- pad, action_type,
- action_number);
- if (label)
- return label;
-
-#ifdef HAVE_WAYLAND
- /* Second, if this wayland, lookup the actions set by the clients */
- if (meta_is_wayland_compositor ())
- {
- MetaWaylandCompositor *compositor;
- MetaWaylandTabletSeat *tablet_seat;
- MetaWaylandTabletPad *tablet_pad = NULL;
-
- compositor = meta_wayland_compositor_get_default ();
- tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager,
- compositor->seat);
- if (tablet_seat)
- tablet_pad = meta_wayland_tablet_seat_lookup_pad (tablet_seat, pad);
-
- if (tablet_pad)
- {
- label = meta_wayland_tablet_pad_get_label (tablet_pad, action_type,
- action_number);
- }
-
- if (label)
- return label;
- }
-#endif
-
- return NULL;
-}
-
-static void
-meta_display_show_osd (MetaDisplay *display,
- gint monitor_idx,
- const gchar *icon_name,
- const gchar *message)
-{
- g_signal_emit (display, display_signals[SHOW_OSD], 0,
- monitor_idx, icon_name, message);
-}
-
-static gint
-lookup_tablet_monitor (MetaDisplay *display,
- ClutterInputDevice *device)
-{
- MetaInputMapper *input_mapper;
- MetaLogicalMonitor *monitor;
- gint monitor_idx = -1;
-
- input_mapper = meta_backend_get_input_mapper (meta_get_backend ());
- if (!input_mapper)
- return -1;
-
- monitor = meta_input_mapper_get_device_logical_monitor (input_mapper, device);
-
- if (monitor)
- {
- monitor_idx = meta_display_get_monitor_index_for_rect (display,
- &monitor->rect);
- }
-
- return monitor_idx;
-}
-
-void
-meta_display_show_tablet_mapping_notification (MetaDisplay *display,
- ClutterInputDevice *pad,
- const gchar *pretty_name)
-{
- if (!pretty_name)
- pretty_name = clutter_input_device_get_device_name (pad);
- meta_display_show_osd (display, lookup_tablet_monitor (display, pad),
- "input-tablet-symbolic", pretty_name);
-}
-
-void
-meta_display_notify_pad_group_switch (MetaDisplay *display,
- ClutterInputDevice *pad,
- const gchar *pretty_name,
- guint n_group,
- guint n_mode,
- guint n_modes)
-{
- GString *message;
- guint i;
-
- if (!pretty_name)
- pretty_name = clutter_input_device_get_device_name (pad);
-
- message = g_string_new (pretty_name);
- g_string_append_c (message, '\n');
- for (i = 0; i < n_modes; i++)
- g_string_append (message, (i == n_mode) ? "⚫" : "⚪");
-
- meta_display_show_osd (display, lookup_tablet_monitor (display, pad),
- "input-tablet-symbolic", message->str);
-
- g_signal_emit (display, display_signals[PAD_MODE_SWITCH], 0, pad,
- n_group, n_mode);
-
- g_string_free (message, TRUE);
-}
-
-void
-meta_display_foreach_window (MetaDisplay *display,
- MetaListWindowsFlags flags,
- MetaDisplayWindowFunc func,
- gpointer data)
-{
- GSList *windows;
-
- /* If we end up doing this often, just keeping a list
- * of windows might be sensible.
- */
-
- windows = meta_display_list_windows (display, flags);
-
- g_slist_foreach (windows, (GFunc) func, data);
-
- g_slist_free (windows);
-}
-
-static void
-meta_display_resize_func (MetaWindow *window,
- gpointer user_data)
-{
- if (window->struts)
- {
- meta_window_update_struts (window);
- }
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
-
- meta_window_recalc_features (window);
-}
-
-static void
-on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
- MetaDisplay *display)
-{
- meta_workspace_manager_reload_work_areas (display->workspace_manager);
-
- /* Fix up monitor for all windows on this display */
- meta_display_foreach_window (display, META_LIST_INCLUDE_OVERRIDE_REDIRECT,
- (MetaDisplayWindowFunc)
- meta_window_update_for_monitors_changed, 0);
-
- /* Queue a resize on all the windows */
- meta_display_foreach_window (display, META_LIST_DEFAULT,
- meta_display_resize_func, 0);
-
- meta_display_queue_check_fullscreen (display);
-}
-
-void
-meta_display_restacked (MetaDisplay *display)
-{
- g_signal_emit (display, display_signals[RESTACKED], 0);
-}
-
-static gboolean
-meta_display_update_tile_preview_timeout (gpointer data)
-{
- MetaDisplay *display = data;
- MetaWindow *window = display->grab_window;
- gboolean needs_preview = FALSE;
-
- display->tile_preview_timeout_id = 0;
-
- if (window)
- {
- switch (display->preview_tile_mode)
- {
- case META_TILE_LEFT:
- case META_TILE_RIGHT:
- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
- needs_preview = TRUE;
- break;
-
- case META_TILE_MAXIMIZED:
- if (!META_WINDOW_MAXIMIZED (window))
- needs_preview = TRUE;
- break;
-
- default:
- needs_preview = FALSE;
- break;
- }
- }
-
- if (needs_preview)
- {
- MetaRectangle tile_rect;
- int monitor;
-
- monitor = meta_window_get_current_tile_monitor_number (window);
- meta_window_get_tile_area (window, display->preview_tile_mode,
- &tile_rect);
- meta_compositor_show_tile_preview (display->compositor,
- window, &tile_rect, monitor);
- }
- else
- meta_compositor_hide_tile_preview (display->compositor);
-
- return FALSE;
-}
-
-#define TILE_PREVIEW_TIMEOUT_MS 200
-
-void
-meta_display_update_tile_preview (MetaDisplay *display,
- gboolean delay)
-{
- if (delay)
- {
- if (display->tile_preview_timeout_id > 0)
- return;
-
- display->tile_preview_timeout_id =
- g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
- meta_display_update_tile_preview_timeout,
- display);
- g_source_set_name_by_id (display->tile_preview_timeout_id,
- "[mutter] meta_display_update_tile_preview_timeout");
- }
- else
- {
- g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove);
-
- meta_display_update_tile_preview_timeout ((gpointer)display);
- }
-}
-
-void
-meta_display_hide_tile_preview (MetaDisplay *display)
-{
- g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove);
-
- display->preview_tile_mode = META_TILE_NONE;
- meta_compositor_hide_tile_preview (display->compositor);
-}
-
-static MetaStartupSequence *
-find_startup_sequence_by_wmclass (MetaDisplay *display,
- MetaWindow *window)
-{
- GSList *startup_sequences, *l;
-
- startup_sequences =
- meta_startup_notification_get_sequences (display->startup_notification);
-
- for (l = startup_sequences; l; l = l->next)
- {
- MetaStartupSequence *sequence = l->data;
- const char *wmclass;
-
- wmclass = meta_startup_sequence_get_wmclass (sequence);
-
- if (wmclass != NULL &&
- ((window->res_class &&
- strcmp (wmclass, window->res_class) == 0) ||
- (window->res_name &&
- strcmp (wmclass, window->res_name) == 0)))
- return sequence;
- }
-
- return NULL;
-}
-
-/* Sets the initial_timestamp and initial_workspace properties
- * of a window according to information given us by the
- * startup-notification library.
- *
- * Returns TRUE if startup properties have been applied, and
- * FALSE if they have not (for example, if they had already
- * been applied.)
- */
-gboolean
-meta_display_apply_startup_properties (MetaDisplay *display,
- MetaWindow *window)
-{
- const char *startup_id;
- MetaStartupSequence *sequence = NULL;
-
- /* Does the window have a startup ID stored? */
- startup_id = meta_window_get_startup_id (window);
-
- meta_topic (META_DEBUG_STARTUP,
- "Applying startup props to %s id \"%s\"",
- window->desc,
- startup_id ? startup_id : "(none)");
-
- if (!startup_id)
- {
- /* No startup ID stored for the window. Let's ask the
- * startup-notification library whether there's anything
- * stored for the resource name or resource class hints.
- */
- sequence = find_startup_sequence_by_wmclass (display, window);
-
- if (sequence)
- {
- g_assert (window->startup_id == NULL);
- window->startup_id = g_strdup (meta_startup_sequence_get_id (sequence));
- startup_id = window->startup_id;
-
- meta_topic (META_DEBUG_STARTUP,
- "Ending legacy sequence %s due to window %s",
- meta_startup_sequence_get_id (sequence),
- window->desc);
-
- meta_startup_sequence_complete (sequence);
- }
- }
-
- /* Still no startup ID? Bail. */
- if (!startup_id)
- return FALSE;
-
- /* We might get this far and not know the sequence ID (if the window
- * already had a startup ID stored), so let's look for one if we don't
- * already know it.
- */
- if (sequence == NULL)
- {
- sequence =
- meta_startup_notification_lookup_sequence (display->startup_notification,
- startup_id);
- }
-
- if (sequence != NULL)
- {
- gboolean changed_something = FALSE;
-
- meta_topic (META_DEBUG_STARTUP,
- "Found startup sequence for window %s ID \"%s\"",
- window->desc, startup_id);
-
- if (!window->initial_workspace_set)
- {
- int space = meta_startup_sequence_get_workspace (sequence);
- if (space >= 0)
- {
- meta_topic (META_DEBUG_STARTUP,
- "Setting initial window workspace to %d based on startup info",
- space);
-
- window->initial_workspace_set = TRUE;
- window->initial_workspace = space;
- changed_something = TRUE;
- }
- }
-
- if (!window->initial_timestamp_set)
- {
- guint32 timestamp = meta_startup_sequence_get_timestamp (sequence);
- meta_topic (META_DEBUG_STARTUP,
- "Setting initial window timestamp to %u based on startup info",
- timestamp);
-
- window->initial_timestamp_set = TRUE;
- window->initial_timestamp = timestamp;
- changed_something = TRUE;
- }
-
- return changed_something;
- }
- else
- {
- meta_topic (META_DEBUG_STARTUP,
- "Did not find startup sequence for window %s ID \"%s\"",
- window->desc, startup_id);
- }
-
- return FALSE;
-}
-
-static gboolean
-set_work_area_later_func (MetaDisplay *display)
-{
- meta_topic (META_DEBUG_WORKAREA,
- "Running work area hint computation function");
-
- display->work_area_later = 0;
-
- g_signal_emit (display, display_signals[WORKAREAS_CHANGED], 0);
-
- return FALSE;
-}
-
-void
-meta_display_queue_workarea_recalc (MetaDisplay *display)
-{
- /* Recompute work area later before redrawing */
- if (display->work_area_later == 0)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Adding work area hint computation function");
- display->work_area_later =
- meta_later_add (META_LATER_BEFORE_REDRAW,
- (GSourceFunc) set_work_area_later_func,
- display,
- NULL);
- }
-}
-
-static gboolean
-check_fullscreen_func (gpointer data)
-{
- MetaDisplay *display = data;
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- GList *logical_monitors, *l;
- MetaWindow *window;
- GSList *fullscreen_monitors = NULL;
- GSList *obscured_monitors = NULL;
- gboolean in_fullscreen_changed = FALSE;
-
- display->check_fullscreen_later = 0;
-
- logical_monitors =
- meta_monitor_manager_get_logical_monitors (monitor_manager);
-
- /* We consider a monitor in fullscreen if it contains a fullscreen window;
- * however we make an exception for maximized windows above the fullscreen
- * one, as in that case window+chrome fully obscure the fullscreen window.
- */
- for (window = meta_stack_get_top (display->stack);
- window;
- window = meta_stack_get_below (display->stack, window, FALSE))
- {
- gboolean covers_monitors = FALSE;
-
- if (window->hidden)
- continue;
-
- if (window->fullscreen)
- {
- covers_monitors = TRUE;
- }
- else if (window->override_redirect)
- {
- /* We want to handle the case where an application is creating an
- * override-redirect window the size of the screen (monitor) and treat
- * it similarly to a fullscreen window, though it doesn't have fullscreen
- * window management behavior. (Being O-R, it's not managed at all.)
- */
- if (meta_window_is_monitor_sized (window))
- covers_monitors = TRUE;
- }
- else if (window->maximized_horizontally &&
- window->maximized_vertically)
- {
- MetaLogicalMonitor *logical_monitor;
-
- logical_monitor = meta_window_get_main_logical_monitor (window);
- if (!g_slist_find (obscured_monitors, logical_monitor))
- obscured_monitors = g_slist_prepend (obscured_monitors,
- logical_monitor);
- }
-
- if (covers_monitors)
- {
- MetaRectangle window_rect;
-
- meta_window_get_frame_rect (window, &window_rect);
-
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
-
- if (meta_rectangle_overlap (&window_rect,
- &logical_monitor->rect) &&
- !g_slist_find (fullscreen_monitors, logical_monitor) &&
- !g_slist_find (obscured_monitors, logical_monitor))
- fullscreen_monitors = g_slist_prepend (fullscreen_monitors,
- logical_monitor);
- }
- }
- }
-
- g_slist_free (obscured_monitors);
-
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
- gboolean in_fullscreen;
-
- in_fullscreen = g_slist_find (fullscreen_monitors,
- logical_monitor) != NULL;
- if (in_fullscreen != logical_monitor->in_fullscreen)
- {
- logical_monitor->in_fullscreen = in_fullscreen;
- in_fullscreen_changed = TRUE;
- }
- }
-
- g_slist_free (fullscreen_monitors);
-
- if (in_fullscreen_changed)
- {
- /* DOCK window stacking depends on the monitor's fullscreen
- status so we need to trigger a re-layering. */
- MetaWindow *window = meta_stack_get_top (display->stack);
- if (window)
- meta_stack_update_layer (display->stack, window);
-
- g_signal_emit (display, display_signals[IN_FULLSCREEN_CHANGED], 0, NULL);
- }
-
- return FALSE;
-}
-
-void
-meta_display_queue_check_fullscreen (MetaDisplay *display)
-{
- if (!display->check_fullscreen_later)
- display->check_fullscreen_later = meta_later_add (META_LATER_CHECK_FULLSCREEN,
- check_fullscreen_func,
- display, NULL);
-}
-
-int
-meta_display_get_monitor_index_for_rect (MetaDisplay *display,
- MetaRectangle *rect)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, rect);
- if (!logical_monitor)
- return -1;
-
- return logical_monitor->number;
-}
-
-int
-meta_display_get_monitor_neighbor_index (MetaDisplay *display,
- int which_monitor,
- MetaDisplayDirection direction)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
- MetaLogicalMonitor *neighbor;
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
- which_monitor);
- neighbor = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- logical_monitor,
- direction);
- return neighbor ? neighbor->number : -1;
-}
-
-/**
- * meta_display_get_current_monitor:
- * @display: a #MetaDisplay
- *
- * Gets the index of the monitor that currently has the mouse pointer.
- *
- * Return value: a monitor index
- */
-int
-meta_display_get_current_monitor (MetaDisplay *display)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaLogicalMonitor *logical_monitor;
-
- logical_monitor = meta_backend_get_current_logical_monitor (backend);
-
- /* Pretend its the first when there is no actual current monitor. */
- if (!logical_monitor)
- return 0;
-
- return logical_monitor->number;
-}
-
-/**
- * meta_display_get_n_monitors:
- * @display: a #MetaDisplay
- *
- * Gets the number of monitors that are joined together to form @display.
- *
- * Return value: the number of monitors
- */
-int
-meta_display_get_n_monitors (MetaDisplay *display)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
-
- g_return_val_if_fail (META_IS_DISPLAY (display), 0);
-
- return meta_monitor_manager_get_num_logical_monitors (monitor_manager);
-}
-
-/**
- * meta_display_get_primary_monitor:
- * @display: a #MetaDisplay
- *
- * Gets the index of the primary monitor on this @display.
- *
- * Return value: a monitor index
- */
-int
-meta_display_get_primary_monitor (MetaDisplay *display)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-
- g_return_val_if_fail (META_IS_DISPLAY (display), 0);
-
- logical_monitor =
- meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
- if (logical_monitor)
- return logical_monitor->number;
- else
- return 0;
-}
-
-/**
- * meta_display_get_monitor_geometry:
- * @display: a #MetaDisplay
- * @monitor: the monitor number
- * @geometry: (out): location to store the monitor geometry
- *
- * Stores the location and size of the indicated @monitor in @geometry.
- */
-void
-meta_display_get_monitor_geometry (MetaDisplay *display,
- int monitor,
- MetaRectangle *geometry)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-#ifndef G_DISABLE_CHECKS
- int n_logical_monitors =
- meta_monitor_manager_get_num_logical_monitors (monitor_manager);
-#endif
-
- g_return_if_fail (META_IS_DISPLAY (display));
- g_return_if_fail (monitor >= 0 && monitor < n_logical_monitors);
- g_return_if_fail (geometry != NULL);
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
- monitor);
- *geometry = logical_monitor->rect;
-}
-
-/**
- * meta_display_get_monitor_scale:
- * @display: a #MetaDisplay
- * @monitor: the monitor number
- *
- * Gets the monitor scaling value for the given @monitor.
- *
- * Return value: the monitor scaling value
- */
-float
-meta_display_get_monitor_scale (MetaDisplay *display,
- int monitor)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-#ifndef G_DISABLE_CHECKS
- int n_logical_monitors =
- meta_monitor_manager_get_num_logical_monitors (monitor_manager);
-#endif
-
- g_return_val_if_fail (META_IS_DISPLAY (display), 1.0f);
- g_return_val_if_fail (monitor >= 0 && monitor < n_logical_monitors, 1.0f);
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
- monitor);
- return logical_monitor->scale;
-}
-
-/**
- * meta_display_get_monitor_in_fullscreen:
- * @display: a #MetaDisplay
- * @monitor: the monitor number
- *
- * Determines whether there is a fullscreen window obscuring the specified
- * monitor. If there is a fullscreen window, the desktop environment will
- * typically hide any controls that might obscure the fullscreen window.
- *
- * You can get notification when this changes by connecting to
- * MetaDisplay::in-fullscreen-changed.
- *
- * Returns: %TRUE if there is a fullscreen window covering the specified monitor.
- */
-gboolean
-meta_display_get_monitor_in_fullscreen (MetaDisplay *display,
- int monitor)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-#ifndef G_DISABLE_CHECKS
- int n_logical_monitors =
- meta_monitor_manager_get_num_logical_monitors (monitor_manager);
-#endif
-
- g_return_val_if_fail (META_IS_DISPLAY (display), FALSE);
- g_return_val_if_fail (monitor >= 0 &&
- monitor < n_logical_monitors, FALSE);
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
- monitor);
-
- /* We use -1 as a flag to mean "not known yet" for notification
- purposes */ return logical_monitor->in_fullscreen == TRUE;
-}
-
-MetaWindow *
-meta_display_get_pointer_window (MetaDisplay *display,
- MetaWindow *not_this_one)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- MetaBackend *backend = meta_get_backend ();
- MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
- MetaWindow *window;
- graphene_point_t point;
-
- if (not_this_one)
- meta_topic (META_DEBUG_FOCUS,
- "Focusing mouse window excluding %s", not_this_one->desc);
-
- meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
-
- window = meta_stack_get_default_focus_window_at_point (display->stack,
- workspace_manager->active_workspace,
- not_this_one,
- point.x, point.y);
-
- return window;
-}
-
-void
-meta_display_focus_default_window (MetaDisplay *display,
- guint32 timestamp)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
-
- meta_workspace_focus_default_window (workspace_manager->active_workspace,
- NULL,
- timestamp);
-}
-
-/**
- * meta_display_get_workspace_manager:
- * @display: a #MetaDisplay
- *
- * Returns: (transfer none): The workspace manager of the display
- */
-MetaWorkspaceManager *
-meta_display_get_workspace_manager (MetaDisplay *display)
-{
- return display->workspace_manager;
-}
-
-MetaStartupNotification *
-meta_display_get_startup_notification (MetaDisplay *display)
-{
- return display->startup_notification;
-}
-
-MetaWindow *
-meta_display_get_window_from_id (MetaDisplay *display,
- uint64_t window_id)
-{
- g_autoptr (GSList) windows = NULL;
- GSList *l;
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- for (l = windows; l; l = l->next)
- {
- MetaWindow *window = l->data;
-
- if (window->id == window_id)
- return window;
- }
-
- return NULL;
-}
-
-uint64_t
-meta_display_generate_window_id (MetaDisplay *display)
-{
- static uint64_t base_window_id;
- static uint64_t last_window_id;
-
- if (!base_window_id)
- base_window_id = g_random_int () + 1;
-
- /* We can overflow here, that's fine */
- return (base_window_id + last_window_id++);
-}
-
-/**
- * meta_display_get_sound_player:
- * @display: a #MetaDisplay
- *
- * Returns: (transfer none): The sound player of the display
- */
-MetaSoundPlayer *
-meta_display_get_sound_player (MetaDisplay *display)
-{
- return display->sound_player;
-}
-
-/**
- * meta_display_get_selection:
- * @display: a #MetaDisplay
- *
- * Returns: (transfer none): The selection manager of the display
- */
-MetaSelection *
-meta_display_get_selection (MetaDisplay *display)
-{
- return display->selection;
-}