summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/bell.c209
-rw-r--r--src/core/bell.h43
-rw-r--r--src/core/boxes-private.h288
-rw-r--r--src/core/boxes.c2183
-rw-r--r--src/core/constraints.c1878
-rw-r--r--src/core/constraints.h39
-rw-r--r--src/core/delete.c124
-rw-r--r--src/core/display-private.h434
-rw-r--r--src/core/display.c3852
-rw-r--r--src/core/edge-resistance.c1310
-rw-r--r--src/core/edge-resistance.h40
-rw-r--r--src/core/events.c509
-rw-r--r--src/core/events.h31
-rw-r--r--src/core/frame.c427
-rw-r--r--src/core/frame.h85
-rw-r--r--src/core/keybindings-private.h160
-rw-r--r--src/core/keybindings.c4578
-rw-r--r--src/core/meta-accel-parse.c358
-rw-r--r--src/core/meta-accel-parse.h44
-rw-r--r--src/core/meta-anonymous-file.c368
-rw-r--r--src/core/meta-anonymous-file.h53
-rw-r--r--src/core/meta-border.c154
-rw-r--r--src/core/meta-border.h84
-rw-r--r--src/core/meta-clipboard-manager.c179
-rw-r--r--src/core/meta-clipboard-manager.h30
-rw-r--r--src/core/meta-close-dialog-default-private.h37
-rw-r--r--src/core/meta-close-dialog-default.c281
-rw-r--r--src/core/meta-close-dialog.c144
-rw-r--r--src/core/meta-context-main.c702
-rw-r--r--src/core/meta-context-main.h31
-rw-r--r--src/core/meta-context-private.h63
-rw-r--r--src/core/meta-context.c568
-rw-r--r--src/core/meta-fraction.c134
-rw-r--r--src/core/meta-fraction.h31
-rw-r--r--src/core/meta-gesture-tracker-private.h70
-rw-r--r--src/core/meta-gesture-tracker.c581
-rw-r--r--src/core/meta-inhibit-shortcuts-dialog-default-private.h34
-rw-r--r--src/core/meta-inhibit-shortcuts-dialog-default.c132
-rw-r--r--src/core/meta-inhibit-shortcuts-dialog.c103
-rw-r--r--src/core/meta-launch-context.c269
-rw-r--r--src/core/meta-pad-action-mapper.c860
-rw-r--r--src/core/meta-pad-action-mapper.h46
-rw-r--r--src/core/meta-private-enums.h31
-rw-r--r--src/core/meta-selection-private.h32
-rw-r--r--src/core/meta-selection-source-memory.c128
-rw-r--r--src/core/meta-selection-source-remote.c144
-rw-r--r--src/core/meta-selection-source-remote.h43
-rw-r--r--src/core/meta-selection-source.c166
-rw-r--r--src/core/meta-selection.c415
-rw-r--r--src/core/meta-sound-player.c296
-rw-r--r--src/core/meta-workspace-manager-private.h96
-rw-r--r--src/core/meta-workspace-manager.c1060
-rw-r--r--src/core/mutter.c97
-rw-r--r--src/core/place.c942
-rw-r--r--src/core/place.h39
-rw-r--r--src/core/prefs-private.h26
-rw-r--r--src/core/prefs.c2229
-rw-r--r--src/core/restart-helper.c84
-rw-r--r--src/core/restart.c201
-rw-r--r--src/core/stack-tracker.c1293
-rw-r--r--src/core/stack-tracker.h87
-rw-r--r--src/core/stack.c1340
-rw-r--r--src/core/stack.h406
-rw-r--r--src/core/startup-notification-private.h52
-rw-r--r--src/core/startup-notification.c696
-rw-r--r--src/core/util-private.h61
-rw-r--r--src/core/util.c796
-rw-r--r--src/core/window-private.h888
-rw-r--r--src/core/window.c8665
-rw-r--r--src/core/workspace-private.h103
-rw-r--r--src/core/workspace.c1477
71 files changed, 0 insertions, 43439 deletions
diff --git a/src/core/bell.c b/src/core/bell.c
deleted file mode 100644
index f0c6f9463..000000000
--- a/src/core/bell.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter visual bell */
-
-/*
- * Copyright (C) 2002 Sun Microsystems Inc.
- * Copyright (C) 2005, 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:bell
- * @short_description: Ring the bell or flash the screen
- *
- * Sometimes, X programs "ring the bell", whatever that means. Mutter lets
- * the user configure the bell to be audible or visible (aka visual), and
- * if it's visual it can be configured to be frame-flash or fullscreen-flash.
- * We never get told about audible bells; X handles them just fine by itself.
- *
- * Visual bells come in at meta_bell_notify(), which checks we are actually
- * in visual mode and calls through to bell_visual_notify(). That
- * function then checks what kind of visual flash you like, and calls either
- * bell_flash_fullscreen()-- which calls bell_flash_screen() to do
- * its work-- or bell_flash_frame(), which flashes the focused window
- * using bell_flash_window(), unless there is no such window, in
- * which case it flashes the screen instead.
- *
- * The visual bell was the result of a discussion in Bugzilla here:
- * <http://bugzilla.gnome.org/show_bug.cgi?id=99886>.
- *
- * Several of the functions in this file are ifdeffed out entirely if we are
- * found not to have the XKB extension, which is required to do these clever
- * things with bells; some others are entirely no-ops in that case.
- */
-
-#include "config.h"
-
-#include "core/bell.h"
-
-#include "compositor/compositor-private.h"
-#include "core/util-private.h"
-#include "core/window-private.h"
-#include "meta/compositor.h"
-
-G_DEFINE_TYPE (MetaBell, meta_bell, G_TYPE_OBJECT)
-
-enum
-{
- IS_AUDIBLE_CHANGED,
- LAST_SIGNAL
-};
-
-static guint bell_signals [LAST_SIGNAL] = { 0 };
-
-static void
-prefs_changed_callback (MetaPreference pref,
- gpointer data)
-{
- MetaBell *bell = data;
-
- if (pref == META_PREF_AUDIBLE_BELL)
- {
- g_signal_emit (bell, bell_signals[IS_AUDIBLE_CHANGED], 0,
- meta_prefs_bell_is_audible ());
- }
-}
-
-static void
-meta_bell_finalize (GObject *object)
-{
- MetaBell *bell = META_BELL (object);
-
- meta_prefs_remove_listener (prefs_changed_callback, bell);
-
- G_OBJECT_CLASS (meta_bell_parent_class)->finalize (object);
-}
-
-static void
-meta_bell_class_init (MetaBellClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_bell_finalize;
-
- bell_signals[IS_AUDIBLE_CHANGED] =
- g_signal_new ("is-audible-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- G_TYPE_BOOLEAN);
-}
-
-static void
-meta_bell_init (MetaBell *bell)
-{
- meta_prefs_add_listener (prefs_changed_callback, bell);
-}
-
-MetaBell *
-meta_bell_new (MetaDisplay *display)
-{
- return g_object_new (META_TYPE_BELL, NULL);
-}
-
-/**
- * bell_flash_fullscreen:
- * @display: The display the event came in on
- * @xkb_ev: The bell event
- *
- * Flashes one screen, or all screens, in response to a bell event.
- * If the event is on a particular window, flash the screen that
- * window is on. Otherwise, flash every screen on this display.
- *
- * If the configure script found we had no XKB, this does not exist.
- */
-static void
-bell_flash_fullscreen (MetaDisplay *display)
-{
- meta_compositor_flash_display (display->compositor, display);
-}
-
-static void
-bell_flash_window (MetaWindow *window)
-{
- meta_compositor_flash_window (window->display->compositor, window);
-}
-
-/**
- * bell_flash_frame:
- * @display: The display the bell event came in on
- * @xkb_ev: The bell event we just received
- *
- * Flashes the frame of the focused window. If there is no focused window,
- * flashes the screen.
- */
-static void
-bell_flash_frame (MetaDisplay *display,
- MetaWindow *window)
-{
- if (window)
- bell_flash_window (window);
- else
- bell_flash_fullscreen (display);
-}
-
-/**
- * bell_visual_notify:
- * @display: The display the bell event came in on
- * @xkb_ev: The bell event we just received
- *
- * Gives the user some kind of visual bell substitute, in response to a
- * bell event. What this is depends on the "visual bell type" pref.
- */
-static void
-bell_visual_notify (MetaDisplay *display,
- MetaWindow *window)
-{
- switch (meta_prefs_get_visual_bell_type ())
- {
- case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH:
- bell_flash_fullscreen (display);
- break;
- case G_DESKTOP_VISUAL_BELL_FRAME_FLASH:
- bell_flash_frame (display, window);
- break;
- }
-}
-
-static gboolean
-bell_audible_notify (MetaDisplay *display,
- MetaWindow *window)
-{
- MetaSoundPlayer *player;
-
- player = meta_display_get_sound_player (display);
- meta_sound_player_play_from_theme (player,
- "bell-window-system",
- _("Bell event"),
- NULL);
- return TRUE;
-}
-
-gboolean
-meta_bell_notify (MetaDisplay *display,
- MetaWindow *window)
-{
- /* flash something */
- if (meta_prefs_get_visual_bell ())
- bell_visual_notify (display, window);
-
- if (meta_prefs_bell_is_audible ())
- return bell_audible_notify (display, window);
-
- return TRUE;
-}
diff --git a/src/core/bell.h b/src/core/bell.h
deleted file mode 100644
index f86cbb7c2..000000000
--- a/src/core/bell.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2002 Sun Microsystems Inc.
- *
- * 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/>.
- */
-
-#include "core/display-private.h"
-#include "core/frame.h"
-
-struct _MetaBell
-{
- GObject parent;
-};
-
-#define META_TYPE_BELL (meta_bell_get_type ())
-G_DECLARE_FINAL_TYPE (MetaBell, meta_bell, META, BELL, GObject)
-
-MetaBell * meta_bell_new (MetaDisplay *display);
-
-/**
- * meta_bell_notify:
- * @display: The display the bell event came in on
- * @window: The window the bell event was received on
- *
- * Gives the user some kind of aural or visual feedback, such as a bell sound
- * or flash. What type of feedback is invoked depends on the configuration.
- * If the aural feedback could not be invoked, FALSE is returned.
- */
-gboolean meta_bell_notify (MetaDisplay *display,
- MetaWindow *window);
diff --git a/src/core/boxes-private.h b/src/core/boxes-private.h
deleted file mode 100644
index d39816495..000000000
--- a/src/core/boxes-private.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Simple box operations */
-
-/*
- * Copyright (C) 2005, 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/>.
- */
-
-#ifndef META_BOXES_PRIVATE_H
-#define META_BOXES_PRIVATE_H
-
-#include <glib-object.h>
-
-#include "backends/meta-backend-types.h"
-#include "core/util-private.h"
-#include "meta/boxes.h"
-#include "meta/common.h"
-
-#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
-#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
-#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
-#define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */
-
-typedef enum
-{
- FIXED_DIRECTION_NONE = 0,
- FIXED_DIRECTION_X = 1 << 0,
- FIXED_DIRECTION_Y = 1 << 1,
-} FixedDirections;
-
-typedef enum _MetaRoundingStrategy
-{
- META_ROUNDING_STRATEGY_SHRINK,
- META_ROUNDING_STRATEGY_GROW,
- META_ROUNDING_STRATEGY_ROUND,
-} MetaRoundingStrategy;
-
-/* Output functions -- note that the output buffer had better be big enough:
- * rect_to_string: RECT_LENGTH
- * region_to_string: (RECT_LENGTH+strlen(separator_string)) *
- * g_list_length (region)
- * edge_to_string: EDGE_LENGTH
- * edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *
- * g_list_length (edge_list)
- */
-#define RECT_LENGTH 27
-#define EDGE_LENGTH 37
-char* meta_rectangle_to_string (const MetaRectangle *rect,
- char *output);
-char* meta_rectangle_region_to_string (GList *region,
- const char *separator_string,
- char *output);
-char* meta_rectangle_edge_to_string (const MetaEdge *edge,
- char *output);
-char* meta_rectangle_edge_list_to_string (
- GList *edge_list,
- const char *separator_string,
- char *output);
-
-/* Resize old_rect to the given new_width and new_height, but store the
- * result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR
- * A MOVERESIZE OPERATION (that simplifies the routine a little bit as it
- * means there's no difference between META_GRAVITY_NORTH_WEST and
- * META_GRAVITY_STATIC. Also, I lied a little bit--technically, you could use
- * it in a MoveResize operation if you muck with old_rect just right).
- */
-META_EXPORT_TEST
-void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
- MetaRectangle *rect,
- MetaGravity gravity,
- int new_width,
- int new_height);
-
-/* find a list of rectangles with the property that a window is contained
- * in the given region if and only if it is contained in one of the
- * rectangles in the list.
- *
- * In this case, the region is given by taking basic_rect, removing from
- * it the intersections with all the rectangles in the all_struts list,
- * then expanding all the rectangles in the resulting list by the given
- * amounts on each side.
- *
- * See boxes.c for more details.
- */
-META_EXPORT_TEST
-GList* meta_rectangle_get_minimal_spanning_set_for_region (
- const MetaRectangle *basic_rect,
- const GSList *all_struts);
-
-/* Expand all rectangles in region by the given amount on each side */
-GList* meta_rectangle_expand_region (GList *region,
- const int left_expand,
- const int right_expand,
- const int top_expand,
- const int bottom_expand);
-/* Same as for meta_rectangle_expand_region except that rectangles not at
- * least min_x or min_y in size are not expanded in that direction
- */
-GList* meta_rectangle_expand_region_conditionally (
- GList *region,
- const int left_expand,
- const int right_expand,
- const int top_expand,
- const int bottom_expand,
- const int min_x,
- const int min_y);
-
-/* Expand rect in direction to the size of expand_to, and then clip out any
- * overlapping struts oriented orthogonal to the expansion direction. (Think
- * horizontal or vertical maximization)
- */
-META_EXPORT_TEST
-void meta_rectangle_expand_to_avoiding_struts (
- MetaRectangle *rect,
- const MetaRectangle *expand_to,
- const MetaDirection direction,
- const GSList *all_struts);
-
-/* Free the list created by
- * meta_rectangle_get_minimal_spanning_set_for_region()
- * or
- * meta_rectangle_find_onscreen_edges ()
- * or
- * meta_rectangle_find_nonintersected_monitor_edges()
- */
-META_EXPORT_TEST
-void meta_rectangle_free_list_and_elements (GList *filled_list);
-
-/* could_fit_in_region determines whether one of the spanning_rects is
- * big enough to contain rect. contained_in_region checks whether one
- * actually contains it.
- */
-META_EXPORT_TEST
-gboolean meta_rectangle_could_fit_in_region (
- const GList *spanning_rects,
- const MetaRectangle *rect);
-
-META_EXPORT_TEST
-gboolean meta_rectangle_contained_in_region (
- const GList *spanning_rects,
- const MetaRectangle *rect);
-
-META_EXPORT_TEST
-gboolean meta_rectangle_overlaps_with_region (
- const GList *spanning_rects,
- const MetaRectangle *rect);
-
-/* Make the rectangle small enough to fit into one of the spanning_rects,
- * but make it no smaller than min_size.
- */
-META_EXPORT_TEST
-void meta_rectangle_clamp_to_fit_into_region (
- const GList *spanning_rects,
- FixedDirections fixed_directions,
- MetaRectangle *rect,
- const MetaRectangle *min_size);
-
-/* Clip the rectangle so that it fits into one of the spanning_rects, assuming
- * it overlaps with at least one of them
- */
-META_EXPORT_TEST
-void meta_rectangle_clip_to_region (const GList *spanning_rects,
- FixedDirections fixed_directions,
- MetaRectangle *rect);
-
-/* Shove the rectangle into one of the spanning_rects, assuming it fits in
- * one of them.
- */
-META_EXPORT_TEST
-void meta_rectangle_shove_into_region(
- const GList *spanning_rects,
- FixedDirections fixed_directions,
- MetaRectangle *rect);
-
-/* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest
- * to (px, py). Useful for finding an optimal rectangle size when given a
- * range between two sizes that are all candidates.
- */
-META_EXPORT_TEST
-void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1,
- double x2, double y2,
- double px, double py,
- double *valx, double *valy);
-
-/***************************************************************************/
-/* */
-/* Switching gears to code for edges instead of just rectangles */
-/* */
-/***************************************************************************/
-
-/* Return whether an edge overlaps or is adjacent to the rectangle in the
- * nonzero-width dimension of the edge.
- */
-META_EXPORT_TEST
-gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,
- const MetaEdge *edge);
-
-/* Compare two edges, so that sorting functions can put a list of edges in
- * canonical order.
- */
-META_EXPORT_TEST
-gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b);
-
-/* Compare two edges, so that sorting functions can put a list of edges in
- * order. This function doesn't separate left edges first, then right edges,
- * etc., but rather compares only upon location.
- */
-META_EXPORT_TEST
-gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b);
-
-/* Removes an parts of edges in the given list that intersect any box in the
- * given rectangle list. Returns the result.
- */
-GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
- GList *edges,
- const GSList *rectangles);
-
-/* Finds all the edges of an onscreen region, returning a GList* of
- * MetaEdgeRect's.
- */
-META_EXPORT_TEST
-GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
- const GSList *all_struts);
-
-/* Finds edges between adjacent monitors which are not covered by the given
- * struts.
- */
-META_EXPORT_TEST
-GList* meta_rectangle_find_nonintersected_monitor_edges (
- const GList *monitor_rects,
- const GSList *all_struts);
-
-META_EXPORT_TEST
-gboolean meta_rectangle_is_adjacent_to (MetaRectangle *rect,
- MetaRectangle *other);
-
-META_EXPORT_TEST
-void meta_rectangle_scale_double (const MetaRectangle *rect,
- double scale,
- MetaRoundingStrategy rounding_strategy,
- MetaRectangle *dest);
-
-static inline graphene_rect_t
-meta_rectangle_to_graphene_rect (MetaRectangle *rect)
-{
- return (graphene_rect_t) {
- .origin = {
- .x = rect->x,
- .y = rect->y
- },
- .size = {
- .width = rect->width,
- .height = rect->height
- }
- };
-}
-
-META_EXPORT_TEST
-void meta_rectangle_transform (const MetaRectangle *rect,
- MetaMonitorTransform transform,
- int width,
- int height,
- MetaRectangle *dest);
-
-void meta_rectangle_from_graphene_rect (const graphene_rect_t *rect,
- MetaRoundingStrategy rounding_strategy,
- MetaRectangle *dest);
-
-void meta_rectangle_crop_and_scale (const MetaRectangle *rect,
- graphene_rect_t *src_rect,
- int dst_width,
- int dst_height,
- MetaRectangle *dest);
-
-#endif /* META_BOXES_PRIVATE_H */
diff --git a/src/core/boxes.c b/src/core/boxes.c
deleted file mode 100644
index 9a9633e05..000000000
--- a/src/core/boxes.c
+++ /dev/null
@@ -1,2183 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/**
- * SECTION:boxes
- * @Title: MetaRectangle
- * @Short_Description: Simple box operations
- */
-
-/*
- * Copyright (C) 2005, 2006 Elijah Newren
- * [meta_rectangle_intersect() is copyright the GTK+ Team according to Havoc,
- * see gdkrectangle.c. As far as Havoc knows, he probably wrote
- * meta_rectangle_equal(), and I'm guessing it's (C) Red Hat. So...]
- * Copyright (C) 1995-2000 GTK+ Team
- * Copyright (C) 2002 Red Hat, Inc.
- *
- * 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/>.
- */
-
-#include "config.h"
-
-#include "backends/meta-monitor-transform.h"
-#include "core/boxes-private.h"
-
-#include <math.h>
-#include <X11/Xutil.h>
-
-#include "meta/util.h"
-
-/* It would make sense to use GSlice here, but until we clean up the
- * rest of this file and the internal API to use these functions, we
- * leave it using g_malloc()/g_free() for consistency.
- */
-
-MetaRectangle *
-meta_rectangle_copy (const MetaRectangle *rect)
-{
- return g_memdup2 (rect, sizeof (MetaRectangle));
-}
-
-void
-meta_rectangle_free (MetaRectangle *rect)
-{
- g_free (rect);
-}
-
-G_DEFINE_BOXED_TYPE (MetaRectangle, meta_rectangle,
- meta_rectangle_copy, meta_rectangle_free);
-
-char*
-meta_rectangle_to_string (const MetaRectangle *rect,
- char *output)
-{
- /* 25 chars: 2 commas, space, plus, trailing \0 + 5 for each digit.
- * Should be more than enough space. Note that of this space, the
- * trailing \0 will be overwritten for all but the last rectangle.
- */
- g_snprintf (output, RECT_LENGTH, "%d,%d +%d,%d",
- rect->x, rect->y, rect->width, rect->height);
-
- return output;
-}
-
-char*
-meta_rectangle_region_to_string (GList *region,
- const char *separator_string,
- char *output)
-{
- /* 27 chars: 2 commas, 2 square brackets, space, plus, trailing \0 + 5
- * for each digit. Should be more than enough space. Note that of this
- * space, the trailing \0 will be overwritten for all but the last
- * rectangle.
- */
- char rect_string[RECT_LENGTH];
-
- GList *tmp = region;
- char *cur = output;
-
- if (region == NULL)
- g_snprintf (output, 10, "(EMPTY)");
-
- while (tmp)
- {
- MetaRectangle *rect = tmp->data;
- g_snprintf (rect_string, RECT_LENGTH, "[%d,%d +%d,%d]",
- rect->x, rect->y, rect->width, rect->height);
- cur = g_stpcpy (cur, rect_string);
- tmp = tmp->next;
- if (tmp)
- cur = g_stpcpy (cur, separator_string);
- }
-
- return output;
-}
-
-char*
-meta_rectangle_edge_to_string (const MetaEdge *edge,
- char *output)
-{
- /* 25 chars: 2 commas, space, plus, trailing \0 + 5 for each digit.
- * Should be more than enough space. Note that of this space, the
- * trailing \0 will be overwritten for all but the last rectangle.
- *
- * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and
- * 2 more spaces, for a total of 10 more.
- */
- g_snprintf (output, EDGE_LENGTH, "[%d,%d +%d,%d], %2d, %2d",
- edge->rect.x, edge->rect.y, edge->rect.width, edge->rect.height,
- edge->side_type, edge->edge_type);
-
- return output;
-}
-
-char*
-meta_rectangle_edge_list_to_string (GList *edge_list,
- const char *separator_string,
- char *output)
-{
- /* 27 chars: 2 commas, 2 square brackets, space, plus, trailing \0 + 5 for
- * each digit. Should be more than enough space. Note that of this
- * space, the trailing \0 will be overwritten for all but the last
- * rectangle.
- *
- * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and
- * 2 more spaces, for a total of 10 more.
- */
- char rect_string[EDGE_LENGTH];
-
- char *cur = output;
- GList *tmp = edge_list;
-
- if (edge_list == NULL)
- g_snprintf (output, 10, "(EMPTY)");
-
- while (tmp)
- {
- MetaEdge *edge = tmp->data;
- MetaRectangle *rect = &edge->rect;
- g_snprintf (rect_string, EDGE_LENGTH, "([%d,%d +%d,%d], %2d, %2d)",
- rect->x, rect->y, rect->width, rect->height,
- edge->side_type, edge->edge_type);
- cur = g_stpcpy (cur, rect_string);
- tmp = tmp->next;
- if (tmp)
- cur = g_stpcpy (cur, separator_string);
- }
-
- return output;
-}
-
-MetaRectangle
-meta_rect (int x, int y, int width, int height)
-{
- MetaRectangle temporary;
- temporary.x = x;
- temporary.y = y;
- temporary.width = width;
- temporary.height = height;
-
- return temporary;
-}
-
-int
-meta_rectangle_area (const MetaRectangle *rect)
-{
- g_return_val_if_fail (rect != NULL, 0);
- return rect->width * rect->height;
-}
-
-/**
- * meta_rectangle_intersect:
- * @src1: a #MetaRectangle
- * @src2: another #MetaRectangle
- * @dest: (out caller-allocates): an empty #MetaRectangle, to be filled
- * with the coordinates of the intersection.
- *
- * Returns: TRUE is some intersection exists and is not degenerate, FALSE
- * otherwise.
- */
-gboolean
-meta_rectangle_intersect (const MetaRectangle *src1,
- const MetaRectangle *src2,
- MetaRectangle *dest)
-{
- int dest_x, dest_y;
- int dest_w, dest_h;
- int return_val;
-
- g_return_val_if_fail (src1 != NULL, FALSE);
- g_return_val_if_fail (src2 != NULL, FALSE);
- g_return_val_if_fail (dest != NULL, FALSE);
-
- return_val = FALSE;
-
- dest_x = MAX (src1->x, src2->x);
- dest_y = MAX (src1->y, src2->y);
- dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x;
- dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y;
-
- if (dest_w > 0 && dest_h > 0)
- {
- dest->x = dest_x;
- dest->y = dest_y;
- dest->width = dest_w;
- dest->height = dest_h;
- return_val = TRUE;
- }
- else
- {
- dest->width = 0;
- dest->height = 0;
- }
-
- return return_val;
-}
-
-gboolean
-meta_rectangle_equal (const MetaRectangle *src1,
- const MetaRectangle *src2)
-{
- return ((src1->x == src2->x) &&
- (src1->y == src2->y) &&
- (src1->width == src2->width) &&
- (src1->height == src2->height));
-}
-
-/**
- * meta_rectangle_union:
- * @rect1: a #MetaRectangle
- * @rect2: another #MetaRectangle
- * @dest: (out caller-allocates): an empty #MetaRectangle, to be filled
- * with the coordinates of the bounding box.
- */
-void
-meta_rectangle_union (const MetaRectangle *rect1,
- const MetaRectangle *rect2,
- MetaRectangle *dest)
-{
- int dest_x, dest_y;
- int dest_w, dest_h;
-
- dest_x = rect1->x;
- dest_y = rect1->y;
- dest_w = rect1->width;
- dest_h = rect1->height;
-
- if (rect2->x < dest_x)
- {
- dest_w += dest_x - rect2->x;
- dest_x = rect2->x;
- }
- if (rect2->y < dest_y)
- {
- dest_h += dest_y - rect2->y;
- dest_y = rect2->y;
- }
- if (rect2->x + rect2->width > dest_x + dest_w)
- dest_w = rect2->x + rect2->width - dest_x;
- if (rect2->y + rect2->height > dest_y + dest_h)
- dest_h = rect2->y + rect2->height - dest_y;
-
- dest->x = dest_x;
- dest->y = dest_y;
- dest->width = dest_w;
- dest->height = dest_h;
-}
-
-gboolean
-meta_rectangle_overlap (const MetaRectangle *rect1,
- const MetaRectangle *rect2)
-{
- g_return_val_if_fail (rect1 != NULL, FALSE);
- g_return_val_if_fail (rect2 != NULL, FALSE);
-
- return !((rect1->x + rect1->width <= rect2->x) ||
- (rect2->x + rect2->width <= rect1->x) ||
- (rect1->y + rect1->height <= rect2->y) ||
- (rect2->y + rect2->height <= rect1->y));
-}
-
-gboolean
-meta_rectangle_vert_overlap (const MetaRectangle *rect1,
- const MetaRectangle *rect2)
-{
- return (rect1->y < rect2->y + rect2->height &&
- rect2->y < rect1->y + rect1->height);
-}
-
-gboolean
-meta_rectangle_horiz_overlap (const MetaRectangle *rect1,
- const MetaRectangle *rect2)
-{
- return (rect1->x < rect2->x + rect2->width &&
- rect2->x < rect1->x + rect1->width);
-}
-
-gboolean
-meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect,
- const MetaRectangle *inner_rect)
-{
- return (outer_rect->width >= inner_rect->width &&
- outer_rect->height >= inner_rect->height);
-}
-
-gboolean
-meta_rectangle_contains_rect (const MetaRectangle *outer_rect,
- const MetaRectangle *inner_rect)
-{
- return
- inner_rect->x >= outer_rect->x &&
- inner_rect->y >= outer_rect->y &&
- inner_rect->x + inner_rect->width <= outer_rect->x + outer_rect->width &&
- inner_rect->y + inner_rect->height <= outer_rect->y + outer_rect->height;
-}
-
-void
-meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
- MetaRectangle *rect,
- MetaGravity gravity,
- int new_width,
- int new_height)
-{
- /* FIXME: I'm too deep into this to know whether the below comment is
- * still clear or not now that I've moved it out of constraints.c.
- * boxes.h has a good comment, but I'm not sure if the below info is also
- * helpful on top of that (or whether it has superfluous info).
- */
-
- /* These formulas may look overly simplistic at first but you can work
- * everything out with a left_frame_with, right_frame_width,
- * border_width, and old and new client area widths (instead of old total
- * width and new total width) and you come up with the same formulas.
- *
- * Also, note that the reason we can treat META_GRAVITY_NORTH_WEST and
- * META_GRAVITY_STATIC the same is because we're not given a location at
- * which to place the window--the window was already placed
- * appropriately before. So, META_GRAVITY_NORTH_WEST for this function
- * means to just leave the upper left corner of the outer window
- * where it already is, and META_GRAVITY_STATIC for this function means to
- * just leave the upper left corner of the inner window where it
- * already is. But leaving either of those two corners where they
- * already are will ensure that the other corner is fixed as well
- * (since frame size doesn't change)--thus making the two
- * equivalent.
- */
-
- /* First, the x direction */
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- rect->x = old_rect->x;
- break;
-
- case META_GRAVITY_NORTH:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_SOUTH:
- /* FIXME: Needing to adjust new_width kind of sucks, but not doing so
- * would cause drift.
- */
- new_width -= (old_rect->width - new_width) % 2;
- rect->x = old_rect->x + (old_rect->width - new_width)/2;
- break;
-
- case META_GRAVITY_NORTH_EAST:
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- rect->x = old_rect->x + (old_rect->width - new_width);
- break;
-
- case META_GRAVITY_STATIC:
- default:
- rect->x = old_rect->x;
- break;
- }
- rect->width = new_width;
-
- /* Next, the y direction */
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_EAST:
- rect->y = old_rect->y;
- break;
-
- case META_GRAVITY_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_EAST:
- /* FIXME: Needing to adjust new_height kind of sucks, but not doing so
- * would cause drift.
- */
- new_height -= (old_rect->height - new_height) % 2;
- rect->y = old_rect->y + (old_rect->height - new_height)/2;
- break;
-
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_EAST:
- rect->y = old_rect->y + (old_rect->height - new_height);
- break;
-
- case META_GRAVITY_STATIC:
- default:
- rect->y = old_rect->y;
- break;
- }
- rect->height = new_height;
-}
-
-/* Not so simple helper function for get_minimal_spanning_set_for_region() */
-static GList*
-merge_spanning_rects_in_region (GList *region)
-{
- /* NOTE FOR ANY OPTIMIZATION PEOPLE OUT THERE: Please see the
- * documentation of get_minimal_spanning_set_for_region() for performance
- * considerations that also apply to this function.
- */
-
- GList* compare;
- compare = region;
-
- if (region == NULL)
- {
- g_warning ("Region to merge was empty! Either you have a some "
- "pathological STRUT list or there's a bug somewhere!");
- return NULL;
- }
-
- while (compare && compare->next)
- {
- MetaRectangle *a = compare->data;
- GList *other = compare->next;
-
- g_assert (a->width > 0 && a->height > 0);
-
- while (other)
- {
- MetaRectangle *b = other->data;
- GList *delete_me = NULL;
-
- g_assert (b->width > 0 && b->height > 0);
-
- /* If a contains b, just remove b */
- if (meta_rectangle_contains_rect (a, b))
- {
- delete_me = other;
- }
- /* If b contains a, just remove a */
- else if (meta_rectangle_contains_rect (b, a))
- {
- delete_me = compare;
- }
- /* If a and b might be mergeable horizontally */
- else if (a->y == b->y && a->height == b->height)
- {
- /* If a and b overlap */
- if (meta_rectangle_overlap (a, b))
- {
- int new_x = MIN (a->x, b->x);
- a->width = MAX (a->x + a->width, b->x + b->width) - new_x;
- a->x = new_x;
- delete_me = other;
- }
- /* If a and b are adjacent */
- else if (a->x + a->width == b->x || a->x == b->x + b->width)
- {
- int new_x = MIN (a->x, b->x);
- a->width = MAX (a->x + a->width, b->x + b->width) - new_x;
- a->x = new_x;
- delete_me = other;
- }
- }
- /* If a and b might be mergeable vertically */
- else if (a->x == b->x && a->width == b->width)
- {
- /* If a and b overlap */
- if (meta_rectangle_overlap (a, b))
- {
- int new_y = MIN (a->y, b->y);
- a->height = MAX (a->y + a->height, b->y + b->height) - new_y;
- a->y = new_y;
- delete_me = other;
- }
- /* If a and b are adjacent */
- else if (a->y + a->height == b->y || a->y == b->y + b->height)
- {
- int new_y = MIN (a->y, b->y);
- a->height = MAX (a->y + a->height, b->y + b->height) - new_y;
- a->y = new_y;
- delete_me = other;
- }
- }
-
- other = other->next;
-
- /* Delete any rectangle in the list that is no longer wanted */
- if (delete_me != NULL)
- {
- /* Deleting the rect we compare others to is a little tricker */
- if (compare == delete_me)
- {
- compare = compare->next;
- other = compare->next;
- a = compare->data;
- }
-
- /* Okay, we can free it now */
- g_free (delete_me->data);
- region = g_list_delete_link (region, delete_me);
- }
-
- }
-
- compare = compare->next;
- }
-
- return region;
-}
-
-/* Simple helper function for get_minimal_spanning_set_for_region()... */
-static gint
-compare_rect_areas (gconstpointer a, gconstpointer b)
-{
- const MetaRectangle *a_rect = (gconstpointer) a;
- const MetaRectangle *b_rect = (gconstpointer) b;
-
- int a_area = meta_rectangle_area (a_rect);
- int b_area = meta_rectangle_area (b_rect);
-
- return b_area - a_area; /* positive ret value denotes b > a, ... */
-}
-
-/* ... and another helper for get_minimal_spanning_set_for_region()... */
-static gboolean
-check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
-{
- /* Check whether @strut actually aligns to the side of @rect it claims */
- switch (strut->side)
- {
- case META_SIDE_TOP:
- return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
- case META_SIDE_BOTTOM:
- return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
- case META_SIDE_LEFT:
- return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
- case META_SIDE_RIGHT:
- return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
- default:
- return FALSE;
- }
-}
-
-/**
- * meta_rectangle_get_minimal_spanning_set_for_region:
- * @basic_rect: Input rectangle
- * @all_struts: (element-type Meta.Rectangle): List of struts
- *
- * This function is trying to find a "minimal spanning set (of rectangles)"
- * for a given region.
- *
- * The region is given by taking basic_rect, then removing the areas
- * covered by all the rectangles in the all_struts list, and then expanding
- * the resulting region by the given number of pixels in each direction.
- *
- * A "minimal spanning set (of rectangles)" is the best name I could come
- * up with for the concept I had in mind. Basically, for a given region, I
- * want a set of rectangles with the property that a window is contained in
- * the region if and only if it is contained within at least one of the
- * rectangles.
- *
- * Returns: (transfer full) (element-type Meta.Rectangle): Minimal spanning set
- */
-GList*
-meta_rectangle_get_minimal_spanning_set_for_region (
- const MetaRectangle *basic_rect,
- const GSList *all_struts)
-{
- /* NOTE FOR OPTIMIZERS: This function *might* be somewhat slow,
- * especially due to the call to merge_spanning_rects_in_region() (which
- * is O(n^2) where n is the size of the list generated in this function).
- * This is made more onerous due to the fact that it involves a fair
- * number of memory allocation and deallocation calls. However, n is 1
- * for default installations of Gnome (because partial struts aren't used
- * by default and only partial struts increase the size of the spanning
- * set generated). With one partial strut, n will be 2 or 3. With 2
- * partial struts, n will probably be 4 or 5. So, n probably isn't large
- * enough to make this worth bothering. Further, it is only called from
- * workspace.c:ensure_work_areas_validated (at least as of the time of
- * writing this comment), which in turn should only be called if the
- * strut list changes or the screen or monitor size changes. If it ever
- * does show up on profiles (most likely because people start using
- * ridiculously huge numbers of partial struts), possible optimizations
- * include:
- *
- * (1) rewrite merge_spanning_rects_in_region() to be O(n) or O(nlogn).
- * I'm not totally sure it's possible, but with a couple copies of
- * the list and sorting them appropriately, I believe it might be.
- * (2) only call merge_spanning_rects_in_region() with a subset of the
- * full list of rectangles. I believe from some of my preliminary
- * debugging and thinking about it that it is possible to figure out
- * apriori groups of rectangles which are only merge candidates with
- * each other. (See testboxes.c:get_screen_region() when which==2
- * and track the steps of this function carefully to see what gave
- * me the hint that this might work)
- * (3) figure out how to avoid merge_spanning_rects_in_region(). I think
- * it might be possible to modify this function to make that
- * possible, and I spent just a little while thinking about it, but n
- * wasn't large enough to convince me to care yet.
- * (4) Some of the stuff Rob mentioned at http://mail.gnome.org/archives\
- * /metacity-devel-list/2005-November/msg00028.html. (Sorry for the
- * URL splitting.)
- */
-
- GList *ret;
- GList *tmp_list;
- const GSList *strut_iter;
- MetaRectangle *temp_rect;
-
- /* The algorithm is basically as follows:
- * Initialize rectangle_set to basic_rect
- * Foreach strut:
- * Foreach rectangle in rectangle_set:
- * - Split the rectangle into new rectangles that don't overlap the
- * strut (but which are as big as possible otherwise)
- * - Remove the old (pre-split) rectangle from the rectangle_set,
- * and replace it with the new rectangles generated from the
- * splitting
- */
-
- temp_rect = g_new (MetaRectangle, 1);
- *temp_rect = *basic_rect;
- ret = g_list_prepend (NULL, temp_rect);
-
- for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
- {
- GList *rect_iter;
- MetaStrut *strut = (MetaStrut*)strut_iter->data;
- MetaRectangle *strut_rect = &strut->rect;
-
- tmp_list = ret;
- ret = NULL;
- rect_iter = tmp_list;
- while (rect_iter)
- {
- MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
-
- if (!meta_rectangle_overlap (strut_rect, rect) ||
- !check_strut_align (strut, basic_rect))
- ret = g_list_prepend (ret, rect);
- else
- {
- /* If there is area in rect left of strut */
- if (BOX_LEFT (*rect) < BOX_LEFT (*strut_rect))
- {
- temp_rect = g_new (MetaRectangle, 1);
- *temp_rect = *rect;
- temp_rect->width = BOX_LEFT (*strut_rect) - BOX_LEFT (*rect);
- ret = g_list_prepend (ret, temp_rect);
- }
- /* If there is area in rect right of strut */
- if (BOX_RIGHT (*rect) > BOX_RIGHT (*strut_rect))
- {
- int new_x;
- temp_rect = g_new (MetaRectangle, 1);
- *temp_rect = *rect;
- new_x = BOX_RIGHT (*strut_rect);
- temp_rect->width = BOX_RIGHT(*rect) - new_x;
- temp_rect->x = new_x;
- ret = g_list_prepend (ret, temp_rect);
- }
- /* If there is area in rect above strut */
- if (BOX_TOP (*rect) < BOX_TOP (*strut_rect))
- {
- temp_rect = g_new (MetaRectangle, 1);
- *temp_rect = *rect;
- temp_rect->height = BOX_TOP (*strut_rect) - BOX_TOP (*rect);
- ret = g_list_prepend (ret, temp_rect);
- }
- /* If there is area in rect below strut */
- if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*strut_rect))
- {
- int new_y;
- temp_rect = g_new (MetaRectangle, 1);
- *temp_rect = *rect;
- new_y = BOX_BOTTOM (*strut_rect);
- temp_rect->height = BOX_BOTTOM (*rect) - new_y;
- temp_rect->y = new_y;
- ret = g_list_prepend (ret, temp_rect);
- }
- g_free (rect);
- }
- rect_iter = rect_iter->next;
- }
- g_list_free (tmp_list);
- }
-
- /* Sort by maximal area, just because I feel like it... */
- ret = g_list_sort (ret, compare_rect_areas);
-
- /* Merge rectangles if possible so that the list really is minimal */
- ret = merge_spanning_rects_in_region (ret);
-
- return ret;
-}
-
-/**
- * meta_rectangle_expand_region: (skip)
- *
- */
-GList*
-meta_rectangle_expand_region (GList *region,
- const int left_expand,
- const int right_expand,
- const int top_expand,
- const int bottom_expand)
-{
- return meta_rectangle_expand_region_conditionally (region,
- left_expand,
- right_expand,
- top_expand,
- bottom_expand,
- 0,
- 0);
-}
-
-/**
- * meta_rectangle_expand_region_conditionally: (skip)
- *
- */
-GList*
-meta_rectangle_expand_region_conditionally (GList *region,
- const int left_expand,
- const int right_expand,
- const int top_expand,
- const int bottom_expand,
- const int min_x,
- const int min_y)
-{
- GList *tmp_list = region;
- while (tmp_list)
- {
- MetaRectangle *rect = (MetaRectangle*) tmp_list->data;
- if (rect->width >= min_x)
- {
- rect->x -= left_expand;
- rect->width += (left_expand + right_expand);
- }
- if (rect->height >= min_y)
- {
- rect->y -= top_expand;
- rect->height += (top_expand + bottom_expand);
- }
- tmp_list = tmp_list->next;
- }
-
- return region;
-}
-
-void
-meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect,
- const MetaRectangle *expand_to,
- const MetaDirection direction,
- const GSList *all_struts)
-{
- const GSList *strut_iter;
-
- /* If someone wants this function to handle more fine-grained
- * direction expanding in the future (e.g. only left, or fully
- * horizontal plus upward), feel free. But I'm hard-coding for both
- * horizontal directions (exclusive-)or both vertical directions.
- */
- g_assert ((direction == META_DIRECTION_HORIZONTAL) ^
- (direction == META_DIRECTION_VERTICAL ));
-
- if (direction == META_DIRECTION_HORIZONTAL)
- {
- rect->x = expand_to->x;
- rect->width = expand_to->width;
- }
- else
- {
- rect->y = expand_to->y;
- rect->height = expand_to->height;
- }
-
-
- /* Run over all struts */
- for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
- {
- MetaStrut *strut = (MetaStrut*) strut_iter->data;
-
- /* Skip struts that don't overlap */
- if (!meta_rectangle_overlap (&strut->rect, rect))
- continue;
-
- if (direction == META_DIRECTION_HORIZONTAL)
- {
- if (strut->side == META_SIDE_LEFT)
- {
- int offset = BOX_RIGHT(strut->rect) - BOX_LEFT(*rect);
- rect->x += offset;
- rect->width -= offset;
- }
- else if (strut->side == META_SIDE_RIGHT)
- {
- int offset = BOX_RIGHT (*rect) - BOX_LEFT(strut->rect);
- rect->width -= offset;
- }
- /* else ignore the strut */
- }
- else /* direction == META_DIRECTION_VERTICAL */
- {
- if (strut->side == META_SIDE_TOP)
- {
- int offset = BOX_BOTTOM(strut->rect) - BOX_TOP(*rect);
- rect->y += offset;
- rect->height -= offset;
- }
- else if (strut->side == META_SIDE_BOTTOM)
- {
- int offset = BOX_BOTTOM(*rect) - BOX_TOP(strut->rect);
- rect->height -= offset;
- }
- /* else ignore the strut */
- }
- } /* end loop over struts */
-} /* end meta_rectangle_expand_to_avoiding_struts */
-
-void
-meta_rectangle_free_list_and_elements (GList *filled_list)
-{
- g_list_free_full (filled_list, g_free);
-}
-
-gboolean
-meta_rectangle_could_fit_in_region (const GList *spanning_rects,
- const MetaRectangle *rect)
-{
- const GList *temp;
- gboolean could_fit;
-
- temp = spanning_rects;
- could_fit = FALSE;
- while (!could_fit && temp != NULL)
- {
- could_fit = could_fit || meta_rectangle_could_fit_rect (temp->data, rect);
- temp = temp->next;
- }
-
- return could_fit;
-}
-
-gboolean
-meta_rectangle_contained_in_region (const GList *spanning_rects,
- const MetaRectangle *rect)
-{
- const GList *temp;
- gboolean contained;
-
- temp = spanning_rects;
- contained = FALSE;
- while (!contained && temp != NULL)
- {
- contained = contained || meta_rectangle_contains_rect (temp->data, rect);
- temp = temp->next;
- }
-
- return contained;
-}
-
-gboolean
-meta_rectangle_overlaps_with_region (const GList *spanning_rects,
- const MetaRectangle *rect)
-{
- const GList *temp;
- gboolean overlaps;
-
- temp = spanning_rects;
- overlaps = FALSE;
- while (!overlaps && temp != NULL)
- {
- overlaps = overlaps || meta_rectangle_overlap (temp->data, rect);
- temp = temp->next;
- }
-
- return overlaps;
-}
-
-
-void
-meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects,
- FixedDirections fixed_directions,
- MetaRectangle *rect,
- const MetaRectangle *min_size)
-{
- const GList *temp;
- const MetaRectangle *best_rect = NULL;
- int best_overlap = 0;
-
- /* First, find best rectangle from spanning_rects to which we can clamp
- * rect to fit into.
- */
- for (temp = spanning_rects; temp; temp = temp->next)
- {
- MetaRectangle *compare_rect = temp->data;
- int maximal_overlap_amount_for_compare;
-
- /* If x is fixed and the entire width of rect doesn't fit in compare,
- * skip this rectangle.
- */
- if ((fixed_directions & FIXED_DIRECTION_X) &&
- (compare_rect->x > rect->x ||
- compare_rect->x + compare_rect->width < rect->x + rect->width))
- continue;
-
- /* If y is fixed and the entire height of rect doesn't fit in compare,
- * skip this rectangle.
- */
- if ((fixed_directions & FIXED_DIRECTION_Y) &&
- (compare_rect->y > rect->y ||
- compare_rect->y + compare_rect->height < rect->y + rect->height))
- continue;
-
- /* If compare can't hold the min_size window, skip this rectangle. */
- if (compare_rect->width < min_size->width ||
- compare_rect->height < min_size->height)
- continue;
-
- /* Determine maximal overlap amount */
- maximal_overlap_amount_for_compare =
- MIN (rect->width, compare_rect->width) *
- MIN (rect->height, compare_rect->height);
-
- /* See if this is the best rect so far */
- if (maximal_overlap_amount_for_compare > best_overlap)
- {
- best_rect = compare_rect;
- best_overlap = maximal_overlap_amount_for_compare;
- }
- }
-
- /* Clamp rect appropriately */
- if (best_rect == NULL)
- {
- g_warning ("No rect whose size to clamp to found!");
-
- /* If it doesn't fit, at least make it no bigger than it has to be */
- if (!(fixed_directions & FIXED_DIRECTION_X))
- rect->width = min_size->width;
- if (!(fixed_directions & FIXED_DIRECTION_Y))
- rect->height = min_size->height;
- }
- else
- {
- rect->width = MIN (rect->width, best_rect->width);
- rect->height = MIN (rect->height, best_rect->height);
- }
-}
-
-void
-meta_rectangle_clip_to_region (const GList *spanning_rects,
- FixedDirections fixed_directions,
- MetaRectangle *rect)
-{
- const GList *temp;
- const MetaRectangle *best_rect = NULL;
- int best_overlap = 0;
-
- /* First, find best rectangle from spanning_rects to which we will clip
- * rect into.
- */
- for (temp = spanning_rects; temp; temp = temp->next)
- {
- MetaRectangle *compare_rect = temp->data;
- MetaRectangle overlap;
- int maximal_overlap_amount_for_compare;
-
- /* If x is fixed and the entire width of rect doesn't fit in compare,
- * skip the rectangle.
- */
- if ((fixed_directions & FIXED_DIRECTION_X) &&
- (compare_rect->x > rect->x ||
- compare_rect->x + compare_rect->width < rect->x + rect->width))
- continue;
-
- /* If y is fixed and the entire height of rect doesn't fit in compare,
- * skip the rectangle.
- */
- if ((fixed_directions & FIXED_DIRECTION_Y) &&
- (compare_rect->y > rect->y ||
- compare_rect->y + compare_rect->height < rect->y + rect->height))
- continue;
-
- /* Determine maximal overlap amount */
- meta_rectangle_intersect (rect, compare_rect, &overlap);
- maximal_overlap_amount_for_compare = meta_rectangle_area (&overlap);
-
- /* See if this is the best rect so far */
- if (maximal_overlap_amount_for_compare > best_overlap)
- {
- best_rect = compare_rect;
- best_overlap = maximal_overlap_amount_for_compare;
- }
- }
-
- /* Clip rect appropriately */
- if (best_rect == NULL)
- {
- g_warning ("No rect to clip to found!");
- }
- else
- {
- /* Extra precaution with checking fixed direction shouldn't be needed
- * due to logic above, but it shouldn't hurt either.
- */
- if (!(fixed_directions & FIXED_DIRECTION_X))
- {
- /* Find the new left and right */
- int new_x = MAX (rect->x, best_rect->x);
- rect->width = MIN ((rect->x + rect->width) - new_x,
- (best_rect->x + best_rect->width) - new_x);
- rect->x = new_x;
- }
-
- /* Extra precaution with checking fixed direction shouldn't be needed
- * due to logic above, but it shouldn't hurt either.
- */
- if (!(fixed_directions & FIXED_DIRECTION_Y))
- {
- /* Clip the top, if needed */
- int new_y = MAX (rect->y, best_rect->y);
- rect->height = MIN ((rect->y + rect->height) - new_y,
- (best_rect->y + best_rect->height) - new_y);
- rect->y = new_y;
- }
- }
-}
-
-void
-meta_rectangle_shove_into_region (const GList *spanning_rects,
- FixedDirections fixed_directions,
- MetaRectangle *rect)
-{
- const GList *temp;
- const MetaRectangle *best_rect = NULL;
- int best_overlap = 0;
- int shortest_distance = G_MAXINT;
-
- /* First, find best rectangle from spanning_rects to which we will shove
- * rect into.
- */
-
- for (temp = spanning_rects; temp; temp = temp->next)
- {
- MetaRectangle *compare_rect = temp->data;
- int maximal_overlap_amount_for_compare;
- int dist_to_compare;
-
- /* If x is fixed and the entire width of rect doesn't fit in compare,
- * skip this rectangle.
- */
- if ((fixed_directions & FIXED_DIRECTION_X) &&
- (compare_rect->x > rect->x ||
- compare_rect->x + compare_rect->width < rect->x + rect->width))
- continue;
-
- /* If y is fixed and the entire height of rect doesn't fit in compare,
- * skip this rectangle.
- */
- if ((fixed_directions & FIXED_DIRECTION_Y) &&
- (compare_rect->y > rect->y ||
- compare_rect->y + compare_rect->height < rect->y + rect->height))
- continue;
-
- /* Determine maximal overlap amount between rect & compare_rect */
- maximal_overlap_amount_for_compare =
- MIN (rect->width, compare_rect->width) *
- MIN (rect->height, compare_rect->height);
-
- /* Determine distance necessary to put rect into compare_rect */
- dist_to_compare = 0;
- if (compare_rect->x > rect->x)
- dist_to_compare += compare_rect->x - rect->x;
- if (compare_rect->x + compare_rect->width < rect->x + rect->width)
- dist_to_compare += (rect->x + rect->width) -
- (compare_rect->x + compare_rect->width);
- if (compare_rect->y > rect->y)
- dist_to_compare += compare_rect->y - rect->y;
- if (compare_rect->y + compare_rect->height < rect->y + rect->height)
- dist_to_compare += (rect->y + rect->height) -
- (compare_rect->y + compare_rect->height);
-
- /* See if this is the best rect so far */
- if ((maximal_overlap_amount_for_compare > best_overlap) ||
- (maximal_overlap_amount_for_compare == best_overlap &&
- dist_to_compare < shortest_distance))
- {
- best_rect = compare_rect;
- best_overlap = maximal_overlap_amount_for_compare;
- shortest_distance = dist_to_compare;
- }
- }
-
- /* Shove rect appropriately */
- if (best_rect == NULL)
- {
- g_warning ("No rect to shove into found!");
- }
- else
- {
- /* Extra precaution with checking fixed direction shouldn't be needed
- * due to logic above, but it shouldn't hurt either.
- */
- if (!(fixed_directions & FIXED_DIRECTION_X))
- {
- /* Shove to the right, if needed */
- if (best_rect->x > rect->x)
- rect->x = best_rect->x;
-
- /* Shove to the left, if needed */
- if (best_rect->x + best_rect->width < rect->x + rect->width)
- rect->x = (best_rect->x + best_rect->width) - rect->width;
- }
-
- /* Extra precaution with checking fixed direction shouldn't be needed
- * due to logic above, but it shouldn't hurt either.
- */
- if (!(fixed_directions & FIXED_DIRECTION_Y))
- {
- /* Shove down, if needed */
- if (best_rect->y > rect->y)
- rect->y = best_rect->y;
-
- /* Shove up, if needed */
- if (best_rect->y + best_rect->height < rect->y + rect->height)
- rect->y = (best_rect->y + best_rect->height) - rect->height;
- }
- }
-}
-
-void
-meta_rectangle_find_linepoint_closest_to_point (double x1,
- double y1,
- double x2,
- double y2,
- double px,
- double py,
- double *valx,
- double *valy)
-{
- /* I'll use the shorthand rx, ry for the return values, valx & valy.
- * Now, we need (rx,ry) to be on the line between (x1,y1) and (x2,y2).
- * For that to happen, we first need the slope of the line from (x1,y1)
- * to (rx,ry) must match the slope of (x1,y1) to (x2,y2), i.e.:
- * (ry-y1) (y2-y1)
- * ------- = -------
- * (rx-x1) (x2-x1)
- * If x1==x2, though, this gives divide by zero errors, so we want to
- * rewrite the equation by multiplying both sides by (rx-x1)*(x2-x1):
- * (ry-y1)(x2-x1) = (y2-y1)(rx-x1)
- * This is a valid requirement even when x1==x2 (when x1==x2, this latter
- * equation will basically just mean that rx must be equal to both x1 and
- * x2)
- *
- * The other requirement that we have is that the line from (rx,ry) to
- * (px,py) must be perpendicular to the line from (x1,y1) to (x2,y2). So
- * we just need to get a vector in the direction of each line, take the
- * dot product of the two, and ensure that the result is 0:
- * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0.
- *
- * This gives us two equations and two unknowns:
- *
- * (ry-y1)(x2-x1) = (y2-y1)(rx-x1)
- * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0.
- *
- * This particular pair of equations is always solvable so long as
- * (x1,y1) and (x2,y2) are not the same point (and note that anyone who
- * calls this function that way is braindead because it means that they
- * really didn't specify a line after all). However, the caller should
- * be careful to avoid making (x1,y1) and (x2,y2) too close (e.g. like
- * 10^{-8} apart in each coordinate), otherwise roundoff error could
- * cause issues. Solving these equations by hand (or using Maple(TM) or
- * Mathematica(TM) or whatever) results in slightly messy expressions,
- * but that's all the below few lines do.
- */
-
- double diffx, diffy, den;
- diffx = x2 - x1;
- diffy = y2 - y1;
- den = diffx * diffx + diffy * diffy;
-
- *valx = (py * diffx * diffy + px * diffx * diffx +
- y2 * x1 * diffy - y1 * x2 * diffy) / den;
- *valy = (px * diffx * diffy + py * diffy * diffy +
- x2 * y1 * diffx - x1 * y2 * diffx) / den;
-}
-
-/***************************************************************************/
-/* */
-/* Switching gears to code for edges instead of just rectangles */
-/* */
-/***************************************************************************/
-
-gboolean
-meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge)
-{
- /* The reason for the usage of <= below instead of < is because we are
- * interested in in-the-way-or-adject'ness. So, a left (i.e. vertical
- * edge) occupying y positions 0-9 (which has a y of 0 and a height of
- * 10) and a rectangle with top at y=10 would be considered to "align" by
- * this function.
- */
- switch (edge->side_type)
- {
- case META_SIDE_LEFT:
- case META_SIDE_RIGHT:
- return BOX_TOP (*rect) <= BOX_BOTTOM (edge->rect) &&
- BOX_TOP (edge->rect) <= BOX_BOTTOM (*rect);
- case META_SIDE_TOP:
- case META_SIDE_BOTTOM:
- return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) &&
- BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect);
- default:
- g_assert_not_reached ();
- return FALSE;
- }
-}
-
-static GList*
-get_rect_minus_overlap (const GList *rect_in_list,
- MetaRectangle *overlap)
-{
- MetaRectangle *temp;
- MetaRectangle *rect = rect_in_list->data;
- GList *ret = NULL;
-
- if (BOX_LEFT (*rect) < BOX_LEFT (*overlap))
- {
- temp = g_new (MetaRectangle, 1);
- *temp = *rect;
- temp->width = BOX_LEFT (*overlap) - BOX_LEFT (*rect);
- ret = g_list_prepend (ret, temp);
- }
- if (BOX_RIGHT (*rect) > BOX_RIGHT (*overlap))
- {
- temp = g_new (MetaRectangle, 1);
- *temp = *rect;
- temp->x = BOX_RIGHT (*overlap);
- temp->width = BOX_RIGHT (*rect) - BOX_RIGHT (*overlap);
- ret = g_list_prepend (ret, temp);
- }
- if (BOX_TOP (*rect) < BOX_TOP (*overlap))
- {
- temp = g_new (MetaRectangle, 1);
- temp->x = overlap->x;
- temp->width = overlap->width;
- temp->y = BOX_TOP (*rect);
- temp->height = BOX_TOP (*overlap) - BOX_TOP (*rect);
- ret = g_list_prepend (ret, temp);
- }
- if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*overlap))
- {
- temp = g_new (MetaRectangle, 1);
- temp->x = overlap->x;
- temp->width = overlap->width;
- temp->y = BOX_BOTTOM (*overlap);
- temp->height = BOX_BOTTOM (*rect) - BOX_BOTTOM (*overlap);
- ret = g_list_prepend (ret, temp);
- }
-
- return ret;
-}
-
-static GList*
-replace_rect_with_list (GList *old_element,
- GList *new_list)
-{
- GList *ret;
- g_assert (old_element != NULL);
-
- if (!new_list)
- {
- /* If there is no new list, just remove the old_element */
- ret = g_list_remove_link (old_element, old_element);
- }
- else
- {
- /* Fix up the prev and next pointers everywhere */
- ret = new_list;
- if (old_element->prev)
- {
- old_element->prev->next = new_list;
- new_list->prev = old_element->prev;
- }
- if (old_element->next)
- {
- GList *tmp = g_list_last (new_list);
- old_element->next->prev = tmp;
- tmp->next = old_element->next;
- }
- }
-
- /* Free the old_element and return the appropriate "next" point */
- g_free (old_element->data);
- g_list_free_1 (old_element);
- return ret;
-}
-
-/* Make a copy of the strut list, make sure that copy only contains parts
- * of the old_struts that intersect with the region rect, and then do some
- * magic to make all the new struts disjoint (okay, we we break up struts
- * that aren't disjoint in a way that the overlapping part is only included
- * once, so it's not really magic...).
- */
-static GList*
-get_disjoint_strut_rect_list_in_region (const GSList *old_struts,
- const MetaRectangle *region)
-{
- GList *strut_rects;
- GList *tmp;
-
- /* First, copy the list */
- strut_rects = NULL;
- while (old_struts)
- {
- MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect;
- MetaRectangle *copy = g_new (MetaRectangle, 1);
- *copy = *cur;
- if (meta_rectangle_intersect (copy, region, copy))
- strut_rects = g_list_prepend (strut_rects, copy);
- else
- g_free (copy);
-
- old_struts = old_struts->next;
- }
-
- /* Now, loop over the list and check for intersections, fixing things up
- * where they do intersect.
- */
- tmp = strut_rects;
- while (tmp)
- {
- GList *compare;
-
- MetaRectangle *cur = tmp->data;
-
- compare = tmp->next;
- while (compare)
- {
- MetaRectangle *comp = compare->data;
- MetaRectangle overlap;
-
- if (meta_rectangle_intersect (cur, comp, &overlap))
- {
- /* Get a list of rectangles for each strut that don't overlap
- * the intersection region.
- */
- GList *cur_leftover = get_rect_minus_overlap (tmp, &overlap);
- GList *comp_leftover = get_rect_minus_overlap (compare, &overlap);
-
- /* Add the intersection region to cur_leftover */
- MetaRectangle *overlap_allocated = g_new (MetaRectangle, 1);
- *overlap_allocated = overlap;
- cur_leftover = g_list_prepend (cur_leftover, overlap_allocated);
-
- /* Fix up tmp, compare, and cur -- maybe struts too */
- if (strut_rects == tmp)
- {
- strut_rects = replace_rect_with_list (tmp, cur_leftover);
- tmp = strut_rects;
- }
- else
- tmp = replace_rect_with_list (tmp, cur_leftover);
- compare = replace_rect_with_list (compare, comp_leftover);
-
- if (compare == NULL)
- break;
-
- cur = tmp->data;
- }
-
- compare = compare->next;
- }
-
- tmp = tmp->next;
- }
-
- return strut_rects;
-}
-
-gint
-meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b)
-{
- const MetaEdge *a_edge_rect = (gconstpointer) a;
- const MetaEdge *b_edge_rect = (gconstpointer) b;
- int a_compare, b_compare;
-
- /* Edges must be both vertical or both horizontal, or it doesn't make
- * sense to compare them.
- */
- g_assert ((a_edge_rect->rect.width == 0 && b_edge_rect->rect.width == 0) ||
- (a_edge_rect->rect.height == 0 && b_edge_rect->rect.height == 0));
-
- a_compare = b_compare = 0; /* gcc-3.4.2 sucks at figuring initialized'ness */
-
- if (a_edge_rect->side_type == META_SIDE_LEFT ||
- a_edge_rect->side_type == META_SIDE_RIGHT)
- {
- a_compare = a_edge_rect->rect.x;
- b_compare = b_edge_rect->rect.x;
- if (a_compare == b_compare)
- {
- a_compare = a_edge_rect->rect.y;
- b_compare = b_edge_rect->rect.y;
- }
- }
- else if (a_edge_rect->side_type == META_SIDE_TOP ||
- a_edge_rect->side_type == META_SIDE_BOTTOM)
- {
- a_compare = a_edge_rect->rect.y;
- b_compare = b_edge_rect->rect.y;
- if (a_compare == b_compare)
- {
- a_compare = a_edge_rect->rect.x;
- b_compare = b_edge_rect->rect.x;
- }
- }
- else
- g_assert ("Some idiot wanted to sort sides of different types.");
-
- return a_compare - b_compare; /* positive value denotes a > b ... */
-}
-
-/* To make things easily testable, provide a nice way of sorting edges */
-gint
-meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b)
-{
- const MetaEdge *a_edge_rect = (gconstpointer) a;
- const MetaEdge *b_edge_rect = (gconstpointer) b;
-
- int a_compare, b_compare;
-
- a_compare = a_edge_rect->side_type;
- b_compare = b_edge_rect->side_type;
-
- if (a_compare == b_compare)
- return meta_rectangle_edge_cmp_ignore_type (a, b);
-
- return a_compare - b_compare; /* positive value denotes a > b ... */
-}
-
-/* Determine whether two given edges overlap */
-static gboolean
-edges_overlap (const MetaEdge *edge1,
- const MetaEdge *edge2)
-{
- if (edge1->rect.width == 0 && edge2->rect.width == 0)
- {
- return meta_rectangle_vert_overlap (&edge1->rect, &edge2->rect) &&
- edge1->rect.x == edge2->rect.x;
- }
- else if (edge1->rect.height == 0 && edge2->rect.height == 0)
- {
- return meta_rectangle_horiz_overlap (&edge1->rect, &edge2->rect) &&
- edge1->rect.y == edge2->rect.y;
- }
- else
- {
- return FALSE;
- }
-}
-
-static gboolean
-rectangle_and_edge_intersection (const MetaRectangle *rect,
- const MetaEdge *edge,
- MetaEdge *overlap,
- int *handle_type)
-{
- const MetaRectangle *rect2 = &edge->rect;
- MetaRectangle *result = &overlap->rect;
- gboolean intersect = TRUE;
-
- /* We don't know how to set these, so set them to invalid values */
- overlap->edge_type = -1;
- overlap->side_type = -1;
-
- /* Figure out what the intersection is */
- result->x = MAX (rect->x, rect2->x);
- result->y = MAX (rect->y, rect2->y);
- result->width = MIN (BOX_RIGHT (*rect), BOX_RIGHT (*rect2)) - result->x;
- result->height = MIN (BOX_BOTTOM (*rect), BOX_BOTTOM (*rect2)) - result->y;
-
- /* Find out if the intersection is empty; have to do it this way since
- * edges have a thickness of 0
- */
- if ((result->width < 0 || result->height < 0) ||
- (result->width == 0 && result->height == 0))
- {
- result->width = 0;
- result->height = 0;
- intersect = FALSE;
- }
- else
- {
- /* Need to figure out the handle_type, a somewhat weird quantity:
- * 0 - overlap is in middle of rect
- * -1 - overlap is at the side of rect, and is on the opposite side
- * of rect than the edge->side_type side
- * 1 - overlap is at the side of rect, and the side of rect it is
- * on is the edge->side_type side
- */
- switch (edge->side_type)
- {
- case META_SIDE_LEFT:
- if (result->x == rect->x)
- *handle_type = 1;
- else if (result->x == BOX_RIGHT (*rect))
- *handle_type = -1;
- else
- *handle_type = 0;
- break;
- case META_SIDE_RIGHT:
- if (result->x == rect->x)
- *handle_type = -1;
- else if (result->x == BOX_RIGHT (*rect))
- *handle_type = 1;
- else
- *handle_type = 0;
- break;
- case META_SIDE_TOP:
- if (result->y == rect->y)
- *handle_type = 1;
- else if (result->y == BOX_BOTTOM (*rect))
- *handle_type = -1;
- else
- *handle_type = 0;
- break;
- case META_SIDE_BOTTOM:
- if (result->y == rect->y)
- *handle_type = -1;
- else if (result->y == BOX_BOTTOM (*rect))
- *handle_type = 1;
- else
- *handle_type = 0;
- break;
- default:
- g_assert_not_reached ();
- }
- }
- return intersect;
-}
-
-/* Add all edges of the given rect to cur_edges and return the result. If
- * rect_is_internal is false, the side types are switched (LEFT<->RIGHT and
- * TOP<->BOTTOM).
- */
-static GList*
-add_edges (GList *cur_edges,
- const MetaRectangle *rect,
- gboolean rect_is_internal)
-{
- MetaEdge *temp_edge;
- int i;
-
- for (i=0; i<4; i++)
- {
- temp_edge = g_new (MetaEdge, 1);
- temp_edge->rect = *rect;
- switch (i)
- {
- case 0:
- temp_edge->side_type =
- rect_is_internal ? META_SIDE_LEFT : META_SIDE_RIGHT;
- temp_edge->rect.width = 0;
- break;
- case 1:
- temp_edge->side_type =
- rect_is_internal ? META_SIDE_RIGHT : META_SIDE_LEFT;
- temp_edge->rect.x += temp_edge->rect.width;
- temp_edge->rect.width = 0;
- break;
- case 2:
- temp_edge->side_type =
- rect_is_internal ? META_SIDE_TOP : META_SIDE_BOTTOM;
- temp_edge->rect.height = 0;
- break;
- case 3:
- temp_edge->side_type =
- rect_is_internal ? META_SIDE_BOTTOM : META_SIDE_TOP;
- temp_edge->rect.y += temp_edge->rect.height;
- temp_edge->rect.height = 0;
- break;
- }
- temp_edge->edge_type = META_EDGE_SCREEN;
- cur_edges = g_list_prepend (cur_edges, temp_edge);
- }
-
- return cur_edges;
-}
-
-/* Remove any part of old_edge that intersects remove and add any resulting
- * edges to cur_list. Return cur_list when finished.
- */
-static GList*
-split_edge (GList *cur_list,
- const MetaEdge *old_edge,
- const MetaEdge *remove)
-{
- MetaEdge *temp_edge;
- switch (old_edge->side_type)
- {
- case META_SIDE_LEFT:
- case META_SIDE_RIGHT:
- g_assert (meta_rectangle_vert_overlap (&old_edge->rect, &remove->rect));
- if (BOX_TOP (old_edge->rect) < BOX_TOP (remove->rect))
- {
- temp_edge = g_new (MetaEdge, 1);
- *temp_edge = *old_edge;
- temp_edge->rect.height = BOX_TOP (remove->rect)
- - BOX_TOP (old_edge->rect);
- cur_list = g_list_prepend (cur_list, temp_edge);
- }
- if (BOX_BOTTOM (old_edge->rect) > BOX_BOTTOM (remove->rect))
- {
- temp_edge = g_new (MetaEdge, 1);
- *temp_edge = *old_edge;
- temp_edge->rect.y = BOX_BOTTOM (remove->rect);
- temp_edge->rect.height = BOX_BOTTOM (old_edge->rect)
- - BOX_BOTTOM (remove->rect);
- cur_list = g_list_prepend (cur_list, temp_edge);
- }
- break;
- case META_SIDE_TOP:
- case META_SIDE_BOTTOM:
- g_assert (meta_rectangle_horiz_overlap (&old_edge->rect, &remove->rect));
- if (BOX_LEFT (old_edge->rect) < BOX_LEFT (remove->rect))
- {
- temp_edge = g_new (MetaEdge, 1);
- *temp_edge = *old_edge;
- temp_edge->rect.width = BOX_LEFT (remove->rect)
- - BOX_LEFT (old_edge->rect);
- cur_list = g_list_prepend (cur_list, temp_edge);
- }
- if (BOX_RIGHT (old_edge->rect) > BOX_RIGHT (remove->rect))
- {
- temp_edge = g_new (MetaEdge, 1);
- *temp_edge = *old_edge;
- temp_edge->rect.x = BOX_RIGHT (remove->rect);
- temp_edge->rect.width = BOX_RIGHT (old_edge->rect)
- - BOX_RIGHT (remove->rect);
- cur_list = g_list_prepend (cur_list, temp_edge);
- }
- break;
- default:
- g_assert_not_reached ();
- }
-
- return cur_list;
-}
-
-/* Split up edge and remove preliminary edges from strut_edges depending on
- * if and how rect and edge intersect.
- */
-static void
-fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
- GList **strut_edges, GList **edge_splits,
- gboolean *edge_needs_removal)
-{
- MetaEdge overlap;
- int handle_type;
-
- if (!rectangle_and_edge_intersection (rect, edge, &overlap, &handle_type))
- return;
-
- if (handle_type == 0 || handle_type == 1)
- {
- /* Put the result of removing overlap from edge into edge_splits */
- *edge_splits = split_edge (*edge_splits, edge, &overlap);
- *edge_needs_removal = TRUE;
- }
-
- if (handle_type == -1 || handle_type == 1)
- {
- /* Remove the overlap from strut_edges */
- /* First, loop over the edges of the strut */
- GList *tmp = *strut_edges;
- while (tmp)
- {
- MetaEdge *cur = tmp->data;
- /* If this is the edge that overlaps, then we need to split it */
- if (edges_overlap (cur, &overlap))
- {
- GList *delete_me = tmp;
-
- /* Split this edge into some new ones */
- *strut_edges = split_edge (*strut_edges, cur, &overlap);
-
- /* Delete the old one */
- tmp = tmp->next;
- g_free (cur);
- *strut_edges = g_list_delete_link (*strut_edges, delete_me);
- }
- else
- tmp = tmp->next;
- }
- }
-}
-
-/**
- * meta_rectangle_remove_intersections_with_boxes_from_edges: (skip)
- *
- * This function removes intersections of edges with the rectangles from the
- * list of edges.
- */
-GList*
-meta_rectangle_remove_intersections_with_boxes_from_edges (
- GList *edges,
- const GSList *rectangles)
-{
- const GSList *rect_iter;
- const int opposing = 1;
-
- /* Now remove all intersections of rectangles with the edge list */
- rect_iter = rectangles;
- while (rect_iter)
- {
- MetaRectangle *rect = rect_iter->data;
- GList *edge_iter = edges;
- while (edge_iter)
- {
- MetaEdge *edge = edge_iter->data;
- MetaEdge overlap;
- int handle;
- gboolean edge_iter_advanced = FALSE;
-
- /* If this edge overlaps with this rect... */
- if (rectangle_and_edge_intersection (rect, edge, &overlap, &handle))
- {
-
- /* "Intersections" where the edges touch but are opposite
- * sides (e.g. a left edge against the right edge) should not
- * be split. Note that the comments in
- * rectangle_and_edge_intersection() say that opposing edges
- * occur when handle is -1, BUT you need to remember that we
- * treat the left side of a window as a right edge because
- * it's what the right side of the window being moved should
- * be-resisted-by/snap-to. So opposing is really 1. Anyway,
- * we just keep track of it in the opposing constant set up
- * above and if handle isn't equal to that, then we know the
- * edge should be split.
- */
- if (handle != opposing)
- {
- /* Keep track of this edge so we can delete it below */
- GList *delete_me = edge_iter;
- edge_iter = edge_iter->next;
- edge_iter_advanced = TRUE;
-
- /* Split the edge and add the result to beginning of edges */
- edges = split_edge (edges, edge, &overlap);
-
- /* Now free the edge... */
- g_free (edge);
- edges = g_list_delete_link (edges, delete_me);
- }
- }
-
- if (!edge_iter_advanced)
- edge_iter = edge_iter->next;
- }
-
- rect_iter = rect_iter->next;
- }
-
- return edges;
-}
-
-/**
- * meta_rectangle_find_onscreen_edges: (skip)
- *
- * This function is trying to find all the edges of an onscreen region.
- */
-GList*
-meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
- const GSList *all_struts)
-{
- GList *ret;
- GList *fixed_strut_rects;
- GList *edge_iter;
- const GList *strut_rect_iter;
-
- /* The algorithm is basically as follows:
- * Make sure the struts are disjoint
- * Initialize the edge_set to the edges of basic_rect
- * Foreach strut:
- * Put together a preliminary new edge from the edges of the strut
- * Foreach edge in edge_set:
- * - Split the edge if it is partially contained inside the strut
- * - If the edge matches an edge of the strut (i.e. a strut just
- * against the edge of the screen or a not-next-to-edge-of-screen
- * strut adjacent to another), then both the edge from the
- * edge_set and the preliminary edge for the strut will need to
- * be split
- * Add any remaining "preliminary" strut edges to the edge_set
- */
-
- /* Make sure the struts are disjoint */
- fixed_strut_rects =
- get_disjoint_strut_rect_list_in_region (all_struts, basic_rect);
-
- /* Start off the list with the edges of basic_rect */
- ret = add_edges (NULL, basic_rect, TRUE);
-
- strut_rect_iter = fixed_strut_rects;
- while (strut_rect_iter)
- {
- MetaRectangle *strut_rect = (MetaRectangle*) strut_rect_iter->data;
-
- /* Get the new possible edges we may need to add from the strut */
- GList *new_strut_edges = add_edges (NULL, strut_rect, FALSE);
-
- edge_iter = ret;
- while (edge_iter)
- {
- MetaEdge *cur_edge = edge_iter->data;
- GList *splits_of_cur_edge = NULL;
- gboolean edge_needs_removal = FALSE;
-
- fix_up_edges (strut_rect, cur_edge,
- &new_strut_edges, &splits_of_cur_edge,
- &edge_needs_removal);
-
- if (edge_needs_removal)
- {
- /* Delete the old edge */
- GList *delete_me = edge_iter;
- edge_iter = edge_iter->next;
- g_free (cur_edge);
- ret = g_list_delete_link (ret, delete_me);
-
- /* Add the new split parts of the edge */
- ret = g_list_concat (splits_of_cur_edge, ret);
- }
- else
- {
- edge_iter = edge_iter->next;
- }
-
- /* edge_iter was already advanced above */
- }
-
- ret = g_list_concat (new_strut_edges, ret);
- strut_rect_iter = strut_rect_iter->next;
- }
-
- /* Sort the list */
- ret = g_list_sort (ret, meta_rectangle_edge_cmp);
-
- /* Free the fixed struts list */
- meta_rectangle_free_list_and_elements (fixed_strut_rects);
-
- return ret;
-}
-
-/**
- * meta_rectangle_find_nonintersected_monitor_edges: (skip)
- *
- */
-GList*
-meta_rectangle_find_nonintersected_monitor_edges (
- const GList *monitor_rects,
- const GSList *all_struts)
-{
- /* This function cannot easily be merged with
- * meta_rectangle_find_onscreen_edges() because real screen edges
- * and strut edges both are of the type "there ain't anything
- * immediately on the other side"; monitor edges are different.
- */
- GList *ret;
- const GList *cur;
- GSList *temp_rects;
-
- /* Initialize the return list to be empty */
- ret = NULL;
-
- /* start of ret with all the edges of monitors that are adjacent to
- * another monitor.
- */
- cur = monitor_rects;
- while (cur)
- {
- MetaRectangle *cur_rect = cur->data;
- const GList *compare = monitor_rects;
- while (compare)
- {
- MetaRectangle *compare_rect = compare->data;
-
- /* Check if cur might be horizontally adjacent to compare */
- if (meta_rectangle_vert_overlap(cur_rect, compare_rect))
- {
- MetaSide side_type;
- int y = MAX (cur_rect->y, compare_rect->y);
- int height = MIN (BOX_BOTTOM (*cur_rect) - y,
- BOX_BOTTOM (*compare_rect) - y);
- int width = 0;
- int x;
-
- if (BOX_LEFT (*cur_rect) == BOX_RIGHT (*compare_rect))
- {
- /* compare_rect is to the left of cur_rect */
- x = BOX_LEFT (*cur_rect);
- side_type = META_SIDE_LEFT;
- }
- else if (BOX_RIGHT (*cur_rect) == BOX_LEFT (*compare_rect))
- {
- /* compare_rect is to the right of cur_rect */
- x = BOX_RIGHT (*cur_rect);
- side_type = META_SIDE_RIGHT;
- }
- else
- /* These rectangles aren't adjacent after all */
- x = INT_MIN;
-
- /* If the rectangles really are adjacent */
- if (x != INT_MIN)
- {
- /* We need a left edge for the monitor on the right, and
- * a right edge for the monitor on the left. Just fill
- * up the edges and stick 'em on the list.
- */
- MetaEdge *new_edge = g_new (MetaEdge, 1);
-
- new_edge->rect = meta_rect (x, y, width, height);
- new_edge->side_type = side_type;
- new_edge->edge_type = META_EDGE_MONITOR;
-
- ret = g_list_prepend (ret, new_edge);
- }
- }
-
- /* Check if cur might be vertically adjacent to compare */
- if (meta_rectangle_horiz_overlap(cur_rect, compare_rect))
- {
- MetaSide side_type;
- int x = MAX (cur_rect->x, compare_rect->x);
- int width = MIN (BOX_RIGHT (*cur_rect) - x,
- BOX_RIGHT (*compare_rect) - x);
- int height = 0;
- int y;
-
- if (BOX_TOP (*cur_rect) == BOX_BOTTOM (*compare_rect))
- {
- /* compare_rect is to the top of cur_rect */
- y = BOX_TOP (*cur_rect);
- side_type = META_SIDE_TOP;
- }
- else if (BOX_BOTTOM (*cur_rect) == BOX_TOP (*compare_rect))
- {
- /* compare_rect is to the bottom of cur_rect */
- y = BOX_BOTTOM (*cur_rect);
- side_type = META_SIDE_BOTTOM;
- }
- else
- /* These rectangles aren't adjacent after all */
- y = INT_MIN;
-
- /* If the rectangles really are adjacent */
- if (y != INT_MIN)
- {
- /* We need a top edge for the monitor on the bottom, and
- * a bottom edge for the monitor on the top. Just fill
- * up the edges and stick 'em on the list.
- */
- MetaEdge *new_edge = g_new (MetaEdge, 1);
-
- new_edge->rect = meta_rect (x, y, width, height);
- new_edge->side_type = side_type;
- new_edge->edge_type = META_EDGE_MONITOR;
-
- ret = g_list_prepend (ret, new_edge);
- }
- }
-
- compare = compare->next;
- }
- cur = cur->next;
- }
-
- temp_rects = NULL;
- for (; all_struts; all_struts = all_struts->next)
- temp_rects = g_slist_prepend (temp_rects,
- &((MetaStrut*)all_struts->data)->rect);
- ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret,
- temp_rects);
- g_slist_free (temp_rects);
-
- /* Sort the list */
- ret = g_list_sort (ret, meta_rectangle_edge_cmp);
-
- return ret;
-}
-
-gboolean
-meta_rectangle_is_adjacent_to (MetaRectangle *rect,
- MetaRectangle *other)
-{
- int rect_x1 = rect->x;
- int rect_y1 = rect->y;
- int rect_x2 = rect->x + rect->width;
- int rect_y2 = rect->y + rect->height;
- int other_x1 = other->x;
- int other_y1 = other->y;
- int other_x2 = other->x + other->width;
- int other_y2 = other->y + other->height;
-
- if ((rect_x1 == other_x2 || rect_x2 == other_x1) &&
- !(rect_y2 <= other_y1 || rect_y1 >= other_y2))
- return TRUE;
- else if ((rect_y1 == other_y2 || rect_y2 == other_y1) &&
- !(rect_x2 <= other_x1 || rect_x1 >= other_x2))
- return TRUE;
- else
- return FALSE;
-}
-
-void
-meta_rectangle_scale_double (const MetaRectangle *rect,
- double scale,
- MetaRoundingStrategy rounding_strategy,
- MetaRectangle *dest)
-{
- graphene_rect_t tmp = GRAPHENE_RECT_INIT (rect->x, rect->y,
- rect->width, rect->height);
-
- graphene_rect_scale (&tmp, scale, scale, &tmp);
- meta_rectangle_from_graphene_rect (&tmp, rounding_strategy, dest);
-}
-
-void
-meta_rectangle_transform (const MetaRectangle *rect,
- MetaMonitorTransform transform,
- int width,
- int height,
- MetaRectangle *dest)
-{
- switch (transform)
- {
- case META_MONITOR_TRANSFORM_NORMAL:
- *dest = *rect;
- break;
- case META_MONITOR_TRANSFORM_90:
- *dest = (MetaRectangle) {
- .x = width - (rect->y + rect->height),
- .y = rect->x,
- .width = rect->height,
- .height = rect->width,
- };
- break;
- case META_MONITOR_TRANSFORM_180:
- *dest = (MetaRectangle) {
- .x = width - (rect->x + rect->width),
- .y = height - (rect->y + rect->height),
- .width = rect->width,
- .height = rect->height,
- };
- break;
- case META_MONITOR_TRANSFORM_270:
- *dest = (MetaRectangle) {
- .x = rect->y,
- .y = height - (rect->x + rect->width),
- .width = rect->height,
- .height = rect->width,
- };
- break;
- case META_MONITOR_TRANSFORM_FLIPPED:
- *dest = (MetaRectangle) {
- .x = width - (rect->x + rect->width),
- .y = rect->y,
- .width = rect->width,
- .height = rect->height,
- };
- break;
- case META_MONITOR_TRANSFORM_FLIPPED_90:
- *dest = (MetaRectangle) {
- .x = width - (rect->y + rect->height),
- .y = height - (rect->x + rect->width),
- .width = rect->height,
- .height = rect->width,
- };
- break;
- case META_MONITOR_TRANSFORM_FLIPPED_180:
- *dest = (MetaRectangle) {
- .x = rect->x,
- .y = height - (rect->y + rect->height),
- .width = rect->width,
- .height = rect->height,
- };
- break;
- case META_MONITOR_TRANSFORM_FLIPPED_270:
- *dest = (MetaRectangle) {
- .x = rect->y,
- .y = rect->x,
- .width = rect->height,
- .height = rect->width,
- };
- break;
- }
-}
-
-void
-meta_rectangle_from_graphene_rect (const graphene_rect_t *rect,
- MetaRoundingStrategy rounding_strategy,
- MetaRectangle *dest)
-{
- switch (rounding_strategy)
- {
- case META_ROUNDING_STRATEGY_SHRINK:
- {
- *dest = (MetaRectangle) {
- .x = ceilf (rect->origin.x),
- .y = ceilf (rect->origin.y),
- .width = floorf (rect->size.width),
- .height = floorf (rect->size.height),
- };
- }
- break;
- case META_ROUNDING_STRATEGY_GROW:
- {
- graphene_rect_t clamped = *rect;
-
- graphene_rect_round_extents (&clamped, &clamped);
-
- *dest = (MetaRectangle) {
- .x = clamped.origin.x,
- .y = clamped.origin.y,
- .width = clamped.size.width,
- .height = clamped.size.height,
- };
- }
- break;
- case META_ROUNDING_STRATEGY_ROUND:
- {
- *dest = (MetaRectangle) {
- .x = roundf (rect->origin.x),
- .y = roundf (rect->origin.y),
- .width = roundf (rect->size.width),
- .height = roundf (rect->size.height),
- };
- }
- }
-}
-
-void
-meta_rectangle_crop_and_scale (const MetaRectangle *rect,
- graphene_rect_t *src_rect,
- int dst_width,
- int dst_height,
- MetaRectangle *dest)
-{
- graphene_rect_t tmp = GRAPHENE_RECT_INIT (rect->x, rect->y,
- rect->width, rect->height);
-
- graphene_rect_scale (&tmp,
- src_rect->size.width / dst_width,
- src_rect->size.height / dst_height,
- &tmp);
- graphene_rect_offset (&tmp, src_rect->origin.x, src_rect->origin.y);
-
- meta_rectangle_from_graphene_rect (&tmp, META_ROUNDING_STRATEGY_GROW, dest);
-}
diff --git a/src/core/constraints.c b/src/core/constraints.c
deleted file mode 100644
index 4b1d95338..000000000
--- a/src/core/constraints.c
+++ /dev/null
@@ -1,1878 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter size/position constraints */
-
-/*
- * Copyright (C) 2002, 2003 Red Hat, Inc.
- * Copyright (C) 2003, 2004 Rob Adams
- * Copyright (C) 2005, 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/>.
- */
-
-#include "config.h"
-
-#include "core/constraints.h"
-
-#include <stdlib.h>
-#include <math.h>
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-logical-monitor.h"
-#include "backends/meta-monitor-manager-private.h"
-#include "core/boxes-private.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/place.h"
-#include "core/workspace-private.h"
-#include "meta/prefs.h"
-
-#if 0
- // This is the short and sweet version of how to hack on this file; see
- // doc/how-constraints-works.txt for the gory details. The basics of
- // understanding this file can be shown by the steps needed to add a new
- // constraint, which are:
- // 1) Add a new entry in the ConstraintPriority enum; higher values
- // have higher priority
- // 2) Write a new function following the format of the example below,
- // "constrain_whatever".
- // 3) Add your function to the all_constraints and all_constraint_names
- // arrays (the latter of which is for debugging purposes)
- //
- // An example constraint function, constrain_whatever:
- //
- // /* constrain_whatever does the following:
- // * Quits (returning true) if priority is higher than PRIORITY_WHATEVER
- // * If check_only is TRUE
- // * Returns whether the constraint is satisfied or not
- // * otherwise
- // * Enforces the constraint
- // * Note that the value of PRIORITY_WHATEVER is centralized with the
- // * priorities of other constraints in the definition of ConstrainPriority
- // * for easier maintenance and shuffling of priorities.
- // */
- // static gboolean
- // constrain_whatever (MetaWindow *window,
- // ConstraintInfo *info,
- // ConstraintPriority priority,
- // gboolean check_only)
- // {
- // if (priority > PRIORITY_WHATEVER)
- // return TRUE;
- //
- // /* Determine whether constraint applies; note that if the constraint
- // * cannot possibly be satisfied, constraint_applies should be set to
- // * false. If we don't do this, all constraints with a lesser priority
- // * will be dropped along with this one, and we'd rather apply as many as
- // * possible.
- // */
- // if (!constraint_applies)
- // return TRUE;
- //
- // /* Determine whether constraint is already satisfied; if we're only
- // * checking the status of whether the constraint is satisfied, we end
- // * here.
- // */
- // if (check_only || constraint_already_satisfied)
- // return constraint_already_satisfied;
- //
- // /* Enforce constraints */
- // return TRUE; /* Note that we exited early if check_only is FALSE; also,
- // * we know we can return TRUE here because we exited early
- // * if the constraint could not be satisfied; not that the
- // * return value is heeded in this case...
- // */
- // }
-#endif
-
-typedef enum
-{
- PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
- PRIORITY_ASPECT_RATIO = 0,
- PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
- PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
- PRIORITY_SIZE_HINTS_INCREMENTS = 1,
- PRIORITY_MAXIMIZATION = 2,
- PRIORITY_TILING = 2,
- PRIORITY_FULLSCREEN = 2,
- PRIORITY_SIZE_HINTS_LIMITS = 3,
- PRIORITY_TITLEBAR_VISIBLE = 4,
- PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4,
- PRIORITY_CUSTOM_RULE = 4,
- PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */
-} ConstraintPriority;
-
-typedef enum
-{
- ACTION_MOVE,
- ACTION_RESIZE,
- ACTION_MOVE_AND_RESIZE
-} ActionType;
-
-typedef struct
-{
- MetaRectangle orig;
- MetaRectangle current;
- MetaRectangle temporary;
- int rel_x;
- int rel_y;
- ActionType action_type;
- gboolean is_user_action;
-
- /* I know that these two things probably look similar at first, but they
- * have much different uses. See doc/how-constraints-works.txt for for
- * explanation of the differences and similarity between resize_gravity
- * and fixed_directions
- */
- MetaGravity resize_gravity;
- FixedDirections fixed_directions;
-
- /* work_area_monitor - current monitor region minus struts
- * entire_monitor - current monitor, including strut regions
- */
- MetaRectangle work_area_monitor;
- MetaRectangle entire_monitor;
-
- /* Spanning rectangles for the non-covered (by struts) region of the
- * screen and also for just the current monitor
- */
- GList *usable_screen_region;
- GList *usable_monitor_region;
-
- MetaMoveResizeFlags flags;
-} ConstraintInfo;
-
-static gboolean do_screen_and_monitor_relative_constraints (MetaWindow *window,
- GList *region_spanning_rectangles,
- ConstraintInfo *info,
- gboolean check_only);
-static gboolean constrain_custom_rule (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_modal_dialog (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_maximization (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_tiling (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_fullscreen (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_size_increments (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_size_limits (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_aspect_ratio (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_to_single_monitor (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_fully_onscreen (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_titlebar_visible (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-static gboolean constrain_partially_onscreen (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-
-static void setup_constraint_info (ConstraintInfo *info,
- MetaWindow *window,
- MetaMoveResizeFlags flags,
- MetaGravity resize_gravity,
- const MetaRectangle *orig,
- MetaRectangle *new);
-static void place_window_if_needed (MetaWindow *window,
- ConstraintInfo *info);
-static void update_onscreen_requirements (MetaWindow *window,
- ConstraintInfo *info);
-
-typedef gboolean (* ConstraintFunc) (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only);
-
-typedef struct {
- ConstraintFunc func;
- const char* name;
-} Constraint;
-
-static const Constraint all_constraints[] = {
- {constrain_custom_rule, "constrain_custom_rule"},
- {constrain_modal_dialog, "constrain_modal_dialog"},
- {constrain_maximization, "constrain_maximization"},
- {constrain_tiling, "constrain_tiling"},
- {constrain_fullscreen, "constrain_fullscreen"},
- {constrain_size_increments, "constrain_size_increments"},
- {constrain_size_limits, "constrain_size_limits"},
- {constrain_aspect_ratio, "constrain_aspect_ratio"},
- {constrain_to_single_monitor, "constrain_to_single_monitor"},
- {constrain_fully_onscreen, "constrain_fully_onscreen"},
- {constrain_titlebar_visible, "constrain_titlebar_visible"},
- {constrain_partially_onscreen, "constrain_partially_onscreen"},
- {NULL, NULL}
-};
-
-static gboolean
-do_all_constraints (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- const Constraint *constraint;
- gboolean satisfied;
-
- constraint = &all_constraints[0];
- satisfied = TRUE;
- while (constraint->func != NULL)
- {
- satisfied = satisfied &&
- (*constraint->func) (window, info, priority, check_only);
-
- if (!check_only)
- {
- /* Log how the constraint modified the position */
- meta_topic (META_DEBUG_GEOMETRY,
- "info->current is %d,%d +%d,%d after %s",
- info->current.x, info->current.y,
- info->current.width, info->current.height,
- constraint->name);
- }
- else if (!satisfied)
- {
- /* Log which constraint was not satisfied */
- meta_topic (META_DEBUG_GEOMETRY,
- "constraint %s not satisfied.",
- constraint->name);
- return FALSE;
- }
- ++constraint;
- }
-
- return TRUE;
-}
-
-void
-meta_window_constrain (MetaWindow *window,
- MetaMoveResizeFlags flags,
- MetaGravity resize_gravity,
- const MetaRectangle *orig,
- MetaRectangle *new,
- MetaRectangle *temporary,
- int *rel_x,
- int *rel_y)
-{
- ConstraintInfo info;
- ConstraintPriority priority = PRIORITY_MINIMUM;
- gboolean satisfied = FALSE;
-
- meta_topic (META_DEBUG_GEOMETRY,
- "Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d",
- window->desc,
- orig->x, orig->y, orig->width, orig->height,
- new->x, new->y, new->width, new->height);
-
- setup_constraint_info (&info,
- window,
- flags,
- resize_gravity,
- orig,
- new);
- place_window_if_needed (window, &info);
-
- while (!satisfied && priority <= PRIORITY_MAXIMUM) {
- gboolean check_only = TRUE;
-
- /* Individually enforce all the high-enough priority constraints */
- do_all_constraints (window, &info, priority, !check_only);
-
- /* Check if all high-enough priority constraints are simultaneously
- * satisfied
- */
- satisfied = do_all_constraints (window, &info, priority, check_only);
-
- /* Drop the least important constraints if we can't satisfy them all */
- priority++;
- }
-
- /* Make sure we use the constrained position */
- *new = info.current;
- *temporary = info.temporary;
- *rel_x = info.rel_x;
- *rel_y = info.rel_y;
-
- /* We may need to update window->require_fully_onscreen,
- * window->require_on_single_monitor, and perhaps other quantities
- * if this was a user move or user move-and-resize operation.
- */
- update_onscreen_requirements (window, &info);
-}
-
-static void
-setup_constraint_info (ConstraintInfo *info,
- MetaWindow *window,
- MetaMoveResizeFlags flags,
- MetaGravity resize_gravity,
- const MetaRectangle *orig,
- MetaRectangle *new)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
- MetaWorkspace *cur_workspace;
-
- info->orig = *orig;
- info->current = *new;
- info->temporary = *orig;
- info->rel_x = 0;
- info->rel_y = 0;
- info->flags = flags;
-
- if (info->current.width < 1)
- info->current.width = 1;
- if (info->current.height < 1)
- info->current.height = 1;
-
- if (flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_RESIZE_ACTION)
- info->action_type = ACTION_MOVE_AND_RESIZE;
- else if (flags & META_MOVE_RESIZE_RESIZE_ACTION)
- info->action_type = ACTION_RESIZE;
- else if (flags & META_MOVE_RESIZE_MOVE_ACTION)
- info->action_type = ACTION_MOVE;
- else
- g_error ("BAD, BAD developer! No treat for you! (Fix your calls to "
- "meta_window_move_resize_internal()).");
-
- info->is_user_action = (flags & META_MOVE_RESIZE_USER_ACTION);
-
- info->resize_gravity = resize_gravity;
-
- /* FIXME: fixed_directions might be more sane if we (a) made it
- * depend on the grab_op type instead of current amount of movement
- * (thus implying that it only has effect when user_action is true,
- * and (b) ignored it for aspect ratio windows -- at least in those
- * cases where both directions do actually change size.
- */
- info->fixed_directions = FIXED_DIRECTION_NONE;
- /* If x directions don't change but either y direction does */
- if ( orig->x == new->x && orig->x + orig->width == new->x + new->width &&
- (orig->y != new->y || orig->y + orig->height != new->y + new->height))
- {
- info->fixed_directions = FIXED_DIRECTION_X;
- }
- /* If y directions don't change but either x direction does */
- if ( orig->y == new->y && orig->y + orig->height == new->y + new->height &&
- (orig->x != new->x || orig->x + orig->width != new->x + new->width ))
- {
- info->fixed_directions = FIXED_DIRECTION_Y;
- }
- /* The point of fixed directions is just that "move to nearest valid
- * position" is sometimes a poorer choice than "move to nearest
- * valid position but only change this coordinate" for windows the
- * user is explicitly moving. This isn't ever true for things that
- * aren't explicit user interaction, though, so just clear it out.
- */
- if (!info->is_user_action)
- info->fixed_directions = FIXED_DIRECTION_NONE;
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager,
- &info->current);
- meta_window_get_work_area_for_logical_monitor (window,
- logical_monitor,
- &info->work_area_monitor);
-
- if (window->fullscreen && meta_window_has_fullscreen_monitors (window))
- {
- info->entire_monitor = window->fullscreen_monitors.top->rect;
- meta_rectangle_union (&info->entire_monitor,
- &window->fullscreen_monitors.bottom->rect,
- &info->entire_monitor);
- meta_rectangle_union (&info->entire_monitor,
- &window->fullscreen_monitors.left->rect,
- &info->entire_monitor);
- meta_rectangle_union (&info->entire_monitor,
- &window->fullscreen_monitors.right->rect,
- &info->entire_monitor);
- }
- else
- {
- info->entire_monitor = logical_monitor->rect;
- if (window->fullscreen)
- meta_window_adjust_fullscreen_monitor_rect (window, &info->entire_monitor);
- }
-
- cur_workspace = window->display->workspace_manager->active_workspace;
- info->usable_screen_region =
- meta_workspace_get_onscreen_region (cur_workspace);
- info->usable_monitor_region =
- meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor);
-
- /* Log all this information for debugging */
- meta_topic (META_DEBUG_GEOMETRY,
- "Setting up constraint info:\n"
- " orig: %d,%d +%d,%d\n"
- " new : %d,%d +%d,%d\n"
- " action_type : %s\n"
- " is_user_action : %s\n"
- " resize_gravity : %s\n"
- " fixed_directions: %s\n"
- " work_area_monitor: %d,%d +%d,%d\n"
- " entire_monitor : %d,%d +%d,%d",
- info->orig.x, info->orig.y, info->orig.width, info->orig.height,
- info->current.x, info->current.y,
- info->current.width, info->current.height,
- (info->action_type == ACTION_MOVE) ? "Move" :
- (info->action_type == ACTION_RESIZE) ? "Resize" :
- (info->action_type == ACTION_MOVE_AND_RESIZE) ? "Move&Resize" :
- "Freakin' Invalid Stupid",
- (info->is_user_action) ? "true" : "false",
- meta_gravity_to_string (info->resize_gravity),
- (info->fixed_directions == FIXED_DIRECTION_NONE) ? "None" :
- (info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" :
- (info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
- "Freakin' Invalid Stupid",
- info->work_area_monitor.x, info->work_area_monitor.y,
- info->work_area_monitor.width,
- info->work_area_monitor.height,
- info->entire_monitor.x, info->entire_monitor.y,
- info->entire_monitor.width, info->entire_monitor.height);
-}
-
-static MetaRectangle *
-get_start_rect_for_resize (MetaWindow *window,
- ConstraintInfo *info)
-{
- if (!info->is_user_action && info->action_type == ACTION_MOVE_AND_RESIZE)
- return &info->current;
- else
- return &info->orig;
-}
-
-static void
-place_window_if_needed(MetaWindow *window,
- ConstraintInfo *info)
-{
- gboolean did_placement;
-
- /* Do placement if any, so we go ahead and apply position
- * constraints in a move-only context. Don't place
- * maximized/minimized/fullscreen windows until they are
- * unmaximized, unminimized and unfullscreened.
- */
- did_placement = FALSE;
- if (!window->placed &&
- window->calc_placement &&
- !(window->maximized_horizontally ||
- window->maximized_vertically) &&
- !window->minimized &&
- !window->fullscreen)
- {
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaRectangle orig_rect;
- MetaRectangle placed_rect;
- MetaWorkspace *cur_workspace;
- MetaLogicalMonitor *logical_monitor;
-
- placed_rect = (MetaRectangle) {
- .x = window->rect.x,
- .y = window->rect.y,
- .width = info->current.width,
- .height = info->current.height
- };
-
- orig_rect = info->orig;
-
- if (window->placement.rule)
- {
- meta_window_process_placement (window,
- window->placement.rule,
- &info->rel_x, &info->rel_y);
- placed_rect.x = window->placement.rule->parent_rect.x + info->rel_x;
- placed_rect.y = window->placement.rule->parent_rect.y + info->rel_y;
- }
- else
- {
- meta_window_place (window, orig_rect.x, orig_rect.y,
- &placed_rect.x, &placed_rect.y);
- }
- did_placement = TRUE;
-
- /* placing the window may have changed the monitor. Find the
- * new monitor and update the ConstraintInfo
- */
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager,
- &placed_rect);
- info->entire_monitor = logical_monitor->rect;
- meta_window_get_work_area_for_logical_monitor (window,
- logical_monitor,
- &info->work_area_monitor);
- cur_workspace = window->display->workspace_manager->active_workspace;
- info->usable_monitor_region =
- meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor);
-
- info->current.x = placed_rect.x;
- info->current.y = placed_rect.y;
-
- /* Since we just barely placed the window, there's no reason to
- * consider any of the directions fixed.
- */
- info->fixed_directions = FIXED_DIRECTION_NONE;
- }
-
- if (window->placed || did_placement)
- {
- if (window->maximize_horizontally_after_placement ||
- window->maximize_vertically_after_placement)
- {
- /* define a sane saved_rect so that the user can unmaximize to
- * something reasonable.
- */
- if (info->current.width >= info->work_area_monitor.width)
- {
- info->current.width = .75 * info->work_area_monitor.width;
- info->current.x = info->work_area_monitor.x +
- .125 * info->work_area_monitor.width;
- }
- if (info->current.height >= info->work_area_monitor.height)
- {
- info->current.height = .75 * info->work_area_monitor.height;
- info->current.y = info->work_area_monitor.y +
- .083 * info->work_area_monitor.height;
- }
-
- /* idle_move_resize() uses the unconstrained_rect, so make sure it
- * uses the placed coordinates (bug #556696).
- */
- window->unconstrained_rect = info->current;
-
- if (window->maximize_horizontally_after_placement ||
- window->maximize_vertically_after_placement)
- meta_window_maximize_internal (window,
- (window->maximize_horizontally_after_placement ?
- META_MAXIMIZE_HORIZONTAL : 0 ) |
- (window->maximize_vertically_after_placement ?
- META_MAXIMIZE_VERTICAL : 0), &info->current);
-
- window->maximize_horizontally_after_placement = FALSE;
- window->maximize_vertically_after_placement = FALSE;
- }
- if (window->minimize_after_placement)
- {
- meta_window_minimize (window);
- window->minimize_after_placement = FALSE;
- }
- }
-}
-
-static void
-update_onscreen_requirements (MetaWindow *window,
- ConstraintInfo *info)
-{
- gboolean old;
-
- /* We only apply the various onscreen requirements to normal windows */
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK)
- return;
-
- /* We don't want to update the requirements for fullscreen windows;
- * fullscreen windows are specially handled anyway, and it updating
- * the requirements when windows enter fullscreen mode mess up the
- * handling of the window when it leaves that mode (especially when
- * the application sends a bunch of configurerequest events). See
- * #353699.
- */
- if (window->fullscreen)
- return;
-
- /* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
- * require_on_single_monitor, and require_titlebar_visible flags to
- * *become false* due to user interactions (which is allowed since
- * certain constraints are ignored for user interactions regardless of
- * the setting of these flags). However, whether to make these flags
- * *become true* due to just an application interaction is a little
- * trickier. It's possible that users may find not doing that strange
- * since two application interactions that resize in opposite ways don't
- * necessarily end up cancelling--but it may also be strange for the user
- * to have an application resize the window so that it's onscreen, the
- * user forgets about it, and then later the app is able to resize itself
- * off the screen. Anyway, for now, I think the latter is the more
- * problematic case but this may need to be revisited.
- */
-
- /* Update whether we want future constraint runs to require the
- * window to be on fully onscreen.
- */
- old = window->require_fully_onscreen;
- window->require_fully_onscreen =
- meta_rectangle_contained_in_region (info->usable_screen_region,
- &info->current);
- if (old != window->require_fully_onscreen)
- meta_topic (META_DEBUG_GEOMETRY,
- "require_fully_onscreen for %s toggled to %s",
- window->desc,
- window->require_fully_onscreen ? "TRUE" : "FALSE");
-
- /* Update whether we want future constraint runs to require the
- * window to be on a single monitor.
- */
- old = window->require_on_single_monitor;
- window->require_on_single_monitor =
- meta_rectangle_contained_in_region (info->usable_monitor_region,
- &info->current);
- if (old != window->require_on_single_monitor)
- meta_topic (META_DEBUG_GEOMETRY,
- "require_on_single_monitor for %s toggled to %s",
- window->desc,
- window->require_on_single_monitor ? "TRUE" : "FALSE");
-
- /* Update whether we want future constraint runs to require the
- * titlebar to be visible.
- */
- if (window->frame && window->decorated)
- {
- MetaRectangle titlebar_rect, frame_rect;
-
- meta_window_get_titlebar_rect (window, &titlebar_rect);
- meta_window_get_frame_rect (window, &frame_rect);
-
- /* translate into screen coordinates */
- titlebar_rect.x = frame_rect.x;
- titlebar_rect.y = frame_rect.y;
-
- old = window->require_titlebar_visible;
- window->require_titlebar_visible =
- meta_rectangle_overlaps_with_region (info->usable_screen_region,
- &titlebar_rect);
- if (old != window->require_titlebar_visible)
- meta_topic (META_DEBUG_GEOMETRY,
- "require_titlebar_visible for %s toggled to %s",
- window->desc,
- window->require_titlebar_visible ? "TRUE" : "FALSE");
- }
-}
-
-static inline void
-get_size_limits (MetaWindow *window,
- MetaRectangle *min_size,
- MetaRectangle *max_size)
-{
- /* We pack the results into MetaRectangle structs just for convenience; we
- * don't actually use the position of those rects.
- */
- min_size->x = min_size->y = max_size->x = max_size->y = 0;
- min_size->width = window->size_hints.min_width;
- min_size->height = window->size_hints.min_height;
- max_size->width = window->size_hints.max_width;
- max_size->height = window->size_hints.max_height;
-
- meta_window_client_rect_to_frame_rect (window, min_size, min_size);
- meta_window_client_rect_to_frame_rect (window, max_size, max_size);
-}
-
-static void
-placement_rule_flip_horizontally (MetaPlacementRule *placement_rule)
-{
- if (placement_rule->anchor & META_PLACEMENT_ANCHOR_LEFT)
- {
- placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_LEFT;
- placement_rule->anchor |= META_PLACEMENT_ANCHOR_RIGHT;
- }
- else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_RIGHT)
- {
- placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_RIGHT;
- placement_rule->anchor |= META_PLACEMENT_ANCHOR_LEFT;
- }
-
- if (placement_rule->gravity & META_PLACEMENT_GRAVITY_LEFT)
- {
- placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_LEFT;
- placement_rule->gravity |= META_PLACEMENT_GRAVITY_RIGHT;
- }
- else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_RIGHT)
- {
- placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_RIGHT;
- placement_rule->gravity |= META_PLACEMENT_GRAVITY_LEFT;
- }
-}
-
-static void
-placement_rule_flip_vertically (MetaPlacementRule *placement_rule)
-{
- if (placement_rule->anchor & META_PLACEMENT_ANCHOR_TOP)
- {
- placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_TOP;
- placement_rule->anchor |= META_PLACEMENT_ANCHOR_BOTTOM;
- }
- else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_BOTTOM)
- {
- placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_BOTTOM;
- placement_rule->anchor |= META_PLACEMENT_ANCHOR_TOP;
- }
-
- if (placement_rule->gravity & META_PLACEMENT_GRAVITY_TOP)
- {
- placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_TOP;
- placement_rule->gravity |= META_PLACEMENT_GRAVITY_BOTTOM;
- }
- else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_BOTTOM)
- {
- placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_BOTTOM;
- placement_rule->gravity |= META_PLACEMENT_GRAVITY_TOP;
- }
-}
-
-static void
-try_flip_window_position (MetaWindow *window,
- ConstraintInfo *info,
- MetaPlacementRule *placement_rule,
- MetaPlacementConstraintAdjustment constraint_adjustment,
- int parent_x,
- int parent_y,
- MetaRectangle *rect,
- int *rel_x,
- int *rel_y,
- MetaRectangle *intersection)
-{
- MetaPlacementRule flipped_rule = *placement_rule;
- MetaRectangle flipped_rect;
- MetaRectangle flipped_intersection;
- int flipped_rel_x;
- int flipped_rel_y;
-
- switch (constraint_adjustment)
- {
- case META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X:
- placement_rule_flip_horizontally (&flipped_rule);
- break;
- case META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y:
- placement_rule_flip_vertically (&flipped_rule);
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- flipped_rect = info->current;
- meta_window_process_placement (window, &flipped_rule,
- &flipped_rel_x, &flipped_rel_y);
- flipped_rect.x = parent_x + flipped_rel_x;
- flipped_rect.y = parent_y + flipped_rel_y;
- meta_rectangle_intersect (&flipped_rect, &info->work_area_monitor,
- &flipped_intersection);
-
- if ((constraint_adjustment == META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X &&
- flipped_intersection.width == flipped_rect.width) ||
- (constraint_adjustment == META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y &&
- flipped_intersection.height == flipped_rect.height))
- {
- *placement_rule = flipped_rule;
- *rect = flipped_rect;
- *rel_x = flipped_rel_x;
- *rel_y = flipped_rel_y;
- *intersection = flipped_intersection;
- }
-}
-
-static gboolean
-is_custom_rule_satisfied (MetaRectangle *rect,
- MetaPlacementRule *placement_rule,
- MetaRectangle *intersection)
-{
- uint32_t x_constrain_actions, y_constrain_actions;
-
- x_constrain_actions = (META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X |
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X);
- y_constrain_actions = (META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y |
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y);
- if ((placement_rule->constraint_adjustment & x_constrain_actions &&
- rect->width != intersection->width) ||
- (placement_rule->constraint_adjustment & y_constrain_actions &&
- rect->height != intersection->height))
- return FALSE;
- else
- return TRUE;
-}
-
-static gboolean
-constrain_custom_rule (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- MetaPlacementRule *placement_rule;
- MetaRectangle intersection;
- gboolean constraint_satisfied;
- MetaRectangle temporary_rect;
- MetaRectangle adjusted_unconstrained;
- int adjusted_rel_x;
- int adjusted_rel_y;
- MetaPlacementRule current_rule;
- MetaWindow *parent;
- int parent_x, parent_y;
-
- if (priority > PRIORITY_CUSTOM_RULE)
- return TRUE;
-
- placement_rule = meta_window_get_placement_rule (window);
- if (!placement_rule)
- return TRUE;
-
- parent = meta_window_get_transient_for (window);
- if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED)
- {
- placement_rule->parent_rect.x = parent->rect.x;
- placement_rule->parent_rect.y = parent->rect.y;
- }
- parent_x = placement_rule->parent_rect.x;
- parent_y = placement_rule->parent_rect.y;
-
- /*
- * Calculate the temporary position, meaning a position that will be
- * applied if the new constrained position requires asynchronous
- * configuration of the window. This happens for example when the parent
- * moves, causing this window to change relative position, meaning it can
- * only have its newly constrained position applied when the configuration is
- * acknowledged.
- */
-
- switch (window->placement.state)
- {
- case META_PLACEMENT_STATE_UNCONSTRAINED:
- temporary_rect = info->current;
- break;
- case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED:
- case META_PLACEMENT_STATE_CONSTRAINED_PENDING:
- case META_PLACEMENT_STATE_CONSTRAINED_FINISHED:
- case META_PLACEMENT_STATE_INVALIDATED:
- temporary_rect = (MetaRectangle) {
- .x = parent->rect.x + window->placement.current.rel_x,
- .y = parent->rect.y + window->placement.current.rel_y,
- .width = info->current.width,
- .height = info->current.height,
- };
- break;
- }
-
- /*
- * Calculate an adjusted current position. Depending on the rule
- * configuration and placement state, this may result in window being
- * reconstrained.
- */
-
- adjusted_unconstrained = temporary_rect;
-
- if (window->placement.state == META_PLACEMENT_STATE_INVALIDATED ||
- window->placement.state == META_PLACEMENT_STATE_UNCONSTRAINED ||
- (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED &&
- placement_rule->is_reactive))
- {
- meta_window_process_placement (window, placement_rule,
- &adjusted_rel_x,
- &adjusted_rel_y);
- adjusted_unconstrained.x = parent_x + adjusted_rel_x;
- adjusted_unconstrained.y = parent_y + adjusted_rel_y;
- }
- else if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_PENDING)
- {
- adjusted_rel_x = window->placement.pending.rel_x;
- adjusted_rel_y = window->placement.pending.rel_y;
- adjusted_unconstrained.x = window->placement.pending.x;
- adjusted_unconstrained.y = window->placement.pending.y;
- }
- else
- {
- adjusted_rel_x = window->placement.current.rel_x;
- adjusted_rel_y = window->placement.current.rel_y;
- }
-
- meta_rectangle_intersect (&adjusted_unconstrained, &info->work_area_monitor,
- &intersection);
-
- constraint_satisfied = (meta_rectangle_equal (&info->current,
- &adjusted_unconstrained) &&
- is_custom_rule_satisfied (&adjusted_unconstrained,
- placement_rule,
- &intersection));
-
- if (check_only)
- return constraint_satisfied;
-
- info->current = adjusted_unconstrained;
- info->rel_x = adjusted_rel_x;
- info->rel_y = adjusted_rel_y;
- info->temporary = temporary_rect;
-
- switch (window->placement.state)
- {
- case META_PLACEMENT_STATE_CONSTRAINED_FINISHED:
- if (!placement_rule->is_reactive)
- return TRUE;
- break;
- case META_PLACEMENT_STATE_CONSTRAINED_PENDING:
- case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED:
- return TRUE;
- case META_PLACEMENT_STATE_UNCONSTRAINED:
- case META_PLACEMENT_STATE_INVALIDATED:
- break;
- }
-
- if (constraint_satisfied)
- goto done;
-
- /*
- * Process the placement rule in order either until constraints are
- * satisfied, or there are no more rules to process.
- */
-
- current_rule = *placement_rule;
-
- if (info->current.width != intersection.width &&
- (current_rule.constraint_adjustment &
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X))
- {
- try_flip_window_position (window, info, &current_rule,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X,
- parent_x,
- parent_y,
- &info->current,
- &info->rel_x,
- &info->rel_y,
- &intersection);
- }
- if (info->current.height != intersection.height &&
- (current_rule.constraint_adjustment &
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y))
- {
- try_flip_window_position (window, info, &current_rule,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y,
- parent_x,
- parent_y,
- &info->current,
- &info->rel_x,
- &info->rel_y,
- &intersection);
- }
-
- meta_rectangle_intersect (&info->current, &info->work_area_monitor,
- &intersection);
- constraint_satisfied = is_custom_rule_satisfied (&info->current,
- placement_rule,
- &intersection);
-
- if (constraint_satisfied)
- goto done;
-
- if (current_rule.constraint_adjustment &
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X)
- {
- int current_x2;
- int work_area_monitor_x2;
- int new_x;
-
- current_x2 = info->current.x + info->current.width;
- work_area_monitor_x2 = (info->work_area_monitor.x +
- info->work_area_monitor.width);
-
- if (current_x2 > work_area_monitor_x2)
- {
- new_x = MAX (info->work_area_monitor.x,
- work_area_monitor_x2 - info->current.width);
- }
- else if (info->current.x < info->work_area_monitor.x)
- {
- new_x = info->work_area_monitor.x;
- }
- else
- {
- new_x = info->current.x;
- }
-
- info->rel_x += new_x - info->current.x;
- info->current.x = new_x;
- }
- if (current_rule.constraint_adjustment &
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
- {
- int current_y2;
- int work_area_monitor_y2;
- int new_y;
-
- current_y2 = info->current.y + info->current.height;
- work_area_monitor_y2 = (info->work_area_monitor.y +
- info->work_area_monitor.height);
-
- if (current_y2 > work_area_monitor_y2)
- {
- new_y = MAX (info->work_area_monitor.y,
- work_area_monitor_y2 - info->current.height);
- }
- else if (info->current.y < info->work_area_monitor.y)
- {
- new_y = info->work_area_monitor.y;
- }
- else
- {
- new_y = info->current.y;
- }
-
- info->rel_y += new_y - info->current.y;
- info->current.y = new_y;
- }
-
- meta_rectangle_intersect (&info->current, &info->work_area_monitor,
- &intersection);
- constraint_satisfied = is_custom_rule_satisfied (&info->current,
- placement_rule,
- &intersection);
-
- if (constraint_satisfied)
- goto done;
-
- if (current_rule.constraint_adjustment &
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X)
- {
- int new_x;
- new_x = intersection.x;
- info->current.width = intersection.width;
- info->rel_x += new_x - info->current.x;
- info->current.x = new_x;
- }
- if (current_rule.constraint_adjustment &
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
- {
- int new_y;
- new_y = intersection.y;
- info->current.height = intersection.height;
- info->rel_y += new_y - info->current.y;
- info->current.y = new_y;
- }
-
-done:
- window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_PENDING;
-
- window->placement.pending.rel_x = info->rel_x;
- window->placement.pending.rel_y = info->rel_y;
- window->placement.pending.x = info->current.x;
- window->placement.pending.y = info->current.y;
-
- return TRUE;
-}
-
-static gboolean
-constrain_modal_dialog (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- int x, y;
- MetaWindow *parent = meta_window_get_transient_for (window);
- MetaRectangle child_rect, parent_rect;
- gboolean constraint_already_satisfied;
-
- if (!parent ||
- !meta_window_is_attached_dialog (window) ||
- meta_window_get_placement_rule (window))
- return TRUE;
-
- /* We want to center the dialog on the parent, including the decorations
- for both of them. info->current is in client X window coordinates, so we need
- to convert them to frame coordinates, apply the centering and then
- convert back to client.
- */
-
- child_rect = info->current;
-
- meta_window_get_frame_rect (parent, &parent_rect);
-
- child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
- child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
- x = child_rect.x;
- y = child_rect.y;
-
- constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
-
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- info->current.y = y;
- info->current.x = x;
- /* The calculated position above may need adjustment to make sure the
- * dialog does not end up partially off-screen */
- return do_screen_and_monitor_relative_constraints (window,
- info->usable_screen_region,
- info,
- check_only);
-}
-
-static gboolean
-constrain_maximization (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- MetaRectangle target_size;
- MetaRectangle min_size, max_size;
- gboolean hminbad, vminbad;
- gboolean horiz_equal, vert_equal;
- gboolean constraint_already_satisfied;
-
- if (priority > PRIORITY_MAXIMIZATION)
- return TRUE;
-
- /* Determine whether constraint applies; exit if it doesn't */
- if ((!window->maximized_horizontally && !window->maximized_vertically) ||
- META_WINDOW_TILED_SIDE_BY_SIDE (window))
- return TRUE;
-
- /* Calculate target_size = maximized size of (window + frame) */
- if (META_WINDOW_TILED_MAXIMIZED (window))
- {
- meta_window_get_tile_area (window, window->tile_mode, &target_size);
- }
- else if (META_WINDOW_MAXIMIZED (window))
- {
- target_size = info->work_area_monitor;
- }
- else
- {
- /* Amount of maximization possible in a single direction depends
- * on which struts could occlude the window given its current
- * position. For example, a vertical partial strut on the right
- * is only relevant for a horizontally maximized window when the
- * window is at a vertical position where it could be occluded
- * by that partial strut.
- */
- MetaDirection direction;
- GSList *active_workspace_struts;
-
- if (window->maximized_horizontally)
- direction = META_DIRECTION_HORIZONTAL;
- else
- direction = META_DIRECTION_VERTICAL;
- active_workspace_struts = workspace_manager->active_workspace->all_struts;
-
- target_size = info->current;
- meta_rectangle_expand_to_avoiding_struts (&target_size,
- &info->entire_monitor,
- direction,
- active_workspace_struts);
- }
-
- /* Check min size constraints; max size constraints are ignored for maximized
- * windows, as per bug 327543.
- */
- get_size_limits (window, &min_size, &max_size);
- hminbad = target_size.width < min_size.width && window->maximized_horizontally;
- vminbad = target_size.height < min_size.height && window->maximized_vertically;
- if (hminbad || vminbad)
- return TRUE;
-
- /* Determine whether constraint is already satisfied; exit if it is */
- horiz_equal = target_size.x == info->current.x &&
- target_size.width == info->current.width;
- vert_equal = target_size.y == info->current.y &&
- target_size.height == info->current.height;
- constraint_already_satisfied =
- (horiz_equal || !window->maximized_horizontally) &&
- (vert_equal || !window->maximized_vertically);
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- /*** Enforce constraint ***/
- if (window->maximized_horizontally)
- {
- info->current.x = target_size.x;
- info->current.width = target_size.width;
- }
- if (window->maximized_vertically)
- {
- info->current.y = target_size.y;
- info->current.height = target_size.height;
- }
- return TRUE;
-}
-
-static gboolean
-constrain_tiling (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- MetaRectangle target_size;
- MetaRectangle min_size, max_size;
- gboolean hminbad, vminbad;
- gboolean horiz_equal, vert_equal;
- gboolean constraint_already_satisfied;
-
- if (priority > PRIORITY_TILING)
- return TRUE;
-
- /* Determine whether constraint applies; exit if it doesn't */
- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
- return TRUE;
-
- /* Calculate target_size - as the tile previews need this as well, we
- * use an external function for the actual calculation
- */
- meta_window_get_tile_area (window, window->tile_mode, &target_size);
-
- /* Check min size constraints; max size constraints are ignored as for
- * maximized windows.
- */
- get_size_limits (window, &min_size, &max_size);
- hminbad = target_size.width < min_size.width;
- vminbad = target_size.height < min_size.height;
- if (hminbad || vminbad)
- return TRUE;
-
- /* Determine whether constraint is already satisfied; exit if it is */
- horiz_equal = target_size.x == info->current.x &&
- target_size.width == info->current.width;
- vert_equal = target_size.y == info->current.y &&
- target_size.height == info->current.height;
- constraint_already_satisfied = horiz_equal && vert_equal;
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- /*** Enforce constraint ***/
- info->current.x = target_size.x;
- info->current.width = target_size.width;
- info->current.y = target_size.y;
- info->current.height = target_size.height;
-
- return TRUE;
-}
-
-
-static gboolean
-constrain_fullscreen (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- MetaRectangle min_size, max_size, monitor;
- gboolean too_big, too_small, constraint_already_satisfied;
-
- if (priority > PRIORITY_FULLSCREEN)
- return TRUE;
-
- /* Determine whether constraint applies; exit if it doesn't */
- if (!window->fullscreen)
- return TRUE;
-
- monitor = info->entire_monitor;
-
- get_size_limits (window, &min_size, &max_size);
- too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
- too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
- if (too_big || too_small)
- return TRUE;
-
- /* Determine whether constraint is already satisfied; exit if it is */
- constraint_already_satisfied =
- meta_rectangle_equal (&info->current, &monitor);
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- /*** Enforce constraint ***/
- info->current = monitor;
- return TRUE;
-}
-
-static gboolean
-constrain_size_increments (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- int bh, hi, bw, wi, extra_height, extra_width;
- int new_width, new_height;
- gboolean constraint_already_satisfied;
- MetaRectangle *start_rect;
- MetaRectangle client_rect;
-
- if (priority > PRIORITY_SIZE_HINTS_INCREMENTS)
- return TRUE;
-
- /* Determine whether constraint applies; exit if it doesn't */
- if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
- META_WINDOW_TILED_SIDE_BY_SIDE (window) ||
- info->action_type == ACTION_MOVE)
- return TRUE;
-
- meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
-
- /* Determine whether constraint is already satisfied; exit if it is */
- bh = window->size_hints.base_height;
- hi = window->size_hints.height_inc;
- bw = window->size_hints.base_width;
- wi = window->size_hints.width_inc;
- extra_height = (client_rect.height - bh) % hi;
- extra_width = (client_rect.width - bw) % wi;
- /* ignore size increments for maximized windows */
- if (window->maximized_horizontally)
- extra_width *= 0;
- if (window->maximized_vertically)
- extra_height *= 0;
- /* constraint is satisfied iff there is no extra height or width */
- constraint_already_satisfied =
- (extra_height == 0 && extra_width == 0);
-
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- /*** Enforce constraint ***/
- new_width = client_rect.width - extra_width;
- new_height = client_rect.height - extra_height;
-
- /* Adjusting down instead of up (as done in the above two lines) may
- * violate minimum size constraints; fix the adjustment if this
- * happens.
- */
- if (new_width < window->size_hints.min_width)
- new_width += ((window->size_hints.min_width - new_width)/wi + 1)*wi;
- if (new_height < window->size_hints.min_height)
- new_height += ((window->size_hints.min_height - new_height)/hi + 1)*hi;
-
- {
- client_rect.width = new_width;
- client_rect.height = new_height;
- meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
- new_width = client_rect.width;
- new_height = client_rect.height;
- }
-
- start_rect = get_start_rect_for_resize (window, info);
-
- /* Resize to the new size */
- meta_rectangle_resize_with_gravity (start_rect,
- &info->current,
- info->resize_gravity,
- new_width,
- new_height);
- return TRUE;
-}
-
-static gboolean
-constrain_size_limits (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- MetaRectangle min_size, max_size;
- gboolean too_big, too_small, constraint_already_satisfied;
- int new_width, new_height;
- MetaRectangle *start_rect;
-
- if (priority > PRIORITY_SIZE_HINTS_LIMITS)
- return TRUE;
-
- /* Determine whether constraint applies; exit if it doesn't.
- *
- * Note: The old code didn't apply this constraint for fullscreen or
- * maximized windows--but that seems odd to me. *shrug*
- */
- if (info->action_type == ACTION_MOVE)
- return TRUE;
-
- /* Determine whether constraint is already satisfied; exit if it is */
- get_size_limits (window, &min_size, &max_size);
- /* We ignore max-size limits for maximized windows; see #327543 */
- if (window->maximized_horizontally)
- max_size.width = MAX (max_size.width, info->current.width);
- if (window->maximized_vertically)
- max_size.height = MAX (max_size.height, info->current.height);
- too_small = !meta_rectangle_could_fit_rect (&info->current, &min_size);
- too_big = !meta_rectangle_could_fit_rect (&max_size, &info->current);
- constraint_already_satisfied = !too_big && !too_small;
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- /*** Enforce constraint ***/
- new_width = CLAMP (info->current.width, min_size.width, max_size.width);
- new_height = CLAMP (info->current.height, min_size.height, max_size.height);
-
- start_rect = get_start_rect_for_resize (window, info);
-
- meta_rectangle_resize_with_gravity (start_rect,
- &info->current,
- info->resize_gravity,
- new_width,
- new_height);
- return TRUE;
-}
-
-static gboolean
-constrain_aspect_ratio (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- double minr, maxr;
- gboolean constraints_are_inconsistent, constraint_already_satisfied;
- int fudge, new_width, new_height;
- double best_width, best_height;
- double alt_width, alt_height;
- MetaRectangle *start_rect;
- MetaRectangle client_rect;
-
- if (priority > PRIORITY_ASPECT_RATIO)
- return TRUE;
-
- /* Determine whether constraint applies; exit if it doesn't. */
- minr = window->size_hints.min_aspect.x /
- (double)window->size_hints.min_aspect.y;
- maxr = window->size_hints.max_aspect.x /
- (double)window->size_hints.max_aspect.y;
- constraints_are_inconsistent = minr > maxr;
- if (constraints_are_inconsistent ||
- META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
- META_WINDOW_TILED_SIDE_BY_SIDE (window) ||
- info->action_type == ACTION_MOVE)
- return TRUE;
-
- /* Determine whether constraint is already satisfied; exit if it is. We
- * need the following to hold:
- *
- * width
- * minr <= ------ <= maxr
- * height
- *
- * But we need to allow for some slight fudging since width and height
- * are integers instead of floating point numbers (this is particularly
- * important when minr == maxr), so we allow width and height to be off
- * a little bit from strictly satisfying these equations. For just one
- * sided resizing, we have to make the fudge factor a little bigger
- * because of how meta_rectangle_resize_with_gravity treats those as
- * being a resize increment (FIXME: I should handle real resize
- * increments better here...)
- */
- switch (info->resize_gravity)
- {
- case META_GRAVITY_WEST:
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_EAST:
- fudge = 2;
- break;
-
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NORTH_EAST:
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_STATIC:
- default:
- fudge = 1;
- break;
- }
-
- meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
-
- constraint_already_satisfied =
- client_rect.width - (client_rect.height * minr ) > -minr*fudge &&
- client_rect.width - (client_rect.height * maxr ) < maxr*fudge;
- if (check_only || constraint_already_satisfied)
- return constraint_already_satisfied;
-
- /*** Enforce constraint ***/
- new_width = client_rect.width;
- new_height = client_rect.height;
-
- switch (info->resize_gravity)
- {
- case META_GRAVITY_WEST:
- case META_GRAVITY_EAST:
- /* Yeah, I suck for doing implicit rounding -- sue me */
- new_height = CLAMP (new_height, new_width / maxr, new_width / minr);
- break;
-
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- /* Yeah, I suck for doing implicit rounding -- sue me */
- new_width = CLAMP (new_width, new_height * minr, new_height * maxr);
- break;
-
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NORTH_EAST:
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_STATIC:
- default:
- /* Find what width would correspond to new_height, and what height would
- * correspond to new_width */
- alt_width = CLAMP (new_width, new_height * minr, new_height * maxr);
- alt_height = CLAMP (new_height, new_width / maxr, new_width / minr);
-
- /* The line connecting the points (alt_width, new_height) and
- * (new_width, alt_height) provide a range of
- * valid-for-the-aspect-ratio-constraint sizes. We want the
- * size in that range closest to the value requested, i.e. the
- * point on the line which is closest to the point (new_width,
- * new_height)
- */
- meta_rectangle_find_linepoint_closest_to_point (alt_width, new_height,
- new_width, alt_height,
- new_width, new_height,
- &best_width, &best_height);
-
- /* Yeah, I suck for doing implicit rounding -- sue me */
- new_width = best_width;
- new_height = best_height;
-
- break;
- }
-
- {
- client_rect.width = new_width;
- client_rect.height = new_height;
- meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
- new_width = client_rect.width;
- new_height = client_rect.height;
- }
-
- start_rect = get_start_rect_for_resize (window, info);
-
- meta_rectangle_resize_with_gravity (start_rect,
- &info->current,
- info->resize_gravity,
- new_width,
- new_height);
-
- return TRUE;
-}
-
-static gboolean
-do_screen_and_monitor_relative_constraints (
- MetaWindow *window,
- GList *region_spanning_rectangles,
- ConstraintInfo *info,
- gboolean check_only)
-{
- gboolean exit_early = FALSE, constraint_satisfied;
- MetaRectangle how_far_it_can_be_smushed, min_size, max_size;
-
-#ifdef WITH_VERBOSE_MODE
- if (meta_is_verbose ())
- {
- /* First, log some debugging information */
- char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
-
- meta_topic (META_DEBUG_GEOMETRY,
- "screen/monitor constraint; region_spanning_rectangles: %s",
- meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
- spanning_region));
- }
-#endif
-
- /* Determine whether constraint applies; exit if it doesn't */
- how_far_it_can_be_smushed = info->current;
- get_size_limits (window, &min_size, &max_size);
-
- if (info->action_type != ACTION_MOVE)
- {
- if (!(info->fixed_directions & FIXED_DIRECTION_X))
- how_far_it_can_be_smushed.width = min_size.width;
-
- if (!(info->fixed_directions & FIXED_DIRECTION_Y))
- how_far_it_can_be_smushed.height = min_size.height;
- }
- if (!meta_rectangle_could_fit_in_region (region_spanning_rectangles,
- &how_far_it_can_be_smushed))
- exit_early = TRUE;
-
- /* Determine whether constraint is already satisfied; exit if it is */
- constraint_satisfied =
- meta_rectangle_contained_in_region (region_spanning_rectangles,
- &info->current);
- if (exit_early || constraint_satisfied || check_only)
- return constraint_satisfied;
-
- /* Enforce constraint */
-
- /* Clamp rectangle size for resize or move+resize actions */
- if (info->action_type != ACTION_MOVE)
- meta_rectangle_clamp_to_fit_into_region (region_spanning_rectangles,
- info->fixed_directions,
- &info->current,
- &min_size);
-
- if (info->is_user_action && info->action_type == ACTION_RESIZE)
- /* For user resize, clip to the relevant region */
- meta_rectangle_clip_to_region (region_spanning_rectangles,
- info->fixed_directions,
- &info->current);
- else
- /* For everything else, shove the rectangle into the relevant region */
- meta_rectangle_shove_into_region (region_spanning_rectangles,
- info->fixed_directions,
- &info->current);
-
- return TRUE;
-}
-
-static gboolean
-constrain_to_single_monitor (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
-
- if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR)
- return TRUE;
-
- /* Exit early if we know the constraint won't apply--note that this constraint
- * is only meant for normal windows (e.g. we don't want docks to be shoved
- * "onscreen" by their own strut) and we can't apply it to frameless windows
- * or else users will be unable to move windows such as XMMS across monitors.
- */
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK ||
- meta_monitor_manager_get_num_logical_monitors (monitor_manager) == 1 ||
- !window->require_on_single_monitor ||
- !window->frame ||
- info->is_user_action ||
- meta_window_get_placement_rule (window))
- return TRUE;
-
- /* Have a helper function handle the constraint for us */
- return do_screen_and_monitor_relative_constraints (window,
- info->usable_monitor_region,
- info,
- check_only);
-}
-
-static gboolean
-constrain_fully_onscreen (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA)
- return TRUE;
-
- /* Exit early if we know the constraint won't apply--note that this constraint
- * is only meant for normal windows (e.g. we don't want docks to be shoved
- * "onscreen" by their own strut).
- */
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK ||
- window->fullscreen ||
- !window->require_fully_onscreen ||
- info->is_user_action ||
- meta_window_get_placement_rule (window))
- return TRUE;
-
- /* Have a helper function handle the constraint for us */
- return do_screen_and_monitor_relative_constraints (window,
- info->usable_screen_region,
- info,
- check_only);
-}
-
-static gboolean
-constrain_titlebar_visible (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- gboolean unconstrained_user_action;
- gboolean retval;
- int bottom_amount;
- int horiz_amount_offscreen, vert_amount_offscreen;
- int horiz_amount_onscreen, vert_amount_onscreen;
-
- if (priority > PRIORITY_TITLEBAR_VISIBLE)
- return TRUE;
-
- /* Allow the titlebar beyond the top of the screen only if the user wasn't
- * clicking on the frame to start the move.
- */
- unconstrained_user_action =
- info->is_user_action && !window->display->grab_frame_action;
-
- /* Exit early if we know the constraint won't apply--note that this constraint
- * is only meant for normal windows (e.g. we don't want docks to be shoved
- * "onscreen" by their own strut).
- */
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK ||
- window->fullscreen ||
- !window->require_titlebar_visible ||
- unconstrained_user_action ||
- meta_window_get_placement_rule (window))
- return TRUE;
-
- /* Determine how much offscreen things are allowed. We first need to
- * figure out how much must remain on the screen. For that, we use 25%
- * window width/height but clamp to the range of (10,75) pixels. This is
- * somewhat of a seat of my pants random guess at what might look good.
- * Then, the amount that is allowed off is just the window size minus
- * this amount (but no less than 0 for tiny windows).
- */
- horiz_amount_onscreen = info->current.width / 4;
- vert_amount_onscreen = info->current.height / 4;
- horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75);
- vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75);
- horiz_amount_offscreen = info->current.width - horiz_amount_onscreen;
- vert_amount_offscreen = info->current.height - vert_amount_onscreen;
- horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0);
- vert_amount_offscreen = MAX (vert_amount_offscreen, 0);
- /* Allow the titlebar to touch the bottom panel; If there is no titlebar,
- * require vert_amount to remain on the screen.
- */
- if (window->frame)
- {
- MetaFrameBorders borders;
- meta_frame_calc_borders (window->frame, &borders);
-
- bottom_amount = info->current.height - borders.visible.top;
- vert_amount_onscreen = borders.visible.top;
- }
- else
- bottom_amount = vert_amount_offscreen;
-
- /* Extend the region, have a helper function handle the constraint,
- * then return the region to its original size.
- */
- meta_rectangle_expand_region_conditionally (info->usable_screen_region,
- horiz_amount_offscreen,
- horiz_amount_offscreen,
- 0, /* Don't let titlebar off */
- bottom_amount,
- horiz_amount_onscreen,
- vert_amount_onscreen);
- retval =
- do_screen_and_monitor_relative_constraints (window,
- info->usable_screen_region,
- info,
- check_only);
- meta_rectangle_expand_region_conditionally (info->usable_screen_region,
- -horiz_amount_offscreen,
- -horiz_amount_offscreen,
- 0, /* Don't let titlebar off */
- -bottom_amount,
- horiz_amount_onscreen,
- vert_amount_onscreen);
-
- return retval;
-}
-
-static gboolean
-constrain_partially_onscreen (MetaWindow *window,
- ConstraintInfo *info,
- ConstraintPriority priority,
- gboolean check_only)
-{
- gboolean retval;
- int top_amount, bottom_amount;
- int horiz_amount_offscreen, vert_amount_offscreen;
- int horiz_amount_onscreen, vert_amount_onscreen;
-
- if (priority > PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA)
- return TRUE;
-
- /* Exit early if we know the constraint won't apply--note that this constraint
- * is only meant for normal windows (e.g. we don't want docks to be shoved
- * "onscreen" by their own strut).
- */
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK ||
- meta_window_get_placement_rule (window))
- return TRUE;
-
- /* Determine how much offscreen things are allowed. We first need to
- * figure out how much must remain on the screen. For that, we use 25%
- * window width/height but clamp to the range of (10,75) pixels. This is
- * somewhat of a seat of my pants random guess at what might look good.
- * Then, the amount that is allowed off is just the window size minus
- * this amount (but no less than 0 for tiny windows).
- */
- horiz_amount_onscreen = info->current.width / 4;
- vert_amount_onscreen = info->current.height / 4;
- horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75);
- vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75);
- horiz_amount_offscreen = info->current.width - horiz_amount_onscreen;
- vert_amount_offscreen = info->current.height - vert_amount_onscreen;
- horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0);
- vert_amount_offscreen = MAX (vert_amount_offscreen, 0);
- top_amount = vert_amount_offscreen;
- /* Allow the titlebar to touch the bottom panel; If there is no titlebar,
- * require vert_amount to remain on the screen.
- */
- if (window->frame)
- {
- MetaFrameBorders borders;
- meta_frame_calc_borders (window->frame, &borders);
-
- bottom_amount = info->current.height - borders.visible.top;
- vert_amount_onscreen = borders.visible.top;
- }
- else
- bottom_amount = vert_amount_offscreen;
-
- /* Extend the region, have a helper function handle the constraint,
- * then return the region to its original size.
- */
- meta_rectangle_expand_region_conditionally (info->usable_screen_region,
- horiz_amount_offscreen,
- horiz_amount_offscreen,
- top_amount,
- bottom_amount,
- horiz_amount_onscreen,
- vert_amount_onscreen);
- retval =
- do_screen_and_monitor_relative_constraints (window,
- info->usable_screen_region,
- info,
- check_only);
- meta_rectangle_expand_region_conditionally (info->usable_screen_region,
- -horiz_amount_offscreen,
- -horiz_amount_offscreen,
- -top_amount,
- -bottom_amount,
- horiz_amount_onscreen,
- vert_amount_onscreen);
-
- return retval;
-}
diff --git a/src/core/constraints.h b/src/core/constraints.h
deleted file mode 100644
index eaa4e4594..000000000
--- a/src/core/constraints.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter size/position constraints */
-
-/*
- * Copyright (C) 2002 Red Hat, Inc.
- * Copyright (C) 2005 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/>.
- */
-
-#ifndef META_CONSTRAINTS_H
-#define META_CONSTRAINTS_H
-
-#include "core/frame.h"
-#include "core/window-private.h"
-#include "meta/util.h"
-
-void meta_window_constrain (MetaWindow *window,
- MetaMoveResizeFlags flags,
- MetaGravity resize_gravity,
- const MetaRectangle *orig,
- MetaRectangle *new,
- MetaRectangle *intermediate,
- int *rel_x,
- int *rel_y);
-
-#endif /* META_CONSTRAINTS_H */
diff --git a/src/core/delete.c b/src/core/delete.c
deleted file mode 100644
index 058764b08..000000000
--- a/src/core/delete.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter window deletion */
-
-/*
- * Copyright (C) 2001, 2002 Havoc Pennington
- * Copyright (C) 2004 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/>.
- */
-
-#define _XOPEN_SOURCE /* for kill() */
-
-#include "config.h"
-
-#include <errno.h>
-
-#include "compositor/compositor-private.h"
-#include "core/util-private.h"
-#include "core/window-private.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/workspace.h"
-
-static void
-close_dialog_response_cb (MetaCloseDialog *dialog,
- MetaCloseDialogResponse response,
- MetaWindow *window)
-{
- if (response == META_CLOSE_DIALOG_RESPONSE_FORCE_CLOSE)
- meta_window_kill (window);
-}
-
-static void
-meta_window_ensure_close_dialog (MetaWindow *window)
-{
- MetaDisplay *display;
-
- if (window->close_dialog)
- return;
-
- display = window->display;
- window->close_dialog = meta_compositor_create_close_dialog (display->compositor,
- window);
- g_signal_connect (window->close_dialog, "response",
- G_CALLBACK (close_dialog_response_cb), window);
-}
-
-void
-meta_window_set_alive (MetaWindow *window,
- gboolean is_alive)
-{
- if (is_alive && window->close_dialog)
- {
- meta_close_dialog_hide (window->close_dialog);
- }
- else if (!is_alive)
- {
- meta_window_ensure_close_dialog (window);
- meta_close_dialog_show (window->close_dialog);
-
- if (window->display &&
- window->display->event_route == META_EVENT_ROUTE_NORMAL &&
- window == window->display->focus_window)
- meta_close_dialog_focus (window->close_dialog);
- }
-}
-
-void
-meta_window_check_alive (MetaWindow *window,
- guint32 timestamp)
-{
- meta_display_ping_window (window, timestamp);
-}
-
-void
-meta_window_delete (MetaWindow *window,
- guint32 timestamp)
-{
- META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
-
- meta_window_check_alive (window, timestamp);
-}
-
-void
-meta_window_kill (MetaWindow *window)
-{
- pid_t pid = meta_window_get_pid (window);
-
- if (pid > 0)
- {
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Killing %s with kill()",
- window->desc);
-
- if (kill (pid, 9) == 0)
- return;
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Failed to signal %s: %s",
- window->desc, strerror (errno));
- }
-
- META_WINDOW_GET_CLASS (window)->kill (window);
-}
-
-void
-meta_window_free_delete_dialog (MetaWindow *window)
-{
- if (window->close_dialog &&
- meta_close_dialog_is_visible (window->close_dialog))
- meta_close_dialog_hide (window->close_dialog);
- g_clear_object (&window->close_dialog);
-}
diff --git a/src/core/display-private.h b/src/core/display-private.h
deleted file mode 100644
index 8efac0b49..000000000
--- a/src/core/display-private.h
+++ /dev/null
@@ -1,434 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter X display handler */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002 Red Hat, Inc.
- * Copyright (C) 2003 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/>.
- */
-
-#ifndef META_DISPLAY_PRIVATE_H
-#define META_DISPLAY_PRIVATE_H
-
-#include "meta/display.h"
-
-#include <glib.h>
-#include <X11/extensions/sync.h>
-#include <X11/Xlib.h>
-
-#include "clutter/clutter.h"
-#include "core/keybindings-private.h"
-#include "core/meta-gesture-tracker-private.h"
-#include "core/meta-pad-action-mapper.h"
-#include "core/stack-tracker.h"
-#include "core/startup-notification-private.h"
-#include "meta/barrier.h"
-#include "meta/boxes.h"
-#include "meta/common.h"
-#include "meta/meta-selection.h"
-#include "meta/prefs.h"
-
-typedef struct _MetaBell MetaBell;
-typedef struct _MetaStack MetaStack;
-
-typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
-
-typedef enum
-{
- META_LIST_DEFAULT = 0, /* normal windows */
- META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
- META_LIST_SORTED = 1 << 1, /* sort list by mru */
-} MetaListWindowsFlags;
-
-#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
-#define _NET_WM_STATE_ADD 1 /* add/set property */
-#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
-
-/* This is basically a bogus number, just has to be large enough
- * to handle the expected case of the alt+tab operation, where
- * we want to ignore serials from UnmapNotify on the tab popup,
- * and the LeaveNotify/EnterNotify from the pointer ungrab. It
- * also has to be big enough to hold ignored serials from the point
- * where we reshape the stage to the point where we get events back.
- */
-#define N_IGNORED_CROSSING_SERIALS 10
-
-typedef enum
-{
- META_TILE_NONE,
- META_TILE_LEFT,
- META_TILE_RIGHT,
- META_TILE_MAXIMIZED
-} MetaTileMode;
-
-typedef enum
-{
- /* Normal interaction where you're interacting with windows.
- * Events go to windows normally. */
- META_EVENT_ROUTE_NORMAL,
-
- /* In a window operation like moving or resizing. All events
- * goes to MetaWindow, but not to the actual client window. */
- META_EVENT_ROUTE_WINDOW_OP,
-
- /* In a compositor grab operation. All events go to the
- * compositor plugin. */
- META_EVENT_ROUTE_COMPOSITOR_GRAB,
-
- /* A Wayland application has a popup open. All events go to
- * the Wayland application. */
- META_EVENT_ROUTE_WAYLAND_POPUP,
-
- /* The user is clicking on a window button. */
- META_EVENT_ROUTE_FRAME_BUTTON,
-} MetaEventRoute;
-
-typedef void (* MetaDisplayWindowFunc) (MetaWindow *window,
- gpointer user_data);
-
-struct _MetaDisplay
-{
- GObject parent_instance;
-
- MetaX11Display *x11_display;
-
- int clutter_event_filter;
-
- /* 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), and the serial of the request
- * or event that caused this.
- */
- MetaWindow *focus_window;
-
- /* last timestamp passed to XSetInputFocus */
- guint32 last_focus_time;
-
- /* last user interaction time in any app */
- guint32 last_user_time;
-
- /* whether we're using mousenav (only relevant for sloppy&mouse focus modes;
- * !mouse_mode means "keynav mode")
- */
- guint mouse_mode : 1;
-
- /* Helper var used when focus_new_windows setting is 'strict'; only
- * relevant in 'strict' mode and if the focus window is a terminal.
- * In that case, we don't allow new windows to take focus away from
- * a terminal, but if the user explicitly did something that should
- * allow a different window to gain focus (e.g. global keybinding or
- * clicking on a dock), then we will allow the transfer.
- */
- guint allow_terminal_deactivation : 1;
-
- /*< private-ish >*/
- GHashTable *stamps;
- GHashTable *wayland_windows;
-
- /* serials of leave/unmap events that may
- * correspond to an enter event we should
- * ignore
- */
- unsigned long ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS];
-
- guint32 current_time;
-
- /* We maintain a sequence counter, incremented for each #MetaWindow
- * created. This is exposed by meta_window_get_stable_sequence()
- * but is otherwise not used inside mutter.
- *
- * It can be useful to plugins which want to sort windows in a
- * stable fashion.
- */
- guint32 window_sequence_counter;
-
- /* Pings which we're waiting for a reply from */
- GSList *pending_pings;
-
- /* Pending focus change */
- guint focus_timeout_id;
-
- /* Pending autoraise */
- guint autoraise_timeout_id;
- MetaWindow* autoraise_window;
-
- /* Event routing */
- MetaEventRoute event_route;
-
- /* current window operation */
- MetaGrabOp grab_op;
- MetaWindow *grab_window;
- int grab_button;
- int grab_anchor_root_x;
- int grab_anchor_root_y;
- MetaRectangle grab_anchor_window_pos;
- MetaTileMode grab_tile_mode;
- int grab_tile_monitor_number;
- int grab_latest_motion_x;
- int grab_latest_motion_y;
- guint grab_have_pointer : 1;
- guint grab_have_keyboard : 1;
- guint grab_frame_action : 1;
- MetaRectangle grab_initial_window_pos;
- int grab_initial_x, grab_initial_y; /* These are only relevant for */
- gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
- int64_t grab_last_moveresize_time;
- MetaEdgeResistanceData *grab_edge_resistance_data;
- unsigned int grab_last_edge_resistance_flags;
-
- int grab_resize_timeout_id;
-
- MetaKeyBindingManager key_binding_manager;
-
- /* Opening the display */
- unsigned int display_opening : 1;
-
- /* Closing down the display */
- int closing;
-
- /* Managed by compositor.c */
- MetaCompositor *compositor;
-
- MetaGestureTracker *gesture_tracker;
- ClutterEventSequence *pointer_emulating_sequence;
-
- ClutterActor *current_pad_osd;
- MetaPadActionMapper *pad_action_mapper;
-
- MetaStartupNotification *startup_notification;
-
- MetaCursor current_cursor;
-
- MetaStack *stack;
- MetaStackTracker *stack_tracker;
-
- guint tile_preview_timeout_id;
- guint preview_tile_mode : 2;
-
- GSList *startup_sequences;
-
- guint work_area_later;
- guint check_fullscreen_later;
-
- MetaBell *bell;
- MetaWorkspaceManager *workspace_manager;
-
- MetaSoundPlayer *sound_player;
-
- MetaSelectionSource *selection_source;
- GBytes *saved_clipboard;
- gchar *saved_clipboard_mimetype;
- MetaSelection *selection;
-};
-
-struct _MetaDisplayClass
-{
- GObjectClass parent_class;
-};
-
-#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
- ( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \
- (( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \
- )
-/**
- * XSERVER_TIME_IS_BEFORE:
- *
- * See the docs for meta_display_xserver_time_is_before().
- */
-#define XSERVER_TIME_IS_BEFORE(time1, time2) \
- ( (time1) == 0 || \
- (XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \
- (time2) != 0) \
- )
-
-MetaDisplay * meta_display_new (MetaContext *context,
- GError **error);
-
-void meta_display_manage_all_xwindows (MetaDisplay *display);
-void meta_display_unmanage_windows (MetaDisplay *display,
- guint32 timestamp);
-
-/* Utility function to compare the stacking of two windows */
-int meta_display_stack_cmp (const void *a,
- const void *b);
-
-/* Each MetaWindow is uniquely identified by a 64-bit "stamp"; unlike a
- * a MetaWindow *, a stamp will never be recycled
- */
-MetaWindow* meta_display_lookup_stamp (MetaDisplay *display,
- guint64 stamp);
-void meta_display_register_stamp (MetaDisplay *display,
- guint64 *stampp,
- MetaWindow *window);
-void meta_display_unregister_stamp (MetaDisplay *display,
- guint64 stamp);
-
-/* A "stack id" is a XID or a stamp */
-#define META_STACK_ID_IS_X11(id) ((id) < G_GUINT64_CONSTANT(0x100000000))
-
-META_EXPORT_TEST
-MetaWindow* meta_display_lookup_stack_id (MetaDisplay *display,
- guint64 stack_id);
-
-/* for debug logging only; returns a human-description of the stack
- * ID - a small number of buffers are recycled, so the result must
- * be used immediately or copied */
-const char *meta_display_describe_stack_id (MetaDisplay *display,
- guint64 stack_id);
-
-void meta_display_register_wayland_window (MetaDisplay *display,
- MetaWindow *window);
-void meta_display_unregister_wayland_window (MetaDisplay *display,
- MetaWindow *window);
-
-void meta_display_notify_window_created (MetaDisplay *display,
- MetaWindow *window);
-
-META_EXPORT_TEST
-GSList* meta_display_list_windows (MetaDisplay *display,
- MetaListWindowsFlags flags);
-
-MetaDisplay* meta_display_for_x_display (Display *xdisplay);
-
-META_EXPORT_TEST
-MetaDisplay* meta_get_display (void);
-
-void meta_display_reload_cursor (MetaDisplay *display);
-void meta_display_update_cursor (MetaDisplay *display);
-
-void meta_display_check_threshold_reached (MetaDisplay *display,
- int x,
- int y);
-void meta_display_grab_window_buttons (MetaDisplay *display,
- Window xwindow);
-void meta_display_ungrab_window_buttons (MetaDisplay *display,
- Window xwindow);
-
-void meta_display_grab_focus_window_button (MetaDisplay *display,
- MetaWindow *window);
-void meta_display_ungrab_focus_window_button (MetaDisplay *display,
- MetaWindow *window);
-
-/* Next function is defined in edge-resistance.c */
-void meta_display_cleanup_edges (MetaDisplay *display);
-
-/* utility goo */
-const char* meta_event_mode_to_string (int m);
-const char* meta_event_detail_to_string (int d);
-
-void meta_display_queue_retheme_all_windows (MetaDisplay *display);
-
-void meta_display_ping_window (MetaWindow *window,
- guint32 serial);
-void meta_display_pong_for_serial (MetaDisplay *display,
- guint32 serial);
-
-MetaGravity meta_resize_gravity_from_grab_op (MetaGrabOp op);
-
-gboolean meta_grab_op_is_moving (MetaGrabOp op);
-gboolean meta_grab_op_is_resizing (MetaGrabOp op);
-gboolean meta_grab_op_is_mouse (MetaGrabOp op);
-gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
-
-void meta_display_queue_autoraise_callback (MetaDisplay *display,
- MetaWindow *window);
-void meta_display_remove_autoraise_callback (MetaDisplay *display);
-
-void meta_display_overlay_key_activate (MetaDisplay *display);
-void meta_display_accelerator_activate (MetaDisplay *display,
- guint action,
- ClutterKeyEvent *event);
-gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
-
-void meta_display_sync_wayland_input_focus (MetaDisplay *display);
-void meta_display_update_focus_window (MetaDisplay *display,
- MetaWindow *window);
-
-void meta_display_sanity_check_timestamps (MetaDisplay *display,
- guint32 timestamp);
-gboolean meta_display_timestamp_too_old (MetaDisplay *display,
- guint32 *timestamp);
-
-void meta_display_remove_pending_pings_for_window (MetaDisplay *display,
- MetaWindow *window);
-
-MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
-
-gboolean meta_display_show_restart_message (MetaDisplay *display,
- const char *message);
-gboolean meta_display_request_restart (MetaDisplay *display);
-
-gboolean meta_display_show_resize_popup (MetaDisplay *display,
- gboolean show,
- MetaRectangle *rect,
- int display_w,
- int display_h);
-
-void meta_set_is_restart (gboolean whether);
-
-void meta_display_cancel_touch (MetaDisplay *display);
-
-gboolean meta_display_windows_are_interactable (MetaDisplay *display);
-
-void meta_display_show_tablet_mapping_notification (MetaDisplay *display,
- ClutterInputDevice *pad,
- const gchar *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);
-
-void meta_display_foreach_window (MetaDisplay *display,
- MetaListWindowsFlags flags,
- MetaDisplayWindowFunc func,
- gpointer data);
-
-void meta_display_restacked (MetaDisplay *display);
-
-
-void meta_display_update_tile_preview (MetaDisplay *display,
- gboolean delay);
-void meta_display_hide_tile_preview (MetaDisplay *display);
-
-gboolean meta_display_apply_startup_properties (MetaDisplay *display,
- MetaWindow *window);
-
-void meta_display_queue_workarea_recalc (MetaDisplay *display);
-void meta_display_queue_check_fullscreen (MetaDisplay *display);
-
-MetaWindow *meta_display_get_pointer_window (MetaDisplay *display,
- MetaWindow *not_this_one);
-
-MetaWindow *meta_display_get_window_from_id (MetaDisplay *display,
- uint64_t window_id);
-uint64_t meta_display_generate_window_id (MetaDisplay *display);
-
-void meta_display_init_x11 (MetaDisplay *display,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean meta_display_init_x11_finish (MetaDisplay *display,
- GAsyncResult *result,
- GError **error);
-
-void meta_display_shutdown_x11 (MetaDisplay *display);
-
-#endif
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;
-}
diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c
deleted file mode 100644
index 3e42936e7..000000000
--- a/src/core/edge-resistance.c
+++ /dev/null
@@ -1,1310 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Edge resistance for move/resize operations */
-
-/*
- * Copyright (C) 2005, 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/>.
- */
-
-#include "config.h"
-
-#include "core/edge-resistance.h"
-
-#include "core/boxes-private.h"
-#include "core/display-private.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/workspace-private.h"
-
-/* A simple macro for whether a given window's edges are potentially
- * relevant for resistance/snapping during a move/resize operation
- */
-#define WINDOW_EDGES_RELEVANT(window, display) \
- meta_window_should_be_showing (window) && \
- window != display->grab_window && \
- window->type != META_WINDOW_DESKTOP && \
- window->type != META_WINDOW_MENU && \
- window->type != META_WINDOW_SPLASHSCREEN
-
-struct ResistanceDataForAnEdge
-{
- gboolean timeout_setup;
- guint timeout_id;
- int timeout_edge_pos;
- gboolean timeout_over;
- GSourceFunc timeout_func;
- MetaWindow *window;
- int keyboard_buildup;
-};
-typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge;
-
-struct MetaEdgeResistanceData
-{
- GArray *left_edges;
- GArray *right_edges;
- GArray *top_edges;
- GArray *bottom_edges;
-
- ResistanceDataForAnEdge left_data;
- ResistanceDataForAnEdge right_data;
- ResistanceDataForAnEdge top_data;
- ResistanceDataForAnEdge bottom_data;
-};
-
-static void compute_resistance_and_snapping_edges (MetaDisplay *display);
-
-/* !WARNING!: this function can return invalid indices (namely, either -1 or
- * edges->len); this is by design, but you need to remember this.
- */
-static int
-find_index_of_edge_near_position (const GArray *edges,
- int position,
- gboolean want_interval_min,
- gboolean horizontal)
-{
- /* This is basically like a binary search, except that we're trying to
- * find a range instead of an exact value. So, if we have in our array
- * Value: 3 27 316 316 316 505 522 800 1213
- * Index: 0 1 2 3 4 5 6 7 8
- * and we call this function with position=500 & want_interval_min=TRUE
- * then we should get 5 (because 505 is the first value bigger than 500).
- * If we call this function with position=805 and want_interval_min=FALSE
- * then we should get 7 (because 800 is the last value smaller than 800).
- * A couple more, to make things clear:
- * position want_interval_min correct_answer
- * 316 TRUE 2
- * 316 FALSE 4
- * 2 FALSE -1
- * 2000 TRUE 9
- */
- int low, high, mid;
- int compare;
- MetaEdge *edge;
-
- /* Initialize mid, edge, & compare in the off change that the array only
- * has one element.
- */
- mid = 0;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
-
- /* Begin the search... */
- low = 0;
- high = edges->len - 1;
- while (low < high)
- {
- mid = low + (high - low)/2;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
-
- if (compare == position)
- break;
-
- if (compare > position)
- high = mid - 1;
- else
- low = mid + 1;
- }
-
- /* mid should now be _really_ close to the index we want, so we start
- * linearly searching. However, note that we don't know if mid is less
- * than or greater than what we need and it's possible that there are
- * several equal values equal to what we were searching for and we ended
- * up in the middle of them instead of at the end. So we may need to
- * move mid multiple locations over.
- */
- if (want_interval_min)
- {
- while (compare >= position && mid > 0)
- {
- mid--;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
- }
- while (compare < position && mid < (int)edges->len - 1)
- {
- mid++;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
- }
-
- /* Special case for no values in array big enough */
- if (compare < position)
- return edges->len;
-
- /* Return the found value */
- return mid;
- }
- else
- {
- while (compare <= position && mid < (int)edges->len - 1)
- {
- mid++;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
- }
- while (compare > position && mid > 0)
- {
- mid--;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
- }
-
- /* Special case for no values in array small enough */
- if (compare > position)
- return -1;
-
- /* Return the found value */
- return mid;
- }
-}
-
-static gboolean
-points_on_same_side (int ref, int pt1, int pt2)
-{
- return (pt1 - ref) * (pt2 - ref) > 0;
-}
-
-static int
-find_nearest_position (const GArray *edges,
- int position,
- int old_position,
- const MetaRectangle *new_rect,
- gboolean horizontal,
- gboolean only_forward)
-{
- /* This is basically just a binary search except that we're looking
- * for the value closest to position, rather than finding that
- * actual value. Also, we ignore any edges that aren't relevant
- * given the horizontal/vertical position of new_rect.
- */
- int low, high, mid;
- int compare;
- MetaEdge *edge;
- int best, best_dist, i;
- gboolean edges_align;
-
- /* Initialize mid, edge, & compare in the off change that the array only
- * has one element.
- */
- mid = 0;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
-
- /* Begin the search... */
- low = 0;
- high = edges->len - 1;
- while (low < high)
- {
- mid = low + (high - low)/2;
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
-
- if (compare == position)
- break;
-
- if (compare > position)
- high = mid - 1;
- else
- low = mid + 1;
- }
-
- /* mid should now be _really_ close to the index we want, so we
- * start searching nearby for something that overlaps and is closer
- * than the original position.
- */
- best = old_position;
- best_dist = INT_MAX;
-
- /* Start the search at mid */
- edge = g_array_index (edges, MetaEdge*, mid);
- compare = horizontal ? edge->rect.x : edge->rect.y;
- edges_align = meta_rectangle_edge_aligns (new_rect, edge);
- if (edges_align &&
- (!only_forward || !points_on_same_side (position, compare, old_position)))
- {
- int dist = ABS (compare - position);
- if (dist < best_dist)
- {
- best = compare;
- best_dist = dist;
- }
- }
-
- /* Now start searching higher than mid */
- for (i = mid + 1; i < (int)edges->len; i++)
- {
- edge = g_array_index (edges, MetaEdge*, i);
- compare = horizontal ? edge->rect.x : edge->rect.y;
-
- edges_align = horizontal ?
- meta_rectangle_vert_overlap (&edge->rect, new_rect) :
- meta_rectangle_horiz_overlap (&edge->rect, new_rect);
-
- if (edges_align &&
- (!only_forward ||
- !points_on_same_side (position, compare, old_position)))
- {
- int dist = ABS (compare - position);
- if (dist < best_dist)
- {
- best = compare;
- best_dist = dist;
- }
- break;
- }
- }
-
- /* Now start searching lower than mid */
- for (i = mid-1; i >= 0; i--)
- {
- edge = g_array_index (edges, MetaEdge*, i);
- compare = horizontal ? edge->rect.x : edge->rect.y;
-
- edges_align = horizontal ?
- meta_rectangle_vert_overlap (&edge->rect, new_rect) :
- meta_rectangle_horiz_overlap (&edge->rect, new_rect);
-
- if (edges_align &&
- (!only_forward ||
- !points_on_same_side (position, compare, old_position)))
- {
- int dist = ABS (compare - position);
- if (dist < best_dist)
- {
- best = compare;
- best_dist = dist;
- }
- break;
- }
- }
-
- /* Return the best one found */
- return best;
-}
-
-static gboolean
-movement_towards_edge (MetaSide side, int increment)
-{
- switch (side)
- {
- case META_SIDE_LEFT:
- case META_SIDE_TOP:
- return increment < 0;
- case META_SIDE_RIGHT:
- case META_SIDE_BOTTOM:
- return increment > 0;
- default:
- g_assert_not_reached ();
- return FALSE;
- }
-}
-
-static gboolean
-edge_resistance_timeout (gpointer data)
-{
- ResistanceDataForAnEdge *resistance_data = data;
-
- resistance_data->timeout_over = TRUE;
- resistance_data->timeout_id = 0;
- (*resistance_data->timeout_func)(resistance_data->window);
-
- return FALSE;
-}
-
-static int
-apply_edge_resistance (MetaWindow *window,
- int old_pos,
- int new_pos,
- const MetaRectangle *old_rect,
- const MetaRectangle *new_rect,
- GArray *edges,
- ResistanceDataForAnEdge *resistance_data,
- GSourceFunc timeout_func,
- gboolean xdir,
- gboolean include_windows,
- gboolean keyboard_op)
-{
- int i, begin, end;
- int last_edge;
- gboolean increasing = new_pos > old_pos;
- int increment = increasing ? 1 : -1;
-
- const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16;
- const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0;
- const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32;
- const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 0;
- const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32;
- const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0;
- const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0;
- const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0;
- const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0;
-
- /* Quit if no movement was specified */
- if (old_pos == new_pos)
- return new_pos;
-
- /* Remove the old timeout if it's no longer relevant */
- if (resistance_data->timeout_setup &&
- ((resistance_data->timeout_edge_pos > old_pos &&
- resistance_data->timeout_edge_pos > new_pos) ||
- (resistance_data->timeout_edge_pos < old_pos &&
- resistance_data->timeout_edge_pos < new_pos)))
- {
- resistance_data->timeout_setup = FALSE;
- g_clear_handle_id (&resistance_data->timeout_id, g_source_remove);
- }
-
- /* Get the range of indices in the edge array that we move past/to. */
- begin = find_index_of_edge_near_position (edges, old_pos, increasing, xdir);
- end = find_index_of_edge_near_position (edges, new_pos, !increasing, xdir);
-
- /* begin and end can be outside the array index, if the window is partially
- * off the screen
- */
- last_edge = edges->len - 1;
- begin = CLAMP (begin, 0, last_edge);
- end = CLAMP (end, 0, last_edge);
-
- /* Loop over all these edges we're moving past/to. */
- i = begin;
- while ((increasing && i <= end) ||
- (!increasing && i >= end))
- {
- gboolean edges_align;
- MetaEdge *edge = g_array_index (edges, MetaEdge*, i);
- int compare = xdir ? edge->rect.x : edge->rect.y;
-
- /* Find out if this edge is relevant */
- edges_align = meta_rectangle_edge_aligns (new_rect, edge) ||
- meta_rectangle_edge_aligns (old_rect, edge);
-
- /* Nothing to do unless the edges align */
- if (!edges_align)
- {
- /* Go to the next edge in the range */
- i += increment;
- continue;
- }
-
- /* Rest is easier to read if we split on keyboard vs. mouse op */
- if (keyboard_op)
- {
- if ((old_pos < compare && compare < new_pos) ||
- (old_pos > compare && compare > new_pos))
- return compare;
- }
- else /* mouse op */
- {
- int threshold;
-
- /* TIMEOUT RESISTANCE: If the edge is relevant and we're moving
- * towards it, then we may want to have some kind of time delay
- * before the user can move past this edge.
- */
- if (movement_towards_edge (edge->side_type, increment))
- {
- /* First, determine the length of time for the resistance */
- int timeout_length_ms = 0;
- switch (edge->edge_type)
- {
- case META_EDGE_WINDOW:
- if (include_windows)
- timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW;
- break;
- case META_EDGE_MONITOR:
- timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR;
- break;
- case META_EDGE_SCREEN:
- timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN;
- break;
- }
-
- if (!resistance_data->timeout_setup &&
- timeout_length_ms != 0)
- {
- resistance_data->timeout_id =
- g_timeout_add (timeout_length_ms,
- edge_resistance_timeout,
- resistance_data);
- g_source_set_name_by_id (resistance_data->timeout_id,
- "[mutter] edge_resistance_timeout");
- resistance_data->timeout_setup = TRUE;
- resistance_data->timeout_edge_pos = compare;
- resistance_data->timeout_over = FALSE;
- resistance_data->timeout_func = timeout_func;
- resistance_data->window = window;
- }
- if (!resistance_data->timeout_over &&
- timeout_length_ms != 0)
- return compare;
- }
-
- /* PIXEL DISTANCE MOUSE RESISTANCE: If the edge matters and the
- * user hasn't moved at least threshold pixels past this edge,
- * stop movement at this edge. (Note that this is different from
- * keyboard resistance precisely because keyboard move ops are
- * relative to previous positions, whereas mouse move ops are
- * relative to differences in mouse position and mouse position
- * is an absolute quantity rather than a relative quantity)
- */
-
- /* First, determine the threshold */
- threshold = 0;
- switch (edge->edge_type)
- {
- case META_EDGE_WINDOW:
- if (!include_windows)
- break;
- if (movement_towards_edge (edge->side_type, increment))
- threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW;
- else
- threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW;
- break;
- case META_EDGE_MONITOR:
- if (movement_towards_edge (edge->side_type, increment))
- threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR;
- else
- threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR;
- break;
- case META_EDGE_SCREEN:
- if (movement_towards_edge (edge->side_type, increment))
- threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN;
- else
- threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN;
- break;
- }
-
- if (ABS (compare - new_pos) < threshold)
- return compare;
- }
-
- /* Go to the next edge in the range */
- i += increment;
- }
-
- return new_pos;
-}
-
-static int
-apply_edge_snapping (int old_pos,
- int new_pos,
- const MetaRectangle *new_rect,
- GArray *edges,
- gboolean xdir,
- gboolean keyboard_op)
-{
- int snap_to;
-
- if (old_pos == new_pos)
- return new_pos;
-
- snap_to = find_nearest_position (edges,
- new_pos,
- old_pos,
- new_rect,
- xdir,
- keyboard_op);
-
- /* If mouse snap-moving, the user could easily accidentally move just a
- * couple pixels in a direction they didn't mean to move; so ignore snap
- * movement in those cases unless it's only a small number of pixels
- * anyway.
- */
- if (!keyboard_op &&
- ABS (snap_to - old_pos) >= 8 &&
- ABS (new_pos - old_pos) < 8)
- return old_pos;
- else
- /* Otherwise, return the snapping position found */
- return snap_to;
-}
-
-/* This function takes the position (including any frame) of the window and
- * a proposed new position (ignoring edge resistance/snapping), and then
- * applies edge resistance to EACH edge (separately) updating new_outer.
- * It returns true if new_outer is modified, false otherwise.
- *
- * display->grab_edge_resistance_data MUST already be setup or calling this
- * function will cause a crash.
- */
-static gboolean
-apply_edge_resistance_to_each_side (MetaDisplay *display,
- MetaWindow *window,
- const MetaRectangle *old_outer,
- MetaRectangle *new_outer,
- GSourceFunc timeout_func,
- MetaEdgeResistanceFlags flags,
- gboolean is_resize)
-{
- MetaEdgeResistanceData *edge_data;
- MetaRectangle modified_rect;
- gboolean modified;
- int new_left, new_right, new_top, new_bottom;
- gboolean auto_snap, keyboard_op;
-
- auto_snap = flags & META_EDGE_RESISTANCE_SNAP;
- keyboard_op = flags & META_EDGE_RESISTANCE_KEYBOARD_OP;
-
- if (display->grab_edge_resistance_data == NULL)
- compute_resistance_and_snapping_edges (display);
-
- edge_data = display->grab_edge_resistance_data;
-
- if (auto_snap && !META_WINDOW_TILED_SIDE_BY_SIDE (window))
- {
- /* Do the auto snapping instead of normal edge resistance; in all
- * cases, we allow snapping to opposite kinds of edges (e.g. left
- * sides of windows to both left and right edges.
- */
-
- new_left = apply_edge_snapping (BOX_LEFT (*old_outer),
- BOX_LEFT (*new_outer),
- new_outer,
- edge_data->left_edges,
- TRUE,
- keyboard_op);
-
- new_right = apply_edge_snapping (BOX_RIGHT (*old_outer),
- BOX_RIGHT (*new_outer),
- new_outer,
- edge_data->right_edges,
- TRUE,
- keyboard_op);
-
- new_top = apply_edge_snapping (BOX_TOP (*old_outer),
- BOX_TOP (*new_outer),
- new_outer,
- edge_data->top_edges,
- FALSE,
- keyboard_op);
-
- new_bottom = apply_edge_snapping (BOX_BOTTOM (*old_outer),
- BOX_BOTTOM (*new_outer),
- new_outer,
- edge_data->bottom_edges,
- FALSE,
- keyboard_op);
- }
- else if (auto_snap && META_WINDOW_TILED_SIDE_BY_SIDE (window))
- {
- MetaRectangle workarea;
- guint i;
-
- const gfloat tile_edges[] =
- {
- 1./4.,
- 1./3.,
- 1./2.,
- 2./3.,
- 3./4.,
- };
-
- meta_window_get_work_area_current_monitor (window, &workarea);
-
- new_left = new_outer->x;
- new_top = new_outer->y;
- new_right = new_outer->x + new_outer->width;
- new_bottom = new_outer->y + new_outer->height;
-
- /* When snapping tiled windows, we don't really care about the
- * x and y position, only about the width and height. Also, it
- * is special-cased (instead of relying on edge_data) because
- * we don't really care for other windows when calculating the
- * snapping points of tiled windows - we only care about the
- * work area and the target position.
- */
- for (i = 0; i < G_N_ELEMENTS (tile_edges); i++)
- {
- guint horizontal_point = workarea.x + floor (workarea.width * tile_edges[i]);
-
- if (ABS (horizontal_point - new_left) < 16)
- {
- new_left = horizontal_point;
- new_right = workarea.x + workarea.width;
- }
- else if (ABS (horizontal_point - new_right) < 16)
- {
- new_left = workarea.x;
- new_right = horizontal_point;
- }
- }
- }
- else
- {
- gboolean include_windows = flags & META_EDGE_RESISTANCE_WINDOWS;
-
- /* Disable edge resistance for resizes when windows have size
- * increment hints; see #346782. For all other cases, apply
- * them.
- */
- if (!is_resize || window->size_hints.width_inc == 1)
- {
- /* Now, apply the normal horizontal edge resistance */
- new_left = apply_edge_resistance (window,
- BOX_LEFT (*old_outer),
- BOX_LEFT (*new_outer),
- old_outer,
- new_outer,
- edge_data->left_edges,
- &edge_data->left_data,
- timeout_func,
- TRUE,
- include_windows,
- keyboard_op);
- new_right = apply_edge_resistance (window,
- BOX_RIGHT (*old_outer),
- BOX_RIGHT (*new_outer),
- old_outer,
- new_outer,
- edge_data->right_edges,
- &edge_data->right_data,
- timeout_func,
- TRUE,
- include_windows,
- keyboard_op);
- }
- else
- {
- new_left = new_outer->x;
- new_right = new_outer->x + new_outer->width;
- }
- /* Same for vertical resizes... */
- if (!is_resize || window->size_hints.height_inc == 1)
- {
- new_top = apply_edge_resistance (window,
- BOX_TOP (*old_outer),
- BOX_TOP (*new_outer),
- old_outer,
- new_outer,
- edge_data->top_edges,
- &edge_data->top_data,
- timeout_func,
- FALSE,
- include_windows,
- keyboard_op);
- new_bottom = apply_edge_resistance (window,
- BOX_BOTTOM (*old_outer),
- BOX_BOTTOM (*new_outer),
- old_outer,
- new_outer,
- edge_data->bottom_edges,
- &edge_data->bottom_data,
- timeout_func,
- FALSE,
- include_windows,
- keyboard_op);
- }
- else
- {
- new_top = new_outer->y;
- new_bottom = new_outer->y + new_outer->height;
- }
- }
-
- /* Determine whether anything changed, and save the changes */
- modified_rect = meta_rect (new_left,
- new_top,
- new_right - new_left,
- new_bottom - new_top);
- modified = !meta_rectangle_equal (new_outer, &modified_rect);
- *new_outer = modified_rect;
- return modified;
-}
-
-void
-meta_display_cleanup_edges (MetaDisplay *display)
-{
- guint i,j;
- MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
- GHashTable *edges_to_be_freed;
-
- if (edge_data == NULL) /* Not currently cached */
- return;
-
- /* We first need to clean out any window edges */
- edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- g_free, NULL);
- for (i = 0; i < 4; i++)
- {
- GArray *tmp = NULL;
- MetaSide side;
- switch (i)
- {
- case 0:
- tmp = edge_data->left_edges;
- side = META_SIDE_LEFT;
- break;
- case 1:
- tmp = edge_data->right_edges;
- side = META_SIDE_RIGHT;
- break;
- case 2:
- tmp = edge_data->top_edges;
- side = META_SIDE_TOP;
- break;
- case 3:
- tmp = edge_data->bottom_edges;
- side = META_SIDE_BOTTOM;
- break;
- default:
- g_assert_not_reached ();
- }
-
- for (j = 0; j < tmp->len; j++)
- {
- MetaEdge *edge = g_array_index (tmp, MetaEdge*, j);
- if (edge->edge_type == META_EDGE_WINDOW &&
- edge->side_type == side)
- {
- /* The same edge will appear in two arrays, and we can't free
- * it yet we still need to compare edge->side_type for the other
- * array that it is in. So store it in a hash table for later
- * freeing. Could also do this in a simple linked list.
- */
- g_hash_table_insert (edges_to_be_freed, edge, edge);
- }
- }
- }
-
- /* Now free all the window edges (the key destroy function is g_free) */
- g_hash_table_destroy (edges_to_be_freed);
-
- /* Now free the arrays and data */
- g_array_free (edge_data->left_edges, TRUE);
- g_array_free (edge_data->right_edges, TRUE);
- g_array_free (edge_data->top_edges, TRUE);
- g_array_free (edge_data->bottom_edges, TRUE);
- edge_data->left_edges = NULL;
- edge_data->right_edges = NULL;
- edge_data->top_edges = NULL;
- edge_data->bottom_edges = NULL;
-
- /* Cleanup the timeouts */
- if (edge_data->left_data.timeout_setup)
- g_clear_handle_id (&edge_data->left_data.timeout_id, g_source_remove);
- if (edge_data->right_data.timeout_setup)
- g_clear_handle_id (&edge_data->right_data.timeout_id, g_source_remove);
- if (edge_data->top_data.timeout_setup)
- g_clear_handle_id (&edge_data->top_data.timeout_id, g_source_remove);
- if (edge_data->bottom_data.timeout_setup)
- g_clear_handle_id (&edge_data->bottom_data.timeout_id, g_source_remove);
-
- g_free (display->grab_edge_resistance_data);
- display->grab_edge_resistance_data = NULL;
-}
-
-static int
-stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
- gconstpointer b)
-{
- const MetaEdge * const *a_edge = a;
- const MetaEdge * const *b_edge = b;
- return meta_rectangle_edge_cmp_ignore_type (*a_edge, *b_edge);
-}
-
-static void
-cache_edges (MetaDisplay *display,
- GList *window_edges,
- GList *monitor_edges,
- GList *screen_edges)
-{
- MetaEdgeResistanceData *edge_data;
- GList *tmp;
- int num_left, num_right, num_top, num_bottom;
- int i;
-
- /*
- * 0th: Print debugging information to the log about the edges
- */
-#ifdef WITH_VERBOSE_MODE
- if (meta_is_verbose())
- {
- int max_edges = MAX (MAX( g_list_length (window_edges),
- g_list_length (monitor_edges)),
- g_list_length (screen_edges));
- char big_buffer[(EDGE_LENGTH+2)*max_edges];
-
- meta_rectangle_edge_list_to_string (window_edges, ", ", big_buffer);
- meta_topic (META_DEBUG_EDGE_RESISTANCE,
- "Window edges for resistance : %s", big_buffer);
-
- meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer);
- meta_topic (META_DEBUG_EDGE_RESISTANCE,
- "Monitor edges for resistance: %s", big_buffer);
-
- meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer);
- meta_topic (META_DEBUG_EDGE_RESISTANCE,
- "Screen edges for resistance : %s", big_buffer);
- }
-#endif
-
- /*
- * 1st: Get the total number of each kind of edge
- */
- num_left = num_right = num_top = num_bottom = 0;
- for (i = 0; i < 3; i++)
- {
- tmp = NULL;
- switch (i)
- {
- case 0:
- tmp = window_edges;
- break;
- case 1:
- tmp = monitor_edges;
- break;
- case 2:
- tmp = screen_edges;
- break;
- default:
- g_assert_not_reached ();
- }
-
- while (tmp)
- {
- MetaEdge *edge = tmp->data;
- switch (edge->side_type)
- {
- case META_SIDE_LEFT:
- num_left++;
- break;
- case META_SIDE_RIGHT:
- num_right++;
- break;
- case META_SIDE_TOP:
- num_top++;
- break;
- case META_SIDE_BOTTOM:
- num_bottom++;
- break;
- default:
- g_assert_not_reached ();
- }
- tmp = tmp->next;
- }
- }
-
- /*
- * 2nd: Allocate the edges
- */
- g_assert (display->grab_edge_resistance_data == NULL);
- display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1);
- edge_data = display->grab_edge_resistance_data;
- edge_data->left_edges = g_array_sized_new (FALSE,
- FALSE,
- sizeof(MetaEdge*),
- num_left + num_right);
- edge_data->right_edges = g_array_sized_new (FALSE,
- FALSE,
- sizeof(MetaEdge*),
- num_left + num_right);
- edge_data->top_edges = g_array_sized_new (FALSE,
- FALSE,
- sizeof(MetaEdge*),
- num_top + num_bottom);
- edge_data->bottom_edges = g_array_sized_new (FALSE,
- FALSE,
- sizeof(MetaEdge*),
- num_top + num_bottom);
-
- /*
- * 3rd: Add the edges to the arrays
- */
- for (i = 0; i < 3; i++)
- {
- tmp = NULL;
- switch (i)
- {
- case 0:
- tmp = window_edges;
- break;
- case 1:
- tmp = monitor_edges;
- break;
- case 2:
- tmp = screen_edges;
- break;
- default:
- g_assert_not_reached ();
- }
-
- while (tmp)
- {
- MetaEdge *edge = tmp->data;
- switch (edge->side_type)
- {
- case META_SIDE_LEFT:
- case META_SIDE_RIGHT:
- g_array_append_val (edge_data->left_edges, edge);
- g_array_append_val (edge_data->right_edges, edge);
- break;
- case META_SIDE_TOP:
- case META_SIDE_BOTTOM:
- g_array_append_val (edge_data->top_edges, edge);
- g_array_append_val (edge_data->bottom_edges, edge);
- break;
- default:
- g_assert_not_reached ();
- }
- tmp = tmp->next;
- }
- }
-
- /*
- * 4th: Sort the arrays (FIXME: This is kinda dumb since the arrays were
- * individually sorted earlier and we could have done this faster and
- * avoided this sort by sticking them into the array with some simple
- * merging of the lists).
- */
- g_array_sort (display->grab_edge_resistance_data->left_edges,
- stupid_sort_requiring_extra_pointer_dereference);
- g_array_sort (display->grab_edge_resistance_data->right_edges,
- stupid_sort_requiring_extra_pointer_dereference);
- g_array_sort (display->grab_edge_resistance_data->top_edges,
- stupid_sort_requiring_extra_pointer_dereference);
- g_array_sort (display->grab_edge_resistance_data->bottom_edges,
- stupid_sort_requiring_extra_pointer_dereference);
-}
-
-static void
-initialize_grab_edge_resistance_data (MetaDisplay *display)
-{
- MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
-
- edge_data->left_data.timeout_setup = FALSE;
- edge_data->right_data.timeout_setup = FALSE;
- edge_data->top_data.timeout_setup = FALSE;
- edge_data->bottom_data.timeout_setup = FALSE;
-
- edge_data->left_data.keyboard_buildup = 0;
- edge_data->right_data.keyboard_buildup = 0;
- edge_data->top_data.keyboard_buildup = 0;
- edge_data->bottom_data.keyboard_buildup = 0;
-}
-
-static void
-compute_resistance_and_snapping_edges (MetaDisplay *display)
-{
- GList *stacked_windows;
- GList *cur_window_iter;
- GList *edges;
- /* Lists of window positions (rects) and their relative stacking positions */
- int stack_position;
- GSList *obscuring_windows, *window_stacking;
- /* The portions of the above lists that still remain at the stacking position
- * in the layer that we are working on
- */
- GSList *rem_windows, *rem_win_stacking;
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
-
- g_assert (display->grab_window != NULL);
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Computing edges to resist-movement or snap-to for %s.",
- display->grab_window->desc);
-
- /*
- * 1st: Get the list of relevant windows, from bottom to top
- */
- stacked_windows =
- meta_stack_list_windows (display->stack,
- workspace_manager->active_workspace);
-
- /*
- * 2nd: we need to separate that stacked list into a list of windows that
- * can obscure other edges. To make sure we only have windows obscuring
- * those below it instead of going both ways, we also need to keep a
- * counter list. Messy, I know.
- */
- obscuring_windows = window_stacking = NULL;
- cur_window_iter = stacked_windows;
- stack_position = 0;
- while (cur_window_iter != NULL)
- {
- MetaWindow *cur_window = cur_window_iter->data;
- if (WINDOW_EDGES_RELEVANT (cur_window, display))
- {
- MetaRectangle *new_rect;
- new_rect = g_new (MetaRectangle, 1);
- meta_window_get_frame_rect (cur_window, new_rect);
- obscuring_windows = g_slist_prepend (obscuring_windows, new_rect);
- window_stacking =
- g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position));
- }
-
- stack_position++;
- cur_window_iter = cur_window_iter->next;
- }
- /* Put 'em in bottom to top order */
- rem_windows = obscuring_windows = g_slist_reverse (obscuring_windows);
- rem_win_stacking = window_stacking = g_slist_reverse (window_stacking);
-
- /*
- * 3rd: loop over the windows again, this time getting the edges from
- * them and removing intersections with the relevant obscuring_windows &
- * obscuring_docks.
- */
- edges = NULL;
- stack_position = 0;
- cur_window_iter = stacked_windows;
- while (cur_window_iter != NULL)
- {
- MetaRectangle cur_rect;
- MetaWindow *cur_window = cur_window_iter->data;
- meta_window_get_frame_rect (cur_window, &cur_rect);
-
- /* Check if we want to use this window's edges for edge
- * resistance (note that dock edges are considered screen edges
- * which are handled separately
- */
- if (WINDOW_EDGES_RELEVANT (cur_window, display) &&
- cur_window->type != META_WINDOW_DOCK)
- {
- GList *new_edges;
- MetaEdge *new_edge;
- MetaRectangle display_rect = { 0 };
- MetaRectangle reduced;
-
- meta_display_get_size (display,
- &display_rect.width, &display_rect.height);
-
- /* We don't care about snapping to any portion of the window that
- * is offscreen (we also don't care about parts of edges covered
- * by other windows or DOCKS, but that's handled below).
- */
- meta_rectangle_intersect (&cur_rect,
- &display_rect,
- &reduced);
-
- new_edges = NULL;
-
- /* Left side of this window is resistance for the right edge of
- * the window being moved.
- */
- new_edge = g_new (MetaEdge, 1);
- new_edge->rect = reduced;
- new_edge->rect.width = 0;
- new_edge->side_type = META_SIDE_RIGHT;
- new_edge->edge_type = META_EDGE_WINDOW;
- new_edges = g_list_prepend (new_edges, new_edge);
-
- /* Right side of this window is resistance for the left edge of
- * the window being moved.
- */
- new_edge = g_new (MetaEdge, 1);
- new_edge->rect = reduced;
- new_edge->rect.x += new_edge->rect.width;
- new_edge->rect.width = 0;
- new_edge->side_type = META_SIDE_LEFT;
- new_edge->edge_type = META_EDGE_WINDOW;
- new_edges = g_list_prepend (new_edges, new_edge);
-
- /* Top side of this window is resistance for the bottom edge of
- * the window being moved.
- */
- new_edge = g_new (MetaEdge, 1);
- new_edge->rect = reduced;
- new_edge->rect.height = 0;
- new_edge->side_type = META_SIDE_BOTTOM;
- new_edge->edge_type = META_EDGE_WINDOW;
- new_edges = g_list_prepend (new_edges, new_edge);
-
- /* Top side of this window is resistance for the bottom edge of
- * the window being moved.
- */
- new_edge = g_new (MetaEdge, 1);
- new_edge->rect = reduced;
- new_edge->rect.y += new_edge->rect.height;
- new_edge->rect.height = 0;
- new_edge->side_type = META_SIDE_TOP;
- new_edge->edge_type = META_EDGE_WINDOW;
- new_edges = g_list_prepend (new_edges, new_edge);
-
- /* Update the remaining windows to only those at a higher
- * stacking position than this one.
- */
- while (rem_win_stacking &&
- stack_position >= GPOINTER_TO_INT (rem_win_stacking->data))
- {
- rem_windows = rem_windows->next;
- rem_win_stacking = rem_win_stacking->next;
- }
-
- /* Remove edge portions overlapped by rem_windows and rem_docks */
- new_edges =
- meta_rectangle_remove_intersections_with_boxes_from_edges (
- new_edges,
- rem_windows);
-
- /* Save the new edges */
- edges = g_list_concat (new_edges, edges);
- }
-
- stack_position++;
- cur_window_iter = cur_window_iter->next;
- }
-
- /*
- * 4th: Free the extra memory not needed and sort the list
- */
- g_list_free (stacked_windows);
- /* Free the memory used by the obscuring windows/docks lists */
- g_slist_free (window_stacking);
- g_slist_free_full (obscuring_windows, g_free);
-
- /* Sort the list. FIXME: Should I bother with this sorting? I just
- * sort again later in cache_edges() anyway...
- */
- edges = g_list_sort (edges, meta_rectangle_edge_cmp);
-
- /*
- * 5th: Cache the combination of these edges with the onscreen and
- * monitor edges in an array for quick access. Free the edges since
- * they've been cached elsewhere.
- */
- cache_edges (display,
- edges,
- workspace_manager->active_workspace->monitor_edges,
- workspace_manager->active_workspace->screen_edges);
- g_list_free (edges);
-
- /*
- * 6th: Initialize the resistance timeouts and buildups
- */
- initialize_grab_edge_resistance_data (display);
-}
-
-void
-meta_window_edge_resistance_for_move (MetaWindow *window,
- int *new_x,
- int *new_y,
- GSourceFunc timeout_func,
- MetaEdgeResistanceFlags flags)
-{
- MetaRectangle old_outer, proposed_outer, new_outer;
- MetaEdgeResistanceFlags saved_flags;
- gboolean is_resize, is_keyboard_op, snap;
-
- meta_window_get_frame_rect (window, &old_outer);
-
- proposed_outer = old_outer;
- proposed_outer.x = *new_x;
- proposed_outer.y = *new_y;
- new_outer = proposed_outer;
-
- snap = flags & META_EDGE_RESISTANCE_SNAP;
- is_keyboard_op = flags & META_EDGE_RESISTANCE_KEYBOARD_OP;
- saved_flags = flags & ~META_EDGE_RESISTANCE_KEYBOARD_OP;
-
- window->display->grab_last_edge_resistance_flags = saved_flags;
- is_resize = FALSE;
- if (apply_edge_resistance_to_each_side (window->display,
- window,
- &old_outer,
- &new_outer,
- timeout_func,
- flags,
- is_resize))
- {
- /* apply_edge_resistance_to_each_side independently applies
- * resistance to both the right and left edges of new_outer as both
- * could meet areas of resistance. But we don't want a resize, so we
- * just have both edges move according to the stricter of the
- * resistances. Same thing goes for top & bottom edges.
- */
- MetaRectangle *reference;
- int left_change, right_change, smaller_x_change;
- int top_change, bottom_change, smaller_y_change;
-
- if (snap && !is_keyboard_op)
- reference = &proposed_outer;
- else
- reference = &old_outer;
-
- left_change = BOX_LEFT (new_outer) - BOX_LEFT (*reference);
- right_change = BOX_RIGHT (new_outer) - BOX_RIGHT (*reference);
- if ( snap && is_keyboard_op && left_change == 0)
- smaller_x_change = right_change;
- else if (snap && is_keyboard_op && right_change == 0)
- smaller_x_change = left_change;
- else if (ABS (left_change) < ABS (right_change))
- smaller_x_change = left_change;
- else
- smaller_x_change = right_change;
-
- top_change = BOX_TOP (new_outer) - BOX_TOP (*reference);
- bottom_change = BOX_BOTTOM (new_outer) - BOX_BOTTOM (*reference);
- if ( snap && is_keyboard_op && top_change == 0)
- smaller_y_change = bottom_change;
- else if (snap && is_keyboard_op && bottom_change == 0)
- smaller_y_change = top_change;
- else if (ABS (top_change) < ABS (bottom_change))
- smaller_y_change = top_change;
- else
- smaller_y_change = bottom_change;
-
- *new_x = old_outer.x + smaller_x_change +
- (BOX_LEFT (*reference) - BOX_LEFT (old_outer));
- *new_y = old_outer.y + smaller_y_change +
- (BOX_TOP (*reference) - BOX_TOP (old_outer));
-
- meta_topic (META_DEBUG_EDGE_RESISTANCE,
- "outer x & y move-to coordinate changed from %d,%d to %d,%d",
- proposed_outer.x, proposed_outer.y,
- *new_x, *new_y);
- }
-}
-
-void
-meta_window_edge_resistance_for_resize (MetaWindow *window,
- int *new_width,
- int *new_height,
- MetaGravity gravity,
- GSourceFunc timeout_func,
- MetaEdgeResistanceFlags flags)
-{
- MetaRectangle old_outer, new_outer;
- MetaEdgeResistanceFlags saved_flags;
- int proposed_outer_width, proposed_outer_height;
-
- meta_window_get_frame_rect (window, &old_outer);
- proposed_outer_width = *new_width;
- proposed_outer_height = *new_height;
- meta_rectangle_resize_with_gravity (&old_outer,
- &new_outer,
- gravity,
- proposed_outer_width,
- proposed_outer_height);
-
- saved_flags = flags & ~META_EDGE_RESISTANCE_KEYBOARD_OP;
- window->display->grab_last_edge_resistance_flags = saved_flags;
-
- if (apply_edge_resistance_to_each_side (window->display,
- window,
- &old_outer,
- &new_outer,
- timeout_func,
- flags,
- TRUE))
- {
- *new_width = new_outer.width;
- *new_height = new_outer.height;
-
- meta_topic (META_DEBUG_EDGE_RESISTANCE,
- "outer width & height got changed from %d,%d to %d,%d",
- proposed_outer_width, proposed_outer_height,
- new_outer.width, new_outer.height);
- }
-}
diff --git a/src/core/edge-resistance.h b/src/core/edge-resistance.h
deleted file mode 100644
index 4eb6abdca..000000000
--- a/src/core/edge-resistance.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Edge resistance for move/resize operations */
-
-/*
- * Copyright (C) 2005 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/>.
- */
-
-#ifndef META_EDGE_RESISTANCE_H
-#define META_EDGE_RESISTANCE_H
-
-#include "core/window-private.h"
-
-void meta_window_edge_resistance_for_move (MetaWindow *window,
- int *new_x,
- int *new_y,
- GSourceFunc timeout_func,
- MetaEdgeResistanceFlags flags);
-void meta_window_edge_resistance_for_resize (MetaWindow *window,
- int *new_width,
- int *new_height,
- MetaGravity gravity,
- GSourceFunc timeout_func,
- MetaEdgeResistanceFlags flags);
-
-#endif /* META_EDGE_RESISTANCE_H */
-
diff --git a/src/core/events.c b/src/core/events.c
deleted file mode 100644
index 8afc720ef..000000000
--- a/src/core/events.c
+++ /dev/null
@@ -1,509 +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/>.
- */
-
-#include "config.h"
-
-#include "core/events.h"
-
-#include "backends/meta-cursor-tracker-private.h"
-#include "backends/meta-idle-manager.h"
-#include "backends/x11/meta-backend-x11.h"
-#include "backends/x11/meta-input-device-x11.h"
-#include "compositor/meta-window-actor-private.h"
-#include "core/display-private.h"
-#include "core/window-private.h"
-#include "meta/meta-backend.h"
-
-#ifdef HAVE_NATIVE_BACKEND
-#include "backends/native/meta-backend-native.h"
-#endif
-
-#ifdef HAVE_WAYLAND
-#include "wayland/meta-wayland-private.h"
-#endif
-
-#define IS_GESTURE_EVENT(e) ((e)->type == CLUTTER_TOUCHPAD_SWIPE || \
- (e)->type == CLUTTER_TOUCHPAD_PINCH || \
- (e)->type == CLUTTER_TOUCH_BEGIN || \
- (e)->type == CLUTTER_TOUCH_UPDATE || \
- (e)->type == CLUTTER_TOUCH_END || \
- (e)->type == CLUTTER_TOUCH_CANCEL)
-
-#define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \
- (e)->type == CLUTTER_KEY_RELEASE)
-
-typedef enum
-{
- EVENTS_UNFREEZE_SYNC,
- EVENTS_UNFREEZE_REPLAY,
-} EventsUnfreezeMethod;
-
-static gboolean
-stage_has_key_focus (void)
-{
- MetaBackend *backend = meta_get_backend ();
- ClutterActor *stage = meta_backend_get_stage (backend);
-
- return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == stage;
-}
-
-static MetaWindow *
-get_window_for_event (MetaDisplay *display,
- const ClutterEvent *event)
-{
- switch (display->event_route)
- {
- case META_EVENT_ROUTE_NORMAL:
- {
- ClutterActor *source;
- MetaWindowActor *window_actor;
-
- /* Always use the key focused window for key events. */
- if (IS_KEY_EVENT (event))
- return stage_has_key_focus () ? display->focus_window : NULL;
-
- source = clutter_event_get_source (event);
- window_actor = meta_window_actor_from_actor (source);
- if (window_actor)
- return meta_window_actor_get_meta_window (window_actor);
- else
- return NULL;
- }
- case META_EVENT_ROUTE_WINDOW_OP:
- case META_EVENT_ROUTE_COMPOSITOR_GRAB:
- case META_EVENT_ROUTE_WAYLAND_POPUP:
- case META_EVENT_ROUTE_FRAME_BUTTON:
- return display->grab_window;
- default:
- g_assert_not_reached ();
- return NULL;
- }
-}
-
-static void
-handle_idletime_for_event (const ClutterEvent *event)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaIdleManager *idle_manager;
-
- if (clutter_event_get_device (event) == NULL)
- return;
-
- if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
- event->type == CLUTTER_ENTER ||
- event->type == CLUTTER_LEAVE)
- return;
-
- idle_manager = meta_backend_get_idle_manager (backend);
- meta_idle_manager_reset_idle_time (idle_manager);
-}
-
-static gboolean
-sequence_is_pointer_emulated (MetaDisplay *display,
- const ClutterEvent *event)
-{
- ClutterEventSequence *sequence;
-
- sequence = clutter_event_get_event_sequence (event);
-
- if (!sequence)
- return FALSE;
-
- if (clutter_event_is_pointer_emulated (event))
- return TRUE;
-
-#ifdef HAVE_NATIVE_BACKEND
- MetaBackend *backend = meta_get_backend ();
-
- /* When using Clutter's native input backend there is no concept of
- * pointer emulating sequence, we still must make up our own to be
- * able to implement single-touch (hence pointer alike) behavior.
- *
- * This is implemented similarly to X11, where only the first touch
- * on screen gets the "pointer emulated" flag, and it won't get assigned
- * to another sequence until the next first touch on an idle touchscreen.
- */
- if (META_IS_BACKEND_NATIVE (backend))
- {
- MetaGestureTracker *tracker;
-
- tracker = meta_display_get_gesture_tracker (display);
-
- if (event->type == CLUTTER_TOUCH_BEGIN &&
- meta_gesture_tracker_get_n_current_touches (tracker) == 0)
- return TRUE;
- }
-#endif /* HAVE_NATIVE_BACKEND */
-
- return FALSE;
-}
-
-static void
-maybe_unfreeze_pointer_events (MetaBackend *backend,
- const ClutterEvent *event,
- EventsUnfreezeMethod unfreeze_method)
-{
- ClutterInputDevice *device;
- Display *xdisplay;
- int event_mode;
- int device_id;
-
- if (event->type != CLUTTER_BUTTON_PRESS)
- return;
-
- if (!META_IS_BACKEND_X11 (backend))
- return;
-
- device = clutter_event_get_device (event);
- device_id = meta_input_device_x11_get_device_id (device);
- switch (unfreeze_method)
- {
- case EVENTS_UNFREEZE_SYNC:
- event_mode = XISyncDevice;
- meta_verbose ("Syncing events time %u device %i",
- (unsigned int) event->button.time, device_id);
- break;
- case EVENTS_UNFREEZE_REPLAY:
- event_mode = XIReplayDevice;
- meta_verbose ("Replaying events time %u device %i",
- (unsigned int) event->button.time, device_id);
- break;
- default:
- g_assert_not_reached ();
- return;
- }
-
- xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
- XIAllowEvents (xdisplay, device_id, event_mode, event->button.time);
-}
-
-static gboolean
-meta_display_handle_event (MetaDisplay *display,
- const ClutterEvent *event)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaWindow *window;
- gboolean bypass_clutter = FALSE;
- G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
- MetaGestureTracker *gesture_tracker;
- ClutterEventSequence *sequence;
-
- sequence = clutter_event_get_event_sequence (event);
-
- /* Set the pointer emulating sequence on touch begin, if eligible */
- if (event->type == CLUTTER_TOUCH_BEGIN)
- {
- if (sequence_is_pointer_emulated (display, event))
- {
- /* This is the new pointer emulating sequence */
- display->pointer_emulating_sequence = sequence;
- }
- else if (display->pointer_emulating_sequence == sequence)
- {
- /* This sequence was "pointer emulating" in a prior incarnation,
- * but now it isn't. We unset the pointer emulating sequence at
- * this point so the current sequence is not mistaken as pointer
- * emulating, while we've ensured that it's been deemed
- * "pointer emulating" throughout all of the event processing
- * of the previous incarnation.
- */
- display->pointer_emulating_sequence = NULL;
- }
- }
-
-#ifdef HAVE_WAYLAND
- MetaWaylandCompositor *compositor = NULL;
- if (meta_is_wayland_compositor ())
- {
- compositor = meta_wayland_compositor_get_default ();
- meta_wayland_compositor_update (compositor, event);
- }
-#endif
-
- if (event->type == CLUTTER_PAD_BUTTON_PRESS ||
- event->type == CLUTTER_PAD_BUTTON_RELEASE ||
- event->type == CLUTTER_PAD_RING ||
- event->type == CLUTTER_PAD_STRIP)
- {
- gboolean handle_pad_event;
- gboolean is_mode_switch = FALSE;
-
- if (event->type == CLUTTER_PAD_BUTTON_PRESS ||
- event->type == CLUTTER_PAD_BUTTON_RELEASE)
- {
- ClutterInputDevice *pad;
- uint32_t button;
-
- pad = clutter_event_get_source_device (event);
- button = clutter_event_get_button (event);
-
- is_mode_switch =
- clutter_input_device_get_mode_switch_button_group (pad, button) >= 0;
- }
-
- handle_pad_event = !display->current_pad_osd || is_mode_switch;
-
- if (handle_pad_event &&
- meta_pad_action_mapper_handle_event (display->pad_action_mapper, event))
- {
- bypass_wayland = bypass_clutter = TRUE;
- goto out;
- }
- }
-
- if (event->type != CLUTTER_DEVICE_ADDED &&
- event->type != CLUTTER_DEVICE_REMOVED)
- {
- ClutterInputDevice *source;
-
- handle_idletime_for_event (event);
- source = clutter_event_get_source_device (event);
-
- if (source)
- meta_backend_update_last_device (backend, source);
- }
-
-#ifdef HAVE_WAYLAND
- if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
- {
- MetaCursorRenderer *cursor_renderer;
- ClutterInputDevice *device;
-
- device = clutter_event_get_device (event);
- cursor_renderer = meta_backend_get_cursor_renderer_for_device (backend,
- device);
- if (cursor_renderer)
- meta_cursor_renderer_update_position (cursor_renderer);
-
- if (device == clutter_seat_get_pointer (clutter_input_device_get_seat (device)))
- {
- MetaCursorTracker *cursor_tracker =
- meta_backend_get_cursor_tracker (backend);
-
- meta_cursor_tracker_invalidate_position (cursor_tracker);
- }
- }
-#endif
-
- window = get_window_for_event (display, event);
-
- display->current_time = event->any.time;
-
- if (window && !window->override_redirect &&
- (event->type == CLUTTER_KEY_PRESS ||
- event->type == CLUTTER_BUTTON_PRESS ||
- event->type == CLUTTER_TOUCH_BEGIN))
- {
- if (META_CURRENT_TIME == display->current_time)
- {
- /* We can't use missing (i.e. invalid) timestamps to set user time,
- * nor do we want to use them to sanity check other timestamps.
- * See bug 313490 for more details.
- */
- meta_warning ("Event has no timestamp! You may be using a broken "
- "program such as xse. Please ask the authors of that "
- "program to fix it.");
- }
- else
- {
- meta_window_set_user_time (window, display->current_time);
- meta_display_sanity_check_timestamps (display, display->current_time);
- }
- }
-
- gesture_tracker = meta_display_get_gesture_tracker (display);
-
- if (meta_gesture_tracker_handle_event (gesture_tracker, event))
- {
- bypass_wayland = bypass_clutter = TRUE;
- goto out;
- }
-
- if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
- {
- if (meta_window_handle_mouse_grab_op_event (window, event))
- {
- bypass_clutter = TRUE;
- bypass_wayland = TRUE;
- goto out;
- }
- }
-
- /* For key events, it's important to enforce single-handling, or
- * we can get into a confused state. So if a keybinding is
- * handled (because it's one of our hot-keys, or because we are
- * in a keyboard-grabbed mode like moving a window, we don't
- * want to pass the key event to the compositor or Wayland at all.
- */
- if (meta_keybindings_process_event (display, window, event))
- {
- bypass_clutter = TRUE;
- bypass_wayland = TRUE;
- goto out;
- }
-
- /* Do not pass keyboard events to Wayland if key focus is not on the
- * stage in normal mode (e.g. during keynav in the panel)
- */
- if (display->event_route == META_EVENT_ROUTE_NORMAL)
- {
- if (IS_KEY_EVENT (event) && !stage_has_key_focus ())
- {
- bypass_wayland = TRUE;
- goto out;
- }
- }
-
- if (meta_is_wayland_compositor () &&
- event->type == CLUTTER_SCROLL &&
- meta_prefs_get_mouse_button_mods () > 0)
- {
- ClutterModifierType grab_mods;
-
- grab_mods = meta_display_get_compositor_modifiers (display);
- if ((clutter_event_get_state (event) & grab_mods) != 0)
- {
- bypass_wayland = TRUE;
- goto out;
- }
- }
-
- if (display->current_pad_osd)
- {
- bypass_wayland = TRUE;
- goto out;
- }
-
- if (window)
- {
- /* Events that are likely to trigger compositor gestures should
- * be known to clutter so they can propagate along the hierarchy.
- * Gesture-wise, there's two groups of events we should be getting
- * here:
- * - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted
- * by the gesture tracker, these might trigger gesture actions
- * into recognition. Already accepted touch sequences are handled
- * directly by meta_gesture_tracker_handle_event().
- * - CLUTTER_TOUCHPAD_* events over windows. These can likewise
- * trigger ::captured-event handlers along the way.
- */
- bypass_clutter = !IS_GESTURE_EVENT (event);
-
- /* When double clicking to un-maximize an X11 window under Wayland,
- * there is a race between X11 and Wayland protocols and the X11
- * XConfigureWindow may be processed by Xwayland before the button
- * press event is forwarded via the Wayland protocol.
- * As a result, the second click may reach another X11 window placed
- * immediately underneath in the X11 stack.
- * The following is to make sure we do not forward the button press
- * event to Wayland if it was handled by the frame UI.
- * See: https://gitlab.gnome.org/GNOME/mutter/issues/88
- */
- if (meta_window_handle_ui_frame_event (window, event))
- bypass_wayland = (event->type == CLUTTER_BUTTON_PRESS ||
- event->type == CLUTTER_TOUCH_BEGIN);
- else
- meta_window_handle_ungrabbed_event (window, event);
-
- /* This might start a grab op. If it does, then filter out the
- * event, and if it doesn't, replay the event to release our
- * own sync grab. */
-
- if (display->event_route == META_EVENT_ROUTE_WINDOW_OP ||
- display->event_route == META_EVENT_ROUTE_FRAME_BUTTON)
- {
- bypass_clutter = TRUE;
- bypass_wayland = TRUE;
- }
- else
- {
- /* Only replay button press events, since that's where we
- * have the synchronous grab. */
- maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY);
-
- /* If the focus window has an active close dialog let clutter
- * events go through, so fancy clutter dialogs can get to handle
- * all events.
- */
- if (window->close_dialog &&
- meta_close_dialog_is_visible (window->close_dialog))
- {
- bypass_wayland = TRUE;
- bypass_clutter = FALSE;
- }
- }
-
- goto out;
- }
- else
- {
- /* We could not match the event with a window, make sure we sync
- * the pointer to discard the sequence and don't keep events frozen.
- */
- maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC);
- }
-
- out:
- /* If the compositor has a grab, don't pass that through to Wayland */
- if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
- bypass_wayland = TRUE;
-
- /* If a Wayland client has a grab, don't pass that through to Clutter */
- if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
- bypass_clutter = TRUE;
-
-#ifdef HAVE_WAYLAND
- if (compositor && !bypass_wayland)
- {
- if (meta_wayland_compositor_handle_event (compositor, event))
- bypass_clutter = TRUE;
- }
-#endif
-
- display->current_time = META_CURRENT_TIME;
- return bypass_clutter;
-}
-
-static gboolean
-event_callback (const ClutterEvent *event,
- gpointer data)
-{
- MetaDisplay *display = data;
-
- return meta_display_handle_event (display, event);
-}
-
-void
-meta_display_init_events (MetaDisplay *display)
-{
- display->clutter_event_filter = clutter_event_add_filter (NULL,
- event_callback,
- NULL,
- display);
-}
-
-void
-meta_display_free_events (MetaDisplay *display)
-{
- clutter_event_remove_filter (display->clutter_event_filter);
- display->clutter_event_filter = 0;
-}
diff --git a/src/core/events.h b/src/core/events.h
deleted file mode 100644
index 6338119ae..000000000
--- a/src/core/events.h
+++ /dev/null
@@ -1,31 +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/>.
- */
-
-#ifndef META_EVENTS_H
-#define META_EVENTS_H
-
-#include "meta/display.h"
-
-void meta_display_init_events (MetaDisplay *display);
-void meta_display_free_events (MetaDisplay *display);
-
-#endif
diff --git a/src/core/frame.c b/src/core/frame.c
deleted file mode 100644
index 9c8cbb946..000000000
--- a/src/core/frame.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter X window decorations */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2003, 2004 Red Hat, Inc.
- * Copyright (C) 2005 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/>.
- */
-
-#include "config.h"
-
-#include "core/frame.h"
-
-#include "backends/x11/meta-backend-x11.h"
-#include "core/bell.h"
-#include "core/keybindings-private.h"
-#include "meta/meta-x11-errors.h"
-#include "x11/meta-x11-display-private.h"
-
-#define EVENT_MASK (SubstructureRedirectMask | \
- StructureNotifyMask | SubstructureNotifyMask | \
- ExposureMask | FocusChangeMask)
-
-void
-meta_window_ensure_frame (MetaWindow *window)
-{
- MetaFrame *frame;
- XSetWindowAttributes attrs;
- gulong create_serial;
- MetaX11Display *x11_display;
-
- if (window->frame)
- return;
-
- x11_display = window->display->x11_display;
-
- frame = g_new (MetaFrame, 1);
-
- frame->window = window;
- frame->xwindow = None;
-
- frame->rect = window->rect;
- frame->child_x = 0;
- frame->child_y = 0;
- frame->bottom_height = 0;
- frame->right_width = 0;
- frame->current_cursor = 0;
-
- frame->borders_cached = FALSE;
-
- meta_verbose ("Frame geometry %d,%d %dx%d",
- frame->rect.x, frame->rect.y,
- frame->rect.width, frame->rect.height);
-
- frame->ui_frame = meta_ui_create_frame (x11_display->ui,
- x11_display->xdisplay,
- frame->window,
- window->xvisual,
- frame->rect.x,
- frame->rect.y,
- frame->rect.width,
- frame->rect.height,
- &create_serial);
- frame->xwindow = frame->ui_frame->xwindow;
-
- meta_stack_tracker_record_add (window->display->stack_tracker,
- frame->xwindow,
- create_serial);
-
- meta_verbose ("Frame for %s is 0x%lx", frame->window->desc, frame->xwindow);
- attrs.event_mask = EVENT_MASK;
- XChangeWindowAttributes (x11_display->xdisplay,
- frame->xwindow, CWEventMask, &attrs);
-
- meta_x11_display_register_x_window (x11_display, &frame->xwindow, window);
-
- meta_x11_error_trap_push (x11_display);
- if (window->mapped)
- {
- window->mapped = FALSE; /* the reparent will unmap the window,
- * we don't want to take that as a withdraw
- */
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Incrementing unmaps_pending on %s for reparent", window->desc);
- window->unmaps_pending += 1;
- }
-
- meta_stack_tracker_record_remove (window->display->stack_tracker,
- window->xwindow,
- XNextRequest (x11_display->xdisplay));
- XReparentWindow (x11_display->xdisplay,
- window->xwindow,
- frame->xwindow,
- frame->child_x,
- frame->child_y);
- window->reparents_pending += 1;
- /* FIXME handle this error */
- meta_x11_error_trap_pop (x11_display);
-
- /* Ensure focus is restored after the unmap/map events triggered
- * by XReparentWindow().
- */
- if (meta_window_has_focus (window))
- window->restore_focus_on_map = TRUE;
-
- /* stick frame to the window */
- window->frame = frame;
-
- /* Now that frame->xwindow is registered with window, we can set its
- * style and background.
- */
- meta_frame_update_style (frame);
- meta_frame_update_title (frame);
-
- meta_ui_map_frame (x11_display->ui, frame->xwindow);
-
- {
- MetaBackend *backend = meta_get_backend ();
- if (META_IS_BACKEND_X11 (backend))
- {
- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
-
- /* Since the backend selects for events on another connection,
- * make sure to sync the GTK+ connection to ensure that the
- * frame window has been created on the server at this point. */
- XSync (x11_display->xdisplay, False);
-
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
- XISelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- frame->xwindow, &mask, 1);
-
- XISetMask (mask.mask, XI_ButtonPress);
- XISetMask (mask.mask, XI_ButtonRelease);
- XISetMask (mask.mask, XI_Motion);
- XISetMask (mask.mask, XI_Enter);
- XISetMask (mask.mask, XI_Leave);
-
- XISelectEvents (xdisplay, frame->xwindow, &mask, 1);
- }
- }
-
- /* Move keybindings to frame instead of window */
- meta_window_grab_keys (window);
-}
-
-void
-meta_window_destroy_frame (MetaWindow *window)
-{
- MetaFrame *frame;
- MetaFrameBorders borders;
- MetaX11Display *x11_display;
-
- if (window->frame == NULL)
- return;
-
- x11_display = window->display->x11_display;
-
- meta_verbose ("Unframing window %s", window->desc);
-
- frame = window->frame;
-
- meta_frame_calc_borders (frame, &borders);
-
- /* Unparent the client window; it may be destroyed,
- * thus the error trap.
- */
- meta_x11_error_trap_push (x11_display);
- if (window->mapped)
- {
- window->mapped = FALSE; /* Keep track of unmapping it, so we
- * can identify a withdraw initiated
- * by the client.
- */
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Incrementing unmaps_pending on %s for reparent back to root", window->desc);
- window->unmaps_pending += 1;
- }
-
- if (!x11_display->closing)
- {
- meta_stack_tracker_record_add (window->display->stack_tracker,
- window->xwindow,
- XNextRequest (x11_display->xdisplay));
-
- XReparentWindow (x11_display->xdisplay,
- window->xwindow,
- x11_display->xroot,
- /* Using anything other than client root window coordinates
- * coordinates here means we'll need to ensure a configure
- * notify event is sent; see bug 399552.
- */
- window->frame->rect.x + borders.invisible.left,
- window->frame->rect.y + borders.invisible.top);
- window->reparents_pending += 1;
- }
-
- meta_x11_error_trap_pop (x11_display);
-
- meta_ui_frame_unmanage (frame->ui_frame);
-
- /* Ensure focus is restored after the unmap/map events triggered
- * by XReparentWindow().
- */
- if (meta_window_has_focus (window))
- window->restore_focus_on_map = TRUE;
-
- meta_x11_display_unregister_x_window (x11_display, frame->xwindow);
-
- window->frame = NULL;
- if (window->frame_bounds)
- {
- cairo_region_destroy (window->frame_bounds);
- window->frame_bounds = NULL;
- }
-
- /* Move keybindings to window instead of frame */
- meta_window_grab_keys (window);
-
- g_free (frame);
-
- /* Put our state back where it should be */
- meta_window_queue (window, META_QUEUE_CALC_SHOWING);
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
-}
-
-
-MetaFrameFlags
-meta_frame_get_flags (MetaFrame *frame)
-{
- MetaFrameFlags flags;
-
- flags = 0;
-
- if (frame->window->border_only)
- {
- ; /* FIXME this may disable the _function_ as well as decor
- * in some cases, which is sort of wrong.
- */
- }
- else
- {
- flags |= META_FRAME_ALLOWS_MENU;
-
- if (frame->window->has_close_func)
- flags |= META_FRAME_ALLOWS_DELETE;
-
- if (frame->window->has_maximize_func)
- flags |= META_FRAME_ALLOWS_MAXIMIZE;
-
- if (frame->window->has_minimize_func)
- flags |= META_FRAME_ALLOWS_MINIMIZE;
-
- if (frame->window->has_shade_func)
- flags |= META_FRAME_ALLOWS_SHADE;
- }
-
- if (META_WINDOW_ALLOWS_MOVE (frame->window))
- flags |= META_FRAME_ALLOWS_MOVE;
-
- if (META_WINDOW_ALLOWS_HORIZONTAL_RESIZE (frame->window))
- flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE;
-
- if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
- flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
-
- if (meta_window_appears_focused (frame->window))
- flags |= META_FRAME_HAS_FOCUS;
-
- if (frame->window->shaded)
- flags |= META_FRAME_SHADED;
-
- if (frame->window->on_all_workspaces_requested)
- flags |= META_FRAME_STUCK;
-
- /* FIXME: Should we have some kind of UI for windows that are just vertically
- * maximized or just horizontally maximized?
- */
- if (META_WINDOW_MAXIMIZED (frame->window))
- flags |= META_FRAME_MAXIMIZED;
-
- if (META_WINDOW_TILED_LEFT (frame->window))
- flags |= META_FRAME_TILED_LEFT;
-
- if (META_WINDOW_TILED_RIGHT (frame->window))
- flags |= META_FRAME_TILED_RIGHT;
-
- if (frame->window->fullscreen)
- flags |= META_FRAME_FULLSCREEN;
-
- if (frame->window->wm_state_above)
- flags |= META_FRAME_ABOVE;
-
- return flags;
-}
-
-void
-meta_frame_borders_clear (MetaFrameBorders *self)
-{
- self->visible.top = self->invisible.top = self->total.top = 0;
- self->visible.bottom = self->invisible.bottom = self->total.bottom = 0;
- self->visible.left = self->invisible.left = self->total.left = 0;
- self->visible.right = self->invisible.right = self->total.right = 0;
-}
-
-void
-meta_frame_calc_borders (MetaFrame *frame,
- MetaFrameBorders *borders)
-{
- /* Save on if statements and potential uninitialized values
- * in callers -- if there's no frame, then zero the borders. */
- if (frame == NULL)
- meta_frame_borders_clear (borders);
- else
- {
- if (!frame->borders_cached)
- {
- meta_ui_frame_get_borders (frame->ui_frame, &frame->cached_borders);
- frame->borders_cached = TRUE;
- }
-
- *borders = frame->cached_borders;
- }
-}
-
-void
-meta_frame_clear_cached_borders (MetaFrame *frame)
-{
- frame->borders_cached = FALSE;
-}
-
-gboolean
-meta_frame_sync_to_window (MetaFrame *frame,
- gboolean need_resize)
-{
- meta_topic (META_DEBUG_GEOMETRY,
- "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)",
- frame->rect.x, frame->rect.y,
- frame->rect.width, frame->rect.height,
- frame->rect.x + frame->rect.width,
- frame->rect.y + frame->rect.height);
-
- meta_ui_frame_move_resize (frame->ui_frame,
- frame->rect.x,
- frame->rect.y,
- frame->rect.width,
- frame->rect.height);
-
- return need_resize;
-}
-
-cairo_region_t *
-meta_frame_get_frame_bounds (MetaFrame *frame)
-{
- return meta_ui_frame_get_bounds (frame->ui_frame);
-}
-
-void
-meta_frame_get_mask (MetaFrame *frame,
- cairo_rectangle_int_t *frame_rect,
- cairo_t *cr)
-{
- meta_ui_frame_get_mask (frame->ui_frame, frame_rect, cr);
-}
-
-void
-meta_frame_queue_draw (MetaFrame *frame)
-{
- meta_ui_frame_queue_draw (frame->ui_frame);
-}
-
-void
-meta_frame_set_screen_cursor (MetaFrame *frame,
- MetaCursor cursor)
-{
- MetaX11Display *x11_display;
- Cursor xcursor;
- if (cursor == frame->current_cursor)
- return;
-
- frame->current_cursor = cursor;
- x11_display = frame->window->display->x11_display;
-
- if (cursor == META_CURSOR_DEFAULT)
- XUndefineCursor (x11_display->xdisplay, frame->xwindow);
- else
- {
- xcursor = meta_x11_display_create_x_cursor (x11_display, cursor);
- XDefineCursor (x11_display->xdisplay, frame->xwindow, xcursor);
- XFlush (x11_display->xdisplay);
- XFreeCursor (x11_display->xdisplay, xcursor);
- }
-}
-
-Window
-meta_frame_get_xwindow (MetaFrame *frame)
-{
- return frame->xwindow;
-}
-
-void
-meta_frame_update_style (MetaFrame *frame)
-{
- meta_ui_frame_update_style (frame->ui_frame);
-}
-
-void
-meta_frame_update_title (MetaFrame *frame)
-{
- if (frame->window->title)
- meta_ui_frame_set_title (frame->ui_frame, frame->window->title);
-}
diff --git a/src/core/frame.h b/src/core/frame.h
deleted file mode 100644
index 61a5ca725..000000000
--- a/src/core/frame.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter X window decorations */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- *
- * 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/>.
- */
-
-#ifndef META_FRAME_PRIVATE_H
-#define META_FRAME_PRIVATE_H
-
-#include "core/window-private.h"
-#include "ui/frames.h"
-
-struct _MetaFrame
-{
- /* window we frame */
- MetaWindow *window;
-
- /* reparent window */
- Window xwindow;
-
- MetaCursor current_cursor;
-
- /* This rect is trusted info from where we put the
- * frame, not the result of ConfigureNotify
- */
- MetaRectangle rect;
-
- MetaFrameBorders cached_borders; /* valid if borders_cached is set */
-
- /* position of client, size of frame */
- int child_x;
- int child_y;
- int right_width;
- int bottom_height;
-
- guint need_reapply_frame_shape : 1;
- guint borders_cached : 1;
-
- MetaUIFrame *ui_frame;
-};
-
-void meta_window_ensure_frame (MetaWindow *window);
-void meta_window_destroy_frame (MetaWindow *window);
-void meta_frame_queue_draw (MetaFrame *frame);
-
-MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
-Window meta_frame_get_xwindow (MetaFrame *frame);
-
-/* These should ONLY be called from meta_window_move_resize_internal */
-void meta_frame_calc_borders (MetaFrame *frame,
- MetaFrameBorders *borders);
-
-gboolean meta_frame_sync_to_window (MetaFrame *frame,
- gboolean need_resize);
-
-void meta_frame_clear_cached_borders (MetaFrame *frame);
-
-cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
-
-void meta_frame_get_mask (MetaFrame *frame,
- cairo_rectangle_int_t *frame_rect,
- cairo_t *cr);
-
-void meta_frame_set_screen_cursor (MetaFrame *frame,
- MetaCursor cursor);
-
-void meta_frame_update_style (MetaFrame *frame);
-void meta_frame_update_title (MetaFrame *frame);
-
-#endif
diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h
deleted file mode 100644
index 56792c200..000000000
--- a/src/core/keybindings-private.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/**
- * \file keybindings.h Grab and ungrab keys, and process the key events
- *
- * Performs global X grabs on the keys we need to be told about, like
- * the one to close a window. It also deals with incoming key events.
- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- *
- * 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/>.
- */
-
-#ifndef META_KEYBINDINGS_PRIVATE_H
-#define META_KEYBINDINGS_PRIVATE_H
-
-#include <gio/gio.h>
-#include <xkbcommon/xkbcommon.h>
-
-#include "core/meta-accel-parse.h"
-#include "meta/keybindings.h"
-
-typedef struct _MetaKeyHandler MetaKeyHandler;
-struct _MetaKeyHandler
-{
- char *name;
- MetaKeyHandlerFunc func;
- MetaKeyHandlerFunc default_func;
- gint data, flags;
- gpointer user_data;
- GDestroyNotify user_data_free_func;
-};
-
-typedef struct _MetaResolvedKeyCombo {
- xkb_keycode_t *keycodes;
- int len;
- xkb_mod_mask_t mask;
-} MetaResolvedKeyCombo;
-
-/**
- * MetaKeyCombo:
- * @keysym: keysym
- * @keycode: keycode
- * @modifiers: modifiers
- */
-struct _MetaKeyCombo
-{
- unsigned int keysym;
- unsigned int keycode;
- MetaVirtualModifier modifiers;
-};
-
-struct _MetaKeyBinding
-{
- const char *name;
- MetaKeyCombo combo;
- MetaResolvedKeyCombo resolved_combo;
- gint flags;
- MetaKeyHandler *handler;
-};
-
-typedef struct
-{
- char *name;
- GSettings *settings;
-
- MetaKeyBindingAction action;
-
- /*
- * A list of MetaKeyCombos. Each of them is bound to
- * this keypref. If one has keysym==modifiers==0, it is
- * ignored.
- */
- GSList *combos;
-
- /* for keybindings not added with meta_display_add_keybinding() */
- gboolean builtin:1;
-} MetaKeyPref;
-
-typedef struct _MetaKeyBindingKeyboardLayout
-{
- struct xkb_keymap *keymap;
- xkb_layout_index_t index;
- xkb_level_index_t n_levels;
-} MetaKeyBindingKeyboardLayout;
-
-typedef struct
-{
- MetaBackend *backend;
-
- GHashTable *key_bindings;
- GHashTable *key_bindings_index;
- xkb_mod_mask_t ignored_modifier_mask;
- xkb_mod_mask_t hyper_mask;
- xkb_mod_mask_t virtual_hyper_mask;
- xkb_mod_mask_t super_mask;
- xkb_mod_mask_t virtual_super_mask;
- xkb_mod_mask_t meta_mask;
- xkb_mod_mask_t virtual_meta_mask;
- MetaKeyCombo overlay_key_combo;
- MetaResolvedKeyCombo overlay_resolved_key_combo;
- gboolean overlay_key_only_pressed;
- MetaKeyCombo locate_pointer_key_combo;
- MetaResolvedKeyCombo locate_pointer_resolved_key_combo;
- gboolean locate_pointer_key_only_pressed;
- MetaResolvedKeyCombo iso_next_group_combo[2];
- int n_iso_next_group_combos;
-
- /*
- * A primary layout, and an optional secondary layout for when the
- * primary layout does not use the latin alphabet.
- */
- MetaKeyBindingKeyboardLayout active_layouts[2];
-
- /* Alt+click button grabs */
- ClutterModifierType window_grab_modifiers;
-} MetaKeyBindingManager;
-
-void meta_display_init_keys (MetaDisplay *display);
-void meta_display_shutdown_keys (MetaDisplay *display);
-void meta_window_grab_keys (MetaWindow *window);
-void meta_window_ungrab_keys (MetaWindow *window);
-gboolean meta_window_grab_all_keys (MetaWindow *window,
- guint32 timestamp);
-void meta_window_ungrab_all_keys (MetaWindow *window,
- guint32 timestamp);
-gboolean meta_keybindings_process_event (MetaDisplay *display,
- MetaWindow *window,
- const ClutterEvent *event);
-
-gboolean meta_prefs_add_keybinding (const char *name,
- GSettings *settings,
- MetaKeyBindingAction action,
- MetaKeyBindingFlags flags);
-
-gboolean meta_prefs_remove_keybinding (const char *name);
-
-GList *meta_prefs_get_keybindings (void);
-void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
-void meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo);
-const char *meta_prefs_get_iso_next_group_option (void);
-gboolean meta_prefs_is_locate_pointer_enabled (void);
-
-void meta_x11_display_grab_keys (MetaX11Display *x11_display);
-void meta_x11_display_ungrab_keys (MetaX11Display *x11_display);
-
-#endif
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
deleted file mode 100644
index a6e16f084..000000000
--- a/src/core/keybindings.c
+++ /dev/null
@@ -1,4578 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter Keybindings */
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002 Red Hat Inc.
- * Copyright (C) 2003 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:keybindings
- * @Title: MetaKeybinding
- * @Short_Description: Key bindings
- */
-
-#include "config.h"
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-keymap-utils.h"
-#include "backends/meta-logical-monitor.h"
-#include "backends/meta-monitor-manager-private.h"
-#include "backends/x11/meta-backend-x11.h"
-#include "backends/x11/meta-input-device-x11.h"
-#include "compositor/compositor-private.h"
-#include "core/edge-resistance.h"
-#include "core/frame.h"
-#include "core/keybindings-private.h"
-#include "core/meta-accel-parse.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/workspace-private.h"
-#include "meta/compositor.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/prefs.h"
-#include "x11/meta-x11-display-private.h"
-#include "x11/window-x11.h"
-
-#ifdef HAVE_NATIVE_BACKEND
-#include "backends/native/meta-backend-native.h"
-#endif
-
-#ifdef __linux__
-#include <linux/input.h>
-#elif !defined KEY_GRAVE
-#define KEY_GRAVE 0x29 /* assume the use of xf86-input-keyboard */
-#endif
-
-#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
-#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
-#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
-
-#define META_KEY_BINDING_PRIMARY_LAYOUT 0
-#define META_KEY_BINDING_SECONDARY_LAYOUT 1
-
-/* Only for special modifier keys */
-#define IGNORED_MODIFIERS (CLUTTER_LOCK_MASK | \
- CLUTTER_MOD2_MASK | \
- CLUTTER_BUTTON1_MASK | \
- CLUTTER_BUTTON2_MASK | \
- CLUTTER_BUTTON3_MASK | \
- CLUTTER_BUTTON4_MASK | \
- CLUTTER_BUTTON5_MASK)
-
-static gboolean add_builtin_keybinding (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyBindingAction action,
- MetaKeyHandlerFunc handler,
- int handler_arg);
-
-static void
-resolved_key_combo_reset (MetaResolvedKeyCombo *resolved_combo)
-{
- g_free (resolved_combo->keycodes);
- resolved_combo->len = 0;
- resolved_combo->keycodes = NULL;
-}
-
-static void
-resolved_key_combo_copy (MetaResolvedKeyCombo *from,
- MetaResolvedKeyCombo *to)
-{
- to->len = from->len;
- to->keycodes = g_memdup2 (from->keycodes,
- from->len * sizeof (xkb_keycode_t));
-}
-
-static gboolean
-resolved_key_combo_has_keycode (MetaResolvedKeyCombo *resolved_combo,
- int keycode)
-{
- int i;
-
- for (i = 0; i < resolved_combo->len; i++)
- if ((int) resolved_combo->keycodes[i] == keycode)
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-resolved_key_combo_intersect (MetaResolvedKeyCombo *a,
- MetaResolvedKeyCombo *b)
-{
- int i;
-
- for (i = 0; i < a->len; i++)
- if (resolved_key_combo_has_keycode (b, a->keycodes[i]))
- return TRUE;
-
- return FALSE;
-}
-
-static void
-meta_key_binding_free (MetaKeyBinding *binding)
-{
- resolved_key_combo_reset (&binding->resolved_combo);
- g_free (binding);
-}
-
-static MetaKeyBinding *
-meta_key_binding_copy (MetaKeyBinding *binding)
-{
- MetaKeyBinding *clone = g_memdup2 (binding, sizeof (MetaKeyBinding));
- resolved_key_combo_copy (&binding->resolved_combo,
- &clone->resolved_combo);
- return clone;
-}
-
-G_DEFINE_BOXED_TYPE(MetaKeyBinding,
- meta_key_binding,
- meta_key_binding_copy,
- meta_key_binding_free)
-
-const char *
-meta_key_binding_get_name (MetaKeyBinding *binding)
-{
- return binding->name;
-}
-
-MetaVirtualModifier
-meta_key_binding_get_modifiers (MetaKeyBinding *binding)
-{
- return binding->combo.modifiers;
-}
-
-gboolean
-meta_key_binding_is_reversed (MetaKeyBinding *binding)
-{
- return (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0;
-}
-
-guint
-meta_key_binding_get_mask (MetaKeyBinding *binding)
-{
- return binding->resolved_combo.mask;
-}
-
-gboolean
-meta_key_binding_is_builtin (MetaKeyBinding *binding)
-{
- return binding->handler->flags & META_KEY_BINDING_BUILTIN;
-}
-
-/* These can't be bound to anything, but they are used to handle
- * various other events. TODO: Possibly we should include them as event
- * handler functions and have some kind of flag to say they're unbindable.
- */
-
-static gboolean process_mouse_move_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event);
-
-static gboolean process_keyboard_move_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event);
-
-static gboolean process_keyboard_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event);
-
-static void maybe_update_locate_pointer_keygrab (MetaDisplay *display,
- gboolean grab);
-
-static GHashTable *key_handlers;
-static GHashTable *external_grabs;
-
-#define HANDLER(name) g_hash_table_lookup (key_handlers, (name))
-
-static void
-key_handler_free (MetaKeyHandler *handler)
-{
- g_free (handler->name);
- if (handler->user_data_free_func && handler->user_data)
- handler->user_data_free_func (handler->user_data);
- g_free (handler);
-}
-
-typedef struct _MetaKeyGrab MetaKeyGrab;
-struct _MetaKeyGrab {
- char *name;
- guint action;
- MetaKeyCombo combo;
- gint flags;
-};
-
-static void
-meta_key_grab_free (MetaKeyGrab *grab)
-{
- g_free (grab->name);
- g_free (grab);
-}
-
-static guint32
-key_combo_key (MetaResolvedKeyCombo *resolved_combo,
- int i)
-{
- /* On X, keycodes are only 8 bits while libxkbcommon supports 32 bit
- keycodes, but since we're using the same XKB keymaps that X uses,
- we won't find keycodes bigger than 8 bits in practice. The bits
- that mutter cares about in the modifier mask are also all in the
- lower 8 bits both on X and clutter key events. This means that we
- can use a 32 bit integer to safely concatenate both keycode and
- mask and thus making it easy to use them as an index in a
- GHashTable. */
- guint32 key = resolved_combo->keycodes[i] & 0xffff;
- return (key << 16) | (resolved_combo->mask & 0xffff);
-}
-
-static void
-reload_modmap (MetaKeyBindingManager *keys)
-{
- struct xkb_keymap *keymap = meta_backend_get_keymap (keys->backend);
- struct xkb_state *scratch_state;
- xkb_mod_mask_t scroll_lock_mask;
- xkb_mod_mask_t dummy_mask;
-
- /* Modifiers to find. */
- struct {
- const char *name;
- xkb_mod_mask_t *mask_p;
- xkb_mod_mask_t *virtual_mask_p;
- } mods[] = {
- { "ScrollLock", &scroll_lock_mask, &dummy_mask },
- { "Meta", &keys->meta_mask, &keys->virtual_meta_mask },
- { "Hyper", &keys->hyper_mask, &keys->virtual_hyper_mask },
- { "Super", &keys->super_mask, &keys->virtual_super_mask },
- };
-
- scratch_state = xkb_state_new (keymap);
-
- gsize i;
- for (i = 0; i < G_N_ELEMENTS (mods); i++)
- {
- xkb_mod_mask_t *mask_p = mods[i].mask_p;
- xkb_mod_mask_t *virtual_mask_p = mods[i].virtual_mask_p;
- xkb_mod_index_t idx = xkb_keymap_mod_get_index (keymap, mods[i].name);
-
- if (idx != XKB_MOD_INVALID)
- {
- xkb_mod_mask_t vmodmask = (1 << idx);
- xkb_state_update_mask (scratch_state, vmodmask, 0, 0, 0, 0, 0);
- *mask_p = xkb_state_serialize_mods (scratch_state, XKB_STATE_MODS_DEPRESSED) & ~vmodmask;
- *virtual_mask_p = vmodmask;
- }
- else
- {
- *mask_p = 0;
- *virtual_mask_p = 0;
- }
- }
-
- xkb_state_unref (scratch_state);
-
- keys->ignored_modifier_mask = (scroll_lock_mask | Mod2Mask | LockMask);
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Ignoring modmask 0x%x scroll lock 0x%x hyper 0x%x super 0x%x meta 0x%x",
- keys->ignored_modifier_mask,
- scroll_lock_mask,
- keys->hyper_mask,
- keys->super_mask,
- keys->meta_mask);
-}
-
-static gboolean
-is_keycode_for_keysym (struct xkb_keymap *keymap,
- xkb_layout_index_t layout,
- xkb_level_index_t level,
- xkb_keycode_t keycode,
- xkb_keysym_t keysym)
-{
- const xkb_keysym_t *syms;
- int num_syms, k;
-
- num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, layout, level, &syms);
- for (k = 0; k < num_syms; k++)
- {
- if (syms[k] == keysym)
- return TRUE;
- }
-
- return FALSE;
-}
-
-typedef struct
-{
- GArray *keycodes;
- xkb_keysym_t keysym;
- xkb_layout_index_t layout;
- xkb_level_index_t level;
-} FindKeysymData;
-
-static void
-get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
- xkb_keycode_t keycode,
- void *data)
-{
- FindKeysymData *search_data = data;
- GArray *keycodes = search_data->keycodes;
- xkb_keysym_t keysym = search_data->keysym;
- xkb_layout_index_t layout = search_data->layout;
- xkb_level_index_t level = search_data->level;
-
- if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym))
- {
- guint i;
- gboolean missing = TRUE;
-
- /* duplicate keycode detection */
- for (i = 0; i < keycodes->len; i++)
- if (g_array_index (keycodes, xkb_keysym_t, i) == keycode)
- {
- missing = FALSE;
- break;
- }
-
- if (missing)
- g_array_append_val (keycodes, keycode);
- }
-}
-
-static void
-add_keysym_keycodes_from_layout (int keysym,
- MetaKeyBindingKeyboardLayout *layout,
- GArray *keycodes)
-{
- xkb_level_index_t layout_level;
-
- for (layout_level = 0;
- layout_level < layout->n_levels && keycodes->len == 0;
- layout_level++)
- {
- FindKeysymData search_data = (FindKeysymData) {
- .keycodes = keycodes,
- .keysym = keysym,
- .layout = layout->index,
- .level = layout_level
- };
- xkb_keymap_key_for_each (layout->keymap,
- get_keycodes_for_keysym_iter,
- &search_data);
- }
-}
-
-/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
- * gdkkeys-x11.c */
-static void
-get_keycodes_for_keysym (MetaKeyBindingManager *keys,
- int keysym,
- MetaResolvedKeyCombo *resolved_combo)
-{
- unsigned int i;
- GArray *keycodes;
- int keycode;
-
- keycodes = g_array_new (FALSE, FALSE, sizeof (xkb_keysym_t));
-
- /* Special-case: Fake mutter keysym */
- if (keysym == META_KEY_ABOVE_TAB)
- {
- keycode = KEY_GRAVE + 8;
- g_array_append_val (keycodes, keycode);
- goto out;
- }
-
- for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++)
- {
- MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i];
-
- if (!layout->keymap)
- continue;
-
- add_keysym_keycodes_from_layout (keysym, layout, keycodes);
- }
-
- out:
- resolved_combo->len = keycodes->len;
- resolved_combo->keycodes =
- (xkb_keycode_t *) g_array_free (keycodes,
- keycodes->len == 0 ? TRUE : FALSE);
-}
-
-typedef struct _CalculateLayoutLevelsState
-{
- struct xkb_keymap *keymap;
- xkb_layout_index_t layout_index;
-
- xkb_level_index_t out_n_levels;
-} CalculateLayoutLevelState;
-
-static void
-calculate_n_layout_levels_iter (struct xkb_keymap *keymap,
- xkb_keycode_t keycode,
- void *data)
-{
- CalculateLayoutLevelState *state = data;
- xkb_level_index_t n_levels;
-
- n_levels = xkb_keymap_num_levels_for_key (keymap,
- keycode,
- state->layout_index);
-
- state->out_n_levels = MAX (n_levels, state->out_n_levels);
-}
-
-static xkb_level_index_t
-calculate_n_layout_levels (struct xkb_keymap *keymap,
- xkb_layout_index_t layout_index)
-
-{
- CalculateLayoutLevelState state = {
- .keymap = keymap,
- .layout_index = layout_index,
-
- .out_n_levels = 0
- };
-
- xkb_keymap_key_for_each (keymap, calculate_n_layout_levels_iter, &state);
-
- return state.out_n_levels;
-}
-
-static void
-reload_iso_next_group_combos (MetaKeyBindingManager *keys)
-{
- const char *iso_next_group_option;
- int i;
-
- for (i = 0; i < keys->n_iso_next_group_combos; i++)
- resolved_key_combo_reset (&keys->iso_next_group_combo[i]);
-
- keys->n_iso_next_group_combos = 0;
-
- iso_next_group_option = meta_prefs_get_iso_next_group_option ();
- if (iso_next_group_option == NULL)
- return;
-
- get_keycodes_for_keysym (keys, XKB_KEY_ISO_Next_Group, keys->iso_next_group_combo);
-
- if (keys->iso_next_group_combo[0].len == 0)
- return;
-
- keys->n_iso_next_group_combos = 1;
-
- if (g_str_equal (iso_next_group_option, "toggle") ||
- g_str_equal (iso_next_group_option, "lalt_toggle") ||
- g_str_equal (iso_next_group_option, "lwin_toggle") ||
- g_str_equal (iso_next_group_option, "rwin_toggle") ||
- g_str_equal (iso_next_group_option, "lshift_toggle") ||
- g_str_equal (iso_next_group_option, "rshift_toggle") ||
- g_str_equal (iso_next_group_option, "lctrl_toggle") ||
- g_str_equal (iso_next_group_option, "rctrl_toggle") ||
- g_str_equal (iso_next_group_option, "sclk_toggle") ||
- g_str_equal (iso_next_group_option, "menu_toggle") ||
- g_str_equal (iso_next_group_option, "caps_toggle"))
- {
- keys->iso_next_group_combo[0].mask = 0;
- }
- else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
- g_str_equal (iso_next_group_option, "shifts_toggle"))
- {
- keys->iso_next_group_combo[0].mask = ShiftMask;
- }
- else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
- g_str_equal (iso_next_group_option, "alt_space_toggle"))
- {
- keys->iso_next_group_combo[0].mask = Mod1Mask;
- }
- else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
- g_str_equal (iso_next_group_option, "lctrl_lshift_toggle") ||
- g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
- {
- resolved_key_combo_copy (&keys->iso_next_group_combo[0],
- &keys->iso_next_group_combo[1]);
-
- keys->iso_next_group_combo[0].mask = ShiftMask;
- keys->iso_next_group_combo[1].mask = ControlMask;
- keys->n_iso_next_group_combos = 2;
- }
- else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
- {
- resolved_key_combo_copy (&keys->iso_next_group_combo[0],
- &keys->iso_next_group_combo[1]);
-
- keys->iso_next_group_combo[0].mask = Mod1Mask;
- keys->iso_next_group_combo[1].mask = ControlMask;
- keys->n_iso_next_group_combos = 2;
- }
- else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
- g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
- {
- resolved_key_combo_copy (&keys->iso_next_group_combo[0],
- &keys->iso_next_group_combo[1]);
-
- keys->iso_next_group_combo[0].mask = Mod1Mask;
- keys->iso_next_group_combo[1].mask = ShiftMask;
- keys->n_iso_next_group_combos = 2;
- }
- else
- {
- resolved_key_combo_reset (keys->iso_next_group_combo);
- keys->n_iso_next_group_combos = 0;
- }
-}
-
-static void
-devirtualize_modifiers (MetaKeyBindingManager *keys,
- MetaVirtualModifier modifiers,
- unsigned int *mask)
-{
- *mask = 0;
-
- if (modifiers & META_VIRTUAL_SHIFT_MASK)
- *mask |= ShiftMask;
- if (modifiers & META_VIRTUAL_CONTROL_MASK)
- *mask |= ControlMask;
- if (modifiers & META_VIRTUAL_ALT_MASK)
- *mask |= Mod1Mask;
- if (modifiers & META_VIRTUAL_META_MASK)
- *mask |= keys->meta_mask;
- if (modifiers & META_VIRTUAL_HYPER_MASK)
- *mask |= keys->hyper_mask;
- if (modifiers & META_VIRTUAL_SUPER_MASK)
- *mask |= keys->super_mask;
- if (modifiers & META_VIRTUAL_MOD2_MASK)
- *mask |= Mod2Mask;
- if (modifiers & META_VIRTUAL_MOD3_MASK)
- *mask |= Mod3Mask;
- if (modifiers & META_VIRTUAL_MOD4_MASK)
- *mask |= Mod4Mask;
- if (modifiers & META_VIRTUAL_MOD5_MASK)
- *mask |= Mod5Mask;
-}
-
-static void
-index_binding (MetaKeyBindingManager *keys,
- MetaKeyBinding *binding)
-{
- int i;
-
- for (i = 0; i < binding->resolved_combo.len; i++)
- {
- MetaKeyBinding *existing;
- guint32 index_key;
-
- index_key = key_combo_key (&binding->resolved_combo, i);
-
- existing = g_hash_table_lookup (keys->key_bindings_index,
- GINT_TO_POINTER (index_key));
- if (existing != NULL)
- {
- /* Overwrite already indexed keycodes only for the first
- * keycode, i.e. we give those primary keycodes precedence
- * over non-first ones. */
- if (i > 0)
- continue;
-
- meta_warning ("Overwriting existing binding of keysym %x"
- " with keysym %x (keycode %x).",
- binding->combo.keysym,
- existing->combo.keysym,
- binding->resolved_combo.keycodes[i]);
- }
-
- g_hash_table_replace (keys->key_bindings_index,
- GINT_TO_POINTER (index_key), binding);
- }
-}
-
-static void
-resolve_key_combo (MetaKeyBindingManager *keys,
- MetaKeyCombo *combo,
- MetaResolvedKeyCombo *resolved_combo)
-{
-
- resolved_key_combo_reset (resolved_combo);
-
- if (combo->keysym != 0)
- {
- get_keycodes_for_keysym (keys, combo->keysym, resolved_combo);
- }
- else if (combo->keycode != 0)
- {
- resolved_combo->keycodes = g_new0 (xkb_keycode_t, 1);
- resolved_combo->keycodes[0] = combo->keycode;
- resolved_combo->len = 1;
- }
-
- devirtualize_modifiers (keys, combo->modifiers, &resolved_combo->mask);
-}
-
-static void
-binding_reload_combos_foreach (gpointer key,
- gpointer value,
- gpointer data)
-{
- MetaKeyBindingManager *keys = data;
- MetaKeyBinding *binding = value;
-
- resolve_key_combo (keys, &binding->combo, &binding->resolved_combo);
- index_binding (keys, binding);
-}
-
-typedef struct _FindLatinKeysymsState
-{
- MetaKeyBindingKeyboardLayout *layout;
- gboolean *required_keysyms_found;
- int n_required_keysyms;
-} FindLatinKeysymsState;
-
-static void
-find_latin_keysym (struct xkb_keymap *keymap,
- xkb_keycode_t key,
- void *data)
-{
- FindLatinKeysymsState *state = data;
- int n_keysyms, i;
- const xkb_keysym_t *keysyms;
-
- n_keysyms = xkb_keymap_key_get_syms_by_level (state->layout->keymap,
- key,
- state->layout->index,
- 0,
- &keysyms);
- for (i = 0; i < n_keysyms; i++)
- {
- xkb_keysym_t keysym = keysyms[i];
-
- if (keysym >= XKB_KEY_a && keysym <= XKB_KEY_z)
- {
- unsigned int keysym_index = keysym - XKB_KEY_a;
-
- if (!state->required_keysyms_found[keysym_index])
- {
- state->required_keysyms_found[keysym_index] = TRUE;
- state->n_required_keysyms--;
- }
- }
- }
-}
-
-static gboolean
-needs_secondary_layout (MetaKeyBindingKeyboardLayout *layout)
-{
- gboolean required_keysyms_found[] = {
- FALSE, /* XKB_KEY_a */
- FALSE, /* XKB_KEY_b */
- FALSE, /* XKB_KEY_c */
- FALSE, /* XKB_KEY_d */
- FALSE, /* XKB_KEY_e */
- FALSE, /* XKB_KEY_f */
- FALSE, /* XKB_KEY_g */
- FALSE, /* XKB_KEY_h */
- FALSE, /* XKB_KEY_i */
- FALSE, /* XKB_KEY_j */
- FALSE, /* XKB_KEY_k */
- FALSE, /* XKB_KEY_l */
- FALSE, /* XKB_KEY_m */
- FALSE, /* XKB_KEY_n */
- FALSE, /* XKB_KEY_o */
- FALSE, /* XKB_KEY_p */
- FALSE, /* XKB_KEY_q */
- FALSE, /* XKB_KEY_r */
- FALSE, /* XKB_KEY_s */
- FALSE, /* XKB_KEY_t */
- FALSE, /* XKB_KEY_u */
- FALSE, /* XKB_KEY_v */
- FALSE, /* XKB_KEY_w */
- FALSE, /* XKB_KEY_x */
- FALSE, /* XKB_KEY_y */
- FALSE, /* XKB_KEY_z */
- };
- FindLatinKeysymsState state = {
- .layout = layout,
- .required_keysyms_found = required_keysyms_found,
- .n_required_keysyms = G_N_ELEMENTS (required_keysyms_found),
- };
-
- xkb_keymap_key_for_each (layout->keymap, find_latin_keysym, &state);
-
- return state.n_required_keysyms != 0;
-}
-
-static void
-clear_active_keyboard_layouts (MetaKeyBindingManager *keys)
-{
- unsigned int i;
-
- for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++)
- {
- MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i];
-
- g_clear_pointer (&layout->keymap, xkb_keymap_unref);
- *layout = (MetaKeyBindingKeyboardLayout) { 0 };
- }
-}
-
-static MetaKeyBindingKeyboardLayout
-create_us_layout (void)
-{
- struct xkb_rule_names names;
- struct xkb_keymap *keymap;
- struct xkb_context *context;
-
- names.rules = DEFAULT_XKB_RULES_FILE;
- names.model = DEFAULT_XKB_MODEL;
- names.layout = "us";
- names.variant = "";
- names.options = "";
-
- context = meta_create_xkb_context ();
- keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
- xkb_context_unref (context);
-
- return (MetaKeyBindingKeyboardLayout) {
- .keymap = keymap,
- .n_levels = calculate_n_layout_levels (keymap, 0),
- };
-}
-
-static void
-reload_active_keyboard_layouts (MetaKeyBindingManager *keys)
-{
- struct xkb_keymap *keymap;
- xkb_layout_index_t layout_index;
- MetaKeyBindingKeyboardLayout primary_layout;
-
- clear_active_keyboard_layouts (keys);
-
- keymap = meta_backend_get_keymap (keys->backend);
- layout_index = meta_backend_get_keymap_layout_group (keys->backend);
- primary_layout = (MetaKeyBindingKeyboardLayout) {
- .keymap = xkb_keymap_ref (keymap),
- .index = layout_index,
- .n_levels = calculate_n_layout_levels (keymap, layout_index),
- };
-
- keys->active_layouts[META_KEY_BINDING_PRIMARY_LAYOUT] = primary_layout;
-
- if (needs_secondary_layout (&primary_layout))
- {
- MetaKeyBindingKeyboardLayout us_layout;
-
- us_layout = create_us_layout ();
- keys->active_layouts[META_KEY_BINDING_SECONDARY_LAYOUT] = us_layout;
- }
-}
-
-static void
-reload_combos (MetaKeyBindingManager *keys)
-{
- g_hash_table_remove_all (keys->key_bindings_index);
-
- reload_active_keyboard_layouts (keys);
-
- resolve_key_combo (keys,
- &keys->overlay_key_combo,
- &keys->overlay_resolved_key_combo);
-
- resolve_key_combo (keys,
- &keys->locate_pointer_key_combo,
- &keys->locate_pointer_resolved_key_combo);
-
- reload_iso_next_group_combos (keys);
-
- g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys);
-}
-
-static void
-rebuild_binding_table (MetaKeyBindingManager *keys,
- GList *prefs,
- GList *grabs)
-{
- MetaKeyBinding *b;
- GList *p, *g;
-
- g_hash_table_remove_all (keys->key_bindings);
-
- p = prefs;
- while (p)
- {
- MetaKeyPref *pref = (MetaKeyPref*)p->data;
- GSList *tmp = pref->combos;
-
- while (tmp)
- {
- MetaKeyCombo *combo = tmp->data;
-
- if (combo && (combo->keysym != None || combo->keycode != 0))
- {
- MetaKeyHandler *handler = HANDLER (pref->name);
-
- b = g_new0 (MetaKeyBinding, 1);
- b->name = pref->name;
- b->handler = handler;
- b->flags = handler->flags;
- b->combo = *combo;
-
- g_hash_table_add (keys->key_bindings, b);
- }
-
- tmp = tmp->next;
- }
-
- p = p->next;
- }
-
- g = grabs;
- while (g)
- {
- MetaKeyGrab *grab = (MetaKeyGrab*)g->data;
- if (grab->combo.keysym != None || grab->combo.keycode != 0)
- {
- MetaKeyHandler *handler = HANDLER ("external-grab");
-
- b = g_new0 (MetaKeyBinding, 1);
- b->name = grab->name;
- b->handler = handler;
- b->flags = grab->flags;
- b->combo = grab->combo;
-
- g_hash_table_add (keys->key_bindings, b);
- }
-
- g = g->next;
- }
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- " %d bindings in table",
- g_hash_table_size (keys->key_bindings));
-}
-
-static void
-rebuild_key_binding_table (MetaKeyBindingManager *keys)
-{
- GList *prefs, *grabs;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Rebuilding key binding table from preferences");
-
- prefs = meta_prefs_get_keybindings ();
- grabs = g_hash_table_get_values (external_grabs);
- rebuild_binding_table (keys, prefs, grabs);
- g_list_free (prefs);
- g_list_free (grabs);
-}
-
-static void
-rebuild_special_bindings (MetaKeyBindingManager *keys)
-{
- MetaKeyCombo combo;
-
- meta_prefs_get_overlay_binding (&combo);
- keys->overlay_key_combo = combo;
-
- meta_prefs_get_locate_pointer_binding (&combo);
- keys->locate_pointer_key_combo = combo;
-}
-
-static void
-ungrab_key_bindings (MetaDisplay *display)
-{
- GSList *windows, *l;
-
- if (display->x11_display)
- meta_x11_display_ungrab_keys (display->x11_display);
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_window_ungrab_keys (w);
- }
-
- g_slist_free (windows);
-}
-
-static void
-grab_key_bindings (MetaDisplay *display)
-{
- GSList *windows, *l;
-
- if (display->x11_display)
- meta_x11_display_grab_keys (display->x11_display);
-
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_window_grab_keys (w);
- }
-
- g_slist_free (windows);
-}
-
-static MetaKeyBinding *
-get_keybinding (MetaKeyBindingManager *keys,
- MetaResolvedKeyCombo *resolved_combo)
-{
- MetaKeyBinding *binding = NULL;
- int i;
-
- for (i = 0; i < resolved_combo->len; i++)
- {
- guint32 key;
-
- key = key_combo_key (resolved_combo, i);
- binding = g_hash_table_lookup (keys->key_bindings_index,
- GINT_TO_POINTER (key));
-
- if (binding != NULL)
- break;
- }
-
- return binding;
-}
-
-static guint
-next_dynamic_keybinding_action (void)
-{
- static guint num_dynamic_bindings = 0;
- return META_KEYBINDING_ACTION_LAST + (++num_dynamic_bindings);
-}
-
-static gboolean
-add_keybinding_internal (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyBindingAction action,
- MetaKeyHandlerFunc func,
- int data,
- gpointer user_data,
- GDestroyNotify free_data)
-{
- MetaKeyHandler *handler;
-
- if (!meta_prefs_add_keybinding (name, settings, action, flags))
- return FALSE;
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup (name);
- handler->func = func;
- handler->default_func = func;
- handler->data = data;
- handler->flags = flags;
- handler->user_data = user_data;
- handler->user_data_free_func = free_data;
-
- g_hash_table_insert (key_handlers, g_strdup (name), handler);
-
- return TRUE;
-}
-
-static gboolean
-add_builtin_keybinding (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyBindingAction action,
- MetaKeyHandlerFunc handler,
- int handler_arg)
-{
- return add_keybinding_internal (display, name, settings,
- flags | META_KEY_BINDING_BUILTIN,
- action, handler, handler_arg, NULL, NULL);
-}
-
-/**
- * meta_display_add_keybinding:
- * @display: a #MetaDisplay
- * @name: the binding's name
- * @settings: the #GSettings object where @name is stored
- * @flags: flags to specify binding details
- * @handler: function to run when the keybinding is invoked
- * @user_data: the data to pass to @handler
- * @free_data: function to free @user_data
- *
- * Add a keybinding at runtime. The key @name in @schema needs to be of
- * type %G_VARIANT_TYPE_STRING_ARRAY, with each string describing a
- * keybinding in the form of "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1". The parser
- * is fairly liberal and allows lower or upper case, and also abbreviations
- * such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If the key is set to the empty list or a
- * list with a single element of either "" or "disabled", the keybinding is
- * disabled.
- *
- * Use meta_display_remove_keybinding() to remove the binding.
- *
- * Returns: the corresponding keybinding action if the keybinding was
- * added successfully, otherwise %META_KEYBINDING_ACTION_NONE
- */
-guint
-meta_display_add_keybinding (MetaDisplay *display,
- const char *name,
- GSettings *settings,
- MetaKeyBindingFlags flags,
- MetaKeyHandlerFunc handler,
- gpointer user_data,
- GDestroyNotify free_data)
-{
- guint new_action = next_dynamic_keybinding_action ();
-
- if (!add_keybinding_internal (display, name, settings, flags, new_action,
- handler, 0, user_data, free_data))
- return META_KEYBINDING_ACTION_NONE;
-
- return new_action;
-}
-
-/**
- * meta_display_remove_keybinding:
- * @display: the #MetaDisplay
- * @name: name of the keybinding to remove
- *
- * Remove keybinding @name; the function will fail if @name is not a known
- * keybinding or has not been added with meta_display_add_keybinding().
- *
- * Returns: %TRUE if the binding has been removed successfully,
- * otherwise %FALSE
- */
-gboolean
-meta_display_remove_keybinding (MetaDisplay *display,
- const char *name)
-{
- if (!meta_prefs_remove_keybinding (name))
- return FALSE;
-
- g_hash_table_remove (key_handlers, name);
-
- return TRUE;
-}
-
-static guint
-get_keybinding_action (MetaKeyBindingManager *keys,
- MetaResolvedKeyCombo *resolved_combo)
-{
- MetaKeyBinding *binding;
-
- /* This is much more vague than the MetaDisplay::overlay-key signal,
- * which is only emitted if the overlay-key is the only key pressed;
- * as this method is primarily intended for plugins to allow processing
- * of mutter keybindings while holding a grab, the overlay-key-only-pressed
- * tracking is left to the plugin here.
- */
- if (resolved_key_combo_intersect (resolved_combo,
- &keys->overlay_resolved_key_combo))
- return META_KEYBINDING_ACTION_OVERLAY_KEY;
-
- if (resolved_key_combo_intersect (resolved_combo,
- &keys->locate_pointer_resolved_key_combo))
- return META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
-
- binding = get_keybinding (keys, resolved_combo);
- if (binding)
- {
- MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name);
- if (grab)
- return grab->action;
- else
- return (guint) meta_prefs_get_keybinding_action (binding->name);
- }
- else
- {
- return META_KEYBINDING_ACTION_NONE;
- }
-}
-
-static xkb_mod_mask_t
-mask_from_event_params (MetaKeyBindingManager *keys,
- unsigned long mask)
-{
- return mask & 0xff & ~keys->ignored_modifier_mask;
-}
-
-/**
- * meta_display_get_keybinding_action:
- * @display: A #MetaDisplay
- * @keycode: Raw keycode
- * @mask: Event mask
- *
- * Get the keybinding action bound to @keycode. Builtin keybindings
- * have a fixed associated #MetaKeyBindingAction, for bindings added
- * dynamically the function will return the keybinding action
- * meta_display_add_keybinding() returns on registration.
- *
- * Returns: The action that should be taken for the given key, or
- * %META_KEYBINDING_ACTION_NONE.
- */
-guint
-meta_display_get_keybinding_action (MetaDisplay *display,
- unsigned int keycode,
- unsigned long mask)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- xkb_keycode_t code = (xkb_keycode_t) keycode;
- MetaResolvedKeyCombo resolved_combo = { &code, 1 };
-
- resolved_combo.mask = mask_from_event_params (keys, mask);
- return get_keybinding_action (keys, &resolved_combo);
-}
-
-static void
-reload_keybindings (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- ungrab_key_bindings (display);
-
- /* Deciphering the modmap depends on the loaded keysyms to find out
- * what modifiers is Super and so forth, so we need to reload it
- * even when only the keymap changes */
- reload_modmap (keys);
-
- reload_combos (keys);
-
- grab_key_bindings (display);
-}
-
-static GArray *
-calc_grab_modifiers (MetaKeyBindingManager *keys,
- unsigned int modmask)
-{
- unsigned int ignored_mask;
- XIGrabModifiers mods;
- GArray *mods_array = g_array_new (FALSE, TRUE, sizeof (XIGrabModifiers));
-
- /* The X server crashes if XIAnyModifier gets passed in with any
- other bits. It doesn't make sense to ask for a grab of
- XIAnyModifier plus other bits anyway so we avoid that. */
- if (modmask & XIAnyModifier)
- {
- mods = (XIGrabModifiers) { XIAnyModifier, 0 };
- g_array_append_val (mods_array, mods);
- return mods_array;
- }
-
- mods = (XIGrabModifiers) { modmask, 0 };
- g_array_append_val (mods_array, mods);
-
- for (ignored_mask = 1;
- ignored_mask <= keys->ignored_modifier_mask;
- ++ignored_mask)
- {
- if (ignored_mask & keys->ignored_modifier_mask)
- {
- mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
- g_array_append_val (mods_array, mods);
- }
- }
-
- return mods_array;
-}
-
-static void
-meta_change_button_grab (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab,
- gboolean sync,
- int button,
- int modmask)
-{
- if (meta_is_wayland_compositor ())
- return;
-
- MetaBackendX11 *backend = META_BACKEND_X11 (keys->backend);
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
-
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
- GArray *mods;
-
- XISetMask (mask.mask, XI_ButtonPress);
- XISetMask (mask.mask, XI_ButtonRelease);
- XISetMask (mask.mask, XI_Motion);
-
- mods = calc_grab_modifiers (keys, modmask);
-
- /* GrabModeSync means freeze until XAllowEvents */
- if (grab)
- XIGrabButton (xdisplay,
- META_VIRTUAL_CORE_POINTER_ID,
- button, xwindow, None,
- sync ? XIGrabModeSync : XIGrabModeAsync,
- XIGrabModeAsync, False,
- &mask, mods->len, (XIGrabModifiers *)mods->data);
- else
- XIUngrabButton (xdisplay,
- META_VIRTUAL_CORE_POINTER_ID,
- button, xwindow, mods->len, (XIGrabModifiers *)mods->data);
-
- g_array_free (mods, TRUE);
-}
-
-ClutterModifierType
-meta_display_get_compositor_modifiers (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- return keys->window_grab_modifiers;
-}
-
-static void
-meta_change_buttons_grab (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab,
- gboolean sync,
- int modmask)
-{
-#define MAX_BUTTON 3
-
- int i;
- for (i = 1; i <= MAX_BUTTON; i++)
- meta_change_button_grab (keys, xwindow, grab, sync, i, modmask);
-}
-
-void
-meta_display_grab_window_buttons (MetaDisplay *display,
- Window xwindow)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- /* Grab Alt + button1 for moving window.
- * Grab Alt + button2 for resizing window.
- * Grab Alt + button3 for popping up window menu.
- * Grab Alt + Shift + button1 for snap-moving window.
- */
- meta_verbose ("Grabbing window buttons for 0x%lx", xwindow);
-
- /* FIXME If we ignored errors here instead of spewing, we could
- * put one big error trap around the loop and avoid a bunch of
- * XSync()
- */
-
- if (keys->window_grab_modifiers != 0)
- {
- meta_change_buttons_grab (keys, xwindow, TRUE, FALSE,
- keys->window_grab_modifiers);
-
- /* In addition to grabbing Alt+Button1 for moving the window,
- * grab Alt+Shift+Button1 for snap-moving the window. See bug
- * 112478. Unfortunately, this doesn't work with
- * Shift+Alt+Button1 for some reason; so at least part of the
- * order still matters, which sucks (please FIXME).
- */
- meta_change_button_grab (keys, xwindow,
- TRUE,
- FALSE,
- 1, keys->window_grab_modifiers | ShiftMask);
- }
-}
-
-void
-meta_display_ungrab_window_buttons (MetaDisplay *display,
- Window xwindow)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (keys->window_grab_modifiers == 0)
- return;
-
- meta_change_buttons_grab (keys, xwindow, FALSE, FALSE,
- keys->window_grab_modifiers);
-}
-
-static void
-update_window_grab_modifiers (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaVirtualModifier virtual_mods;
- unsigned int mods;
-
- virtual_mods = meta_prefs_get_mouse_button_mods ();
- devirtualize_modifiers (keys, virtual_mods, &mods);
-
- if (keys->window_grab_modifiers != mods)
- {
- keys->window_grab_modifiers = mods;
- g_object_notify (G_OBJECT (display), "compositor-modifiers");
- }
-}
-
-void
-meta_display_grab_focus_window_button (MetaDisplay *display,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- /* Grab button 1 for activating unfocused windows */
- meta_verbose ("Grabbing unfocused window buttons for %s", window->desc);
-
- if (window->have_focus_click_grab)
- {
- meta_verbose (" (well, not grabbing since we already have the grab)");
- return;
- }
-
- /* FIXME If we ignored errors here instead of spewing, we could
- * put one big error trap around the loop and avoid a bunch of
- * XSync()
- */
-
- meta_change_buttons_grab (keys, window->xwindow, TRUE, TRUE, XIAnyModifier);
- window->have_focus_click_grab = TRUE;
-}
-
-void
-meta_display_ungrab_focus_window_button (MetaDisplay *display,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- meta_verbose ("Ungrabbing unfocused window buttons for %s", window->desc);
-
- if (!window->have_focus_click_grab)
- return;
-
- meta_change_buttons_grab (keys, window->xwindow, FALSE, FALSE, XIAnyModifier);
- window->have_focus_click_grab = FALSE;
-}
-
-static void
-prefs_changed_callback (MetaPreference pref,
- void *data)
-{
- MetaDisplay *display = data;
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- switch (pref)
- {
- case META_PREF_LOCATE_POINTER:
- maybe_update_locate_pointer_keygrab (display,
- meta_prefs_is_locate_pointer_enabled());
- break;
- case META_PREF_KEYBINDINGS:
- ungrab_key_bindings (display);
- rebuild_key_binding_table (keys);
- rebuild_special_bindings (keys);
- reload_combos (keys);
- grab_key_bindings (display);
- break;
- case META_PREF_MOUSE_BUTTON_MODS:
- {
- GSList *windows, *l;
- windows = meta_display_list_windows (display, META_LIST_DEFAULT);
-
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_display_ungrab_window_buttons (display, w->xwindow);
- }
-
- update_window_grab_modifiers (display);
-
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
- if (w->type != META_WINDOW_DOCK)
- meta_display_grab_window_buttons (display, w->xwindow);
- }
-
- g_slist_free (windows);
- }
- default:
- break;
- }
-}
-
-
-void
-meta_display_shutdown_keys (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- meta_prefs_remove_listener (prefs_changed_callback, display);
-
- g_hash_table_destroy (keys->key_bindings_index);
- g_hash_table_destroy (keys->key_bindings);
-
- clear_active_keyboard_layouts (keys);
-}
-
-/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
-static void
-meta_change_keygrab (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab,
- MetaResolvedKeyCombo *resolved_combo)
-{
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
- XISetMask (mask.mask, XI_KeyPress);
- XISetMask (mask.mask, XI_KeyRelease);
-
- if (meta_is_wayland_compositor ())
- return;
-
- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
- GArray *mods;
- int i;
-
- /* Grab keycode/modmask, together with
- * all combinations of ignored modifiers.
- * X provides no better way to do this.
- */
-
- mods = calc_grab_modifiers (keys, resolved_combo->mask);
-
- for (i = 0; i < resolved_combo->len; i++)
- {
- xkb_keycode_t keycode = resolved_combo->keycodes[i];
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "%s keybinding keycode %d mask 0x%x on 0x%lx",
- grab ? "Grabbing" : "Ungrabbing",
- keycode, resolved_combo->mask, xwindow);
-
- if (grab)
- XIGrabKeycode (xdisplay,
- META_VIRTUAL_CORE_KEYBOARD_ID,
- keycode, xwindow,
- XIGrabModeSync, XIGrabModeAsync,
- False, &mask, mods->len, (XIGrabModifiers *)mods->data);
- else
- XIUngrabKeycode (xdisplay,
- META_VIRTUAL_CORE_KEYBOARD_ID,
- keycode, xwindow,
- mods->len, (XIGrabModifiers *)mods->data);
- }
-
- g_array_free (mods, TRUE);
-}
-
-typedef struct
-{
- MetaKeyBindingManager *keys;
- Window xwindow;
- gboolean only_per_window;
- gboolean grab;
-} ChangeKeygrabData;
-
-static void
-change_keygrab_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- ChangeKeygrabData *data = user_data;
- MetaKeyBinding *binding = value;
- gboolean binding_is_per_window = (binding->flags & META_KEY_BINDING_PER_WINDOW) != 0;
-
- if (data->only_per_window != binding_is_per_window)
- return;
-
- /* Ignore the key bindings marked as META_KEY_BINDING_NO_AUTO_GRAB,
- * those are handled separately
- */
- if (binding->flags & META_KEY_BINDING_NO_AUTO_GRAB)
- return;
-
- if (binding->resolved_combo.len == 0)
- return;
-
- meta_change_keygrab (data->keys, data->xwindow, data->grab, &binding->resolved_combo);
-}
-
-static void
-change_binding_keygrabs (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean only_per_window,
- gboolean grab)
-{
- ChangeKeygrabData data;
-
- data.keys = keys;
- data.xwindow = xwindow;
- data.only_per_window = only_per_window;
- data.grab = grab;
-
- g_hash_table_foreach (keys->key_bindings, change_keygrab_foreach, &data);
-}
-
-static void
-maybe_update_locate_pointer_keygrab (MetaDisplay *display,
- gboolean grab)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (!display->x11_display)
- return;
-
- if (keys->locate_pointer_resolved_key_combo.len != 0)
- meta_change_keygrab (keys, display->x11_display->xroot,
- (!!grab & !!meta_prefs_is_locate_pointer_enabled()),
- &keys->locate_pointer_resolved_key_combo);
-}
-
-static void
-meta_x11_display_change_keygrabs (MetaX11Display *x11_display,
- gboolean grab)
-{
- MetaKeyBindingManager *keys = &x11_display->display->key_binding_manager;
- int i;
-
- if (keys->overlay_resolved_key_combo.len != 0)
- meta_change_keygrab (keys, x11_display->xroot,
- grab, &keys->overlay_resolved_key_combo);
-
- maybe_update_locate_pointer_keygrab (x11_display->display, grab);
-
- for (i = 0; i < keys->n_iso_next_group_combos; i++)
- meta_change_keygrab (keys, x11_display->xroot,
- grab, &keys->iso_next_group_combo[i]);
-
- change_binding_keygrabs (keys, x11_display->xroot,
- FALSE, grab);
-}
-
-void
-meta_x11_display_grab_keys (MetaX11Display *x11_display)
-{
- if (x11_display->keys_grabbed)
- return;
-
- meta_x11_display_change_keygrabs (x11_display, TRUE);
-
- x11_display->keys_grabbed = TRUE;
-}
-
-void
-meta_x11_display_ungrab_keys (MetaX11Display *x11_display)
-{
- if (!x11_display->keys_grabbed)
- return;
-
- meta_x11_display_change_keygrabs (x11_display, FALSE);
-
- x11_display->keys_grabbed = FALSE;
-}
-
-static void
-change_window_keygrabs (MetaKeyBindingManager *keys,
- Window xwindow,
- gboolean grab)
-{
- change_binding_keygrabs (keys, xwindow, TRUE, grab);
-}
-
-void
-meta_window_grab_keys (MetaWindow *window)
-{
- MetaDisplay *display = window->display;
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (meta_is_wayland_compositor ())
- return;
- if (window->all_keys_grabbed)
- return;
-
- if (window->type == META_WINDOW_DOCK
- || window->override_redirect)
- {
- if (window->keys_grabbed)
- change_window_keygrabs (keys, window->xwindow, FALSE);
- window->keys_grabbed = FALSE;
- return;
- }
-
- if (window->keys_grabbed)
- {
- if (window->frame && !window->grab_on_frame)
- change_window_keygrabs (keys, window->xwindow, FALSE);
- else if (window->frame == NULL &&
- window->grab_on_frame)
- ; /* continue to regrab on client window */
- else
- return; /* already all good */
- }
-
- change_window_keygrabs (keys,
- meta_window_x11_get_toplevel_xwindow (window),
- TRUE);
-
- window->keys_grabbed = TRUE;
- window->grab_on_frame = window->frame != NULL;
-}
-
-void
-meta_window_ungrab_keys (MetaWindow *window)
-{
- if (!meta_is_wayland_compositor () && window->keys_grabbed)
- {
- MetaDisplay *display = window->display;
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (window->grab_on_frame &&
- window->frame != NULL)
- change_window_keygrabs (keys, window->frame->xwindow, FALSE);
- else if (!window->grab_on_frame)
- change_window_keygrabs (keys, window->xwindow, FALSE);
-
- window->keys_grabbed = FALSE;
- }
-}
-
-static void
-handle_external_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer user_data)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- guint action = get_keybinding_action (keys, &binding->resolved_combo);
- meta_display_accelerator_activate (display, action, event);
-}
-
-
-guint
-meta_display_grab_accelerator (MetaDisplay *display,
- const char *accelerator,
- MetaKeyBindingFlags flags)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaKeyBinding *binding;
- MetaKeyGrab *grab;
- MetaKeyCombo combo = { 0 };
- MetaResolvedKeyCombo resolved_combo = { NULL, 0 };
-
- if (!meta_parse_accelerator (accelerator, &combo))
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Failed to parse accelerator");
- meta_warning ("\"%s\" is not a valid accelerator", accelerator);
-
- return META_KEYBINDING_ACTION_NONE;
- }
-
- resolve_key_combo (keys, &combo, &resolved_combo);
-
- if (resolved_combo.len == 0)
- return META_KEYBINDING_ACTION_NONE;
-
- if (get_keybinding (keys, &resolved_combo))
- {
- resolved_key_combo_reset (&resolved_combo);
- return META_KEYBINDING_ACTION_NONE;
- }
-
- if (!meta_is_wayland_compositor ())
- {
- meta_change_keygrab (keys, display->x11_display->xroot,
- TRUE, &resolved_combo);
- }
-
- grab = g_new0 (MetaKeyGrab, 1);
- grab->action = next_dynamic_keybinding_action ();
- grab->name = meta_external_binding_name_for_action (grab->action);
- grab->combo = combo;
- grab->flags = flags;
-
- g_hash_table_insert (external_grabs, grab->name, grab);
-
- binding = g_new0 (MetaKeyBinding, 1);
- binding->name = grab->name;
- binding->handler = HANDLER ("external-grab");
- binding->combo = combo;
- binding->resolved_combo = resolved_combo;
- binding->flags = flags;
-
- g_hash_table_add (keys->key_bindings, binding);
- index_binding (keys, binding);
-
- return grab->action;
-}
-
-gboolean
-meta_display_ungrab_accelerator (MetaDisplay *display,
- guint action)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaKeyBinding *binding;
- MetaKeyGrab *grab;
- g_autofree char *key = NULL;
- MetaResolvedKeyCombo resolved_combo = { NULL, 0 };
-
- g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE);
-
- key = meta_external_binding_name_for_action (action);
- grab = g_hash_table_lookup (external_grabs, key);
- if (!grab)
- return FALSE;
-
- resolve_key_combo (keys, &grab->combo, &resolved_combo);
- binding = get_keybinding (keys, &resolved_combo);
- if (binding)
- {
- int i;
-
- if (!meta_is_wayland_compositor ())
- {
- meta_change_keygrab (keys, display->x11_display->xroot,
- FALSE, &binding->resolved_combo);
- }
-
- for (i = 0; i < binding->resolved_combo.len; i++)
- {
- guint32 index_key = key_combo_key (&binding->resolved_combo, i);
- g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key));
- }
-
- g_hash_table_remove (keys->key_bindings, binding);
- }
-
- g_hash_table_remove (external_grabs, key);
- resolved_key_combo_reset (&resolved_combo);
-
- return TRUE;
-}
-
-static gboolean
-grab_keyboard (Window xwindow,
- guint32 timestamp,
- int grab_mode)
-{
- int grab_status;
-
- unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
- XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
-
- XISetMask (mask.mask, XI_KeyPress);
- XISetMask (mask.mask, XI_KeyRelease);
-
- if (meta_is_wayland_compositor ())
- return TRUE;
-
- /* Grab the keyboard, so we get key releases and all key
- * presses
- */
-
- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
-
- /* Strictly, we only need to set grab_mode on the keyboard device
- * while the pointer should always be XIGrabModeAsync. Unfortunately
- * there is a bug in the X server, only fixed (link below) in 1.15,
- * which swaps these arguments for keyboard devices. As such, we set
- * both the device and the paired device mode which works around
- * that bug and also works on fixed X servers.
- *
- * http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3
- */
- grab_status = XIGrabDevice (xdisplay,
- META_VIRTUAL_CORE_KEYBOARD_ID,
- xwindow,
- timestamp,
- None,
- grab_mode, grab_mode,
- False, /* owner_events */
- &mask);
-
- return (grab_status == Success);
-}
-
-static void
-ungrab_keyboard (guint32 timestamp)
-{
- if (meta_is_wayland_compositor ())
- return;
-
- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
- Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
-
- XIUngrabDevice (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
-}
-
-gboolean
-meta_window_grab_all_keys (MetaWindow *window,
- guint32 timestamp)
-{
- Window grabwindow;
- gboolean retval = TRUE;
-
- if (window->all_keys_grabbed)
- return FALSE;
-
- if (window->keys_grabbed)
- meta_window_ungrab_keys (window);
-
- /* Make sure the window is focused, otherwise the grab
- * won't do a lot of good.
- */
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s because we're grabbing all its keys",
- window->desc);
- meta_window_focus (window, timestamp);
-
- if (!meta_is_wayland_compositor ())
- {
- grabwindow = meta_window_x11_get_toplevel_xwindow (window);
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Grabbing all keys on window %s", window->desc);
- retval = grab_keyboard (grabwindow, timestamp, XIGrabModeAsync);
- }
- if (retval)
- {
- window->keys_grabbed = FALSE;
- window->all_keys_grabbed = TRUE;
- window->grab_on_frame = window->frame != NULL;
- }
-
- return retval;
-}
-
-void
-meta_window_ungrab_all_keys (MetaWindow *window,
- guint32 timestamp)
-{
- if (window->all_keys_grabbed)
- {
- if (!meta_is_wayland_compositor())
- ungrab_keyboard (timestamp);
-
- window->grab_on_frame = FALSE;
- window->all_keys_grabbed = FALSE;
- window->keys_grabbed = FALSE;
-
- /* Re-establish our standard bindings */
- meta_window_grab_keys (window);
- }
-}
-
-void
-meta_display_freeze_keyboard (MetaDisplay *display, guint32 timestamp)
-{
- MetaBackend *backend = meta_get_backend ();
-
- if (!META_IS_BACKEND_X11 (backend))
- return;
-
- Window window = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
- grab_keyboard (window, timestamp, XIGrabModeSync);
-}
-
-void
-meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
-{
- ungrab_keyboard (timestamp);
-}
-
-void
-meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
-{
- MetaBackend *backend = meta_get_backend ();
-
- if (!META_IS_BACKEND_X11 (backend))
- return;
-
- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
-
- XIAllowEvents (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
- XIAsyncDevice, timestamp);
- /* We shouldn't need to unfreeze the pointer device here, however we
- * have to, due to the workaround we do in grab_keyboard().
- */
- XIAllowEvents (xdisplay, META_VIRTUAL_CORE_POINTER_ID,
- XIAsyncDevice, timestamp);
-}
-
-static gboolean
-is_modifier (xkb_keysym_t keysym)
-{
- switch (keysym)
- {
- case XKB_KEY_Shift_L:
- case XKB_KEY_Shift_R:
- case XKB_KEY_Control_L:
- case XKB_KEY_Control_R:
- case XKB_KEY_Caps_Lock:
- case XKB_KEY_Shift_Lock:
- case XKB_KEY_Meta_L:
- case XKB_KEY_Meta_R:
- case XKB_KEY_Alt_L:
- case XKB_KEY_Alt_R:
- case XKB_KEY_Super_L:
- case XKB_KEY_Super_R:
- case XKB_KEY_Hyper_L:
- case XKB_KEY_Hyper_R:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static void
-invoke_handler (MetaDisplay *display,
- MetaKeyHandler *handler,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding)
-{
- if (handler->func)
- (* handler->func) (display,
- handler->flags & META_KEY_BINDING_PER_WINDOW ?
- window : NULL,
- event,
- binding,
- handler->user_data);
- else
- (* handler->default_func) (display,
- handler->flags & META_KEY_BINDING_PER_WINDOW ?
- window: NULL,
- event,
- binding,
- NULL);
-}
-
-static gboolean
-meta_key_binding_has_handler_func (MetaKeyBinding *binding)
-{
- return (!!binding->handler->func || !!binding->handler->default_func);
-}
-
-static gboolean
-process_event (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
- MetaResolvedKeyCombo resolved_combo = { &keycode, 1 };
- MetaKeyBinding *binding;
-
- /* we used to have release-based bindings but no longer. */
- if (event->type == CLUTTER_KEY_RELEASE)
- return FALSE;
-
- resolved_combo.mask = mask_from_event_params (keys, event->modifier_state);
-
- binding = get_keybinding (keys, &resolved_combo);
-
- if (!binding ||
- (!window && binding->flags & META_KEY_BINDING_PER_WINDOW))
- goto not_found;
-
- if (binding->handler == NULL)
- meta_bug ("Binding %s has no handler", binding->name);
-
- if (!meta_key_binding_has_handler_func (binding))
- goto not_found;
-
- if (display->focus_window &&
- !(binding->handler->flags & META_KEY_BINDING_NON_MASKABLE))
- {
- ClutterInputDevice *source;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
- if (meta_window_shortcuts_inhibited (display->focus_window, source))
- goto not_found;
- }
-
- /* If the compositor filtered out the keybindings, that
- * means they don't want the binding to trigger, so we do
- * the same thing as if the binding didn't exist. */
- if (meta_compositor_filter_keybinding (display->compositor, binding))
- goto not_found;
-
- if (event->flags & CLUTTER_EVENT_FLAG_REPEATED &&
- binding->flags & META_KEY_BINDING_IGNORE_AUTOREPEAT)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Ignore autorepeat for handler %s",
- binding->name);
- return TRUE;
- }
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Running handler for %s",
- binding->name);
-
- /* Global keybindings count as a let-the-terminal-lose-focus
- * due to new window mapping until the user starts
- * interacting with the terminal again.
- */
- display->allow_terminal_deactivation = TRUE;
-
- invoke_handler (display, binding->handler, window, event, binding);
-
- return TRUE;
-
- not_found:
- meta_topic (META_DEBUG_KEYBINDINGS,
- "No handler found for this event in this binding table");
- return FALSE;
-}
-
-static gboolean
-process_special_modifier_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window,
- gboolean *modifier_press_only,
- MetaResolvedKeyCombo *resolved_key_combo,
- GFunc trigger_callback)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaBackend *backend = keys->backend;
- Display *xdisplay;
-
- if (META_IS_BACKEND_X11 (backend))
- xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
- else
- xdisplay = NULL;
-
- if (*modifier_press_only)
- {
- if (! resolved_key_combo_has_keycode (resolved_key_combo,
- event->hardware_keycode))
- {
- *modifier_press_only = FALSE;
-
- /* If this is a wayland session, we can avoid the shenanigans
- * about passive grabs below, and let the event continue to
- * be processed through the regular paths.
- */
- if (!xdisplay)
- return FALSE;
-
- /* OK, the user hit modifier+key rather than pressing and
- * releasing the modifier key alone. We want to handle the key
- * sequence "normally". Unfortunately, using
- * XAllowEvents(..., ReplayKeyboard, ...) doesn't quite
- * work, since global keybindings won't be activated ("this
- * time, however, the function ignores any passive grabs at
- * above (toward the root of) the grab_window of the grab
- * just released.") So, we first explicitly check for one of
- * our global keybindings, and if not found, we then replay
- * the event. Other clients with global grabs will be out of
- * luck.
- */
- if (process_event (display, window, event))
- {
- /* As normally, after we've handled a global key
- * binding, we unfreeze the keyboard but keep the grab
- * (this is important for something like cycling
- * windows */
-
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
- }
- else
- {
- /* Replay the event so it gets delivered to our
- * per-window key bindings or to the application */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIReplayDevice, event->time);
- }
- }
- else if (event->type == CLUTTER_KEY_RELEASE)
- {
- MetaKeyBinding *binding;
-
- *modifier_press_only = FALSE;
-
- /* We want to unfreeze events, but keep the grab so that if the user
- * starts typing into the overlay we get all the keys */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
-
- binding = get_keybinding (keys, resolved_key_combo);
- if (binding &&
- meta_compositor_filter_keybinding (display->compositor, binding))
- return TRUE;
- trigger_callback (display, NULL);
- }
- else
- {
- /* In some rare race condition, mutter might not receive the Super_L
- * KeyRelease event because:
- * - the compositor might end the modal mode and call XIUngrabDevice
- * while the key is still down
- * - passive grabs are only activated on KeyPress and not KeyRelease.
- *
- * In this case, modifier_press_only might be wrong.
- * Mutter still ought to acknowledge events, otherwise the X server
- * will not send the next events.
- *
- * https://bugzilla.gnome.org/show_bug.cgi?id=666101
- */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
- }
-
- return TRUE;
- }
- else if (event->type == CLUTTER_KEY_PRESS &&
- ((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
- resolved_key_combo_has_keycode (resolved_key_combo,
- event->hardware_keycode))
- {
- *modifier_press_only = TRUE;
- /* We keep the keyboard frozen - this allows us to use ReplayKeyboard
- * on the next event if it's not the release of the modifier key */
- if (xdisplay)
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XISyncDevice, event->time);
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-
-static gboolean
-process_overlay_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- if (display->focus_window && !keys->overlay_key_only_pressed)
- {
- ClutterInputDevice *source;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
- if (meta_window_shortcuts_inhibited (display->focus_window, source))
- return FALSE;
- }
-
- return process_special_modifier_key (display,
- event,
- window,
- &keys->overlay_key_only_pressed,
- &keys->overlay_resolved_key_combo,
- (GFunc) meta_display_overlay_key_activate);
-}
-
-static void
-handle_locate_pointer (MetaDisplay *display)
-{
- meta_compositor_locate_pointer (display->compositor);
-}
-
-static gboolean
-process_locate_pointer_key (MetaDisplay *display,
- ClutterKeyEvent *event,
- MetaWindow *window)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- return process_special_modifier_key (display,
- event,
- window,
- &keys->locate_pointer_key_only_pressed,
- &keys->locate_pointer_resolved_key_combo,
- (GFunc) handle_locate_pointer);
-}
-
-static gboolean
-process_iso_next_group (MetaDisplay *display,
- ClutterKeyEvent *event)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- gboolean activate;
- xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode;
- xkb_mod_mask_t mask;
- int i, j;
-
- if (event->type == CLUTTER_KEY_RELEASE)
- return FALSE;
-
- activate = FALSE;
- mask = mask_from_event_params (keys, event->modifier_state);
-
- for (i = 0; i < keys->n_iso_next_group_combos; ++i)
- {
- for (j = 0; j < keys->iso_next_group_combo[i].len; ++j)
- {
- if (keycode == keys->iso_next_group_combo[i].keycodes[j] &&
- mask == keys->iso_next_group_combo[i].mask)
- {
- /* If the signal handler returns TRUE the keyboard will
- remain frozen. It's the signal handler's responsibility
- to unfreeze it. */
- if (!meta_display_modifiers_accelerator_activate (display))
- meta_display_unfreeze_keyboard (display, event->time);
- activate = TRUE;
- break;
- }
- }
- }
-
- return activate;
-}
-
-static gboolean
-process_key_event (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- gboolean keep_grab;
- gboolean all_keys_grabbed;
-
- all_keys_grabbed = window ? window->all_keys_grabbed : FALSE;
- if (!all_keys_grabbed)
- {
- if (process_overlay_key (display, event, window))
- return TRUE;
-
- if (process_locate_pointer_key (display, event, window))
- return FALSE; /* Continue with the event even if handled */
-
- if (process_iso_next_group (display, event))
- return TRUE;
- }
-
- {
- MetaBackend *backend = meta_get_backend ();
- if (META_IS_BACKEND_X11 (backend))
- {
- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
- XIAllowEvents (xdisplay,
- meta_input_device_x11_get_device_id (event->device),
- XIAsyncDevice, event->time);
- }
- }
-
- keep_grab = TRUE;
- if (all_keys_grabbed)
- {
- if (display->grab_op == META_GRAB_OP_NONE)
- return TRUE;
-
- /* If we get here we have a global grab, because
- * we're in some special keyboard mode such as window move
- * mode.
- */
- if (window == display->grab_window)
- {
- if (display->grab_op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD)
- {
- if (display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Processing event for keyboard move");
- keep_grab = process_keyboard_move_grab (display, window, event);
- }
- else
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Processing event for keyboard resize");
- keep_grab = process_keyboard_resize_grab (display, window, event);
- }
- }
- else
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Processing event for mouse-only move/resize");
- keep_grab = process_mouse_move_resize_grab (display, window, event);
- }
- }
- if (!keep_grab)
- meta_display_end_grab_op (display, event->time);
-
- return TRUE;
- }
-
- /* Do the normal keybindings */
- return process_event (display, window, event);
-}
-
-/* Handle a key event. May be called recursively: some key events cause
- * grabs to be ended and then need to be processed again in their own
- * right. This cannot cause infinite recursion because we never call
- * ourselves when there wasn't a grab, and we always clear the grab
- * first; the invariant is enforced using an assertion. See #112560.
- *
- * The return value is whether we handled the key event.
- *
- * FIXME: We need to prove there are no race conditions here.
- * FIXME: Does it correctly handle alt-Tab being followed by another
- * grabbing keypress without letting go of alt?
- * FIXME: An iterative solution would probably be simpler to understand
- * (and help us solve the other fixmes).
- */
-gboolean
-meta_keybindings_process_event (MetaDisplay *display,
- MetaWindow *window,
- const ClutterEvent *event)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
-
- switch (event->type)
- {
- case CLUTTER_BUTTON_PRESS:
- case CLUTTER_BUTTON_RELEASE:
- case CLUTTER_TOUCH_BEGIN:
- case CLUTTER_TOUCH_END:
- case CLUTTER_SCROLL:
- keys->overlay_key_only_pressed = FALSE;
- keys->locate_pointer_key_only_pressed = FALSE;
- return FALSE;
-
- case CLUTTER_KEY_PRESS:
- case CLUTTER_KEY_RELEASE:
- return process_key_event (display, window, (ClutterKeyEvent *) event);
-
- default:
- return FALSE;
- }
-}
-
-static gboolean
-process_mouse_move_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == CLUTTER_KEY_RELEASE)
- return TRUE;
-
- if (event->keyval == CLUTTER_KEY_Escape)
- {
- MetaTileMode tile_mode;
-
- /* Hide the tiling preview if necessary */
- if (display->preview_tile_mode != META_TILE_NONE)
- meta_display_hide_tile_preview (display);
-
- /* Restore the original tile mode */
- tile_mode = display->grab_tile_mode;
- window->tile_monitor_number = display->grab_tile_monitor_number;
-
- /* End move or resize and restore to original state. If the
- * window was a maximized window that had been "shaken loose" we
- * need to remaximize it. In normal cases, we need to do a
- * moveresize now to get the position back to the original.
- */
- if (window->shaken_loose || tile_mode == META_TILE_MAXIMIZED)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
- else if (tile_mode != META_TILE_NONE)
- meta_window_restore_tile (window,
- tile_mode,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
- else
- meta_window_move_resize_frame (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
-
- /* End grab */
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-process_keyboard_move_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- MetaEdgeResistanceFlags flags;
- gboolean handled;
- MetaRectangle frame_rect;
- int x, y;
- int incr;
-
- handled = FALSE;
-
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == CLUTTER_KEY_RELEASE)
- return TRUE;
-
- /* don't end grab on modifier key presses */
- if (is_modifier (event->keyval))
- return TRUE;
-
- meta_window_get_frame_rect (window, &frame_rect);
- x = frame_rect.x;
- y = frame_rect.y;
-
- flags = META_EDGE_RESISTANCE_KEYBOARD_OP | META_EDGE_RESISTANCE_WINDOWS;
-
- if ((event->modifier_state & CLUTTER_SHIFT_MASK) != 0)
- flags |= META_EDGE_RESISTANCE_SNAP;
-
-#define SMALL_INCREMENT 1
-#define NORMAL_INCREMENT 10
-
- if (flags & META_EDGE_RESISTANCE_SNAP)
- incr = 1;
- else if (event->modifier_state & CLUTTER_CONTROL_MASK)
- incr = SMALL_INCREMENT;
- else
- incr = NORMAL_INCREMENT;
-
- if (event->keyval == CLUTTER_KEY_Escape)
- {
- /* End move and restore to original state. If the window was a
- * maximized window that had been "shaken loose" we need to
- * remaximize it. In normal cases, we need to do a moveresize
- * now to get the position back to the original.
- */
- if (window->shaken_loose)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
- else
- meta_window_move_resize_frame (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
- }
-
- /* When moving by increments, we still snap to edges if the move
- * to the edge is smaller than the increment. This is because
- * Shift + arrow to snap is sort of a hidden feature. This way
- * people using just arrows shouldn't get too frustrated.
- */
- switch (event->keyval)
- {
- case CLUTTER_KEY_KP_Home:
- case CLUTTER_KEY_KP_Prior:
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- y -= incr;
- handled = TRUE;
- break;
- case CLUTTER_KEY_KP_End:
- case CLUTTER_KEY_KP_Next:
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- y += incr;
- handled = TRUE;
- break;
- }
-
- switch (event->keyval)
- {
- case CLUTTER_KEY_KP_Home:
- case CLUTTER_KEY_KP_End:
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- x -= incr;
- handled = TRUE;
- break;
- case CLUTTER_KEY_KP_Prior:
- case CLUTTER_KEY_KP_Next:
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- x += incr;
- handled = TRUE;
- break;
- }
-
- if (handled)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Computed new window location %d,%d due to keypress",
- x, y);
-
- meta_window_edge_resistance_for_move (window,
- &x,
- &y,
- NULL,
- flags);
-
- meta_window_move_frame (window, TRUE, x, y);
- meta_window_update_keyboard_move (window);
- }
-
- return handled;
-}
-
-static gboolean
-process_keyboard_resize_grab_op_change (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- gboolean handled;
-
- handled = FALSE;
- switch (display->grab_op)
- {
- case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_S:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_N:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_W:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_E:
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
- handled = TRUE;
- break;
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
- handled = TRUE;
- break;
- }
- break;
-
- case META_GRAB_OP_KEYBOARD_RESIZING_SE:
- case META_GRAB_OP_KEYBOARD_RESIZING_NE:
- case META_GRAB_OP_KEYBOARD_RESIZING_SW:
- case META_GRAB_OP_KEYBOARD_RESIZING_NW:
- break;
-
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (handled)
- {
- meta_window_update_keyboard_resize (window, TRUE);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-process_keyboard_resize_grab (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event)
-{
- MetaRectangle frame_rect;
- gboolean handled;
- int height_inc;
- int width_inc;
- int width, height;
- MetaEdgeResistanceFlags flags;
- MetaGravity gravity;
-
- handled = FALSE;
-
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == CLUTTER_KEY_RELEASE)
- return TRUE;
-
- /* don't end grab on modifier key presses */
- if (is_modifier (event->keyval))
- return TRUE;
-
- if (event->keyval == CLUTTER_KEY_Escape)
- {
- /* End resize and restore to original state. */
- meta_window_move_resize_frame (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
-
- return FALSE;
- }
-
- if (process_keyboard_resize_grab_op_change (display, window, event))
- return TRUE;
-
- width = window->rect.width;
- height = window->rect.height;
-
- meta_window_get_frame_rect (window, &frame_rect);
- width = frame_rect.width;
- height = frame_rect.height;
-
- gravity = meta_resize_gravity_from_grab_op (display->grab_op);
-
- flags = META_EDGE_RESISTANCE_KEYBOARD_OP;
-
- if ((event->modifier_state & CLUTTER_SHIFT_MASK) != 0)
- flags |= META_EDGE_RESISTANCE_SNAP;
-
-#define SMALL_INCREMENT 1
-#define NORMAL_INCREMENT 10
-
- if (flags & META_EDGE_RESISTANCE_SNAP)
- {
- height_inc = 1;
- width_inc = 1;
- }
- else if (event->modifier_state & CLUTTER_CONTROL_MASK)
- {
- width_inc = SMALL_INCREMENT;
- height_inc = SMALL_INCREMENT;
- }
- else
- {
- width_inc = NORMAL_INCREMENT;
- height_inc = NORMAL_INCREMENT;
- }
-
- /* If this is a resize increment window, make the amount we resize
- * the window by match that amount (well, unless snap resizing...)
- */
- if (window->size_hints.width_inc > 1)
- width_inc = window->size_hints.width_inc;
- if (window->size_hints.height_inc > 1)
- height_inc = window->size_hints.height_inc;
-
- switch (event->keyval)
- {
- case CLUTTER_KEY_Up:
- case CLUTTER_KEY_KP_Up:
- switch (gravity)
- {
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH_EAST:
- /* Move bottom edge up */
- height -= height_inc;
- break;
-
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH_EAST:
- /* Move top edge up */
- height += height_inc;
- break;
-
- case META_GRAVITY_EAST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- case CLUTTER_KEY_Down:
- case CLUTTER_KEY_KP_Down:
- switch (gravity)
- {
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH_EAST:
- /* Move bottom edge down */
- height += height_inc;
- break;
-
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH_EAST:
- /* Move top edge down */
- height -= height_inc;
- break;
-
- case META_GRAVITY_EAST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- case CLUTTER_KEY_Left:
- case CLUTTER_KEY_KP_Left:
- switch (gravity)
- {
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_NORTH_EAST:
- /* Move left edge left */
- width += width_inc;
- break;
-
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_NORTH_WEST:
- /* Move right edge left */
- width -= width_inc;
- break;
-
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- case CLUTTER_KEY_Right:
- case CLUTTER_KEY_KP_Right:
- switch (gravity)
- {
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_NORTH_EAST:
- /* Move left edge right */
- width -= width_inc;
- break;
-
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_NORTH_WEST:
- /* Move right edge right */
- width += width_inc;
- break;
-
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_NONE:
- case META_GRAVITY_STATIC:
- g_assert_not_reached ();
- break;
- }
-
- handled = TRUE;
- break;
-
- default:
- break;
- }
-
- /* fixup hack (just paranoia, not sure it's required) */
- if (height < 1)
- height = 1;
- if (width < 1)
- width = 1;
-
- if (handled)
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Computed new window size due to keypress: "
- "%dx%d, gravity %s",
- width, height, meta_gravity_to_string (gravity));
-
- /* Do any edge resistance/snapping */
- meta_window_edge_resistance_for_resize (window,
- &width,
- &height,
- gravity,
- NULL,
- flags);
-
- meta_window_resize_frame_with_gravity (window,
- TRUE,
- width,
- height,
- gravity);
-
- meta_window_update_keyboard_resize (window, FALSE);
- }
-
- return handled;
-}
-
-static void
-handle_switch_to_last_workspace (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- gint target = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1;
- MetaWorkspace *workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, target);
- meta_workspace_activate (workspace, event->time);
-}
-
-static void
-handle_switch_to_workspace (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gint which = binding->handler->data;
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- MetaWorkspace *workspace;
-
- if (which < 0)
- {
- /* Negative workspace numbers are directions with respect to the
- * current workspace.
- */
-
- workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace,
- which);
- }
- else
- {
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
- }
-
- if (workspace)
- {
- meta_workspace_activate (workspace, event->time);
- }
- else
- {
- /* We could offer to create it I suppose */
- }
-}
-
-
-static void
-handle_maximize_vertically (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_resize_func)
- {
- if (window->maximized_vertically)
- meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
- else
- meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
- }
-}
-
-static void
-handle_maximize_horizontally (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_resize_func)
- {
- if (window->maximized_horizontally)
- meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
- else
- meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
- }
-}
-
-static void
-handle_always_on_top (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->wm_state_above == FALSE)
- meta_window_make_above (window);
- else
- meta_window_unmake_above (window);
-}
-
-static void
-handle_move_to_corner_backend (MetaDisplay *display,
- MetaWindow *window,
- MetaGravity gravity)
-{
- MetaRectangle work_area;
- MetaRectangle frame_rect;
- int new_x, new_y;
-
- if (!window->monitor)
- return;
-
- meta_window_get_work_area_current_monitor (window, &work_area);
- meta_window_get_frame_rect (window, &frame_rect);
-
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_WEST:
- case META_GRAVITY_SOUTH_WEST:
- new_x = work_area.x;
- break;
- case META_GRAVITY_NORTH:
- case META_GRAVITY_SOUTH:
- new_x = frame_rect.x;
- break;
- case META_GRAVITY_NORTH_EAST:
- case META_GRAVITY_EAST:
- case META_GRAVITY_SOUTH_EAST:
- new_x = work_area.x + work_area.width - frame_rect.width;
- break;
- default:
- g_assert_not_reached ();
- }
-
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- case META_GRAVITY_NORTH:
- case META_GRAVITY_NORTH_EAST:
- new_y = work_area.y;
- break;
- case META_GRAVITY_WEST:
- case META_GRAVITY_EAST:
- new_y = frame_rect.y;
- break;
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_EAST:
- new_y = work_area.y + work_area.height - frame_rect.height;
- break;
- default:
- g_assert_not_reached ();
- }
-
- meta_window_move_frame (window,
- TRUE,
- new_x,
- new_y);
-}
-
-static void
-handle_move_to_corner_nw (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH_WEST);
-}
-
-static void
-handle_move_to_corner_ne (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH_EAST);
-}
-
-static void
-handle_move_to_corner_sw (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH_WEST);
-}
-
-static void
-handle_move_to_corner_se (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH_EAST);
-}
-
-static void
-handle_move_to_side_n (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH);
-}
-
-static void
-handle_move_to_side_s (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH);
-}
-
-static void
-handle_move_to_side_e (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_EAST);
-}
-
-static void
-handle_move_to_side_w (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- handle_move_to_corner_backend (display, window, META_GRAVITY_WEST);
-}
-
-static void
-handle_move_to_center (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaRectangle work_area;
- MetaRectangle frame_rect;
-
- meta_window_get_work_area_current_monitor (window, &work_area);
- meta_window_get_frame_rect (window, &frame_rect);
-
- meta_window_move_frame (window,
- TRUE,
- work_area.x + (work_area.width - frame_rect.width ) / 2,
- work_area.y + (work_area.height - frame_rect.height) / 2);
-}
-
-static void
-handle_show_desktop (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
-
- if (workspace_manager->active_workspace->showing_desktop)
- {
- meta_workspace_manager_unshow_desktop (workspace_manager);
- meta_workspace_focus_default_window (workspace_manager->active_workspace,
- NULL,
- event->time);
- }
- else
- meta_workspace_manager_show_desktop (workspace_manager, event->time);
-}
-
-static void
-handle_panel (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaKeyBindingAction action = binding->handler->data;
- MetaX11Display *x11_display = display->x11_display;
- Atom action_atom;
- XClientMessageEvent ev;
-
- action_atom = None;
- switch (action)
- {
- /* FIXME: The numbers are wrong */
- case META_KEYBINDING_ACTION_PANEL_MAIN_MENU:
- action_atom = x11_display->atom__GNOME_PANEL_ACTION_MAIN_MENU;
- break;
- case META_KEYBINDING_ACTION_PANEL_RUN_DIALOG:
- action_atom = x11_display->atom__GNOME_PANEL_ACTION_RUN_DIALOG;
- break;
- default:
- return;
- }
-
- ev.type = ClientMessage;
- ev.window = x11_display->xroot;
- ev.message_type = x11_display->atom__GNOME_PANEL_ACTION;
- ev.format = 32;
- ev.data.l[0] = action_atom;
- ev.data.l[1] = event->time;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Sending panel message with timestamp %u, and turning mouse_mode "
- "off due to keybinding press", event->time);
- display->mouse_mode = FALSE;
-
- meta_x11_error_trap_push (x11_display);
-
- /* Release the grab for the panel before sending the event */
- XUngrabKeyboard (x11_display->xdisplay, event->time);
-
- XSendEvent (x11_display->xdisplay,
- x11_display->xroot,
- False,
- StructureNotifyMask,
- (XEvent*) &ev);
-
- meta_x11_error_trap_pop (x11_display);
-}
-
-static void
-handle_activate_window_menu (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (display->focus_window)
- {
- int x, y;
- MetaRectangle frame_rect;
- cairo_rectangle_int_t child_rect;
-
- meta_window_get_frame_rect (display->focus_window, &frame_rect);
- meta_window_get_client_area_rect (display->focus_window, &child_rect);
-
- x = frame_rect.x + child_rect.x;
- if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL)
- x += child_rect.width;
-
- y = frame_rect.y + child_rect.y;
- meta_window_show_menu (display->focus_window, META_WINDOW_MENU_WM, x, y);
- }
-}
-
-static void
-do_choose_window (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gboolean backward)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- MetaTabList type = binding->handler->data;
- MetaWindow *window;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Tab list = %u", type);
-
- window = meta_display_get_tab_next (display,
- type,
- workspace_manager->active_workspace,
- NULL,
- backward);
-
- if (window)
- meta_window_activate (window, event->time);
-}
-
-static void
-handle_switch (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gboolean backwards = meta_key_binding_is_reversed (binding);
- do_choose_window (display, event_window, event, binding, backwards);
-}
-
-static void
-handle_cycle (MetaDisplay *display,
- MetaWindow *event_window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gboolean backwards = meta_key_binding_is_reversed (binding);
- do_choose_window (display, event_window, event, binding, backwards);
-}
-
-static void
-handle_toggle_fullscreen (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->fullscreen)
- meta_window_unmake_fullscreen (window);
- else if (window->has_fullscreen_func)
- meta_window_make_fullscreen (window);
-}
-
-static void
-handle_toggle_above (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->wm_state_above)
- meta_window_unmake_above (window);
- else
- meta_window_make_above (window);
-}
-
-static void
-handle_toggle_tiled (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaTileMode mode = binding->handler->data;
-
- if ((META_WINDOW_TILED_LEFT (window) && mode == META_TILE_LEFT) ||
- (META_WINDOW_TILED_RIGHT (window) && mode == META_TILE_RIGHT))
- {
- meta_window_untile (window);
- }
- else if (meta_window_can_tile_side_by_side (window))
- {
- window->tile_monitor_number = window->monitor->number;
- /* Maximization constraints beat tiling constraints, so if the window
- * is maximized, tiling won't have any effect unless we unmaximize it
- * horizontally first; rather than calling meta_window_unmaximize(),
- * we just set the flag and rely on meta_window_tile() syncing it to
- * save an additional roundtrip.
- */
- window->maximized_horizontally = FALSE;
- meta_window_tile (window, mode);
- }
-}
-
-static void
-handle_toggle_maximized (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (META_WINDOW_MAXIMIZED (window))
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
- else if (window->has_maximize_func)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
-}
-
-static void
-handle_maximize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_maximize_func)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
-}
-
-static void
-handle_unmaximize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->maximized_vertically || window->maximized_horizontally)
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
-}
-
-static void
-handle_toggle_shaded (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->shaded)
- meta_window_unshade (window, event->time);
- else if (window->has_shade_func)
- meta_window_shade (window, event->time);
-}
-
-static void
-handle_close (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_close_func)
- meta_window_delete (window, event->time);
-}
-
-static void
-handle_minimize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_minimize_func)
- meta_window_minimize (window);
-}
-
-static void
-handle_begin_move (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_move_func)
- {
- meta_window_begin_grab_op (window,
- META_GRAB_OP_KEYBOARD_MOVING,
- FALSE,
- event->time);
- }
-}
-
-static void
-handle_begin_resize (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->has_resize_func)
- {
- meta_window_begin_grab_op (window,
- META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
- FALSE,
- event->time);
- }
-}
-
-static void
-handle_toggle_on_all_workspaces (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- if (window->on_all_workspaces_requested)
- meta_window_unstick (window);
- else
- meta_window_stick (window);
-}
-
-static void
-handle_move_to_workspace_last (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- gint which;
- MetaWorkspace *workspace;
-
- if (window->always_sticky)
- return;
-
- which = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1;
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
- meta_window_change_workspace (window, workspace);
-}
-
-
-static void
-handle_move_to_workspace (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- gint which = binding->handler->data;
- gboolean flip = (which < 0);
- MetaWorkspace *workspace;
-
- /* If which is zero or positive, it's a workspace number, and the window
- * should move to the workspace with that number.
- *
- * However, if it's negative, it's a direction with respect to the current
- * position; it's expressed as a member of the MetaMotionDirection enum,
- * all of whose members are negative. Such a change is called a flip.
- */
-
- if (window->always_sticky)
- return;
-
- workspace = NULL;
- if (flip)
- {
- workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace,
- which);
- }
- else
- {
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which);
- }
-
- if (workspace)
- {
- /* Activate second, so the window is never unmapped */
- meta_window_change_workspace (window, workspace);
- if (flip)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Resetting mouse_mode to FALSE due to "
- "handle_move_to_workspace() call with flip set.");
- meta_display_clear_mouse_mode (workspace->display);
- meta_workspace_activate_with_focus (workspace,
- window,
- event->time);
- }
- }
- else
- {
- /* We could offer to create it I suppose */
- }
-}
-
-static void
-handle_move_to_monitor (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- gint which = binding->handler->data;
- MetaLogicalMonitor *current, *new;
-
- current = window->monitor;
- new = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- current, which);
-
- if (new == NULL)
- return;
-
- meta_window_move_to_monitor (window, new->number);
-}
-
-static void
-handle_raise_or_lower (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- /* Get window at pointer */
-
- MetaWindow *above = NULL;
-
- /* Check if top */
- if (meta_stack_get_top (window->display->stack) == window)
- {
- meta_window_lower (window);
- return;
- }
-
- /* else check if windows in same layer are intersecting it */
-
- above = meta_stack_get_above (window->display->stack, window, TRUE);
-
- while (above)
- {
- MetaRectangle tmp, win_rect, above_rect;
-
- if (above->mapped && meta_window_should_be_showing (above))
- {
- meta_window_get_frame_rect (window, &win_rect);
- meta_window_get_frame_rect (above, &above_rect);
-
- /* Check if obscured */
- if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
- {
- meta_window_raise (window);
- return;
- }
- }
-
- above = meta_stack_get_above (window->display->stack, above, TRUE);
- }
-
- /* window is not obscured */
- meta_window_lower (window);
-}
-
-static void
-handle_raise (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- meta_window_raise (window);
-}
-
-static void
-handle_lower (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- meta_window_lower (window);
-}
-
-static void
-handle_set_spew_mark (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- meta_verbose ("-- MARK MARK MARK MARK --");
-}
-
-#ifdef HAVE_NATIVE_BACKEND
-static void
-handle_switch_vt (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- gint vt = binding->handler->data;
- GError *error = NULL;
-
- if (!meta_activate_vt (vt, &error))
- {
- g_warning ("Failed to switch VT: %s", error->message);
- g_error_free (error);
- }
-}
-#endif /* HAVE_NATIVE_BACKEND */
-
-static void
-handle_switch_monitor (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaMonitorSwitchConfigType config_type =
- meta_monitor_manager_get_switch_config (monitor_manager);
-
- if (!meta_monitor_manager_can_switch_config (monitor_manager))
- return;
-
- config_type = (config_type + 1) % (META_MONITOR_SWITCH_CONFIG_UNKNOWN);
- meta_monitor_manager_switch_config (monitor_manager, config_type);
-}
-
-static void
-handle_rotate_monitor (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
-
- meta_monitor_manager_rotate_monitor (monitor_manager);
-}
-
-static void
-handle_restore_shortcuts (MetaDisplay *display,
- MetaWindow *window,
- ClutterKeyEvent *event,
- MetaKeyBinding *binding,
- gpointer dummy)
-{
- ClutterInputDevice *source;
-
- if (!display->focus_window)
- return;
-
- source = clutter_event_get_source_device ((ClutterEvent *) event);
-
- meta_topic (META_DEBUG_KEYBINDINGS, "Restoring normal keyboard shortcuts");
-
- meta_window_force_restore_shortcuts (display->focus_window, source);
-}
-
-/**
- * meta_keybindings_set_custom_handler:
- * @name: The name of the keybinding to set
- * @handler: (nullable): The new handler function
- * @user_data: User data to pass to the callback
- * @free_data: Will be called when this handler is overridden.
- *
- * Allows users to register a custom handler for a
- * builtin key binding.
- *
- * Returns: %TRUE if the binding known as @name was found,
- * %FALSE otherwise.
- */
-gboolean
-meta_keybindings_set_custom_handler (const gchar *name,
- MetaKeyHandlerFunc handler,
- gpointer user_data,
- GDestroyNotify free_data)
-{
- MetaKeyHandler *key_handler = HANDLER (name);
-
- if (!key_handler)
- return FALSE;
-
- if (key_handler->user_data_free_func && key_handler->user_data)
- key_handler->user_data_free_func (key_handler->user_data);
-
- key_handler->func = handler;
- key_handler->user_data = user_data;
- key_handler->user_data_free_func = free_data;
-
- return TRUE;
-}
-
-static void
-init_builtin_key_bindings (MetaDisplay *display)
-{
- GSettings *common_keybindings = g_settings_new (SCHEMA_COMMON_KEYBINDINGS);
- GSettings *mutter_keybindings = g_settings_new (SCHEMA_MUTTER_KEYBINDINGS);
- GSettings *mutter_wayland_keybindings = g_settings_new (SCHEMA_MUTTER_WAYLAND_KEYBINDINGS);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-1",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_1,
- handle_switch_to_workspace, 0);
- add_builtin_keybinding (display,
- "switch-to-workspace-2",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_2,
- handle_switch_to_workspace, 1);
- add_builtin_keybinding (display,
- "switch-to-workspace-3",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_3,
- handle_switch_to_workspace, 2);
- add_builtin_keybinding (display,
- "switch-to-workspace-4",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_4,
- handle_switch_to_workspace, 3);
- add_builtin_keybinding (display,
- "switch-to-workspace-5",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_5,
- handle_switch_to_workspace, 4);
- add_builtin_keybinding (display,
- "switch-to-workspace-6",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_6,
- handle_switch_to_workspace, 5);
- add_builtin_keybinding (display,
- "switch-to-workspace-7",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_7,
- handle_switch_to_workspace, 6);
- add_builtin_keybinding (display,
- "switch-to-workspace-8",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_8,
- handle_switch_to_workspace, 7);
- add_builtin_keybinding (display,
- "switch-to-workspace-9",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_9,
- handle_switch_to_workspace, 8);
- add_builtin_keybinding (display,
- "switch-to-workspace-10",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_10,
- handle_switch_to_workspace, 9);
- add_builtin_keybinding (display,
- "switch-to-workspace-11",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_11,
- handle_switch_to_workspace, 10);
- add_builtin_keybinding (display,
- "switch-to-workspace-12",
- common_keybindings,
- META_KEY_BINDING_NONE |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_WORKSPACE_12,
- handle_switch_to_workspace, 11);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-left",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_LEFT,
- handle_switch_to_workspace, META_MOTION_LEFT);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-right",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
- handle_switch_to_workspace, META_MOTION_RIGHT);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-up",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_UP,
- handle_switch_to_workspace, META_MOTION_UP);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-down",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_DOWN,
- handle_switch_to_workspace, META_MOTION_DOWN);
-
- add_builtin_keybinding (display,
- "switch-to-workspace-last",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_WORKSPACE_LAST,
- handle_switch_to_last_workspace, 0);
-
-
-
- /* The ones which have inverses. These can't be bound to any keystroke
- * containing Shift because Shift will invert their "backward" state.
- *
- * TODO: "NORMAL" and "DOCKS" should be renamed to the same name as their
- * action, for obviousness.
- *
- * TODO: handle_switch and handle_cycle should probably really be the
- * same function checking a bit in the parameter for difference.
- */
-
- add_builtin_keybinding (display,
- "switch-group",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_GROUP,
- handle_switch, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "switch-group-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD,
- handle_switch, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "switch-applications",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_APPLICATIONS,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-applications-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-windows",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_WINDOWS,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-windows-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD,
- handle_switch, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "switch-panels",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_PANELS,
- handle_switch, META_TAB_LIST_DOCKS);
-
- add_builtin_keybinding (display,
- "switch-panels-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD,
- handle_switch, META_TAB_LIST_DOCKS);
-
- add_builtin_keybinding (display,
- "cycle-group",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_CYCLE_GROUP,
- handle_cycle, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "cycle-group-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD,
- handle_cycle, META_TAB_LIST_GROUP);
-
- add_builtin_keybinding (display,
- "cycle-windows",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_CYCLE_WINDOWS,
- handle_cycle, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "cycle-windows-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD,
- handle_cycle, META_TAB_LIST_NORMAL);
-
- add_builtin_keybinding (display,
- "cycle-panels",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_CYCLE_PANELS,
- handle_cycle, META_TAB_LIST_DOCKS);
-
- add_builtin_keybinding (display,
- "cycle-panels-backward",
- common_keybindings,
- META_KEY_BINDING_IS_REVERSED,
- META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
- handle_cycle, META_TAB_LIST_DOCKS);
-
- /***********************************/
-
- add_builtin_keybinding (display,
- "show-desktop",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SHOW_DESKTOP,
- handle_show_desktop, 0);
-
- add_builtin_keybinding (display,
- "panel-main-menu",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
- handle_panel, META_KEYBINDING_ACTION_PANEL_MAIN_MENU);
-
- add_builtin_keybinding (display,
- "panel-run-dialog",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
- handle_panel, META_KEYBINDING_ACTION_PANEL_RUN_DIALOG);
-
- add_builtin_keybinding (display,
- "set-spew-mark",
- common_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SET_SPEW_MARK,
- handle_set_spew_mark, 0);
-
- add_builtin_keybinding (display,
- "switch-monitor",
- mutter_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_SWITCH_MONITOR,
- handle_switch_monitor, 0);
-
- add_builtin_keybinding (display,
- "rotate-monitor",
- mutter_keybindings,
- META_KEY_BINDING_NONE,
- META_KEYBINDING_ACTION_ROTATE_MONITOR,
- handle_rotate_monitor, 0);
-
-#ifdef HAVE_NATIVE_BACKEND
- MetaBackend *backend = meta_get_backend ();
- if (META_IS_BACKEND_NATIVE (backend))
- {
- add_builtin_keybinding (display,
- "switch-to-session-1",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 1);
-
- add_builtin_keybinding (display,
- "switch-to-session-2",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 2);
-
- add_builtin_keybinding (display,
- "switch-to-session-3",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 3);
-
- add_builtin_keybinding (display,
- "switch-to-session-4",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 4);
-
- add_builtin_keybinding (display,
- "switch-to-session-5",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 5);
-
- add_builtin_keybinding (display,
- "switch-to-session-6",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 6);
-
- add_builtin_keybinding (display,
- "switch-to-session-7",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 7);
-
- add_builtin_keybinding (display,
- "switch-to-session-8",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 8);
-
- add_builtin_keybinding (display,
- "switch-to-session-9",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 9);
-
- add_builtin_keybinding (display,
- "switch-to-session-10",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 10);
-
- add_builtin_keybinding (display,
- "switch-to-session-11",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 11);
-
- add_builtin_keybinding (display,
- "switch-to-session-12",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_switch_vt, 12);
- }
-#endif /* HAVE_NATIVE_BACKEND */
-
- add_builtin_keybinding (display,
- "restore-shortcuts",
- mutter_wayland_keybindings,
- META_KEY_BINDING_NON_MASKABLE,
- META_KEYBINDING_ACTION_NONE,
- handle_restore_shortcuts, 0);
-
- /************************ PER WINDOW BINDINGS ************************/
-
- /* These take a window as an extra parameter; they have no effect
- * if no window is active.
- */
-
- add_builtin_keybinding (display,
- "activate-window-menu",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU,
- handle_activate_window_menu, 0);
-
- add_builtin_keybinding (display,
- "toggle-fullscreen",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN,
- handle_toggle_fullscreen, 0);
-
- add_builtin_keybinding (display,
- "toggle-maximized",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED,
- handle_toggle_maximized, 0);
-
- add_builtin_keybinding (display,
- "toggle-tiled-left",
- mutter_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_TILED_LEFT,
- handle_toggle_tiled, META_TILE_LEFT);
-
- add_builtin_keybinding (display,
- "toggle-tiled-right",
- mutter_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_TILED_RIGHT,
- handle_toggle_tiled, META_TILE_RIGHT);
-
- add_builtin_keybinding (display,
- "toggle-above",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_ABOVE,
- handle_toggle_above, 0);
-
- add_builtin_keybinding (display,
- "maximize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MAXIMIZE,
- handle_maximize, 0);
-
- add_builtin_keybinding (display,
- "unmaximize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_UNMAXIMIZE,
- handle_unmaximize, 0);
-
- add_builtin_keybinding (display,
- "toggle-shaded",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_SHADED,
- handle_toggle_shaded, 0);
-
- add_builtin_keybinding (display,
- "minimize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MINIMIZE,
- handle_minimize, 0);
-
- add_builtin_keybinding (display,
- "close",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_CLOSE,
- handle_close, 0);
-
- add_builtin_keybinding (display,
- "begin-move",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_BEGIN_MOVE,
- handle_begin_move, 0);
-
- add_builtin_keybinding (display,
- "begin-resize",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_BEGIN_RESIZE,
- handle_begin_resize, 0);
-
- add_builtin_keybinding (display,
- "toggle-on-all-workspaces",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES,
- handle_toggle_on_all_workspaces, 0);
-
- add_builtin_keybinding (display,
- "move-to-workspace-1",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1,
- handle_move_to_workspace, 0);
-
- add_builtin_keybinding (display,
- "move-to-workspace-2",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2,
- handle_move_to_workspace, 1);
-
- add_builtin_keybinding (display,
- "move-to-workspace-3",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3,
- handle_move_to_workspace, 2);
-
- add_builtin_keybinding (display,
- "move-to-workspace-4",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4,
- handle_move_to_workspace, 3);
-
- add_builtin_keybinding (display,
- "move-to-workspace-5",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5,
- handle_move_to_workspace, 4);
-
- add_builtin_keybinding (display,
- "move-to-workspace-6",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6,
- handle_move_to_workspace, 5);
-
- add_builtin_keybinding (display,
- "move-to-workspace-7",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7,
- handle_move_to_workspace, 6);
-
- add_builtin_keybinding (display,
- "move-to-workspace-8",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8,
- handle_move_to_workspace, 7);
-
- add_builtin_keybinding (display,
- "move-to-workspace-9",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9,
- handle_move_to_workspace, 8);
-
- add_builtin_keybinding (display,
- "move-to-workspace-10",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10,
- handle_move_to_workspace, 9);
-
- add_builtin_keybinding (display,
- "move-to-workspace-11",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11,
- handle_move_to_workspace, 10);
-
- add_builtin_keybinding (display,
- "move-to-workspace-12",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12,
- handle_move_to_workspace, 11);
-
- add_builtin_keybinding (display,
- "move-to-workspace-last",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LAST,
- handle_move_to_workspace_last, 0);
-
- add_builtin_keybinding (display,
- "move-to-workspace-left",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT,
- handle_move_to_workspace, META_MOTION_LEFT);
-
- add_builtin_keybinding (display,
- "move-to-workspace-right",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT,
- handle_move_to_workspace, META_MOTION_RIGHT);
-
- add_builtin_keybinding (display,
- "move-to-workspace-up",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP,
- handle_move_to_workspace, META_MOTION_UP);
-
- add_builtin_keybinding (display,
- "move-to-workspace-down",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN,
- handle_move_to_workspace, META_MOTION_DOWN);
-
- add_builtin_keybinding (display,
- "move-to-monitor-left",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT,
- handle_move_to_monitor, META_DISPLAY_LEFT);
-
- add_builtin_keybinding (display,
- "move-to-monitor-right",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT,
- handle_move_to_monitor, META_DISPLAY_RIGHT);
-
- add_builtin_keybinding (display,
- "move-to-monitor-down",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN,
- handle_move_to_monitor, META_DISPLAY_DOWN);
-
- add_builtin_keybinding (display,
- "move-to-monitor-up",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW,
- META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP,
- handle_move_to_monitor, META_DISPLAY_UP);
-
- add_builtin_keybinding (display,
- "raise-or-lower",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_RAISE_OR_LOWER,
- handle_raise_or_lower, 0);
-
- add_builtin_keybinding (display,
- "raise",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_RAISE,
- handle_raise, 0);
-
- add_builtin_keybinding (display,
- "lower",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_LOWER,
- handle_lower, 0);
-
- add_builtin_keybinding (display,
- "maximize-vertically",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY,
- handle_maximize_vertically, 0);
-
- add_builtin_keybinding (display,
- "maximize-horizontally",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY,
- handle_maximize_horizontally, 0);
-
- add_builtin_keybinding (display,
- "always-on-top",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
- handle_always_on_top, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-nw",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW,
- handle_move_to_corner_nw, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-ne",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE,
- handle_move_to_corner_ne, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-sw",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW,
- handle_move_to_corner_sw, 0);
-
- add_builtin_keybinding (display,
- "move-to-corner-se",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE,
- handle_move_to_corner_se, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-n",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_N,
- handle_move_to_side_n, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-s",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_S,
- handle_move_to_side_s, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-e",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_E,
- handle_move_to_side_e, 0);
-
- add_builtin_keybinding (display,
- "move-to-side-w",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_SIDE_W,
- handle_move_to_side_w, 0);
-
- add_builtin_keybinding (display,
- "move-to-center",
- common_keybindings,
- META_KEY_BINDING_PER_WINDOW |
- META_KEY_BINDING_IGNORE_AUTOREPEAT,
- META_KEYBINDING_ACTION_MOVE_TO_CENTER,
- handle_move_to_center, 0);
-
- g_object_unref (common_keybindings);
- g_object_unref (mutter_keybindings);
- g_object_unref (mutter_wayland_keybindings);
-}
-
-void
-meta_display_init_keys (MetaDisplay *display)
-{
- MetaKeyBindingManager *keys = &display->key_binding_manager;
- MetaBackend *backend = meta_get_backend ();
- MetaKeyHandler *handler;
-
- keys->backend = backend;
-
- /* Keybindings */
- keys->ignored_modifier_mask = 0;
- keys->hyper_mask = 0;
- keys->super_mask = 0;
- keys->meta_mask = 0;
-
- keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) meta_key_binding_free);
- keys->key_bindings_index = g_hash_table_new (NULL, NULL);
-
- reload_modmap (keys);
-
- key_handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- (GDestroyNotify) key_handler_free);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("overlay-key");
- handler->flags = META_KEY_BINDING_BUILTIN | META_KEY_BINDING_NO_AUTO_GRAB;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("locate-pointer-key");
- handler->flags = META_KEY_BINDING_BUILTIN | META_KEY_BINDING_NO_AUTO_GRAB;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("iso-next-group");
- handler->flags = META_KEY_BINDING_BUILTIN;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- handler = g_new0 (MetaKeyHandler, 1);
- handler->name = g_strdup ("external-grab");
- handler->func = handle_external_grab;
- handler->default_func = handle_external_grab;
-
- g_hash_table_insert (key_handlers, g_strdup (handler->name), handler);
-
- external_grabs = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL,
- (GDestroyNotify)meta_key_grab_free);
-
- init_builtin_key_bindings (display);
-
- rebuild_key_binding_table (keys);
- rebuild_special_bindings (keys);
-
- reload_combos (keys);
-
- update_window_grab_modifiers (display);
-
- /* Keys are actually grabbed in meta_screen_grab_keys() */
-
- meta_prefs_add_listener (prefs_changed_callback, display);
-
- g_signal_connect_swapped (backend, "keymap-changed",
- G_CALLBACK (reload_keybindings), display);
- g_signal_connect_swapped (backend, "keymap-layout-group-changed",
- G_CALLBACK (reload_keybindings), display);
-}
diff --git a/src/core/meta-accel-parse.c b/src/core/meta-accel-parse.c
deleted file mode 100644
index 0d34251af..000000000
--- a/src/core/meta-accel-parse.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2014 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Jasper St. Pierre <jstpierre@mecheye.net>
- */
-
-#include "config.h"
-
-#include "core/meta-accel-parse.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <xkbcommon/xkbcommon.h>
-
-#include "core/keybindings-private.h"
-
-/* This is copied from GTK+ and modified to work with mutter's
- * internal structures. Originating code comes from gtk/gtkaccelgroup.c
- */
-
-static inline gboolean
-is_alt (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'a' || string[1] == 'A') &&
- (string[2] == 'l' || string[2] == 'L') &&
- (string[3] == 't' || string[3] == 'T') &&
- (string[4] == '>'));
-}
-
-static inline gboolean
-is_ctl (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'c' || string[1] == 'C') &&
- (string[2] == 't' || string[2] == 'T') &&
- (string[3] == 'l' || string[3] == 'L') &&
- (string[4] == '>'));
-}
-
-static inline gboolean
-is_modx (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'm' || string[1] == 'M') &&
- (string[2] == 'o' || string[2] == 'O') &&
- (string[3] == 'd' || string[3] == 'D') &&
- (string[4] >= '1' && string[4] <= '5') &&
- (string[5] == '>'));
-}
-
-static inline gboolean
-is_ctrl (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'c' || string[1] == 'C') &&
- (string[2] == 't' || string[2] == 'T') &&
- (string[3] == 'r' || string[3] == 'R') &&
- (string[4] == 'l' || string[4] == 'L') &&
- (string[5] == '>'));
-}
-
-static inline gboolean
-is_shft (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 's' || string[1] == 'S') &&
- (string[2] == 'h' || string[2] == 'H') &&
- (string[3] == 'f' || string[3] == 'F') &&
- (string[4] == 't' || string[4] == 'T') &&
- (string[5] == '>'));
-}
-
-static inline gboolean
-is_shift (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 's' || string[1] == 'S') &&
- (string[2] == 'h' || string[2] == 'H') &&
- (string[3] == 'i' || string[3] == 'I') &&
- (string[4] == 'f' || string[4] == 'F') &&
- (string[5] == 't' || string[5] == 'T') &&
- (string[6] == '>'));
-}
-
-static inline gboolean
-is_control (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'c' || string[1] == 'C') &&
- (string[2] == 'o' || string[2] == 'O') &&
- (string[3] == 'n' || string[3] == 'N') &&
- (string[4] == 't' || string[4] == 'T') &&
- (string[5] == 'r' || string[5] == 'R') &&
- (string[6] == 'o' || string[6] == 'O') &&
- (string[7] == 'l' || string[7] == 'L') &&
- (string[8] == '>'));
-}
-
-static inline gboolean
-is_meta (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'm' || string[1] == 'M') &&
- (string[2] == 'e' || string[2] == 'E') &&
- (string[3] == 't' || string[3] == 'T') &&
- (string[4] == 'a' || string[4] == 'A') &&
- (string[5] == '>'));
-}
-
-static inline gboolean
-is_super (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 's' || string[1] == 'S') &&
- (string[2] == 'u' || string[2] == 'U') &&
- (string[3] == 'p' || string[3] == 'P') &&
- (string[4] == 'e' || string[4] == 'E') &&
- (string[5] == 'r' || string[5] == 'R') &&
- (string[6] == '>'));
-}
-
-static inline gboolean
-is_hyper (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'h' || string[1] == 'H') &&
- (string[2] == 'y' || string[2] == 'Y') &&
- (string[3] == 'p' || string[3] == 'P') &&
- (string[4] == 'e' || string[4] == 'E') &&
- (string[5] == 'r' || string[5] == 'R') &&
- (string[6] == '>'));
-}
-
-static inline gboolean
-is_primary (const gchar *string)
-{
- return ((string[0] == '<') &&
- (string[1] == 'p' || string[1] == 'P') &&
- (string[2] == 'r' || string[2] == 'R') &&
- (string[3] == 'i' || string[3] == 'I') &&
- (string[4] == 'm' || string[4] == 'M') &&
- (string[5] == 'a' || string[5] == 'A') &&
- (string[6] == 'r' || string[6] == 'R') &&
- (string[7] == 'y' || string[7] == 'Y') &&
- (string[8] == '>'));
-}
-
-static inline gboolean
-is_keycode (const gchar *string)
-{
- return (string[0] == '0' &&
- string[1] == 'x' &&
- g_ascii_isxdigit (string[2]) &&
- g_ascii_isxdigit (string[3]));
-}
-
-static gboolean
-accelerator_parse (const gchar *accelerator,
- MetaKeyCombo *combo)
-{
- guint keyval, keycode;
- MetaVirtualModifier mods;
- gint len;
-
- combo->keysym = 0;
- combo->keycode = 0;
- combo->modifiers = 0;
-
- if (accelerator == NULL)
- return FALSE;
-
- keyval = 0;
- keycode = 0;
- mods = 0;
- len = strlen (accelerator);
- while (len)
- {
- if (*accelerator == '<')
- {
- if (len >= 9 && is_primary (accelerator))
- {
- /* Primary is treated the same as Control */
- accelerator += 9;
- len -= 9;
- mods |= META_VIRTUAL_CONTROL_MASK;
- }
- else if (len >= 9 && is_control (accelerator))
- {
- accelerator += 9;
- len -= 9;
- mods |= META_VIRTUAL_CONTROL_MASK;
- }
- else if (len >= 7 && is_shift (accelerator))
- {
- accelerator += 7;
- len -= 7;
- mods |= META_VIRTUAL_SHIFT_MASK;
- }
- else if (len >= 6 && is_shft (accelerator))
- {
- accelerator += 6;
- len -= 6;
- mods |= META_VIRTUAL_SHIFT_MASK;
- }
- else if (len >= 6 && is_ctrl (accelerator))
- {
- accelerator += 6;
- len -= 6;
- mods |= META_VIRTUAL_CONTROL_MASK;
- }
- else if (len >= 6 && is_modx (accelerator))
- {
- static const guint mod_vals[] = {
- META_VIRTUAL_ALT_MASK,
- META_VIRTUAL_MOD2_MASK,
- META_VIRTUAL_MOD3_MASK,
- META_VIRTUAL_MOD4_MASK,
- META_VIRTUAL_MOD5_MASK,
- };
-
- len -= 6;
- accelerator += 4;
- mods |= mod_vals[*accelerator - '1'];
- accelerator += 2;
- }
- else if (len >= 5 && is_ctl (accelerator))
- {
- accelerator += 5;
- len -= 5;
- mods |= META_VIRTUAL_CONTROL_MASK;
- }
- else if (len >= 5 && is_alt (accelerator))
- {
- accelerator += 5;
- len -= 5;
- mods |= META_VIRTUAL_ALT_MASK;
- }
- else if (len >= 6 && is_meta (accelerator))
- {
- accelerator += 6;
- len -= 6;
- mods |= META_VIRTUAL_META_MASK;
- }
- else if (len >= 7 && is_hyper (accelerator))
- {
- accelerator += 7;
- len -= 7;
- mods |= META_VIRTUAL_HYPER_MASK;
- }
- else if (len >= 7 && is_super (accelerator))
- {
- accelerator += 7;
- len -= 7;
- mods |= META_VIRTUAL_SUPER_MASK;
- }
- else
- {
- gchar last_ch;
-
- last_ch = *accelerator;
- while (last_ch && last_ch != '>')
- {
- last_ch = *accelerator;
- accelerator += 1;
- len -= 1;
- }
- }
- }
- else
- {
- if (len >= 4 && is_keycode (accelerator))
- {
- keycode = strtoul (accelerator, NULL, 16);
- goto out;
- }
- else if (strcmp (accelerator, "Above_Tab") == 0)
- {
- keyval = META_KEY_ABOVE_TAB;
- goto out;
- }
- else
- {
- keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
- if (keyval == XKB_KEY_NoSymbol)
- {
- char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
- keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
- g_free (with_xf86);
-
- if (keyval == XKB_KEY_NoSymbol)
- return FALSE;
- }
- }
-
- accelerator += len;
- len -= len;
- }
- }
-
- out:
- combo->keysym = keyval;
- combo->keycode = keycode;
- combo->modifiers = mods;
- return TRUE;
-}
-
-gboolean
-meta_parse_accelerator (const char *accel,
- MetaKeyCombo *combo)
-{
- g_return_val_if_fail (combo != NULL, FALSE);
-
- *combo = (MetaKeyCombo) { 0 };
-
- if (!accel[0] || strcmp (accel, "disabled") == 0)
- return TRUE;
-
- return accelerator_parse (accel, combo);
-}
-
-gboolean
-meta_parse_modifier (const char *accel,
- MetaVirtualModifier *mask)
-{
- MetaKeyCombo combo = { 0 };
-
- g_return_val_if_fail (mask != NULL, FALSE);
-
- *mask = 0;
-
- if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
- return TRUE;
-
- if (!accelerator_parse (accel, &combo))
- return FALSE;
-
- *mask = combo.modifiers;
- return TRUE;
-}
diff --git a/src/core/meta-accel-parse.h b/src/core/meta-accel-parse.h
deleted file mode 100644
index 12cf3f982..000000000
--- a/src/core/meta-accel-parse.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * Copyright (C) 2014 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Jasper St. Pierre <jstpierre@mecheye.net>
- */
-
-#ifndef META_ACCEL_PARSE_H
-#define META_ACCEL_PARSE_H
-
-#include <glib.h>
-
-#include "meta/common.h"
-
-typedef struct _MetaKeyCombo MetaKeyCombo;
-
-/* Not a real key symbol but means "key above the tab key"; this is
- * used as the default keybinding for cycle_group.
- * 0x2xxxxxxx is a range not used by GDK or X. the remaining digits are
- * randomly chosen */
-#define META_KEY_ABOVE_TAB 0x2f7259c9
-
-gboolean meta_parse_accelerator (const char *accel,
- MetaKeyCombo *combo);
-gboolean meta_parse_modifier (const char *accel,
- MetaVirtualModifier *mask);
-
-#endif /* META_ACCEL_PARSE_H */
diff --git a/src/core/meta-anonymous-file.c b/src/core/meta-anonymous-file.c
deleted file mode 100644
index 95b63c9f0..000000000
--- a/src/core/meta-anonymous-file.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2020 Sebastian Wick
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Sebastian Wick <sebastian@sebastianwick.net>
- */
-
-#include "config.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "core/meta-anonymous-file.h"
-
-struct _MetaAnonymousFile
-{
- int fd;
- size_t size;
-};
-
-#define READONLY_SEALS (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)
-
-static int
-create_tmpfile_cloexec (char *tmpname)
-{
- int fd;
-
-#if defined(HAVE_MKOSTEMP)
- fd = mkostemp (tmpname, O_CLOEXEC);
- if (fd >= 0)
- unlink (tmpname);
-#else
- fd = mkstemp (tmpname);
- if (fd >= 0)
- {
- long flags;
-
- unlink (tmpname);
-
- flags = fcntl (fd, F_GETFD);
- if (flags == -1 ||
- fcntl (fd, F_SETFD, flags | FD_CLOEXEC) == -1)
- {
- close (fd);
- return -1;
- }
- }
-#endif
-
- return fd;
-}
-
-/*
- * Create a new, unique, anonymous file of the given size, and
- * return the file descriptor for it. The file descriptor is set
- * CLOEXEC. The file is immediately suitable for mmap()'ing
- * the given size at offset zero.
- *
- * The file should not have a permanent backing store like a disk,
- * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
- *
- * The file name is deleted from the file system.
- *
- * The file is suitable for buffer sharing between processes by
- * transmitting the file descriptor over Unix sockets using the
- * SCM_RIGHTS methods.
- *
- * If the C library implements posix_fallocate(), it is used to
- * guarantee that disk space is available for the file at the
- * given size. If disk space is insufficient, errno is set to ENOSPC.
- * If posix_fallocate() is not supported, program may receive
- * SIGBUS on accessing mmap()'ed file contents instead.
- *
- * If the C library implements memfd_create(), it is used to create the
- * file purely in memory, without any backing file name on the file
- * system, and then sealing off the possibility of shrinking it. This
- * can then be checked before accessing mmap()'ed file contents, to make
- * sure SIGBUS can't happen. It also avoids requiring XDG_RUNTIME_DIR.
- */
-static int
-create_anonymous_file (off_t size)
-{
- int fd, ret;
-
-#if defined(HAVE_MEMFD_CREATE)
- fd = memfd_create ("mutter-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
- if (fd >= 0)
- {
- /* We can add this seal before calling posix_fallocate(), as
- * the file is currently zero-sized anyway.
- *
- * There is also no need to check for the return value, we
- * couldn't do anything with it anyway.
- */
- fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK);
- }
- else
-#endif
- {
- static const char template[] = "/mutter-shared-XXXXXX";
- const char *path;
- char *name;
-
- path = getenv ("XDG_RUNTIME_DIR");
- if (!path)
- {
- errno = ENOENT;
- return -1;
- }
-
- name = g_malloc (strlen (path) + sizeof (template));
- if (!name)
- return -1;
-
- strcpy (name, path);
- strcat (name, template);
-
- fd = create_tmpfile_cloexec (name);
-
- g_free (name);
-
- if (fd < 0)
- return -1;
- }
-
-#if defined(HAVE_POSIX_FALLOCATE)
- do
- {
- ret = posix_fallocate (fd, 0, size);
- }
- while (ret == EINTR);
-
- if (ret != 0)
- {
- close (fd);
- errno = ret;
- return -1;
- }
-#else
- do
- {
- ret = ftruncate (fd, size);
- }
- while (ret < 0 && errno == EINTR);
-
- if (ret < 0)
- {
- close (fd);
- return -1;
- }
-#endif
-
- return fd;
-}
-
-/**
- * meta_anonymous_file_new: (skip)
- * @size: The size of @data
- * @data: The data of the file with the size @size
- *
- * Create a new anonymous read-only file of the given size and the given data
- * The intended use-case is for sending mid-sized data from the compositor
- * to clients.
- *
- * When done, free the data using meta_anonymous_file_free().
- *
- * If this function fails errno is set.
- *
- * Returns: The newly created #MetaAnonymousFile, or NULL on failure. Use
- * meta_anonymous_file_free() to free the resources when done.
- */
-MetaAnonymousFile *
-meta_anonymous_file_new (size_t size,
- const uint8_t *data)
-{
- MetaAnonymousFile *file;
- void *map;
-
- file = g_malloc0 (sizeof *file);
- if (!file)
- {
- errno = ENOMEM;
- return NULL;
- }
-
- file->size = size;
- file->fd = create_anonymous_file (size);
- if (file->fd == -1)
- goto err_free;
-
- map = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0);
- if (map == MAP_FAILED)
- goto err_close;
-
- memcpy (map, data, size);
-
- munmap (map, size);
-
-#if defined(HAVE_MEMFD_CREATE)
- /* try to put seals on the file to make it read-only so that we can
- * return the fd later directly when MAPMODE_SHARED is not set.
- * meta_anonymous_file_open_fd can handle the fd even if it is not
- * sealed read-only and will instead create a new anonymous file on
- * each invocation.
- */
- fcntl (file->fd, F_ADD_SEALS, READONLY_SEALS);
-#endif
-
- return file;
-
-err_close:
- close (file->fd);
-err_free:
- g_free (file);
- return NULL;
-}
-
-
-/**
- * meta_anonymous_file_free: (skip)
- * @file: the #MetaAnonymousFile
- *
- * Free the resources used by an anonymous read-only file.
- */
-void
-meta_anonymous_file_free (MetaAnonymousFile *file)
-{
- close (file->fd);
- g_free (file);
-}
-
-/**
- * meta_anonymous_file_size: (skip)
- * @file: the #MetaAnonymousFile
- *
- * Get the size of an anonymous read-only file.
- *
- * Returns: The size of the anonymous read-only file.
- */
-size_t
-meta_anonymous_file_size (MetaAnonymousFile *file)
-{
- return file->size;
-}
-
-/**
- * meta_anonymous_file_open_fd: (skip)
- * @file: the #MetaAnonymousFile to get a file descriptor for
- * @mapmode: describes the ways in which the returned file descriptor can
- * be used with mmap
- *
- * Returns a file descriptor for the given file, ready to be sent to a client.
- * The returned file descriptor must not be shared between multiple clients.
- * If @mapmode is %META_ANONYMOUS_FILE_MAPMODE_PRIVATE the file descriptor is
- * only guaranteed to be mmapable with MAP_PRIVATE. If @mapmode is
- * %META_ANONYMOUS_FILE_MAPMODE_SHARED the file descriptor can be mmaped with
- * either MAP_PRIVATE or MAP_SHARED.
- *
- * In case %META_ANONYMOUS_FILE_MAPMODE_PRIVATE is used, it is important to
- * only read the returned fd using mmap() since using read() will move the
- * read cursor of the fd and thus may cause read() calls on other returned
- * fds to fail.
- *
- * When done using the fd, it is required to call meta_anonymous_file_close_fd()
- * instead of close().
- *
- * If this function fails errno is set.
- *
- * Returns: A file descriptor for the given file that can be sent to a client
- * or -1 on failure. Use meta_anonymous_file_close_fd() to release the fd
- * when done.
- */
-int
-meta_anonymous_file_open_fd (MetaAnonymousFile *file,
- MetaAnonymousFileMapmode mapmode)
-{
- void *src, *dst;
- int fd;
-
-#if defined(HAVE_MEMFD_CREATE)
- int seals;
-
- seals = fcntl (file->fd, F_GET_SEALS);
-
- /* file was sealed for read-only and we don't have to support MAP_SHARED
- * so we can simply pass the memfd fd
- */
- if (seals != -1 && mapmode == META_ANONYMOUS_FILE_MAPMODE_PRIVATE &&
- (seals & READONLY_SEALS) == READONLY_SEALS)
- return file->fd;
-#endif
-
- /* for all other cases we create a new anonymous file that can be mapped
- * with MAP_SHARED and copy the contents to it and return that instead
- */
- fd = create_anonymous_file (file->size);
- if (fd == -1)
- return fd;
-
- src = mmap (NULL, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0);
- if (src == MAP_FAILED)
- {
- close (fd);
- return -1;
- }
-
- dst = mmap (NULL, file->size, PROT_WRITE, MAP_SHARED, fd, 0);
- if (dst == MAP_FAILED)
- {
- close (fd);
- munmap (src, file->size);
- return -1;
- }
-
- memcpy (dst, src, file->size);
- munmap (src, file->size);
- munmap (dst, file->size);
-
- return fd;
-}
-
-/**
- * meta_anonymous_file_close_fd: (skip)
- * @fd: A file descriptor obtained using meta_anonymous_file_open_fd()
- *
- * Release a file descriptor returned by meta_anonymous_file_open_fd().
- * This function must be called for every file descriptor created with
- * meta_anonymous_file_open_fd() to not leak any resources.
- *
- * If this function fails errno is set.
- */
-void
-meta_anonymous_file_close_fd (int fd)
-{
-#if defined(HAVE_MEMFD_CREATE)
- int seals;
-
- seals = fcntl (fd, F_GET_SEALS);
- if (seals == -1 && errno != EINVAL)
- {
- g_warning ("Reading seals of anonymous file %d failed", fd);
- return;
- }
-
- /* The only case in which we do NOT have to close the file is when the file
- * was sealed for read-only
- */
- if (seals != -1 && (seals & READONLY_SEALS) == READONLY_SEALS)
- return;
-#endif
-
- close (fd);
-}
diff --git a/src/core/meta-anonymous-file.h b/src/core/meta-anonymous-file.h
deleted file mode 100644
index 5289c7193..000000000
--- a/src/core/meta-anonymous-file.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2020 Sebastian Wick
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Sebastian Wick <sebastian@sebastianwick.net>
- */
-
-#ifndef META_ANONYMOUS_FILE_H
-#define META_ANONYMOUS_FILE_H
-
-#include "meta/common.h"
-#include "core/util-private.h"
-
-typedef struct _MetaAnonymousFile MetaAnonymousFile;
-
-typedef enum _MetaAnonymousFileMapmode
-{
- META_ANONYMOUS_FILE_MAPMODE_PRIVATE,
- META_ANONYMOUS_FILE_MAPMODE_SHARED,
-} MetaAnonymousFileMapmode;
-
-META_EXPORT_TEST
-MetaAnonymousFile * meta_anonymous_file_new (size_t size,
- const uint8_t *data);
-
-META_EXPORT_TEST
-void meta_anonymous_file_free (MetaAnonymousFile *file);
-
-META_EXPORT_TEST
-size_t meta_anonymous_file_size (MetaAnonymousFile *file);
-
-META_EXPORT_TEST
-int meta_anonymous_file_open_fd (MetaAnonymousFile *file,
- MetaAnonymousFileMapmode mapmode);
-
-META_EXPORT_TEST
-void meta_anonymous_file_close_fd (int fd);
-
-#endif /* META_ANONYMOUS_FILE_H */
diff --git a/src/core/meta-border.c b/src/core/meta-border.c
deleted file mode 100644
index 3c926c419..000000000
--- a/src/core/meta-border.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2015 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Jonas Ådahl <jadahl@gmail.com>
- */
-
-#include "config.h"
-
-#include "core/meta-border.h"
-
-#include <math.h>
-
-static inline float
-meta_vector2_cross_product (const MetaVector2 a,
- const MetaVector2 b)
-{
- return a.x * b.y - a.y * b.x;
-}
-
-static inline MetaVector2
-meta_vector2_add (const MetaVector2 a,
- const MetaVector2 b)
-{
- return (MetaVector2) {
- .x = a.x + b.x,
- .y = a.y + b.y,
- };
-}
-
-static inline MetaVector2
-meta_vector2_multiply_constant (const float c,
- const MetaVector2 a)
-{
- return (MetaVector2) {
- .x = c * a.x,
- .y = c * a.y,
- };
-}
-
-gboolean
-meta_line2_intersects_with (const MetaLine2 *line1,
- const MetaLine2 *line2,
- MetaVector2 *intersection)
-{
- MetaVector2 p = line1->a;
- MetaVector2 r = meta_vector2_subtract (line1->b, line1->a);
- MetaVector2 q = line2->a;
- MetaVector2 s = meta_vector2_subtract (line2->b, line2->a);
- float rxs;
- float sxr;
- float t;
- float u;
-
- /*
- * The line (p, r) and (q, s) intersects where
- *
- * p + t r = q + u s
- *
- * Calculate t:
- *
- * (p + t r) × s = (q + u s) × s
- * p × s + t (r × s) = q × s + u (s × s)
- * p × s + t (r × s) = q × s
- * t (r × s) = q × s - p × s
- * t (r × s) = (q - p) × s
- * t = ((q - p) × s) / (r × s)
- *
- * Using the same method, for u we get:
- *
- * u = ((p - q) × r) / (s × r)
- */
-
- rxs = meta_vector2_cross_product (r, s);
- sxr = meta_vector2_cross_product (s, r);
-
- /* If r × s = 0 then the lines are either parallel or collinear. */
- if (fabsf (rxs) < FLT_MIN)
- return FALSE;
-
- t = meta_vector2_cross_product (meta_vector2_subtract (q, p), s) / rxs;
- u = meta_vector2_cross_product (meta_vector2_subtract (p, q), r) / sxr;
-
- /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */
- if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
- return FALSE;
-
- *intersection = meta_vector2_add (p, meta_vector2_multiply_constant (t, r));
-
- return TRUE;
-}
-
-gboolean
-meta_border_is_horizontal (MetaBorder *border)
-{
- return border->line.a.y == border->line.b.y;
-}
-
-gboolean
-meta_border_is_blocking_directions (MetaBorder *border,
- MetaBorderMotionDirection directions)
-{
- if (meta_border_is_horizontal (border))
- {
- if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
- META_BORDER_MOTION_DIRECTION_NEGATIVE_Y)) == 0)
- return FALSE;
- }
- else
- {
- if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
- META_BORDER_MOTION_DIRECTION_NEGATIVE_X)) == 0)
- return FALSE;
- }
-
- return (~border->blocking_directions & directions) != directions;
-}
-
-unsigned int
-meta_border_get_allows_directions (MetaBorder *border)
-{
- return ~border->blocking_directions &
- (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
- META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
- META_BORDER_MOTION_DIRECTION_NEGATIVE_X |
- META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
-}
-
-void
-meta_border_set_allows_directions (MetaBorder *border, unsigned int directions)
-{
- border->blocking_directions =
- ~directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X |
- META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
- META_BORDER_MOTION_DIRECTION_NEGATIVE_X |
- META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
-}
diff --git a/src/core/meta-border.h b/src/core/meta-border.h
deleted file mode 100644
index dd76db5c9..000000000
--- a/src/core/meta-border.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2015 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Jonas Ådahl <jadahl@gmail.com>
- */
-
-#ifndef META_BORDER_H
-#define META_BORDER_H
-
-#include <glib.h>
-
-typedef enum
-{
- META_BORDER_MOTION_DIRECTION_POSITIVE_X = 1 << 0,
- META_BORDER_MOTION_DIRECTION_POSITIVE_Y = 1 << 1,
- META_BORDER_MOTION_DIRECTION_NEGATIVE_X = 1 << 2,
- META_BORDER_MOTION_DIRECTION_NEGATIVE_Y = 1 << 3,
-} MetaBorderMotionDirection;
-
-typedef struct _MetaVector2
-{
- float x;
- float y;
-} MetaVector2;
-
-typedef struct _MetaLine2
-{
- MetaVector2 a;
- MetaVector2 b;
-} MetaLine2;
-
-typedef struct _MetaBorder
-{
- MetaLine2 line;
- MetaBorderMotionDirection blocking_directions;
-} MetaBorder;
-
-static inline MetaVector2
-meta_vector2_subtract (const MetaVector2 a,
- const MetaVector2 b)
-{
- return (MetaVector2) {
- .x = a.x - b.x,
- .y = a.y - b.y,
- };
-}
-
-gboolean
-meta_line2_intersects_with (const MetaLine2 *line1,
- const MetaLine2 *line2,
- MetaVector2 *intersection);
-
-gboolean
-meta_border_is_horizontal (MetaBorder *border);
-
-gboolean
-meta_border_is_blocking_directions (MetaBorder *border,
- MetaBorderMotionDirection directions);
-
-unsigned int
-meta_border_get_allows_directions (MetaBorder *border);
-
-void
-meta_border_set_allows_directions (MetaBorder *border, unsigned int directions);
-
-#endif /* META_BORDER_H */
diff --git a/src/core/meta-clipboard-manager.c b/src/core/meta-clipboard-manager.c
deleted file mode 100644
index 794195f41..000000000
--- a/src/core/meta-clipboard-manager.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include "core/meta-clipboard-manager.h"
-#include "meta/meta-selection-source-memory.h"
-
-#define MAX_TEXT_SIZE (4 * 1024 * 1024) /* 4MB */
-#define MAX_IMAGE_SIZE (200 * 1024 * 1024) /* 200MB */
-
-/* Supported mimetype globs, from least to most preferred */
-static struct {
- const char *mimetype_glob;
- ssize_t max_transfer_size;
-} supported_mimetypes[] = {
- { "image/tiff", MAX_IMAGE_SIZE },
- { "image/bmp", MAX_IMAGE_SIZE },
- { "image/gif", MAX_IMAGE_SIZE },
- { "image/jpeg", MAX_IMAGE_SIZE },
- { "image/webp", MAX_IMAGE_SIZE },
- { "image/png", MAX_IMAGE_SIZE },
- { "image/svg+xml", MAX_IMAGE_SIZE },
- { "text/plain", MAX_TEXT_SIZE },
- { "text/plain;charset=utf-8", MAX_TEXT_SIZE },
-};
-
-static gboolean
-mimetype_match (const char *mimetype,
- int *idx,
- gssize *max_transfer_size)
-{
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (supported_mimetypes); i++)
- {
- if (g_pattern_match_simple (supported_mimetypes[i].mimetype_glob, mimetype))
- {
- *max_transfer_size = supported_mimetypes[i].max_transfer_size;
- *idx = i;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static void
-transfer_cb (MetaSelection *selection,
- GAsyncResult *result,
- GOutputStream *output)
-{
- MetaDisplay *display = meta_get_display ();
- GError *error = NULL;
-
- if (!meta_selection_transfer_finish (selection, result, &error))
- {
- g_warning ("Failed to store clipboard: %s", error->message);
- g_error_free (error);
- g_object_unref (output);
- return;
- }
-
- g_output_stream_close (output, NULL, NULL);
- display->saved_clipboard =
- g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output));
- g_object_unref (output);
-}
-
-static void
-owner_changed_cb (MetaSelection *selection,
- MetaSelectionType selection_type,
- MetaSelectionSource *new_owner,
- MetaDisplay *display)
-{
- if (selection_type != META_SELECTION_CLIPBOARD)
- return;
-
- if (new_owner && new_owner != display->selection_source)
- {
- GOutputStream *output;
- GList *mimetypes, *l;
- int best_idx = -1;
- const char *best = NULL;
- ssize_t transfer_size = -1;
-
- /* New selection source, find the best mimetype in order to
- * keep a copy of it.
- */
- g_clear_object (&display->selection_source);
- g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
- g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
-
- mimetypes = meta_selection_get_mimetypes (selection, selection_type);
-
- for (l = mimetypes; l; l = l->next)
- {
- gssize max_transfer_size;
- int idx;
-
- if (!mimetype_match (l->data, &idx, &max_transfer_size))
- continue;
-
- if (best_idx < idx)
- {
- best_idx = idx;
- best = l->data;
- transfer_size = max_transfer_size;
- }
- }
-
- if (best_idx < 0)
- {
- g_list_free_full (mimetypes, g_free);
- return;
- }
-
- display->saved_clipboard_mimetype = g_strdup (best);
- g_list_free_full (mimetypes, g_free);
- output = g_memory_output_stream_new_resizable ();
- meta_selection_transfer_async (selection,
- META_SELECTION_CLIPBOARD,
- display->saved_clipboard_mimetype,
- transfer_size,
- output,
- NULL,
- (GAsyncReadyCallback) transfer_cb,
- output);
- }
- else if (!new_owner && display->saved_clipboard)
- {
- /* Old owner is gone, time to take over */
- new_owner = meta_selection_source_memory_new (display->saved_clipboard_mimetype,
- display->saved_clipboard);
- g_set_object (&display->selection_source, new_owner);
- meta_selection_set_owner (selection, selection_type, new_owner);
- g_object_unref (new_owner);
- }
-}
-
-void
-meta_clipboard_manager_init (MetaDisplay *display)
-{
- MetaSelection *selection;
-
- selection = meta_display_get_selection (display);
- g_signal_connect_after (selection, "owner-changed",
- G_CALLBACK (owner_changed_cb), display);
-}
-
-void
-meta_clipboard_manager_shutdown (MetaDisplay *display)
-{
- MetaSelection *selection;
-
- g_clear_object (&display->selection_source);
- g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
- g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
- selection = meta_display_get_selection (display);
- g_signal_handlers_disconnect_by_func (selection, owner_changed_cb, display);
-}
diff --git a/src/core/meta-clipboard-manager.h b/src/core/meta-clipboard-manager.h
deleted file mode 100644
index 2ba130f9b..000000000
--- a/src/core/meta-clipboard-manager.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#ifndef META_CLIPBOARD_MANAGER_H
-#define META_CLIPBOARD_MANAGER_H
-
-#include "core/display-private.h"
-
-void meta_clipboard_manager_init (MetaDisplay *display);
-void meta_clipboard_manager_shutdown (MetaDisplay *display);
-
-#endif /* META_CLIPBOARD_MANAGER_H */
diff --git a/src/core/meta-close-dialog-default-private.h b/src/core/meta-close-dialog-default-private.h
deleted file mode 100644
index f149d3686..000000000
--- a/src/core/meta-close-dialog-default-private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2016 Red Hat
- *
- * 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/>.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#ifndef META_CLOSE_DIALOG_DEFAULT_H
-#define META_CLOSE_DIALOG_DEFAULT_H
-
-#include <glib-object.h>
-
-#include "meta/meta-plugin.h"
-
-#define META_TYPE_CLOSE_DIALOG_DEFAULT (meta_close_dialog_default_get_type ())
-G_DECLARE_FINAL_TYPE (MetaCloseDialogDefault,
- meta_close_dialog_default,
- META, CLOSE_DIALOG_DEFAULT,
- GObject)
-
-MetaCloseDialog * meta_close_dialog_default_new (MetaWindow *window);
-
-#endif /* META_CLOSE_DIALOG_DEFAULT_H */
diff --git a/src/core/meta-close-dialog-default.c b/src/core/meta-close-dialog-default.c
deleted file mode 100644
index 544a5b62d..000000000
--- a/src/core/meta-close-dialog-default.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001, 2002 Havoc Pennington
- * Copyright (C) 2004 Elijah Newren
- * Copyright (C) 2016 Red Hat
- *
- * 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/>.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#define _XOPEN_SOURCE /* for kill() */
-
-#include "config.h"
-
-#include "core/meta-close-dialog-default-private.h"
-#include "meta/meta-close-dialog.h"
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#include "core/util-private.h"
-#include "core/window-private.h"
-#include "x11/meta-x11-display-private.h"
-
-typedef struct _MetaCloseDialogDefaultPrivate MetaCloseDialogDefaultPrivate;
-
-struct _MetaCloseDialogDefault
-{
- GObject parent_instance;
- MetaWindow *window;
- int dialog_pid;
- guint child_watch_id;
-};
-
-enum
-{
- PROP_0,
- PROP_WINDOW,
- N_PROPS
-};
-
-GParamSpec *pspecs[N_PROPS] = { NULL };
-
-static void meta_close_dialog_iface_init (MetaCloseDialogInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (MetaCloseDialogDefault, meta_close_dialog_default,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (META_TYPE_CLOSE_DIALOG,
- meta_close_dialog_iface_init))
-
-static void
-dialog_exited (GPid pid,
- int status,
- gpointer user_data)
-{
- MetaCloseDialogDefault *dialog = user_data;
-
- dialog->dialog_pid = -1;
-
- /* exit status of 0 means the user pressed "Force Quit" */
- if (WIFEXITED (status) && WEXITSTATUS (status) == 0)
- g_signal_emit_by_name (dialog, "response", META_CLOSE_DIALOG_RESPONSE_FORCE_CLOSE);
-}
-
-static void
-present_existing_delete_dialog (MetaCloseDialogDefault *dialog)
-{
- MetaWindow *window;
- GSList *windows;
- GSList *tmp;
-
- window = dialog->window;
-
- if (dialog->dialog_pid < 0)
- return;
-
- meta_topic (META_DEBUG_PING,
- "Presenting existing ping dialog for %s",
- window->desc);
-
- /* Activate transient for window that belongs to
- * mutter-dialog
- */
- windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
- tmp = windows;
-
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
-
- if (w->transient_for == window && w->res_class &&
- g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
- {
- meta_window_activate (w, CLUTTER_CURRENT_TIME);
- break;
- }
-
- tmp = tmp->next;
- }
-
- g_slist_free (windows);
-}
-
-static void
-meta_close_dialog_default_show (MetaCloseDialog *dialog)
-{
- MetaCloseDialogDefault *dialog_default = META_CLOSE_DIALOG_DEFAULT (dialog);
- MetaWindow *window = dialog_default->window;
- gchar *window_title, *window_content, *tmp;
- GPid dialog_pid;
-
- if (dialog_default->dialog_pid >= 0)
- {
- present_existing_delete_dialog (dialog_default);
- return;
- }
-
- /* This is to get a better string if the title isn't representable
- * in the locale encoding; actual conversion to UTF-8 is done inside
- * meta_show_dialog */
- if (window->title && window->title[0])
- {
- tmp = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
- if (tmp == NULL)
- window_title = NULL;
- else
- window_title = window->title;
- g_free (tmp);
- }
- else
- {
- window_title = NULL;
- }
-
- if (window_title)
- /* Translators: %s is a window title */
- tmp = g_strdup_printf (_("“%s” is not responding."), window_title);
- else
- tmp = g_strdup (_("Application is not responding."));
-
- window_content = g_strdup_printf (
- "<big><b>%s</b></big>\n\n%s",
- tmp,
- _("You may choose to wait a short while for it to "
- "continue or force the application to quit entirely."));
-
- dialog_pid =
- meta_show_dialog ("--question",
- window_content, NULL,
- window->display->x11_display->screen_name,
- _("_Force Quit"), _("_Wait"),
- "face-sad-symbolic", window->xwindow,
- NULL, NULL);
-
- g_free (window_content);
- g_free (tmp);
-
- dialog_default->dialog_pid = dialog_pid;
- g_child_watch_add (dialog_pid, dialog_exited, dialog);
-}
-
-static void
-meta_close_dialog_default_hide (MetaCloseDialog *dialog)
-{
- MetaCloseDialogDefault *dialog_default;
-
- dialog_default = META_CLOSE_DIALOG_DEFAULT (dialog);
-
- g_clear_handle_id (&dialog_default->child_watch_id, g_source_remove);
-
- if (dialog_default->dialog_pid > -1)
- {
- kill (dialog_default->dialog_pid, SIGTERM);
- dialog_default->dialog_pid = -1;
- }
-}
-
-static void
-meta_close_dialog_iface_init (MetaCloseDialogInterface *iface)
-{
- iface->show = meta_close_dialog_default_show;
- iface->hide = meta_close_dialog_default_hide;
-}
-
-static void
-meta_close_dialog_default_finalize (GObject *object)
-{
- MetaCloseDialogDefault *dialog;
-
- dialog = META_CLOSE_DIALOG_DEFAULT (object);
-
- g_clear_handle_id (&dialog->child_watch_id, g_source_remove);
-
- if (dialog->dialog_pid > -1)
- {
- kill (dialog->dialog_pid, SIGKILL);
- dialog->dialog_pid = -1;
- }
-
- G_OBJECT_CLASS (meta_close_dialog_default_parent_class)->finalize (object);
-}
-
-static void
-meta_close_dialog_default_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaCloseDialogDefault *dialog;
-
- dialog = META_CLOSE_DIALOG_DEFAULT (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- dialog->window = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_close_dialog_default_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaCloseDialogDefault *dialog;
-
- dialog = META_CLOSE_DIALOG_DEFAULT (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- g_value_set_object (value, dialog->window);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_close_dialog_default_class_init (MetaCloseDialogDefaultClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_close_dialog_default_finalize;
- object_class->set_property = meta_close_dialog_default_set_property;
- object_class->get_property = meta_close_dialog_default_get_property;
-
- g_object_class_override_property (object_class, PROP_WINDOW, "window");
-}
-
-static void
-meta_close_dialog_default_init (MetaCloseDialogDefault *dialog)
-{
- dialog->dialog_pid = -1;
-}
-
-MetaCloseDialog *
-meta_close_dialog_default_new (MetaWindow *window)
-{
- return g_object_new (META_TYPE_CLOSE_DIALOG_DEFAULT,
- "window", window,
- NULL);
-}
diff --git a/src/core/meta-close-dialog.c b/src/core/meta-close-dialog.c
deleted file mode 100644
index 6d24fa570..000000000
--- a/src/core/meta-close-dialog.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2016 Red Hat
- *
- * 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/>.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include "core/window-private.h"
-#include "meta/meta-close-dialog.h"
-#include "meta/meta-enum-types.h"
-
-enum
-{
- RESPONSE,
- N_SIGNALS
-};
-
-guint dialog_signals[N_SIGNALS] = { 0 };
-
-static GQuark quark_visible = 0;
-
-G_DEFINE_INTERFACE (MetaCloseDialog, meta_close_dialog, G_TYPE_OBJECT)
-
-static void
-meta_close_dialog_default_init (MetaCloseDialogInterface *iface)
-{
- g_object_interface_install_property (iface,
- g_param_spec_object ("window",
- "Window",
- "Window",
- META_TYPE_WINDOW,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
- dialog_signals[RESPONSE] =
- g_signal_new ("response",
- G_TYPE_FROM_INTERFACE (iface),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1, META_TYPE_CLOSE_DIALOG_RESPONSE);
-
- quark_visible = g_quark_from_static_string ("meta-close-dialog-visible");
-}
-
-/**
- * meta_close_dialog_show:
- * @dialog: a #MetaCloseDialog
- *
- * Shows the close dialog.
- **/
-void
-meta_close_dialog_show (MetaCloseDialog *dialog)
-{
- MetaCloseDialogInterface *iface;
-
- g_return_if_fail (META_IS_CLOSE_DIALOG (dialog));
-
- iface = META_CLOSE_DIALOG_GET_IFACE (dialog);
- iface->show (dialog);
- g_object_set_qdata (G_OBJECT (dialog), quark_visible, GINT_TO_POINTER (TRUE));
-}
-
-/**
- * meta_close_dialog_hide:
- * @dialog: a #MetaCloseDialog
- *
- * Hides the close dialog.
- **/
-void
-meta_close_dialog_hide (MetaCloseDialog *dialog)
-{
- MetaCloseDialogInterface *iface;
-
- g_return_if_fail (META_IS_CLOSE_DIALOG (dialog));
-
- iface = META_CLOSE_DIALOG_GET_IFACE (dialog);
- iface->hide (dialog);
- g_object_steal_qdata (G_OBJECT (dialog), quark_visible);
-}
-
-/**
- * meta_close_dialog_response:
- * @dialog: a #MetaCloseDialog
- * @response: a #MetaCloseDialogResponse
- *
- * Responds and closes the dialog. To be called by #MetaCloseDialog
- * implementations.
- **/
-void
-meta_close_dialog_response (MetaCloseDialog *dialog,
- MetaCloseDialogResponse response)
-{
- g_signal_emit (dialog, dialog_signals[RESPONSE], 0, response);
- meta_close_dialog_hide (dialog);
-}
-
-/**
- * meta_close_dialog_is_visible:
- * @dialog: a #MetaCloseDialog
- *
- * Returns whether @dialog is currently visible.
- *
- * Returns: #TRUE if @dialog is visible.
- **/
-gboolean
-meta_close_dialog_is_visible (MetaCloseDialog *dialog)
-{
- return GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (dialog), quark_visible));
-}
-
-/**
- * meta_close_dialog_focus:
- * @dialog: a #MetaCloseDialog
- *
- * Call whenever @dialog should receive keyboard focus,
- * usually when the window would.
- **/
-void
-meta_close_dialog_focus (MetaCloseDialog *dialog)
-{
- MetaCloseDialogInterface *iface;
-
- g_return_if_fail (META_IS_CLOSE_DIALOG (dialog));
-
- iface = META_CLOSE_DIALOG_GET_IFACE (dialog);
- if (iface->focus)
- iface->focus (dialog);
-}
diff --git a/src/core/meta-context-main.c b/src/core/meta-context-main.c
deleted file mode 100644
index 8f669151a..000000000
--- a/src/core/meta-context-main.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2006 Elijah Newren
- * Copyright (C) 2021 Red Hat Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#include "config.h"
-
-#include "core/meta-context-main.h"
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#if defined(HAVE_NATIVE_BACKEND) && defined(HAVE_WAYLAND)
-#include <systemd/sd-login.h>
-#endif /* HAVE_WAYLAND && HAVE_NATIVE_BACKEND */
-
-#include "backends/meta-monitor-manager-private.h"
-#include "backends/meta-virtual-monitor.h"
-#include "backends/x11/cm/meta-backend-x11-cm.h"
-#include "meta/meta-backend.h"
-#include "wayland/meta-wayland.h"
-#include "x11/session.h"
-
-#ifdef HAVE_NATIVE_BACKEND
-#include "backends/native/meta-backend-native.h"
-#endif
-
-#ifdef HAVE_WAYLAND
-#include "backends/x11/nested/meta-backend-x11-nested.h"
-#endif
-
-typedef struct _MetaContextMainOptions
-{
- struct {
- char *display_name;
- gboolean replace;
- gboolean sync;
- gboolean force;
- } x11;
- struct {
- char *save_file;
- char *client_id;
- gboolean disable;
- } sm;
-#ifdef HAVE_WAYLAND
- gboolean wayland;
- gboolean nested;
- gboolean no_x11;
- char *wayland_display;
-#endif
-#ifdef HAVE_NATIVE_BACKEND
- gboolean display_server;
- gboolean headless;
-#endif
-#ifdef HAVE_NATIVE_BACKEND
- GList *virtual_monitor_infos;
-#endif
-} MetaContextMainOptions;
-
-struct _MetaContextMain
-{
- GObject parent;
-
- MetaContextMainOptions options;
-
- MetaCompositorType compositor_type;
-
- GList *persistent_virtual_monitors;
-};
-
-G_DEFINE_TYPE (MetaContextMain, meta_context_main, META_TYPE_CONTEXT)
-
-static gboolean
-check_configuration (MetaContextMain *context_main,
- GError **error)
-{
-#ifdef HAVE_WAYLAND
- if (context_main->options.x11.force && context_main->options.no_x11)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't run in X11 mode with no X11");
- return FALSE;
- }
- if (context_main->options.x11.force && context_main->options.wayland)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't run in X11 mode with Wayland enabled");
- return FALSE;
- }
- if (context_main->options.x11.force && context_main->options.nested)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't run in X11 mode nested");
- return FALSE;
- }
-#endif /* HAVE_WAYLAND */
-
-#ifdef HAVE_NATIVE_BACKEND
- if (context_main->options.x11.force && context_main->options.display_server)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't run in X11 mode as a display server");
- return FALSE;
- }
-
- if (context_main->options.x11.force && context_main->options.headless)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't run in X11 mode headlessly");
- return FALSE;
- }
-
- if (context_main->options.display_server && context_main->options.headless)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't run in display server mode headlessly");
- return FALSE;
- }
-#endif /* HAVE_NATIVE_BACKEND */
-
- if (context_main->options.sm.save_file &&
- context_main->options.sm.client_id)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Can't specify both SM save file and SM client id");
- return FALSE;
- }
-
- return TRUE;
-}
-
-#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
-static gboolean
-session_type_is_supported (const char *session_type)
-{
- return (g_strcmp0 (session_type, "x11") == 0) ||
- (g_strcmp0 (session_type, "wayland") == 0);
-}
-
-static char *
-find_session_type (GError **error)
-{
- char **sessions = NULL;
- char *session_id;
- char *session_type;
- const char *session_type_env;
- gboolean is_tty = FALSE;
- int ret, i;
-
- ret = sd_pid_get_session (0, &session_id);
- if (ret == 0 && session_id != NULL)
- {
- ret = sd_session_get_type (session_id, &session_type);
- free (session_id);
-
- if (ret == 0)
- {
- if (session_type_is_supported (session_type))
- goto out;
- else
- is_tty = g_strcmp0 (session_type, "tty") == 0;
- free (session_type);
- }
- }
- else if (sd_uid_get_sessions (getuid (), 1, &sessions) > 0)
- {
- for (i = 0; sessions[i] != NULL; i++)
- {
- ret = sd_session_get_type (sessions[i], &session_type);
-
- if (ret < 0)
- continue;
-
- if (session_type_is_supported (session_type))
- {
- g_strfreev (sessions);
- goto out;
- }
-
- free (session_type);
- }
- }
- g_strfreev (sessions);
-
- session_type_env = g_getenv ("XDG_SESSION_TYPE");
- if (session_type_is_supported (session_type_env))
- {
- /* The string should be freeable */
- session_type = strdup (session_type_env);
- goto out;
- }
-
- /* Legacy support for starting through xinit */
- if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY")))
- {
- session_type = strdup ("x11");
- goto out;
- }
-
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Unsupported session type");
- return NULL;
-
-out:
- return session_type;
-}
-#else /* defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) */
-static char *
-find_session_type (GError **error)
-{
- return g_strdup ("x11");
-}
-#endif /* defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) */
-
-static MetaCompositorType
-determine_compositor_type (MetaContextMain *context_main,
- GError **error)
-{
- g_autofree char *session_type = NULL;
-
-#ifdef HAVE_WAYLAND
- if (context_main->options.wayland ||
-#ifdef HAVE_NATIVE_BACKEND
- context_main->options.display_server ||
- context_main->options.headless ||
-#endif /* HAVE_NATIVE_BACKEND */
- context_main->options.nested)
- return META_COMPOSITOR_TYPE_WAYLAND;
-#endif /* HAVE_WAYLAND */
-
- if (context_main->options.x11.force)
- return META_COMPOSITOR_TYPE_X11;
-
- session_type = find_session_type (error);
- if (!session_type)
- return -1;
-
- if (strcmp (session_type, "x11") == 0)
- return META_COMPOSITOR_TYPE_X11;
-#ifdef HAVE_WAYLAND
- else if (strcmp (session_type, "wayland") == 0)
- return META_COMPOSITOR_TYPE_WAYLAND;
-#endif
- else
- g_assert_not_reached ();
-}
-
-static gboolean
-meta_context_main_configure (MetaContext *context,
- int *argc,
- char ***argv,
- GError **error)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
- MetaContextClass *context_class =
- META_CONTEXT_CLASS (meta_context_main_parent_class);
-
- if (!context_class->configure (context, argc, argv, error))
- return FALSE;
-
- if (!check_configuration (context_main, error))
- return FALSE;
-
- context_main->compositor_type = determine_compositor_type (context_main,
- error);
- if (context_main->compositor_type == -1)
- return FALSE;
-
-#ifdef HAVE_WAYLAND
- if (context_main->options.wayland_display)
- meta_wayland_override_display_name (context_main->options.wayland_display);
-#endif
-
- return TRUE;
-}
-
-static MetaCompositorType
-meta_context_main_get_compositor_type (MetaContext *context)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
-
- return context_main->compositor_type;
-}
-
-static MetaX11DisplayPolicy
-meta_context_main_get_x11_display_policy (MetaContext *context)
-{
- MetaCompositorType compositor_type;
-#ifdef HAVE_WAYLAND
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
- char *unit;
-#endif
-
- compositor_type = meta_context_get_compositor_type (context);
- switch (compositor_type)
- {
- case META_COMPOSITOR_TYPE_X11:
- return META_X11_DISPLAY_POLICY_MANDATORY;
- case META_COMPOSITOR_TYPE_WAYLAND:
-#ifdef HAVE_WAYLAND
- if (context_main->options.no_x11)
- return META_X11_DISPLAY_POLICY_DISABLED;
- else if (sd_pid_get_user_unit (0, &unit) < 0)
- return META_X11_DISPLAY_POLICY_MANDATORY;
- else
- return META_X11_DISPLAY_POLICY_ON_DEMAND;
-#else /* HAVE_WAYLAND */
- g_assert_not_reached ();
-#endif /* HAVE_WAYLAND */
- }
-
- g_assert_not_reached ();
-}
-
-static gboolean
-meta_context_main_is_replacing (MetaContext *context)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
-
- return context_main->options.x11.replace;
-}
-
-#ifdef HAVE_NATIVE_BACKEND
-static gboolean
-add_persistent_virtual_monitors (MetaContextMain *context_main,
- GError **error)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- GList *l;
-
- for (l = context_main->options.virtual_monitor_infos; l; l = l->next)
- {
- MetaVirtualMonitorInfo *info = l->data;
- MetaVirtualMonitor *virtual_monitor;
-
- virtual_monitor =
- meta_monitor_manager_create_virtual_monitor (monitor_manager,
- info,
- error);
- if (!virtual_monitor)
- {
- g_prefix_error (error, "Failed to add virtual monitor: ");
- return FALSE;
- }
-
- context_main->persistent_virtual_monitors =
- g_list_append (context_main->persistent_virtual_monitors, virtual_monitor);
- }
-
- if (context_main->options.virtual_monitor_infos)
- {
- g_list_free_full (context_main->options.virtual_monitor_infos,
- (GDestroyNotify) meta_virtual_monitor_info_free);
- context_main->options.virtual_monitor_infos = NULL;
-
- meta_monitor_manager_reload (monitor_manager);
- }
-
- return TRUE;
-}
-#endif
-
-static gboolean
-meta_context_main_setup (MetaContext *context,
- GError **error)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
-
- if (!META_CONTEXT_CLASS (meta_context_main_parent_class)->setup (context,
- error))
- return FALSE;
-
- meta_set_syncing (context_main->options.x11.sync || g_getenv ("MUTTER_SYNC"));
-
-#ifdef HAVE_NATIVE_BACKEND
- if (!add_persistent_virtual_monitors (context_main, error))
- return FALSE;
-#endif
-
- return TRUE;
-}
-
-static MetaBackend *
-create_x11_cm_backend (MetaContext *context,
- GError **error)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
-
-#ifdef HAVE_NATIVE_BACKEND
- if (context_main->options.virtual_monitor_infos)
- g_warning ("Ignoring added virtual monitors in X11 session");
-#endif
-
- return g_initable_new (META_TYPE_BACKEND_X11_CM,
- NULL, error,
- "context", context,
- "display-name", context_main->options.x11.display_name,
- NULL);
-}
-
-#ifdef HAVE_WAYLAND
-static MetaBackend *
-create_nested_backend (MetaContext *context,
- GError **error)
-{
- return g_initable_new (META_TYPE_BACKEND_X11_NESTED,
- NULL, error,
- "context", context,
- NULL);
-}
-
-#ifdef HAVE_NATIVE_BACKEND
-static MetaBackend *
-create_headless_backend (MetaContext *context,
- GError **error)
-{
- return g_initable_new (META_TYPE_BACKEND_NATIVE,
- NULL, error,
- "context", context,
- "headless", TRUE,
- NULL);
-}
-
-static MetaBackend *
-create_native_backend (MetaContext *context,
- GError **error)
-{
- return g_initable_new (META_TYPE_BACKEND_NATIVE,
- NULL, error,
- "context", context,
- NULL);
-}
-#endif /* HAVE_NATIVE_BACKEND */
-#endif /* HAVE_WAYLAND */
-
-static MetaBackend *
-meta_context_main_create_backend (MetaContext *context,
- GError **error)
-{
-#ifdef HAVE_WAYLAND
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
-#endif
- MetaCompositorType compositor_type;
-
- compositor_type = meta_context_get_compositor_type (context);
- switch (compositor_type)
- {
- case META_COMPOSITOR_TYPE_X11:
- return create_x11_cm_backend (context, error);
- case META_COMPOSITOR_TYPE_WAYLAND:
-#ifdef HAVE_WAYLAND
- if (context_main->options.nested)
- return create_nested_backend (context, error);
-#ifdef HAVE_NATIVE_BACKEND
- else if (context_main->options.headless)
- return create_headless_backend (context, error);
- else
- return create_native_backend (context, error);
-#endif /* HAVE_NATIVE_BACKEND */
-#else /* HAVE_WAYLAND */
- g_assert_not_reached ();
-#endif /* HAVE_WAYLAND */
- }
-
- g_assert_not_reached ();
-}
-
-static void
-meta_context_main_notify_ready (MetaContext *context)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (context);
-
- if (!context_main->options.sm.disable)
- {
- meta_session_init (context,
- context_main->options.sm.client_id,
- context_main->options.sm.save_file);
- }
- g_clear_pointer (&context_main->options.sm.client_id, g_free);
- g_clear_pointer (&context_main->options.sm.save_file, g_free);
-}
-
-#ifdef HAVE_NATIVE_BACKEND
-static gboolean
-add_virtual_monitor_cb (const char *option_name,
- const char *value,
- gpointer user_data,
- GError **error)
-{
- MetaContextMain *context_main = user_data;
- int width, height;
- float refresh_rate = 60.0;
-
- if (sscanf (value, "%dx%d@%f",
- &width, &height, &refresh_rate) == 3 ||
- sscanf (value, "%dx%d",
- &width, &height) == 2)
- {
- g_autofree char *serial = NULL;
- MetaVirtualMonitorInfo *virtual_monitor;
- int n_existing_virtual_monitor_infos;
-
- n_existing_virtual_monitor_infos =
- g_list_length (context_main->options.virtual_monitor_infos);
- serial = g_strdup_printf ("0x%.2x", n_existing_virtual_monitor_infos);
- virtual_monitor = meta_virtual_monitor_info_new (width,
- height,
- refresh_rate,
- "MetaVendor",
- "MetaVirtualMonitor",
- serial);
- context_main->options.virtual_monitor_infos =
- g_list_append (context_main->options.virtual_monitor_infos,
- virtual_monitor);
- return TRUE;
- }
- else
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
- "Unrecognizable virtual monitor spec '%s'", value);
- return FALSE;
- }
-}
-#endif /* HAVE_NATIVE_BACKEND */
-
-static void
-meta_context_main_add_option_entries (MetaContextMain *context_main)
-{
- MetaContext *context = META_CONTEXT (context_main);
- GOptionEntry options[] = {
- {
- "replace", 'r', 0, G_OPTION_ARG_NONE,
- &context_main->options.x11.replace,
- N_("Replace the running window manager"),
- NULL
- },
- {
- "display", 'd', 0, G_OPTION_ARG_STRING,
- &context_main->options.x11.display_name,
- N_("X Display to use"),
- "DISPLAY"
- },
- {
- "sm-disable", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.sm.disable,
- N_("Disable connection to session manager"),
- NULL
- },
- {
- "sm-client-id", 0, 0, G_OPTION_ARG_STRING,
- &context_main->options.sm.client_id,
- N_("Specify session management ID"),
- "ID"
- },
- {
- "sm-save-file", 0, 0, G_OPTION_ARG_FILENAME,
- &context_main->options.sm.save_file,
- N_("Initialize session from savefile"),
- "FILE"
- },
- {
- "sync", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.x11.sync,
- N_("Make X calls synchronous"),
- NULL
- },
-#ifdef HAVE_WAYLAND
- {
- "wayland", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.wayland,
- N_("Run as a wayland compositor"),
- NULL
- },
- {
- "nested", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.nested,
- N_("Run as a nested compositor"),
- NULL
- },
- {
- "no-x11", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.no_x11,
- N_("Run wayland compositor without starting Xwayland"),
- NULL
- },
- {
- "wayland-display", 0, 0, G_OPTION_ARG_STRING,
- &context_main->options.wayland_display,
- N_("Specify Wayland display name to use"),
- NULL
- },
-#endif
-#ifdef HAVE_NATIVE_BACKEND
- {
- "display-server", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.display_server,
- N_("Run as a full display server, rather than nested")
- },
- {
- "headless", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.headless,
- N_("Run as a headless display server")
- },
- {
- "virtual-monitor", 0, 0, G_OPTION_ARG_CALLBACK,
- add_virtual_monitor_cb,
- N_("Add persistent virtual monitor (WxH or WxH@R)")
- },
-#endif
- {
- "x11", 0, 0, G_OPTION_ARG_NONE,
- &context_main->options.x11.force,
- N_("Run with X11 backend")
- },
- { NULL }
- };
-
- meta_context_add_option_entries (context, options, GETTEXT_PACKAGE);
-}
-
-/**
- * meta_create_context:
- * @name: Human readable name of display server or window manager
- *
- * Create a context.
- *
- * Returns: (transfer full): A new context instance.
- */
-MetaContext *
-meta_create_context (const char *name)
-{
- return g_object_new (META_TYPE_CONTEXT_MAIN,
- "name", name,
- NULL);
-}
-
-static void
-meta_context_main_finalize (GObject *object)
-{
-#ifdef HAVE_NATIVE_BACKEND
- MetaContextMain *context_main = META_CONTEXT_MAIN (object);
-
- g_list_free_full (context_main->persistent_virtual_monitors, g_object_unref);
- context_main->persistent_virtual_monitors = NULL;
-#endif
-
- G_OBJECT_CLASS (meta_context_main_parent_class)->finalize (object);
-}
-
-static void
-meta_context_main_constructed (GObject *object)
-{
- MetaContextMain *context_main = META_CONTEXT_MAIN (object);
-
- G_OBJECT_CLASS (meta_context_main_parent_class)->constructed (object);
-
- meta_context_main_add_option_entries (context_main);
-}
-
-static void
-meta_context_main_class_init (MetaContextMainClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- MetaContextClass *context_class = META_CONTEXT_CLASS (klass);
-
- object_class->finalize = meta_context_main_finalize;
- object_class->constructed = meta_context_main_constructed;
-
- context_class->configure = meta_context_main_configure;
- context_class->get_compositor_type = meta_context_main_get_compositor_type;
- context_class->get_x11_display_policy =
- meta_context_main_get_x11_display_policy;
- context_class->is_replacing = meta_context_main_is_replacing;
- context_class->setup = meta_context_main_setup;
- context_class->create_backend = meta_context_main_create_backend;
- context_class->notify_ready = meta_context_main_notify_ready;
-}
-
-static void
-meta_context_main_init (MetaContextMain *context_main)
-{
- context_main->compositor_type = -1;
-}
diff --git a/src/core/meta-context-main.h b/src/core/meta-context-main.h
deleted file mode 100644
index 9a8ce902b..000000000
--- a/src/core/meta-context-main.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 Red Hat Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#ifndef META_CONTEXT_MAIN_H
-#define META_CONTEXT_MAIN_H
-
-#include "core/meta-context-private.h"
-
-#define META_TYPE_CONTEXT_MAIN (meta_context_main_get_type ())
-G_DECLARE_FINAL_TYPE (MetaContextMain, meta_context_main,
- META, CONTEXT_MAIN,
- MetaContext)
-
-#endif /* META_CONTEXT_MAIN_H */
diff --git a/src/core/meta-context-private.h b/src/core/meta-context-private.h
deleted file mode 100644
index a3b7f9b4b..000000000
--- a/src/core/meta-context-private.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 Red Hat Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#ifndef META_CONTEXT_PRIVATE_H
-#define META_CONTEXT_PRIVATE_H
-
-#include "core/meta-private-enums.h"
-#include "core/util-private.h"
-#include "meta/meta-backend.h"
-#include "meta/meta-context.h"
-#include "wayland/meta-wayland-types.h"
-
-struct _MetaContextClass
-{
- GObjectClass parent_class;
-
- gboolean (* configure) (MetaContext *context,
- int *argc,
- char ***argv,
- GError **error);
-
- MetaCompositorType (* get_compositor_type) (MetaContext *context);
-
- MetaX11DisplayPolicy (* get_x11_display_policy) (MetaContext *context);
-
- gboolean (* is_replacing) (MetaContext *context);
-
- gboolean (* setup) (MetaContext *context,
- GError **error);
-
- MetaBackend * (* create_backend) (MetaContext *context,
- GError **error);
-
- void (* notify_ready) (MetaContext *context);
-};
-
-const char * meta_context_get_name (MetaContext *context);
-
-const char * meta_context_get_gnome_wm_keybindings (MetaContext *context);
-
-META_EXPORT_TEST
-MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context);
-
-MetaX11DisplayPolicy meta_context_get_x11_display_policy (MetaContext *context);
-
-#endif /* META_CONTEXT_PRIVATE_H */
diff --git a/src/core/meta-context.c b/src/core/meta-context.c
deleted file mode 100644
index 7bb0e5f46..000000000
--- a/src/core/meta-context.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * Copyright (C) 2019 Red Hat Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#include "config.h"
-
-#include "core/meta-context-private.h"
-
-#include <locale.h>
-
-#include "backends/meta-backend-private.h"
-#include "compositor/meta-plugin-manager.h"
-#include "core/display-private.h"
-#include "core/prefs-private.h"
-#include "core/util-private.h"
-
-#ifdef HAVE_WAYLAND
-#include "wayland/meta-wayland.h"
-#endif
-
-enum
-{
- PROP_0,
-
- PROP_NAME,
-
- N_PROPS
-};
-
-static GParamSpec *obj_props[N_PROPS];
-
-typedef enum _MetaContextState
-{
- META_CONTEXT_STATE_INIT,
- META_CONTEXT_STATE_CONFIGURED,
- META_CONTEXT_STATE_SETUP,
- META_CONTEXT_STATE_STARTED,
- META_CONTEXT_STATE_RUNNING,
- META_CONTEXT_STATE_TERMINATED,
-} MetaContextState;
-
-typedef struct _MetaContextPrivate
-{
- char *name;
- char *plugin_name;
- GType plugin_gtype;
- char *gnome_wm_keybindings;
-
- MetaContextState state;
-
- GOptionContext *option_context;
-
- MetaBackend *backend;
- MetaDisplay *display;
-#ifdef HAVE_WAYLAND
- MetaWaylandCompositor *wayland_compositor;
-#endif
-
- GMainLoop *main_loop;
- GError *termination_error;
-} MetaContextPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT)
-
-void
-meta_context_add_option_entries (MetaContext *context,
- const GOptionEntry *entries,
- const char *translation_domain)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
-
- g_option_context_add_main_entries (priv->option_context,
- entries,
- translation_domain);
-}
-
-void
-meta_context_add_option_group (MetaContext *context,
- GOptionGroup *group)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
- g_return_if_fail (priv->option_context);
-
- g_option_context_add_group (priv->option_context, group);
-}
-
-void
-meta_context_set_plugin_gtype (MetaContext *context,
- GType plugin_gtype)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
- g_return_if_fail (!priv->plugin_name);
-
- priv->plugin_gtype = plugin_gtype;
-}
-
-void
-meta_context_set_plugin_name (MetaContext *context,
- const char *plugin_name)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
- g_return_if_fail (priv->plugin_gtype == G_TYPE_NONE);
-
- priv->plugin_name = g_strdup (plugin_name);
-}
-
-void
-meta_context_set_gnome_wm_keybindings (MetaContext *context,
- const char *wm_keybindings)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED);
-
- g_clear_pointer (&priv->gnome_wm_keybindings, g_free);
- priv->gnome_wm_keybindings = g_strdup (wm_keybindings);
-}
-
-const char *
-meta_context_get_gnome_wm_keybindings (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- return priv->gnome_wm_keybindings;
-}
-
-void
-meta_context_notify_ready (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_return_if_fail (priv->state == META_CONTEXT_STATE_STARTED ||
- priv->state == META_CONTEXT_STATE_RUNNING);
-
- META_CONTEXT_GET_CLASS (context)->notify_ready (context);
-}
-
-const char *
-meta_context_get_name (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- return priv->name;
-}
-
-/**
- * meta_context_get_backend:
- * @context: The #MetaContext
- *
- * Returns: (transfer none): the #MetaBackend
- */
-MetaBackend *
-meta_context_get_backend (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- return priv->backend;
-}
-
-/**
- * meta_context_get_display:
- * @context: The #MetaContext
- *
- * Returns: (transfer none): the #MetaDisplay
- */
-MetaDisplay *
-meta_context_get_display (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- return priv->display;
-}
-
-#ifdef HAVE_WAYLAND
-MetaWaylandCompositor *
-meta_context_get_wayland_compositor (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- return priv->wayland_compositor;
-}
-#endif
-
-MetaCompositorType
-meta_context_get_compositor_type (MetaContext *context)
-{
- return META_CONTEXT_GET_CLASS (context)->get_compositor_type (context);
-}
-
-gboolean
-meta_context_is_replacing (MetaContext *context)
-{
- return META_CONTEXT_GET_CLASS (context)->is_replacing (context);
-}
-
-MetaX11DisplayPolicy
-meta_context_get_x11_display_policy (MetaContext *context)
-{
- return META_CONTEXT_GET_CLASS (context)->get_x11_display_policy (context);
-}
-
-static gboolean
-meta_context_real_configure (MetaContext *context,
- int *argc,
- char ***argv,
- GError **error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
- g_autoptr (GOptionContext) option_context = NULL;
-
- if (!priv->option_context)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Tried to configure multiple times");
- return FALSE;
- }
-
- option_context = g_steal_pointer (&priv->option_context);
- return g_option_context_parse (option_context, argc, argv, error);
-}
-
-gboolean
-meta_context_configure (MetaContext *context,
- int *argc,
- char ***argv,
- GError **error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
- MetaCompositorType compositor_type;
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT);
-
- if (!META_CONTEXT_GET_CLASS (context)->configure (context, argc, argv, error))
- {
- priv->state = META_CONTEXT_STATE_TERMINATED;
- return FALSE;
- }
-
- compositor_type = meta_context_get_compositor_type (context);
- switch (compositor_type)
- {
- case META_COMPOSITOR_TYPE_WAYLAND:
- meta_set_is_wayland_compositor (TRUE);
- break;
- case META_COMPOSITOR_TYPE_X11:
- meta_set_is_wayland_compositor (FALSE);
- break;
- }
-
- priv->state = META_CONTEXT_STATE_CONFIGURED;
-
- return TRUE;
-}
-
-static const char *
-compositor_type_to_description (MetaCompositorType compositor_type)
-{
- switch (compositor_type)
- {
- case META_COMPOSITOR_TYPE_WAYLAND:
- return "Wayland display server";
- case META_COMPOSITOR_TYPE_X11:
- return "X11 window and compositing manager";
- }
-
- g_assert_not_reached ();
-}
-
-static void
-init_introspection (MetaContext *context)
-{
-#ifdef HAVE_INTROSPECTION
- g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
-#endif
-}
-
-static gboolean
-meta_context_real_setup (MetaContext *context,
- GError **error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
- MetaBackend *backend;
-
- backend = META_CONTEXT_GET_CLASS (context)->create_backend (context, error);
- if (!backend)
- return FALSE;
-
- priv->backend = backend;
- return TRUE;
-}
-
-gboolean
-meta_context_setup (MetaContext *context,
- GError **error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
- MetaCompositorType compositor_type;
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_CONFIGURED);
-
- if (!priv->plugin_name && priv->plugin_gtype == G_TYPE_NONE)
- {
- priv->state = META_CONTEXT_STATE_TERMINATED;
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "No compositor plugin set");
- return FALSE;
- }
-
- meta_init_debug_utils ();
-
- compositor_type = meta_context_get_compositor_type (context);
- g_message ("Running %s (using mutter %s) as a %s",
- priv->name, VERSION,
- compositor_type_to_description (compositor_type));
-
- if (priv->plugin_name)
- meta_plugin_manager_load (priv->plugin_name);
- else
- meta_plugin_manager_set_plugin_type (priv->plugin_gtype);
-
- init_introspection (context);
-
- if (!META_CONTEXT_GET_CLASS (context)->setup (context, error))
- {
- priv->state = META_CONTEXT_STATE_TERMINATED;
- return FALSE;
- }
-
- priv->state = META_CONTEXT_STATE_SETUP;
- return TRUE;
-}
-
-gboolean
-meta_context_start (MetaContext *context,
- GError **error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_SETUP);
-
- meta_prefs_init ();
-
-#ifdef HAVE_WAYLAND
- if (meta_context_get_compositor_type (context) ==
- META_COMPOSITOR_TYPE_WAYLAND)
- priv->wayland_compositor = meta_wayland_compositor_new (context);
-#endif
-
- priv->display = meta_display_new (context, error);
- if (!priv->display)
- {
- priv->state = META_CONTEXT_STATE_TERMINATED;
- return FALSE;
- }
-
- priv->main_loop = g_main_loop_new (NULL, FALSE);
-
- priv->state = META_CONTEXT_STATE_STARTED;
-
- return TRUE;
-}
-
-gboolean
-meta_context_run_main_loop (MetaContext *context,
- GError **error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_STARTED);
- if (!priv->main_loop)
- {
- priv->state = META_CONTEXT_STATE_TERMINATED;
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Tried to run main loop without having started");
- return FALSE;
- }
-
- priv->state = META_CONTEXT_STATE_RUNNING;
- g_main_loop_run (priv->main_loop);
- priv->state = META_CONTEXT_STATE_TERMINATED;
- g_clear_pointer (&priv->main_loop, g_main_loop_unref);
-
- if (priv->termination_error)
- {
- g_propagate_error (error, g_steal_pointer (&priv->termination_error));
- return FALSE;
- }
-
- return TRUE;
-}
-
-void
-meta_context_terminate (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_warn_if_fail (priv->state == META_CONTEXT_STATE_RUNNING);
- g_warn_if_fail (g_main_loop_is_running (priv->main_loop));
-
- g_main_loop_quit (priv->main_loop);
-}
-
-void
-meta_context_terminate_with_error (MetaContext *context,
- GError *error)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- priv->termination_error = g_steal_pointer (&error);
- meta_context_terminate (context);
-}
-
-void
-meta_context_destroy (MetaContext *context)
-{
- g_object_run_dispose (G_OBJECT (context));
- g_object_unref (context);
-}
-
-static void
-meta_context_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaContext *context = META_CONTEXT (object);
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- switch (prop_id)
- {
- case PROP_NAME:
- g_value_set_string (value, priv->name);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_context_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaContext *context = META_CONTEXT (object);
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- switch (prop_id)
- {
- case PROP_NAME:
- priv->name = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_context_dispose (GObject *object)
-{
- MetaContext *context = META_CONTEXT (object);
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- if (priv->backend)
- meta_backend_prepare_shutdown (priv->backend);
-
-#ifdef HAVE_WAYLAND
- if (priv->wayland_compositor)
- meta_wayland_compositor_prepare_shutdown (priv->wayland_compositor);
-#endif
-
- if (priv->display)
- meta_display_close (priv->display, META_CURRENT_TIME);
- g_clear_object (&priv->display);
-
-#ifdef HAVE_WAYLAND
- g_clear_object (&priv->wayland_compositor);
-#endif
-
- g_clear_pointer (&priv->backend, meta_backend_destroy);
-
- g_clear_pointer (&priv->option_context, g_option_context_free);
- g_clear_pointer (&priv->main_loop, g_main_loop_unref);
-
- G_OBJECT_CLASS (meta_context_parent_class)->dispose (object);
-}
-
-static void
-meta_context_finalize (GObject *object)
-{
- MetaContext *context = META_CONTEXT (object);
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- g_clear_pointer (&priv->gnome_wm_keybindings, g_free);
- g_clear_pointer (&priv->plugin_name, g_free);
- g_clear_pointer (&priv->name, g_free);
-
- G_OBJECT_CLASS (meta_context_parent_class)->finalize (object);
-}
-
-static void
-meta_context_class_init (MetaContextClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = meta_context_get_property;
- object_class->set_property = meta_context_set_property;
- object_class->dispose = meta_context_dispose;
- object_class->finalize = meta_context_finalize;
-
- klass->configure = meta_context_real_configure;
- klass->setup = meta_context_real_setup;
-
- obj_props[PROP_NAME] =
- g_param_spec_string ("name",
- "name",
- "Human readable name",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties (object_class, N_PROPS, obj_props);
-}
-
-static void
-meta_context_init (MetaContext *context)
-{
- MetaContextPrivate *priv = meta_context_get_instance_private (context);
-
- priv->plugin_gtype = G_TYPE_NONE;
- priv->gnome_wm_keybindings = g_strdup ("Mutter");
-
- if (!setlocale (LC_ALL, ""))
- g_warning ("Locale not understood by C library");
- bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-
- priv->option_context = g_option_context_new (NULL);
- g_option_context_set_main_group (priv->option_context,
- g_option_group_new (NULL, NULL, NULL,
- context, NULL));
-}
diff --git a/src/core/meta-fraction.c b/src/core/meta-fraction.c
deleted file mode 100644
index 8090aa411..000000000
--- a/src/core/meta-fraction.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
- * 2002 Thomas Vander Stichele <thomas@apestaart.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Fraction utility functions in this file comes from gstutils.c in gstreamer.
- */
-
-#include "config.h"
-
-#include "core/meta-fraction.h"
-
-#include <glib.h>
-#include <math.h>
-
-#define MAX_TERMS 30
-#define MIN_DIVISOR 1.0e-10
-#define MAX_ERROR 1.0e-20
-
-static int
-greatest_common_divisor (int a,
- int b)
-{
- while (b != 0)
- {
- int temp = a;
-
- a = b;
- b = temp % b;
- }
-
- return ABS (a);
-}
-
-MetaFraction
-meta_fraction_from_double (double src)
-{
- double V, F; /* double being converted */
- int N, D; /* will contain the result */
- int A; /* current term in continued fraction */
- int64_t N1, D1; /* numerator, denominator of last approx */
- int64_t N2, D2; /* numerator, denominator of previous approx */
- int i;
- int gcd;
- gboolean negative = FALSE;
-
- /* initialize fraction being converted */
- F = src;
- if (F < 0.0)
- {
- F = -F;
- negative = TRUE;
- }
-
- V = F;
- /* initialize fractions with 1/0, 0/1 */
- N1 = 1;
- D1 = 0;
- N2 = 0;
- D2 = 1;
- N = 1;
- D = 1;
-
- for (i = 0; i < MAX_TERMS; i++)
- {
- /* get next term */
- A = (gint) F; /* no floor() needed, F is always >= 0 */
- /* get new divisor */
- F = F - A;
-
- /* calculate new fraction in temp */
- N2 = N1 * A + N2;
- D2 = D1 * A + D2;
-
- /* guard against overflow */
- if (N2 > G_MAXINT || D2 > G_MAXINT)
- break;
-
- N = N2;
- D = D2;
-
- /* save last two fractions */
- N2 = N1;
- D2 = D1;
- N1 = N;
- D1 = D;
-
- /* quit if dividing by zero or close enough to target */
- if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR)
- break;
-
- /* Take reciprocal */
- F = 1 / F;
- }
-
- /* fix for overflow */
- if (D == 0)
- {
- N = G_MAXINT;
- D = 1;
- }
-
- /* fix for negative */
- if (negative)
- N = -N;
-
- /* simplify */
- gcd = greatest_common_divisor (N, D);
- if (gcd)
- {
- N /= gcd;
- D /= gcd;
- }
-
- return (MetaFraction) {
- .num = N,
- .denom = D
- };
-}
diff --git a/src/core/meta-fraction.h b/src/core/meta-fraction.h
deleted file mode 100644
index f7ab294cd..000000000
--- a/src/core/meta-fraction.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- *
- * 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/>.
- */
-
-#ifndef META_FRACTION_H
-#define META_FRACTION_H
-
-typedef struct _MetaFraction
-{
- int num;
- int denom;
-} MetaFraction;
-
-MetaFraction meta_fraction_from_double (double src);
-
-#endif /* META_FRACTION_H */
diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h
deleted file mode 100644
index e7bfc5472..000000000
--- a/src/core/meta-gesture-tracker-private.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2014 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#ifndef META_GESTURE_TRACKER_PRIVATE_H
-#define META_GESTURE_TRACKER_PRIVATE_H
-
-#include <glib-object.h>
-
-#include "backends/meta-backend-private.h"
-#include "clutter/clutter.h"
-#include "meta/window.h"
-
-#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ())
-#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker))
-#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
-#define META_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_GESTURE_TRACKER))
-#define META_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_GESTURE_TRACKER))
-#define META_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
-
-typedef struct _MetaGestureTracker MetaGestureTracker;
-typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
-
-struct _MetaGestureTracker
-{
- GObject parent_instance;
-};
-
-struct _MetaGestureTrackerClass
-{
- GObjectClass parent_class;
-
- void (* state_changed) (MetaGestureTracker *tracker,
- ClutterEventSequence *sequence,
- MetaSequenceState state);
-};
-
-GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
-
-MetaGestureTracker * meta_gesture_tracker_new (void);
-
-gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
- const ClutterEvent *event);
-gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
- ClutterEventSequence *sequence,
- MetaSequenceState state);
-MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
- ClutterEventSequence *sequence);
-gint meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker);
-
-#endif /* META_GESTURE_TRACKER_PRIVATE_H */
diff --git a/src/core/meta-gesture-tracker.c b/src/core/meta-gesture-tracker.c
deleted file mode 100644
index 2badf8b82..000000000
--- a/src/core/meta-gesture-tracker.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright (C) 2014 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-/**
- * SECTION:gesture-tracker
- * @Title: MetaGestureTracker
- * @Short_Description: Manages gestures on windows/desktop
- *
- * Forwards touch events to clutter actors, and accepts/rejects touch sequences
- * based on the outcome of those.
- */
-
-#include "config.h"
-
-#include "core/meta-gesture-tracker-private.h"
-
-#include "compositor/meta-surface-actor.h"
-
-#define DISTANCE_THRESHOLD 30
-
-typedef struct _MetaGestureTrackerPrivate MetaGestureTrackerPrivate;
-typedef struct _GestureActionData GestureActionData;
-typedef struct _MetaSequenceInfo MetaSequenceInfo;
-
-struct _MetaSequenceInfo
-{
- MetaGestureTracker *tracker;
- ClutterEventSequence *sequence;
- MetaSequenceState state;
- guint autodeny_timeout_id;
- gfloat start_x;
- gfloat start_y;
-};
-
-struct _GestureActionData
-{
- ClutterGestureAction *gesture;
- MetaSequenceState state;
- gulong gesture_begin_id;
- gulong gesture_end_id;
- gulong gesture_cancel_id;
-};
-
-struct _MetaGestureTrackerPrivate
-{
- GHashTable *sequences; /* Hashtable of ClutterEventSequence->MetaSequenceInfo */
-
- MetaSequenceState stage_state;
- GArray *stage_gestures; /* Array of GestureActionData */
- GList *listeners; /* List of ClutterGestureAction */
- guint autodeny_timeout;
-};
-
-enum
-{
- PROP_0,
- PROP_AUTODENY_TIMEOUT,
- PROP_LAST,
-};
-
-static GParamSpec *obj_props[PROP_LAST];
-
-enum
-{
- STATE_CHANGED,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS] = { 0 };
-
-#define DEFAULT_AUTODENY_TIMEOUT 150
-
-static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
-
-G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
-
-static void
-meta_gesture_tracker_finalize (GObject *object)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
-
- g_hash_table_destroy (priv->sequences);
- g_array_free (priv->stage_gestures, TRUE);
- g_list_free (priv->listeners);
-
- G_OBJECT_CLASS (meta_gesture_tracker_parent_class)->finalize (object);
-}
-
-static void
-meta_gesture_tracker_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
-
- switch (prop_id)
- {
- case PROP_AUTODENY_TIMEOUT:
- priv->autodeny_timeout = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_gesture_tracker_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
-
- switch (prop_id)
- {
- case PROP_AUTODENY_TIMEOUT:
- g_value_set_uint (value, priv->autodeny_timeout);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_gesture_tracker_finalize;
- object_class->set_property = meta_gesture_tracker_set_property;
- object_class->get_property = meta_gesture_tracker_get_property;
-
- obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout",
- "Auto-deny timeout",
- "Auto-deny timeout",
- 0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT,
- G_PARAM_STATIC_STRINGS |
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- g_object_class_install_properties (object_class, PROP_LAST, obj_props);
-
- signals[STATE_CHANGED] =
- g_signal_new ("state-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MetaGestureTrackerClass, state_changed),
- NULL, NULL, NULL,
- G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
-}
-
-static gboolean
-autodeny_sequence (gpointer user_data)
-{
- MetaSequenceInfo *info = user_data;
-
- /* Deny the sequence automatically after the given timeout */
- if (info->state == META_SEQUENCE_NONE)
- meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
- META_SEQUENCE_REJECTED);
-
- info->autodeny_timeout_id = 0;
- return G_SOURCE_REMOVE;
-}
-
-static MetaSequenceInfo *
-meta_sequence_info_new (MetaGestureTracker *tracker,
- const ClutterEvent *event)
-{
- MetaGestureTrackerPrivate *priv;
- MetaSequenceInfo *info;
- guint ms;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- ms = priv->autodeny_timeout;
-
- info = g_new0 (MetaSequenceInfo, 1);
- info->tracker = tracker;
- info->sequence = event->touch.sequence;
- info->state = META_SEQUENCE_NONE;
- info->autodeny_timeout_id = g_timeout_add (ms, autodeny_sequence, info);
-
- clutter_event_get_coords (event, &info->start_x, &info->start_y);
-
- return info;
-}
-
-static void
-meta_sequence_info_free (MetaSequenceInfo *info)
-{
- g_clear_handle_id (&info->autodeny_timeout_id, g_source_remove);
-
- if (info->state == META_SEQUENCE_NONE)
- meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
- META_SEQUENCE_REJECTED);
- g_free (info);
-}
-
-static gboolean
-state_is_applicable (MetaSequenceState prev_state,
- MetaSequenceState state)
-{
- if (prev_state == META_SEQUENCE_PENDING_END)
- return FALSE;
-
- /* Don't allow reverting to none */
- if (state == META_SEQUENCE_NONE)
- return FALSE;
-
- /* PENDING_END state is final */
- if (prev_state == META_SEQUENCE_PENDING_END)
- return FALSE;
-
- /* Sequences must be accepted/denied before PENDING_END */
- if (prev_state == META_SEQUENCE_NONE &&
- state == META_SEQUENCE_PENDING_END)
- return FALSE;
-
- /* Make sequences stick to their accepted/denied state */
- if (state != META_SEQUENCE_PENDING_END &&
- prev_state != META_SEQUENCE_NONE)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-meta_gesture_tracker_set_state (MetaGestureTracker *tracker,
- MetaSequenceState state)
-{
- MetaGestureTrackerPrivate *priv;
- ClutterEventSequence *sequence;
- GHashTableIter iter;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
-
- if (priv->stage_state != state &&
- !state_is_applicable (priv->stage_state, state))
- return FALSE;
-
- g_hash_table_iter_init (&iter, priv->sequences);
- priv->stage_state = state;
-
- while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, NULL))
- meta_gesture_tracker_set_sequence_state (tracker, sequence, state);
-
- return TRUE;
-}
-
-static gboolean
-gesture_begin_cb (ClutterGestureAction *gesture,
- ClutterActor *actor,
- MetaGestureTracker *tracker)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
-
- if (!g_list_find (priv->listeners, gesture) &&
- meta_gesture_tracker_set_state (tracker, META_SEQUENCE_ACCEPTED))
- priv->listeners = g_list_prepend (priv->listeners, gesture);
-
- return TRUE;
-}
-
-static void
-gesture_end_cb (ClutterGestureAction *gesture,
- ClutterActor *actor,
- MetaGestureTracker *tracker)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- priv->listeners = g_list_remove (priv->listeners, gesture);
-
- if (!priv->listeners)
- meta_gesture_tracker_untrack_stage (tracker);
-}
-
-static void
-gesture_cancel_cb (ClutterGestureAction *gesture,
- ClutterActor *actor,
- MetaGestureTracker *tracker)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
-
- if (g_list_find (priv->listeners, gesture))
- {
- priv->listeners = g_list_remove (priv->listeners, gesture);
-
- if (!priv->listeners)
- meta_gesture_tracker_set_state (tracker, META_SEQUENCE_PENDING_END);
- }
-}
-
-static gboolean
-cancel_and_unref_gesture_cb (ClutterGestureAction *action)
-{
- clutter_gesture_action_cancel (action);
- g_object_unref (action);
- return G_SOURCE_REMOVE;
-}
-
-static void
-clear_gesture_data (GestureActionData *data)
-{
- g_clear_signal_handler (&data->gesture_begin_id, data->gesture);
- g_clear_signal_handler (&data->gesture_end_id, data->gesture);
- g_clear_signal_handler (&data->gesture_cancel_id, data->gesture);
-
- /* Defer cancellation to an idle, as it may happen within event handling */
- g_idle_add ((GSourceFunc) cancel_and_unref_gesture_cb, data->gesture);
-}
-
-static void
-meta_gesture_tracker_init (MetaGestureTracker *tracker)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- priv->sequences = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) meta_sequence_info_free);
- priv->stage_gestures = g_array_new (FALSE, FALSE, sizeof (GestureActionData));
- g_array_set_clear_func (priv->stage_gestures, (GDestroyNotify) clear_gesture_data);
-}
-
-MetaGestureTracker *
-meta_gesture_tracker_new (void)
-{
- return g_object_new (META_TYPE_GESTURE_TRACKER, NULL);
-}
-
-static void
-meta_gesture_tracker_track_stage (MetaGestureTracker *tracker,
- ClutterActor *stage)
-{
- MetaGestureTrackerPrivate *priv;
- GList *actions, *l;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- actions = clutter_actor_get_actions (stage);
-
- for (l = actions; l; l = l->next)
- {
- GestureActionData data;
-
- if (!CLUTTER_IS_GESTURE_ACTION (l->data))
- continue;
-
- data.gesture = g_object_ref (l->data);
- data.state = META_SEQUENCE_NONE;
- data.gesture_begin_id =
- g_signal_connect (data.gesture, "gesture-begin",
- G_CALLBACK (gesture_begin_cb), tracker);
- data.gesture_end_id =
- g_signal_connect (data.gesture, "gesture-end",
- G_CALLBACK (gesture_end_cb), tracker);
- data.gesture_cancel_id =
- g_signal_connect (data.gesture, "gesture-cancel",
- G_CALLBACK (gesture_cancel_cb), tracker);
- g_array_append_val (priv->stage_gestures, data);
- }
-
- g_list_free (actions);
-}
-
-static void
-meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker)
-{
- MetaGestureTrackerPrivate *priv;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- priv->stage_state = META_SEQUENCE_NONE;
-
- g_hash_table_remove_all (priv->sequences);
-
- if (priv->stage_gestures->len > 0)
- g_array_remove_range (priv->stage_gestures, 0, priv->stage_gestures->len);
-
- g_list_free (priv->listeners);
- priv->listeners = NULL;
-}
-
-gboolean
-meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
- const ClutterEvent *event)
-{
- MetaGestureTrackerPrivate *priv;
- ClutterEventSequence *sequence;
- MetaSequenceState state;
- MetaSequenceInfo *info;
- ClutterActor *stage;
- gfloat x, y;
-
- sequence = clutter_event_get_event_sequence (event);
-
- if (!sequence)
- return FALSE;
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- stage = CLUTTER_ACTOR (clutter_event_get_stage (event));
-
- switch (event->type)
- {
- case CLUTTER_TOUCH_BEGIN:
- if (g_hash_table_size (priv->sequences) == 0)
- meta_gesture_tracker_track_stage (tracker, stage);
-
- info = meta_sequence_info_new (tracker, event);
- g_hash_table_insert (priv->sequences, sequence, info);
-
- if (priv->stage_gestures->len == 0)
- {
- /* If no gestures are attached, reject the sequence right away */
- meta_gesture_tracker_set_sequence_state (tracker, sequence,
- META_SEQUENCE_REJECTED);
- }
- else if (priv->stage_state != META_SEQUENCE_NONE)
- {
- /* Make the sequence state match the general state */
- meta_gesture_tracker_set_sequence_state (tracker, sequence,
- priv->stage_state);
- }
- state = info->state;
- break;
- case CLUTTER_TOUCH_END:
- info = g_hash_table_lookup (priv->sequences, sequence);
-
- if (!info)
- return FALSE;
-
- /* If nothing was done yet about the sequence, reject it so X11
- * clients may see it
- */
- if (info->state == META_SEQUENCE_NONE)
- meta_gesture_tracker_set_sequence_state (tracker, sequence,
- META_SEQUENCE_REJECTED);
-
- state = info->state;
- g_hash_table_remove (priv->sequences, sequence);
-
- if (g_hash_table_size (priv->sequences) == 0)
- meta_gesture_tracker_untrack_stage (tracker);
- break;
- case CLUTTER_TOUCH_UPDATE:
- info = g_hash_table_lookup (priv->sequences, sequence);
-
- if (!info)
- return FALSE;
-
- clutter_event_get_coords (event, &x, &y);
-
- if (info->state == META_SEQUENCE_NONE &&
- (ABS (info->start_x - x) > DISTANCE_THRESHOLD ||
- ABS (info->start_y - y) > DISTANCE_THRESHOLD))
- meta_gesture_tracker_set_sequence_state (tracker, sequence,
- META_SEQUENCE_REJECTED);
- state = info->state;
- break;
- default:
- return FALSE;
- break;
- }
-
- /* As soon as a sequence is accepted, we replay it to
- * the stage as a captured event, and make sure it's never
- * propagated anywhere else. Since ClutterGestureAction does
- * all its event handling from a captured-event handler on
- * the stage, this effectively acts as a "sequence grab" on
- * gesture actions.
- *
- * Sequences that aren't (yet or never) in an accepted state
- * will go through, these events will get processed through
- * the compositor, and eventually through clutter, still
- * triggering the gestures capturing events on the stage, and
- * possibly resulting in MetaSequenceState changes.
- */
- if (state == META_SEQUENCE_ACCEPTED)
- {
- clutter_actor_event (CLUTTER_ACTOR (clutter_event_get_stage (event)),
- event, TRUE);
- return TRUE;
- }
-
- return FALSE;
-}
-
-gboolean
-meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
- ClutterEventSequence *sequence,
- MetaSequenceState state)
-{
- MetaGestureTrackerPrivate *priv;
- MetaSequenceInfo *info;
-
- g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- info = g_hash_table_lookup (priv->sequences, sequence);
-
- if (!info)
- return FALSE;
- else if (state == info->state)
- return TRUE;
-
- if (!state_is_applicable (info->state, state))
- return FALSE;
-
- /* Unset autodeny timeout */
- g_clear_handle_id (&info->autodeny_timeout_id, g_source_remove);
-
- info->state = state;
- g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
-
- /* If the sequence was denied, set immediately to PENDING_END after emission */
- if (state == META_SEQUENCE_REJECTED)
- {
- info->state = META_SEQUENCE_PENDING_END;
- g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
- }
-
- return TRUE;
-}
-
-MetaSequenceState
-meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
- ClutterEventSequence *sequence)
-{
- MetaGestureTrackerPrivate *priv;
- MetaSequenceInfo *info;
-
- g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), META_SEQUENCE_PENDING_END);
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- info = g_hash_table_lookup (priv->sequences, sequence);
-
- if (!info)
- return META_SEQUENCE_PENDING_END;
-
- return info->state;
-}
-
-gint
-meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker)
-{
- MetaGestureTrackerPrivate *priv;
-
- g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), 0);
-
- priv = meta_gesture_tracker_get_instance_private (tracker);
- return g_hash_table_size (priv->sequences);
-}
diff --git a/src/core/meta-inhibit-shortcuts-dialog-default-private.h b/src/core/meta-inhibit-shortcuts-dialog-default-private.h
deleted file mode 100644
index 7f65494ef..000000000
--- a/src/core/meta-inhibit-shortcuts-dialog-default-private.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2017 Red Hat
- *
- * 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/>.
- *
- */
-
-#ifndef META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT_H
-#define META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT_H
-
-#include <glib-object.h>
-
-#include "meta/meta-plugin.h"
-
-#define META_TYPE_INHIBIT_SHORTCUTS_DIALOG_DEFAULT (meta_inhibit_shortcuts_dialog_default_get_type ())
-G_DECLARE_FINAL_TYPE (MetaInhibitShortcutsDialogDefault,
- meta_inhibit_shortcuts_dialog_default,
- META, INHIBIT_SHORTCUTS_DIALOG_DEFAULT,
- GObject)
-
-MetaInhibitShortcutsDialog * meta_inhibit_shortcuts_dialog_default_new (MetaWindow *window);
-
-#endif /* META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT_H */
diff --git a/src/core/meta-inhibit-shortcuts-dialog-default.c b/src/core/meta-inhibit-shortcuts-dialog-default.c
deleted file mode 100644
index d90234d6a..000000000
--- a/src/core/meta-inhibit-shortcuts-dialog-default.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2001, 2002 Havoc Pennington
- * Copyright (C) 2004 Elijah Newren
- * Copyright (C) 2017 Red Hat
- *
- * 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/>.
- *
- */
-
-#include "config.h"
-
-#include "core/meta-inhibit-shortcuts-dialog-default-private.h"
-#include "core/util-private.h"
-#include "core/window-private.h"
-#include "meta/meta-inhibit-shortcuts-dialog.h"
-
-typedef struct _MetaInhibitShortcutsDialogDefaultPrivate MetaInhibitShortcutsDialogDefaultPrivate;
-
-struct _MetaInhibitShortcutsDialogDefault
-{
- GObject parent_instance;
- MetaWindow *window;
-};
-
-enum
-{
- PROP_0,
- PROP_WINDOW,
- N_PROPS
-};
-
-static void meta_inhibit_shortcuts_dialog_iface_init (MetaInhibitShortcutsDialogInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (MetaInhibitShortcutsDialogDefault, meta_inhibit_shortcuts_dialog_default,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (META_TYPE_INHIBIT_SHORTCUTS_DIALOG,
- meta_inhibit_shortcuts_dialog_iface_init))
-
-static void
-meta_inhibit_shortcuts_dialog_default_show (MetaInhibitShortcutsDialog *dialog)
-{
- /* Default to allow shortcuts inhibitor, but complain that no dialog is implemented */
- g_warning ("No MetaInhibitShortcutDialog implementation, falling back on allowing");
- meta_inhibit_shortcuts_dialog_response (dialog, META_INHIBIT_SHORTCUTS_DIALOG_RESPONSE_ALLOW);
-}
-
-static void
-meta_inhibit_shortcuts_dialog_default_hide (MetaInhibitShortcutsDialog *dialog)
-{
-}
-
-static void
-meta_inhibit_shortcuts_dialog_iface_init (MetaInhibitShortcutsDialogInterface *iface)
-{
- iface->show = meta_inhibit_shortcuts_dialog_default_show;
- iface->hide = meta_inhibit_shortcuts_dialog_default_hide;
-}
-
-static void
-meta_inhibit_shortcuts_dialog_default_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaInhibitShortcutsDialogDefault *dialog;
-
- dialog = META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- dialog->window = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_inhibit_shortcuts_dialog_default_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaInhibitShortcutsDialogDefault *dialog;
-
- dialog = META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT (object);
-
- switch (prop_id)
- {
- case PROP_WINDOW:
- g_value_set_object (value, dialog->window);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_inhibit_shortcuts_dialog_default_class_init (MetaInhibitShortcutsDialogDefaultClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->set_property = meta_inhibit_shortcuts_dialog_default_set_property;
- object_class->get_property = meta_inhibit_shortcuts_dialog_default_get_property;
-
- g_object_class_override_property (object_class, PROP_WINDOW, "window");
-}
-
-static void
-meta_inhibit_shortcuts_dialog_default_init (MetaInhibitShortcutsDialogDefault *dialog)
-{
-}
-
-MetaInhibitShortcutsDialog *
-meta_inhibit_shortcuts_dialog_default_new (MetaWindow *window)
-{
- return g_object_new (META_TYPE_INHIBIT_SHORTCUTS_DIALOG_DEFAULT,
- "window", window,
- NULL);
-}
diff --git a/src/core/meta-inhibit-shortcuts-dialog.c b/src/core/meta-inhibit-shortcuts-dialog.c
deleted file mode 100644
index d5b4e5a05..000000000
--- a/src/core/meta-inhibit-shortcuts-dialog.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2017 Red Hat
- *
- * 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/>.
- *
- */
-
-#include "config.h"
-
-#include "core/window-private.h"
-#include "meta/meta-inhibit-shortcuts-dialog.h"
-#include "meta/meta-enum-types.h"
-
-enum
-{
- RESPONSE,
- LAST_SIGNAL
-};
-
-static guint inhibit_dialog_signals[LAST_SIGNAL] = { 0, };
-
-G_DEFINE_INTERFACE (MetaInhibitShortcutsDialog, meta_inhibit_shortcuts_dialog, G_TYPE_OBJECT)
-
-static void
-meta_inhibit_shortcuts_dialog_default_init (MetaInhibitShortcutsDialogInterface *iface)
-{
- g_object_interface_install_property (iface,
- g_param_spec_object ("window",
- "Window",
- "Window",
- META_TYPE_WINDOW,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
- inhibit_dialog_signals[RESPONSE] =
- g_signal_new ("response",
- G_TYPE_FROM_INTERFACE (iface),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1, META_TYPE_INHIBIT_SHORTCUTS_DIALOG_RESPONSE);
-}
-
-/**
- * meta_inhibit_shortcuts_dialog_show:
- * @dialog: a #MetaInhibitShortcutsDialog
- *
- * Shows the inhibit shortcuts dialog.
- **/
-void
-meta_inhibit_shortcuts_dialog_show (MetaInhibitShortcutsDialog *dialog)
-{
- MetaInhibitShortcutsDialogInterface *iface;
-
- g_return_if_fail (META_IS_INHIBIT_SHORTCUTS_DIALOG (dialog));
-
- iface = META_INHIBIT_SHORTCUTS_DIALOG_GET_IFACE (dialog);
- iface->show (dialog);
-}
-
-/**
- * meta_inhibit_shortcuts_dialog_hide:
- * @dialog: a #MetaInhibitShortcutsDialog
- *
- * Hides the inhibit shortcuts dialog.
- **/
-void
-meta_inhibit_shortcuts_dialog_hide (MetaInhibitShortcutsDialog *dialog)
-{
- MetaInhibitShortcutsDialogInterface *iface;
-
- g_return_if_fail (META_IS_INHIBIT_SHORTCUTS_DIALOG (dialog));
-
- iface = META_INHIBIT_SHORTCUTS_DIALOG_GET_IFACE (dialog);
- iface->hide (dialog);
-}
-
-/**
- * meta_inhibit_shortcuts_dialog_response:
- * @dialog: a #MetaInhibitShortcutsDialog
- * @response: a #MetaInhibitShortcutsDialogResponse
- *
- * Responds and closes the dialog. To be called by #MetaInhibitShortcutsDialog
- * implementations.
- **/
-void
-meta_inhibit_shortcuts_dialog_response (MetaInhibitShortcutsDialog *dialog,
- MetaInhibitShortcutsDialogResponse response)
-{
- g_signal_emit (dialog, inhibit_dialog_signals[RESPONSE], 0, response);
- meta_inhibit_shortcuts_dialog_hide (dialog);
-}
diff --git a/src/core/meta-launch-context.c b/src/core/meta-launch-context.c
deleted file mode 100644
index 984338c1b..000000000
--- a/src/core/meta-launch-context.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include <gio/gdesktopappinfo.h>
-
-#include "core/display-private.h"
-#include "meta/meta-launch-context.h"
-#include "x11/meta-startup-notification-x11.h"
-
-typedef struct _MetaLaunchContext MetaLaunchContext;
-
-struct _MetaLaunchContext
-{
- GAppLaunchContext parent_instance;
- MetaDisplay *display;
- MetaWorkspace *workspace;
- uint32_t timestamp;
-};
-
-G_DEFINE_TYPE (MetaLaunchContext, meta_launch_context,
- G_TYPE_APP_LAUNCH_CONTEXT)
-
-enum
-{
- PROP_DISPLAY = 1,
- PROP_WORKSPACE,
- PROP_TIMESTAMP,
- N_PROPS
-};
-
-static GParamSpec *props[N_PROPS] = { 0, };
-
-static void
-meta_launch_context_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
-
- switch (prop_id)
- {
- case PROP_DISPLAY:
- context->display = g_value_get_object (value);
- break;
- case PROP_WORKSPACE:
- meta_launch_context_set_workspace (context,
- g_value_get_object (value));
- break;
- case PROP_TIMESTAMP:
- meta_launch_context_set_timestamp (context,
- g_value_get_uint (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_launch_context_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
-
- switch (prop_id)
- {
- case PROP_DISPLAY:
- g_value_set_object (value, context->display);
- break;
- case PROP_WORKSPACE:
- g_value_set_object (value, context->workspace);
- break;
- case PROP_TIMESTAMP:
- g_value_set_uint (value, context->timestamp);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_launch_context_finalize (GObject *object)
-{
- G_OBJECT_CLASS (meta_launch_context_parent_class)->finalize (object);
-}
-
-static void
-meta_launch_context_constructed (GObject *object)
-{
- MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
- const char *x11_display, *wayland_display;
-
- G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object);
-
- x11_display = getenv ("DISPLAY");
- wayland_display = getenv ("WAYLAND_DISPLAY");
-
- if (x11_display)
- {
- g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
- "DISPLAY", x11_display);
- }
-
- if (wayland_display)
- {
- g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
- "WAYLAND_DISPLAY", wayland_display);
- }
-}
-
-static gchar *
-meta_launch_context_get_startup_notify_id (GAppLaunchContext *launch_context,
- GAppInfo *info,
- GList *files)
-{
- MetaLaunchContext *context = META_LAUNCH_CONTEXT (launch_context);
- MetaDisplay *display = context->display;
- int workspace_idx = -1;
- char *startup_id = NULL;
-
- if (context->workspace)
- workspace_idx = meta_workspace_index (context->workspace);
-
- if (display->x11_display)
- {
- /* If there is a X11 display, we prefer going entirely through
- * libsn, as SnMonitor expects to keep a view of the full lifetime
- * of the startup sequence. We can't avoid it when launching and
- * expect that a "remove" message from a X11 client will be handled.
- */
- startup_id =
- meta_x11_startup_notification_launch (display->x11_display,
- info,
- context->timestamp,
- workspace_idx);
- }
-
- if (!startup_id)
- {
- const char *application_id = NULL;
- MetaStartupNotification *sn;
- MetaStartupSequence *seq;
-
- startup_id = g_uuid_string_random ();
-
- /* Fallback through inserting our own startup sequence, this
- * will be enough for wayland clients.
- */
- if (G_IS_DESKTOP_APP_INFO (info))
- {
- application_id =
- g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (info));
- }
-
- sn = meta_display_get_startup_notification (context->display);
- seq = g_object_new (META_TYPE_STARTUP_SEQUENCE,
- "id", startup_id,
- "application-id", application_id,
- "name", g_app_info_get_name (info),
- "workspace", workspace_idx,
- "timestamp", context->timestamp,
- NULL);
-
- meta_startup_notification_add_sequence (sn, seq);
- g_object_unref (seq);
- }
-
- return startup_id;
-}
-
-static void
-meta_launch_context_launch_failed (GAppLaunchContext *launch_context,
- const gchar *startup_notify_id)
-{
- MetaLaunchContext *context = META_LAUNCH_CONTEXT (launch_context);
- MetaStartupNotification *sn;
- MetaStartupSequence *seq;
-
- sn = meta_display_get_startup_notification (context->display);
- seq = meta_startup_notification_lookup_sequence (sn, startup_notify_id);
-
- if (seq)
- {
- meta_startup_sequence_complete (seq);
- meta_startup_notification_remove_sequence (sn, seq);
- }
-}
-
-static void
-meta_launch_context_class_init (MetaLaunchContextClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GAppLaunchContextClass *ctx_class = G_APP_LAUNCH_CONTEXT_CLASS (klass);
-
- object_class->finalize = meta_launch_context_finalize;
- object_class->constructed = meta_launch_context_constructed;
- object_class->set_property = meta_launch_context_set_property;
- object_class->get_property = meta_launch_context_get_property;
-
- ctx_class->get_startup_notify_id = meta_launch_context_get_startup_notify_id;
- ctx_class->launch_failed = meta_launch_context_launch_failed;
-
- props[PROP_DISPLAY] =
- g_param_spec_object ("display",
- "display",
- "Display",
- META_TYPE_DISPLAY,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
- props[PROP_WORKSPACE] =
- g_param_spec_object ("workspace",
- "workspace",
- "Workspace",
- META_TYPE_WORKSPACE,
- G_PARAM_READWRITE);
- props[PROP_TIMESTAMP] =
- g_param_spec_uint ("timestamp",
- "timestamp",
- "Timestamp",
- 0, G_MAXUINT32, 0,
- G_PARAM_READWRITE);
-
- g_object_class_install_properties (object_class, N_PROPS, props);
-}
-
-static void
-meta_launch_context_init (MetaLaunchContext *context)
-{
-}
-
-void
-meta_launch_context_set_workspace (MetaLaunchContext *context,
- MetaWorkspace *workspace)
-{
- g_return_if_fail (META_IS_LAUNCH_CONTEXT (context));
- g_return_if_fail (META_IS_WORKSPACE (workspace));
-
- g_set_object (&context->workspace, workspace);
-}
-
-void
-meta_launch_context_set_timestamp (MetaLaunchContext *context,
- uint32_t timestamp)
-{
- g_return_if_fail (META_IS_LAUNCH_CONTEXT (context));
-
- context->timestamp = timestamp;
-}
diff --git a/src/core/meta-pad-action-mapper.c b/src/core/meta-pad-action-mapper.c
deleted file mode 100644
index 7c78c4014..000000000
--- a/src/core/meta-pad-action-mapper.c
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * Copyright (C) 2014-2020 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include <glib/gi18n-lib.h>
-#include <gsettings-desktop-schemas/gdesktop-enums.h>
-
-#ifdef HAVE_LIBWACOM
-#include <libwacom/libwacom.h>
-#endif
-
-#include "core/meta-pad-action-mapper.h"
-#include "backends/meta-input-device-private.h"
-#include "backends/meta-logical-monitor.h"
-#include "backends/meta-monitor.h"
-#include "core/display-private.h"
-
-typedef struct _PadMappingInfo PadMappingInfo;
-
-struct _PadMappingInfo
-{
- ClutterInputDevice *device;
- GSettings *settings;
- guint *group_modes;
-};
-
-typedef enum
-{
- META_PAD_DIRECTION_NONE = -1,
- META_PAD_DIRECTION_UP = 0,
- META_PAD_DIRECTION_DOWN,
- META_PAD_DIRECTION_CW,
- META_PAD_DIRECTION_CCW,
-} MetaPadDirection;
-
-struct _MetaPadActionMapper
-{
- GObject parent_class;
-
- GHashTable *pads;
- ClutterSeat *seat;
- ClutterVirtualInputDevice *virtual_pad_keyboard;
- MetaMonitorManager *monitor_manager;
-
- /* Pad ring/strip emission */
- struct {
- ClutterInputDevice *pad;
- MetaPadActionType action;
- guint number;
- double value;
- } last_pad_action_info;
-};
-
-G_DEFINE_TYPE (MetaPadActionMapper, meta_pad_action_mapper, G_TYPE_OBJECT)
-
-static void
-meta_pad_action_mapper_finalize (GObject *object)
-{
- MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (object);
-
- g_hash_table_unref (mapper->pads);
- g_object_unref (mapper->monitor_manager);
- g_clear_object (&mapper->virtual_pad_keyboard);
-
- G_OBJECT_CLASS (meta_pad_action_mapper_parent_class)->finalize (object);
-}
-
-static void
-meta_pad_action_mapper_class_init (MetaPadActionMapperClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_pad_action_mapper_finalize;
-}
-
-static GSettings *
-lookup_device_settings (ClutterInputDevice *device)
-{
- const char *vendor, *product;
- GSettings *settings;
- char *path;
-
- vendor = clutter_input_device_get_vendor_id (device);
- product = clutter_input_device_get_product_id (device);
- path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/",
- vendor, product);
-
- settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet",
- path);
- g_free (path);
-
- return settings;
-}
-
-static PadMappingInfo *
-pad_mapping_info_new (ClutterInputDevice *pad)
-{
- PadMappingInfo *info;
-
- info = g_new0 (PadMappingInfo, 1);
- info->device = pad;
- info->settings = lookup_device_settings (pad);
- info->group_modes =
- g_new0 (guint, clutter_input_device_get_n_mode_groups (pad));
-
- return info;
-}
-
-static void
-pad_mapping_info_free (PadMappingInfo *info)
-{
- g_object_unref (info->settings);
- g_free (info->group_modes);
- g_free (info);
-}
-
-static void
-device_added (ClutterSeat *seat,
- ClutterInputDevice *device,
- MetaPadActionMapper *mapper)
-{
- PadMappingInfo *info;
-
- if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
- {
- info = pad_mapping_info_new (device);
- g_hash_table_insert (mapper->pads, device, info);
- }
-}
-
-static void
-device_removed (ClutterSeat *seat,
- ClutterInputDevice *device,
- MetaPadActionMapper *mapper)
-{
- g_hash_table_remove (mapper->pads, device);
-}
-
-static void
-meta_pad_action_mapper_init (MetaPadActionMapper *mapper)
-{
- mapper->pads = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) pad_mapping_info_free);
-
- mapper->seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
- g_signal_connect (mapper->seat, "device-added",
- G_CALLBACK (device_added), mapper);
- g_signal_connect (mapper->seat, "device-removed",
- G_CALLBACK (device_removed), mapper);
-}
-
-MetaPadActionMapper *
-meta_pad_action_mapper_new (MetaMonitorManager *monitor_manager)
-{
- MetaPadActionMapper *action_mapper;
-
- action_mapper = g_object_new (META_TYPE_PAD_ACTION_MAPPER, NULL);
- g_set_object (&action_mapper->monitor_manager, monitor_manager);
-
- return action_mapper;
-}
-
-static GSettings *
-lookup_pad_action_settings (ClutterInputDevice *device,
- MetaPadActionType action,
- guint number,
- MetaPadDirection direction,
- int mode)
-{
- const char *vendor, *product, *action_type, *detail_type = NULL;
- GSettings *settings;
- GString *path;
- char action_label;
-
- vendor = clutter_input_device_get_vendor_id (device);
- product = clutter_input_device_get_product_id (device);
-
- action_label = 'A' + number;
-
- switch (action)
- {
- case META_PAD_ACTION_BUTTON:
- action_type = "button";
- break;
- case META_PAD_ACTION_RING:
- g_assert (direction == META_PAD_DIRECTION_CW ||
- direction == META_PAD_DIRECTION_CCW);
- action_type = "ring";
- detail_type = (direction == META_PAD_DIRECTION_CW) ? "cw" : "ccw";
- break;
- case META_PAD_ACTION_STRIP:
- g_assert (direction == META_PAD_DIRECTION_UP ||
- direction == META_PAD_DIRECTION_DOWN);
- action_type = "strip";
- detail_type = (direction == META_PAD_DIRECTION_UP) ? "up" : "down";
- break;
- default:
- return NULL;
- }
-
- path = g_string_new (NULL);
- g_string_append_printf (path, "/org/gnome/desktop/peripherals/tablets/%s:%s/%s%c",
- vendor, product, action_type, action_label);
-
- if (detail_type)
- g_string_append_printf (path, "-%s", detail_type);
-
- if (mode >= 0)
- g_string_append_printf (path, "-mode-%d", mode);
-
- g_string_append_c (path, '/');
-
- settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
- path->str);
- g_string_free (path, TRUE);
-
- return settings;
-}
-
-static GDesktopPadButtonAction
-meta_pad_action_mapper_get_button_action (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- guint button)
-{
- GDesktopPadButtonAction action;
- GSettings *settings;
-
- g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper),
- G_DESKTOP_PAD_BUTTON_ACTION_NONE);
- g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad),
- G_DESKTOP_PAD_BUTTON_ACTION_NONE);
-
- settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
- button, META_PAD_DIRECTION_NONE, -1);
- action = g_settings_get_enum (settings, "action");
- g_object_unref (settings);
-
- return action;
-}
-
-static gboolean
-cycle_logical_monitors (MetaPadActionMapper *mapper,
- gboolean skip_all_monitors,
- MetaLogicalMonitor *current_logical_monitor,
- MetaLogicalMonitor **next_logical_monitor)
-{
- MetaMonitorManager *monitor_manager = mapper->monitor_manager;
- GList *logical_monitors;
-
- /* We cycle between:
- * - the span of all monitors (current_output = NULL), only for
- * non-integrated devices.
- * - each monitor individually.
- */
-
- logical_monitors =
- meta_monitor_manager_get_logical_monitors (monitor_manager);
-
- if (!current_logical_monitor)
- {
- *next_logical_monitor = logical_monitors->data;
- }
- else
- {
- GList *l;
-
- l = g_list_find (logical_monitors, current_logical_monitor);
- if (l->next)
- *next_logical_monitor = l->next->data;
- else if (skip_all_monitors)
- *next_logical_monitor = logical_monitors->data;
- else
- *next_logical_monitor = NULL;
- }
-
- return TRUE;
-}
-
-static MetaMonitor *
-logical_monitor_find_monitor (MetaLogicalMonitor *logical_monitor,
- const char *vendor,
- const char *product,
- const char *serial)
-{
- GList *monitors;
- GList *l;
-
- monitors = meta_logical_monitor_get_monitors (logical_monitor);
- for (l = monitors; l; l = l->next)
- {
- MetaMonitor *monitor = l->data;
-
- if (g_strcmp0 (meta_monitor_get_vendor (monitor), vendor) == 0 &&
- g_strcmp0 (meta_monitor_get_product (monitor), product) == 0 &&
- g_strcmp0 (meta_monitor_get_serial (monitor), serial) == 0)
- return monitor;
- }
-
- return NULL;
-}
-
-static void
-meta_pad_action_mapper_find_monitor (MetaPadActionMapper *mapper,
- GSettings *settings,
- ClutterInputDevice *device,
- MetaMonitor **out_monitor,
- MetaLogicalMonitor **out_logical_monitor)
-{
- MetaMonitorManager *monitor_manager;
- MetaMonitor *monitor;
- guint n_values;
- GList *logical_monitors;
- GList *l;
- char **edid;
-
- edid = g_settings_get_strv (settings, "output");
- n_values = g_strv_length (edid);
-
- if (n_values != 3)
- {
- g_warning ("EDID configuration for device '%s' "
- "is incorrect, must have 3 values",
- clutter_input_device_get_device_name (device));
- goto out;
- }
-
- if (!*edid[0] && !*edid[1] && !*edid[2])
- goto out;
-
- monitor_manager = mapper->monitor_manager;
- logical_monitors =
- meta_monitor_manager_get_logical_monitors (monitor_manager);
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
-
- monitor = logical_monitor_find_monitor (logical_monitor,
- edid[0], edid[1], edid[2]);
- if (monitor)
- {
- if (out_monitor)
- *out_monitor = monitor;
- if (out_logical_monitor)
- *out_logical_monitor = logical_monitor;
- break;
- }
- }
-
-out:
- g_strfreev (edid);
-}
-
-static void
-meta_pad_action_mapper_cycle_tablet_output (MetaPadActionMapper *mapper,
- ClutterInputDevice *device)
-{
- PadMappingInfo *info;
- MetaLogicalMonitor *logical_monitor = NULL;
- const char *edid[4] = { 0 }, *pretty_name = NULL;
- gboolean is_integrated_device = FALSE;
-#ifdef HAVE_LIBWACOM
- WacomDevice *wacom_device;
-#endif
-
- g_return_if_fail (META_IS_PAD_ACTION_MAPPER (mapper));
- g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
- g_return_if_fail (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE ||
- clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE);
-
- info = g_hash_table_lookup (mapper->pads, device);
- g_return_if_fail (info != NULL);
-
-#ifdef HAVE_LIBWACOM
- wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
-
- if (wacom_device)
- {
- pretty_name = libwacom_get_name (wacom_device);
- is_integrated_device =
- libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE;
- }
-#endif
-
- meta_pad_action_mapper_find_monitor (mapper, info->settings, device,
- NULL, &logical_monitor);
-
- if (!cycle_logical_monitors (mapper,
- is_integrated_device,
- logical_monitor,
- &logical_monitor))
- return;
-
- if (logical_monitor)
- {
- MetaMonitor *monitor;
-
- /* Pick an arbitrary monitor in the logical monitor to represent it. */
- monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
- edid[0] = meta_monitor_get_vendor (monitor);
- edid[1] = meta_monitor_get_product (monitor);
- edid[2] = meta_monitor_get_serial (monitor);
- }
- else
- {
- edid[0] = "";
- edid[1] = "";
- edid[2] = "";
- }
-
- g_settings_set_strv (info->settings, "output", edid);
- meta_display_show_tablet_mapping_notification (meta_get_display (),
- device, pretty_name);
-}
-
-gboolean
-meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- guint button)
-{
- g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE);
- g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE);
- g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
- CLUTTER_PAD_DEVICE, FALSE);
-
- return (meta_pad_action_mapper_get_button_action (mapper, pad, button) !=
- G_DESKTOP_PAD_BUTTON_ACTION_NONE);
-}
-
-static void
-emulate_modifiers (ClutterVirtualInputDevice *device,
- ClutterModifierType mods,
- ClutterKeyState state)
-{
- guint i;
- struct {
- ClutterModifierType mod;
- guint keyval;
- } mod_map[] = {
- { CLUTTER_SHIFT_MASK, CLUTTER_KEY_Shift_L },
- { CLUTTER_CONTROL_MASK, CLUTTER_KEY_Control_L },
- { CLUTTER_MOD1_MASK, CLUTTER_KEY_Meta_L }
- };
-
- for (i = 0; i < G_N_ELEMENTS (mod_map); i++)
- {
- if ((mods & mod_map[i].mod) == 0)
- continue;
-
- clutter_virtual_input_device_notify_keyval (device,
- clutter_get_current_event_time (),
- mod_map[i].keyval, state);
- }
-}
-
-static void
-meta_pad_action_mapper_emulate_keybinding (MetaPadActionMapper *mapper,
- const char *accel,
- gboolean is_press)
-{
- ClutterKeyState state;
- guint key, mods;
-
- if (!accel || !*accel)
- return;
-
- /* FIXME: This is appalling */
- gtk_accelerator_parse (accel, &key, &mods);
-
- if (!mapper->virtual_pad_keyboard)
- {
- ClutterBackend *backend;
- ClutterSeat *seat;
-
- backend = clutter_get_default_backend ();
- seat = clutter_backend_get_default_seat (backend);
-
- mapper->virtual_pad_keyboard =
- clutter_seat_create_virtual_device (seat,
- CLUTTER_KEYBOARD_DEVICE);
- }
-
- state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED;
-
- if (is_press)
- emulate_modifiers (mapper->virtual_pad_keyboard, mods, state);
-
- clutter_virtual_input_device_notify_keyval (mapper->virtual_pad_keyboard,
- clutter_get_current_event_time (),
- key, state);
- if (!is_press)
- emulate_modifiers (mapper->virtual_pad_keyboard, mods, state);
-}
-
-static gboolean
-meta_pad_action_mapper_handle_button (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- const ClutterPadButtonEvent *event)
-{
- GDesktopPadButtonAction action;
- int button, group, mode, n_modes = 0;
- gboolean is_press;
- GSettings *settings;
- char *accel;
-
- g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE);
- g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
- event->type == CLUTTER_PAD_BUTTON_RELEASE, FALSE);
-
- button = event->button;
- mode = event->mode;
- group = clutter_input_device_get_mode_switch_button_group (pad, button);
- is_press = event->type == CLUTTER_PAD_BUTTON_PRESS;
-
- if (group >= 0)
- n_modes = clutter_input_device_get_group_n_modes (pad, group);
-
- if (is_press && n_modes > 0)
- {
- const char *pretty_name = NULL;
- PadMappingInfo *info;
-#ifdef HAVE_LIBWACOM
- WacomDevice *wacom_device;
-#endif
-
- info = g_hash_table_lookup (mapper->pads, pad);
-
-#ifdef HAVE_LIBWACOM
- wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad));
-
- if (wacom_device)
- pretty_name = libwacom_get_name (wacom_device);
-#endif
- meta_display_notify_pad_group_switch (meta_get_display (), pad,
- pretty_name, group, mode, n_modes);
- info->group_modes[group] = mode;
- }
-
- action = meta_pad_action_mapper_get_button_action (mapper, pad, button);
-
- switch (action)
- {
- case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
- if (is_press)
- meta_pad_action_mapper_cycle_tablet_output (mapper, pad);
- return TRUE;
- case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
- if (is_press)
- meta_display_request_pad_osd (meta_get_display (), pad, FALSE);
- return TRUE;
- case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
- settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
- button, META_PAD_DIRECTION_NONE, -1);
- accel = g_settings_get_string (settings, "keybinding");
- meta_pad_action_mapper_emulate_keybinding (mapper, accel, is_press);
- g_object_unref (settings);
- g_free (accel);
- return TRUE;
- case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
- default:
- return FALSE;
- }
-}
-
-static gboolean
-meta_pad_action_mapper_handle_action (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- MetaPadActionType action,
- guint number,
- MetaPadDirection direction,
- guint mode)
-{
- GSettings *settings;
- gboolean handled = FALSE;
- char *accel;
-
- settings = lookup_pad_action_settings (pad, action, number, direction, mode);
- accel = g_settings_get_string (settings, "keybinding");
-
- if (accel && *accel)
- {
- meta_pad_action_mapper_emulate_keybinding (mapper, accel, TRUE);
- meta_pad_action_mapper_emulate_keybinding (mapper, accel, FALSE);
- handled = TRUE;
- }
-
- g_object_unref (settings);
- g_free (accel);
-
- return handled;
-}
-
-static gboolean
-meta_pad_action_mapper_get_action_direction (MetaPadActionMapper *mapper,
- const ClutterEvent *event,
- MetaPadDirection *direction)
-{
- ClutterInputDevice *pad = clutter_event_get_device (event);
- MetaPadActionType pad_action;
- gboolean has_direction = FALSE;
- MetaPadDirection inc_dir, dec_dir;
- guint number;
- double value;
-
- *direction = META_PAD_DIRECTION_NONE;
-
- switch (event->type)
- {
- case CLUTTER_PAD_RING:
- pad_action = META_PAD_ACTION_RING;
- number = event->pad_ring.ring_number;
- value = event->pad_ring.angle;
- inc_dir = META_PAD_DIRECTION_CW;
- dec_dir = META_PAD_DIRECTION_CCW;
- break;
- case CLUTTER_PAD_STRIP:
- pad_action = META_PAD_ACTION_STRIP;
- number = event->pad_strip.strip_number;
- value = event->pad_strip.value;
- inc_dir = META_PAD_DIRECTION_DOWN;
- dec_dir = META_PAD_DIRECTION_UP;
- break;
- default:
- return FALSE;
- }
-
- if (mapper->last_pad_action_info.pad == pad &&
- mapper->last_pad_action_info.action == pad_action &&
- mapper->last_pad_action_info.number == number &&
- value >= 0 && mapper->last_pad_action_info.value >= 0)
- {
- *direction = (value - mapper->last_pad_action_info.value) > 0 ?
- inc_dir : dec_dir;
- has_direction = TRUE;
- }
-
- mapper->last_pad_action_info.pad = pad;
- mapper->last_pad_action_info.action = pad_action;
- mapper->last_pad_action_info.number = number;
- mapper->last_pad_action_info.value = value;
- return has_direction;
-}
-
-gboolean
-meta_pad_action_mapper_handle_event (MetaPadActionMapper *mapper,
- const ClutterEvent *event)
-{
- ClutterInputDevice *pad;
- MetaPadDirection direction = META_PAD_DIRECTION_NONE;
-
- pad = clutter_event_get_source_device ((ClutterEvent *) event);
-
- switch (event->type)
- {
- case CLUTTER_PAD_BUTTON_PRESS:
- case CLUTTER_PAD_BUTTON_RELEASE:
- return meta_pad_action_mapper_handle_button (mapper, pad,
- &event->pad_button);
- case CLUTTER_PAD_RING:
- if (!meta_pad_action_mapper_get_action_direction (mapper,
- event, &direction))
- return FALSE;
- return meta_pad_action_mapper_handle_action (mapper, pad,
- META_PAD_ACTION_RING,
- event->pad_ring.ring_number,
- direction,
- event->pad_ring.mode);
- case CLUTTER_PAD_STRIP:
- if (!meta_pad_action_mapper_get_action_direction (mapper,
- event, &direction))
- return FALSE;
- return meta_pad_action_mapper_handle_action (mapper, pad,
- META_PAD_ACTION_STRIP,
- event->pad_strip.strip_number,
- direction,
- event->pad_strip.mode);
- default:
- return FALSE;
- }
-}
-
-
-static char *
-compose_directional_action_label (GSettings *direction1,
- GSettings *direction2)
-{
- char *accel1, *accel2, *str = NULL;
-
- accel1 = g_settings_get_string (direction1, "keybinding");
- accel2 = g_settings_get_string (direction2, "keybinding");
-
- if (accel1 && *accel1 && accel2 && *accel2)
- str = g_strdup_printf ("%s / %s", accel1, accel2);
-
- g_free (accel1);
- g_free (accel2);
-
- return str;
-}
-
-static char *
-meta_pad_action_mapper_get_ring_label (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- guint number,
- guint mode)
-{
- GSettings *settings1, *settings2;
- char *label;
-
- /* We only allow keybinding actions with those */
- settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number,
- META_PAD_DIRECTION_CW, mode);
- settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number,
- META_PAD_DIRECTION_CCW, mode);
- label = compose_directional_action_label (settings1, settings2);
- g_object_unref (settings1);
- g_object_unref (settings2);
-
- return label;
-}
-
-static char *
-meta_pad_action_mapper_get_strip_label (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- guint number,
- guint mode)
-{
- GSettings *settings1, *settings2;
- char *label;
-
- /* We only allow keybinding actions with those */
- settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number,
- META_PAD_DIRECTION_UP, mode);
- settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number,
- META_PAD_DIRECTION_DOWN, mode);
- label = compose_directional_action_label (settings1, settings2);
- g_object_unref (settings1);
- g_object_unref (settings2);
-
- return label;
-}
-
-static char *
-meta_pad_action_mapper_get_button_label (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- guint button)
-{
- GDesktopPadButtonAction action;
- int group;
-
- g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), NULL);
- g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), NULL);
- g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
- CLUTTER_PAD_DEVICE, NULL);
-
- group = clutter_input_device_get_mode_switch_button_group (pad, button);
-
- if (group >= 0)
- {
- /* TRANSLATORS: This string refers to a button that switches between
- * different modes.
- */
- return g_strdup_printf (_("Mode Switch (Group %d)"), group);
- }
-
- action = meta_pad_action_mapper_get_button_action (mapper, pad, button);
-
- switch (action)
- {
- case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
- {
- GSettings *settings;
- char *accel;
-
- settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
- button, META_PAD_DIRECTION_NONE, -1);
- accel = g_settings_get_string (settings, "keybinding");
- g_object_unref (settings);
-
- return accel;
- }
- case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
- /* TRANSLATORS: This string refers to an action, cycles drawing tablets'
- * mapping through the available outputs.
- */
- return g_strdup (_("Switch monitor"));
- case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
- return g_strdup (_("Show on-screen help"));
- case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
- default:
- return NULL;
- }
-}
-
-static guint
-get_current_pad_mode (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- MetaPadActionType action_type,
- guint number)
-{
- PadMappingInfo *info;
- guint group = 0, n_groups;
-
- info = g_hash_table_lookup (mapper->pads, pad);
- n_groups = clutter_input_device_get_n_mode_groups (pad);
-
- if (!info->group_modes || n_groups == 0)
- return 0;
-
- if (action_type == META_PAD_ACTION_RING ||
- action_type == META_PAD_ACTION_STRIP)
- {
- /* Assume features are evenly distributed in groups */
- group = number % n_groups;
- }
-
- return info->group_modes[group];
-}
-
-char *
-meta_pad_action_mapper_get_action_label (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- MetaPadActionType action_type,
- guint number)
-{
- guint mode;
-
- switch (action_type)
- {
- case META_PAD_ACTION_BUTTON:
- return meta_pad_action_mapper_get_button_label (mapper, pad, number);
- case META_PAD_ACTION_RING:
- mode = get_current_pad_mode (mapper, pad, action_type, number);
- return meta_pad_action_mapper_get_ring_label (mapper, pad, number, mode);
- case META_PAD_ACTION_STRIP:
- mode = get_current_pad_mode (mapper, pad, action_type, number);
- return meta_pad_action_mapper_get_strip_label (mapper, pad, number, mode);
- }
-
- return NULL;
-}
diff --git a/src/core/meta-pad-action-mapper.h b/src/core/meta-pad-action-mapper.h
deleted file mode 100644
index 63fc2261b..000000000
--- a/src/core/meta-pad-action-mapper.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Carlos Garnacho <carlosg@gnome.org>
- */
-
-#ifndef META_PAD_ACTION_MAPPER_H
-#define META_PAD_ACTION_MAPPER_H
-
-#include "clutter/clutter.h"
-#include "meta/display.h"
-#include "meta/meta-monitor-manager.h"
-
-#define META_TYPE_PAD_ACTION_MAPPER (meta_pad_action_mapper_get_type ())
-G_DECLARE_FINAL_TYPE (MetaPadActionMapper, meta_pad_action_mapper,
- META, PAD_ACTION_MAPPER, GObject)
-
-MetaPadActionMapper * meta_pad_action_mapper_new (MetaMonitorManager *monitor_manager);
-
-gboolean meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- guint button);
-gboolean meta_pad_action_mapper_handle_event (MetaPadActionMapper *mapper,
- const ClutterEvent *event);
-gchar * meta_pad_action_mapper_get_action_label (MetaPadActionMapper *mapper,
- ClutterInputDevice *pad,
- MetaPadActionType action,
- guint number);
-
-#endif /* META_PAD_ACTION_MAPPER_H */
diff --git a/src/core/meta-private-enums.h b/src/core/meta-private-enums.h
deleted file mode 100644
index 1a361c782..000000000
--- a/src/core/meta-private-enums.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019-2021 Red Hat Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#ifndef META_PRIVATE_ENUMS_H
-#define META_PRIVATE_ENUMS_H
-
-typedef enum _MetaX11DisplayPolicy
-{
- META_X11_DISPLAY_POLICY_MANDATORY,
- META_X11_DISPLAY_POLICY_ON_DEMAND,
- META_X11_DISPLAY_POLICY_DISABLED,
-} MetaX11DisplayPolicy;
-
-#endif /* META_PRIVATE_ENUMS_H */
diff --git a/src/core/meta-selection-private.h b/src/core/meta-selection-private.h
deleted file mode 100644
index de9caf9bf..000000000
--- a/src/core/meta-selection-private.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Written by:
- * Carlos Garnacho <carlosg@gnome.org>
- */
-
-#ifndef META_SELECTION_PRIVATE_H
-#define META_SELECTION_PRIVATE_H
-
-#include "meta/meta-selection.h"
-
-MetaSelectionSource *
- meta_selection_get_current_owner (MetaSelection *selection,
- MetaSelectionType selection_type);
-
-#endif /* META_SELECTION_PRIVATE_H */
diff --git a/src/core/meta-selection-source-memory.c b/src/core/meta-selection-source-memory.c
deleted file mode 100644
index a52f50861..000000000
--- a/src/core/meta-selection-source-memory.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include "meta/meta-selection-source-memory.h"
-
-struct _MetaSelectionSourceMemory
-{
- MetaSelectionSource parent_instance;
- char *mimetype;
- GBytes *content;
-};
-
-G_DEFINE_TYPE (MetaSelectionSourceMemory,
- meta_selection_source_memory,
- META_TYPE_SELECTION_SOURCE)
-
-static void
-meta_selection_source_memory_read_async (MetaSelectionSource *source,
- const char *mimetype,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (source);
- GInputStream *stream;
- g_autoptr (GTask) task = NULL;
-
- if (g_strcmp0 (mimetype, source_mem->mimetype) != 0)
- {
- g_task_report_new_error (source, callback, user_data,
- meta_selection_source_memory_read_async,
- G_IO_ERROR, G_IO_ERROR_FAILED,
- "Mimetype not in selection");
- return;
- }
-
- task = g_task_new (source, cancellable, callback, user_data);
- g_task_set_source_tag (task, meta_selection_source_memory_read_async);
-
- stream = g_memory_input_stream_new_from_bytes (source_mem->content);
- g_task_return_pointer (task, stream, g_object_unref);
-}
-
-static GInputStream *
-meta_selection_source_memory_read_finish (MetaSelectionSource *source,
- GAsyncResult *result,
- GError **error)
-{
- g_assert (g_task_get_source_tag (G_TASK (result)) ==
- meta_selection_source_memory_read_async);
- return g_task_propagate_pointer (G_TASK (result), error);
-}
-
-static GList *
-meta_selection_source_memory_get_mimetypes (MetaSelectionSource *source)
-{
- MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (source);
-
- if (!source_mem->mimetype)
- return NULL;
-
- return g_list_prepend (NULL, g_strdup (source_mem->mimetype));
-}
-
-static void
-meta_selection_source_memory_finalize (GObject *object)
-{
- MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (object);
-
- g_clear_pointer (&source_mem->content, g_bytes_unref);
- g_free (source_mem->mimetype);
-
- G_OBJECT_CLASS (meta_selection_source_memory_parent_class)->finalize (object);
-}
-
-static void
-meta_selection_source_memory_class_init (MetaSelectionSourceMemoryClass *klass)
-{
- MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_selection_source_memory_finalize;
-
- source_class->read_async = meta_selection_source_memory_read_async;
- source_class->read_finish = meta_selection_source_memory_read_finish;
- source_class->get_mimetypes = meta_selection_source_memory_get_mimetypes;
-}
-
-static void
-meta_selection_source_memory_init (MetaSelectionSourceMemory *source)
-{
-}
-
-MetaSelectionSource *
-meta_selection_source_memory_new (const char *mimetype,
- GBytes *content)
-{
- MetaSelectionSourceMemory *source;
-
- g_return_val_if_fail (mimetype != NULL, NULL);
- g_return_val_if_fail (content != NULL, NULL);
-
- source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
- source->mimetype = g_strdup (mimetype);
- source->content = g_bytes_ref (content);
-
- return META_SELECTION_SOURCE (source);
-}
diff --git a/src/core/meta-selection-source-remote.c b/src/core/meta-selection-source-remote.c
deleted file mode 100644
index aa9f9e60a..000000000
--- a/src/core/meta-selection-source-remote.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2020 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#include "config.h"
-
-#include "core/meta-selection-source-remote.h"
-
-#include <gio/gunixinputstream.h>
-
-#include "backends/meta-remote-desktop-session.h"
-
-struct _MetaSelectionSourceRemote
-{
- MetaSelectionSource parent;
-
- MetaRemoteDesktopSession *session;
- GList *mime_types;
-};
-
-G_DEFINE_TYPE (MetaSelectionSourceRemote,
- meta_selection_source_remote,
- META_TYPE_SELECTION_SOURCE)
-
-MetaSelectionSourceRemote *
-meta_selection_source_remote_new (MetaRemoteDesktopSession *session,
- GList *mime_types)
-{
- MetaSelectionSourceRemote *source_remote;
-
- source_remote = g_object_new (META_TYPE_SELECTION_SOURCE_REMOTE, NULL);
- source_remote->session = session;
- source_remote->mime_types = mime_types;
-
- return source_remote;
-}
-
-static void
-meta_selection_source_remote_read_async (MetaSelectionSource *source,
- const char *mimetype,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- MetaSelectionSourceRemote *source_remote =
- META_SELECTION_SOURCE_REMOTE (source);
- GTask *task;
-
- task = g_task_new (source, cancellable, callback, user_data);
- g_task_set_source_tag (task, meta_selection_source_remote_read_async);
-
- meta_remote_desktop_session_request_transfer (source_remote->session,
- mimetype,
- task);
-}
-
-static GInputStream *
-meta_selection_source_remote_read_finish (MetaSelectionSource *source,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (g_task_is_valid (result, source), FALSE);
- g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
- meta_selection_source_remote_read_async, FALSE);
-
- return g_task_propagate_pointer (G_TASK (result), error);
-}
-
-void
-meta_selection_source_remote_complete_transfer (MetaSelectionSourceRemote *source_remote,
- int fd,
- GTask *task)
-{
- GInputStream *stream;
-
- stream = g_unix_input_stream_new (fd, TRUE);
- g_task_return_pointer (task, stream, g_object_unref);
- g_object_unref (task);
-}
-
-void
-meta_selection_source_remote_cancel_transfer (MetaSelectionSourceRemote *source_remote,
- GTask *task)
-{
- g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED,
- "Remote selection transfer was cancelled");
- g_object_unref (task);
-}
-
-static GList *
-meta_selection_source_remote_get_mimetypes (MetaSelectionSource *source)
-{
- MetaSelectionSourceRemote *source_remote =
- META_SELECTION_SOURCE_REMOTE (source);
-
- return g_list_copy_deep (source_remote->mime_types,
- (GCopyFunc) g_strdup,
- NULL);
-}
-
-static void
-meta_selection_source_remote_finalize (GObject *object)
-{
- MetaSelectionSourceRemote *source_remote =
- META_SELECTION_SOURCE_REMOTE (object);
-
- g_list_free_full (source_remote->mime_types, g_free);
-
- G_OBJECT_CLASS (meta_selection_source_remote_parent_class)->finalize (object);
-}
-
-static void
-meta_selection_source_remote_init (MetaSelectionSourceRemote *source_remote)
-{
-}
-
-static void
-meta_selection_source_remote_class_init (MetaSelectionSourceRemoteClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass);
-
- object_class->finalize = meta_selection_source_remote_finalize;
-
- source_class->read_async = meta_selection_source_remote_read_async;
- source_class->read_finish = meta_selection_source_remote_read_finish;
- source_class->get_mimetypes = meta_selection_source_remote_get_mimetypes;
-}
diff --git a/src/core/meta-selection-source-remote.h b/src/core/meta-selection-source-remote.h
deleted file mode 100644
index 51e66957b..000000000
--- a/src/core/meta-selection-source-remote.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#ifndef META_SELECTION_SOURCE_REMOTE_H
-#define META_SELECTION_SOURCE_REMOTE_H
-
-#include "backends/meta-remote-desktop.h"
-#include "meta/meta-selection-source.h"
-
-#define META_TYPE_SELECTION_SOURCE_REMOTE (meta_selection_source_remote_get_type ())
-G_DECLARE_FINAL_TYPE (MetaSelectionSourceRemote,
- meta_selection_source_remote,
- META, SELECTION_SOURCE_REMOTE,
- MetaSelectionSource)
-
-void meta_selection_source_remote_complete_transfer (MetaSelectionSourceRemote *source_remote,
- int fd,
- GTask *task);
-
-void meta_selection_source_remote_cancel_transfer (MetaSelectionSourceRemote *source_remote,
- GTask *task);
-
-MetaSelectionSourceRemote * meta_selection_source_remote_new (MetaRemoteDesktopSession *session,
- GList *mime_types);
-
-#endif /* META_SELECTION_SOURCE_REMOTE_H */
diff --git a/src/core/meta-selection-source.c b/src/core/meta-selection-source.c
deleted file mode 100644
index b076391ce..000000000
--- a/src/core/meta-selection-source.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include "meta/meta-selection.h"
-#include "meta/meta-selection-source.h"
-
-typedef struct MetaSelectionSourcePrivate MetaSelectionSourcePrivate;
-
-struct MetaSelectionSourcePrivate
-{
- guint active : 1;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (MetaSelectionSource,
- meta_selection_source,
- G_TYPE_OBJECT)
-
-enum
-{
- ACTIVE,
- INACTIVE,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS] = { 0 };
-
-static void
-meta_selection_source_activated (MetaSelectionSource *source)
-{
- MetaSelectionSourcePrivate *priv =
- meta_selection_source_get_instance_private (source);
-
- priv->active = TRUE;
-}
-
-static void
-meta_selection_source_deactivated (MetaSelectionSource *source)
-{
- MetaSelectionSourcePrivate *priv =
- meta_selection_source_get_instance_private (source);
-
- priv->active = FALSE;
-}
-
-static void
-meta_selection_source_class_init (MetaSelectionSourceClass *klass)
-{
- klass->activated = meta_selection_source_activated;
- klass->deactivated = meta_selection_source_deactivated;
-
- signals[ACTIVE] =
- g_signal_new ("activated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (MetaSelectionSourceClass, activated),
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
- signals[INACTIVE] =
- g_signal_new ("deactivated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (MetaSelectionSourceClass, deactivated),
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-}
-
-static void
-meta_selection_source_init (MetaSelectionSource *source)
-{
-}
-
-void
-meta_selection_source_read_async (MetaSelectionSource *source,
- const gchar *mimetype,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- g_return_if_fail (META_IS_SELECTION_SOURCE (source));
- g_return_if_fail (mimetype != NULL);
- g_return_if_fail (callback != NULL);
-
- META_SELECTION_SOURCE_GET_CLASS (source)->read_async (source,
- mimetype,
- cancellable,
- callback,
- user_data);
-}
-
-/**
- * meta_selection_source_read_finish:
- * @source: The selection source
- * @result: The async result
- * @error: Location for returned error
- *
- * Finishes a read from the selection source.
- *
- * Returns: (transfer full): The resulting #GInputStream
- */
-GInputStream *
-meta_selection_source_read_finish (MetaSelectionSource *source,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (META_IS_SELECTION_SOURCE (source), NULL);
- g_return_val_if_fail (g_task_is_valid (result, source), NULL);
-
- return META_SELECTION_SOURCE_GET_CLASS (source)->read_finish (source,
- result,
- error);
-}
-
-/**
- * meta_selection_source_get_mimetypes:
- * @source: The selection source
- *
- * Returns the list of supported mimetypes.
- *
- * Returns: (element-type utf8) (transfer full): The supported mimetypes
- */
-GList *
-meta_selection_source_get_mimetypes (MetaSelectionSource *source)
-{
- g_return_val_if_fail (META_IS_SELECTION_SOURCE (source), NULL);
-
- return META_SELECTION_SOURCE_GET_CLASS (source)->get_mimetypes (source);
-}
-
-/**
- * meta_selection_source_is_active:
- * @source: the selection source
- *
- * Returns #TRUE if the source is active on a selection.
- *
- * Returns: #TRUE if the source owns a selection.
- **/
-gboolean
-meta_selection_source_is_active (MetaSelectionSource *source)
-{
- MetaSelectionSourcePrivate *priv =
- meta_selection_source_get_instance_private (source);
-
- g_return_val_if_fail (META_IS_SELECTION_SOURCE (source), FALSE);
-
- return priv->active;
-}
diff --git a/src/core/meta-selection.c b/src/core/meta-selection.c
deleted file mode 100644
index 4e42e59a9..000000000
--- a/src/core/meta-selection.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include "core/meta-selection-private.h"
-#include "meta/meta-selection.h"
-
-typedef struct TransferRequest TransferRequest;
-
-struct _MetaSelection
-{
- GObject parent_instance;
- MetaDisplay *display;
- MetaSelectionSource *owners[META_N_SELECTION_TYPES];
-};
-
-struct TransferRequest
-{
- MetaSelectionType selection_type;
- GInputStream *istream;
- GOutputStream *ostream;
- gssize len;
-};
-
-enum
-{
- OWNER_CHANGED,
- N_SIGNALS
-};
-
-static guint signals[N_SIGNALS] = { 0 };
-
-G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT)
-
-static void read_selection_source_async (GTask *task,
- TransferRequest *request);
-
-static void
-meta_selection_dispose (GObject *object)
-{
- MetaSelection *selection = META_SELECTION (object);
- guint i;
-
- for (i = 0; i < META_N_SELECTION_TYPES; i++)
- {
- g_clear_object (&selection->owners[i]);
- }
-
- G_OBJECT_CLASS (meta_selection_parent_class)->dispose (object);
-}
-
-static void
-meta_selection_class_init (MetaSelectionClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = meta_selection_dispose;
-
- signals[OWNER_CHANGED] =
- g_signal_new ("owner-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 2,
- G_TYPE_UINT,
- META_TYPE_SELECTION_SOURCE);
-}
-
-static void
-meta_selection_init (MetaSelection *selection)
-{
-}
-
-MetaSelection *
-meta_selection_new (MetaDisplay *display)
-{
- return g_object_new (META_TYPE_SELECTION,
- NULL);
-}
-
-/**
- * meta_selection_set_owner:
- * @selection: The selection manager
- * @selection_type: Selection type
- * @owner: New selection owner
- *
- * Sets @owner as the owner of the selection given by @selection_type,
- * unsets any previous owner there was.
- **/
-void
-meta_selection_set_owner (MetaSelection *selection,
- MetaSelectionType selection_type,
- MetaSelectionSource *owner)
-{
- g_return_if_fail (META_IS_SELECTION (selection));
- g_return_if_fail (selection_type < META_N_SELECTION_TYPES);
-
- if (selection->owners[selection_type] == owner)
- return;
-
- if (selection->owners[selection_type])
- g_signal_emit_by_name (selection->owners[selection_type], "deactivated");
-
- g_set_object (&selection->owners[selection_type], owner);
- g_signal_emit_by_name (owner, "activated");
- g_signal_emit (selection, signals[OWNER_CHANGED], 0, selection_type, owner);
-}
-
-/**
- * meta_selection_unset_owner:
- * @selection: The selection manager
- * @selection_type: Selection type
- * @owner: Owner to unset
- *
- * Unsets @owner as the owner the selection given by @selection_type. If
- * @owner does not own the selection, nothing is done.
- **/
-void
-meta_selection_unset_owner (MetaSelection *selection,
- MetaSelectionType selection_type,
- MetaSelectionSource *owner)
-{
- g_return_if_fail (META_IS_SELECTION (selection));
- g_return_if_fail (selection_type < META_N_SELECTION_TYPES);
-
- if (selection->owners[selection_type] == owner)
- {
- g_signal_emit_by_name (owner, "deactivated");
- g_clear_object (&selection->owners[selection_type]);
- g_signal_emit (selection, signals[OWNER_CHANGED], 0,
- selection_type, NULL);
- }
-}
-
-/**
- * meta_selection_get_mimetypes:
- * @selection: The selection manager
- * @selection_type: Selection to query
- *
- * Returns the list of supported mimetypes for the given selection type.
- *
- * Returns: (element-type utf8) (transfer full): The supported mimetypes
- */
-GList *
-meta_selection_get_mimetypes (MetaSelection *selection,
- MetaSelectionType selection_type)
-{
- g_return_val_if_fail (META_IS_SELECTION (selection), NULL);
- g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL);
-
- if (!selection->owners[selection_type])
- return NULL;
-
- return meta_selection_source_get_mimetypes (selection->owners[selection_type]);
-}
-
-static TransferRequest *
-transfer_request_new (GOutputStream *ostream,
- MetaSelectionType selection_type,
- gssize len)
-{
- TransferRequest *request;
-
- request = g_new0 (TransferRequest, 1);
- request->ostream = g_object_ref (ostream);
- request->selection_type = selection_type;
- request->len = len;
- return request;
-}
-
-static void
-transfer_request_free (TransferRequest *request)
-{
- g_clear_object (&request->istream);
- g_clear_object (&request->ostream);
- g_free (request);
-}
-
-static void
-splice_cb (GOutputStream *stream,
- GAsyncResult *result,
- GTask *task)
-{
- GError *error = NULL;
-
- g_output_stream_splice_finish (stream, result, &error);
- if (error)
- {
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
-
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
-}
-
-static void
-write_cb (GOutputStream *stream,
- GAsyncResult *result,
- GTask *task)
-{
- TransferRequest *request;
- GError *error = NULL;
-
- g_output_stream_write_bytes_finish (stream, result, &error);
- if (error)
- {
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
-
- request = g_task_get_task_data (task);
-
- if (request->len > 0)
- {
- read_selection_source_async (task, request);
- }
- else
- {
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
- }
-}
-
-static void
-read_cb (GInputStream *stream,
- GAsyncResult *result,
- GTask *task)
-{
- TransferRequest *request;
- GError *error = NULL;
- GBytes *bytes;
-
- bytes = g_input_stream_read_bytes_finish (stream, result, &error);
- if (error)
- {
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
- else if (g_bytes_get_size (bytes) == 0)
- {
- g_task_return_boolean (task, TRUE);
- g_object_unref (task);
- return;
- }
-
- request = g_task_get_task_data (task);
-
- if (request->len < g_bytes_get_size (bytes))
- {
- GBytes *copy;
-
- /* Trim content */
- copy = g_bytes_new_from_bytes (bytes, 0, request->len);
- g_bytes_unref (bytes);
- bytes = copy;
- }
-
- request->len -= g_bytes_get_size (bytes);
- g_output_stream_write_bytes_async (request->ostream,
- bytes,
- G_PRIORITY_DEFAULT,
- g_task_get_cancellable (task),
- (GAsyncReadyCallback) write_cb,
- task);
- g_bytes_unref (bytes);
-}
-
-static void
-read_selection_source_async (GTask *task,
- TransferRequest *request)
-{
- g_input_stream_read_bytes_async (request->istream,
- (gsize) request->len,
- G_PRIORITY_DEFAULT,
- g_task_get_cancellable (task),
- (GAsyncReadyCallback) read_cb,
- task);
-}
-
-static void
-source_read_cb (MetaSelectionSource *source,
- GAsyncResult *result,
- GTask *task)
-{
- TransferRequest *request;
- GInputStream *stream;
- GError *error = NULL;
-
- stream = meta_selection_source_read_finish (source, result, &error);
- if (!stream)
- {
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
-
- request = g_task_get_task_data (task);
- request->istream = stream;
-
- if (request->len < 0)
- {
- g_output_stream_splice_async (request->ostream,
- request->istream,
- G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
- G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
- G_PRIORITY_DEFAULT,
- g_task_get_cancellable (task),
- (GAsyncReadyCallback) splice_cb,
- task);
- }
- else
- {
- read_selection_source_async (task, request);
- }
-}
-
-/**
- * meta_selection_transfer_async:
- * @selection: The selection manager
- * @selection_type: Selection type
- * @mimetype: Mimetype to transfer
- * @size: Maximum size to transfer, -1 for unlimited
- * @output: Output stream to write contents to
- * @cancellable: Cancellable
- * @callback: User callback
- * @user_data: User data
- *
- * Requests a transfer of @mimetype on the selection given by
- * @selection_type.
- **/
-void
-meta_selection_transfer_async (MetaSelection *selection,
- MetaSelectionType selection_type,
- const char *mimetype,
- gssize size,
- GOutputStream *output,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GTask *task;
-
- g_return_if_fail (META_IS_SELECTION (selection));
- g_return_if_fail (selection_type < META_N_SELECTION_TYPES);
- g_return_if_fail (G_IS_OUTPUT_STREAM (output));
- g_return_if_fail (mimetype != NULL);
-
- task = g_task_new (selection, cancellable, callback, user_data);
- g_task_set_source_tag (task, meta_selection_transfer_async);
-
- g_task_set_task_data (task,
- transfer_request_new (output, selection_type, size),
- (GDestroyNotify) transfer_request_free);
- meta_selection_source_read_async (selection->owners[selection_type],
- mimetype,
- cancellable,
- (GAsyncReadyCallback) source_read_cb,
- task);
-}
-
-/**
- * meta_selection_transfer_finish:
- * @selection: The selection manager
- * @result: The async result
- * @error: Location for returned error, or %NULL
- *
- * Finishes the transfer of a queried mimetype.
- *
- * Returns: #TRUE if the transfer was successful.
- **/
-gboolean
-meta_selection_transfer_finish (MetaSelection *selection,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (g_task_is_valid (result, selection), FALSE);
- g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) ==
- meta_selection_transfer_async, FALSE);
-
- return g_task_propagate_boolean (G_TASK (result), error);
-}
-
-MetaSelectionSource *
-meta_selection_get_current_owner (MetaSelection *selection,
- MetaSelectionType selection_type)
-{
- g_return_val_if_fail (META_IS_SELECTION (selection), NULL);
- g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL);
-
- return selection->owners[selection_type];
-}
diff --git a/src/core/meta-sound-player.c b/src/core/meta-sound-player.c
deleted file mode 100644
index e2d103893..000000000
--- a/src/core/meta-sound-player.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2018 Red Hat
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * Author: Carlos Garnacho <carlosg@gnome.org>
- */
-
-#include "config.h"
-
-#include <canberra.h>
-
-#include "meta/meta-sound-player.h"
-
-#define EVENT_SOUNDS_KEY "event-sounds"
-#define THEME_NAME_KEY "theme-name"
-
-typedef struct _MetaPlayRequest MetaPlayRequest;
-
-struct _MetaSoundPlayer
-{
- GObject parent;
- GThreadPool *queue;
- GSettings *settings;
- ca_context *context;
- uint32_t id_pool;
-};
-
-struct _MetaPlayRequest
-{
- ca_proplist *props;
- uint32_t id;
- gulong cancel_id;
- GCancellable *cancellable;
- MetaSoundPlayer *player;
-};
-
-const char * const cache_allow_list[] = {
- "bell-window-system",
- "desktop-switch-left",
- "desktop-switch-right",
- "desktop-switch-up",
- "desktop-switch-down",
- NULL
-};
-
-G_DEFINE_TYPE (MetaSoundPlayer, meta_sound_player, G_TYPE_OBJECT)
-
-static MetaPlayRequest *
-meta_play_request_new (MetaSoundPlayer *player,
- ca_proplist *props,
- GCancellable *cancellable)
-{
- MetaPlayRequest *req;
-
- req = g_new0 (MetaPlayRequest, 1);
- req->props = props;
- req->player = player;
- g_set_object (&req->cancellable, cancellable);
-
- return req;
-}
-
-static void
-meta_play_request_free (MetaPlayRequest *req)
-{
- g_clear_object (&req->cancellable);
- ca_proplist_destroy (req->props);
- g_free (req);
-}
-
-static void
-meta_sound_player_finalize (GObject *object)
-{
- MetaSoundPlayer *player = META_SOUND_PLAYER (object);
-
- g_object_unref (player->settings);
- g_thread_pool_free (player->queue, FALSE, TRUE);
- ca_context_destroy (player->context);
-
- G_OBJECT_CLASS (meta_sound_player_parent_class)->finalize (object);
-}
-
-static void
-meta_sound_player_class_init (MetaSoundPlayerClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_sound_player_finalize;
-}
-
-static void
-cancelled_cb (GCancellable *cancellable,
- MetaPlayRequest *req)
-{
- ca_context_cancel (req->player->context, req->id);
-}
-
-static void
-finish_cb (ca_context *context,
- uint32_t id,
- int error_code,
- gpointer user_data)
-{
- MetaPlayRequest *req = user_data;
-
- if (error_code != CA_ERROR_CANCELED)
- g_cancellable_disconnect (req->cancellable, req->cancel_id);
- else if (req->cancellable != NULL)
- g_clear_signal_handler (&req->cancel_id, req->cancellable);
-
- meta_play_request_free (req);
-}
-
-static void
-play_sound (MetaPlayRequest *req,
- MetaSoundPlayer *player)
-{
- req->id = player->id_pool++;
-
- if (ca_context_play_full (player->context, req->id, req->props,
- finish_cb, req) != CA_SUCCESS)
- {
- meta_play_request_free (req);
- return;
- }
-
- if (req->cancellable)
- {
- gulong cancel_id =
- g_cancellable_connect (req->cancellable,
- G_CALLBACK (cancelled_cb), req, NULL);
- if (cancel_id)
- req->cancel_id = cancel_id;
- }
-}
-
-static void
-settings_changed_cb (GSettings *settings,
- const char *key,
- MetaSoundPlayer *player)
-{
- if (strcmp (key, EVENT_SOUNDS_KEY) == 0)
- {
- gboolean enabled;
-
- enabled = g_settings_get_boolean (settings, EVENT_SOUNDS_KEY);
- ca_context_change_props (player->context, CA_PROP_CANBERRA_ENABLE,
- enabled ? "1" : "0", NULL);
- }
- else if (strcmp (key, THEME_NAME_KEY) == 0)
- {
- char *theme_name;
-
- theme_name = g_settings_get_string (settings, THEME_NAME_KEY);
- ca_context_change_props (player->context, CA_PROP_CANBERRA_XDG_THEME_NAME,
- theme_name, NULL);
- g_free (theme_name);
- }
-}
-
-static ca_context *
-create_context (GSettings *settings)
-{
- ca_context *context;
- ca_proplist *props;
- gboolean enabled;
- char *theme_name;
-
- if (ca_context_create (&context) != CA_SUCCESS)
- return NULL;
-
- if (ca_proplist_create (&props) != CA_SUCCESS)
- {
- ca_context_destroy (context);
- return NULL;
- }
-
- ca_proplist_sets (props, CA_PROP_APPLICATION_NAME, "Mutter");
-
- enabled = g_settings_get_boolean (settings, EVENT_SOUNDS_KEY);
- ca_proplist_sets (props, CA_PROP_CANBERRA_ENABLE, enabled ? "1" : "0");
-
- theme_name = g_settings_get_string (settings, THEME_NAME_KEY);
- ca_proplist_sets (props, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name);
- g_free (theme_name);
-
- ca_context_change_props_full (context, props);
- ca_proplist_destroy (props);
-
- return context;
-}
-
-static void
-meta_sound_player_init (MetaSoundPlayer *player)
-{
- player->queue = g_thread_pool_new ((GFunc) play_sound,
- player, 1, FALSE, NULL);
- player->settings = g_settings_new ("org.gnome.desktop.sound");
- player->context = create_context (player->settings);
-
- g_signal_connect (player->settings, "changed",
- G_CALLBACK (settings_changed_cb), player);
-}
-
-static void
-build_ca_proplist (ca_proplist *props,
- const char *event_property,
- const char *event_id,
- const char *event_description)
-{
- ca_proplist_sets (props, event_property, event_id);
- ca_proplist_sets (props, CA_PROP_EVENT_DESCRIPTION, event_description);
-}
-
-/**
- * meta_sound_player_play_from_theme:
- * @player: a #MetaSoundPlayer
- * @name: sound theme name of the event
- * @description: description of the event
- * @cancellable: cancellable for the request
- *
- * Plays a sound from the sound theme.
- **/
-void
-meta_sound_player_play_from_theme (MetaSoundPlayer *player,
- const char *name,
- const char *description,
- GCancellable *cancellable)
-{
- MetaPlayRequest *req;
- ca_proplist *props;
-
- g_return_if_fail (META_IS_SOUND_PLAYER (player));
- g_return_if_fail (name != NULL);
- g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
-
- ca_proplist_create (&props);
- build_ca_proplist (props, CA_PROP_EVENT_ID, name, description);
-
- if (g_strv_contains (cache_allow_list, name))
- ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
- else
- ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile");
-
- req = meta_play_request_new (player, props, cancellable);
- g_thread_pool_push (player->queue, req, NULL);
-}
-
-/**
- * meta_sound_player_play_from_file:
- * @player: a #MetaSoundPlayer
- * @file: file to play
- * @description: description of the played sound
- * @cancellable: cancellable for the request
- *
- * Plays a sound from a file.
- **/
-void
-meta_sound_player_play_from_file (MetaSoundPlayer *player,
- GFile *file,
- const char *description,
- GCancellable *cancellable)
-{
- MetaPlayRequest *req;
- ca_proplist *props;
- char *path;
-
- g_return_if_fail (META_IS_SOUND_PLAYER (player));
- g_return_if_fail (G_IS_FILE (file));
- g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
-
- path = g_file_get_path (file);
- g_return_if_fail (path != NULL);
-
- ca_proplist_create (&props);
- build_ca_proplist (props, CA_PROP_MEDIA_FILENAME, path, description);
- ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile");
- g_free (path);
-
- req = meta_play_request_new (player, props, cancellable);
- g_thread_pool_push (player->queue, req, NULL);
-}
diff --git a/src/core/meta-workspace-manager-private.h b/src/core/meta-workspace-manager-private.h
deleted file mode 100644
index 261c4d47c..000000000
--- a/src/core/meta-workspace-manager-private.h
+++ /dev/null
@@ -1,96 +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/>.
- */
-
-#ifndef META_WORKSPACE_MANAGER_PRIVATE_H
-#define META_WORKSPACE_MANAGER_PRIVATE_H
-
-#include <glib.h>
-
-#include "core/display-private.h"
-#include "meta/common.h"
-#include "meta/types.h"
-#include "meta/meta-workspace-manager.h"
-
-struct _MetaWorkspaceManager
-{
- GObject parent;
-
- MetaDisplay *display;
- MetaWorkspace *active_workspace;
-
- GList *workspaces;
-
- int rows_of_workspaces;
- int columns_of_workspaces;
- MetaDisplayCorner starting_corner;
- guint vertical_workspaces : 1;
- guint workspace_layout_overridden : 1;
-};
-
-MetaWorkspaceManager *meta_workspace_manager_new (MetaDisplay *display);
-
-void meta_workspace_manager_init_workspaces (MetaWorkspaceManager *workspace_manager);
-void meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_manager,
- MetaDisplayCorner starting_corner,
- gboolean vertical_layout,
- int n_rows,
- int n_columns);
-
-void meta_workspace_manager_reload_work_areas (MetaWorkspaceManager *workspace_manager);
-
-typedef struct MetaWorkspaceLayout MetaWorkspaceLayout;
-
-struct MetaWorkspaceLayout
-{
- int rows;
- int cols;
- int *grid;
- int grid_area;
- int current_row;
- int current_col;
-};
-
-void meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_manager,
- int num_workspaces,
- int current_space,
- MetaWorkspaceLayout *layout);
-
-void meta_workspace_manager_free_workspace_layout (MetaWorkspaceLayout *layout);
-
-void meta_workspace_manager_minimize_all_on_active_workspace_except (MetaWorkspaceManager *workspace_manager,
- MetaWindow *keep);
-
-/* Show/hide the desktop (temporarily hide all windows) */
-void meta_workspace_manager_show_desktop (MetaWorkspaceManager *workspace_manager,
- guint32 timestamp);
-void meta_workspace_manager_unshow_desktop (MetaWorkspaceManager *workspace_manager);
-
-void meta_workspace_manager_workspace_switched (MetaWorkspaceManager *workspace_manager,
- int from,
- int to,
- MetaMotionDirection direction);
-
-void meta_workspace_manager_update_num_workspaces (MetaWorkspaceManager *workspace_manager,
- guint32 timestamp,
- int new_num);
-
-#endif /* META_WORKSPACE_MANAGER_PRIVATE_H */
diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c
deleted file mode 100644
index 61fbc0090..000000000
--- a/src/core/meta-workspace-manager.c
+++ /dev/null
@@ -1,1060 +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/>.
- */
-
-#include "config.h"
-
-#include "core/meta-workspace-manager-private.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "core/window-private.h"
-#include "core/workspace-private.h"
-#include "meta/meta-enum-types.h"
-#include "meta/prefs.h"
-#include "meta/util.h"
-
-G_DEFINE_TYPE (MetaWorkspaceManager, meta_workspace_manager, G_TYPE_OBJECT)
-
-enum
-{
- WORKSPACE_ADDED,
- WORKSPACE_REMOVED,
- WORKSPACE_SWITCHED,
- WORKSPACES_REORDERED,
- ACTIVE_WORKSPACE_CHANGED,
- SHOWING_DESKTOP_CHANGED,
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
-
- PROP_LAYOUT_COLUMNS,
- PROP_LAYOUT_ROWS,
-
- PROP_N_WORKSPACES
-};
-
-static guint workspace_manager_signals [LAST_SIGNAL] = { 0 };
-
-static void prefs_changed_callback (MetaPreference pref,
- gpointer data);
-
-static void
-meta_workspace_manager_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaWorkspaceManager *workspace_manager = META_WORKSPACE_MANAGER (object);
-
- switch (prop_id)
- {
- case PROP_LAYOUT_COLUMNS:
- g_value_set_int (value, workspace_manager->columns_of_workspaces);
- break;
- case PROP_LAYOUT_ROWS:
- g_value_set_int (value, workspace_manager->rows_of_workspaces);
- break;
- case PROP_N_WORKSPACES:
- g_value_set_int (value, meta_workspace_manager_get_n_workspaces (workspace_manager));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_workspace_manager_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_workspace_manager_finalize (GObject *object)
-{
- MetaWorkspaceManager *workspace_manager = META_WORKSPACE_MANAGER (object);
-
- meta_prefs_remove_listener (prefs_changed_callback, workspace_manager);
-
- G_OBJECT_CLASS (meta_workspace_manager_parent_class)->finalize (object);
-}
-
-static void
-meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = meta_workspace_manager_get_property;
- object_class->set_property = meta_workspace_manager_set_property;
-
- object_class->finalize = meta_workspace_manager_finalize;
-
- workspace_manager_signals[WORKSPACE_ADDED] =
- g_signal_new ("workspace-added",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE,
- 1,
- G_TYPE_INT);
-
- workspace_manager_signals[WORKSPACE_REMOVED] =
- g_signal_new ("workspace-removed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE,
- 1,
- G_TYPE_INT);
-
- workspace_manager_signals[WORKSPACE_SWITCHED] =
- g_signal_new ("workspace-switched",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE,
- 3,
- G_TYPE_INT,
- G_TYPE_INT,
- META_TYPE_MOTION_DIRECTION);
-
- /* Emitted when calling meta_workspace_manager_reorder_workspace.
- *
- * This signal is emitted when a workspace has been reordered to
- * a different index. Note that other workspaces can change
- * their index too when reordering happens.
- */
- workspace_manager_signals[WORKSPACES_REORDERED] =
- g_signal_new ("workspaces-reordered",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED] =
- g_signal_new ("active-workspace-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- workspace_manager_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);
-
- g_object_class_install_property (object_class,
- PROP_LAYOUT_COLUMNS,
- g_param_spec_int ("layout-columns",
- "Layout columns",
- "Number of columns in layout",
- -1, G_MAXINT, 1,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (object_class,
- PROP_LAYOUT_ROWS,
- g_param_spec_int ("layout-rows",
- "Layout rows",
- "Number of rows in layout",
- -1, G_MAXINT, -1,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (object_class,
- PROP_N_WORKSPACES,
- g_param_spec_int ("n-workspaces",
- "N Workspaces",
- "Number of workspaces",
- 1, G_MAXINT, 1,
- G_PARAM_READABLE));
-}
-
-static void
-meta_workspace_manager_init (MetaWorkspaceManager *workspace_manager)
-{
-}
-
-void
-meta_workspace_manager_reload_work_areas (MetaWorkspaceManager *workspace_manager)
-{
- GList *l;
-
- for (l = workspace_manager->workspaces; l; l = l->next)
- {
- MetaWorkspace *workspace = l->data;
-
- meta_workspace_invalidate_work_area (workspace);
- }
-}
-
-MetaWorkspaceManager *
-meta_workspace_manager_new (MetaDisplay *display)
-{
- MetaWorkspaceManager *workspace_manager;
-
- workspace_manager = g_object_new (META_TYPE_WORKSPACE_MANAGER, NULL);
-
- workspace_manager->display = display;
- workspace_manager->active_workspace = NULL;
- workspace_manager->workspaces = NULL;
- workspace_manager->rows_of_workspaces = 1;
- workspace_manager->columns_of_workspaces = -1;
- workspace_manager->vertical_workspaces = FALSE;
- workspace_manager->starting_corner = META_DISPLAY_TOPLEFT;
-
- /* This is the default layout extracted from default
- * variable values in update_num_workspaces ()
- * This can be overridden using _NET_DESKTOP_LAYOUT in
- * meta_x11_display_new (), if it's specified */
- meta_workspace_manager_update_workspace_layout (workspace_manager,
- META_DISPLAY_TOPLEFT,
- FALSE,
- 1,
- -1);
-
- /* There must be at least one workspace at all times,
- * so create that required workspace.
- */
- meta_workspace_new (workspace_manager);
-
- meta_workspace_manager_init_workspaces (workspace_manager);
-
- meta_prefs_add_listener (prefs_changed_callback, workspace_manager);
-
- return workspace_manager;
-}
-
-void
-meta_workspace_manager_init_workspaces (MetaWorkspaceManager *workspace_manager)
-{
- int num;
-
- g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager));
-
- if (meta_prefs_get_dynamic_workspaces ())
- /* This will be properly updated using _NET_NUMBER_OF_DESKTOPS
- * (if set) in meta_x11_display_new () */
- num = 1;
- else
- num = meta_prefs_get_num_workspaces ();
-
- meta_workspace_manager_update_num_workspaces (workspace_manager, META_CURRENT_TIME, num);
-
- meta_workspace_activate (workspace_manager->workspaces->data, META_CURRENT_TIME);
-
- meta_workspace_manager_reload_work_areas (workspace_manager);
-}
-
-int
-meta_workspace_manager_get_n_workspaces (MetaWorkspaceManager *workspace_manager)
-{
- return g_list_length (workspace_manager->workspaces);
-}
-
-/**
- * meta_workspace_manager_get_workspace_by_index:
- * @workspace_manager: a #MetaWorkspaceManager
- * @index: index of one of the display's workspaces
- *
- * Gets the workspace object for one of a workspace manager's workspaces given the workspace
- * index. It's valid to call this function with an out-of-range index and it
- * will robustly return %NULL.
- *
- * Return value: (transfer none) (nullable): the workspace object with specified
- * index, or %NULL if the index is out of range.
- */
-MetaWorkspace *
-meta_workspace_manager_get_workspace_by_index (MetaWorkspaceManager *workspace_manager,
- int idx)
-{
- return g_list_nth_data (workspace_manager->workspaces, idx);
-}
-
-void
-meta_workspace_manager_remove_workspace (MetaWorkspaceManager *workspace_manager,
- MetaWorkspace *workspace,
- guint32 timestamp)
-{
- GList *l;
- GList *next;
- MetaWorkspace *neighbour = NULL;
- int index;
- int active_index;
- gboolean active_index_changed;
- int new_num;
-
- l = g_list_find (workspace_manager->workspaces, workspace);
- if (!l)
- return;
-
- next = l->next;
-
- if (l->prev)
- neighbour = l->prev->data;
- else if (l->next)
- neighbour = l->next->data;
- else
- {
- /* Cannot remove the only workspace! */
- return;
- }
-
- meta_workspace_relocate_windows (workspace, neighbour);
-
- if (workspace == workspace_manager->active_workspace)
- meta_workspace_activate (neighbour, timestamp);
-
- /* To emit the signal after removing the workspace */
- index = meta_workspace_index (workspace);
- active_index = meta_workspace_manager_get_active_workspace_index (workspace_manager);
- active_index_changed = index < active_index;
-
- /* This also removes the workspace from the displays list */
- meta_workspace_remove (workspace);
-
- new_num = g_list_length (workspace_manager->workspaces);
-
- if (!meta_prefs_get_dynamic_workspaces ())
- meta_prefs_set_num_workspaces (new_num);
-
- /* If deleting a workspace before the current workspace, the active
- * workspace index changes, so we need to update that hint */
- if (active_index_changed)
- g_signal_emit (workspace_manager,
- workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED],
- 0, NULL);
-
- for (l = next; l; l = l->next)
- {
- MetaWorkspace *w = l->data;
- meta_workspace_index_changed (w);
- }
-
- meta_display_queue_workarea_recalc (workspace_manager->display);
-
- g_signal_emit (workspace_manager,
- workspace_manager_signals[WORKSPACE_REMOVED],
- 0, index);
- g_object_notify (G_OBJECT (workspace_manager), "n-workspaces");
-}
-
-/**
- * meta_workspace_manager_append_new_workspace:
- * @workspace_manager: a #MetaWorkspaceManager
- * @activate: %TRUE if the workspace should be switched to after creation
- * @timestamp: if switching to a new workspace, timestamp to be used when
- * focusing a window on the new workspace. (Doesn't hurt to pass a valid
- * timestamp when available even if not switching workspaces.)
- *
- * Append a new workspace to the workspace manager and (optionally) switch to that
- * display.
- *
- * Return value: (transfer none): the newly appended workspace.
- */
-MetaWorkspace *
-meta_workspace_manager_append_new_workspace (MetaWorkspaceManager *workspace_manager,
- gboolean activate,
- guint32 timestamp)
-{
- MetaWorkspace *w;
- int new_num;
-
- /* This also adds the workspace to the workspace manager list */
- w = meta_workspace_new (workspace_manager);
-
- if (!w)
- return NULL;
-
- if (activate)
- meta_workspace_activate (w, timestamp);
-
- new_num = g_list_length (workspace_manager->workspaces);
-
- if (!meta_prefs_get_dynamic_workspaces ())
- meta_prefs_set_num_workspaces (new_num);
-
- meta_display_queue_workarea_recalc (workspace_manager->display);
-
- g_signal_emit (workspace_manager, workspace_manager_signals[WORKSPACE_ADDED],
- 0, meta_workspace_index (w));
- g_object_notify (G_OBJECT (workspace_manager), "n-workspaces");
-
- return w;
-}
-
-void
-meta_workspace_manager_update_num_workspaces (MetaWorkspaceManager *workspace_manager,
- guint32 timestamp,
- int new_num)
-{
- int old_num;
- GList *l;
- int i = 0;
- GList *extras = NULL;
- MetaWorkspace *last_remaining = NULL;
- gboolean need_change_space = FALSE;
-
- g_assert (new_num > 0);
-
- if (g_list_length (workspace_manager->workspaces) == (guint) new_num)
- return;
-
- for (l = workspace_manager->workspaces; l; l = l->next)
- {
- MetaWorkspace *w = l->data;
-
- if (i >= new_num)
- extras = g_list_prepend (extras, w);
- else
- last_remaining = w;
-
- ++i;
- }
- old_num = i;
-
- g_assert (last_remaining);
-
- /* Get rid of the extra workspaces by moving all their windows
- * to last_remaining, then activating last_remaining if
- * one of the removed workspaces was active. This will be a bit
- * wacky if the config tool for changing number of workspaces
- * is on a removed workspace ;-)
- */
- for (l = extras; l; l = l->next)
- {
- MetaWorkspace *w = l->data;
-
- meta_workspace_relocate_windows (w, last_remaining);
-
- if (w == workspace_manager->active_workspace)
- need_change_space = TRUE;
- }
-
- if (need_change_space)
- meta_workspace_activate (last_remaining, timestamp);
-
- /* Should now be safe to free the workspaces */
- for (l = extras; l; l = l->next)
- {
- MetaWorkspace *w = l->data;
-
- meta_workspace_remove (w);
- }
-
- g_list_free (extras);
-
- for (i = old_num; i < new_num; i++)
- meta_workspace_new (workspace_manager);
-
- meta_display_queue_workarea_recalc (workspace_manager->display);
-
- for (i = old_num; i < new_num; i++)
- g_signal_emit (workspace_manager,
- workspace_manager_signals[WORKSPACE_ADDED],
- 0, i);
-
- g_object_notify (G_OBJECT (workspace_manager), "n-workspaces");
-}
-
-/**
- * meta_workspace_manager_reorder_workspace:
- * @workspace_manager: a #MetaWorkspaceManager
- * @workspace: a #MetaWorkspace to reorder
- * @new_index: the new index of the passed workspace
- *
- * Reorder a workspace to a new index. If the workspace is currently active
- * the "active-workspace-changed" signal will be emitted.
- * If the workspace's index is the same as @new_index or the workspace
- * will not be found in the list, this function will return.
- *
- * Calling this function will also emit the "workspaces-reordered" signal.
- */
-void
-meta_workspace_manager_reorder_workspace (MetaWorkspaceManager *workspace_manager,
- MetaWorkspace *workspace,
- int new_index)
-{
- GList *l;
- GList *from, *to;
- int index;
- int active_index, new_active_index;
-
- g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager));
- g_return_if_fail (new_index >= 0 &&
- new_index < g_list_length (workspace_manager->workspaces));
-
- l = g_list_find (workspace_manager->workspaces, workspace);
- g_return_if_fail (l);
-
- index = meta_workspace_index (workspace);
-
- if (new_index == index)
- return;
-
- active_index =
- meta_workspace_manager_get_active_workspace_index (workspace_manager);
-
- workspace_manager->workspaces =
- g_list_remove_link (workspace_manager->workspaces, l);
-
- workspace_manager->workspaces =
- g_list_insert (workspace_manager->workspaces, l->data, new_index);
-
- g_list_free (l);
-
- new_active_index =
- meta_workspace_manager_get_active_workspace_index (workspace_manager);
-
- if (active_index != new_active_index)
- g_signal_emit (workspace_manager,
- workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED],
- 0, NULL);
-
- from = g_list_nth (workspace_manager->workspaces, MIN (new_index, index));
- to = g_list_nth (workspace_manager->workspaces, MAX (new_index, index));
- for (l = from; l != to->next; l = l->next)
- {
- MetaWorkspace *w = l->data;
-
- meta_workspace_index_changed (w);
- }
-
- meta_display_queue_workarea_recalc (workspace_manager->display);
- g_signal_emit (workspace_manager,
- workspace_manager_signals[WORKSPACES_REORDERED], 0, NULL);
-}
-
-void
-meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_manager,
- MetaDisplayCorner starting_corner,
- gboolean vertical_layout,
- int n_rows,
- int n_columns)
-{
- g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager));
- g_return_if_fail (n_rows > 0 || n_columns > 0);
- g_return_if_fail (n_rows != 0 && n_columns != 0);
-
- if (workspace_manager->workspace_layout_overridden)
- return;
-
- workspace_manager->vertical_workspaces = vertical_layout != FALSE;
- workspace_manager->starting_corner = starting_corner;
- workspace_manager->rows_of_workspaces = n_rows;
- workspace_manager->columns_of_workspaces = n_columns;
-
- meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u",
- workspace_manager->rows_of_workspaces,
- workspace_manager->columns_of_workspaces,
- workspace_manager->vertical_workspaces,
- workspace_manager->starting_corner);
- g_object_notify (G_OBJECT (workspace_manager), "layout-columns");
- g_object_notify (G_OBJECT (workspace_manager), "layout-rows");
-}
-
-/**
- * meta_workspace_manager_override_workspace_layout:
- * @workspace_manager: a #MetaWorkspaceManager
- * @starting_corner: the corner at which the first workspace is found
- * @vertical_layout: if %TRUE the workspaces are laid out in columns rather than rows
- * @n_rows: number of rows of workspaces, or -1 to determine the number of rows from
- * @n_columns and the total number of workspaces
- * @n_columns: number of columns of workspaces, or -1 to determine the number of columns from
- * @n_rows and the total number of workspaces
- *
- * Explicitly set the layout of workspaces. Once this has been called, the contents of the
- * _NET_DESKTOP_LAYOUT property on the root window are completely ignored.
- */
-void
-meta_workspace_manager_override_workspace_layout (MetaWorkspaceManager *workspace_manager,
- MetaDisplayCorner starting_corner,
- gboolean vertical_layout,
- int n_rows,
- int n_columns)
-{
- workspace_manager->workspace_layout_overridden = FALSE;
-
- meta_workspace_manager_update_workspace_layout (workspace_manager,
- starting_corner,
- vertical_layout,
- n_rows,
- n_columns);
-
- workspace_manager->workspace_layout_overridden = TRUE;
-}
-
-#ifdef WITH_VERBOSE_MODE
-static const char *
-meta_workspace_manager_corner_to_string (MetaDisplayCorner corner)
-{
- switch (corner)
- {
- case META_DISPLAY_TOPLEFT:
- return "TopLeft";
- case META_DISPLAY_TOPRIGHT:
- return "TopRight";
- case META_DISPLAY_BOTTOMLEFT:
- return "BottomLeft";
- case META_DISPLAY_BOTTOMRIGHT:
- return "BottomRight";
- }
-
- return "Unknown";
-}
-#endif /* WITH_VERBOSE_MODE */
-
-void
-meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_manager,
- int num_workspaces,
- int current_space,
- MetaWorkspaceLayout *layout)
-{
- int rows, cols;
- int grid_area;
- int *grid;
- int i, r, c;
- int current_row, current_col;
-
- rows = workspace_manager->rows_of_workspaces;
- cols = workspace_manager->columns_of_workspaces;
- if (rows <= 0 && cols <= 0)
- cols = num_workspaces;
-
- if (rows <= 0)
- rows = num_workspaces / cols + ((num_workspaces % cols) > 0 ? 1 : 0);
- if (cols <= 0)
- cols = num_workspaces / rows + ((num_workspaces % rows) > 0 ? 1 : 0);
-
- /* paranoia */
- if (rows < 1)
- rows = 1;
- if (cols < 1)
- cols = 1;
-
- g_assert (rows != 0 && cols != 0);
-
- grid_area = rows * cols;
-
- meta_verbose ("Getting layout rows = %d cols = %d current = %d "
- "num_spaces = %d vertical = %s corner = %s",
- rows, cols, current_space, num_workspaces,
- workspace_manager->vertical_workspaces ? "(true)" : "(false)",
- meta_workspace_manager_corner_to_string (workspace_manager->starting_corner));
-
- /* ok, we want to setup the distances in the workspace array to go
- * in each direction. Remember, there are many ways that a workspace
- * array can be setup.
- * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html
- * and look at the _NET_DESKTOP_LAYOUT section for details.
- * For instance:
- */
- /* starting_corner = META_DISPLAY_TOPLEFT
- * vertical_workspaces = 0 vertical_workspaces=1
- * 1234 1357
- * 5678 2468
- *
- * starting_corner = META_DISPLAY_TOPRIGHT
- * vertical_workspaces = 0 vertical_workspaces=1
- * 4321 7531
- * 8765 8642
- *
- * starting_corner = META_DISPLAY_BOTTOMLEFT
- * vertical_workspaces = 0 vertical_workspaces=1
- * 5678 2468
- * 1234 1357
- *
- * starting_corner = META_DISPLAY_BOTTOMRIGHT
- * vertical_workspaces = 0 vertical_workspaces=1
- * 8765 8642
- * 4321 7531
- *
- */
- /* keep in mind that we could have a ragged layout, e.g. the "8"
- * in the above grids could be missing
- */
-
-
- grid = g_new (int, grid_area);
-
- i = 0;
-
- switch (workspace_manager->starting_corner)
- {
- case META_DISPLAY_TOPLEFT:
- if (workspace_manager->vertical_workspaces)
- {
- c = 0;
- while (c < cols)
- {
- r = 0;
- while (r < rows)
- {
- grid[r*cols+c] = i;
- ++i;
- ++r;
- }
- ++c;
- }
- }
- else
- {
- r = 0;
- while (r < rows)
- {
- c = 0;
- while (c < cols)
- {
- grid[r*cols+c] = i;
- ++i;
- ++c;
- }
- ++r;
- }
- }
- break;
- case META_DISPLAY_TOPRIGHT:
- if (workspace_manager->vertical_workspaces)
- {
- c = cols - 1;
- while (c >= 0)
- {
- r = 0;
- while (r < rows)
- {
- grid[r*cols+c] = i;
- ++i;
- ++r;
- }
- --c;
- }
- }
- else
- {
- r = 0;
- while (r < rows)
- {
- c = cols - 1;
- while (c >= 0)
- {
- grid[r*cols+c] = i;
- ++i;
- --c;
- }
- ++r;
- }
- }
- break;
- case META_DISPLAY_BOTTOMLEFT:
- if (workspace_manager->vertical_workspaces)
- {
- c = 0;
- while (c < cols)
- {
- r = rows - 1;
- while (r >= 0)
- {
- grid[r*cols+c] = i;
- ++i;
- --r;
- }
- ++c;
- }
- }
- else
- {
- r = rows - 1;
- while (r >= 0)
- {
- c = 0;
- while (c < cols)
- {
- grid[r*cols+c] = i;
- ++i;
- ++c;
- }
- --r;
- }
- }
- break;
- case META_DISPLAY_BOTTOMRIGHT:
- if (workspace_manager->vertical_workspaces)
- {
- c = cols - 1;
- while (c >= 0)
- {
- r = rows - 1;
- while (r >= 0)
- {
- grid[r*cols+c] = i;
- ++i;
- --r;
- }
- --c;
- }
- }
- else
- {
- r = rows - 1;
- while (r >= 0)
- {
- c = cols - 1;
- while (c >= 0)
- {
- grid[r*cols+c] = i;
- ++i;
- --c;
- }
- --r;
- }
- }
- break;
- }
-
- if (i != grid_area)
- meta_bug ("did not fill in the whole workspace grid in %s (%d filled)",
- G_STRFUNC, i);
-
- current_row = 0;
- current_col = 0;
- r = 0;
- while (r < rows)
- {
- c = 0;
- while (c < cols)
- {
- if (grid[r*cols+c] == current_space)
- {
- current_row = r;
- current_col = c;
- }
- else if (grid[r*cols+c] >= num_workspaces)
- {
- /* flag nonexistent spaces with -1 */
- grid[r*cols+c] = -1;
- }
- ++c;
- }
- ++r;
- }
-
- layout->rows = rows;
- layout->cols = cols;
- layout->grid = grid;
- layout->grid_area = grid_area;
- layout->current_row = current_row;
- layout->current_col = current_col;
-
-#ifdef WITH_VERBOSE_MODE
- if (meta_is_verbose ())
- {
- r = 0;
- while (r < layout->rows)
- {
- meta_verbose (" ");
- meta_push_no_msg_prefix ();
- c = 0;
- while (c < layout->cols)
- {
- if (r == layout->current_row &&
- c == layout->current_col)
- meta_verbose ("*%2d ", layout->grid[r*layout->cols+c]);
- else
- meta_verbose ("%3d ", layout->grid[r*layout->cols+c]);
- ++c;
- }
- meta_pop_no_msg_prefix ();
- ++r;
- }
- }
-#endif /* WITH_VERBOSE_MODE */
-}
-
-void
-meta_workspace_manager_free_workspace_layout (MetaWorkspaceLayout *layout)
-{
- g_free (layout->grid);
-}
-
-static void
-queue_windows_showing (MetaWorkspaceManager *workspace_manager)
-{
- GSList *windows, *l;
-
- /* Must operate on all windows on display instead of just on the
- * active_workspace's window list, because the active_workspace's
- * window list may not contain the on_all_workspace windows.
- */
- windows = meta_display_list_windows (workspace_manager->display, META_LIST_DEFAULT);
-
- for (l = windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
-
- meta_window_queue (w, META_QUEUE_CALC_SHOWING);
- }
-
- g_slist_free (windows);
-}
-
-void
-meta_workspace_manager_minimize_all_on_active_workspace_except (MetaWorkspaceManager *workspace_manager,
- MetaWindow *keep)
-{
- GList *l;
-
- for (l = workspace_manager->active_workspace->windows; l; l = l->next)
- {
- MetaWindow *w = l->data;
-
- if (w->has_minimize_func && w != keep)
- meta_window_minimize (w);
- }
-}
-
-void
-meta_workspace_manager_show_desktop (MetaWorkspaceManager *workspace_manager,
- guint32 timestamp)
-{
- GList *l;
-
- if (workspace_manager->active_workspace->showing_desktop)
- return;
-
- workspace_manager->active_workspace->showing_desktop = TRUE;
-
- queue_windows_showing (workspace_manager);
-
- /* Focus the most recently used META_WINDOW_DESKTOP window, if there is one;
- * see bug 159257.
- */
- for (l = workspace_manager->active_workspace->mru_list; l; l = l->next)
- {
- MetaWindow *w = l->data;
-
- if (w->type == META_WINDOW_DESKTOP)
- {
- meta_window_focus (w, timestamp);
- break;
- }
- }
-
- g_signal_emit (workspace_manager,
- workspace_manager_signals[SHOWING_DESKTOP_CHANGED],
- 0, NULL);
-}
-
-void
-meta_workspace_manager_unshow_desktop (MetaWorkspaceManager *workspace_manager)
-{
- if (!workspace_manager->active_workspace->showing_desktop)
- return;
-
- workspace_manager->active_workspace->showing_desktop = FALSE;
-
- queue_windows_showing (workspace_manager);
-
- g_signal_emit (workspace_manager,
- workspace_manager_signals[SHOWING_DESKTOP_CHANGED],
- 0, NULL);
-}
-
-/**
- * meta_workspace_manager_get_workspaces: (skip)
- * @workspace_manager: a #MetaWorkspaceManager
- *
- * Returns: (transfer none) (element-type Meta.Workspace): The workspaces for @display
- */
-GList *
-meta_workspace_manager_get_workspaces (MetaWorkspaceManager *workspace_manager)
-{
- return workspace_manager->workspaces;
-}
-
-int
-meta_workspace_manager_get_active_workspace_index (MetaWorkspaceManager *workspace_manager)
-{
- MetaWorkspace *active = workspace_manager->active_workspace;
-
- if (!active)
- return -1;
-
- return meta_workspace_index (active);
-}
-
-/**
- * meta_workspace_manager_get_active_workspace:
- * @workspace_manager: A #MetaWorkspaceManager
- *
- * Returns: (transfer none): The current workspace
- */
-MetaWorkspace *
-meta_workspace_manager_get_active_workspace (MetaWorkspaceManager *workspace_manager)
-{
- return workspace_manager->active_workspace;
-}
-
-void
-meta_workspace_manager_workspace_switched (MetaWorkspaceManager *workspace_manager,
- int from,
- int to,
- MetaMotionDirection direction)
-{
- g_signal_emit (workspace_manager,
- workspace_manager_signals[WORKSPACE_SWITCHED], 0,
- from, to, direction);
-}
-
-static void
-prefs_changed_callback (MetaPreference pref,
- gpointer data)
-{
- MetaWorkspaceManager *workspace_manager = data;
-
- if ((pref == META_PREF_NUM_WORKSPACES ||
- pref == META_PREF_DYNAMIC_WORKSPACES) &&
- !meta_prefs_get_dynamic_workspaces ())
- {
- guint32 timestamp;
- int new_num;
-
- timestamp =
- meta_display_get_current_time_roundtrip (workspace_manager->display);
- new_num = meta_prefs_get_num_workspaces ();
- meta_workspace_manager_update_num_workspaces (workspace_manager,
- timestamp, new_num);
- }
-}
diff --git a/src/core/mutter.c b/src/core/mutter.c
deleted file mode 100644
index 9d716014a..000000000
--- a/src/core/mutter.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright 2011 Red Hat, Inc.
- *
- * 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/>.
- */
-
-#include "config.h"
-
-#include <glib.h>
-#include <glib/gi18n-lib.h>
-#include <stdlib.h>
-
-#include "compositor/meta-plugin-manager.h"
-#include "meta/main.h"
-#include "meta/meta-context.h"
-#include "meta/util.h"
-
-static gboolean
-print_version (const gchar *option_name,
- const gchar *value,
- gpointer data,
- GError **error)
-{
- g_print ("mutter %s\n", VERSION);
- exit (0);
-}
-
-static const char *plugin = "libdefault";
-
-GOptionEntry mutter_options[] = {
- {
- "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
- print_version,
- N_("Print version"),
- NULL
- },
- {
- "mutter-plugin", 0, 0, G_OPTION_ARG_STRING,
- &plugin,
- N_("Mutter plugin to use"),
- "PLUGIN",
- },
- { NULL }
-};
-
-int
-main (int argc, char **argv)
-{
- g_autoptr (MetaContext) context = NULL;
- g_autoptr (GError) error = NULL;
-
- context = meta_create_context ("Mutter");
-
- meta_context_add_option_entries (context, mutter_options, GETTEXT_PACKAGE);
- if (!meta_context_configure (context, &argc, &argv, &error))
- {
- g_printerr ("Failed to configure: %s", error->message);
- return EXIT_FAILURE;
- }
-
- meta_context_set_plugin_name (context, plugin);
-
- if (!meta_context_setup (context, &error))
- {
- g_printerr ("Failed to setup: %s", error->message);
- return EXIT_FAILURE;
- }
-
- if (!meta_context_start (context, &error))
- {
- g_printerr ("Failed to start: %s", error->message);
- return EXIT_FAILURE;
- }
-
- meta_context_notify_ready (context);
-
- if (!meta_context_run_main_loop (context, &error))
- {
- g_printerr ("Mutter terminated with a failure: %s", error->message);
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/src/core/place.c b/src/core/place.c
deleted file mode 100644
index 1075fe20d..000000000
--- a/src/core/place.c
+++ /dev/null
@@ -1,942 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter window placement */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002, 2003 Red Hat, Inc.
- * Copyright (C) 2003 Rob Adams
- * Copyright (C) 2005 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/>.
- */
-
-#include "config.h"
-
-#include "core/place.h"
-
-#include <gdk/gdk.h>
-#include <math.h>
-#include <stdlib.h>
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-logical-monitor.h"
-#include "core/boxes-private.h"
-#include "meta/meta-backend.h"
-#include "meta/prefs.h"
-#include "meta/workspace.h"
-
-typedef enum
-{
- META_LEFT,
- META_RIGHT,
- META_TOP,
- META_BOTTOM
-} MetaWindowDirection;
-
-static gint
-northwestcmp (gconstpointer a, gconstpointer b)
-{
- MetaWindow *aw = (gpointer) a;
- MetaWindow *bw = (gpointer) b;
- MetaRectangle a_frame;
- MetaRectangle b_frame;
- int from_origin_a;
- int from_origin_b;
- int ax, ay, bx, by;
-
- meta_window_get_frame_rect (aw, &a_frame);
- meta_window_get_frame_rect (bw, &b_frame);
- ax = a_frame.x;
- ay = a_frame.y;
- bx = b_frame.x;
- by = b_frame.y;
-
- /* probably there's a fast good-enough-guess we could use here. */
- from_origin_a = sqrt (ax * ax + ay * ay);
- from_origin_b = sqrt (bx * bx + by * by);
-
- if (from_origin_a < from_origin_b)
- return -1;
- else if (from_origin_a > from_origin_b)
- return 1;
- else
- return 0;
-}
-
-static void
-find_next_cascade (MetaWindow *window,
- /* visible windows on relevant workspaces */
- GList *windows,
- int x,
- int y,
- int *new_x,
- int *new_y)
-{
- MetaBackend *backend = meta_get_backend ();
- GList *tmp;
- GList *sorted;
- int cascade_x, cascade_y;
- MetaRectangle titlebar_rect;
- int x_threshold, y_threshold;
- MetaRectangle frame_rect;
- int window_width, window_height;
- int cascade_stage;
- MetaRectangle work_area;
- MetaLogicalMonitor *current;
-
- sorted = g_list_copy (windows);
- sorted = g_list_sort (sorted, northwestcmp);
-
- /* This is a "fuzzy" cascade algorithm.
- * For each window in the list, we find where we'd cascade a
- * new window after it. If a window is already nearly at that
- * position, we move on.
- */
-
- /* arbitrary-ish threshold, honors user attempts to
- * manually cascade.
- */
-#define CASCADE_FUZZ 15
- meta_window_get_titlebar_rect (window, &titlebar_rect);
- x_threshold = MAX (titlebar_rect.x, CASCADE_FUZZ);
- y_threshold = MAX (titlebar_rect.y, CASCADE_FUZZ);
-
- /* Find furthest-SE origin of all workspaces.
- * cascade_x, cascade_y are the target position
- * of NW corner of window frame.
- */
-
- current = meta_backend_get_current_logical_monitor (backend);
- meta_window_get_work_area_for_logical_monitor (window, current, &work_area);
-
- cascade_x = MAX (0, work_area.x);
- cascade_y = MAX (0, work_area.y);
-
- /* Find first cascade position that's not used. */
-
- meta_window_get_frame_rect (window, &frame_rect);
- window_width = frame_rect.width;
- window_height = frame_rect.height;
-
- cascade_stage = 0;
- tmp = sorted;
- while (tmp != NULL)
- {
- MetaWindow *w;
- MetaRectangle w_frame_rect;
- int wx, wy;
-
- w = tmp->data;
-
- /* we want frame position, not window position */
- meta_window_get_frame_rect (w, &w_frame_rect);
- wx = w_frame_rect.x;
- wy = w_frame_rect.y;
-
- if (ABS (wx - cascade_x) < x_threshold &&
- ABS (wy - cascade_y) < y_threshold)
- {
- meta_window_get_titlebar_rect (w, &titlebar_rect);
-
- /* Cascade the window evenly by the titlebar height; this isn't a typo. */
- cascade_x = wx + titlebar_rect.height;
- cascade_y = wy + titlebar_rect.height;
-
- /* If we go off the screen, start over with a new cascade */
- if (((cascade_x + window_width) >
- (work_area.x + work_area.width)) ||
- ((cascade_y + window_height) >
- (work_area.y + work_area.height)))
- {
- cascade_x = MAX (0, work_area.x);
- cascade_y = MAX (0, work_area.y);
-
-#define CASCADE_INTERVAL 50 /* space between top-left corners of cascades */
- cascade_stage += 1;
- cascade_x += CASCADE_INTERVAL * cascade_stage;
-
- /* start over with a new cascade translated to the right, unless
- * we are out of space
- */
- if ((cascade_x + window_width) <
- (work_area.x + work_area.width))
- {
- tmp = sorted;
- continue;
- }
- else
- {
- /* All out of space, this cascade_x won't work */
- cascade_x = MAX (0, work_area.x);
- break;
- }
- }
- }
- else
- {
- /* Keep searching for a further-down-the-diagonal window. */
- }
-
- tmp = tmp->next;
- }
-
- /* cascade_x and cascade_y will match the last window in the list
- * that was "in the way" (in the approximate cascade diagonal)
- */
-
- g_list_free (sorted);
-
- *new_x = cascade_x;
- *new_y = cascade_y;
-}
-
-static void
-find_most_freespace (MetaWindow *window,
- /* visible windows on relevant workspaces */
- MetaWindow *focus_window,
- int x,
- int y,
- int *new_x,
- int *new_y)
-{
- MetaWindowDirection side;
- int max_area;
- int max_width, max_height, left, right, top, bottom;
- int left_space, right_space, top_space, bottom_space;
- MetaRectangle work_area;
- MetaRectangle avoid;
- MetaRectangle frame_rect;
-
- meta_window_get_work_area_current_monitor (focus_window, &work_area);
- meta_window_get_frame_rect (focus_window, &avoid);
- meta_window_get_frame_rect (window, &frame_rect);
-
- /* Find the areas of choosing the various sides of the focus window */
- max_width = MIN (avoid.width, frame_rect.width);
- max_height = MIN (avoid.height, frame_rect.height);
- left_space = avoid.x - work_area.x;
- right_space = work_area.width - (avoid.x + avoid.width - work_area.x);
- top_space = avoid.y - work_area.y;
- bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y);
- left = MIN (left_space, frame_rect.width);
- right = MIN (right_space, frame_rect.width);
- top = MIN (top_space, frame_rect.height);
- bottom = MIN (bottom_space, frame_rect.height);
-
- /* Find out which side of the focus_window can show the most of the window */
- side = META_LEFT;
- max_area = left*max_height;
- if (right*max_height > max_area)
- {
- side = META_RIGHT;
- max_area = right*max_height;
- }
- if (top*max_width > max_area)
- {
- side = META_TOP;
- max_area = top*max_width;
- }
- if (bottom*max_width > max_area)
- {
- side = META_BOTTOM;
- max_area = bottom*max_width;
- }
-
- /* Give up if there's no where to put it (i.e. focus window is maximized) */
- if (max_area == 0)
- return;
-
- /* Place the window on the relevant side; if the whole window fits,
- * make it adjacent to the focus window; if not, make sure the
- * window doesn't go off the edge of the screen.
- */
- switch (side)
- {
- case META_LEFT:
- *new_y = avoid.y;
- if (left_space > frame_rect.width)
- *new_x = avoid.x - frame_rect.width;
- else
- *new_x = work_area.x;
- break;
- case META_RIGHT:
- *new_y = avoid.y;
- if (right_space > frame_rect.width)
- *new_x = avoid.x + avoid.width;
- else
- *new_x = work_area.x + work_area.width - frame_rect.width;
- break;
- case META_TOP:
- *new_x = avoid.x;
- if (top_space > frame_rect.height)
- *new_y = avoid.y - frame_rect.height;
- else
- *new_y = work_area.y;
- break;
- case META_BOTTOM:
- *new_x = avoid.x;
- if (bottom_space > frame_rect.height)
- *new_y = avoid.y + avoid.height;
- else
- *new_y = work_area.y + work_area.height - frame_rect.height;
- break;
- }
-}
-
-static gboolean
-window_overlaps_focus_window (MetaWindow *window)
-{
- MetaWindow *focus_window;
- MetaRectangle window_frame, focus_frame, overlap;
-
- focus_window = window->display->focus_window;
- if (focus_window == NULL)
- return FALSE;
-
- meta_window_get_frame_rect (window, &window_frame);
- meta_window_get_frame_rect (focus_window, &focus_frame);
-
- return meta_rectangle_intersect (&window_frame,
- &focus_frame,
- &overlap);
-}
-
-static gboolean
-window_place_centered (MetaWindow *window)
-{
- MetaWindowType type;
-
- type = window->type;
-
- return (type == META_WINDOW_DIALOG ||
- type == META_WINDOW_MODAL_DIALOG ||
- type == META_WINDOW_SPLASHSCREEN ||
- (type == META_WINDOW_NORMAL && meta_prefs_get_center_new_windows ()));
-}
-
-static void
-avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
- int *x,
- int *y)
-{
- /* We can't center this dialog if it was denied focus and it
- * overlaps with the focus window and this dialog is modal and this
- * dialog is in the same app as the focus window (*phew*...please
- * don't make me say that ten times fast). See bug 307875 comment 11
- * and 12 for details, but basically it means this is probably a
- * second modal dialog for some app while the focus window is the
- * first modal dialog. We should probably make them simultaneously
- * visible in general, but it becomes mandatory to do so due to
- * buggy apps (e.g. those using gtk+ *sigh*) because in those cases
- * this second modal dialog also happens to be modal to the first
- * dialog in addition to the main window, while it has only let us
- * know about the modal-to-the-main-window part.
- */
-
- MetaWindow *focus_window;
-
- focus_window = window->display->focus_window;
-
- /* denied_focus_and_not_transient is only set when focus_window != NULL */
-
- if (window->denied_focus_and_not_transient &&
- window->type == META_WINDOW_MODAL_DIALOG &&
- meta_window_same_application (window, focus_window) &&
- window_overlaps_focus_window (window))
- {
- find_most_freespace (window, focus_window, *x, *y, x, y);
- meta_topic (META_DEBUG_PLACEMENT,
- "Dialog window %s was denied focus but may be modal "
- "to the focus window; had to move it to avoid the "
- "focus window",
- window->desc);
- }
-}
-
-static gboolean
-rectangle_overlaps_some_window (MetaRectangle *rect,
- GList *windows)
-{
- GList *tmp;
- MetaRectangle dest;
-
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *other = tmp->data;
- MetaRectangle other_rect;
-
- switch (other->type)
- {
- case META_WINDOW_DOCK:
- case META_WINDOW_SPLASHSCREEN:
- case META_WINDOW_DESKTOP:
- case META_WINDOW_DIALOG:
- case META_WINDOW_MODAL_DIALOG:
- /* override redirect window types: */
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_COMBO:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- break;
-
- case META_WINDOW_NORMAL:
- case META_WINDOW_UTILITY:
- case META_WINDOW_TOOLBAR:
- case META_WINDOW_MENU:
- meta_window_get_frame_rect (other, &other_rect);
-
- if (meta_rectangle_intersect (rect, &other_rect, &dest))
- return TRUE;
- break;
- }
-
- tmp = tmp->next;
- }
-
- return FALSE;
-}
-
-static gint
-leftmost_cmp (gconstpointer a, gconstpointer b)
-{
- MetaWindow *aw = (gpointer) a;
- MetaWindow *bw = (gpointer) b;
- MetaRectangle a_frame;
- MetaRectangle b_frame;
- int ax, bx;
-
- meta_window_get_frame_rect (aw, &a_frame);
- meta_window_get_frame_rect (bw, &b_frame);
- ax = a_frame.x;
- bx = b_frame.x;
-
- if (ax < bx)
- return -1;
- else if (ax > bx)
- return 1;
- else
- return 0;
-}
-
-static gint
-topmost_cmp (gconstpointer a, gconstpointer b)
-{
- MetaWindow *aw = (gpointer) a;
- MetaWindow *bw = (gpointer) b;
- MetaRectangle a_frame;
- MetaRectangle b_frame;
- int ay, by;
-
- meta_window_get_frame_rect (aw, &a_frame);
- meta_window_get_frame_rect (bw, &b_frame);
- ay = a_frame.y;
- by = b_frame.y;
-
- if (ay < by)
- return -1;
- else if (ay > by)
- return 1;
- else
- return 0;
-}
-
-static void
-center_tile_rect_in_area (MetaRectangle *rect,
- MetaRectangle *work_area)
-{
- int fluff;
-
- /* The point here is to tile a window such that "extra"
- * space is equal on either side (i.e. so a full screen
- * of windows tiled this way would center the windows
- * as a group)
- */
-
- fluff = (work_area->width % (rect->width+1)) / 2;
- rect->x = work_area->x + fluff;
- fluff = (work_area->height % (rect->height+1)) / 3;
- rect->y = work_area->y + fluff;
-}
-
-/* Find the leftmost, then topmost, empty area on the workspace
- * that can contain the new window.
- *
- * Cool feature to have: if we can't fit the current window size,
- * try shrinking the window (within geometry constraints). But
- * beware windows such as Emacs with no sane minimum size, we
- * don't want to create a 1x1 Emacs.
- */
-static gboolean
-find_first_fit (MetaWindow *window,
- /* visible windows on relevant workspaces */
- GList *windows,
- MetaLogicalMonitor *logical_monitor,
- int x,
- int y,
- int *new_x,
- int *new_y)
-{
- /* This algorithm is limited - it just brute-force tries
- * to fit the window in a small number of locations that are aligned
- * with existing windows. It tries to place the window on
- * the bottom of each existing window, and then to the right
- * of each existing window, aligned with the left/top of the
- * existing window in each of those cases.
- */
- int retval;
- GList *below_sorted;
- GList *right_sorted;
- GList *tmp;
- MetaRectangle rect;
- MetaRectangle work_area;
-
- retval = FALSE;
-
- /* Below each window */
- below_sorted = g_list_copy (windows);
- below_sorted = g_list_sort (below_sorted, leftmost_cmp);
- below_sorted = g_list_sort (below_sorted, topmost_cmp);
-
- /* To the right of each window */
- right_sorted = g_list_copy (windows);
- right_sorted = g_list_sort (right_sorted, topmost_cmp);
- right_sorted = g_list_sort (right_sorted, leftmost_cmp);
-
- meta_window_get_frame_rect (window, &rect);
-
-#ifdef WITH_VERBOSE_MODE
- {
- char monitor_location_string[RECT_LENGTH];
-
- meta_rectangle_to_string (&logical_monitor->rect,
- monitor_location_string);
- meta_topic (META_DEBUG_PLACEMENT,
- "Natural monitor is %s",
- monitor_location_string);
- }
-#endif
-
- meta_window_get_work_area_for_logical_monitor (window,
- logical_monitor,
- &work_area);
-
- center_tile_rect_in_area (&rect, &work_area);
-
- if (meta_rectangle_contains_rect (&work_area, &rect) &&
- !rectangle_overlaps_some_window (&rect, windows))
- {
- *new_x = rect.x;
- *new_y = rect.y;
-
- retval = TRUE;
-
- goto out;
- }
-
- /* try below each window */
- tmp = below_sorted;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
- MetaRectangle frame_rect;
-
- meta_window_get_frame_rect (w, &frame_rect);
-
- rect.x = frame_rect.x;
- rect.y = frame_rect.y + frame_rect.height;
-
- if (meta_rectangle_contains_rect (&work_area, &rect) &&
- !rectangle_overlaps_some_window (&rect, below_sorted))
- {
- *new_x = rect.x;
- *new_y = rect.y;
-
- retval = TRUE;
-
- goto out;
- }
-
- tmp = tmp->next;
- }
-
- /* try to the right of each window */
- tmp = right_sorted;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
- MetaRectangle frame_rect;
-
- meta_window_get_frame_rect (w, &frame_rect);
-
- rect.x = frame_rect.x + frame_rect.width;
- rect.y = frame_rect.y;
-
- if (meta_rectangle_contains_rect (&work_area, &rect) &&
- !rectangle_overlaps_some_window (&rect, right_sorted))
- {
- *new_x = rect.x;
- *new_y = rect.y;
-
- retval = TRUE;
-
- goto out;
- }
-
- tmp = tmp->next;
- }
-
- out:
- g_list_free (below_sorted);
- g_list_free (right_sorted);
- return retval;
-}
-
-void
-meta_window_process_placement (MetaWindow *window,
- MetaPlacementRule *placement_rule,
- int *rel_x,
- int *rel_y)
-{
- MetaRectangle anchor_rect;
- int window_width, window_height;
- int x, y;
-
- window_width = placement_rule->width;
- window_height = placement_rule->height;
-
- anchor_rect = placement_rule->anchor_rect;
-
- /* Place at anchor point. */
- if (placement_rule->anchor & META_PLACEMENT_ANCHOR_LEFT)
- x = anchor_rect.x;
- else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_RIGHT)
- x = anchor_rect.x + anchor_rect.width;
- else
- x = anchor_rect.x + (anchor_rect.width / 2);
- if (placement_rule->anchor & META_PLACEMENT_ANCHOR_TOP)
- y = anchor_rect.y;
- else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_BOTTOM)
- y = anchor_rect.y + anchor_rect.height;
- else
- y = anchor_rect.y + (anchor_rect.height / 2);
-
- /* Shift according to gravity. */
- if (placement_rule->gravity & META_PLACEMENT_GRAVITY_LEFT)
- x -= window_width;
- else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_RIGHT)
- x = x;
- else
- x -= window_width / 2;
- if (placement_rule->gravity & META_PLACEMENT_GRAVITY_TOP)
- y -= window_height;
- else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_BOTTOM)
- y = y;
- else
- y -= window_height / 2;
-
- /* Offset according to offset. */
- x += placement_rule->offset_x;
- y += placement_rule->offset_y;
-
- *rel_x = x;
- *rel_y = y;
-}
-
-void
-meta_window_place (MetaWindow *window,
- int x,
- int y,
- int *new_x,
- int *new_y)
-{
- MetaBackend *backend = meta_get_backend ();
- GList *windows = NULL;
- MetaLogicalMonitor *logical_monitor;
-
- meta_topic (META_DEBUG_PLACEMENT, "Placing window %s", window->desc);
-
- g_return_if_fail (!window->placement.rule);
-
- switch (window->type)
- {
- /* Run placement algorithm on these. */
- case META_WINDOW_NORMAL:
- case META_WINDOW_DIALOG:
- case META_WINDOW_MODAL_DIALOG:
- case META_WINDOW_SPLASHSCREEN:
- break;
-
- /* Assume the app knows best how to place these, no placement
- * algorithm ever (other than "leave them as-is")
- */
- case META_WINDOW_DESKTOP:
- case META_WINDOW_DOCK:
- case META_WINDOW_TOOLBAR:
- case META_WINDOW_MENU:
- case META_WINDOW_UTILITY:
- /* override redirect window types: */
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_COMBO:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- goto done;
- }
-
- if (meta_prefs_get_disable_workarounds ())
- {
- switch (window->type)
- {
- /* Only accept USPosition on normal windows because the app is full
- * of shit claiming the user set -geometry for a dialog or dock
- */
- case META_WINDOW_NORMAL:
- if (window->size_hints.flags & USPosition)
- {
- /* don't constrain with placement algorithm */
- meta_topic (META_DEBUG_PLACEMENT,
- "Honoring USPosition for %s instead of using placement algorithm",
- window->desc);
-
- goto done;
- }
- break;
-
- /* Ignore even USPosition on dialogs, splashscreen */
- case META_WINDOW_DIALOG:
- case META_WINDOW_MODAL_DIALOG:
- case META_WINDOW_SPLASHSCREEN:
- break;
-
- /* Assume the app knows best how to place these. */
- case META_WINDOW_DESKTOP:
- case META_WINDOW_DOCK:
- case META_WINDOW_TOOLBAR:
- case META_WINDOW_MENU:
- case META_WINDOW_UTILITY:
- /* override redirect window types: */
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_COMBO:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- if (window->size_hints.flags & PPosition)
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Not placing non-normal non-dialog window with PPosition set");
- goto done;
- }
- break;
- }
- }
- else
- {
- /* workarounds enabled */
-
- if ((window->size_hints.flags & PPosition) ||
- (window->size_hints.flags & USPosition))
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Not placing window with PPosition or USPosition set");
- avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
- goto done;
- }
- }
-
- if (window->type == META_WINDOW_DIALOG ||
- window->type == META_WINDOW_MODAL_DIALOG)
- {
- MetaWindow *parent = meta_window_get_transient_for (window);
-
- if (parent)
- {
- MetaRectangle frame_rect, parent_frame_rect;
-
- meta_window_get_frame_rect (window, &frame_rect);
- meta_window_get_frame_rect (parent, &parent_frame_rect);
-
- y = parent_frame_rect.y;
-
- /* center of parent */
- x = parent_frame_rect.x + parent_frame_rect.width / 2;
- /* center of child over center of parent */
- x -= frame_rect.width / 2;
-
- /* "visually" center window over parent, leaving twice as
- * much space below as on top.
- */
- y += (parent_frame_rect.height - frame_rect.height)/3;
-
- meta_topic (META_DEBUG_PLACEMENT,
- "Centered window %s over transient parent",
- window->desc);
-
- avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
-
- goto done;
- }
- }
-
- /* FIXME UTILITY with transient set should be stacked up
- * on the sides of the parent window or something.
- */
-
- if (window_place_centered (window))
- {
- /* Center on current monitor */
- MetaRectangle work_area;
- MetaRectangle frame_rect;
-
- /* Warning, this function is a round trip! */
- logical_monitor = meta_backend_get_current_logical_monitor (backend);
-
- meta_window_get_work_area_for_logical_monitor (window,
- logical_monitor,
- &work_area);
- meta_window_get_frame_rect (window, &frame_rect);
-
- x = work_area.x + (work_area.width - frame_rect.width) / 2;
- y = work_area.y + (work_area.height - frame_rect.height) / 2;
-
- meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on monitor %d",
- window->desc, logical_monitor->number);
-
- goto done_check_denied_focus;
- }
-
- /* Find windows that matter (not minimized, on same workspace
- * as placed window, may be shaded - if shaded we pretend it isn't
- * for placement purposes)
- */
- {
- GSList *all_windows;
- GSList *tmp;
-
- all_windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
-
- tmp = all_windows;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
-
- if (w != window &&
- meta_window_showing_on_its_workspace (w) &&
- (window->on_all_workspaces ||
- meta_window_located_on_workspace (w, window->workspace)))
- windows = g_list_prepend (windows, w);
-
- tmp = tmp->next;
- }
-
- g_slist_free (all_windows);
- }
-
- /* Warning, on X11 this might be a round trip! */
- logical_monitor = meta_backend_get_current_logical_monitor (backend);
-
- /* Maximize windows if they are too big for their work area (bit of
- * a hack here). Assume undecorated windows probably don't intend to
- * be maximized.
- */
- if (window->has_maximize_func && window->decorated &&
- !window->fullscreen)
- {
- MetaRectangle workarea;
- MetaRectangle frame_rect;
-
- meta_window_get_work_area_for_logical_monitor (window,
- logical_monitor,
- &workarea);
- meta_window_get_frame_rect (window, &frame_rect);
-
- /* If the window is bigger than the screen, then automaximize. Do NOT
- * auto-maximize the directions independently. See #419810.
- */
- if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height)
- {
- window->maximize_horizontally_after_placement = TRUE;
- window->maximize_vertically_after_placement = TRUE;
- }
- }
-
- /* "Origin" placement algorithm */
- x = logical_monitor->rect.x;
- y = logical_monitor->rect.y;
-
- if (find_first_fit (window, windows,
- logical_monitor,
- x, y, &x, &y))
- goto done_check_denied_focus;
-
- /* No good fit? Fall back to cascading... */
- find_next_cascade (window, windows, x, y, &x, &y);
-
- done_check_denied_focus:
- /* If the window is being denied focus and isn't a transient of the
- * focus window, we do NOT want it to overlap with the focus window
- * if at all possible. This is guaranteed to only be called if the
- * focus_window is non-NULL, and we try to avoid that window.
- */
- if (window->denied_focus_and_not_transient)
- {
- MetaWindow *focus_window;
- gboolean found_fit;
-
- focus_window = window->display->focus_window;
- g_assert (focus_window != NULL);
-
- /* No need to do anything if the window doesn't overlap at all */
- found_fit = !window_overlaps_focus_window (window);
-
- /* Try to do a first fit again, this time only taking into account the
- * focus window.
- */
- if (!found_fit)
- {
- GList *focus_window_list;
- focus_window_list = g_list_prepend (NULL, focus_window);
-
- /* Reset x and y ("origin" placement algorithm) */
- x = logical_monitor->rect.x;
- y = logical_monitor->rect.y;
-
- found_fit = find_first_fit (window, focus_window_list,
- logical_monitor,
- x, y, &x, &y);
- g_list_free (focus_window_list);
- }
-
- /* If that still didn't work, just place it where we can see as much
- * as possible.
- */
- if (!found_fit)
- find_most_freespace (window, focus_window, x, y, &x, &y);
- }
-
- done:
- if (windows)
- g_list_free (windows);
-
- *new_x = x;
- *new_y = y;
-}
diff --git a/src/core/place.h b/src/core/place.h
deleted file mode 100644
index 2e2c81141..000000000
--- a/src/core/place.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter window placement */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- *
- * 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/>.
- */
-
-#ifndef META_PLACE_H
-#define META_PLACE_H
-
-#include "core/frame.h"
-#include "core/window-private.h"
-
-void meta_window_process_placement (MetaWindow *window,
- MetaPlacementRule *placement_rule,
- int *rel_x,
- int *rel_y);
-
-void meta_window_place (MetaWindow *window,
- int x,
- int y,
- int *new_x,
- int *new_y);
-
-#endif
diff --git a/src/core/prefs-private.h b/src/core/prefs-private.h
deleted file mode 100644
index e587bfaa1..000000000
--- a/src/core/prefs-private.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2021 Red Hat Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- */
-
-#ifndef PREFS_PRIVATE_H
-#define PREFS_PRIVATE_H
-
-void meta_prefs_init (void);
-
-#endif /* PREFS_PRIVATE_H */
diff --git a/src/core/prefs.c b/src/core/prefs.c
deleted file mode 100644
index 536d9dd57..000000000
--- a/src/core/prefs.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc.
- * Copyright (C) 2006 Elijah Newren
- * Copyright (C) 2008 Thomas Thurman
- * Copyright (C) 2010 Milan Bouchet-Valat, Copyright (C) 2011 Red Hat Inc.
- *
- * 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:prefs
- * @title: Preferences
- * @short_description: Mutter preferences
- */
-
-#include "config.h"
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "compositor/meta-plugin-manager.h"
-#include "core/keybindings-private.h"
-#include "core/meta-accel-parse.h"
-#include "core/prefs-private.h"
-#include "core/util-private.h"
-#include "meta/prefs.h"
-#include "x11/meta-x11-display-private.h"
-
-/* If you add a key, it needs updating in init() and in the gsettings
- * notify listener and of course in the .schemas file.
- *
- * Keys which are handled by one of the unified handlers below are
- * not given a name here, because the purpose of the unified handlers
- * is that keys should be referred to exactly once.
- */
-#define KEY_TITLEBAR_FONT "titlebar-font"
-#define KEY_NUM_WORKSPACES "num-workspaces"
-#define KEY_WORKSPACE_NAMES "workspace-names"
-
-/* Keys from "foreign" schemas */
-#define KEY_GNOME_ACCESSIBILITY "toolkit-accessibility"
-#define KEY_GNOME_ANIMATIONS "enable-animations"
-#define KEY_GNOME_CURSOR_THEME "cursor-theme"
-#define KEY_GNOME_CURSOR_SIZE "cursor-size"
-#define KEY_XKB_OPTIONS "xkb-options"
-
-#define KEY_OVERLAY_KEY "overlay-key"
-#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
-#define KEY_LOCATE_POINTER "locate-pointer"
-
-/* These are the different schemas we are keeping
- * a GSettings instance for */
-#define SCHEMA_GENERAL "org.gnome.desktop.wm.preferences"
-#define SCHEMA_MUTTER "org.gnome.mutter"
-#define SCHEMA_INTERFACE "org.gnome.desktop.interface"
-#define SCHEMA_INPUT_SOURCES "org.gnome.desktop.input-sources"
-#define SCHEMA_MOUSE "org.gnome.desktop.peripherals.mouse"
-
-#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s))
-
-static GList *changes = NULL;
-static guint changed_idle;
-static GList *listeners = NULL;
-static GHashTable *settings_schemas;
-
-static gboolean use_system_font = FALSE;
-static PangoFontDescription *titlebar_font = NULL;
-static MetaVirtualModifier mouse_button_mods = Mod1Mask;
-static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
-static MetaKeyCombo locate_pointer_key_combo = { 0, 0, 0 };
-static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
-static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
-static gboolean raise_on_click = TRUE;
-static gboolean center_new_windows = FALSE;
-static gboolean attach_modal_dialogs = FALSE;
-static int num_workspaces = 4;
-static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE;
-static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER;
-static GDesktopTitlebarAction action_right_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_MENU;
-static gboolean dynamic_workspaces = FALSE;
-static gboolean disable_workarounds = FALSE;
-static gboolean auto_raise = FALSE;
-static gboolean auto_raise_delay = 500;
-static gboolean focus_change_on_pointer_rest = FALSE;
-static gboolean bell_is_visible = FALSE;
-static gboolean bell_is_audible = TRUE;
-static gboolean gnome_accessibility = FALSE;
-static gboolean gnome_animations = TRUE;
-static gboolean locate_pointer_is_enabled = FALSE;
-static unsigned int check_alive_timeout = 5000;
-static char *cursor_theme = NULL;
-/* cursor_size will, when running as an X11 compositing window manager, be the
- * actual cursor size, multiplied with the global window scaling factor. On
- * Wayland, it will be the actual cursor size retrieved from gsettings.
- */
-static int cursor_size = 24;
-static int draggable_border_width = 10;
-static int drag_threshold;
-static gboolean resize_with_right_button = FALSE;
-static gboolean edge_tiling = FALSE;
-static gboolean force_fullscreen = TRUE;
-static gboolean auto_maximize = TRUE;
-static gboolean show_fallback_app_menu = TRUE;
-
-static GDesktopVisualBellType visual_bell_type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH;
-static MetaButtonLayout button_layout;
-
-/* NULL-terminated array */
-static char **workspace_names = NULL;
-
-static gboolean workspaces_only_on_primary = FALSE;
-
-static char *iso_next_group_option = NULL;
-
-static void handle_preference_update_enum (GSettings *settings,
- gchar *key);
-static gboolean update_binding (MetaKeyPref *binding,
- gchar **strokes);
-static gboolean update_key_binding (const char *key,
- gchar **strokes);
-
-static void settings_changed (GSettings *settings,
- gchar *key,
- gpointer data);
-static void bindings_changed (GSettings *settings,
- gchar *key,
- gpointer data);
-
-static void queue_changed (MetaPreference pref);
-
-static void maybe_give_disable_workarounds_warning (void);
-
-static gboolean titlebar_handler (GVariant*, gpointer*, gpointer);
-static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
-static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
-static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer);
-static gboolean locate_pointer_key_handler (GVariant*, gpointer*, gpointer);
-
-static gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer);
-
-static void init_bindings (void);
-
-typedef struct
-{
- MetaPrefsChangedFunc func;
- gpointer data;
-} MetaPrefsListener;
-
-typedef struct
-{
- const char *key;
- const char *schema;
- MetaPreference pref;
-} MetaBasePreference;
-
-typedef struct
-{
- MetaBasePreference base;
- gpointer target;
-} MetaEnumPreference;
-
-typedef struct
-{
- MetaBasePreference base;
- gboolean *target;
-} MetaBoolPreference;
-
-
-/**
- * MetaStringPreference:
- * @handler: (nullable): A handler. Many of the string preferences
- * aren't stored as strings and need parsing; others of them have
- * default values which can't be solved in the general case. If you
- * include a function pointer here, it will be called instead of writing
- * the string value out to the target variable.
- * The function will be passed to g_settings_get_mapped() and should
- * return %TRUE if the mapping was successful and %FALSE otherwise.
- * In the former case the function is expected to handle the result
- * of the conversion itself and call queue_changed() appropriately;
- * in particular the @result (out) parameter as returned by
- * g_settings_get_mapped() will be ignored in all cases.
- * This may be %NULL. If it is, see "target", below.
- * @target: (nullable): Where to write the incoming string.
- * This must be %NULL if the handler is non-%NULL.
- * If the incoming string is %NULL, no change will be made.
- */
-typedef struct
-{
- MetaBasePreference base;
- GSettingsGetMapping handler;
- gchar **target;
-} MetaStringPreference;
-
-typedef struct
-{
- MetaBasePreference base;
- GSettingsGetMapping handler;
- gchar ***target;
-} MetaStringArrayPreference;
-
-typedef struct
-{
- MetaBasePreference base;
- gint *target;
-} MetaIntPreference;
-
-typedef struct
-{
- MetaBasePreference base;
- unsigned int *target;
-} MetaUintPreference;
-
-
-/* All preferences that are not keybindings must be listed here,
- * plus in the GSettings schemas and the MetaPreference enum.
- */
-
-/* FIXMEs: */
-/* @@@ Don't use NULL lines at the end; glib can tell you how big it is */
-
-static MetaEnumPreference preferences_enum[] =
- {
- {
- { "focus-new-windows",
- SCHEMA_GENERAL,
- META_PREF_FOCUS_NEW_WINDOWS,
- },
- &focus_new_windows,
- },
- {
- { "focus-mode",
- SCHEMA_GENERAL,
- META_PREF_FOCUS_MODE,
- },
- &focus_mode,
- },
- {
- { "visual-bell-type",
- SCHEMA_GENERAL,
- META_PREF_VISUAL_BELL_TYPE,
- },
- &visual_bell_type,
- },
- {
- { "action-double-click-titlebar",
- SCHEMA_GENERAL,
- META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
- },
- &action_double_click_titlebar,
- },
- {
- { "action-middle-click-titlebar",
- SCHEMA_GENERAL,
- META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
- },
- &action_middle_click_titlebar,
- },
- {
- { "action-right-click-titlebar",
- SCHEMA_GENERAL,
- META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
- },
- &action_right_click_titlebar,
- },
- { { NULL, 0, 0 }, NULL },
- };
-
-static MetaBoolPreference preferences_bool[] =
- {
- {
- { "attach-modal-dialogs",
- SCHEMA_MUTTER,
- META_PREF_ATTACH_MODAL_DIALOGS,
- },
- &attach_modal_dialogs,
- },
- {
- { "center-new-windows",
- SCHEMA_MUTTER,
- META_PREF_CENTER_NEW_WINDOWS,
- },
- &center_new_windows,
- },
- {
- { "raise-on-click",
- SCHEMA_GENERAL,
- META_PREF_RAISE_ON_CLICK,
- },
- &raise_on_click,
- },
- {
- { "titlebar-uses-system-font",
- SCHEMA_GENERAL,
- META_PREF_TITLEBAR_FONT, /* note! shares a pref */
- },
- &use_system_font,
- },
- {
- { "dynamic-workspaces",
- SCHEMA_MUTTER,
- META_PREF_DYNAMIC_WORKSPACES,
- },
- &dynamic_workspaces,
- },
- {
- { "disable-workarounds",
- SCHEMA_GENERAL,
- META_PREF_DISABLE_WORKAROUNDS,
- },
- &disable_workarounds,
- },
- {
- { "auto-raise",
- SCHEMA_GENERAL,
- META_PREF_AUTO_RAISE,
- },
- &auto_raise,
- },
- {
- { "focus-change-on-pointer-rest",
- SCHEMA_MUTTER,
- META_PREF_FOCUS_CHANGE_ON_POINTER_REST,
- },
- &focus_change_on_pointer_rest
- },
- {
- { "visual-bell",
- SCHEMA_GENERAL,
- META_PREF_VISUAL_BELL,
- },
- &bell_is_visible, /* FIXME: change the name: it's confusing */
- },
- {
- { "audible-bell",
- SCHEMA_GENERAL,
- META_PREF_AUDIBLE_BELL,
- },
- &bell_is_audible, /* FIXME: change the name: it's confusing */
- },
- {
- { KEY_GNOME_ACCESSIBILITY,
- SCHEMA_INTERFACE,
- META_PREF_GNOME_ACCESSIBILITY,
- },
- &gnome_accessibility,
- },
- {
- { KEY_GNOME_ANIMATIONS,
- SCHEMA_INTERFACE,
- META_PREF_GNOME_ANIMATIONS,
- },
- &gnome_animations,
- },
- {
- { "resize-with-right-button",
- SCHEMA_GENERAL,
- META_PREF_RESIZE_WITH_RIGHT_BUTTON,
- },
- &resize_with_right_button,
- },
- {
- { "edge-tiling",
- SCHEMA_MUTTER,
- META_PREF_EDGE_TILING,
- },
- &edge_tiling,
- },
- {
- { "workspaces-only-on-primary",
- SCHEMA_MUTTER,
- META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
- },
- &workspaces_only_on_primary,
- },
- {
- { "auto-maximize",
- SCHEMA_MUTTER,
- META_PREF_AUTO_MAXIMIZE,
- },
- &auto_maximize,
- },
- {
- { KEY_LOCATE_POINTER,
- SCHEMA_INTERFACE,
- META_PREF_LOCATE_POINTER,
- },
- &locate_pointer_is_enabled,
- },
- { { NULL, 0, 0 }, NULL },
- };
-
-static MetaStringPreference preferences_string[] =
- {
- {
- { "mouse-button-modifier",
- SCHEMA_GENERAL,
- META_PREF_MOUSE_BUTTON_MODS,
- },
- mouse_button_mods_handler,
- NULL,
- },
- {
- { KEY_TITLEBAR_FONT,
- SCHEMA_GENERAL,
- META_PREF_TITLEBAR_FONT,
- },
- titlebar_handler,
- NULL,
- },
- {
- { "button-layout",
- SCHEMA_GENERAL,
- META_PREF_BUTTON_LAYOUT,
- },
- button_layout_handler,
- NULL,
- },
- {
- { "cursor-theme",
- SCHEMA_INTERFACE,
- META_PREF_CURSOR_THEME,
- },
- NULL,
- &cursor_theme,
- },
- {
- { "overlay-key",
- SCHEMA_MUTTER,
- META_PREF_KEYBINDINGS,
- },
- overlay_key_handler,
- NULL,
- },
- {
- { "locate-pointer-key",
- SCHEMA_MUTTER,
- META_PREF_KEYBINDINGS,
- },
- locate_pointer_key_handler,
- NULL,
- },
- { { NULL, 0, 0 }, NULL },
- };
-
-static MetaStringArrayPreference preferences_string_array[] =
- {
- {
- { KEY_WORKSPACE_NAMES,
- SCHEMA_GENERAL,
- META_PREF_WORKSPACE_NAMES,
- },
- NULL,
- &workspace_names,
- },
- {
- { KEY_XKB_OPTIONS,
- SCHEMA_INPUT_SOURCES,
- META_PREF_KEYBINDINGS,
- },
- iso_next_group_handler,
- NULL,
- },
- { { NULL, 0, 0 }, NULL },
- };
-
-static MetaIntPreference preferences_int[] =
- {
- {
- { KEY_NUM_WORKSPACES,
- SCHEMA_GENERAL,
- META_PREF_NUM_WORKSPACES,
- },
- &num_workspaces
- },
- {
- { "auto-raise-delay",
- SCHEMA_GENERAL,
- META_PREF_AUTO_RAISE_DELAY,
- },
- &auto_raise_delay
- },
- {
- { "draggable-border-width",
- SCHEMA_MUTTER,
- META_PREF_DRAGGABLE_BORDER_WIDTH,
- },
- &draggable_border_width
- },
- {
- { "drag-threshold",
- SCHEMA_MOUSE,
- META_PREF_DRAG_THRESHOLD,
- },
- &drag_threshold
- },
- {
- { "cursor-size",
- SCHEMA_INTERFACE,
- META_PREF_CURSOR_SIZE,
- },
- &cursor_size
- },
- { { NULL, 0, 0 }, NULL },
- };
-
-static MetaUintPreference preferences_uint[] =
- {
- {
- { "check-alive-timeout",
- SCHEMA_MUTTER,
- META_PREF_CHECK_ALIVE_TIMEOUT,
- },
- &check_alive_timeout,
- },
- { { NULL, 0, 0 }, NULL },
- };
-
-static void
-handle_preference_init_enum (void)
-{
- MetaEnumPreference *cursor = preferences_enum;
-
- while (cursor->base.key != NULL)
- {
- if (cursor->target==NULL)
- continue;
-
- *((gint *) cursor->target) =
- g_settings_get_enum (SETTINGS (cursor->base.schema), cursor->base.key);
-
- ++cursor;
- }
-}
-
-static void
-handle_preference_init_bool (void)
-{
- MetaBoolPreference *cursor = preferences_bool;
-
- while (cursor->base.key != NULL)
- {
- if (cursor->target!=NULL)
- *cursor->target =
- g_settings_get_boolean (SETTINGS (cursor->base.schema),
- cursor->base.key);
-
- ++cursor;
- }
-
- maybe_give_disable_workarounds_warning ();
-}
-
-static void
-handle_preference_init_string (void)
-{
- MetaStringPreference *cursor = preferences_string;
-
- while (cursor->base.key != NULL)
- {
- char *value;
-
- /* Complex keys have a mapping function to check validity */
- if (cursor->handler)
- {
- if (cursor->target)
- meta_bug ("%s has both a target and a handler", cursor->base.key);
-
- g_settings_get_mapped (SETTINGS (cursor->base.schema),
- cursor->base.key, cursor->handler, NULL);
- }
- else
- {
- if (!cursor->target)
- meta_bug ("%s must have handler or target", cursor->base.key);
-
- g_free (*(cursor->target));
-
- value = g_settings_get_string (SETTINGS (cursor->base.schema),
- cursor->base.key);
-
- *(cursor->target) = value;
- }
-
- ++cursor;
- }
-}
-
-static void
-handle_preference_init_string_array (void)
-{
- MetaStringArrayPreference *cursor = preferences_string_array;
-
- while (cursor->base.key != NULL)
- {
- char **value;
-
- /* Complex keys have a mapping function to check validity */
- if (cursor->handler)
- {
- if (cursor->target)
- meta_bug ("%s has both a target and a handler", cursor->base.key);
-
- g_settings_get_mapped (SETTINGS (cursor->base.schema),
- cursor->base.key, cursor->handler, NULL);
- }
- else
- {
- if (!cursor->target)
- meta_bug ("%s must have handler or target", cursor->base.key);
-
- if (*(cursor->target))
- g_strfreev (*(cursor->target));
-
- value = g_settings_get_strv (SETTINGS (cursor->base.schema),
- cursor->base.key);
-
- *(cursor->target) = value;
- }
-
- ++cursor;
- }
-}
-
-static void
-handle_preference_init_int (void)
-{
- MetaIntPreference *cursor = preferences_int;
-
-
- while (cursor->base.key != NULL)
- {
- if (cursor->target)
- *cursor->target = g_settings_get_int (SETTINGS (cursor->base.schema),
- cursor->base.key);
-
- ++cursor;
- }
-}
-
-static void
-handle_preference_init_uint (void)
-{
- MetaUintPreference *cursor = preferences_uint;
-
- while (cursor->base.key != NULL)
- {
- if (cursor->target)
- *cursor->target = g_settings_get_uint (SETTINGS (cursor->base.schema),
- cursor->base.key);
-
- ++cursor;
- }
-}
-
-static void
-handle_preference_update_enum (GSettings *settings,
- gchar *key)
-{
- MetaEnumPreference *cursor = preferences_enum;
- gint old_value;
-
- while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
- ++cursor;
-
- if (cursor->base.key == NULL)
- /* Didn't recognise that key. */
- return;
-
- /* We need to know whether the value changes, so
- * store the current value away.
- */
-
- old_value = * ((gint *)cursor->target);
- *((gint *)cursor->target) =
- g_settings_get_enum (SETTINGS (cursor->base.schema), key);
-
- /* Did it change? If so, tell the listeners about it. */
- if (old_value != *((gint *)cursor->target))
- queue_changed (cursor->base.pref);
-}
-
-static void
-handle_preference_update_bool (GSettings *settings,
- gchar *key)
-{
- MetaBoolPreference *cursor = preferences_bool;
- gboolean old_value;
-
- while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
- ++cursor;
-
- if (cursor->base.key == NULL || cursor->target == NULL)
- /* Unknown key or no work for us to do. */
- return;
-
- /* We need to know whether the value changes, so
- * store the current value away.
- */
- old_value = *((gboolean *) cursor->target);
-
- /* Now look it up... */
- *((gboolean *) cursor->target) =
- g_settings_get_boolean (SETTINGS (cursor->base.schema), key);
-
- /* Did it change? If so, tell the listeners about it. */
- if (old_value != *((gboolean *)cursor->target))
- queue_changed (cursor->base.pref);
-
- if (cursor->base.pref==META_PREF_DISABLE_WORKAROUNDS)
- maybe_give_disable_workarounds_warning ();
-}
-
-static void
-handle_preference_update_string (GSettings *settings,
- gchar *key)
-{
- MetaStringPreference *cursor = preferences_string;
- char *value;
- gboolean inform_listeners = FALSE;
-
- while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
- ++cursor;
-
- if (cursor->base.key==NULL)
- /* Didn't recognise that key. */
- return;
-
- /* Complex keys have a mapping function to check validity */
- if (cursor->handler)
- {
- if (cursor->target)
- meta_bug ("%s has both a target and a handler", cursor->base.key);
-
- g_settings_get_mapped (SETTINGS (cursor->base.schema),
- cursor->base.key, cursor->handler, NULL);
- }
- else
- {
- if (!cursor->target)
- meta_bug ("%s must have handler or target", cursor->base.key);
-
- value = g_settings_get_string (SETTINGS (cursor->base.schema),
- cursor->base.key);
-
- inform_listeners = (g_strcmp0 (value, *(cursor->target)) != 0);
-
- g_free(*(cursor->target));
-
- *(cursor->target) = value;
- }
-
- if (inform_listeners)
- queue_changed (cursor->base.pref);
-}
-
-static void
-handle_preference_update_string_array (GSettings *settings,
- gchar *key)
-{
- MetaStringArrayPreference *cursor = preferences_string_array;
- gboolean inform_listeners = FALSE;
-
- while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
- ++cursor;
-
- if (cursor->base.key==NULL)
- /* Didn't recognise that key. */
- return;
-
- /* Complex keys have a mapping function to check validity */
- if (cursor->handler)
- {
- if (cursor->target)
- meta_bug ("%s has both a target and a handler", cursor->base.key);
-
- g_settings_get_mapped (SETTINGS (cursor->base.schema),
- cursor->base.key, cursor->handler, NULL);
- }
- else
- {
- char **values, **previous;
- int n_values, n_previous, i;
-
- if (!cursor->target)
- meta_bug ("%s must have handler or target", cursor->base.key);
-
- values = g_settings_get_strv (SETTINGS (cursor->base.schema),
- cursor->base.key);
- n_values = g_strv_length (values);
- previous = *(cursor->target);
- n_previous = previous ? g_strv_length (previous) : 0;
-
- inform_listeners = n_previous != n_values;
- for (i = 0; i < n_values && !inform_listeners; i++)
- inform_listeners = g_strcmp0 (values[i], previous[i]) != 0;
-
- if (*(cursor->target))
- g_strfreev (*(cursor->target));
- *(cursor->target) = values;
- }
-
- if (inform_listeners)
- queue_changed (cursor->base.pref);
-}
-
-static void
-handle_preference_update_int (GSettings *settings,
- gchar *key)
-{
- MetaIntPreference *cursor = preferences_int;
- gint new_value;
-
- while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
- ++cursor;
-
- if (cursor->base.key == NULL || cursor->target == NULL)
- /* Unknown key or no work for us to do. */
- return;
-
- new_value = g_settings_get_int (SETTINGS (cursor->base.schema), key);
-
- /* Did it change? If so, tell the listeners about it. */
- if (*cursor->target != new_value)
- {
- *cursor->target = new_value;
- queue_changed (cursor->base.pref);
- }
-}
-
-static void
-handle_preference_update_uint (GSettings *settings,
- char *key)
-{
- MetaUintPreference *cursor = preferences_uint;
- unsigned int new_value;
-
- while (cursor->base.key && strcmp (key, cursor->base.key) != 0)
- ++cursor;
-
- if (!cursor->base.key || !cursor->target)
- return;
-
- new_value = g_settings_get_uint (SETTINGS (cursor->base.schema), key);
-
- if (*cursor->target != new_value)
- {
- *cursor->target = new_value;
- queue_changed (cursor->base.pref);
- }
-}
-
-
-/****************************************************************************/
-/* Listeners. */
-/****************************************************************************/
-
-/**
- * meta_prefs_add_listener: (skip)
- * @func: a #MetaPrefsChangedFunc
- * @user_data: data passed to the function
- *
- */
-void
-meta_prefs_add_listener (MetaPrefsChangedFunc func,
- gpointer user_data)
-{
- MetaPrefsListener *l;
-
- l = g_new (MetaPrefsListener, 1);
- l->func = func;
- l->data = user_data;
-
- listeners = g_list_prepend (listeners, l);
-}
-
-/**
- * meta_prefs_remove_listener: (skip)
- * @func: a #MetaPrefsChangedFunc
- * @user_data: data passed to the function
- *
- */
-void
-meta_prefs_remove_listener (MetaPrefsChangedFunc func,
- gpointer user_data)
-{
- GList *tmp;
-
- tmp = listeners;
- while (tmp != NULL)
- {
- MetaPrefsListener *l = tmp->data;
-
- if (l->func == func &&
- l->data == user_data)
- {
- g_free (l);
- listeners = g_list_delete_link (listeners, tmp);
-
- return;
- }
-
- tmp = tmp->next;
- }
-}
-
-static void
-emit_changed (MetaPreference pref)
-{
- GList *tmp;
- GList *copy;
-
- meta_topic (META_DEBUG_PREFS, "Notifying listeners that pref %s changed",
- meta_preference_to_string (pref));
-
- copy = g_list_copy (listeners);
-
- tmp = copy;
-
- while (tmp != NULL)
- {
- MetaPrefsListener *l = tmp->data;
-
- (* l->func) (pref, l->data);
-
- tmp = tmp->next;
- }
-
- g_list_free (copy);
-}
-
-static gboolean
-changed_idle_handler (gpointer data)
-{
- GList *tmp;
- GList *copy;
-
- changed_idle = 0;
-
- copy = g_list_copy (changes); /* reentrancy paranoia */
-
- g_list_free (changes);
- changes = NULL;
-
- tmp = copy;
- while (tmp != NULL)
- {
- MetaPreference pref = GPOINTER_TO_INT (tmp->data);
-
- emit_changed (pref);
-
- tmp = tmp->next;
- }
-
- g_list_free (copy);
-
- return FALSE;
-}
-
-static void
-queue_changed (MetaPreference pref)
-{
- meta_topic (META_DEBUG_PREFS, "Queueing change of pref %s",
- meta_preference_to_string (pref));
-
- if (g_list_find (changes, GINT_TO_POINTER (pref)) == NULL)
- changes = g_list_prepend (changes, GINT_TO_POINTER (pref));
- else
- meta_topic (META_DEBUG_PREFS, "Change of pref %s was already pending",
- meta_preference_to_string (pref));
-
- if (changed_idle == 0)
- {
- changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY,
- changed_idle_handler, NULL, NULL);
- g_source_set_name_by_id (changed_idle, "[mutter] changed_idle_handler");
- }
-}
-
-
-/****************************************************************************/
-/* Initialisation. */
-/****************************************************************************/
-
-void
-meta_prefs_init (void)
-{
- GSettings *settings;
-
- settings_schemas = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
-
- settings = g_settings_new (SCHEMA_GENERAL);
- g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
- g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_GENERAL), settings);
-
- settings = g_settings_new (SCHEMA_MUTTER);
- g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
- g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MUTTER), settings);
-
- settings = g_settings_new (SCHEMA_MOUSE);
- g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
- g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MOUSE), settings);
-
- /* Individual keys we watch outside of our schemas */
- settings = g_settings_new (SCHEMA_INTERFACE);
- g_signal_connect (settings, "changed::" KEY_GNOME_ACCESSIBILITY,
- G_CALLBACK (settings_changed), NULL);
- g_signal_connect (settings, "changed::" KEY_GNOME_ANIMATIONS,
- G_CALLBACK (settings_changed), NULL);
- g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_THEME,
- G_CALLBACK (settings_changed), NULL);
- g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_SIZE,
- G_CALLBACK (settings_changed), NULL);
- g_signal_connect (settings, "changed::" KEY_LOCATE_POINTER,
- G_CALLBACK (settings_changed), NULL);
- g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings);
-
- settings = g_settings_new (SCHEMA_INPUT_SOURCES);
- g_signal_connect (settings, "changed::" KEY_XKB_OPTIONS,
- G_CALLBACK (settings_changed), NULL);
- g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INPUT_SOURCES), settings);
-
- /* Pick up initial values. */
-
- handle_preference_init_enum ();
- handle_preference_init_bool ();
- handle_preference_init_string ();
- handle_preference_init_string_array ();
- handle_preference_init_int ();
- handle_preference_init_uint ();
-
- init_bindings ();
-}
-
-static gboolean
-find_pref (void *prefs,
- size_t pref_size,
- const char *search_key,
- MetaBasePreference **pref)
-{
- void *p = prefs;
-
- while (TRUE)
- {
- char **key = p;
- if (*key == NULL)
- break;
-
- if (strcmp (*key, search_key) == 0)
- {
- *pref = p;
- return TRUE;
- }
-
- p = (guchar *)p + pref_size;
- }
-
- return FALSE;
-}
-
-
-/****************************************************************************/
-/* Updates. */
-/****************************************************************************/
-
-
-static void
-settings_changed (GSettings *settings,
- gchar *key,
- gpointer data)
-{
- GVariant *value;
- const GVariantType *type;
- MetaEnumPreference *cursor;
- gboolean found_enum;
-
- value = g_settings_get_value (settings, key);
- type = g_variant_get_type (value);
-
- if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
- handle_preference_update_bool (settings, key);
- else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
- handle_preference_update_int (settings, key);
- else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
- handle_preference_update_uint (settings, key);
- else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING_ARRAY))
- handle_preference_update_string_array (settings, key);
- else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
- {
- cursor = preferences_enum;
- found_enum = FALSE;
-
- while (cursor->base.key != NULL)
- {
-
- if (strcmp (key, cursor->base.key) == 0)
- found_enum = TRUE;
-
- cursor++;
- }
-
- if (found_enum)
- handle_preference_update_enum (settings, key);
- else
- handle_preference_update_string (settings, key);
- }
- else
- {
- /* Unknown preference type. This quite likely simply isn't
- * a preference we track changes to. */
- }
-
- g_variant_unref (value);
-}
-
-static void
-bindings_changed (GSettings *settings,
- gchar *key,
- gpointer data)
-{
- gchar **strokes;
- strokes = g_settings_get_strv (settings, key);
-
- if (update_key_binding (key, strokes))
- queue_changed (META_PREF_KEYBINDINGS);
-
- g_strfreev (strokes);
-}
-
-/**
- * maybe_give_disable_workaround_warning:
- *
- * Special case: give a warning the first time disable_workarounds
- * is turned on.
- */
-static void
-maybe_give_disable_workarounds_warning (void)
-{
- static gboolean first_disable = TRUE;
-
- if (first_disable && disable_workarounds)
- {
- first_disable = FALSE;
-
- meta_warning ("Workarounds for broken applications disabled. "
- "Some applications may not behave properly.");
- }
-}
-
-MetaVirtualModifier
-meta_prefs_get_mouse_button_mods (void)
-{
- return mouse_button_mods;
-}
-
-GDesktopFocusMode
-meta_prefs_get_focus_mode (void)
-{
- return focus_mode;
-}
-
-GDesktopFocusNewWindows
-meta_prefs_get_focus_new_windows (void)
-{
- return focus_new_windows;
-}
-
-gboolean
-meta_prefs_get_center_new_windows (void)
-{
- return center_new_windows;
-}
-
-gboolean
-meta_prefs_get_attach_modal_dialogs (void)
-{
- return attach_modal_dialogs;
-}
-
-gboolean
-meta_prefs_get_raise_on_click (void)
-{
- return raise_on_click;
-}
-
-gboolean
-meta_prefs_get_show_fallback_app_menu (void)
-{
- return show_fallback_app_menu;
-}
-
-void
-meta_prefs_set_show_fallback_app_menu (gboolean whether)
-{
- gboolean changed = FALSE;
-
- changed = (show_fallback_app_menu == !whether);
-
- show_fallback_app_menu = whether;
-
- if (changed)
- queue_changed (META_PREF_BUTTON_LAYOUT);
-}
-
-const char*
-meta_prefs_get_cursor_theme (void)
-{
- return cursor_theme;
-}
-
-int
-meta_prefs_get_cursor_size (void)
-{
- return cursor_size;
-}
-
-
-/****************************************************************************/
-/* Handlers for string preferences. */
-/****************************************************************************/
-
-static gboolean
-titlebar_handler (GVariant *value,
- gpointer *result,
- gpointer data)
-{
- PangoFontDescription *desc;
- const gchar *string_value;
-
- *result = NULL; /* ignored */
- string_value = g_variant_get_string (value, NULL);
- desc = pango_font_description_from_string (string_value);
-
- if (desc == NULL)
- {
- meta_warning ("Could not parse font description "
- "\"%s\" from GSettings key %s",
- string_value ? string_value : "(null)",
- KEY_TITLEBAR_FONT);
- return FALSE;
- }
-
- /* Is the new description the same as the old? */
- if (titlebar_font &&
- pango_font_description_equal (desc, titlebar_font))
- {
- pango_font_description_free (desc);
- }
- else
- {
- if (titlebar_font)
- pango_font_description_free (titlebar_font);
-
- titlebar_font = desc;
- queue_changed (META_PREF_TITLEBAR_FONT);
- }
-
- return TRUE;
-}
-
-static gboolean
-mouse_button_mods_handler (GVariant *value,
- gpointer *result,
- gpointer data)
-{
- MetaVirtualModifier mods;
- const gchar *string_value;
-
- *result = NULL; /* ignored */
- string_value = g_variant_get_string (value, NULL);
-
- if (!string_value || !meta_parse_modifier (string_value, &mods))
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Failed to parse new GSettings value");
-
- meta_warning ("\"%s\" found in configuration database is "
- "not a valid value for mouse button modifier",
- string_value);
-
- return FALSE;
- }
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Mouse button modifier has new GSettings value \"%s\"",
- string_value);
-
- if (mods != mouse_button_mods)
- {
- mouse_button_mods = mods;
- queue_changed (META_PREF_MOUSE_BUTTON_MODS);
- }
-
- return TRUE;
-}
-
-static gboolean
-button_layout_equal (const MetaButtonLayout *a,
- const MetaButtonLayout *b)
-{
- int i;
-
- i = 0;
- while (i < MAX_BUTTONS_PER_CORNER)
- {
- if (a->left_buttons[i] != b->left_buttons[i])
- return FALSE;
- if (a->right_buttons[i] != b->right_buttons[i])
- return FALSE;
- if (a->left_buttons_has_spacer[i] != b->left_buttons_has_spacer[i])
- return FALSE;
- if (a->right_buttons_has_spacer[i] != b->right_buttons_has_spacer[i])
- return FALSE;
- ++i;
- }
-
- return TRUE;
-}
-
-/*
- * This conversion cannot be handled by GSettings since
- * several values are stored in the same key (as a string).
- */
-static MetaButtonFunction
-button_function_from_string (const char *str)
-{
- if (strcmp (str, "menu") == 0)
- return META_BUTTON_FUNCTION_MENU;
- else if (strcmp (str, "minimize") == 0)
- return META_BUTTON_FUNCTION_MINIMIZE;
- else if (strcmp (str, "maximize") == 0)
- return META_BUTTON_FUNCTION_MAXIMIZE;
- else if (strcmp (str, "close") == 0)
- return META_BUTTON_FUNCTION_CLOSE;
- else
- /* don't know; give up */
- return META_BUTTON_FUNCTION_LAST;
-}
-
-static gboolean
-button_layout_handler (GVariant *value,
- gpointer *result,
- gpointer data)
-{
- MetaButtonLayout new_layout;
- const gchar *string_value;
- char **sides = NULL;
- int i;
-
- /* We need to ignore unknown button functions, for
- * compat with future versions
- */
-
- *result = NULL; /* ignored */
- string_value = g_variant_get_string (value, NULL);
-
- if (string_value)
- sides = g_strsplit (string_value, ":", 2);
-
- i = 0;
- if (sides != NULL && sides[0] != NULL)
- {
- char **buttons;
- int b;
- gboolean used[META_BUTTON_FUNCTION_LAST];
-
- while (i < META_BUTTON_FUNCTION_LAST)
- {
- used[i] = FALSE;
- new_layout.left_buttons_has_spacer[i] = FALSE;
- ++i;
- }
-
- buttons = g_strsplit (sides[0], ",", -1);
- i = 0;
- b = 0;
- while (buttons[b] != NULL)
- {
- MetaButtonFunction f = button_function_from_string (buttons[b]);
- if (i > 0 && strcmp("spacer", buttons[b]) == 0)
- {
- new_layout.left_buttons_has_spacer[i-1] = TRUE;
- }
- else
- {
- if (f != META_BUTTON_FUNCTION_LAST && !used[f])
- {
- new_layout.left_buttons[i] = f;
- used[f] = TRUE;
- ++i;
- }
- else
- {
- meta_topic (META_DEBUG_PREFS,
- "Ignoring unknown or already-used button name \"%s\"",
- buttons[b]);
- }
- }
-
- ++b;
- }
-
- g_strfreev (buttons);
- }
-
- for (; i < MAX_BUTTONS_PER_CORNER; i++)
- {
- new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
- new_layout.left_buttons_has_spacer[i] = FALSE;
- }
-
- i = 0;
- if (sides != NULL && sides[0] != NULL && sides[1] != NULL)
- {
- char **buttons;
- int b;
- gboolean used[META_BUTTON_FUNCTION_LAST];
-
- while (i < META_BUTTON_FUNCTION_LAST)
- {
- used[i] = FALSE;
- new_layout.right_buttons_has_spacer[i] = FALSE;
- ++i;
- }
-
- buttons = g_strsplit (sides[1], ",", -1);
- i = 0;
- b = 0;
- while (buttons[b] != NULL)
- {
- MetaButtonFunction f = button_function_from_string (buttons[b]);
- if (i > 0 && strcmp("spacer", buttons[b]) == 0)
- {
- new_layout.right_buttons_has_spacer[i-1] = TRUE;
- }
- else
- {
- if (f != META_BUTTON_FUNCTION_LAST && !used[f])
- {
- new_layout.right_buttons[i] = f;
- used[f] = TRUE;
- ++i;
- }
- else
- {
- meta_topic (META_DEBUG_PREFS,
- "Ignoring unknown or already-used button name \"%s\"",
- buttons[b]);
- }
- }
-
- ++b;
- }
-
- g_strfreev (buttons);
- }
-
- for (; i < MAX_BUTTONS_PER_CORNER; i++)
- {
- new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
- new_layout.right_buttons_has_spacer[i] = FALSE;
- }
-
- g_strfreev (sides);
-
- /* Invert the button layout for RTL languages */
- if (meta_get_locale_direction() == META_LOCALE_DIRECTION_RTL)
- {
- MetaButtonLayout rtl_layout;
- int j;
-
- for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
- for (j = 0; j < i; j++)
- {
- rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
- if (j == 0)
- rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
- else
- rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
- }
- for (; j < MAX_BUTTONS_PER_CORNER; j++)
- {
- rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
- rtl_layout.right_buttons_has_spacer[j] = FALSE;
- }
-
- for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
- for (j = 0; j < i; j++)
- {
- rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
- if (j == 0)
- rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
- else
- rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
- }
- for (; j < MAX_BUTTONS_PER_CORNER; j++)
- {
- rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
- rtl_layout.left_buttons_has_spacer[j] = FALSE;
- }
-
- new_layout = rtl_layout;
- }
-
- if (!button_layout_equal (&button_layout, &new_layout))
- {
- button_layout = new_layout;
- emit_changed (META_PREF_BUTTON_LAYOUT);
- }
-
- return TRUE;
-}
-
-static gboolean
-overlay_key_handler (GVariant *value,
- gpointer *result,
- gpointer data)
-{
- MetaKeyCombo combo;
- const gchar *string_value;
-
- *result = NULL; /* ignored */
- string_value = g_variant_get_string (value, NULL);
-
- if (string_value && meta_parse_accelerator (string_value, &combo))
- ;
- else
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Failed to parse value for overlay-key");
- return FALSE;
- }
-
- combo.modifiers = 0;
-
- if (overlay_key_combo.keysym != combo.keysym ||
- overlay_key_combo.keycode != combo.keycode)
- {
- overlay_key_combo = combo;
- queue_changed (META_PREF_KEYBINDINGS);
- }
-
- return TRUE;
-}
-
-static gboolean
-locate_pointer_key_handler (GVariant *value,
- gpointer *result,
- gpointer data)
-{
- MetaKeyCombo combo;
- const gchar *string_value;
-
- *result = NULL; /* ignored */
- string_value = g_variant_get_string (value, NULL);
-
- if (!string_value || !meta_parse_accelerator (string_value, &combo))
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Failed to parse value for locate-pointer-key");
- return FALSE;
- }
-
- combo.modifiers = 0;
-
- if (locate_pointer_key_combo.keysym != combo.keysym ||
- locate_pointer_key_combo.keycode != combo.keycode)
- {
- locate_pointer_key_combo = combo;
- queue_changed (META_PREF_KEYBINDINGS);
- }
-
- return TRUE;
-}
-
-static gboolean
-iso_next_group_handler (GVariant *value,
- gpointer *result,
- gpointer data)
-{
- const char **xkb_options, **p;
- const char *option = NULL;
- gboolean changed = FALSE;
-
- *result = NULL; /* ignored */
- xkb_options = g_variant_get_strv (value, NULL);
-
- for (p = xkb_options; p && *p; ++p)
- if (g_str_has_prefix (*p, "grp:"))
- {
- option = (*p + 4);
- break;
- }
-
- changed = (g_strcmp0 (option, iso_next_group_option) != 0);
-
- if (changed)
- {
- g_free (iso_next_group_option);
- iso_next_group_option = g_strdup (option);
- queue_changed (META_PREF_KEYBINDINGS);
- }
-
- g_free (xkb_options);
-
- return TRUE;
-}
-
-const PangoFontDescription*
-meta_prefs_get_titlebar_font (void)
-{
- if (use_system_font)
- return NULL;
- else
- return titlebar_font;
-}
-
-int
-meta_prefs_get_num_workspaces (void)
-{
- return num_workspaces;
-}
-
-gboolean
-meta_prefs_get_dynamic_workspaces (void)
-{
- return dynamic_workspaces;
-}
-
-gboolean
-meta_prefs_get_disable_workarounds (void)
-{
- return disable_workarounds;
-}
-
-#ifdef WITH_VERBOSE_MODE
-const char*
-meta_preference_to_string (MetaPreference pref)
-{
- /* TODO: better handled via GLib enum nicknames */
- switch (pref)
- {
- case META_PREF_MOUSE_BUTTON_MODS:
- return "MOUSE_BUTTON_MODS";
-
- case META_PREF_FOCUS_MODE:
- return "FOCUS_MODE";
-
- case META_PREF_FOCUS_NEW_WINDOWS:
- return "FOCUS_NEW_WINDOWS";
-
- case META_PREF_CENTER_NEW_WINDOWS:
- return "CENTER_NEW_WINDOWS";
-
- case META_PREF_ATTACH_MODAL_DIALOGS:
- return "ATTACH_MODAL_DIALOGS";
-
- case META_PREF_RAISE_ON_CLICK:
- return "RAISE_ON_CLICK";
-
- case META_PREF_TITLEBAR_FONT:
- return "TITLEBAR_FONT";
-
- case META_PREF_NUM_WORKSPACES:
- return "NUM_WORKSPACES";
-
- case META_PREF_KEYBINDINGS:
- return "KEYBINDINGS";
-
- case META_PREF_DISABLE_WORKAROUNDS:
- return "DISABLE_WORKAROUNDS";
-
- case META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR:
- return "ACTION_DOUBLE_CLICK_TITLEBAR";
-
- case META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR:
- return "ACTION_MIDDLE_CLICK_TITLEBAR";
-
- case META_PREF_ACTION_RIGHT_CLICK_TITLEBAR:
- return "ACTION_RIGHT_CLICK_TITLEBAR";
-
- case META_PREF_AUTO_RAISE:
- return "AUTO_RAISE";
-
- case META_PREF_AUTO_RAISE_DELAY:
- return "AUTO_RAISE_DELAY";
-
- case META_PREF_FOCUS_CHANGE_ON_POINTER_REST:
- return "FOCUS_CHANGE_ON_POINTER_REST";
-
- case META_PREF_BUTTON_LAYOUT:
- return "BUTTON_LAYOUT";
-
- case META_PREF_WORKSPACE_NAMES:
- return "WORKSPACE_NAMES";
-
- case META_PREF_VISUAL_BELL:
- return "VISUAL_BELL";
-
- case META_PREF_AUDIBLE_BELL:
- return "AUDIBLE_BELL";
-
- case META_PREF_VISUAL_BELL_TYPE:
- return "VISUAL_BELL_TYPE";
-
- case META_PREF_GNOME_ACCESSIBILITY:
- return "GNOME_ACCESSIBILTY";
-
- case META_PREF_GNOME_ANIMATIONS:
- return "GNOME_ANIMATIONS";
-
- case META_PREF_CURSOR_THEME:
- return "CURSOR_THEME";
-
- case META_PREF_CURSOR_SIZE:
- return "CURSOR_SIZE";
-
- case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
- return "RESIZE_WITH_RIGHT_BUTTON";
-
- case META_PREF_EDGE_TILING:
- return "EDGE_TILING";
-
- case META_PREF_FORCE_FULLSCREEN:
- return "FORCE_FULLSCREEN";
-
- case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
- return "WORKSPACES_ONLY_ON_PRIMARY";
-
- case META_PREF_DRAGGABLE_BORDER_WIDTH:
- return "DRAGGABLE_BORDER_WIDTH";
-
- case META_PREF_DRAG_THRESHOLD:
- return "DRAG_THRESHOLD";
-
- case META_PREF_DYNAMIC_WORKSPACES:
- return "DYNAMIC_WORKSPACES";
-
- case META_PREF_AUTO_MAXIMIZE:
- return "AUTO_MAXIMIZE";
-
- case META_PREF_LOCATE_POINTER:
- return "LOCATE_POINTER";
-
- case META_PREF_CHECK_ALIVE_TIMEOUT:
- return "CHECK_ALIVE_TIMEOUT";
- }
-
- return "(unknown)";
-}
-#endif /* WITH_VERBOSE_MODE */
-
-void
-meta_prefs_set_num_workspaces (int n_workspaces)
-{
- MetaBasePreference *pref;
-
- if (find_pref (preferences_int, sizeof(MetaIntPreference),
- KEY_NUM_WORKSPACES, &pref))
- {
- g_settings_set_int (SETTINGS (pref->schema),
- KEY_NUM_WORKSPACES,
- n_workspaces);
- }
-}
-
-static GHashTable *key_bindings;
-
-static void
-meta_key_pref_free (MetaKeyPref *pref)
-{
- update_binding (pref, NULL);
-
- g_free (pref->name);
- g_object_unref (pref->settings);
-
- g_free (pref);
-}
-
-
-static void
-init_bindings (void)
-{
- MetaKeyPref *pref;
-
- key_bindings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- (GDestroyNotify)meta_key_pref_free);
-
- pref = g_new0 (MetaKeyPref, 1);
- pref->name = g_strdup ("overlay-key");
- pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
- pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
- pref->builtin = 1;
-
- g_hash_table_insert (key_bindings, g_strdup (pref->name), pref);
-
- pref = g_new0 (MetaKeyPref, 1);
- pref->name = g_strdup ("locate-pointer-key");
- pref->action = META_KEYBINDING_ACTION_LOCATE_POINTER_KEY;
- pref->combos = g_slist_prepend (pref->combos, &locate_pointer_key_combo);
- pref->builtin = 1;
-
- g_hash_table_insert (key_bindings, g_strdup (pref->name), pref);
-}
-
-static gboolean
-update_binding (MetaKeyPref *binding,
- gchar **strokes)
-{
- GSList *old_combos, *a, *b;
- gboolean changed;
- int i;
-
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Binding \"%s\" has new GSettings value",
- binding->name);
-
- old_combos = binding->combos;
- binding->combos = NULL;
-
- for (i = 0; strokes && strokes[i]; i++)
- {
- MetaKeyCombo *combo;
-
- combo = g_malloc0 (sizeof (MetaKeyCombo));
-
- if (!meta_parse_accelerator (strokes[i], combo))
- {
- meta_topic (META_DEBUG_KEYBINDINGS,
- "Failed to parse new GSettings value");
- meta_warning ("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"",
- strokes[i], binding->name);
-
- g_free (combo);
-
- /* Value is kept and will thus be removed next time we save the key.
- * Changing the key in response to a modification could lead to cyclic calls. */
- continue;
- }
-
- binding->combos = g_slist_prepend (binding->combos, combo);
- }
-
- binding->combos = g_slist_reverse (binding->combos);
-
- a = old_combos;
- b = binding->combos;
- while (TRUE)
- {
- if ((!a && b) || (a && !b))
- {
- changed = TRUE;
- break;
- }
- else if (!a && !b)
- {
- changed = FALSE;
- break;
- }
- else if (memcmp (a->data, b->data, sizeof (MetaKeyCombo)) != 0)
- {
- changed = TRUE;
- break;
- }
- else
- {
- a = a->next;
- b = b->next;
- }
- }
-
- g_slist_free_full (old_combos, g_free);
-
- return changed;
-}
-
-static gboolean
-update_key_binding (const char *key,
- gchar **strokes)
-{
- MetaKeyPref *pref = g_hash_table_lookup (key_bindings, key);
-
- if (pref)
- return update_binding (pref, strokes);
- else
- return FALSE;
-}
-
-const char*
-meta_prefs_get_workspace_name (int i)
-{
- const char *name;
-
- if (!workspace_names ||
- g_strv_length (workspace_names) < (guint)i + 1 ||
- !*workspace_names[i])
- {
- char *generated_name = g_strdup_printf (_("Workspace %d"), i + 1);
- name = g_intern_string (generated_name);
- g_free (generated_name);
- }
- else
- name = workspace_names[i];
-
- meta_topic (META_DEBUG_PREFS,
- "Getting name of workspace %d: \"%s\"", i, name);
-
- return name;
-}
-
-void
-meta_prefs_change_workspace_name (int num,
- const char *name)
-{
- GVariantBuilder builder;
- int n_workspace_names, i;
-
- g_return_if_fail (num >= 0);
-
- meta_topic (META_DEBUG_PREFS,
- "Changing name of workspace %d to %s",
- num, name ? name : "none");
-
- /* NULL and empty string both mean "default" here,
- * and we also need to match the name against its default value
- * to avoid saving it literally. */
- if (g_strcmp0 (name, meta_prefs_get_workspace_name (num)) == 0)
- {
- if (!name || !*name)
- meta_topic (META_DEBUG_PREFS,
- "Workspace %d already uses default name", num);
- else
- meta_topic (META_DEBUG_PREFS,
- "Workspace %d already has name %s", num, name);
- return;
- }
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
- n_workspace_names = workspace_names ? g_strv_length (workspace_names) : 0;
-
- for (i = 0; i < MAX (num + 1, n_workspace_names); i++)
- {
- const char *value;
-
- if (i == num)
- value = name ? name : "";
- else if (i < n_workspace_names)
- value = workspace_names[i] ? workspace_names[i] : "";
- else
- value = "";
-
- g_variant_builder_add (&builder, "s", value);
- }
-
- g_settings_set_value (SETTINGS (SCHEMA_GENERAL), KEY_WORKSPACE_NAMES,
- g_variant_builder_end (&builder));
-}
-
-/**
- * meta_prefs_get_button_layout:
- * @button_layout: (out):
- */
-void
-meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p)
-{
- *button_layout_p = button_layout;
-}
-
-gboolean
-meta_prefs_get_visual_bell (void)
-{
- return bell_is_visible;
-}
-
-gboolean
-meta_prefs_bell_is_audible (void)
-{
- return bell_is_audible;
-}
-
-GDesktopVisualBellType
-meta_prefs_get_visual_bell_type (void)
-{
- return visual_bell_type;
-}
-
-gboolean
-meta_prefs_add_keybinding (const char *name,
- GSettings *settings,
- MetaKeyBindingAction action,
- MetaKeyBindingFlags flags)
-{
- MetaKeyPref *pref;
- char **strokes;
- guint id;
-
- if (g_hash_table_lookup (key_bindings, name))
- {
- meta_warning ("Trying to re-add keybinding \"%s\".", name);
- return FALSE;
- }
-
- pref = g_new0 (MetaKeyPref, 1);
- pref->name = g_strdup (name);
- pref->settings = g_object_ref (settings);
- pref->action = action;
- pref->combos = NULL;
- pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
-
- if (pref->builtin)
- {
- if (g_object_get_data (G_OBJECT (settings), "changed-signal") == NULL)
- {
- id = g_signal_connect (settings, "changed",
- G_CALLBACK (bindings_changed), NULL);
- g_object_set_data (G_OBJECT (settings), "changed-signal", GUINT_TO_POINTER (id));
- }
- }
- else
- {
- char *changed_signal = g_strdup_printf ("changed::%s", name);
- id = g_signal_connect (settings, changed_signal,
- G_CALLBACK (bindings_changed), NULL);
- g_free (changed_signal);
-
- g_object_set_data (G_OBJECT (settings), name, GUINT_TO_POINTER (id));
-
- queue_changed (META_PREF_KEYBINDINGS);
- }
-
- strokes = g_settings_get_strv (settings, name);
- update_binding (pref, strokes);
- g_strfreev (strokes);
-
- g_hash_table_insert (key_bindings, g_strdup (name), pref);
-
- return TRUE;
-}
-
-gboolean
-meta_prefs_remove_keybinding (const char *name)
-{
- MetaKeyPref *pref;
- gulong id;
-
- pref = g_hash_table_lookup (key_bindings, name);
- if (!pref)
- {
- meta_warning ("Trying to remove non-existent keybinding \"%s\".", name);
- return FALSE;
- }
-
- if (pref->builtin)
- {
- meta_warning ("Trying to remove builtin keybinding \"%s\".", name);
- return FALSE;
- }
-
- id = GPOINTER_TO_UINT (g_object_steal_data (G_OBJECT (pref->settings), name));
- g_clear_signal_handler (&id, pref->settings);
-
- g_hash_table_remove (key_bindings, name);
-
- queue_changed (META_PREF_KEYBINDINGS);
-
- return TRUE;
-}
-
-GList *
-meta_prefs_get_keybindings (void)
-{
- return g_hash_table_get_values (key_bindings);
-}
-
-void
-meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
-{
- *combo = overlay_key_combo;
-}
-
-void
-meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo)
-{
- *combo = locate_pointer_key_combo;
-}
-
-gboolean
-meta_prefs_is_locate_pointer_enabled (void)
-{
- return locate_pointer_is_enabled;
-}
-
-unsigned int
-meta_prefs_get_check_alive_timeout (void)
-{
- return check_alive_timeout;
-}
-
-const char *
-meta_prefs_get_iso_next_group_option (void)
-{
- return iso_next_group_option;
-}
-
-GDesktopTitlebarAction
-meta_prefs_get_action_double_click_titlebar (void)
-{
- return action_double_click_titlebar;
-}
-
-GDesktopTitlebarAction
-meta_prefs_get_action_middle_click_titlebar (void)
-{
- return action_middle_click_titlebar;
-}
-
-GDesktopTitlebarAction
-meta_prefs_get_action_right_click_titlebar (void)
-{
- return action_right_click_titlebar;
-}
-
-gboolean
-meta_prefs_get_auto_raise (void)
-{
- return auto_raise;
-}
-
-int
-meta_prefs_get_auto_raise_delay (void)
-{
- return auto_raise_delay;
-}
-
-gboolean
-meta_prefs_get_focus_change_on_pointer_rest (void)
-{
- return focus_change_on_pointer_rest;
-}
-
-gboolean
-meta_prefs_get_gnome_accessibility (void)
-{
- return gnome_accessibility;
-}
-
-gboolean
-meta_prefs_get_gnome_animations (void)
-{
- return gnome_animations;
-}
-
-gboolean
-meta_prefs_get_edge_tiling (void)
-{
- return edge_tiling;
-}
-
-gboolean
-meta_prefs_get_auto_maximize (void)
-{
- return auto_maximize;
-}
-
-MetaKeyBindingAction
-meta_prefs_get_keybinding_action (const char *name)
-{
- MetaKeyPref *pref = g_hash_table_lookup (key_bindings, name);
-
- return pref ? pref->action
- : META_KEYBINDING_ACTION_NONE;
-}
-
-gint
-meta_prefs_get_mouse_button_resize (void)
-{
- return resize_with_right_button ? 3: 2;
-}
-
-gint
-meta_prefs_get_mouse_button_menu (void)
-{
- return resize_with_right_button ? 2: 3;
-}
-
-gboolean
-meta_prefs_get_force_fullscreen (void)
-{
- return force_fullscreen;
-}
-
-gboolean
-meta_prefs_get_workspaces_only_on_primary (void)
-{
- return workspaces_only_on_primary;
-}
-
-int
-meta_prefs_get_draggable_border_width (void)
-{
- return draggable_border_width;
-}
-
-int
-meta_prefs_get_drag_threshold (void)
-{
- return drag_threshold;
-}
-
-void
-meta_prefs_set_force_fullscreen (gboolean whether)
-{
- force_fullscreen = whether;
-}
diff --git a/src/core/restart-helper.c b/src/core/restart-helper.c
deleted file mode 100644
index 68ede2671..000000000
--- a/src/core/restart-helper.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * SECTION:restart-helper
- * @short_description: helper program during a restart
- *
- * To smoothly restart Mutter, we want to keep the composite
- * overlay window enabled during the restart. This is done by
- * spawning this program, which keeps a reference to the the composite
- * overlay window until Mutter picks it back up.
- */
-
-/*
- * Copyright (C) 2014 Red Hat, Inc.
- *
- * 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/>.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xcomposite.h>
-
-int
-main (int argc,
- char **argv)
-{
- Display *display = XOpenDisplay (NULL);
- Window selection_window;
- XSetWindowAttributes xwa;
- unsigned long mask = 0;
-
- xwa.override_redirect = True;
- mask |= CWOverrideRedirect;
-
-
- XCompositeGetOverlayWindow (display, DefaultRootWindow (display));
-
- selection_window = XCreateWindow (display,
- DefaultRootWindow (display),
- -100, -100, 1, 1, 0,
- 0,
- InputOnly,
- DefaultVisual (display, DefaultScreen (display)),
- mask, &xwa);
-
- XSetSelectionOwner (display,
- XInternAtom (display, "_MUTTER_RESTART_HELPER", False),
- selection_window,
- CurrentTime);
-
- /* Mutter looks for an (arbitrary) line printed to stdout to know that
- * we have started and have a reference to the COW. XSync() so that
- * everything is set on the X server before Mutter starts restarting.
- */
- XSync (display, False);
-
- printf ("STARTED\n");
- fflush (stdout);
-
- while (True)
- {
- XEvent xev;
-
- XNextEvent (display, &xev);
- /* Mutter restarted and unset the selection to indicate that
- * it has a reference on the COW again */
- if (xev.xany.type == SelectionClear)
- return 0;
- }
-}
diff --git a/src/core/restart.c b/src/core/restart.c
deleted file mode 100644
index e9a5bfd27..000000000
--- a/src/core/restart.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2014 Red Hat, Inc.
- *
- * 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:restart
- * @short_description: Smoothly restart the compositor
- *
- * There are some cases where we need to restart Mutter in order
- * to deal with changes in state - the particular case inspiring
- * this is enabling or disabling stereo output. To make this
- * fairly smooth for the user, we need to do two things:
- *
- * - Display a message to the user and make sure that it is
- * actually painted before we exit.
- * - Use a helper program so that the Composite Overlay Window
- * isn't unmapped and mapped.
- *
- * This handles both of these.
- */
-
-#include "config.h"
-
-#include <gio/gunixinputstream.h>
-
-#include "clutter/clutter.h"
-#include "core/display-private.h"
-#include "core/util-private.h"
-#include "meta/main.h"
-#include "ui/ui.h"
-#include "x11/meta-x11-display-private.h"
-
-static gboolean restart_helper_started = FALSE;
-static gboolean restart_message_shown = FALSE;
-static gboolean is_restart = FALSE;
-
-void
-meta_set_is_restart (gboolean whether)
-{
- is_restart = whether;
-}
-
-static void
-restart_check_ready (void)
-{
- if (restart_helper_started && restart_message_shown)
- {
- MetaDisplay *display = meta_get_display ();
-
- if (!meta_display_request_restart (display))
- meta_display_show_restart_message (display, NULL);
- }
-}
-
-static void
-restart_helper_read_line_callback (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- GError *error = NULL;
- gsize length;
- char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object),
- res,
- &length, &error);
- if (line == NULL)
- {
- meta_warning ("Failed to read output from restart helper%s%s",
- error ? ": " : NULL,
- error ? error->message : NULL);
- }
- else
- g_free (line); /* We don't actually care what the restart helper outputs */
-
- g_object_unref (source_object);
-
- restart_helper_started = TRUE;
- restart_check_ready ();
-}
-
-static gboolean
-restart_message_painted (gpointer data)
-{
- restart_message_shown = TRUE;
- restart_check_ready ();
-
- return FALSE;
-}
-
-/**
- * meta_restart:
- * @message: (allow-none): message to display to the user, or %NULL
- *
- * Starts the process of restarting the compositor. Note that Mutter's
- * involvement here is to make the restart visually smooth for the
- * user - it cannot itself safely reexec a program that embeds libmuttter.
- * So in order for this to work, the compositor must handle two
- * signals - MetaDisplay::show-restart-message, to display the
- * message passed here on the Clutter stage, and ::restart to actually
- * reexec the compositor.
- */
-void
-meta_restart (const char *message)
-{
- MetaDisplay *display = meta_get_display();
- GInputStream *unix_stream;
- GDataInputStream *data_stream;
- GError *error = NULL;
- int helper_out_fd;
-
- static const char * const helper_argv[] = {
- MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL
- };
-
- if (message && meta_display_show_restart_message (display, message))
- {
- /* Wait until the stage was painted */
- clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
- restart_message_painted,
- NULL, NULL);
- }
- else
- {
- /* Can't show the message, show the message as soon as the
- * restart helper starts
- */
- restart_message_painted (NULL);
- }
-
- /* We also need to wait for the restart helper to get its
- * reference to the Composite Overlay Window.
- */
- if (!g_spawn_async_with_pipes (NULL, /* working directory */
- (char **)helper_argv,
- NULL, /* envp */
- G_SPAWN_DEFAULT,
- NULL, NULL, /* child_setup */
- NULL, /* child_pid */
- NULL, /* standard_input */
- &helper_out_fd,
- NULL, /* standard_error */
- &error))
- {
- meta_warning ("Failed to start restart helper: %s", error->message);
- goto error;
- }
-
- unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE);
- data_stream = g_data_input_stream_new (unix_stream);
- g_object_unref (unix_stream);
-
- g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
- NULL, restart_helper_read_line_callback,
- &error);
- if (error != NULL)
- {
- meta_warning ("Failed to read from restart helper: %s", error->message);
- g_object_unref (data_stream);
- goto error;
- }
-
- return;
-
- error:
- /* If starting the restart helper fails, then we just go ahead and restart
- * immediately. We won't get a smooth transition, since the overlay window
- * will be destroyed and recreated, but otherwise it will work fine.
- */
- restart_helper_started = TRUE;
- restart_check_ready ();
-
- return;
-}
-
-/**
- * meta_is_restart:
- *
- * Returns %TRUE if this instance of Mutter comes from Mutter
- * restarting itself (for example to enable/disable stereo.)
- * See meta_restart(). If this is the case, any startup visuals
- * or animations should be suppressed.
- */
-gboolean
-meta_is_restart (void)
-{
- return is_restart;
-}
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
deleted file mode 100644
index fbfef6465..000000000
--- a/src/core/stack-tracker.c
+++ /dev/null
@@ -1,1293 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * SECTION:stack-tracker
- * @short_description: Track stacking order for compositor
- *
- * #MetaStackTracker maintains the most accurate view we have at a
- * given point of time of the ordering of the children of the root
- * window (including override-redirect windows.) This is used to order
- * the windows when the compositor draws them.
- *
- * By contrast, #MetaStack is responsible for keeping track of how we
- * think that windows *should* be ordered. For windows we manage
- * (non-override-redirect windows), the two stacking orders will be
- * the same.
- */
-
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * 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/>.
- */
-
-#include "config.h"
-
-#include "core/stack-tracker.h"
-
-#include <string.h>
-
-#include "core/display-private.h"
-#include "core/frame.h"
-#include "meta/compositor.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/util.h"
-#include "x11/meta-x11-display-private.h"
-
-/* The complexity here comes from resolving two competing factors:
- *
- * - We need to have a view of the stacking order that takes into
- * account everything we have done without waiting for events
- * back from the X server; we don't want to draw intermediate
- * partially-stacked stack states just because we haven't received
- * some notification yet.
- *
- * - Only the X server has an accurate view of the complete stacking;
- * when we make a request to restack windows, we don't know how
- * it will affect override-redirect windows, because at any point
- * applications may restack these windows without our involvement.
- *
- * The technique we use is that we keep three sets of information:
- *
- * - The stacking order on the server as known from the last
- * event we received.
- * - A queue of stacking requests that *we* made subsequent to
- * that last event.
- * - A predicted stacking order, derived from applying the queued
- * requests to the last state from the server.
- *
- * When we receive a new event: a) we compare the serial in the event to
- * the serial of the queued requests and remove any that are now
- * no longer pending b) if necessary, drop the predicted stacking
- * order to recompute it at the next opportunity.
- *
- * Possible optimizations:
- * Keep the stacks as an array + reverse-mapping hash table to avoid
- * linear lookups.
- * Keep the stacks as a GList + reverse-mapping hash table to avoid
- * linear lookups and to make restacking constant-time.
- */
-
-typedef union _MetaStackOp MetaStackOp;
-
-typedef enum
-{
- STACK_OP_ADD,
- STACK_OP_REMOVE,
- STACK_OP_RAISE_ABOVE,
- STACK_OP_LOWER_BELOW
-} MetaStackOpType;
-
-typedef enum
-{
- APPLY_DEFAULT = 0,
- /* Only do restacking that we can do locally without changing
- * the order of X windows. After we've received any stack
- * events from the X server, we apply the locally cached
- * ops in this mode to handle the non-X parts */
- NO_RESTACK_X_WINDOWS = 1 << 0,
- /* If the stacking operation wouldn't change the order of X
- * windows, ignore it. We use this when applying events received
- * from X so that a spontaneous ConfigureNotify (for a move, say)
- * doesn't change the stacking of X windows with respect to
- * Wayland windows. */
- IGNORE_NOOP_X_RESTACK = 1 << 1
-} ApplyFlags;
-
-/* MetaStackOp represents a "stacking operation" - a change to
- * apply to a window stack. Depending on the context, it could
- * either reflect a request we have sent to the server, or a
- * notification event we received from the X server.
- */
-union _MetaStackOp
-{
- struct {
- MetaStackOpType type;
- gulong serial;
- guint64 window;
- } any;
- struct {
- MetaStackOpType type;
- gulong serial;
- guint64 window;
- } add;
- struct {
- MetaStackOpType type;
- gulong serial;
- guint64 window;
- } remove;
- struct {
- MetaStackOpType type;
- gulong serial;
- guint64 window;
- guint64 sibling;
- } raise_above;
- struct {
- MetaStackOpType type;
- gulong serial;
- guint64 window;
- guint64 sibling;
- } lower_below;
-};
-
-struct _MetaStackTracker
-{
- MetaDisplay *display;
-
- /* This is the serial of the last request we made that was reflected
- * in xserver_stack
- */
- gulong xserver_serial;
-
- /* A combined stack containing X and Wayland windows but without
- * any unverified operations applied. */
- GArray *verified_stack;
-
- /* This is a queue of requests we've made to change the stacking order,
- * where we haven't yet gotten a reply back from the server.
- */
- GQueue *unverified_predictions;
-
- /* This is how we think the stack is, based on verified_stack, and
- * on the unverified_predictions we've made subsequent to
- * verified_stack.
- */
- GArray *predicted_stack;
-
- /* Idle function used to sync the compositor's view of the window
- * stack up with our best guess before a frame is drawn.
- */
- guint sync_stack_later;
-};
-
-static void
-meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker);
-
-static inline const char *
-get_window_desc (MetaStackTracker *tracker,
- guint64 window)
-{
- return meta_display_describe_stack_id (tracker->display, window);
-}
-
-static void
-meta_stack_op_dump (MetaStackTracker *tracker,
- MetaStackOp *op,
- const char *prefix,
- const char *suffix)
-{
-#ifdef WITH_VERBOSE_MODE
- const char *window_desc = get_window_desc (tracker, op->any.window);
-#endif
-
- switch (op->any.type)
- {
- case STACK_OP_ADD:
- meta_topic (META_DEBUG_STACK, "%sADD(%s; %ld)%s",
- prefix, window_desc, op->any.serial, suffix);
- break;
- case STACK_OP_REMOVE:
- meta_topic (META_DEBUG_STACK, "%sREMOVE(%s; %ld)%s",
- prefix, window_desc, op->any.serial, suffix);
- break;
- case STACK_OP_RAISE_ABOVE:
- {
- meta_topic (META_DEBUG_STACK, "%sRAISE_ABOVE(%s, %s; %ld)%s",
- prefix,
- window_desc,
- get_window_desc (tracker, op->raise_above.sibling),
- op->any.serial,
- suffix);
- break;
- }
- case STACK_OP_LOWER_BELOW:
- {
- meta_topic (META_DEBUG_STACK, "%sLOWER_BELOW(%s, %s; %ld)%s",
- prefix,
- window_desc,
- get_window_desc (tracker, op->lower_below.sibling),
- op->any.serial,
- suffix);
- break;
- }
- }
-}
-
-#ifdef WITH_VERBOSE_MODE
-static void
-stack_dump (MetaStackTracker *tracker,
- GArray *stack)
-{
- guint i;
-
- meta_push_no_msg_prefix ();
- for (i = 0; i < stack->len; i++)
- {
- guint64 window = g_array_index (stack, guint64, i);
- meta_topic (META_DEBUG_STACK, " %s", get_window_desc (tracker, window));
- }
- meta_pop_no_msg_prefix ();
-}
-#endif /* WITH_VERBOSE_MODE */
-
-static void
-meta_stack_tracker_dump (MetaStackTracker *tracker)
-{
-#ifdef WITH_VERBOSE_MODE
- GList *l;
-
- meta_topic (META_DEBUG_STACK, "MetaStackTracker state");
- meta_push_no_msg_prefix ();
- meta_topic (META_DEBUG_STACK, " xserver_serial: %ld", tracker->xserver_serial);
- meta_topic (META_DEBUG_STACK, " verified_stack: ");
- stack_dump (tracker, tracker->verified_stack);
- meta_topic (META_DEBUG_STACK, " unverified_predictions: [");
- for (l = tracker->unverified_predictions->head; l; l = l->next)
- {
- MetaStackOp *op = l->data;
- meta_stack_op_dump (tracker, op, "", l->next ? ", " : "");
- }
- meta_topic (META_DEBUG_STACK, "]");
- if (tracker->predicted_stack)
- {
- meta_topic (META_DEBUG_STACK, " predicted_stack: ");
- stack_dump (tracker, tracker->predicted_stack);
- }
- meta_pop_no_msg_prefix ();
-#endif /* WITH_VERBOSE_MODE */
-}
-
-static void
-meta_stack_op_free (MetaStackOp *op)
-{
- g_free (op);
-}
-
-static int
-find_window (GArray *window_stack,
- guint64 window)
-{
- guint i;
-
- for (i = 0; i < window_stack->len; i++)
- {
- guint64 current = g_array_index (window_stack, guint64, i);
- if (current == window)
- return i;
- }
-
- return -1;
-}
-
-/* Returns TRUE if stack was changed */
-static gboolean
-move_window_above (GArray *stack,
- guint64 window,
- int old_pos,
- int above_pos,
- ApplyFlags apply_flags)
-{
- int i;
- gboolean can_restack_this_window =
- (apply_flags & NO_RESTACK_X_WINDOWS) == 0 || !META_STACK_ID_IS_X11 (window);
-
- if (old_pos < above_pos)
- {
- if ((apply_flags & IGNORE_NOOP_X_RESTACK) != 0)
- {
- gboolean found_x_window = FALSE;
- for (i = old_pos + 1; i <= above_pos; i++)
- if (META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i)))
- found_x_window = TRUE;
-
- if (!found_x_window)
- return FALSE;
- }
-
- for (i = old_pos; i < above_pos; i++)
- {
- if (!can_restack_this_window &&
- META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i + 1)))
- break;
-
- g_array_index (stack, guint64, i) =
- g_array_index (stack, guint64, i + 1);
- }
-
- g_array_index (stack, guint64, i) = window;
-
- return i != old_pos;
- }
- else if (old_pos > above_pos + 1)
- {
- if ((apply_flags & IGNORE_NOOP_X_RESTACK) != 0)
- {
- gboolean found_x_window = FALSE;
- for (i = above_pos + 1; i < old_pos; i++)
- if (META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i)))
- found_x_window = TRUE;
-
- if (!found_x_window)
- return FALSE;
- }
-
- for (i = old_pos; i > above_pos + 1; i--)
- {
- if (!can_restack_this_window &&
- META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i - 1)))
- break;
-
- g_array_index (stack, guint64, i) =
- g_array_index (stack, guint64, i - 1);
- }
-
- g_array_index (stack, guint64, i) = window;
-
- return i != old_pos;
- }
- else
- return FALSE;
-}
-
-/* Returns TRUE if stack was changed */
-static gboolean
-meta_stack_op_apply (MetaStackTracker *tracker,
- MetaStackOp *op,
- GArray *stack,
- ApplyFlags apply_flags)
-{
- switch (op->any.type)
- {
- case STACK_OP_ADD:
- {
- int old_pos;
-
- if (META_STACK_ID_IS_X11 (op->add.window) &&
- (apply_flags & NO_RESTACK_X_WINDOWS) != 0)
- return FALSE;
-
- old_pos = find_window (stack, op->add.window);
- if (old_pos >= 0)
- {
- meta_topic (META_DEBUG_STACK,
- "STACK_OP_ADD: window %s already in stack",
- get_window_desc (tracker, op->add.window));
- return FALSE;
- }
-
- g_array_append_val (stack, op->add.window);
- return TRUE;
- }
- case STACK_OP_REMOVE:
- {
- int old_pos;
-
- if (META_STACK_ID_IS_X11 (op->remove.window) &&
- (apply_flags & NO_RESTACK_X_WINDOWS) != 0)
- return FALSE;
-
- old_pos = find_window (stack, op->remove.window);
- if (old_pos < 0)
- {
- meta_topic (META_DEBUG_STACK,
- "STACK_OP_REMOVE: window %s not in stack",
- get_window_desc (tracker, op->remove.window));
- return FALSE;
- }
-
- g_array_remove_index (stack, old_pos);
- return TRUE;
- }
- case STACK_OP_RAISE_ABOVE:
- {
- int old_pos;
- int above_pos;
-
- old_pos = find_window (stack, op->raise_above.window);
- if (old_pos < 0)
- {
- meta_topic (META_DEBUG_STACK,
- "STACK_OP_RAISE_ABOVE: window %s not in stack",
- get_window_desc (tracker, op->raise_above.window));
- return FALSE;
- }
-
- if (op->raise_above.sibling)
- {
- above_pos = find_window (stack, op->raise_above.sibling);
- if (above_pos < 0)
- {
- meta_topic (META_DEBUG_STACK,
- "STACK_OP_RAISE_ABOVE: sibling window %s not in stack",
- get_window_desc (tracker, op->raise_above.sibling));
- return FALSE;
- }
- }
- else
- {
- above_pos = -1;
- }
-
- return move_window_above (stack, op->raise_above.window, old_pos, above_pos,
- apply_flags);
- }
- case STACK_OP_LOWER_BELOW:
- {
- int old_pos;
- int above_pos;
-
- old_pos = find_window (stack, op->raise_above.window);
- if (old_pos < 0)
- {
- meta_topic (META_DEBUG_STACK,
- "STACK_OP_LOWER_BELOW: window %s not in stack",
- get_window_desc (tracker, op->lower_below.window));
- return FALSE;
- }
-
- if (op->lower_below.sibling)
- {
- int below_pos;
-
- below_pos = find_window (stack, op->lower_below.sibling);
- if (below_pos < 0)
- {
- meta_topic (META_DEBUG_STACK,
- "STACK_OP_LOWER_BELOW: sibling window %s not in stack",
- get_window_desc (tracker, op->lower_below.sibling));
- return FALSE;
- }
-
- above_pos = below_pos - 1;
- }
- else
- {
- above_pos = stack->len - 1;
- }
-
- return move_window_above (stack, op->lower_below.window, old_pos, above_pos,
- apply_flags);
- }
- }
-
- g_assert_not_reached ();
- return FALSE;
-}
-
-static GArray *
-copy_stack (GArray *stack)
-{
- GArray *copy = g_array_sized_new (FALSE, FALSE, sizeof (guint64), stack->len);
-
- g_array_set_size (copy, stack->len);
-
- memcpy (copy->data, stack->data, sizeof (guint64) * stack->len);
-
- return copy;
-}
-
-static void
-query_xserver_stack (MetaDisplay *display,
- MetaStackTracker *tracker)
-{
- MetaX11Display *x11_display = display->x11_display;
- Window ignored1, ignored2;
- Window *children;
- guint n_children;
- guint i, old_len;
-
- tracker->xserver_serial = XNextRequest (x11_display->xdisplay);
-
- XQueryTree (x11_display->xdisplay,
- x11_display->xroot,
- &ignored1, &ignored2, &children, &n_children);
-
- old_len = tracker->verified_stack->len;
-
- g_array_set_size (tracker->verified_stack, old_len + n_children);
-
- for (i = 0; i < n_children; i++)
- g_array_index (tracker->verified_stack, guint64, old_len + i) = children[i];
-
- XFree (children);
-}
-
-static void
-drop_x11_windows (MetaDisplay *display,
- MetaStackTracker *tracker)
-{
- GArray *new_stack;
- GList *l;
- int i;
-
- tracker->xserver_serial = 0;
-
- new_stack = g_array_new (FALSE, FALSE, sizeof (guint64));
-
- for (i = 0; i < tracker->verified_stack->len; i++)
- {
- guint64 window = g_array_index (tracker->verified_stack, guint64, i);
-
- if (!META_STACK_ID_IS_X11 (window))
- g_array_append_val (new_stack, window);
- }
-
- g_array_unref (tracker->verified_stack);
- tracker->verified_stack = new_stack;
- l = tracker->unverified_predictions->head;
-
- while (l)
- {
- MetaStackOp *op = l->data;
- GList *next = l->next;
-
- if (META_STACK_ID_IS_X11 (op->any.window))
- g_queue_remove (tracker->unverified_predictions, op);
-
- l = next;
- }
-}
-
-MetaStackTracker *
-meta_stack_tracker_new (MetaDisplay *display)
-{
- MetaStackTracker *tracker;
-
- tracker = g_new0 (MetaStackTracker, 1);
- tracker->display = display;
-
- tracker->verified_stack = g_array_new (FALSE, FALSE, sizeof (guint64));
- tracker->unverified_predictions = g_queue_new ();
-
- g_signal_connect (display,
- "x11-display-setup",
- G_CALLBACK (query_xserver_stack),
- tracker);
- g_signal_connect (display,
- "x11-display-closing",
- G_CALLBACK (drop_x11_windows),
- tracker);
-
- meta_stack_tracker_dump (tracker);
-
- return tracker;
-}
-
-void
-meta_stack_tracker_free (MetaStackTracker *tracker)
-{
- if (tracker->sync_stack_later)
- meta_later_remove (tracker->sync_stack_later);
-
- g_array_free (tracker->verified_stack, TRUE);
- if (tracker->predicted_stack)
- g_array_free (tracker->predicted_stack, TRUE);
-
- g_queue_foreach (tracker->unverified_predictions, (GFunc)meta_stack_op_free, NULL);
- g_queue_free (tracker->unverified_predictions);
- tracker->unverified_predictions = NULL;
-
- g_signal_handlers_disconnect_by_func (tracker->display,
- (gpointer)query_xserver_stack,
- tracker);
- g_signal_handlers_disconnect_by_func (tracker->display,
- drop_x11_windows,
- tracker);
-
- g_free (tracker);
-}
-
-static void
-stack_tracker_apply_prediction (MetaStackTracker *tracker,
- MetaStackOp *op)
-{
- gboolean free_at_end = FALSE;
-
- /* If this operation doesn't involve restacking X windows then it's
- * implicitly verified. We can apply it immediately unless there
- * are outstanding X restacks that haven't yet been confirmed.
- */
- if (op->any.serial == 0 &&
- tracker->unverified_predictions->length == 0)
- {
- if (meta_stack_op_apply (tracker, op, tracker->verified_stack, APPLY_DEFAULT))
- meta_stack_tracker_queue_sync_stack (tracker);
-
- free_at_end = TRUE;
- }
- else
- {
- meta_stack_op_dump (tracker, op, "Predicting: ", "");
- g_queue_push_tail (tracker->unverified_predictions, op);
- }
-
- if (!tracker->predicted_stack ||
- meta_stack_op_apply (tracker, op, tracker->predicted_stack, APPLY_DEFAULT))
- meta_stack_tracker_queue_sync_stack (tracker);
-
- if (free_at_end)
- meta_stack_op_free (op);
-
- meta_stack_tracker_dump (tracker);
-}
-
-void
-meta_stack_tracker_record_add (MetaStackTracker *tracker,
- guint64 window,
- gulong serial)
-{
- MetaStackOp *op = g_new0 (MetaStackOp, 1);
-
- op->any.type = STACK_OP_ADD;
- op->any.serial = serial;
- op->any.window = window;
-
- stack_tracker_apply_prediction (tracker, op);
-}
-
-void
-meta_stack_tracker_record_remove (MetaStackTracker *tracker,
- guint64 window,
- gulong serial)
-{
- MetaStackOp *op = g_new0 (MetaStackOp, 1);
-
- op->any.type = STACK_OP_REMOVE;
- op->any.serial = serial;
- op->any.window = window;
-
- stack_tracker_apply_prediction (tracker, op);
-}
-
-static void
-meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
- guint64 window,
- guint64 sibling,
- gulong serial)
-{
- MetaStackOp *op = g_new0 (MetaStackOp, 1);
-
- op->any.type = STACK_OP_RAISE_ABOVE;
- op->any.serial = serial;
- op->any.window = window;
- op->raise_above.sibling = sibling;
-
- stack_tracker_apply_prediction (tracker, op);
-}
-
-static void
-meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
- guint64 window,
- guint64 sibling,
- gulong serial)
-{
- MetaStackOp *op = g_new0 (MetaStackOp, 1);
-
- op->any.type = STACK_OP_LOWER_BELOW;
- op->any.serial = serial;
- op->any.window = window;
- op->lower_below.sibling = sibling;
-
- stack_tracker_apply_prediction (tracker, op);
-}
-
-static void
-stack_tracker_event_received (MetaStackTracker *tracker,
- MetaStackOp *op)
-{
- gboolean need_sync = FALSE;
-
- /* If the event is older than our initial query, then it's
- * already included in our tree. Just ignore it. */
- if (op->any.serial < tracker->xserver_serial)
- return;
-
- meta_stack_op_dump (tracker, op, "Stack op event received: ", "");
-
- /* First we apply any operations that we have queued up that depended
- * on X operations *older* than what we received .. those operations
- * must have been ignored by the X server, so we just apply the
- * operations we have as best as possible while not moving windows.
- */
- while (tracker->unverified_predictions->head)
- {
- MetaStackOp *queued_op = tracker->unverified_predictions->head->data;
-
- if (queued_op->any.serial >= op->any.serial)
- break;
-
- meta_stack_op_apply (tracker, queued_op, tracker->verified_stack,
- NO_RESTACK_X_WINDOWS);
-
- g_queue_pop_head (tracker->unverified_predictions);
- meta_stack_op_free (queued_op);
- need_sync = TRUE;
- }
-
- /* Then we apply the received event. If it's a spontaneous event
- * based on stacking we didn't trigger, this is the only handling. If we
- * triggered it, we do the X restacking here, and then any residual
- * local-only Wayland stacking below.
- */
- if (meta_stack_op_apply (tracker, op, tracker->verified_stack,
- IGNORE_NOOP_X_RESTACK))
- need_sync = TRUE;
-
- /* What is left to process is the prediction corresponding to the event
- * (if any), and then any subsequent Wayland-only events we can just
- * go ahead and do now.
- */
- while (tracker->unverified_predictions->head)
- {
- MetaStackOp *queued_op = tracker->unverified_predictions->head->data;
-
- if (queued_op->any.serial > op->any.serial)
- break;
-
- meta_stack_op_apply (tracker, queued_op, tracker->verified_stack,
- NO_RESTACK_X_WINDOWS);
-
- g_queue_pop_head (tracker->unverified_predictions);
- meta_stack_op_free (queued_op);
- need_sync = TRUE;
- }
-
- if (need_sync)
- {
- if (tracker->predicted_stack)
- {
- g_array_free (tracker->predicted_stack, TRUE);
- tracker->predicted_stack = NULL;
- }
-
- meta_stack_tracker_queue_sync_stack (tracker);
- }
-
- meta_stack_tracker_dump (tracker);
-}
-
-void
-meta_stack_tracker_create_event (MetaStackTracker *tracker,
- XCreateWindowEvent *event)
-{
- MetaStackOp op;
-
- op.any.type = STACK_OP_ADD;
- op.any.serial = event->serial;
- op.add.window = event->window;
-
- stack_tracker_event_received (tracker, &op);
-}
-
-void
-meta_stack_tracker_destroy_event (MetaStackTracker *tracker,
- XDestroyWindowEvent *event)
-{
- MetaStackOp op;
-
- op.any.type = STACK_OP_REMOVE;
- op.any.serial = event->serial;
- op.remove.window = event->window;
-
- stack_tracker_event_received (tracker, &op);
-}
-
-void
-meta_stack_tracker_reparent_event (MetaStackTracker *tracker,
- XReparentEvent *event)
-{
- if (event->parent == event->event)
- {
- MetaStackOp op;
-
- op.any.type = STACK_OP_ADD;
- op.any.serial = event->serial;
- op.add.window = event->window;
-
- stack_tracker_event_received (tracker, &op);
- }
- else
- {
- MetaStackOp op;
-
- op.any.type = STACK_OP_REMOVE;
- op.any.serial = event->serial;
- op.remove.window = event->window;
-
- stack_tracker_event_received (tracker, &op);
- }
-}
-
-void
-meta_stack_tracker_configure_event (MetaStackTracker *tracker,
- XConfigureEvent *event)
-{
- MetaStackOp op;
-
- op.any.type = STACK_OP_RAISE_ABOVE;
- op.any.serial = event->serial;
- op.raise_above.window = event->window;
- op.raise_above.sibling = event->above;
-
- stack_tracker_event_received (tracker, &op);
-}
-
-static gboolean
-meta_stack_tracker_is_guard_window (MetaStackTracker *tracker,
- uint64_t stack_id)
-{
- MetaX11Display *x11_display = tracker->display->x11_display;
-
- if (!x11_display)
- return FALSE;
-
- return stack_id == x11_display->guard_window;
-}
-
-/**
- * meta_stack_tracker_get_stack:
- * @tracker: a #MetaStackTracker
- * @windows: location to store list of windows, or %NULL
- * @n_windows: location to store count of windows, or %NULL
- *
- * @windows will contain the most current view we have of the stacking order
- * of the children of the root window. The returned array contains
- * everything: InputOnly windows, override-redirect windows,
- * hidden windows, etc. Some of these will correspond to MetaWindow
- * objects, others won't.
- *
- * Assuming that no other clients have made requests that change
- * the stacking order since we last received a notification, the
- * returned list of windows is exactly that you'd get as the
- * children when calling XQueryTree() on the root window.
- */
-void
-meta_stack_tracker_get_stack (MetaStackTracker *tracker,
- guint64 **windows,
- int *n_windows)
-{
- GArray *stack;
-
- if (tracker->unverified_predictions->length == 0)
- {
- stack = tracker->verified_stack;
- }
- else
- {
- if (tracker->predicted_stack == NULL)
- {
- GList *l;
-
- tracker->predicted_stack = copy_stack (tracker->verified_stack);
- for (l = tracker->unverified_predictions->head; l; l = l->next)
- {
- MetaStackOp *op = l->data;
- meta_stack_op_apply (tracker, op, tracker->predicted_stack, APPLY_DEFAULT);
- }
- }
-
- stack = tracker->predicted_stack;
- }
-
- if (windows)
- *windows = (guint64 *)stack->data;
- if (n_windows)
- *n_windows = stack->len;
-}
-
-/**
- * meta_stack_tracker_sync_stack:
- * @tracker: a #MetaStackTracker
- *
- * Informs the compositor of the current stacking order of windows,
- * based on the predicted view maintained by the #MetaStackTracker.
- */
-void
-meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
-{
- guint64 *windows;
- GList *meta_windows;
- int n_windows;
- int i;
-
- if (tracker->sync_stack_later)
- {
- meta_later_remove (tracker->sync_stack_later);
- tracker->sync_stack_later = 0;
- }
-
- meta_stack_tracker_keep_override_redirect_on_top (tracker);
-
- meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
-
- meta_windows = NULL;
- for (i = 0; i < n_windows; i++)
- {
- guint64 window = windows[i];
-
- if (META_STACK_ID_IS_X11 (window))
- {
- MetaX11Display *x11_display = tracker->display->x11_display;
- MetaWindow *meta_window = NULL;
-
- if (x11_display)
- meta_window = meta_x11_display_lookup_x_window (x11_display, (Window) window);
-
- /* When mapping back from xwindow to MetaWindow we have to be a bit careful;
- * children of the root could include unmapped windows created by toolkits
- * for internal purposes, including ones that we have registered in our
- * XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW;
- * see window-prop.c:reload_net_wm_user_time_window() for registration.)
- */
- if (meta_window &&
- ((Window)window == meta_window->xwindow ||
- (meta_window->frame && (Window)window == meta_window->frame->xwindow)))
- meta_windows = g_list_prepend (meta_windows, meta_window);
- }
- else
- meta_windows = g_list_prepend (meta_windows,
- meta_display_lookup_stamp (tracker->display, window));
- }
-
- meta_compositor_sync_stack (tracker->display->compositor,
- meta_windows);
- g_list_free (meta_windows);
-
- meta_display_restacked (tracker->display);
-}
-
-static gboolean
-stack_tracker_sync_stack_later (gpointer data)
-{
- meta_stack_tracker_sync_stack (data);
-
- return FALSE;
-}
-
-/**
- * meta_stack_tracker_queue_sync_stack:
- * @tracker: a #MetaStackTracker
- *
- * Queue informing the compositor of the new stacking order before the
- * next redraw. (See meta_stack_tracker_sync_stack()). This is called
- * internally when the stack of X windows changes, but also needs be
- * called directly when we an undecorated window is first shown or
- * withdrawn since the compositor's stacking order (which contains only
- * the windows that have a corresponding MetaWindow) will change without
- * any change to the stacking order of the X windows, if we are creating
- * or destroying MetaWindows.
- */
-void
-meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
-{
- if (tracker->sync_stack_later == 0)
- {
- tracker->sync_stack_later = meta_later_add (META_LATER_SYNC_STACK,
- stack_tracker_sync_stack_later,
- tracker, NULL);
- }
-}
-
-/* When moving an X window we sometimes need an X based sibling.
- *
- * If the given sibling is X based this function returns it back
- * otherwise it searches downwards looking for the nearest X window.
- *
- * If no X based sibling could be found return NULL. */
-static Window
-find_x11_sibling_downwards (MetaStackTracker *tracker,
- guint64 sibling)
-{
- guint64 *windows;
- int n_windows;
- int i;
-
- if (META_STACK_ID_IS_X11 (sibling))
- return (Window)sibling;
-
- meta_stack_tracker_get_stack (tracker,
- &windows, &n_windows);
-
- /* NB: Children are in order from bottom to top and we
- * want to search downwards for the nearest X window.
- */
-
- for (i = n_windows - 1; i >= 0; i--)
- if (windows[i] == sibling)
- break;
-
- for (; i >= 0; i--)
- {
- if (META_STACK_ID_IS_X11 (windows[i]))
- return (Window)windows[i];
- }
-
- return None;
-}
-
-static Window
-find_x11_sibling_upwards (MetaStackTracker *tracker,
- guint64 sibling)
-{
- guint64 *windows;
- int n_windows;
- int i;
-
- if (META_STACK_ID_IS_X11 (sibling))
- return (Window)sibling;
-
- meta_stack_tracker_get_stack (tracker,
- &windows, &n_windows);
-
- for (i = 0; i < n_windows; i++)
- if (windows[i] == sibling)
- break;
-
- for (; i < n_windows; i++)
- {
- if (META_STACK_ID_IS_X11 (windows[i]))
- return (Window)windows[i];
- }
-
- return None;
-}
-
-static void
-meta_stack_tracker_lower_below (MetaStackTracker *tracker,
- guint64 window,
- guint64 sibling)
-{
- gulong serial = 0;
- MetaX11Display *x11_display = tracker->display->x11_display;
-
- if (META_STACK_ID_IS_X11 (window))
- {
- XWindowChanges changes;
- changes.sibling = sibling ? find_x11_sibling_upwards (tracker, sibling) : None;
-
- if (changes.sibling != find_x11_sibling_upwards (tracker, window))
- {
- serial = XNextRequest (x11_display->xdisplay);
-
- meta_x11_error_trap_push (x11_display);
-
- changes.stack_mode = changes.sibling ? Below : Above;
-
- XConfigureWindow (x11_display->xdisplay,
- window,
- (changes.sibling ? CWSibling : 0) | CWStackMode,
- &changes);
-
- meta_x11_error_trap_pop (x11_display);
- }
- }
-
- meta_stack_tracker_record_lower_below (tracker,
- window, sibling,
- serial);
-}
-
-static void
-meta_stack_tracker_raise_above (MetaStackTracker *tracker,
- guint64 window,
- guint64 sibling)
-{
- gulong serial = 0;
- MetaX11Display *x11_display = tracker->display->x11_display;
-
- if (META_STACK_ID_IS_X11 (window))
- {
- XWindowChanges changes;
- changes.sibling = sibling ? find_x11_sibling_downwards (tracker, sibling) : None;
-
- if (changes.sibling != find_x11_sibling_downwards (tracker, window))
- {
- serial = XNextRequest (x11_display->xdisplay);
-
- meta_x11_error_trap_push (x11_display);
-
- changes.stack_mode = changes.sibling ? Above : Below;
-
- XConfigureWindow (x11_display->xdisplay,
- (Window)window,
- (changes.sibling ? CWSibling : 0) | CWStackMode,
- &changes);
-
- meta_x11_error_trap_pop (x11_display);
- }
- }
-
- meta_stack_tracker_record_raise_above (tracker, window,
- sibling, serial);
-}
-
-void
-meta_stack_tracker_lower (MetaStackTracker *tracker,
- guint64 window)
-{
- meta_stack_tracker_raise_above (tracker, window, None);
-}
-
-static void
-meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker)
-{
- guint64 *stack;
- int n_windows, i;
- int topmost_non_or;
-
- meta_stack_tracker_get_stack (tracker, &stack, &n_windows);
-
- for (i = n_windows - 1; i >= 0; i--)
- {
- MetaWindow *window;
-
- window = meta_display_lookup_stack_id (tracker->display, stack[i]);
- if (window && window->layer != META_LAYER_OVERRIDE_REDIRECT)
- break;
- }
-
- topmost_non_or = i;
-
- for (i -= 1; i >= 0; i--)
- {
- MetaWindow *window;
-
- if (meta_stack_tracker_is_guard_window (tracker, stack[i]))
- break;
-
- window = meta_display_lookup_stack_id (tracker->display, stack[i]);
- if (window && window->layer == META_LAYER_OVERRIDE_REDIRECT)
- {
- meta_stack_tracker_raise_above (tracker, stack[i], stack[topmost_non_or]);
- meta_stack_tracker_get_stack (tracker, &stack, &n_windows);
- topmost_non_or -= 1;
- }
- }
-}
-
-void
-meta_stack_tracker_restack_managed (MetaStackTracker *tracker,
- const guint64 *managed,
- int n_managed)
-{
- guint64 *windows;
- int n_windows;
- int old_pos, new_pos;
-
- COGL_TRACE_BEGIN_SCOPED (StackTrackerRestackManaged,
- "StackTracker: Restack Managed");
- if (n_managed == 0)
- return;
-
- COGL_TRACE_BEGIN (StackTrackerRestackManagedGet,
- "StackTracker: Restack Managed (get)");
- meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
-
- /* If the top window has to be restacked, we don't want to move it to the very
- * top of the stack, since apps expect override-redirect windows to stay near
- * the top of the X stack; we instead move it above all managed windows (or
- * above the guard window if there are no non-hidden managed windows.)
- */
- old_pos = n_windows - 1;
- for (old_pos = n_windows - 1; old_pos >= 0; old_pos--)
- {
- MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]);
- if ((old_window && !old_window->override_redirect && !old_window->unmanaging) ||
- meta_stack_tracker_is_guard_window (tracker, windows[old_pos]))
- break;
- }
- g_assert (old_pos >= 0);
- COGL_TRACE_END (StackTrackerRestackManagedGet);
-
- COGL_TRACE_BEGIN (StackTrackerRestackManagedRaise,
- "StackTracker: Restack Managed (raise)");
- new_pos = n_managed - 1;
- if (managed[new_pos] != windows[old_pos])
- {
- /* Move the first managed window in the new stack above all managed windows */
- meta_stack_tracker_raise_above (tracker, managed[new_pos], windows[old_pos]);
- meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
- /* Moving managed[new_pos] above windows[old_pos], moves the window at old_pos down by one */
- }
- COGL_TRACE_END (StackTrackerRestackManagedRaise);
-
- old_pos--;
- new_pos--;
-
- COGL_TRACE_BEGIN (StackTrackerRestackManagedRestack,
- "StackTracker: Restack Managed (restack)");
- while (old_pos >= 0 && new_pos >= 0)
- {
- if (meta_stack_tracker_is_guard_window (tracker, windows[old_pos]))
- break;
-
- if (windows[old_pos] == managed[new_pos])
- {
- old_pos--;
- new_pos--;
- continue;
- }
-
- MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]);
- if (!old_window || old_window->override_redirect || old_window->unmanaging)
- {
- old_pos--;
- continue;
- }
-
- meta_stack_tracker_lower_below (tracker, managed[new_pos], managed[new_pos + 1]);
- meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
- /* Moving managed[new_pos] above windows[old_pos] moves the window at old_pos down by one,
- * we'll examine it again to see if it matches the next new window */
- old_pos--;
- new_pos--;
- }
- COGL_TRACE_END (StackTrackerRestackManagedRestack);
-
- COGL_TRACE_BEGIN (StackTrackerRestackManagedLower,
- "StackTracker: Restack Managed (lower)");
- while (new_pos > 0)
- {
- meta_stack_tracker_lower_below (tracker, managed[new_pos], managed[new_pos - 1]);
- new_pos--;
- }
- COGL_TRACE_END (StackTrackerRestackManagedLower);
-}
-
-void
-meta_stack_tracker_restack_at_bottom (MetaStackTracker *tracker,
- const guint64 *new_order,
- int n_new_order)
-{
- guint64 *windows;
- int n_windows;
- int pos;
-
- COGL_TRACE_BEGIN_SCOPED (StackTrackerRestackAtBottom,
- "Stack tracker: Restack at bottom");
- meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
-
- for (pos = 0; pos < n_new_order; pos++)
- {
- if (pos >= n_windows || windows[pos] != new_order[pos])
- {
- if (pos == 0)
- meta_stack_tracker_lower (tracker, new_order[pos]);
- else
- meta_stack_tracker_raise_above (tracker, new_order[pos], new_order[pos - 1]);
-
- meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
- }
- }
-}
diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h
deleted file mode 100644
index dbffb0e5e..000000000
--- a/src/core/stack-tracker.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/**
- * \file stack-tracker.h Track stacking order for compositor
- *
- * MetaStackTracker maintains the most accurate view we have at a
- * given point of time of the ordering of the children of the root
- * window (including override-redirect windows.) This is used to order
- * the windows when the compositor draws them.
- *
- * By contrast, MetaStack is responsible for keeping track of how we
- * think that windows *should* be ordered. For windows we manage
- * (non-override-redirect windows), the two stacking orders will be
- * the same.
- */
-
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * 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/>.
- */
-
-#ifndef META_STACK_TRACKER_H
-#define META_STACK_TRACKER_H
-
-#include "core/util-private.h"
-#include "meta/display.h"
-#include "meta/window.h"
-
-typedef struct _MetaStackTracker MetaStackTracker;
-
-MetaStackTracker *meta_stack_tracker_new (MetaDisplay *display);
-void meta_stack_tracker_free (MetaStackTracker *tracker);
-
-/* These functions are called when we make an X call that changes the
- * stacking order; this allows MetaStackTracker to predict stacking
- * order before it receives events back from the X server */
-void meta_stack_tracker_record_add (MetaStackTracker *tracker,
- guint64 window,
- gulong serial);
-void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
- guint64 window,
- gulong serial);
-
-/* We also have functions that also go ahead and do the work
- */
-void meta_stack_tracker_lower (MetaStackTracker *tracker,
- guint64 window);
-
-void meta_stack_tracker_restack_managed (MetaStackTracker *tracker,
- const guint64 *windows,
- int n_windows);
-void meta_stack_tracker_restack_at_bottom (MetaStackTracker *tracker,
- const guint64 *new_order,
- int n_new_order);
-
-/* These functions are used to update the stack when we get events
- * reflecting changes to the stacking order */
-void meta_stack_tracker_create_event (MetaStackTracker *tracker,
- XCreateWindowEvent *event);
-void meta_stack_tracker_destroy_event (MetaStackTracker *tracker,
- XDestroyWindowEvent *event);
-void meta_stack_tracker_reparent_event (MetaStackTracker *tracker,
- XReparentEvent *event);
-void meta_stack_tracker_configure_event (MetaStackTracker *tracker,
- XConfigureEvent *event);
-
-META_EXPORT_TEST
-void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
- guint64 **windows,
- int *n_entries);
-
-void meta_stack_tracker_sync_stack (MetaStackTracker *tracker);
-void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker);
-
-#endif /* META_STACK_TRACKER_H */
diff --git a/src/core/stack.c b/src/core/stack.c
deleted file mode 100644
index 62b8954e8..000000000
--- a/src/core/stack.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * SECTION:stack
- * @short_description: Which windows cover which other windows
- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002, 2003 Red Hat, Inc.
- * Copyright (C) 2004 Rob Adams
- * Copyright (C) 2004, 2005 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/>.
- */
-
-#include "config.h"
-
-#include "core/stack.h"
-
-#include "backends/meta-logical-monitor.h"
-#include "cogl/cogl.h"
-#include "core/frame.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/window-private.h"
-#include "meta/group.h"
-#include "meta/prefs.h"
-#include "meta/workspace.h"
-#include "x11/meta-x11-display-private.h"
-
-#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \
- (meta_window_has_transient_type (w) && w->transient_for == NULL)
-
-static void meta_window_set_stack_position_no_sync (MetaWindow *window,
- int position);
-static void stack_do_relayer (MetaStack *stack);
-static void stack_do_constrain (MetaStack *stack);
-static void stack_do_resort (MetaStack *stack);
-static void stack_ensure_sorted (MetaStack *stack);
-
-enum
-{
- PROP_DISPLAY = 1,
- N_PROPS
-};
-
-enum
-{
- CHANGED,
- WINDOW_ADDED,
- WINDOW_REMOVED,
- N_SIGNALS
-};
-
-static GParamSpec *pspecs[N_PROPS] = { 0 };
-static guint signals[N_SIGNALS] = { 0 };
-
-G_DEFINE_TYPE (MetaStack, meta_stack, G_TYPE_OBJECT)
-
-static void
-on_stack_changed (MetaStack *stack)
-{
- MetaDisplay *display = stack->display;
- GArray *all_root_children_stacked;
- GList *l;
- GArray *hidden_stack_ids;
- GList *sorted;
-
- COGL_TRACE_BEGIN_SCOPED (StackChanged, "Stack changed");
-
- meta_topic (META_DEBUG_STACK, "Syncing window stack to server");
-
- all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (uint64_t));
- hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (uint64_t));
-
- meta_topic (META_DEBUG_STACK, "Bottom to top: ");
- meta_push_no_msg_prefix ();
-
- sorted = meta_stack_list_windows (stack, NULL);
-
- for (l = sorted; l; l = l->next)
- {
- MetaWindow *w = l->data;
- uint64_t top_level_window;
- uint64_t stack_id;
-
- if (w->unmanaging)
- continue;
-
- meta_topic (META_DEBUG_STACK, " %u:%d - %s ",
- w->layer, w->stack_position, w->desc);
-
- if (w->frame)
- top_level_window = w->frame->xwindow;
- else
- top_level_window = w->xwindow;
-
- if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
- stack_id = top_level_window;
- else
- stack_id = w->stamp;
-
- /* We don't restack hidden windows along with the rest, though they are
- * reflected in the _NET hints. Hidden windows all get pushed below
- * the screens fullscreen guard_window. */
- if (w->hidden)
- {
- g_array_append_val (hidden_stack_ids, stack_id);
- continue;
- }
-
- g_array_append_val (all_root_children_stacked, stack_id);
- }
-
- meta_pop_no_msg_prefix ();
-
- if (display->x11_display)
- {
- uint64_t guard_window_id;
-
- /* The screen guard window sits above all hidden windows and acts as
- * a barrier to input reaching these windows. */
- guard_window_id = display->x11_display->guard_window;
- g_array_append_val (hidden_stack_ids, guard_window_id);
- }
-
- /* Sync to server */
-
- meta_topic (META_DEBUG_STACK, "Restacking %u windows",
- all_root_children_stacked->len);
-
- meta_stack_tracker_restack_managed (display->stack_tracker,
- (uint64_t *)all_root_children_stacked->data,
- all_root_children_stacked->len);
- meta_stack_tracker_restack_at_bottom (display->stack_tracker,
- (uint64_t *)hidden_stack_ids->data,
- hidden_stack_ids->len);
-
- g_array_free (hidden_stack_ids, TRUE);
- g_array_free (all_root_children_stacked, TRUE);
- g_list_free (sorted);
-}
-
-static void
-meta_stack_init (MetaStack *stack)
-{
- g_signal_connect (stack, "changed",
- G_CALLBACK (on_stack_changed), NULL);
-}
-
-static void
-meta_stack_finalize (GObject *object)
-{
- MetaStack *stack = META_STACK (object);
-
- g_list_free (stack->sorted);
-
- G_OBJECT_CLASS (meta_stack_parent_class)->finalize (object);
-}
-
-static void
-meta_stack_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaStack *stack = META_STACK (object);
-
- switch (prop_id)
- {
- case PROP_DISPLAY:
- stack->display = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_stack_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaStack *stack = META_STACK (object);
-
- switch (prop_id)
- {
- case PROP_DISPLAY:
- g_value_set_object (value, stack->display);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-meta_stack_class_init (MetaStackClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->set_property = meta_stack_set_property;
- object_class->get_property = meta_stack_get_property;
- object_class->finalize = meta_stack_finalize;
-
- signals[CHANGED] =
- g_signal_new ("changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
- signals[WINDOW_ADDED] =
- g_signal_new ("window-added",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, META_TYPE_WINDOW);
- signals[WINDOW_REMOVED] =
- g_signal_new ("window-removed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, META_TYPE_WINDOW);
-
- pspecs[PROP_DISPLAY] =
- g_param_spec_object ("display",
- "Display",
- "Display",
- META_TYPE_DISPLAY,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
-
- g_object_class_install_properties (object_class, N_PROPS, pspecs);
-}
-
-MetaStack *
-meta_stack_new (MetaDisplay *display)
-{
- return g_object_new (META_TYPE_STACK,
- "display", display,
- NULL);
-}
-
-static void
-meta_stack_changed (MetaStack *stack)
-{
- /* Bail out if frozen */
- if (stack->freeze_count > 0)
- return;
-
- COGL_TRACE_BEGIN_SCOPED (MetaStackChangedSort, "Stack: Changed");
-
- stack_ensure_sorted (stack);
- g_signal_emit (stack, signals[CHANGED], 0);
-}
-
-void
-meta_stack_add (MetaStack *stack,
- MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- COGL_TRACE_BEGIN_SCOPED (MetaStackAdd,
- "Stack (add window)");
-
- g_return_if_fail (meta_window_is_stackable (window));
-
- meta_topic (META_DEBUG_STACK, "Adding window %s to the stack", window->desc);
-
- if (meta_window_is_in_stack (window))
- meta_bug ("Window %s had stack position already", window->desc);
-
- stack->sorted = g_list_prepend (stack->sorted, window);
- stack->need_resort = TRUE; /* may not be needed as we add to top */
- stack->need_constrain = TRUE;
- stack->need_relayer = TRUE;
-
- g_signal_emit (stack, signals[WINDOW_ADDED], 0, window);
-
- window->stack_position = stack->n_positions;
- stack->n_positions += 1;
- meta_topic (META_DEBUG_STACK,
- "Window %s has stack_position initialized to %d",
- window->desc, window->stack_position);
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
-}
-
-void
-meta_stack_remove (MetaStack *stack,
- MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- COGL_TRACE_BEGIN_SCOPED (MetaStackRemove,
- "Stack (remove window)");
-
- meta_topic (META_DEBUG_STACK, "Removing window %s from the stack", window->desc);
-
- /* Set window to top position, so removing it will not leave gaps
- * in the set of positions
- */
- meta_window_set_stack_position_no_sync (window,
- stack->n_positions - 1);
- window->stack_position = -1;
- stack->n_positions -= 1;
-
- stack->sorted = g_list_remove (stack->sorted, window);
-
- g_signal_emit (stack, signals[WINDOW_REMOVED], 0, window);
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
-}
-
-void
-meta_stack_update_layer (MetaStack *stack,
- MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- stack->need_relayer = TRUE;
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
-}
-
-void
-meta_stack_update_transient (MetaStack *stack,
- MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- stack->need_constrain = TRUE;
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
-}
-
-/* raise/lower within a layer */
-void
-meta_stack_raise (MetaStack *stack,
- MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- GList *l;
- int max_stack_position = window->stack_position;
- MetaWorkspace *workspace;
-
- stack_ensure_sorted (stack);
-
- workspace = meta_window_get_workspace (window);
- for (l = stack->sorted; l; l = l->next)
- {
- MetaWindow *w = (MetaWindow *) l->data;
- if (meta_window_located_on_workspace (w, workspace) &&
- w->stack_position > max_stack_position)
- max_stack_position = w->stack_position;
- }
-
- if (max_stack_position == window->stack_position)
- return;
-
- meta_window_set_stack_position_no_sync (window, max_stack_position);
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
-}
-
-void
-meta_stack_lower (MetaStack *stack,
- MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- GList *l;
- int min_stack_position = window->stack_position;
- MetaWorkspace *workspace;
-
- stack_ensure_sorted (stack);
-
- workspace = meta_window_get_workspace (window);
- for (l = stack->sorted; l; l = l->next)
- {
- MetaWindow *w = (MetaWindow *) l->data;
- if (meta_window_located_on_workspace (w, workspace) &&
- w->stack_position < min_stack_position)
- min_stack_position = w->stack_position;
- }
-
- if (min_stack_position == window->stack_position)
- return;
-
- meta_window_set_stack_position_no_sync (window, min_stack_position);
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
-}
-
-void
-meta_stack_freeze (MetaStack *stack)
-{
- stack->freeze_count += 1;
-}
-
-void
-meta_stack_thaw (MetaStack *stack)
-{
- g_return_if_fail (stack->freeze_count > 0);
-
- stack->freeze_count -= 1;
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, NULL);
-}
-
-void
-meta_stack_update_window_tile_matches (MetaStack *stack,
- MetaWorkspace *workspace)
-{
- GList *windows, *tmp;
-
- if (stack->freeze_count > 0)
- return;
-
- windows = meta_stack_list_windows (stack, workspace);
- tmp = windows;
- while (tmp)
- {
- meta_window_compute_tile_match ((MetaWindow *) tmp->data);
- tmp = tmp->next;
- }
-
- g_list_free (windows);
-}
-
-/* Front of the layer list is the topmost window,
- * so the lower stack position is later in the list
- */
-static int
-compare_window_position (void *a,
- void *b)
-{
- MetaWindow *window_a = a;
- MetaWindow *window_b = b;
-
- /* Go by layer, then stack_position */
- if (window_a->layer < window_b->layer)
- return 1; /* move window_a later in list */
- else if (window_a->layer > window_b->layer)
- return -1;
- else if (window_a->stack_position < window_b->stack_position)
- return 1; /* move window_a later in list */
- else if (window_a->stack_position > window_b->stack_position)
- return -1;
- else
- return 0; /* not reached */
-}
-
-/*
- * Stacking constraints
- *
- * Assume constraints of the form "AB" meaning "window A must be
- * below window B"
- *
- * If we have windows stacked from bottom to top
- * "ABC" then raise A we get "BCA". Say C is
- * transient for B is transient for A. So
- * we have constraints AB and BC.
- *
- * After raising A, we need to reapply the constraints.
- * If we do this by raising one window at a time -
- *
- * start: BCA
- * apply AB: CAB
- * apply BC: ABC
- *
- * but apply constraints in the wrong order and it breaks:
- *
- * start: BCA
- * apply BC: BCA
- * apply AB: CAB
- *
- * We make a directed graph of the constraints by linking
- * from "above windows" to "below windows as follows:
- *
- * AB -> BC -> CD
- * \
- * CE
- *
- * If we then walk that graph and apply the constraints in the order
- * that they appear, we will apply them correctly. Note that the
- * graph MAY have cycles, so we have to guard against that.
- *
- */
-
-typedef struct Constraint Constraint;
-
-struct Constraint
-{
- MetaWindow *above;
- MetaWindow *below;
-
- /* used to keep the constraint in the
- * list of constraints for window "below"
- */
- Constraint *next;
-
- /* used to create the graph. */
- GSList *next_nodes;
-
- /* constraint has been applied, used
- * to detect cycles.
- */
- unsigned int applied : 1;
-
- /* constraint has a previous node in the graph,
- * used to find places to start in the graph.
- * (I think this also has the side effect
- * of preventing cycles, since cycles will
- * have no starting point - so maybe
- * the "applied" flag isn't needed.)
- */
- unsigned int has_prev : 1;
-};
-
-/* We index the array of constraints by window
- * stack positions, just because the stack
- * positions are a convenient index.
- */
-static void
-add_constraint (Constraint **constraints,
- MetaWindow *above,
- MetaWindow *below)
-{
- Constraint *c;
-
- /* check if constraint is a duplicate */
- c = constraints[below->stack_position];
- while (c != NULL)
- {
- if (c->above == above)
- return;
- c = c->next;
- }
-
- /* if not, add the constraint */
- c = g_new (Constraint, 1);
- c->above = above;
- c->below = below;
- c->next = constraints[below->stack_position];
- c->next_nodes = NULL;
- c->applied = FALSE;
- c->has_prev = FALSE;
-
- constraints[below->stack_position] = c;
-}
-
-static void
-create_constraints (Constraint **constraints,
- GList *windows)
-{
- GList *tmp;
-
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
-
- if (!meta_window_is_in_stack (w))
- {
- meta_topic (META_DEBUG_STACK, "Window %s not in the stack, not constraining it",
- w->desc);
- tmp = tmp->next;
- continue;
- }
-
- if (WINDOW_TRANSIENT_FOR_WHOLE_GROUP (w))
- {
- GSList *group_windows;
- GSList *tmp2;
- MetaGroup *group;
-
- group = meta_window_get_group (w);
-
- if (group != NULL)
- group_windows = meta_group_list_windows (group);
- else
- group_windows = NULL;
-
- tmp2 = group_windows;
-
- while (tmp2 != NULL)
- {
- MetaWindow *group_window = tmp2->data;
-
- if (!meta_window_is_in_stack (group_window) ||
- group_window->override_redirect)
- {
- tmp2 = tmp2->next;
- continue;
- }
-
-#if 0
- /* old way of doing it */
- if (!(meta_window_is_ancestor_of_transient (w, group_window)) &&
- !WINDOW_TRANSIENT_FOR_WHOLE_GROUP (group_window)) /* note */;/*note*/
-#else
- /* better way I think, so transient-for-group are constrained
- * only above non-transient-type windows in their group
- */
- if (!meta_window_has_transient_type (group_window))
-#endif
- {
- meta_topic (META_DEBUG_STACK,
- "Constraining %s above %s as it's transient for its group",
- w->desc, group_window->desc);
- add_constraint (constraints, w, group_window);
- }
-
- tmp2 = tmp2->next;
- }
-
- g_slist_free (group_windows);
- }
- else if (w->transient_for != NULL)
- {
- MetaWindow *parent;
-
- parent = w->transient_for;
-
- if (parent && meta_window_is_in_stack (parent))
- {
- meta_topic (META_DEBUG_STACK,
- "Constraining %s above %s due to transiency",
- w->desc, parent->desc);
- add_constraint (constraints, w, parent);
- }
- }
-
- tmp = tmp->next;
- }
-}
-
-static void
-graph_constraints (Constraint **constraints,
- int n_constraints)
-{
- int i;
-
- i = 0;
- while (i < n_constraints)
- {
- Constraint *c;
-
- /* If we have "A below B" and "B below C" then AB -> BC so we
- * add BC to next_nodes in AB.
- */
-
- c = constraints[i];
- while (c != NULL)
- {
- Constraint *n;
-
- g_assert (c->below->stack_position == i);
-
- /* Constraints where ->above is below are our
- * next_nodes and we are their previous
- */
- n = constraints[c->above->stack_position];
- while (n != NULL)
- {
- c->next_nodes = g_slist_prepend (c->next_nodes,
- n);
- /* c is a previous node of n */
- n->has_prev = TRUE;
-
- n = n->next;
- }
-
- c = c->next;
- }
-
- ++i;
- }
-}
-
-static void
-free_constraints (Constraint **constraints,
- int n_constraints)
-{
- int i;
-
- i = 0;
- while (i < n_constraints)
- {
- Constraint *c;
-
- c = constraints[i];
- while (c != NULL)
- {
- Constraint *next = c->next;
-
- g_slist_free (c->next_nodes);
-
- g_free (c);
-
- c = next;
- }
-
- ++i;
- }
-}
-
-static void
-ensure_above (MetaWindow *above,
- MetaWindow *below)
-{
- gboolean is_transient;
-
- is_transient = meta_window_has_transient_type (above) ||
- above->transient_for == below;
- if (is_transient && above->layer < below->layer)
- {
- meta_topic (META_DEBUG_STACK,
- "Promoting window %s from layer %u to %u due to constraint",
- above->desc, above->layer, below->layer);
- above->layer = below->layer;
- }
-
- if (above->stack_position < below->stack_position)
- {
- /* move above to below->stack_position bumping below down the stack */
- meta_window_set_stack_position_no_sync (above, below->stack_position);
- g_assert (below->stack_position + 1 == above->stack_position);
- }
- meta_topic (META_DEBUG_STACK, "%s above at %d > %s below at %d",
- above->desc, above->stack_position,
- below->desc, below->stack_position);
-}
-
-static void
-traverse_constraint (Constraint *c)
-{
- GSList *tmp;
-
- if (c->applied)
- return;
-
- ensure_above (c->above, c->below);
- c->applied = TRUE;
-
- tmp = c->next_nodes;
- while (tmp != NULL)
- {
- traverse_constraint (tmp->data);
-
- tmp = tmp->next;
- }
-}
-
-static void
-apply_constraints (Constraint **constraints,
- int n_constraints)
-{
- GSList *heads;
- GSList *tmp;
- int i;
-
- /* List all heads in an ordered constraint chain */
- heads = NULL;
- i = 0;
- while (i < n_constraints)
- {
- Constraint *c;
-
- c = constraints[i];
- while (c != NULL)
- {
- if (!c->has_prev)
- heads = g_slist_prepend (heads, c);
-
- c = c->next;
- }
-
- ++i;
- }
-
- /* Now traverse the chain and apply constraints */
- tmp = heads;
- while (tmp != NULL)
- {
- Constraint *c = tmp->data;
-
- traverse_constraint (c);
-
- tmp = tmp->next;
- }
-
- g_slist_free (heads);
-}
-
-/**
- * stack_do_relayer:
- *
- * Update the layers that windows are in
- */
-static void
-stack_do_relayer (MetaStack *stack)
-{
- GList *tmp;
-
- if (!stack->need_relayer)
- return;
-
- meta_topic (META_DEBUG_STACK,
- "Recomputing layers");
-
- tmp = stack->sorted;
-
- while (tmp != NULL)
- {
- MetaWindow *w;
- MetaStackLayer old_layer;
-
- w = tmp->data;
- old_layer = w->layer;
-
- w->layer = meta_window_calculate_layer (w);
-
- if (w->layer != old_layer)
- {
- meta_topic (META_DEBUG_STACK,
- "Window %s moved from layer %u to %u",
- w->desc, old_layer, w->layer);
- stack->need_resort = TRUE;
- stack->need_constrain = TRUE;
- /* don't need to constrain as constraining
- * purely operates in terms of stack_position
- * not layer
- */
- }
-
- tmp = tmp->next;
- }
-
- stack->need_relayer = FALSE;
-}
-
-/**
- * stack_do_constrain:
- *
- * Update stack_position and layer to reflect transiency
- * constraints
- */
-static void
-stack_do_constrain (MetaStack *stack)
-{
- Constraint **constraints;
-
- /* It'd be nice if this were all faster, probably */
-
- if (!stack->need_constrain)
- return;
-
- meta_topic (META_DEBUG_STACK,
- "Reapplying constraints");
-
- constraints = g_new0 (Constraint*,
- stack->n_positions);
-
- create_constraints (constraints, stack->sorted);
-
- graph_constraints (constraints, stack->n_positions);
-
- apply_constraints (constraints, stack->n_positions);
-
- free_constraints (constraints, stack->n_positions);
- g_free (constraints);
-
- stack->need_constrain = FALSE;
-}
-
-/**
- * stack_do_resort:
- *
- * Sort stack->sorted with layers having priority over stack_position.
- */
-static void
-stack_do_resort (MetaStack *stack)
-{
- if (!stack->need_resort)
- return;
-
- meta_topic (META_DEBUG_STACK,
- "Sorting stack list");
-
- stack->sorted = g_list_sort (stack->sorted,
- (GCompareFunc) compare_window_position);
-
- meta_display_queue_check_fullscreen (stack->display);
-
- stack->need_resort = FALSE;
-}
-
-/**
- * stack_ensure_sorted:
- *
- * Puts the stack into canonical form.
- *
- * Honour the removed and added lists of the stack, and then recalculate
- * all the layers (if the flag is set), re-run all the constraint calculations
- * (if the flag is set), and finally re-sort the stack (if the flag is set,
- * and if it wasn't already it might have become so during all the previous
- * activity).
- */
-static void
-stack_ensure_sorted (MetaStack *stack)
-{
- stack_do_relayer (stack);
- stack_do_constrain (stack);
- stack_do_resort (stack);
-}
-
-MetaWindow *
-meta_stack_get_top (MetaStack *stack)
-{
- stack_ensure_sorted (stack);
-
- if (stack->sorted)
- return stack->sorted->data;
- else
- return NULL;
-}
-
-MetaWindow *
-meta_stack_get_bottom (MetaStack *stack)
-{
- GList *link;
-
- stack_ensure_sorted (stack);
-
- link = g_list_last (stack->sorted);
- if (link != NULL)
- return link->data;
- else
- return NULL;
-}
-
-MetaWindow *
-meta_stack_get_above (MetaStack *stack,
- MetaWindow *window,
- gboolean only_within_layer)
-{
- GList *link;
- MetaWindow *above;
-
- stack_ensure_sorted (stack);
-
- link = g_list_find (stack->sorted, window);
- if (link == NULL)
- return NULL;
- if (link->prev == NULL)
- return NULL;
-
- above = link->prev->data;
-
- if (only_within_layer &&
- above->layer != window->layer)
- return NULL;
- else
- return above;
-}
-
-MetaWindow *
-meta_stack_get_below (MetaStack *stack,
- MetaWindow *window,
- gboolean only_within_layer)
-{
- GList *link;
- MetaWindow *below;
-
- stack_ensure_sorted (stack);
-
- link = g_list_find (stack->sorted, window);
-
- if (link == NULL)
- return NULL;
- if (link->next == NULL)
- return NULL;
-
- below = link->next->data;
-
- if (only_within_layer &&
- below->layer != window->layer)
- return NULL;
- else
- return below;
-}
-
-static gboolean
-window_contains_point (MetaWindow *window,
- int root_x,
- int root_y)
-{
- MetaRectangle rect;
-
- meta_window_get_frame_rect (window, &rect);
-
- return META_POINT_IN_RECT (root_x, root_y, rect);
-}
-
-static gboolean
-window_can_get_default_focus (MetaWindow *window)
-{
- if (window->unmaps_pending > 0)
- return FALSE;
-
- if (window->unmanaging)
- return FALSE;
-
- if (!meta_window_is_focusable (window))
- return FALSE;
-
- if (!meta_window_should_be_showing (window))
- return FALSE;
-
- if (window->type == META_WINDOW_DOCK)
- return FALSE;
-
- return TRUE;
-}
-
-static MetaWindow *
-get_default_focus_window (MetaStack *stack,
- MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- gboolean must_be_at_point,
- int root_x,
- int root_y)
-{
- /* Find the topmost, focusable, mapped, window.
- * not_this_one is being unfocused or going away, so exclude it.
- */
-
- GList *l;
-
- stack_ensure_sorted (stack);
-
- /* top of this layer is at the front of the list */
- for (l = stack->sorted; l != NULL; l = l->next)
- {
- MetaWindow *window = l->data;
-
- if (!window)
- continue;
-
- if (window == not_this_one)
- continue;
-
- if (!window_can_get_default_focus (window))
- continue;
-
- if (must_be_at_point && !window_contains_point (window, root_x, root_y))
- continue;
-
- return window;
- }
-
- return NULL;
-}
-
-MetaWindow *
-meta_stack_get_default_focus_window_at_point (MetaStack *stack,
- MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- int root_x,
- int root_y)
-{
- return get_default_focus_window (stack, workspace, not_this_one,
- TRUE, root_x, root_y);
-}
-
-MetaWindow *
-meta_stack_get_default_focus_window (MetaStack *stack,
- MetaWorkspace *workspace,
- MetaWindow *not_this_one)
-{
- return get_default_focus_window (stack, workspace, not_this_one,
- FALSE, 0, 0);
-}
-
-GList *
-meta_stack_list_windows (MetaStack *stack,
- MetaWorkspace *workspace)
-{
- GList *workspace_windows = NULL;
- GList *link;
-
- stack_ensure_sorted (stack); /* do adds/removes */
-
- link = stack->sorted;
-
- while (link)
- {
- MetaWindow *window = link->data;
-
- if (window &&
- (workspace == NULL || meta_window_located_on_workspace (window, workspace)))
- {
- workspace_windows = g_list_prepend (workspace_windows,
- window);
- }
-
- link = link->next;
- }
-
- return workspace_windows;
-}
-
-GList *
-meta_stack_get_default_focus_candidates (MetaStack *stack,
- MetaWorkspace *workspace)
-{
- GList *windows = meta_stack_list_windows (stack, workspace);
- GList *l;
-
- for (l = windows; l;)
- {
- GList *next = l->next;
-
- if (!window_can_get_default_focus (l->data))
- windows = g_list_delete_link (windows, l);
-
- l = next;
- }
-
- return windows;
-}
-
-int
-meta_stack_windows_cmp (MetaStack *stack,
- MetaWindow *window_a,
- MetaWindow *window_b)
-{
- /* -1 means a below b */
-
- stack_ensure_sorted (stack); /* update constraints, layers */
-
- if (window_a->layer < window_b->layer)
- return -1;
- else if (window_a->layer > window_b->layer)
- return 1;
- else if (window_a->stack_position < window_b->stack_position)
- return -1;
- else if (window_a->stack_position > window_b->stack_position)
- return 1;
- else
- return 0; /* not reached */
-}
-
-static int
-compare_just_window_stack_position (void *a,
- void *b)
-{
- MetaWindow *window_a = a;
- MetaWindow *window_b = b;
-
- if (window_a->stack_position < window_b->stack_position)
- return -1; /* move window_a earlier in list */
- else if (window_a->stack_position > window_b->stack_position)
- return 1;
- else
- return 0; /* not reached */
-}
-
-GList *
-meta_stack_get_positions (MetaStack *stack)
-{
- GList *tmp;
-
- /* Make sure to handle any adds or removes */
- stack_ensure_sorted (stack);
-
- tmp = g_list_copy (stack->sorted);
- tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position);
-
- return tmp;
-}
-
-static gint
-compare_pointers (gconstpointer a,
- gconstpointer b)
-{
- if (a > b)
- return 1;
- else if (a < b)
- return -1;
- else
- return 0;
-}
-
-static gboolean
-lists_contain_same_windows (GList *a,
- GList *b)
-{
- GList *copy1, *copy2;
- GList *tmp1, *tmp2;
-
- if (g_list_length (a) != g_list_length (b))
- return FALSE;
-
- tmp1 = copy1 = g_list_sort (g_list_copy (a), compare_pointers);
- tmp2 = copy2 = g_list_sort (g_list_copy (b), compare_pointers);
-
- while (tmp1 && tmp1->data == tmp2->data) /* tmp2 is non-NULL if tmp1 is */
- {
- tmp1 = tmp1->next;
- tmp2 = tmp2->next;
- }
-
- g_list_free (copy1);
- g_list_free (copy2);
-
- return (tmp1 == NULL); /* tmp2 is non-NULL if tmp1 is */
-}
-
-void
-meta_stack_set_positions (MetaStack *stack,
- GList *windows)
-{
- int i;
- GList *tmp;
-
- /* Make sure any adds or removes aren't in limbo -- is this needed? */
- stack_ensure_sorted (stack);
-
- if (!lists_contain_same_windows (windows, stack->sorted))
- {
- meta_warning ("This list of windows has somehow changed; not resetting "
- "positions of the windows.");
- return;
- }
-
- g_list_free (stack->sorted);
- stack->sorted = g_list_copy (windows);
-
- stack->need_resort = TRUE;
- stack->need_constrain = TRUE;
-
- i = 0;
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
- w->stack_position = i++;
- tmp = tmp->next;
- }
-
- meta_topic (META_DEBUG_STACK,
- "Reset the stack positions of (nearly) all windows");
-
- meta_stack_changed (stack);
- meta_stack_update_window_tile_matches (stack, NULL);
-}
-
-void
-meta_window_set_stack_position_no_sync (MetaWindow *window,
- int position)
-{
- int low, high, delta;
- GList *tmp;
-
- g_return_if_fail (window->display->stack != NULL);
- g_return_if_fail (window->stack_position >= 0);
- g_return_if_fail (position >= 0);
- g_return_if_fail (position < window->display->stack->n_positions);
-
- if (position == window->stack_position)
- {
- meta_topic (META_DEBUG_STACK, "Window %s already has position %d",
- window->desc, position);
- return;
- }
-
- window->display->stack->need_resort = TRUE;
- window->display->stack->need_constrain = TRUE;
-
- if (position < window->stack_position)
- {
- low = position;
- high = window->stack_position - 1;
- delta = 1;
- }
- else
- {
- low = window->stack_position + 1;
- high = position;
- delta = -1;
- }
-
- tmp = window->display->stack->sorted;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
-
- if (w->stack_position >= low &&
- w->stack_position <= high)
- w->stack_position += delta;
-
- tmp = tmp->next;
- }
-
- window->stack_position = position;
-
- meta_topic (META_DEBUG_STACK,
- "Window %s had stack_position set to %d",
- window->desc, window->stack_position);
-}
-
-void
-meta_window_set_stack_position (MetaWindow *window,
- int position)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- meta_window_set_stack_position_no_sync (window, position);
- meta_stack_changed (window->display->stack);
- meta_stack_update_window_tile_matches (window->display->stack,
- workspace_manager->active_workspace);
-}
diff --git a/src/core/stack.h b/src/core/stack.h
deleted file mode 100644
index ec5753fe7..000000000
--- a/src/core/stack.h
+++ /dev/null
@@ -1,406 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2005 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/>.
- */
-
-#ifndef META_STACK_H
-#define META_STACK_H
-
-/**
- * SECTION:stack
- * @short_description: Which windows cover which other windows
- *
- * There are two factors that determine window position.
- *
- * One is window->stack_position, which is a unique integer
- * indicating how windows are ordered with respect to one
- * another. The ordering here transcends layers; it isn't changed
- * as the window is moved among layers. This allows us to move several
- * windows from one layer to another, while preserving the relative
- * order of the moved windows. Also, it allows us to restore
- * the stacking order from a saved session.
- *
- * However when actually stacking windows on the screen, the
- * layer overrides the stack_position; windows are first sorted
- * by layer, then by stack_position within each layer.
- */
-
-#include "core/display-private.h"
-
-/**
- * A sorted list of windows bearing some level of resemblance to the stack of
- * windows on the X server.
- *
- * (This is only used as a field within a MetaScreen; we treat it as a separate
- * class for simplicity.)
- */
-struct _MetaStack
-{
- GObject parent;
-
- /** The MetaDisplay containing this stack. */
- MetaDisplay *display;
-
- /** The MetaWindows of the windows we manage, sorted in order. */
- GList *sorted;
-
- /**
- * If this is zero, the local stack oughtn't to be brought up to date with
- * the X server's stack, because it is in the middle of being updated.
- * If it is positive, the local stack is said to be "frozen", and will need
- * to be thawed that many times before the stack can be brought up to date
- * again. You may freeze the stack with meta_stack_freeze() and thaw it
- * with meta_stack_thaw().
- */
- int freeze_count;
-
- /**
- * The last-known stack of all windows, bottom to top. We cache it here
- * so that subsequent times we'll be able to do incremental moves.
- */
- GArray *last_all_root_children_stacked;
-
- /**
- * Number of stack positions; same as the length of added, but
- * kept for quick reference.
- */
- gint n_positions;
-
- /** Is the stack in need of re-sorting? */
- unsigned int need_resort : 1;
-
- /**
- * Are the windows in the stack in need of having their
- * layers recalculated?
- */
- unsigned int need_relayer : 1;
-
- /**
- * Are the windows in the stack in need of having their positions
- * recalculated with respect to transiency (parent and child windows)?
- */
- unsigned int need_constrain : 1;
-};
-
-#define META_TYPE_STACK (meta_stack_get_type ())
-G_DECLARE_FINAL_TYPE (MetaStack, meta_stack, META, STACK, GObject)
-
-/**
- * meta_stack_new:
- * @display: The MetaDisplay which will be the parent of this stack.
- *
- * Creates and initialises a MetaStack.
- *
- * Returns: The new stack.
- */
-MetaStack * meta_stack_new (MetaDisplay *display);
-
-/**
- * meta_stack_add:
- * @stack: The stack to add it to
- * @window: The window to add
- *
- * Adds a window to the local stack. It is a fatal error to call this
- * function on a window which already exists on the stack of any screen.
- */
-void meta_stack_add (MetaStack *stack,
- MetaWindow *window);
-
-/**
- * meta_stack_remove:
- * @stack: The stack to remove it from
- * @window: The window to remove
- *
- * Removes a window from the local stack. It is a fatal error to call this
- * function on a window which exists on the stack of any screen.
- */
-void meta_stack_remove (MetaStack *stack,
- MetaWindow *window);
-/**
- * meta_stack_update_layer:
- * @stack: The stack to recalculate
- * @window: Dummy parameter
- *
- * Recalculates the correct layer for all windows in the stack,
- * and moves them about accordingly.
- *
- */
-void meta_stack_update_layer (MetaStack *stack,
- MetaWindow *window);
-
-/**
- * meta_stack_update_transient:
- * @stack: The stack to recalculate
- * @window: Dummy parameter
- *
- * Recalculates the correct stacking order for all windows in the stack
- * according to their transience, and moves them about accordingly.
- *
- * FIXME: What's with the dummy parameter?
- */
-void meta_stack_update_transient (MetaStack *stack,
- MetaWindow *window);
-
-/**
- * meta_stack_raise:
- * @stack: The stack to modify.
- * @window: The window that's making an ascension.
- * (Amulet of Yendor not required.)
- *
- * Move a window to the top of its layer.
- */
-void meta_stack_raise (MetaStack *stack,
- MetaWindow *window);
-/**
- * meta_stack_lower:
- * @stack: The stack to modify.
- * @window: The window that's on the way downwards.
- *
- * Move a window to the bottom of its layer.
- */
-void meta_stack_lower (MetaStack *stack,
- MetaWindow *window);
-
-/**
- * meta_stack_freeze:
- * @stack: The stack to freeze.
- *
- * Prevent syncing to server until the next call of meta_stack_thaw(),
- * so that we can carry out multiple operations in one go without having
- * everything halfway reflected on the X server.
- *
- * (Calls to meta_stack_freeze() nest, so that multiple calls to
- * meta_stack_freeze will require multiple calls to meta_stack_thaw().)
- */
-void meta_stack_freeze (MetaStack *stack);
-
-/**
- * meta_stack_thaw:
- * @stack: The stack to thaw.
- *
- * Undoes a meta_stack_freeze(), and processes anything which has become
- * necessary during the freeze. It is an error to call this function if
- * the stack has not been frozen.
- */
-void meta_stack_thaw (MetaStack *stack);
-
-/**
- * meta_stack_get_top:
- * @stack: The stack to examine.
- *
- * Finds the top window on the stack.
- *
- * Returns: The top window on the stack, or %NULL in the vanishingly unlikely
- * event that you have no windows on your screen whatsoever.
- */
-MetaWindow * meta_stack_get_top (MetaStack *stack);
-
-/**
- * meta_stack_get_bottom:
- * @stack: The stack to search
- *
- * Finds the window at the bottom of the stack. Since that's pretty much
- * always the desktop, this isn't the most useful of functions, and nobody
- * actually calls it. We should probably get rid of it.
- */
-MetaWindow * meta_stack_get_bottom (MetaStack *stack);
-
-/**
- * meta_stack_get_above:
- * @stack: The stack to search.
- * @window: The window to look above.
- * @only_within_layer: If %TRUE, will return %NULL if @window is the
- * top window in its layer.
- *
- * Finds the window above a given window in the stack.
- * It is not an error to pass in a window which does not exist in
- * the stack; the function will merely return %NULL.
- *
- * Returns: %NULL if there is no such window;
- * the window above @window otherwise.
- */
-MetaWindow * meta_stack_get_above (MetaStack *stack,
- MetaWindow *window,
- gboolean only_within_layer);
-
-/**
- * meta_stack_get_below:
- * @stack: The stack to search.
- * @window: The window to look below.
- * @only_within_layer: If %TRUE, will return %NULL if window is the
- * bottom window in its layer.
- *
- * Finds the window below a given window in the stack.
- * It is not an error to pass in a window which does not exist in
- * the stack; the function will merely return %NULL.
- *
- *
- * Returns: %NULL if there is no such window;
- * the window below @window otherwise.
- */
-MetaWindow * meta_stack_get_below (MetaStack *stack,
- MetaWindow *window,
- gboolean only_within_layer);
-
-/**
- * meta_stack_get_default_focus_window:
- * @stack: The stack to search.
- * @workspace: %NULL to search all workspaces; otherwise only windows
- * from that workspace will be returned.
- * @not_this_one: Window to ignore because it's being unfocussed or
- * going away.
- *
- * Find the topmost, focusable, mapped, window in a stack. If you supply
- * a window as @not_this_one, we won't return that one (presumably
- * because it's going to be going away). But if you do supply @not_this_one
- * and we find its parent, we'll return that; and if @not_this_one is in
- * a group, we'll return the top window of that group.
- *
- * Also, we are prejudiced against dock windows. Every kind of window, even
- * the desktop, will be returned in preference to a dock window.
- *
- * Returns: The window matching all these constraints or %NULL if none does.
- */
-MetaWindow * meta_stack_get_default_focus_window (MetaStack *stack,
- MetaWorkspace *workspace,
- MetaWindow *not_this_one);
-
-/**
- * meta_stack_get_default_focus_window_at_point:
- * @stack: The stack to search.
- * @workspace: %NULL to search all workspaces; otherwise only windows
- * from that workspace will be returned.
- * @not_this_one: Window to ignore because it's being unfocussed or
- * going away.
- * @root_x: The returned window must contain this point,
- * unless it's a dock.
- * @root_y: See root_x.
- *
- * Find the topmost, focusable, mapped, window in a stack. If you supply
- * a window as @not_this_one, we won't return that one (presumably
- * because it's going to be going away). But if you do supply @not_this_one
- * and we find its parent, we'll return that; and if @not_this_one is in
- * a group, we'll return the top window of that group.
- *
- * Also, we are prejudiced against dock windows. Every kind of window, even
- * the desktop, will be returned in preference to a dock window.
- *
- * Returns: The window matching all these constraints or %NULL if none does.
- */
-MetaWindow * meta_stack_get_default_focus_window_at_point (MetaStack *stack,
- MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- int root_x,
- int root_y);
-
-/**
- * meta_stack_get_default_focus_candidates:
- * @stack: The stack to examine.
- * @workspace: If not %NULL, only windows on this workspace will be
- * returned; otherwise all windows in the stack will be
- * returned.
- *
- * Returns all the focus candidate windows in the stack, in order.
- *
- * Returns: (transfer container) (element-type Meta.Window):
- * A #GList of #MetaWindow, in stacking order, honouring layers.
- */
-GList * meta_stack_get_default_focus_candidates (MetaStack *stack,
- MetaWorkspace *workspace);
-
-/**
- * meta_stack_list_windows:
- * @stack: The stack to examine.
- * @workspace: If not %NULL, only windows on this workspace will be
- * returned; otherwise all windows in the stack will be
- * returned.
- *
- * Finds all the windows in the stack, in order.
- *
- * Returns: (transfer container) (element-type Meta.Window):
- * A list of windows, in stacking order, honouring layers.
- */
-GList * meta_stack_list_windows (MetaStack *stack,
- MetaWorkspace *workspace);
-
-/**
- * meta_stack_windows_cmp:
- * @stack: A stack containing both window_a and window_b
- * @window_a: A window
- * @window_b Another window
- *
- * Comparison function for windows within a stack. This is not directly
- * suitable for use within a standard comparison routine, because it takes
- * an extra parameter; you will need to wrap it.
- *
- * (FIXME: We could remove the stack parameter and use the stack of
- * the screen of window A, and complain if the stack of the screen of
- * window B differed; then this would be a usable general comparison function.)
- *
- * (FIXME: Apparently identical to compare_window_position(). Merge them.)
- *
- * \return -1 if window_a is below window_b, honouring layers; 1 if it's
- * above it; 0 if you passed in the same window twice!
- */
-int meta_stack_windows_cmp (MetaStack *stack,
- MetaWindow *window_a,
- MetaWindow *window_b);
-
-/**
- * meta_window_set_stack_position:
- * @window: The window which is moving.
- * @position: Where it should move to (0 is the bottom).
- *
- * Sets the position of a window within the stack. This will only move it
- * up or down within its layer. It is an error to attempt to move this
- * below position zero or above the last position in the stack (however, since
- * we don't provide a simple way to tell the number of windows in the stack,
- * this requirement may not be easy to fulfil).
- */
-void meta_window_set_stack_position (MetaWindow *window,
- int position);
-
-/**
- * meta_stack_get_positions:
- * @stack: The stack to examine.
- *
- * Returns the current stack state, allowing rudimentary transactions.
- *
- * Returns: (transfer container) (element-type Meta.Window):
- * An opaque #GList representing the current stack sort order;
- * it is the caller's responsibility to free it.
- * Pass this to meta_stack_set_positions() later if you want to restore
- * the state to where it was when you called this function.
- */
-GList * meta_stack_get_positions (MetaStack *stack);
-
-/**
- * meta_stack_set_positions:
- * @stack: The stack to roll back.
- * @windows: The list returned from meta_stack_get_positions().
- *
- * Rolls back a transaction, given the list returned from
- * meta_stack_get_positions().
- *
- */
-void meta_stack_set_positions (MetaStack *stack,
- GList *windows);
-
-void meta_stack_update_window_tile_matches (MetaStack *stack,
- MetaWorkspace *workspace);
-#endif
diff --git a/src/core/startup-notification-private.h b/src/core/startup-notification-private.h
deleted file mode 100644
index 5bdf2ac1a..000000000
--- a/src/core/startup-notification-private.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001, 2002 Havoc Pennington
- * Copyright (C) 2002, 2003 Red Hat Inc.
- * Some ICCCM manager selection code derived from fvwm2,
- * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
- * Copyright (C) 2003 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/>.
- */
-
-#ifndef META_STARTUP_NOTIFICATION_PRIVATE_H
-#define META_STARTUP_NOTIFICATION_PRIVATE_H
-
-#include "core/display-private.h"
-#include "meta/meta-startup-notification.h"
-
-struct _MetaStartupSequenceClass
-{
- GObjectClass parent_class;
-
- void (* complete) (MetaStartupSequence *sequence);
-};
-
-MetaStartupNotification *
- meta_startup_notification_new (MetaDisplay *display);
-
-gboolean meta_startup_notification_handle_xevent (MetaStartupNotification *sn,
- XEvent *xevent);
-
-void meta_startup_notification_add_sequence (MetaStartupNotification *sn,
- MetaStartupSequence *seq);
-void meta_startup_notification_remove_sequence (MetaStartupNotification *sn,
- MetaStartupSequence *seq);
-MetaStartupSequence *
- meta_startup_notification_lookup_sequence (MetaStartupNotification *sn,
- const gchar *id);
-
-#endif /* META_STARTUP_NOTIFICATION_PRIVATE_H */
diff --git a/src/core/startup-notification.c b/src/core/startup-notification.c
deleted file mode 100644
index 85a14e939..000000000
--- a/src/core/startup-notification.c
+++ /dev/null
@@ -1,696 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001, 2002 Havoc Pennington
- * Copyright (C) 2002, 2003 Red Hat Inc.
- * Some ICCCM manager selection code derived from fvwm2,
- * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
- * Copyright (C) 2003 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/>.
- */
-
-#include "config.h"
-
-#include <glib-object.h>
-
-#include "core/display-private.h"
-#include "core/startup-notification-private.h"
-#include "core/util-private.h"
-#include "meta/meta-x11-errors.h"
-#include "x11/meta-x11-display-private.h"
-
-/* This should be fairly long, as it should never be required unless
- * apps or .desktop files are buggy, and it's confusing if
- * OpenOffice or whatever seems to stop launching - people
- * might decide they need to launch it again.
- */
-#define STARTUP_TIMEOUT_MS 15000
-
-enum
-{
- PROP_0,
- PROP_DISPLAY,
- N_PROPS
-};
-
-enum
-{
- PROP_SEQ_0,
- PROP_SEQ_ID,
- PROP_SEQ_TIMESTAMP,
- PROP_SEQ_ICON_NAME,
- PROP_SEQ_APPLICATION_ID,
- PROP_SEQ_WMCLASS,
- PROP_SEQ_WORKSPACE,
- PROP_SEQ_NAME,
- N_SEQ_PROPS
-};
-
-enum
-{
- SEQ_COMPLETE,
- SEQ_TIMEOUT,
- N_SEQ_SIGNALS
-};
-
-enum
-{
- CHANGED,
- N_SIGNALS
-};
-
-static guint sn_signals[N_SIGNALS];
-static GParamSpec *sn_props[N_PROPS];
-static guint seq_signals[N_SEQ_SIGNALS];
-static GParamSpec *seq_props[N_SEQ_PROPS];
-
-typedef struct
-{
- GSList *list;
- gint64 now;
-} CollectTimedOutData;
-
-struct _MetaStartupNotification
-{
- GObject parent_instance;
- MetaDisplay *display;
-
-
- GSList *startup_sequences;
- guint startup_sequence_timeout;
-};
-
-typedef struct {
- char *wmclass;
- char *name;
- char *application_id;
- char *icon_name;
- char *id;
- uint64_t timestamp;
- int workspace;
- uint completed : 1;
-} MetaStartupSequencePrivate;
-
-G_DEFINE_TYPE (MetaStartupNotification,
- meta_startup_notification,
- G_TYPE_OBJECT)
-G_DEFINE_TYPE_WITH_PRIVATE (MetaStartupSequence,
- meta_startup_sequence,
- G_TYPE_OBJECT)
-
-
-static void meta_startup_notification_ensure_timeout (MetaStartupNotification *sn);
-
-static gboolean
-meta_startup_notification_has_pending_sequences (MetaStartupNotification *sn)
-{
- GSList *l;
-
- for (l = sn->startup_sequences; l; l = l->next)
- {
- if (!meta_startup_sequence_get_completed (l->data))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-meta_startup_notification_update_feedback (MetaStartupNotification *sn)
-{
- MetaDisplay *display = sn->display;
-
- if (meta_startup_notification_has_pending_sequences (sn))
- {
- meta_topic (META_DEBUG_STARTUP,
- "Setting busy cursor");
- meta_display_set_cursor (display, META_CURSOR_BUSY);
- }
- else
- {
- meta_topic (META_DEBUG_STARTUP,
- "Setting default cursor");
- meta_display_set_cursor (display, META_CURSOR_DEFAULT);
- }
-}
-
-static void
-meta_startup_sequence_init (MetaStartupSequence *seq)
-{
-}
-
-static void
-meta_startup_sequence_finalize (GObject *object)
-{
- MetaStartupSequence *seq;
- MetaStartupSequencePrivate *priv;
-
- seq = META_STARTUP_SEQUENCE (object);
- priv = meta_startup_sequence_get_instance_private (seq);
- g_free (priv->id);
- g_free (priv->wmclass);
- g_free (priv->name);
- g_free (priv->application_id);
- g_free (priv->icon_name);
-
- G_OBJECT_CLASS (meta_startup_sequence_parent_class)->finalize (object);
-}
-
-static void
-meta_startup_sequence_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaStartupSequence *seq;
- MetaStartupSequencePrivate *priv;
-
- seq = META_STARTUP_SEQUENCE (object);
- priv = meta_startup_sequence_get_instance_private (seq);
-
- switch (prop_id)
- {
- case PROP_SEQ_ID:
- priv->id = g_value_dup_string (value);
- break;
- case PROP_SEQ_TIMESTAMP:
- priv->timestamp = g_value_get_uint64 (value);
- break;
- case PROP_SEQ_ICON_NAME:
- priv->icon_name = g_value_dup_string (value);
- break;
- case PROP_SEQ_APPLICATION_ID:
- priv->application_id = g_value_dup_string (value);
- break;
- case PROP_SEQ_WMCLASS:
- priv->wmclass = g_value_dup_string (value);
- break;
- case PROP_SEQ_WORKSPACE:
- priv->workspace = g_value_get_int (value);
- break;
- case PROP_SEQ_NAME:
- priv->name = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_startup_sequence_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaStartupSequence *seq;
- MetaStartupSequencePrivate *priv;
-
- seq = META_STARTUP_SEQUENCE (object);
- priv = meta_startup_sequence_get_instance_private (seq);
-
- switch (prop_id)
- {
- case PROP_SEQ_ID:
- g_value_set_string (value, priv->id);
- break;
- case PROP_SEQ_TIMESTAMP:
- g_value_set_uint64 (value, priv->timestamp);
- break;
- case PROP_SEQ_ICON_NAME:
- g_value_set_string (value, priv->icon_name);
- break;
- case PROP_SEQ_APPLICATION_ID:
- g_value_set_string (value, priv->application_id);
- break;
- case PROP_SEQ_WMCLASS:
- g_value_set_string (value, priv->wmclass);
- break;
- case PROP_SEQ_WORKSPACE:
- g_value_set_int (value, priv->workspace);
- break;
- case PROP_SEQ_NAME:
- g_value_set_string (value, priv->name);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_startup_sequence_class_init (MetaStartupSequenceClass *klass)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = meta_startup_sequence_finalize;
- object_class->set_property = meta_startup_sequence_set_property;
- object_class->get_property = meta_startup_sequence_get_property;
-
- seq_signals[SEQ_COMPLETE] =
- g_signal_new ("complete",
- META_TYPE_STARTUP_SEQUENCE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (MetaStartupSequenceClass, complete),
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
- seq_signals[SEQ_TIMEOUT] =
- g_signal_new ("timeout",
- META_TYPE_STARTUP_SEQUENCE,
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- seq_props[PROP_SEQ_ID] =
- g_param_spec_string ("id",
- "ID",
- "ID",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- seq_props[PROP_SEQ_TIMESTAMP] =
- g_param_spec_uint64 ("timestamp",
- "Timestamp",
- "Timestamp",
- 0, G_MAXUINT64, 0,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- seq_props[PROP_SEQ_ICON_NAME] =
- g_param_spec_string ("icon-name",
- "Icon name",
- "Icon name",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- seq_props[PROP_SEQ_APPLICATION_ID] =
- g_param_spec_string ("application-id",
- "Application ID",
- "Application ID",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- seq_props[PROP_SEQ_WMCLASS] =
- g_param_spec_string ("wmclass",
- "WM class",
- "WM class",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- seq_props[PROP_SEQ_WORKSPACE] =
- g_param_spec_int ("workspace",
- "Workspace",
- "Workspace",
- G_MININT, G_MAXINT, -1,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
- seq_props[PROP_SEQ_NAME] =
- g_param_spec_string ("name",
- "Name",
- "Name",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY);
-
- g_object_class_install_properties (object_class, N_SEQ_PROPS, seq_props);
-}
-
-const char *
-meta_startup_sequence_get_id (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->id;
-}
-
-uint64_t
-meta_startup_sequence_get_timestamp (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), 0);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->timestamp;
-}
-
-void
-meta_startup_sequence_complete (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_if_fail (META_IS_STARTUP_SEQUENCE (seq));
-
- priv = meta_startup_sequence_get_instance_private (seq);
- if (priv->completed)
- return;
-
- priv->completed = TRUE;
- g_signal_emit (seq, seq_signals[SEQ_COMPLETE], 0);
-}
-
-gboolean
-meta_startup_sequence_get_completed (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), FALSE);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->completed;
-}
-
-const char *
-meta_startup_sequence_get_name (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->name;
-}
-
-int
-meta_startup_sequence_get_workspace (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), 0);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->workspace;
-}
-
-const char *
-meta_startup_sequence_get_icon_name (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->icon_name;
-}
-
-const char *
-meta_startup_sequence_get_application_id (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->application_id;
-}
-
-const char *
-meta_startup_sequence_get_wmclass (MetaStartupSequence *seq)
-{
- MetaStartupSequencePrivate *priv;
-
- g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL);
-
- priv = meta_startup_sequence_get_instance_private (seq);
- return priv->wmclass;
-}
-
-static void
-on_sequence_completed (MetaStartupSequence *seq,
- MetaStartupNotification *sn)
-{
- meta_startup_notification_update_feedback (sn);
- g_signal_emit (sn, sn_signals[CHANGED], 0, seq);
-}
-
-void
-meta_startup_notification_add_sequence (MetaStartupNotification *sn,
- MetaStartupSequence *seq)
-{
- sn->startup_sequences = g_slist_prepend (sn->startup_sequences,
- g_object_ref (seq));
- g_signal_connect (seq, "complete",
- G_CALLBACK (on_sequence_completed), sn);
-
- meta_startup_notification_ensure_timeout (sn);
- meta_startup_notification_update_feedback (sn);
-
- g_signal_emit (sn, sn_signals[CHANGED], 0, seq);
-}
-
-static void
-collect_timed_out_foreach (void *element,
- void *data)
-{
- MetaStartupSequence *sequence = element;
- CollectTimedOutData *ctod = data;
- gint64 elapsed, timestamp;
-
- timestamp = meta_startup_sequence_get_timestamp (sequence);
- elapsed = ctod->now - timestamp;
-
- meta_topic (META_DEBUG_STARTUP,
- "Sequence used %" G_GINT64_FORMAT " ms vs. %d max: %s",
- elapsed, STARTUP_TIMEOUT_MS,
- meta_startup_sequence_get_id (sequence));
-
- if (elapsed > STARTUP_TIMEOUT_MS)
- ctod->list = g_slist_prepend (ctod->list, sequence);
-}
-
-static gboolean
-startup_sequence_timeout (void *data)
-{
- MetaStartupNotification *sn = data;
- CollectTimedOutData ctod;
- GSList *l;
-
- ctod.list = NULL;
- ctod.now = g_get_monotonic_time () / 1000;
- g_slist_foreach (sn->startup_sequences,
- collect_timed_out_foreach,
- &ctod);
-
- for (l = ctod.list; l != NULL; l = l->next)
- {
- MetaStartupSequence *sequence = l->data;
-
- meta_topic (META_DEBUG_STARTUP,
- "Timed out sequence %s",
- meta_startup_sequence_get_id (sequence));
-
- if (!meta_startup_sequence_get_completed (sequence))
- {
- g_signal_emit (sequence, seq_signals[SEQ_TIMEOUT], 0, sequence);
- meta_startup_sequence_complete (sequence);
- }
-
- meta_startup_notification_remove_sequence (sn, sequence);
- }
-
- g_slist_free (ctod.list);
-
- if (sn->startup_sequences != NULL)
- {
- return TRUE;
- }
- else
- {
- /* remove */
- sn->startup_sequence_timeout = 0;
- return FALSE;
- }
-}
-
-static void
-meta_startup_notification_ensure_timeout (MetaStartupNotification *sn)
-{
- if (sn->startup_sequence_timeout != 0)
- return;
-
- /* our timeout just polls every second, instead of bothering
- * to compute exactly when we may next time out
- */
- sn->startup_sequence_timeout = g_timeout_add_seconds (1,
- startup_sequence_timeout,
- sn);
- g_source_set_name_by_id (sn->startup_sequence_timeout,
- "[mutter] startup_sequence_timeout");
-}
-
-void
-meta_startup_notification_remove_sequence (MetaStartupNotification *sn,
- MetaStartupSequence *seq)
-{
- sn->startup_sequences = g_slist_remove (sn->startup_sequences, seq);
- meta_startup_notification_update_feedback (sn);
-
- g_signal_handlers_disconnect_by_func (seq, on_sequence_completed, sn);
-
- if (sn->startup_sequences == NULL)
- g_clear_handle_id (&sn->startup_sequence_timeout, g_source_remove);
-
- g_signal_emit (sn, sn_signals[CHANGED], 0, seq);
- g_object_unref (seq);
-}
-
-MetaStartupSequence *
-meta_startup_notification_lookup_sequence (MetaStartupNotification *sn,
- const gchar *id)
-{
- MetaStartupSequence *seq;
- const gchar *seq_id;
- GSList *l;
-
- for (l = sn->startup_sequences; l; l = l->next)
- {
- seq = l->data;
- seq_id = meta_startup_sequence_get_id (seq);
-
- if (g_str_equal (seq_id, id))
- return l->data;
- }
-
- return NULL;
-}
-
-static void
-meta_startup_notification_init (MetaStartupNotification *sn)
-{
-}
-
-static void
-meta_startup_notification_finalize (GObject *object)
-{
- MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object);
-
- g_clear_handle_id (&sn->startup_sequence_timeout, g_source_remove);
-
- g_slist_free_full (sn->startup_sequences, g_object_unref);
- sn->startup_sequences = NULL;
-
- G_OBJECT_CLASS (meta_startup_notification_parent_class)->finalize (object);
-}
-
-static void
-meta_startup_notification_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object);
-
- switch (prop_id)
- {
- case PROP_DISPLAY:
- sn->display = g_value_get_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_startup_notification_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object);
-
- switch (prop_id)
- {
- case PROP_DISPLAY:
- g_value_set_object (value, sn->display);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_startup_notification_constructed (GObject *object)
-{
- MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object);
-
- g_assert (sn->display != NULL);
-
- sn->startup_sequences = NULL;
- sn->startup_sequence_timeout = 0;
-}
-
-static void
-meta_startup_notification_class_init (MetaStartupNotificationClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->constructed = meta_startup_notification_constructed;
- object_class->finalize = meta_startup_notification_finalize;
- object_class->set_property = meta_startup_notification_set_property;
- object_class->get_property = meta_startup_notification_get_property;
-
- sn_props[PROP_DISPLAY] =
- g_param_spec_object ("display",
- "Display",
- "Display",
- META_TYPE_DISPLAY,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- sn_signals[CHANGED] =
- g_signal_new ("changed",
- META_TYPE_STARTUP_NOTIFICATION,
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
- g_object_class_install_properties (object_class, N_PROPS, sn_props);
-}
-
-MetaStartupNotification *
-meta_startup_notification_new (MetaDisplay *display)
-{
- return g_object_new (META_TYPE_STARTUP_NOTIFICATION,
- "display", display,
- NULL);
-}
-
-GSList *
-meta_startup_notification_get_sequences (MetaStartupNotification *sn)
-{
- return sn->startup_sequences;
-}
-
-/**
- * meta_startup_notification_create_launcher:
- * @sn: a #MetaStartupNotification
- *
- * Creates an app launch context.
- *
- * Returns: (transfer full): a launch context.
- **/
-MetaLaunchContext *
-meta_startup_notification_create_launcher (MetaStartupNotification *sn)
-{
- return g_object_new (META_TYPE_LAUNCH_CONTEXT,
- "display", sn->display,
- NULL);
-}
diff --git a/src/core/util-private.h b/src/core/util-private.h
deleted file mode 100644
index 01b663966..000000000
--- a/src/core/util-private.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Mutter utilities */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2005 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#ifndef META_UTIL_PRIVATE_H
-#define META_UTIL_PRIVATE_H
-
-#include <glib/gi18n-lib.h>
-
-#include "meta/util.h"
-#include "meta/common.h"
-
-/* META_EXPORT_TEST should be used to export symbols that are exported only
- * for testability purposes */
-#define META_EXPORT_TEST META_EXPORT
-
-void meta_set_verbose (gboolean setting);
-void meta_set_debugging (gboolean setting);
-
-META_EXPORT_TEST
-void meta_set_syncing (gboolean setting);
-
-void meta_set_replace_current_wm (gboolean setting);
-void meta_set_is_wayland_compositor (gboolean setting);
-
-char * meta_generate_random_id (GRand *rand,
- int length);
-
-void meta_init_debug_utils (void);
-
-#define META_POINT_IN_RECT(xcoord, ycoord, rect) \
- ((xcoord) >= (rect).x && \
- (xcoord) < ((rect).x + (rect).width) && \
- (ycoord) >= (rect).y && \
- (ycoord) < ((rect).y + (rect).height))
-
-void meta_get_clutter_debug_flags (ClutterDebugFlag *debug_flags,
- ClutterDrawDebugFlag *draw_flags,
- ClutterPickDebugFlag *pick_flags);
-
-#endif
diff --git a/src/core/util.c b/src/core/util.c
deleted file mode 100644
index 74a884c80..000000000
--- a/src/core/util.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2005 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:util
- * @title: Utility functions
- * @short_description: Miscellaneous utility functions
- */
-
-#define _POSIX_C_SOURCE 200112L /* for fdopen() */
-
-#include "config.h"
-
-#include "core/util-private.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
-#include <X11/Xutil.h> /* Just for the definition of the various gravities */
-
-#ifdef HAVE_SYS_PRCTL
-#include <sys/prctl.h>
-#endif
-
-#include "clutter/clutter-mutter.h"
-#include "cogl/cogl.h"
-#include "meta/common.h"
-#include "meta/main.h"
-
-static const GDebugKey meta_debug_keys[] = {
- { "focus", META_DEBUG_FOCUS },
- { "workarea", META_DEBUG_WORKAREA },
- { "stack", META_DEBUG_STACK },
- { "sm", META_DEBUG_SM },
- { "events", META_DEBUG_EVENTS },
- { "window-state", META_DEBUG_WINDOW_STATE },
- { "window-ops", META_DEBUG_WINDOW_OPS },
- { "geometry", META_DEBUG_GEOMETRY },
- { "placement", META_DEBUG_PLACEMENT },
- { "ping", META_DEBUG_PING },
- { "keybindings", META_DEBUG_KEYBINDINGS },
- { "sync", META_DEBUG_SYNC },
- { "startup", META_DEBUG_STARTUP },
- { "prefs", META_DEBUG_PREFS },
- { "groups", META_DEBUG_GROUPS },
- { "resizing", META_DEBUG_RESIZING },
- { "shapes", META_DEBUG_SHAPES },
- { "edge-resistance", META_DEBUG_EDGE_RESISTANCE },
- { "dbus", META_DEBUG_DBUS },
- { "input", META_DEBUG_INPUT },
- { "wayland", META_DEBUG_WAYLAND },
- { "kms", META_DEBUG_KMS },
- { "screen-cast", META_DEBUG_SCREEN_CAST },
- { "remote-desktop", META_DEBUG_REMOTE_DESKTOP },
- { "backend", META_DEBUG_BACKEND },
-};
-
-#ifdef WITH_VERBOSE_MODE
-static void
-meta_topic_real_valist (MetaDebugTopic topic,
- const char *format,
- va_list args) G_GNUC_PRINTF(2, 0);
-#endif
-
-static gint verbose_topics = 0;
-static int no_prefix = 0;
-static gboolean is_wayland_compositor = FALSE;
-static int debug_paint_flags = 0;
-
-#ifdef WITH_VERBOSE_MODE
-static FILE* logfile = NULL;
-
-static void
-ensure_logfile (void)
-{
- if (logfile == NULL && g_getenv ("MUTTER_USE_LOGFILE"))
- {
- char *filename = NULL;
- char *tmpl;
- int fd;
- GError *err;
-
- tmpl = g_strdup_printf ("mutter-%d-debug-log-XXXXXX",
- (int) getpid ());
-
- err = NULL;
- fd = g_file_open_tmp (tmpl,
- &filename,
- &err);
-
- g_free (tmpl);
-
- if (err != NULL)
- {
- meta_warning ("Failed to open debug log: %s",
- err->message);
- g_error_free (err);
- return;
- }
-
- logfile = fdopen (fd, "w");
-
- if (logfile == NULL)
- {
- meta_warning ("Failed to fdopen() log file %s: %s",
- filename, strerror (errno));
- close (fd);
- }
- else
- {
- g_printerr ("Opened log file %s", filename);
- }
-
- g_free (filename);
- }
-}
-#endif
-
-gboolean
-meta_is_verbose (void)
-{
- return verbose_topics != 0;
-}
-
-void
-meta_set_verbose (gboolean setting)
-{
-#ifndef WITH_VERBOSE_MODE
- if (setting)
- meta_fatal (_("Mutter was compiled without support for verbose mode"));
-#endif
-
- if (setting)
- meta_add_verbose_topic (META_DEBUG_VERBOSE);
- else
- meta_remove_verbose_topic (META_DEBUG_VERBOSE);
-}
-
-/**
- * meta_add_verbose_topic:
- * @topic: Topic for which logging will be started
- *
- * Ensure log messages for the given topic @topic
- * will be printed.
- */
-void
-meta_add_verbose_topic (MetaDebugTopic topic)
-{
- if (verbose_topics == META_DEBUG_VERBOSE)
- return;
-
- ensure_logfile ();
-
- if (topic == META_DEBUG_VERBOSE)
- verbose_topics = META_DEBUG_VERBOSE;
- else
- verbose_topics |= topic;
-}
-
-/**
- * meta_remove_verbose_topic:
- * @topic: Topic for which logging will be stopped
- *
- * Stop printing log messages for the given topic @topic. Note
- * that this method does not stack with meta_add_verbose_topic();
- * i.e. if two calls to meta_add_verbose_topic() for the same
- * topic are made, one call to meta_remove_verbose_topic() will
- * remove it.
- */
-void
-meta_remove_verbose_topic (MetaDebugTopic topic)
-{
- if (topic == META_DEBUG_VERBOSE)
- verbose_topics = 0;
- else
- verbose_topics &= ~topic;
-}
-
-void
-meta_init_debug_utils (void)
-{
- const char *debug_env;
-
-#ifdef HAVE_SYS_PRCTL
- prctl (PR_SET_DUMPABLE, 1);
-#endif
-
- if (g_getenv ("MUTTER_VERBOSE"))
- meta_set_verbose (TRUE);
-
- debug_env = g_getenv ("MUTTER_DEBUG");
- if (debug_env)
- {
- MetaDebugTopic topics;
-
- topics = g_parse_debug_string (debug_env,
- meta_debug_keys,
- G_N_ELEMENTS (meta_debug_keys));
- meta_add_verbose_topic (topics);
- }
-}
-
-gboolean
-meta_is_wayland_compositor (void)
-{
- return is_wayland_compositor;
-}
-
-void
-meta_set_is_wayland_compositor (gboolean value)
-{
- is_wayland_compositor = value;
-}
-
-char *
-meta_g_utf8_strndup (const gchar *src,
- gsize n)
-{
- const gchar *s = src;
- while (n && *s)
- {
- s = g_utf8_next_char (s);
- n--;
- }
-
- return g_strndup (src, s - src);
-}
-
-static int
-utf8_fputs (const char *str,
- FILE *f)
-{
- char *l;
- int retval;
-
- l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL);
-
- if (l == NULL)
- retval = fputs (str, f); /* just print it anyway, better than nothing */
- else
- retval = fputs (l, f);
-
- g_free (l);
-
- return retval;
-}
-
-#ifdef WITH_VERBOSE_MODE
-void
-meta_verbose_real (const char *format, ...)
-{
- va_list args;
-
- va_start (args, format);
- meta_topic_real_valist (META_DEBUG_VERBOSE, format, args);
- va_end (args);
-}
-
-static const char*
-topic_name (MetaDebugTopic topic)
-{
- switch (topic)
- {
- case META_DEBUG_FOCUS:
- return "FOCUS";
- case META_DEBUG_WORKAREA:
- return "WORKAREA";
- case META_DEBUG_STACK:
- return "STACK";
- case META_DEBUG_SM:
- return "SM";
- case META_DEBUG_EVENTS:
- return "EVENTS";
- case META_DEBUG_WINDOW_STATE:
- return "WINDOW_STATE";
- case META_DEBUG_WINDOW_OPS:
- return "WINDOW_OPS";
- case META_DEBUG_PLACEMENT:
- return "PLACEMENT";
- case META_DEBUG_GEOMETRY:
- return "GEOMETRY";
- case META_DEBUG_PING:
- return "PING";
- case META_DEBUG_KEYBINDINGS:
- return "KEYBINDINGS";
- case META_DEBUG_SYNC:
- return "SYNC";
- case META_DEBUG_STARTUP:
- return "STARTUP";
- case META_DEBUG_PREFS:
- return "PREFS";
- case META_DEBUG_GROUPS:
- return "GROUPS";
- case META_DEBUG_RESIZING:
- return "RESIZING";
- case META_DEBUG_SHAPES:
- return "SHAPES";
- case META_DEBUG_EDGE_RESISTANCE:
- return "EDGE_RESISTANCE";
- case META_DEBUG_DBUS:
- return "DBUS";
- case META_DEBUG_INPUT:
- return "INPUT";
- case META_DEBUG_KMS:
- return "KMS";
- case META_DEBUG_SCREEN_CAST:
- return "SCREEN_CAST";
- case META_DEBUG_REMOTE_DESKTOP:
- return "REMOTE_DESKTOP";
- case META_DEBUG_BACKEND:
- return "BACKEND";
- case META_DEBUG_VERBOSE:
- return "VERBOSE";
- case META_DEBUG_WAYLAND:
- return "WAYLAND";
- }
-
- return "WM";
-}
-
-static int sync_count = 0;
-
-gboolean
-meta_is_topic_enabled (MetaDebugTopic topic)
-{
- if (verbose_topics == 0)
- return FALSE;
-
- if (topic == META_DEBUG_VERBOSE && verbose_topics != META_DEBUG_VERBOSE)
- return FALSE;
-
- return !!(verbose_topics & topic);
-}
-
-static void
-meta_topic_real_valist (MetaDebugTopic topic,
- const char *format,
- va_list args)
-{
- gchar *str;
- FILE *out;
-
- g_return_if_fail (format != NULL);
-
- if (!meta_is_topic_enabled (topic))
- return;
-
- str = g_strdup_vprintf (format, args);
-
- out = logfile ? logfile : stderr;
-
- if (no_prefix == 0)
- fprintf (out, "%s: ", topic_name (topic));
-
- if (topic == META_DEBUG_SYNC)
- {
- ++sync_count;
- fprintf (out, "%d: ", sync_count);
- }
-
- utf8_fputs (str, out);
- utf8_fputs ("\n", out);
-
- fflush (out);
-
- g_free (str);
-}
-
-void
-meta_topic_real (MetaDebugTopic topic,
- const char *format,
- ...)
-{
- va_list args;
-
- va_start (args, format);
- meta_topic_real_valist (topic, format, args);
- va_end (args);
-}
-#endif /* WITH_VERBOSE_MODE */
-
-void
-meta_bug (const char *format, ...)
-{
- va_list args;
- gchar *str;
- FILE *out;
-
- g_return_if_fail (format != NULL);
-
- va_start (args, format);
- str = g_strdup_vprintf (format, args);
- va_end (args);
-
-#ifdef WITH_VERBOSE_MODE
- out = logfile ? logfile : stderr;
-#else
- out = stderr;
-#endif
-
- if (no_prefix == 0)
- utf8_fputs ("Bug in window manager: ", out);
- utf8_fputs (str, out);
- utf8_fputs ("\n", out);
-
- fflush (out);
-
- g_free (str);
-
- /* stop us in a debugger */
- abort ();
-}
-
-void
-meta_warning (const char *format, ...)
-{
- va_list args;
- gchar *str;
- FILE *out;
-
- g_return_if_fail (format != NULL);
-
- va_start (args, format);
- str = g_strdup_vprintf (format, args);
- va_end (args);
-
-#ifdef WITH_VERBOSE_MODE
- out = logfile ? logfile : stderr;
-#else
- out = stderr;
-#endif
-
- if (no_prefix == 0)
- utf8_fputs ("Window manager warning: ", out);
- utf8_fputs (str, out);
- utf8_fputs ("\n", out);
-
- fflush (out);
-
- g_free (str);
-}
-
-void
-meta_fatal (const char *format, ...)
-{
- va_list args;
- gchar *str;
- FILE *out;
-
- g_warn_if_fail (format);
- if (!format)
- meta_exit (META_EXIT_ERROR);
-
- va_start (args, format);
- str = g_strdup_vprintf (format, args);
- va_end (args);
-
-#ifdef WITH_VERBOSE_MODE
- out = logfile ? logfile : stderr;
-#else
- out = stderr;
-#endif
-
- if (no_prefix == 0)
- utf8_fputs ("Window manager error: ", out);
- utf8_fputs (str, out);
- utf8_fputs ("\n", out);
-
- fflush (out);
-
- g_free (str);
-
- meta_exit (META_EXIT_ERROR);
-}
-
-void
-meta_push_no_msg_prefix (void)
-{
- ++no_prefix;
-}
-
-void
-meta_pop_no_msg_prefix (void)
-{
- g_return_if_fail (no_prefix > 0);
-
- --no_prefix;
-}
-
-void
-meta_exit (MetaExitCode code)
-{
-
- exit (code);
-}
-
-gint
-meta_unsigned_long_equal (gconstpointer v1,
- gconstpointer v2)
-{
- return *((const gulong*) v1) == *((const gulong*) v2);
-}
-
-guint
-meta_unsigned_long_hash (gconstpointer v)
-{
- gulong val = * (const gulong *) v;
-
- /* I'm not sure this works so well. */
-#if GLIB_SIZEOF_LONG > 4
- return (guint) (val ^ (val >> 32));
-#else
- return val;
-#endif
-}
-
-const char*
-meta_gravity_to_string (MetaGravity gravity)
-{
- switch (gravity)
- {
- case META_GRAVITY_NORTH_WEST:
- return "META_GRAVITY_NORTH_WEST";
- break;
- case META_GRAVITY_NORTH:
- return "META_GRAVITY_NORTH";
- break;
- case META_GRAVITY_NORTH_EAST:
- return "META_GRAVITY_NORTH_EAST";
- break;
- case META_GRAVITY_WEST:
- return "META_GRAVITY_WEST";
- break;
- case META_GRAVITY_CENTER:
- return "META_GRAVITY_CENTER";
- break;
- case META_GRAVITY_EAST:
- return "META_GRAVITY_EAST";
- break;
- case META_GRAVITY_SOUTH_WEST:
- return "META_GRAVITY_SOUTH_WEST";
- break;
- case META_GRAVITY_SOUTH:
- return "META_GRAVITY_SOUTH";
- break;
- case META_GRAVITY_SOUTH_EAST:
- return "META_GRAVITY_SOUTH_EAST";
- break;
- case META_GRAVITY_STATIC:
- return "META_GRAVITY_STATIC";
- break;
- default:
- return "META_GRAVITY_NORTH_WEST";
- break;
- }
-}
-
-char*
-meta_external_binding_name_for_action (guint keybinding_action)
-{
- return g_strdup_printf ("external-grab-%u", keybinding_action);
-}
-
-/* Command line arguments are passed in the locale encoding; in almost
- * all cases, we'd hope that is UTF-8 and no conversion is necessary.
- * If it's not UTF-8, then it's possible that the message isn't
- * representable in the locale encoding.
- */
-static void
-append_argument (GPtrArray *args,
- const char *arg)
-{
- char *locale_arg = g_locale_from_utf8 (arg, -1, NULL, NULL, NULL);
-
- /* This is cheesy, but it's better to have a few ???'s in the dialog
- * for an unresponsive application than no dialog at all appear */
- if (!locale_arg)
- locale_arg = g_strdup ("???");
-
- g_ptr_array_add (args, locale_arg);
-}
-
-/**
- * meta_show_dialog: (skip)
- * @type: type of dialog
- * @message: message
- * @timeout: timeout
- * @display: display
- * @ok_text: text for Ok button
- * @cancel_text: text for Cancel button
- * @icon_name: icon name
- * @transient_for: window XID of parent
- * @columns: columns
- * @entries: entries
- *
- */
-GPid
-meta_show_dialog (const char *type,
- const char *message,
- const char *timeout,
- const char *display,
- const char *ok_text,
- const char *cancel_text,
- const char *icon_name,
- const int transient_for,
- GSList *columns,
- GSList *entries)
-{
- GError *error = NULL;
- GSList *tmp;
- GPid child_pid;
- GPtrArray *args;
-
- args = g_ptr_array_new ();
-
- append_argument (args, "zenity");
- append_argument (args, type);
-
- if (display)
- {
- append_argument (args, "--display");
- append_argument (args, display);
- }
-
- append_argument (args, "--class");
- append_argument (args, "mutter-dialog");
- append_argument (args, "--title");
- append_argument (args, "");
- append_argument (args, "--text");
- append_argument (args, message);
-
- if (timeout)
- {
- append_argument (args, "--timeout");
- append_argument (args, timeout);
- }
-
- if (ok_text)
- {
- append_argument (args, "--ok-label");
- append_argument (args, ok_text);
- }
-
- if (cancel_text)
- {
- append_argument (args, "--cancel-label");
- append_argument (args, cancel_text);
- }
-
- if (icon_name)
- {
- append_argument (args, "--icon-name");
- append_argument (args, icon_name);
- }
-
- tmp = columns;
- while (tmp)
- {
- append_argument (args, "--column");
- append_argument (args, tmp->data);
- tmp = tmp->next;
- }
-
- tmp = entries;
- while (tmp)
- {
- append_argument (args, tmp->data);
- tmp = tmp->next;
- }
-
- if (transient_for)
- {
- gchar *env = g_strdup_printf("%d", transient_for);
- setenv ("WINDOWID", env, 1);
- g_free (env);
-
- append_argument (args, "--modal");
- }
-
- g_ptr_array_add (args, NULL); /* NULL-terminate */
-
- g_spawn_async (
- "/",
- (gchar**) args->pdata,
- NULL,
- G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL,
- &child_pid,
- &error
- );
-
- if (transient_for)
- unsetenv ("WINDOWID");
-
- g_ptr_array_free (args, TRUE);
-
- if (error)
- {
- meta_warning ("%s", error->message);
- g_error_free (error);
- }
-
- return child_pid;
-}
-
-MetaLocaleDirection
-meta_get_locale_direction (void)
-{
- switch (gtk_get_locale_direction ())
- {
- case GTK_TEXT_DIR_LTR:
- return META_LOCALE_DIRECTION_LTR;
- case GTK_TEXT_DIR_RTL:
- return META_LOCALE_DIRECTION_RTL;
- default:
- g_assert_not_reached ();
- return 0;
- }
-}
-
-char *
-meta_generate_random_id (GRand *rand,
- int length)
-{
- char *id;
- int i;
-
- /* Generate a random string of printable ASCII characters. */
-
- id = g_new0 (char, length + 1);
- for (i = 0; i < length; i++)
- id[i] = (char) g_rand_int_range (rand, 32, 127);
-
- return id;
-}
-
-
-void
-meta_add_clutter_debug_flags (ClutterDebugFlag debug_flags,
- ClutterDrawDebugFlag draw_flags,
- ClutterPickDebugFlag pick_flags)
-{
- clutter_add_debug_flags (debug_flags, draw_flags, pick_flags);
-}
-
-void
-meta_remove_clutter_debug_flags (ClutterDebugFlag debug_flags,
- ClutterDrawDebugFlag draw_flags,
- ClutterPickDebugFlag pick_flags)
-{
- clutter_remove_debug_flags (debug_flags, draw_flags, pick_flags);
-}
-
-void
-meta_get_clutter_debug_flags (ClutterDebugFlag *debug_flags,
- ClutterDrawDebugFlag *draw_flags,
- ClutterPickDebugFlag *pick_flags)
-{
- clutter_get_debug_flags (debug_flags, draw_flags, pick_flags);
-}
-
-void
-meta_add_debug_paint_flag (MetaDebugPaintFlag flag)
-{
- debug_paint_flags |= flag;
-}
-
-void
-meta_remove_debug_paint_flag (MetaDebugPaintFlag flag)
-{
- debug_paint_flags &= ~flag;
-}
-
-MetaDebugPaintFlag
-meta_get_debug_paint_flags (void)
-{
- return debug_paint_flags;
-}
diff --git a/src/core/window-private.h b/src/core/window-private.h
deleted file mode 100644
index d1730c988..000000000
--- a/src/core/window-private.h
+++ /dev/null
@@ -1,888 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/**
- * \file window-private.h Windows which Mutter manages
- *
- * Managing X windows.
- * This file contains methods on this class which are available to
- * routines in core but not outside it. (See window.h for the routines
- * which the rest of the world is allowed to use.)
- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2002 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/>.
- */
-
-#ifndef META_WINDOW_PRIVATE_H
-#define META_WINDOW_PRIVATE_H
-
-#include <X11/Xutil.h>
-#include <cairo.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-#include "backends/meta-logical-monitor.h"
-#include "clutter/clutter.h"
-#include "core/stack.h"
-#include "meta/compositor.h"
-#include "meta/meta-close-dialog.h"
-#include "meta/util.h"
-#include "meta/window.h"
-#include "wayland/meta-wayland-types.h"
-#include "x11/group-private.h"
-
-typedef struct _MetaWindowQueue MetaWindowQueue;
-
-typedef enum
-{
- META_CLIENT_TYPE_UNKNOWN = 0,
- META_CLIENT_TYPE_APPLICATION = 1,
- META_CLIENT_TYPE_PAGER = 2,
- META_CLIENT_TYPE_MAX_RECOGNIZED = 2
-} MetaClientType;
-
-typedef enum
-{
- META_QUEUE_CALC_SHOWING = 1 << 0,
- META_QUEUE_MOVE_RESIZE = 1 << 1,
- META_QUEUE_UPDATE_ICON = 1 << 2,
-} MetaQueueType;
-
-#define NUMBER_OF_QUEUES 3
-
-typedef enum
-{
- META_MOVE_RESIZE_CONFIGURE_REQUEST = 1 << 0,
- META_MOVE_RESIZE_USER_ACTION = 1 << 1,
- META_MOVE_RESIZE_MOVE_ACTION = 1 << 2,
- META_MOVE_RESIZE_RESIZE_ACTION = 1 << 3,
- META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE = 1 << 4,
- META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
- META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
- META_MOVE_RESIZE_UNFULLSCREEN = 1 << 7,
- META_MOVE_RESIZE_FORCE_MOVE = 1 << 8,
- META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 9,
- META_MOVE_RESIZE_FORCE_UPDATE_MONITOR = 1 << 10,
- META_MOVE_RESIZE_PLACEMENT_CHANGED = 1 << 11,
-} MetaMoveResizeFlags;
-
-typedef enum
-{
- META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
- META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1,
- META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
- META_MOVE_RESIZE_RESULT_STATE_CHANGED = 1 << 3,
-} MetaMoveResizeResultFlags;
-
-typedef enum
-{
- META_PLACEMENT_GRAVITY_NONE = 0,
- META_PLACEMENT_GRAVITY_TOP = 1 << 0,
- META_PLACEMENT_GRAVITY_BOTTOM = 1 << 1,
- META_PLACEMENT_GRAVITY_LEFT = 1 << 2,
- META_PLACEMENT_GRAVITY_RIGHT = 1 << 3,
-} MetaPlacementGravity;
-
-typedef enum
-{
- META_PLACEMENT_ANCHOR_NONE = 0,
- META_PLACEMENT_ANCHOR_TOP = 1 << 0,
- META_PLACEMENT_ANCHOR_BOTTOM = 1 << 1,
- META_PLACEMENT_ANCHOR_LEFT = 1 << 2,
- META_PLACEMENT_ANCHOR_RIGHT = 1 << 3,
-} MetaPlacementAnchor;
-
-typedef enum
-{
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_NONE = 0,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1 << 0,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 1 << 1,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X = 1 << 2,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y = 1 << 3,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X = 1 << 4,
- META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 1 << 5,
-} MetaPlacementConstraintAdjustment;
-
-typedef enum _MetaWindowUpdateMonitorFlags
-{
- META_WINDOW_UPDATE_MONITOR_FLAGS_NONE = 0,
- META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP = 1 << 0,
- META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE = 1 << 1,
-} MetaWindowUpdateMonitorFlags;
-
-typedef struct _MetaPlacementRule
-{
- MetaRectangle anchor_rect;
- MetaPlacementGravity gravity;
- MetaPlacementAnchor anchor;
- MetaPlacementConstraintAdjustment constraint_adjustment;
- int offset_x;
- int offset_y;
- int width;
- int height;
-
- gboolean is_reactive;
-
- MetaRectangle parent_rect;
-} MetaPlacementRule;
-
-typedef enum _MetaPlacementState
-{
- META_PLACEMENT_STATE_UNCONSTRAINED,
- META_PLACEMENT_STATE_CONSTRAINED_PENDING,
- META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED,
- META_PLACEMENT_STATE_CONSTRAINED_FINISHED,
- META_PLACEMENT_STATE_INVALIDATED,
-} MetaPlacementState;
-
-typedef enum
-{
- META_EDGE_CONSTRAINT_NONE = 0,
- META_EDGE_CONSTRAINT_WINDOW = 1,
- META_EDGE_CONSTRAINT_MONITOR = 2,
-} MetaEdgeConstraint;
-
-typedef enum
-{
- META_EDGE_RESISTANCE_DEFAULT = 0,
- META_EDGE_RESISTANCE_SNAP = 1 << 0,
- META_EDGE_RESISTANCE_KEYBOARD_OP = 1 << 1,
- META_EDGE_RESISTANCE_WINDOWS = 1 << 2,
-} MetaEdgeResistanceFlags;
-
-struct _MetaWindow
-{
- GObject parent_instance;
-
- MetaDisplay *display;
- uint64_t id;
- guint64 stamp;
- MetaLogicalMonitor *monitor;
- MetaWorkspace *workspace;
- MetaWindowClientType client_type;
- MetaWaylandSurface *surface;
- Window xwindow;
- /* may be NULL! not all windows get decorated */
- MetaFrame *frame;
- int depth;
- Visual *xvisual;
- char *desc; /* used in debug spew */
- char *title;
-
- cairo_surface_t *icon;
- cairo_surface_t *mini_icon;
-
- MetaWindowType type;
-
- /* NOTE these five are not in UTF-8, we just treat them as random
- * binary data
- */
- char *res_class;
- char *res_name;
- char *role;
- char *sm_client_id;
- char *wm_client_machine;
-
- char *startup_id;
- char *mutter_hints;
- char *sandboxed_app_id;
- char *gtk_theme_variant;
- char *gtk_application_id;
- char *gtk_unique_bus_name;
- char *gtk_application_object_path;
- char *gtk_window_object_path;
- char *gtk_app_menu_object_path;
- char *gtk_menubar_object_path;
-
- Window xtransient_for;
- Window xgroup_leader;
- Window xclient_leader;
- MetaWindow *transient_for;
-
- /* Initial workspace property */
- int initial_workspace;
-
- /* Initial timestamp property */
- guint32 initial_timestamp;
-
- /* Whether this is an override redirect window or not */
- guint override_redirect : 1;
-
- /* Whether we're maximized */
- guint maximized_horizontally : 1;
- guint maximized_vertically : 1;
-
- /* Whether we have to maximize/minimize after placement */
- guint maximize_horizontally_after_placement : 1;
- guint maximize_vertically_after_placement : 1;
- guint minimize_after_placement : 1;
-
- /* The current tile mode */
- MetaTileMode tile_mode;
-
- /* The last "full" maximized/unmaximized state. We need to keep track of
- * that to toggle between normal/tiled or maximized/tiled states. */
- guint saved_maximize : 1;
- int tile_monitor_number;
-
- struct {
- MetaEdgeConstraint top;
- MetaEdgeConstraint right;
- MetaEdgeConstraint bottom;
- MetaEdgeConstraint left;
- } edge_constraints;
-
- double tile_hfraction;
-
- uint64_t preferred_output_winsys_id;
-
- /* Whether we're shaded */
- guint shaded : 1;
-
- /* Whether we're fullscreen */
- guint fullscreen : 1;
-
- /* Whether the window is marked as urgent */
- guint urgent : 1;
-
- /* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has
- * been overridden (via a client message), the window will cover the union of
- * these monitors. If not, this is the single monitor which the window's
- * origin is on. */
- struct {
- MetaLogicalMonitor *top;
- MetaLogicalMonitor *bottom;
- MetaLogicalMonitor *left;
- MetaLogicalMonitor *right;
- } fullscreen_monitors;
-
- /* Whether we're trying to constrain the window to be fully onscreen */
- guint require_fully_onscreen : 1;
-
- /* Whether we're trying to constrain the window to be on a single monitor */
- guint require_on_single_monitor : 1;
-
- /* Whether we're trying to constrain the window's titlebar to be onscreen */
- guint require_titlebar_visible : 1;
-
- /* Whether we're sticky in the multi-workspace sense
- * (vs. the not-scroll-with-viewport sense, we don't
- * have no stupid viewports)
- */
- guint on_all_workspaces : 1;
-
- /* This is true if the client requested sticky, and implies on_all_workspaces == TRUE,
- * however on_all_workspaces can be set TRUE for other internal reasons too, such as
- * being override_redirect or being on the non-primary monitor. */
- guint on_all_workspaces_requested : 1;
-
- /* Minimize is the state controlled by the minimize button */
- guint minimized : 1;
- guint tab_unminimized : 1;
-
- /* Whether the window is mapped; actual server-side state
- * see also unmaps_pending
- */
- guint mapped : 1;
-
- /* Whether window has been hidden from view by lowering it to the bottom
- * of window stack.
- */
- guint hidden : 1;
-
- /* Whether the compositor thinks the window is visible.
- * This should match up with calls to meta_compositor_show_window /
- * meta_compositor_hide_window.
- */
- guint visible_to_compositor : 1;
-
- /* Whether the compositor knows about the window.
- * This should match up with calls to meta_compositor_add_window /
- * meta_compositor_remove_window.
- */
- guint known_to_compositor : 1;
-
- /* When we next show or hide the window, what effect we should
- * tell the compositor to perform.
- */
- guint pending_compositor_effect : 4; /* MetaCompEffect */
-
- /* Iconic is the state in WM_STATE; happens for workspaces/shading
- * in addition to minimize
- */
- guint iconic : 1;
- /* initially_iconic is the WM_HINTS setting when we first manage
- * the window. It's taken to mean initially minimized.
- */
- guint initially_iconic : 1;
-
- /* whether an initial workspace was explicitly set */
- guint initial_workspace_set : 1;
-
- /* whether an initial timestamp was explicitly set */
- guint initial_timestamp_set : 1;
-
- /* whether net_wm_user_time has been set yet */
- guint net_wm_user_time_set : 1;
-
- /* whether net_wm_icon_geometry has been set */
- guint icon_geometry_set : 1;
-
- /* Globally active / No input */
- guint input : 1;
-
- /* MWM hints about features of window */
- guint mwm_decorated : 1;
- guint mwm_border_only : 1;
- guint mwm_has_close_func : 1;
- guint mwm_has_minimize_func : 1;
- guint mwm_has_maximize_func : 1;
- guint mwm_has_move_func : 1;
- guint mwm_has_resize_func : 1;
-
- /* Computed features of window */
- guint decorated : 1;
- guint border_only : 1;
- guint always_sticky : 1;
- guint has_close_func : 1;
- guint has_minimize_func : 1;
- guint has_maximize_func : 1;
- guint has_shade_func : 1;
- guint has_move_func : 1;
- guint has_resize_func : 1;
- guint has_fullscreen_func : 1;
-
- /* Computed whether to skip taskbar or not */
- guint skip_taskbar : 1;
- guint skip_pager : 1;
- guint skip_from_window_list : 1;
-
- /* TRUE if client set these */
- guint wm_state_above : 1;
- guint wm_state_below : 1;
-
- /* EWHH demands attention flag */
- guint wm_state_demands_attention : 1;
-
- /* TRUE iff window == window->display->focus_window */
- guint has_focus : 1;
-
- /* Have we placed this window? */
- guint placed : 1;
-
- /* Is this not a transient of the focus window which is being denied focus? */
- guint denied_focus_and_not_transient : 1;
-
- /* Has this window not ever been shown yet? */
- guint showing_for_first_time : 1;
-
- /* Are we in meta_window_unmanage()? */
- guint unmanaging : 1;
-
- /* Are we in meta_window_new()? */
- guint constructing : 1;
-
- /* Are we in the various queues? (Bitfield: see META_WINDOW_IS_IN_QUEUE) */
- guint is_in_queues : NUMBER_OF_QUEUES;
-
- /* Used by keybindings.c */
- guint keys_grabbed : 1; /* normal keybindings grabbed */
- guint grab_on_frame : 1; /* grabs are on the frame */
- guint all_keys_grabbed : 1; /* AnyKey grabbed */
-
- /* Set if the reason for unmanaging the window is that
- * it was withdrawn
- */
- guint withdrawn : 1;
-
- /* TRUE if constrain_position should calc placement.
- * only relevant if !window->placed
- */
- guint calc_placement : 1;
-
- /* if TRUE, window was maximized at start of current grab op */
- guint shaken_loose : 1;
-
- /* if TRUE we have a grab on the focus click buttons */
- guint have_focus_click_grab : 1;
-
- /* if TRUE, application is buggy and SYNC resizing is turned off */
- guint disable_sync : 1;
-
- /* if TRUE, window is attached to its parent */
- guint attached : 1;
-
- /* whether or not the window is from a program running on another machine */
- guint is_remote : 1;
-
- /* whether focus should be restored on map */
- guint restore_focus_on_map : 1;
-
- /* if non-NULL, the bounds of the window frame */
- cairo_region_t *frame_bounds;
-
- /* if non-NULL, the bounding shape region of the window. Relative to
- * the server-side client window. */
- cairo_region_t *shape_region;
-
- /* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
- cairo_region_t *opaque_region;
-
- /* the input shape region for picking */
- cairo_region_t *input_region;
-
- /* _NET_WM_WINDOW_OPACITY rescaled to 0xFF */
- guint8 opacity;
-
- /* if TRUE, the we have the new form of sync request counter which
- * also handles application frames */
- guint extended_sync_request_counter : 1;
-
- /* Note: can be NULL */
- GSList *struts;
-
- /* XSync update counter */
- XSyncCounter sync_request_counter;
- gint64 sync_request_serial;
- gint64 sync_request_wait_serial;
- guint sync_request_timeout_id;
- /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
- XSyncAlarm sync_request_alarm;
-
- /* Number of UnmapNotify that are caused by us, if
- * we get UnmapNotify with none pending then the client
- * is withdrawing the window.
- */
- int unmaps_pending;
-
- /* Number of XReparentWindow requests that we have queued.
- */
- int reparents_pending;
-
- /* See docs for meta_window_get_stable_sequence() */
- guint32 stable_sequence;
-
- /* set to the most recent user-interaction event timestamp that we
- know about for this window */
- guint32 net_wm_user_time;
-
- /* window that gets updated net_wm_user_time values */
- Window user_time_window;
-
- gboolean has_custom_frame_extents;
- GtkBorder custom_frame_extents;
-
- /* The rectangles here are in "frame rect" coordinates. See the
- * comment at the top of meta_window_move_resize_internal() for more
- * information. */
-
- /* The current window geometry of the window. */
- MetaRectangle rect;
-
- /* The geometry to restore when we unmaximize. */
- MetaRectangle saved_rect;
-
- /* The geometry to restore when we unfullscreen. */
- MetaRectangle saved_rect_fullscreen;
-
- /* This is the geometry the window will have if no constraints have
- * applied. We use this whenever we are moving implicitly (for example,
- * if we move to avoid a panel, we can snap back to this position if
- * the panel moves again).
- */
- MetaRectangle unconstrained_rect;
-
- /* The rectangle of the "server-side" geometry of the buffer,
- * in root coordinates.
- *
- * For X11 windows, this matches XGetGeometry of the toplevel.
- *
- * For Wayland windows, the position matches the position of the
- * surface associated with shell surface (wl_shell_surface, xdg_surface
- * etc). The size matches the size surface size as displayed in the stage.
- */
- MetaRectangle buffer_rect;
-
- /* Cached net_wm_icon_geometry */
- MetaRectangle icon_geometry;
-
- /* x/y/w/h here get filled with ConfigureRequest values */
- XSizeHints size_hints;
-
- /* Managed by stack.c */
- MetaStackLayer layer;
- int stack_position; /* see comment in stack.h */
-
- /* Managed by delete.c */
- MetaCloseDialog *close_dialog;
-
- /* maintained by group.c */
- MetaGroup *group;
-
- GObject *compositor_private;
-
- /* Focused window that is (directly or indirectly) attached to this one */
- MetaWindow *attached_focus_window;
-
- /* The currently complementary tiled window, if any */
- MetaWindow *tile_match;
-
- struct {
- MetaPlacementRule *rule;
- MetaPlacementState state;
-
- struct {
- int x;
- int y;
- int rel_x;
- int rel_y;
- } pending;
-
- struct {
- int rel_x;
- int rel_y;
- } current;
- } placement;
-
- guint unmanage_idle_id;
-
- pid_t client_pid;
-};
-
-struct _MetaWindowClass
-{
- GObjectClass parent_class;
-
- void (*manage) (MetaWindow *window);
- void (*unmanage) (MetaWindow *window);
- void (*ping) (MetaWindow *window,
- guint32 serial);
- void (*delete) (MetaWindow *window,
- guint32 timestamp);
- void (*kill) (MetaWindow *window);
- void (*focus) (MetaWindow *window,
- guint32 timestamp);
- void (*grab_op_began) (MetaWindow *window,
- MetaGrabOp op);
- void (*grab_op_ended) (MetaWindow *window,
- MetaGrabOp op);
- void (*current_workspace_changed) (MetaWindow *window);
- void (*move_resize_internal) (MetaWindow *window,
- MetaGravity gravity,
- MetaRectangle unconstrained_rect,
- MetaRectangle constrained_rect,
- MetaRectangle temporary_rect,
- int rel_x,
- int rel_y,
- MetaMoveResizeFlags flags,
- MetaMoveResizeResultFlags *result);
- gboolean (*update_struts) (MetaWindow *window);
- void (*get_default_skip_hints) (MetaWindow *window,
- gboolean *skip_taskbar_out,
- gboolean *skip_pager_out);
- gboolean (*update_icon) (MetaWindow *window,
- cairo_surface_t **icon,
- cairo_surface_t **mini_icon);
- pid_t (*get_client_pid) (MetaWindow *window);
- void (*update_main_monitor) (MetaWindow *window,
- MetaWindowUpdateMonitorFlags flags);
- void (*main_monitor_changed) (MetaWindow *window,
- const MetaLogicalMonitor *old);
- void (*adjust_fullscreen_monitor_rect) (MetaWindow *window,
- MetaRectangle *monitor_rect);
- void (*force_restore_shortcuts) (MetaWindow *window,
- ClutterInputDevice *source);
- gboolean (*shortcuts_inhibited) (MetaWindow *window,
- ClutterInputDevice *source);
- gboolean (*is_focusable) (MetaWindow *window);
- gboolean (*is_stackable) (MetaWindow *window);
- gboolean (*can_ping) (MetaWindow *window);
- gboolean (*are_updates_frozen) (MetaWindow *window);
- gboolean (*is_focus_async) (MetaWindow *window);
-
- MetaStackLayer (*calculate_layer) (MetaWindow *window);
-
- void (* map) (MetaWindow *window);
- void (* unmap) (MetaWindow *window);
-};
-
-/* These differ from window->has_foo_func in that they consider
- * the dynamic window state such as "maximized", not just the
- * window's type
- */
-#define META_WINDOW_MAXIMIZED(w) ((w)->maximized_horizontally && \
- (w)->maximized_vertically)
-#define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically)
-#define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally)
-#define META_WINDOW_TILED_SIDE_BY_SIDE(w) ((w)->maximized_vertically && \
- !(w)->maximized_horizontally && \
- (w)->tile_mode != META_TILE_NONE)
-#define META_WINDOW_TILED_LEFT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \
- (w)->tile_mode == META_TILE_LEFT)
-#define META_WINDOW_TILED_RIGHT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \
- (w)->tile_mode == META_TILE_RIGHT)
-#define META_WINDOW_TILED_MAXIMIZED(w)(META_WINDOW_MAXIMIZED(w) && \
- (w)->tile_mode == META_TILE_MAXIMIZED)
-#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen)
-#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen && !(w)->shaded)
-#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \
- (((w)->size_hints.min_width < (w)->size_hints.max_width) || \
- ((w)->size_hints.min_height < (w)->size_hints.max_height)))
-#define META_WINDOW_ALLOWS_HORIZONTAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_width < (w)->size_hints.max_width)
-#define META_WINDOW_ALLOWS_VERTICAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_height < (w)->size_hints.max_height)
-
-MetaWindow * _meta_window_shared_new (MetaDisplay *display,
- MetaWindowClientType client_type,
- MetaWaylandSurface *surface,
- Window xwindow,
- gulong existing_wm_state,
- MetaCompEffect effect,
- XWindowAttributes *attrs);
-
-void meta_window_unmanage (MetaWindow *window,
- guint32 timestamp);
-void meta_window_unmanage_on_idle (MetaWindow *window);
-void meta_window_queue (MetaWindow *window,
- guint queuebits);
-META_EXPORT_TEST
-void meta_window_untile (MetaWindow *window);
-
-META_EXPORT_TEST
-void meta_window_tile (MetaWindow *window,
- MetaTileMode mode);
-MetaTileMode meta_window_get_tile_mode (MetaWindow *window);
-void meta_window_restore_tile (MetaWindow *window,
- MetaTileMode mode,
- int width,
- int height);
-void meta_window_maximize_internal (MetaWindow *window,
- MetaMaximizeFlags directions,
- MetaRectangle *saved_rect);
-
-void meta_window_make_fullscreen_internal (MetaWindow *window);
-void meta_window_update_fullscreen_monitors (MetaWindow *window,
- MetaLogicalMonitor *top,
- MetaLogicalMonitor *bottom,
- MetaLogicalMonitor *left,
- MetaLogicalMonitor *right);
-
-gboolean meta_window_has_fullscreen_monitors (MetaWindow *window);
-
-void meta_window_adjust_fullscreen_monitor_rect (MetaWindow *window,
- MetaRectangle *monitor_rect);
-
-void meta_window_resize_frame_with_gravity (MetaWindow *window,
- gboolean user_op,
- int w,
- int h,
- MetaGravity gravity);
-
-/* Return whether the window should be currently mapped */
-gboolean meta_window_should_be_showing (MetaWindow *window);
-
-void meta_window_update_struts (MetaWindow *window);
-
-/* gets position we need to set to stay in current position,
- * assuming position will be gravity-compensated. i.e.
- * this is the position a client would send in a configure
- * request.
- */
-void meta_window_get_gravity_position (MetaWindow *window,
- MetaGravity gravity,
- int *x,
- int *y);
-/* Get geometry for saving in the session; x/y are gravity
- * position, and w/h are in resize inc above the base size.
- */
-void meta_window_get_session_geometry (MetaWindow *window,
- int *x,
- int *y,
- int *width,
- int *height);
-
-void meta_window_update_unfocused_button_grabs (MetaWindow *window);
-
-void meta_window_set_focused_internal (MetaWindow *window,
- gboolean focused);
-
-gboolean meta_window_is_focusable (MetaWindow *window);
-
-gboolean meta_window_can_ping (MetaWindow *window);
-
-MetaStackLayer meta_window_calculate_layer (MetaWindow *window);
-
-void meta_window_current_workspace_changed (MetaWindow *window);
-
-void meta_window_show_menu (MetaWindow *window,
- MetaWindowMenuType menu,
- int x,
- int y);
-
-void meta_window_show_menu_for_rect (MetaWindow *window,
- MetaWindowMenuType menu,
- MetaRectangle *rect);
-
-gboolean meta_window_handle_mouse_grab_op_event (MetaWindow *window,
- const ClutterEvent *event);
-
-GList* meta_window_get_workspaces (MetaWindow *window);
-
-void meta_window_get_work_area_for_logical_monitor (MetaWindow *window,
- MetaLogicalMonitor *logical_monitor,
- MetaRectangle *area);
-
-int meta_window_get_current_tile_monitor_number (MetaWindow *window);
-void meta_window_get_tile_area (MetaWindow *window,
- MetaTileMode mode,
- MetaRectangle *tile_area);
-
-
-gboolean meta_window_same_application (MetaWindow *window,
- MetaWindow *other_window);
-
-#define META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE(w) \
- ((w)->type != META_WINDOW_DOCK && (w)->type != META_WINDOW_DESKTOP)
-#define META_WINDOW_IN_NORMAL_TAB_CHAIN(w) \
- (meta_window_is_focusable (w) && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w) && (!(w)->skip_taskbar))
-#define META_WINDOW_IN_DOCK_TAB_CHAIN(w) \
- (meta_window_is_focusable (w) && (! META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w) || (w)->skip_taskbar))
-#define META_WINDOW_IN_GROUP_TAB_CHAIN(w, g) \
- (meta_window_is_focusable (w) && (!g || meta_window_get_group(w)==g))
-
-void meta_window_free_delete_dialog (MetaWindow *window);
-
-void meta_window_update_keyboard_resize (MetaWindow *window,
- gboolean update_cursor);
-void meta_window_update_keyboard_move (MetaWindow *window);
-
-MetaStackLayer meta_window_get_default_layer (MetaWindow *window);
-void meta_window_update_layer (MetaWindow *window);
-
-void meta_window_recalc_features (MetaWindow *window);
-
-void meta_window_set_type (MetaWindow *window,
- MetaWindowType type);
-
-void meta_window_frame_size_changed (MetaWindow *window);
-
-gboolean meta_window_is_in_stack (MetaWindow *window);
-
-void meta_window_stack_just_below (MetaWindow *window,
- MetaWindow *below_this_one);
-
-void meta_window_stack_just_above (MetaWindow *window,
- MetaWindow *above_this_one);
-
-void meta_window_set_user_time (MetaWindow *window,
- guint32 timestamp);
-
-void meta_window_update_for_monitors_changed (MetaWindow *window);
-void meta_window_on_all_workspaces_changed (MetaWindow *window);
-
-gboolean meta_window_should_attach_to_parent (MetaWindow *window);
-gboolean meta_window_can_tile_side_by_side (MetaWindow *window);
-
-void meta_window_compute_tile_match (MetaWindow *window);
-
-gboolean meta_window_updates_are_frozen (MetaWindow *window);
-
-void meta_window_set_title (MetaWindow *window,
- const char *title);
-void meta_window_set_wm_class (MetaWindow *window,
- const char *wm_class,
- const char *wm_instance);
-void meta_window_set_gtk_dbus_properties (MetaWindow *window,
- const char *application_id,
- const char *unique_bus_name,
- const char *appmenu_path,
- const char *menubar_path,
- const char *application_object_path,
- const char *window_object_path);
-
-gboolean meta_window_has_transient_type (MetaWindow *window);
-
-void meta_window_set_transient_for (MetaWindow *window,
- MetaWindow *parent);
-
-void meta_window_set_opacity (MetaWindow *window,
- guint8 opacity);
-
-void meta_window_handle_enter (MetaWindow *window,
- guint32 timestamp,
- guint root_x,
- guint root_y);
-void meta_window_handle_leave (MetaWindow *window);
-
-gboolean meta_window_handle_ui_frame_event (MetaWindow *window,
- const ClutterEvent *event);
-
-void meta_window_handle_ungrabbed_event (MetaWindow *window,
- const ClutterEvent *event);
-
-void meta_window_get_client_area_rect (const MetaWindow *window,
- cairo_rectangle_int_t *rect);
-void meta_window_get_titlebar_rect (MetaWindow *window,
- MetaRectangle *titlebar_rect);
-
-void meta_window_activate_full (MetaWindow *window,
- guint32 timestamp,
- MetaClientType source_indication,
- MetaWorkspace *workspace);
-
-META_EXPORT_TEST
-MetaLogicalMonitor * meta_window_calculate_main_logical_monitor (MetaWindow *window);
-
-MetaLogicalMonitor * meta_window_get_main_logical_monitor (MetaWindow *window);
-void meta_window_update_monitor (MetaWindow *window,
- MetaWindowUpdateMonitorFlags flags);
-
-void meta_window_set_urgent (MetaWindow *window,
- gboolean urgent);
-
-void meta_window_update_resize (MetaWindow *window,
- MetaEdgeResistanceFlags flags,
- int x, int y,
- gboolean force);
-
-void meta_window_move_resize_internal (MetaWindow *window,
- MetaMoveResizeFlags flags,
- MetaGravity gravity,
- MetaRectangle frame_rect);
-
-void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op);
-void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);
-
-void meta_window_set_alive (MetaWindow *window, gboolean is_alive);
-
-gboolean meta_window_has_pointer (MetaWindow *window);
-
-void meta_window_emit_size_changed (MetaWindow *window);
-
-MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window);
-
-void meta_window_force_placement (MetaWindow *window,
- gboolean force_move);
-
-void meta_window_force_restore_shortcuts (MetaWindow *window,
- ClutterInputDevice *source);
-
-gboolean meta_window_shortcuts_inhibited (MetaWindow *window,
- ClutterInputDevice *source);
-gboolean meta_window_is_stackable (MetaWindow *window);
-gboolean meta_window_is_focus_async (MetaWindow *window);
-#endif
diff --git a/src/core/window.c b/src/core/window.c
deleted file mode 100644
index ea56f3328..000000000
--- a/src/core/window.c
+++ /dev/null
@@ -1,8665 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington, Anders Carlsson
- * Copyright (C) 2002, 2003 Red Hat, Inc.
- * Copyright (C) 2003 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:meta-window
- * @title: MetaWindow
- * @short_description: A display-agnostic abstraction for a window.
- *
- * #MetaWindow is the core abstraction in Mutter of a window. It has the
- * properties you'd expect, such as a title, an icon, whether it's fullscreen,
- * has decorations, etc.
- *
- * Since a lot of different kinds of windows exist, each window also a
- * #MetaWindowType which denotes which kind of window we're exactly dealing
- * with. For example, one expects slightly different behaviour from a dialog
- * than a "normal" window. The type of a window can be queried with
- * meta_window_get_type().
- *
- * Common API for windows include:
- * - Minimizing: meta_window_minimize() / meta_window_unminimize()
- * - Maximizing: meta_window_maximize() / meta_window_unmaximize()
- * - Fullscreen: meta_window_make_fullscreen() / meta_window_unmake_fullscreen()
- * / meta_window_is_fullscreen()
- *
- * Each #MetaWindow is part of either one or all #MetaWorkspace<!-- -->s of the
- * desktop. You can activate a window on a certain workspace using
- * meta_window_activate_with_workspace(), and query on which workspace it is
- * located using meta_window_located_on_workspace(). The workspace it is part
- * of can be obtained using meta_window_get_workspace().
- *
- * Each display protocol should make a subclass to be compatible with that
- * protocols' specifics, for example #MetaWindowX11 and #MetaWindowWayland.
- * This is independent of the protocol that the client uses, which is modeled
- * using the #MetaWindowClientType enum.
- *
- * To integrate within the Clutter scene graph, which deals with the actual
- * rendering, each #MetaWindow will be part of a #MetaWindowActor.
- */
-
-#include "config.h"
-
-#include "core/window-private.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <X11/Xatom.h>
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-logical-monitor.h"
-#include "cogl/cogl.h"
-#include "core/boxes-private.h"
-#include "core/constraints.h"
-#include "core/edge-resistance.h"
-#include "core/frame.h"
-#include "core/keybindings-private.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/place.h"
-#include "core/stack.h"
-#include "core/util-private.h"
-#include "core/workspace-private.h"
-#include "meta/compositor-mutter.h"
-#include "meta/group.h"
-#include "meta/meta-cursor-tracker.h"
-#include "meta/meta-enum-types.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/prefs.h"
-#include "ui/ui.h"
-#include "x11/meta-x11-display-private.h"
-#include "x11/window-props.h"
-#include "x11/window-x11.h"
-#include "x11/xprops.h"
-
-#ifdef HAVE_WAYLAND
-#include "wayland/meta-wayland-private.h"
-#include "wayland/meta-wayland-surface.h"
-#include "wayland/meta-window-wayland.h"
-#include "wayland/meta-window-xwayland.h"
-#endif
-
-/* Windows that unmaximize to a size bigger than that fraction of the workarea
- * will be scaled down to that size (while maintaining aspect ratio).
- * Windows that cover an area greater then this size are automaximized on map.
- */
-#define MAX_UNMAXIMIZED_WINDOW_AREA .8
-
-#define SNAP_SECURITY_LABEL_PREFIX "snap."
-
-static int destroying_windows_disallowed = 0;
-
-/* Each window has a "stamp" which is a non-recycled 64-bit ID. They
- * start after the end of the XID space so that, for stacking
- * we can keep a guint64 that represents one or the other
- */
-static guint64 next_window_stamp = G_GUINT64_CONSTANT(0x100000000);
-
-static void invalidate_work_areas (MetaWindow *window);
-static void set_wm_state (MetaWindow *window);
-static void set_net_wm_state (MetaWindow *window);
-static void meta_window_set_above (MetaWindow *window,
- gboolean new_value);
-
-static void meta_window_show (MetaWindow *window);
-static void meta_window_hide (MetaWindow *window);
-
-static void meta_window_save_rect (MetaWindow *window);
-
-static void ensure_mru_position_after (MetaWindow *window,
- MetaWindow *after_this_one);
-
-static void meta_window_move_resize_now (MetaWindow *window);
-
-static void meta_window_unqueue (MetaWindow *window, guint queuebits);
-
-static void update_move (MetaWindow *window,
- MetaEdgeResistanceFlags flags,
- int x,
- int y);
-static gboolean update_move_timeout (gpointer data);
-static void update_resize (MetaWindow *window,
- MetaEdgeResistanceFlags flags,
- int x,
- int y,
- gboolean force);
-static gboolean update_resize_timeout (gpointer data);
-static gboolean should_be_on_all_workspaces (MetaWindow *window);
-
-static void meta_window_flush_calc_showing (MetaWindow *window);
-
-static gboolean queue_calc_showing_func (MetaWindow *window,
- void *data);
-
-static void meta_window_move_between_rects (MetaWindow *window,
- MetaMoveResizeFlags move_resize_flags,
- const MetaRectangle *old_area,
- const MetaRectangle *new_area);
-
-static void unmaximize_window_before_freeing (MetaWindow *window);
-static void unminimize_window_and_all_transient_parents (MetaWindow *window);
-
-static void meta_window_propagate_focus_appearance (MetaWindow *window,
- gboolean focused);
-static void meta_window_update_icon_now (MetaWindow *window,
- gboolean force);
-
-static void set_workspace_state (MetaWindow *window,
- gboolean on_all_workspaces,
- MetaWorkspace *workspace);
-
-static MetaWindow * meta_window_find_tile_match (MetaWindow *window,
- MetaTileMode mode);
-static void update_edge_constraints (MetaWindow *window);
-
-/* Idle handlers for the three queues (run with meta_later_add()). The
- * "data" parameter in each case will be a GINT_TO_POINTER of the
- * index into the queue arrays to use.
- *
- * TODO: Possibly there is still some code duplication among these, which we
- * need to sort out at some point.
- */
-static gboolean idle_calc_showing (gpointer data);
-static gboolean idle_move_resize (gpointer data);
-static gboolean idle_update_icon (gpointer data);
-
-G_DEFINE_ABSTRACT_TYPE (MetaWindow, meta_window, G_TYPE_OBJECT);
-
-enum
-{
- PROP_0,
-
- PROP_TITLE,
- PROP_ICON,
- PROP_MINI_ICON,
- PROP_DECORATED,
- PROP_FULLSCREEN,
- PROP_MAXIMIZED_HORIZONTALLY,
- PROP_MAXIMIZED_VERTICALLY,
- PROP_MINIMIZED,
- PROP_WINDOW_TYPE,
- PROP_USER_TIME,
- PROP_DEMANDS_ATTENTION,
- PROP_URGENT,
- PROP_SKIP_TASKBAR,
- PROP_MUTTER_HINTS,
- PROP_APPEARS_FOCUSED,
- PROP_RESIZEABLE,
- PROP_ABOVE,
- PROP_WM_CLASS,
- PROP_GTK_APPLICATION_ID,
- PROP_GTK_UNIQUE_BUS_NAME,
- PROP_GTK_APPLICATION_OBJECT_PATH,
- PROP_GTK_WINDOW_OBJECT_PATH,
- PROP_GTK_APP_MENU_OBJECT_PATH,
- PROP_GTK_MENUBAR_OBJECT_PATH,
- PROP_ON_ALL_WORKSPACES,
-
- PROP_LAST,
-};
-
-static GParamSpec *obj_props[PROP_LAST];
-
-enum
-{
- WORKSPACE_CHANGED,
- FOCUS,
- RAISED,
- UNMANAGING,
- UNMANAGED,
- SIZE_CHANGED,
- POSITION_CHANGED,
- SHOWN,
-
- LAST_SIGNAL
-};
-
-static guint window_signals[LAST_SIGNAL] = { 0 };
-
-static void
-prefs_changed_callback (MetaPreference pref,
- gpointer data)
-{
- MetaWindow *window = data;
-
- if (pref == META_PREF_WORKSPACES_ONLY_ON_PRIMARY)
- {
- meta_window_on_all_workspaces_changed (window);
- }
- else if (pref == META_PREF_ATTACH_MODAL_DIALOGS &&
- window->type == META_WINDOW_MODAL_DIALOG)
- {
- window->attached = meta_window_should_attach_to_parent (window);
- meta_window_recalc_features (window);
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
- }
-}
-
-static void
-meta_window_real_grab_op_began (MetaWindow *window,
- MetaGrabOp op)
-{
-}
-
-static void
-meta_window_real_grab_op_ended (MetaWindow *window,
- MetaGrabOp op)
-{
- window->shaken_loose = FALSE;
-}
-
-static void
-meta_window_real_current_workspace_changed (MetaWindow *window)
-{
-}
-
-static gboolean
-meta_window_real_update_struts (MetaWindow *window)
-{
- return FALSE;
-}
-
-static void
-meta_window_real_get_default_skip_hints (MetaWindow *window,
- gboolean *skip_taskbar_out,
- gboolean *skip_pager_out)
-{
- *skip_taskbar_out = FALSE;
- *skip_pager_out = FALSE;
-}
-
-static gboolean
-meta_window_real_update_icon (MetaWindow *window,
- cairo_surface_t **icon,
- cairo_surface_t **mini_icon)
-{
- *icon = NULL;
- *mini_icon = NULL;
- return FALSE;
-}
-
-static pid_t
-meta_window_real_get_client_pid (MetaWindow *window)
-{
- return 0;
-}
-
-static void
-meta_window_finalize (GObject *object)
-{
- MetaWindow *window = META_WINDOW (object);
-
- if (window->icon)
- cairo_surface_destroy (window->icon);
-
- if (window->mini_icon)
- cairo_surface_destroy (window->mini_icon);
-
- if (window->frame_bounds)
- cairo_region_destroy (window->frame_bounds);
-
- if (window->shape_region)
- cairo_region_destroy (window->shape_region);
-
- if (window->opaque_region)
- cairo_region_destroy (window->opaque_region);
-
- if (window->input_region)
- cairo_region_destroy (window->input_region);
-
- if (window->transient_for)
- g_object_unref (window->transient_for);
-
- g_free (window->sm_client_id);
- g_free (window->wm_client_machine);
- g_free (window->startup_id);
- g_free (window->role);
- g_free (window->res_class);
- g_free (window->res_name);
- g_free (window->title);
- g_free (window->desc);
- g_free (window->sandboxed_app_id);
- g_free (window->gtk_theme_variant);
- g_free (window->gtk_application_id);
- g_free (window->gtk_unique_bus_name);
- g_free (window->gtk_application_object_path);
- g_free (window->gtk_window_object_path);
- g_free (window->gtk_app_menu_object_path);
- g_free (window->gtk_menubar_object_path);
- g_free (window->placement.rule);
-
- G_OBJECT_CLASS (meta_window_parent_class)->finalize (object);
-}
-
-static void
-meta_window_get_property(GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaWindow *win = META_WINDOW (object);
-
- switch (prop_id)
- {
- case PROP_TITLE:
- g_value_set_string (value, win->title);
- break;
- case PROP_ICON:
- g_value_set_pointer (value, win->icon);
- break;
- case PROP_MINI_ICON:
- g_value_set_pointer (value, win->mini_icon);
- break;
- case PROP_DECORATED:
- g_value_set_boolean (value, win->decorated);
- break;
- case PROP_FULLSCREEN:
- g_value_set_boolean (value, win->fullscreen);
- break;
- case PROP_MAXIMIZED_HORIZONTALLY:
- g_value_set_boolean (value, win->maximized_horizontally);
- break;
- case PROP_MAXIMIZED_VERTICALLY:
- g_value_set_boolean (value, win->maximized_vertically);
- break;
- case PROP_MINIMIZED:
- g_value_set_boolean (value, win->minimized);
- break;
- case PROP_WINDOW_TYPE:
- g_value_set_enum (value, win->type);
- break;
- case PROP_USER_TIME:
- g_value_set_uint (value, win->net_wm_user_time);
- break;
- case PROP_DEMANDS_ATTENTION:
- g_value_set_boolean (value, win->wm_state_demands_attention);
- break;
- case PROP_URGENT:
- g_value_set_boolean (value, win->urgent);
- break;
- case PROP_SKIP_TASKBAR:
- g_value_set_boolean (value, win->skip_taskbar);
- break;
- case PROP_MUTTER_HINTS:
- g_value_set_string (value, win->mutter_hints);
- break;
- case PROP_APPEARS_FOCUSED:
- g_value_set_boolean (value, meta_window_appears_focused (win));
- break;
- case PROP_WM_CLASS:
- g_value_set_string (value, win->res_class);
- break;
- case PROP_RESIZEABLE:
- g_value_set_boolean (value, win->has_resize_func);
- break;
- case PROP_ABOVE:
- g_value_set_boolean (value, win->wm_state_above);
- break;
- case PROP_GTK_APPLICATION_ID:
- g_value_set_string (value, win->gtk_application_id);
- break;
- case PROP_GTK_UNIQUE_BUS_NAME:
- g_value_set_string (value, win->gtk_unique_bus_name);
- break;
- case PROP_GTK_APPLICATION_OBJECT_PATH:
- g_value_set_string (value, win->gtk_application_object_path);
- break;
- case PROP_GTK_WINDOW_OBJECT_PATH:
- g_value_set_string (value, win->gtk_window_object_path);
- break;
- case PROP_GTK_APP_MENU_OBJECT_PATH:
- g_value_set_string (value, win->gtk_app_menu_object_path);
- break;
- case PROP_GTK_MENUBAR_OBJECT_PATH:
- g_value_set_string (value, win->gtk_menubar_object_path);
- break;
- case PROP_ON_ALL_WORKSPACES:
- g_value_set_boolean (value, win->on_all_workspaces);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_window_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_window_class_init (MetaWindowClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = meta_window_finalize;
-
- object_class->get_property = meta_window_get_property;
- object_class->set_property = meta_window_set_property;
-
- klass->grab_op_began = meta_window_real_grab_op_began;
- klass->grab_op_ended = meta_window_real_grab_op_ended;
- klass->current_workspace_changed = meta_window_real_current_workspace_changed;
- klass->update_struts = meta_window_real_update_struts;
- klass->get_default_skip_hints = meta_window_real_get_default_skip_hints;
- klass->update_icon = meta_window_real_update_icon;
- klass->get_client_pid = meta_window_real_get_client_pid;
-
- obj_props[PROP_TITLE] =
- g_param_spec_string ("title",
- "Title",
- "The title of the window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_ICON] =
- g_param_spec_pointer ("icon",
- "Icon",
- "Normal icon, usually 96x96 pixels",
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_MINI_ICON] =
- g_param_spec_pointer ("mini-icon",
- "Mini Icon",
- "Mini icon, usually 16x16 pixels",
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_DECORATED] =
- g_param_spec_boolean ("decorated",
- "Decorated",
- "Whether window is decorated",
- TRUE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_FULLSCREEN] =
- g_param_spec_boolean ("fullscreen",
- "Fullscreen",
- "Whether window is fullscreened",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_MAXIMIZED_HORIZONTALLY] =
- g_param_spec_boolean ("maximized-horizontally",
- "Maximized horizontally",
- "Whether window is maximized horizontally",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_MAXIMIZED_VERTICALLY] =
- g_param_spec_boolean ("maximized-vertically",
- "Maximizing vertically",
- "Whether window is maximized vertically",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_MINIMIZED] =
- g_param_spec_boolean ("minimized",
- "Minimizing",
- "Whether window is minimized",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_WINDOW_TYPE] =
- g_param_spec_enum ("window-type",
- "Window Type",
- "The type of the window",
- META_TYPE_WINDOW_TYPE,
- META_WINDOW_NORMAL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_USER_TIME] =
- g_param_spec_uint ("user-time",
- "User time",
- "Timestamp of last user interaction",
- 0,
- G_MAXUINT,
- 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_DEMANDS_ATTENTION] =
- g_param_spec_boolean ("demands-attention",
- "Demands Attention",
- "Whether the window has _NET_WM_STATE_DEMANDS_ATTENTION set",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_URGENT] =
- g_param_spec_boolean ("urgent",
- "Urgent",
- "Whether the urgent flag of WM_HINTS is set",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_SKIP_TASKBAR] =
- g_param_spec_boolean ("skip-taskbar",
- "Skip taskbar",
- "Whether the skip-taskbar flag of WM_HINTS is set",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_MUTTER_HINTS] =
- g_param_spec_string ("mutter-hints",
- "_MUTTER_HINTS",
- "Contents of the _MUTTER_HINTS property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_APPEARS_FOCUSED] =
- g_param_spec_boolean ("appears-focused",
- "Appears focused",
- "Whether the window is drawn as being focused",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_RESIZEABLE] =
- g_param_spec_boolean ("resizeable",
- "Resizeable",
- "Whether the window can be resized",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_ABOVE] =
- g_param_spec_boolean ("above",
- "Above",
- "Whether the window is shown as always-on-top",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_WM_CLASS] =
- g_param_spec_string ("wm-class",
- "WM_CLASS",
- "Contents of the WM_CLASS property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_GTK_APPLICATION_ID] =
- g_param_spec_string ("gtk-application-id",
- "_GTK_APPLICATION_ID",
- "Contents of the _GTK_APPLICATION_ID property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_GTK_UNIQUE_BUS_NAME] =
- g_param_spec_string ("gtk-unique-bus-name",
- "_GTK_UNIQUE_BUS_NAME",
- "Contents of the _GTK_UNIQUE_BUS_NAME property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_GTK_APPLICATION_OBJECT_PATH] =
- g_param_spec_string ("gtk-application-object-path",
- "_GTK_APPLICATION_OBJECT_PATH",
- "Contents of the _GTK_APPLICATION_OBJECT_PATH property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_GTK_WINDOW_OBJECT_PATH] =
- g_param_spec_string ("gtk-window-object-path",
- "_GTK_WINDOW_OBJECT_PATH",
- "Contents of the _GTK_WINDOW_OBJECT_PATH property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_GTK_APP_MENU_OBJECT_PATH] =
- g_param_spec_string ("gtk-app-menu-object-path",
- "_GTK_APP_MENU_OBJECT_PATH",
- "Contents of the _GTK_APP_MENU_OBJECT_PATH property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_GTK_MENUBAR_OBJECT_PATH] =
- g_param_spec_string ("gtk-menubar-object-path",
- "_GTK_MENUBAR_OBJECT_PATH",
- "Contents of the _GTK_MENUBAR_OBJECT_PATH property of this window",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_ON_ALL_WORKSPACES] =
- g_param_spec_boolean ("on-all-workspaces",
- "On all workspaces",
- "Whether the window is set to appear on all workspaces",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, PROP_LAST, obj_props);
-
- window_signals[WORKSPACE_CHANGED] =
- g_signal_new ("workspace-changed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- window_signals[FOCUS] =
- g_signal_new ("focus",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- window_signals[RAISED] =
- g_signal_new ("raised",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- window_signals[UNMANAGING] =
- g_signal_new ("unmanaging",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- window_signals[UNMANAGED] =
- g_signal_new ("unmanaged",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- /**
- * MetaWindow::position-changed:
- * @window: a #MetaWindow
- *
- * This is emitted when the position of a window might
- * have changed. Specifically, this is emitted when the
- * position of the toplevel window has changed, or when
- * the position of the client window has changed.
- */
- window_signals[POSITION_CHANGED] =
- g_signal_new ("position-changed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- /**
- * MetaWindow::shown:
- * @window: a #MetaWindow
- *
- * This is emitted after a window has been shown.
- */
- window_signals[SHOWN] =
- g_signal_new ("shown",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-
- /**
- * MetaWindow::size-changed:
- * @window: a #MetaWindow
- *
- * This is emitted when the size of a window might
- * have changed. Specifically, this is emitted when the
- * size of the toplevel window has changed, or when the
- * size of the client window has changed.
- */
- window_signals[SIZE_CHANGED] =
- g_signal_new ("size-changed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-}
-
-static void
-meta_window_init (MetaWindow *self)
-{
- self->stamp = next_window_stamp++;
- meta_prefs_add_listener (prefs_changed_callback, self);
-}
-
-static gboolean
-is_desktop_or_dock_foreach (MetaWindow *window,
- void *data)
-{
- gboolean *result = data;
-
- *result =
- window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK ||
- window->skip_from_window_list;
- if (*result)
- return FALSE; /* stop as soon as we find one */
- else
- return TRUE;
-}
-
-/* window is the window that's newly mapped provoking
- * the possible change
- */
-static void
-maybe_leave_show_desktop_mode (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- gboolean is_desktop_or_dock;
-
- if (!workspace_manager->active_workspace->showing_desktop)
- return;
-
- /* If the window is a transient for the dock or desktop, don't
- * leave show desktop mode when the window opens. That's
- * so you can e.g. hide all windows, manipulate a file on
- * the desktop via a dialog, then unshow windows again.
- */
- is_desktop_or_dock = FALSE;
- is_desktop_or_dock_foreach (window,
- &is_desktop_or_dock);
-
- meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach,
- &is_desktop_or_dock);
-
- if (!is_desktop_or_dock)
- {
- meta_workspace_manager_minimize_all_on_active_workspace_except (workspace_manager,
- window);
- meta_workspace_manager_unshow_desktop (workspace_manager);
- }
-}
-
-gboolean
-meta_window_should_attach_to_parent (MetaWindow *window)
-{
- MetaWindow *parent;
-
- if (!meta_prefs_get_attach_modal_dialogs () ||
- window->type != META_WINDOW_MODAL_DIALOG)
- return FALSE;
-
- parent = meta_window_get_transient_for (window);
- if (!parent)
- return FALSE;
-
- switch (parent->type)
- {
- case META_WINDOW_NORMAL:
- case META_WINDOW_DIALOG:
- case META_WINDOW_MODAL_DIALOG:
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
-static gboolean
-client_window_should_be_mapped (MetaWindow *window)
-{
-#ifdef HAVE_WAYLAND
- if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
- !meta_wayland_surface_get_buffer (window->surface))
- return FALSE;
-#endif
-
- return !window->shaded;
-}
-
-static void
-sync_client_window_mapped (MetaWindow *window)
-{
- gboolean should_be_mapped = client_window_should_be_mapped (window);
-
- g_return_if_fail (!window->override_redirect);
-
- if (window->mapped == should_be_mapped)
- return;
-
- window->mapped = should_be_mapped;
-
- if (window->mapped)
- META_WINDOW_GET_CLASS (window)->map (window);
- else
- META_WINDOW_GET_CLASS (window)->unmap (window);
-}
-
-static gboolean
-meta_window_update_flatpak_id (MetaWindow *window,
- uint32_t pid)
-{
- g_autoptr(GKeyFile) key_file = NULL;
- g_autofree char *info_filename = NULL;
-
- g_return_val_if_fail (pid != 0, FALSE);
- g_return_val_if_fail (window->sandboxed_app_id == NULL, FALSE);
-
- key_file = g_key_file_new ();
- info_filename = g_strdup_printf ("/proc/%u/root/.flatpak-info", pid);
-
- if (!g_key_file_load_from_file (key_file, info_filename, G_KEY_FILE_NONE, NULL))
- return FALSE;
-
- window->sandboxed_app_id = g_key_file_get_string (key_file, "Application", "name", NULL);
-
- return TRUE;
-}
-
-static gboolean
-meta_window_update_snap_id (MetaWindow *window,
- uint32_t pid)
-{
- g_autofree char *security_label_filename = NULL;
- g_autofree char *security_label_contents = NULL;
- gsize i, security_label_contents_size = 0;
- char *contents_start;
- char *contents_end;
- char *sandboxed_app_id;
-
- g_return_val_if_fail (pid != 0, FALSE);
- g_return_val_if_fail (window->sandboxed_app_id == NULL, FALSE);
-
- security_label_filename = g_strdup_printf ("/proc/%u/attr/current", pid);
-
- if (!g_file_get_contents (security_label_filename,
- &security_label_contents,
- &security_label_contents_size,
- NULL))
- return FALSE;
-
- if (!g_str_has_prefix (security_label_contents, SNAP_SECURITY_LABEL_PREFIX))
- return FALSE;
-
- /* We need to translate the security profile into the desktop-id.
- * The profile is in the form of 'snap.name-space.binary-name (current)'
- * while the desktop id will be name-space_binary-name.
- */
- security_label_contents_size -= sizeof (SNAP_SECURITY_LABEL_PREFIX) - 1;
- contents_start = security_label_contents + sizeof (SNAP_SECURITY_LABEL_PREFIX) - 1;
- contents_end = strchr (contents_start, ' ');
-
- if (contents_end)
- security_label_contents_size = contents_end - contents_start;
-
- for (i = 0; i < security_label_contents_size; ++i)
- {
- if (contents_start[i] == '.')
- contents_start[i] = '_';
- }
-
- sandboxed_app_id = g_malloc0 (security_label_contents_size + 1);
- memcpy (sandboxed_app_id, contents_start, security_label_contents_size);
-
- window->sandboxed_app_id = sandboxed_app_id;
-
- return TRUE;
-}
-
-static void
-meta_window_update_sandboxed_app_id (MetaWindow *window)
-{
- pid_t pid;
-
- g_clear_pointer (&window->sandboxed_app_id, g_free);
-
- pid = meta_window_get_pid (window);
-
- if (pid < 1)
- return;
-
- if (meta_window_update_flatpak_id (window, pid))
- return;
-
- if (meta_window_update_snap_id (window, pid))
- return;
-}
-
-static void
-meta_window_update_desc (MetaWindow *window)
-{
- g_clear_pointer (&window->desc, g_free);
-
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- window->desc = g_strdup_printf ("0x%lx", window->xwindow);
- else
- {
- guint64 small_stamp = window->stamp - G_GUINT64_CONSTANT(0x100000000);
-
- window->desc = g_strdup_printf ("W%" G_GUINT64_FORMAT , small_stamp);
- }
-}
-
-static void
-meta_window_main_monitor_changed (MetaWindow *window,
- const MetaLogicalMonitor *old)
-{
- META_WINDOW_GET_CLASS (window)->main_monitor_changed (window, old);
-
- if (old)
- g_signal_emit_by_name (window->display, "window-left-monitor",
- old->number, window);
- if (window->monitor)
- g_signal_emit_by_name (window->display, "window-entered-monitor",
- window->monitor->number, window);
-}
-
-MetaLogicalMonitor *
-meta_window_calculate_main_logical_monitor (MetaWindow *window)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaRectangle window_rect;
-
- meta_window_get_frame_rect (window, &window_rect);
- return meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager,
- &window_rect);
-}
-
-static void
-meta_window_manage (MetaWindow *window)
-{
- COGL_TRACE_BEGIN_SCOPED (MetaWindowManage,
- "Window (manage)");
-
- META_WINDOW_GET_CLASS (window)->manage (window);
-}
-
-MetaWindow *
-_meta_window_shared_new (MetaDisplay *display,
- MetaWindowClientType client_type,
- MetaWaylandSurface *surface,
- Window xwindow,
- gulong existing_wm_state,
- MetaCompEffect effect,
- XWindowAttributes *attrs)
-{
- MetaWorkspaceManager *workspace_manager = display->workspace_manager;
- MetaWindow *window;
-
- COGL_TRACE_BEGIN_SCOPED (MetaWindowSharedNew,
- "Window (new)");
-
- g_assert (attrs != NULL);
-
- meta_verbose ("attrs->map_state = %d (%s)",
- attrs->map_state,
- (attrs->map_state == IsUnmapped) ?
- "IsUnmapped" :
- (attrs->map_state == IsViewable) ?
- "IsViewable" :
- (attrs->map_state == IsUnviewable) ?
- "IsUnviewable" :
- "(unknown)");
-
- if (client_type == META_WINDOW_CLIENT_TYPE_X11 && !meta_is_wayland_compositor ())
- window = g_object_new (META_TYPE_WINDOW_X11, NULL);
-#ifdef HAVE_WAYLAND
- else if (client_type == META_WINDOW_CLIENT_TYPE_X11)
- window = g_object_new (META_TYPE_WINDOW_XWAYLAND, NULL);
- else if (client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
- window = g_object_new (META_TYPE_WINDOW_WAYLAND, NULL);
-#endif
- else
- g_assert_not_reached ();
-
- window->constructing = TRUE;
-
- window->client_type = client_type;
- window->surface = surface;
- window->xwindow = xwindow;
-
- window->display = display;
- meta_display_register_stamp (window->display, &window->stamp, window);
-
- window->workspace = NULL;
-
- window->sync_request_counter = None;
- window->sync_request_serial = 0;
- window->sync_request_timeout_id = 0;
- window->sync_request_alarm = None;
-
- meta_window_update_sandboxed_app_id (window);
- meta_window_update_desc (window);
-
- window->override_redirect = attrs->override_redirect;
-
- /* avoid tons of stack updates */
- meta_stack_freeze (window->display->stack);
-
- window->rect.x = attrs->x;
- window->rect.y = attrs->y;
- window->rect.width = attrs->width;
- window->rect.height = attrs->height;
-
- /* size_hints are the "request" */
- window->size_hints.x = attrs->x;
- window->size_hints.y = attrs->y;
- window->size_hints.width = attrs->width;
- window->size_hints.height = attrs->height;
- /* initialize the remaining size_hints as if size_hints.flags were zero */
- meta_set_normal_hints (window, NULL);
-
- /* And this is our unmaximized size */
- window->saved_rect = window->rect;
- window->unconstrained_rect = window->rect;
-
- window->depth = attrs->depth;
- window->xvisual = attrs->visual;
-
- window->title = NULL;
- window->icon = NULL;
- window->mini_icon = NULL;
-
- window->frame = NULL;
- window->has_focus = FALSE;
- window->attached_focus_window = NULL;
-
- window->maximized_horizontally = FALSE;
- window->maximized_vertically = FALSE;
- window->maximize_horizontally_after_placement = FALSE;
- window->maximize_vertically_after_placement = FALSE;
- window->minimize_after_placement = FALSE;
- window->fullscreen = FALSE;
- window->require_fully_onscreen = TRUE;
- window->require_on_single_monitor = TRUE;
- window->require_titlebar_visible = TRUE;
- window->on_all_workspaces = FALSE;
- window->on_all_workspaces_requested = FALSE;
- window->tile_mode = META_TILE_NONE;
- window->tile_monitor_number = -1;
- window->tile_hfraction = -1.;
- window->shaded = FALSE;
- window->initially_iconic = FALSE;
- window->minimized = FALSE;
- window->tab_unminimized = FALSE;
- window->iconic = FALSE;
- window->mapped = attrs->map_state != IsUnmapped;
- window->known_to_compositor = FALSE;
- window->visible_to_compositor = FALSE;
- window->pending_compositor_effect = effect;
- /* if already mapped, no need to worry about focus-on-first-time-showing */
- window->showing_for_first_time = !window->mapped;
- /* if already mapped we don't want to do the placement thing;
- * override-redirect windows are placed by the app */
- window->placed = ((window->mapped && !window->hidden) || window->override_redirect);
- window->denied_focus_and_not_transient = FALSE;
- window->unmanaging = FALSE;
- window->is_in_queues = 0;
- window->keys_grabbed = FALSE;
- window->grab_on_frame = FALSE;
- window->all_keys_grabbed = FALSE;
- window->withdrawn = FALSE;
- window->initial_workspace_set = FALSE;
- window->initial_timestamp_set = FALSE;
- window->net_wm_user_time_set = FALSE;
- window->user_time_window = None;
- window->input = TRUE;
- window->calc_placement = FALSE;
- window->shaken_loose = FALSE;
- window->have_focus_click_grab = FALSE;
- window->disable_sync = FALSE;
-
- window->unmaps_pending = 0;
- window->reparents_pending = 0;
-
- window->mwm_decorated = TRUE;
- window->mwm_border_only = FALSE;
- window->mwm_has_close_func = TRUE;
- window->mwm_has_minimize_func = TRUE;
- window->mwm_has_maximize_func = TRUE;
- window->mwm_has_move_func = TRUE;
- window->mwm_has_resize_func = TRUE;
-
- switch (client_type)
- {
- case META_WINDOW_CLIENT_TYPE_X11:
- window->decorated = TRUE;
- window->hidden = FALSE;
- break;
- case META_WINDOW_CLIENT_TYPE_WAYLAND:
- window->decorated = FALSE;
- window->hidden = TRUE;
- break;
- }
-
- window->has_close_func = TRUE;
- window->has_minimize_func = TRUE;
- window->has_maximize_func = TRUE;
- window->has_move_func = TRUE;
- window->has_resize_func = TRUE;
-
- window->has_shade_func = TRUE;
-
- window->has_fullscreen_func = TRUE;
-
- window->always_sticky = FALSE;
-
- window->skip_taskbar = FALSE;
- window->skip_pager = FALSE;
- window->skip_from_window_list = FALSE;
- window->wm_state_above = FALSE;
- window->wm_state_below = FALSE;
- window->wm_state_demands_attention = FALSE;
-
- window->res_class = NULL;
- window->res_name = NULL;
- window->role = NULL;
- window->sm_client_id = NULL;
- window->wm_client_machine = NULL;
- window->is_remote = FALSE;
- window->startup_id = NULL;
-
- window->client_pid = 0;
-
- window->xtransient_for = None;
- window->xclient_leader = None;
-
- window->type = META_WINDOW_NORMAL;
-
- window->struts = NULL;
-
- window->layer = META_LAYER_LAST; /* invalid value */
- window->stack_position = -1;
- window->initial_workspace = 0; /* not used */
- window->initial_timestamp = 0; /* not used */
-
- window->compositor_private = NULL;
-
- window->monitor = meta_window_calculate_main_logical_monitor (window);
- if (window->monitor)
- window->preferred_output_winsys_id = window->monitor->winsys_id;
- else
- window->preferred_output_winsys_id = UINT_MAX;
-
- window->tile_match = NULL;
-
- /* Assign this #MetaWindow a sequence number which can be used
- * for sorting.
- */
- window->stable_sequence = ++display->window_sequence_counter;
-
- window->opacity = 0xFF;
-
- if (window->override_redirect)
- {
- window->decorated = FALSE;
- window->always_sticky = TRUE;
- window->has_close_func = FALSE;
- window->has_shade_func = FALSE;
- window->has_move_func = FALSE;
- window->has_resize_func = FALSE;
- }
-
- window->id = meta_display_generate_window_id (display);
-
- meta_window_manage (window);
-
- if (!window->override_redirect)
- meta_window_update_icon_now (window, TRUE);
-
- if (window->initially_iconic)
- {
- /* WM_HINTS said minimized */
- window->minimized = TRUE;
- meta_verbose ("Window %s asked to start out minimized", window->desc);
- }
-
- if (existing_wm_state == IconicState)
- {
- /* WM_STATE said minimized */
- window->minimized = TRUE;
- meta_verbose ("Window %s had preexisting WM_STATE = IconicState, minimizing",
- window->desc);
-
- /* Assume window was previously placed, though perhaps it's
- * been iconic its whole life, we have no way of knowing.
- */
- window->placed = TRUE;
- }
-
- /* Apply any window attributes such as initial workspace
- * based on startup notification
- */
- meta_display_apply_startup_properties (window->display, window);
-
- /* Try to get a "launch timestamp" for the window. If the window is
- * a transient, we'd like to be able to get a last-usage timestamp
- * from the parent window. If the window has no parent, there isn't
- * much we can do...except record the current time so that any children
- * can use this time as a fallback.
- */
- if (!window->override_redirect && !window->net_wm_user_time_set) {
- /* First, maybe the app was launched with startup notification using an
- * obsolete version of the spec; use that timestamp if it exists.
- */
- if (window->initial_timestamp_set)
- /* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just
- * being recorded as a fallback for potential transients
- */
- window->net_wm_user_time = window->initial_timestamp;
- else if (window->transient_for != NULL)
- meta_window_set_user_time (window, window->transient_for->net_wm_user_time);
- else
- /* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just
- * being recorded as a fallback for potential transients
- */
- window->net_wm_user_time =
- meta_display_get_current_time_roundtrip (window->display);
- }
-
- window->attached = meta_window_should_attach_to_parent (window);
- if (window->attached)
- meta_window_recalc_features (window);
-
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK)
- {
- /* Change the default, but don't enforce this if the user
- * focuses the dock/desktop and unsticks it using key shortcuts.
- * Need to set this before adding to the workspaces so the MRU
- * lists will be updated.
- */
- window->on_all_workspaces_requested = TRUE;
- }
-
- window->on_all_workspaces = should_be_on_all_workspaces (window);
-
- /* For the workspace, first honor hints,
- * if that fails put transients with parents,
- * otherwise put window on active space
- */
-
- if (window->initial_workspace_set)
- {
- gboolean on_all_workspaces = window->on_all_workspaces;
- MetaWorkspace *workspace = NULL;
-
- if (window->initial_workspace == (int) 0xFFFFFFFF)
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Window %s is initially on all spaces",
- window->desc);
-
- /* need to set on_all_workspaces first so that it will be
- * added to all the MRU lists
- */
- window->on_all_workspaces_requested = TRUE;
-
- on_all_workspaces = TRUE;
- }
- else if (!on_all_workspaces)
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Window %s is initially on space %d",
- window->desc, window->initial_workspace);
-
- workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager,
- window->initial_workspace);
- }
-
- /* Ignore when a window requests to be placed on a non-existent workspace
- */
- if (on_all_workspaces || workspace != NULL)
- set_workspace_state (window, on_all_workspaces, workspace);
- }
-
- /* override-redirect windows are subtly different from other windows
- * with window->on_all_workspaces == TRUE. Other windows are part of
- * some workspace (so they can return to that if the flag is turned off),
- * but appear on other workspaces. override-redirect windows are part
- * of no workspace.
- */
- if (!window->override_redirect && window->workspace == NULL)
- {
- if (window->transient_for != NULL)
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Putting window %s on same workspace as parent %s",
- window->desc, window->transient_for->desc);
-
- g_warn_if_fail (!window->transient_for->override_redirect);
- set_workspace_state (window,
- window->transient_for->on_all_workspaces,
- window->transient_for->workspace);
- }
- else if (window->on_all_workspaces)
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Putting window %s on all workspaces",
- window->desc);
-
- set_workspace_state (window, TRUE, NULL);
- }
- else
- {
- meta_topic (META_DEBUG_PLACEMENT,
- "Putting window %s on active workspace",
- window->desc);
-
- set_workspace_state (window, FALSE, workspace_manager->active_workspace);
- }
-
- meta_window_update_struts (window);
- }
-
- meta_window_main_monitor_changed (window, NULL);
-
- /* Must add window to stack before doing move/resize, since the
- * window might have fullscreen size (i.e. should have been
- * fullscreen'd; acrobat is one such braindead case; it withdraws
- * and remaps its window whenever trying to become fullscreen...)
- * and thus constraints may try to auto-fullscreen it which also
- * means restacking it.
- */
- if (meta_window_is_stackable (window))
- meta_stack_add (window->display->stack,
- window);
- else if (window->override_redirect)
- window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */
-
- if (!window->override_redirect)
- {
- /* FIXME we have a tendency to set this then immediately
- * change it again.
- */
- set_wm_state (window);
- set_net_wm_state (window);
- }
-
- meta_compositor_add_window (window->display->compositor, window);
- window->known_to_compositor = TRUE;
-
- /* Sync stack changes */
- meta_stack_thaw (window->display->stack);
-
- /* Usually the we'll have queued a stack sync anyways, because we've
- * added a new frame window or restacked. But if an undecorated
- * window is mapped, already stacked in the right place, then we
- * might need to do this explicitly.
- */
- meta_stack_tracker_queue_sync_stack (window->display->stack_tracker);
-
- /* disable show desktop mode unless we're a desktop component */
- maybe_leave_show_desktop_mode (window);
-
- meta_window_queue (window, META_QUEUE_CALC_SHOWING);
- /* See bug 303284; a transient of the given window can already exist, in which
- * case we think it should probably be shown.
- */
- meta_window_foreach_transient (window,
- queue_calc_showing_func,
- NULL);
- /* See bug 334899; the window may have minimized ancestors
- * which need to be shown.
- *
- * However, we shouldn't unminimize windows here when opening
- * a new display because that breaks passing _NET_WM_STATE_HIDDEN
- * between window managers when replacing them; see bug 358042.
- *
- * And we shouldn't unminimize windows if they were initially
- * iconic.
- */
- if (!window->override_redirect &&
- !display->display_opening &&
- !window->initially_iconic)
- unminimize_window_and_all_transient_parents (window);
-
- window->constructing = FALSE;
-
- meta_display_notify_window_created (display, window);
-
- if (window->wm_state_demands_attention)
- g_signal_emit_by_name (window->display, "window-demands-attention", window);
-
- return window;
-}
-
-static gboolean
-detach_foreach_func (MetaWindow *window,
- void *data)
-{
- GList **children = data;
- MetaWindow *parent;
-
- if (window->attached)
- {
- /* Only return the immediate children of the window being unmanaged */
- parent = meta_window_get_transient_for (window);
- if (parent->unmanaging)
- *children = g_list_prepend (*children, window);
- }
-
- return TRUE;
-}
-
-void
-meta_window_unmanage (MetaWindow *window,
- guint32 timestamp)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- GList *tmp;
-
- meta_verbose ("Unmanaging %s", window->desc);
- window->unmanaging = TRUE;
-
- g_clear_handle_id (&window->unmanage_idle_id, g_source_remove);
-
- g_signal_emit (window, window_signals[UNMANAGING], 0);
-
- meta_window_free_delete_dialog (window);
-
- if (window->visible_to_compositor)
- {
- window->visible_to_compositor = FALSE;
- meta_compositor_hide_window (window->display->compositor, window,
- META_COMP_EFFECT_DESTROY);
- }
-
- meta_compositor_remove_window (window->display->compositor, window);
- window->known_to_compositor = FALSE;
-
- if (destroying_windows_disallowed > 0)
- meta_bug ("Tried to destroy window %s while destruction was not allowed",
- window->desc);
-
- meta_display_unregister_stamp (window->display, window->stamp);
-
- if (meta_prefs_get_attach_modal_dialogs ())
- {
- GList *attached_children = NULL, *iter;
-
- /* Detach any attached dialogs by unmapping and letting them
- * be remapped after @window is destroyed.
- */
- meta_window_foreach_transient (window,
- detach_foreach_func,
- &attached_children);
- for (iter = attached_children; iter; iter = iter->next)
- meta_window_unmanage (iter->data, timestamp);
- g_list_free (attached_children);
- }
-
- /* Make sure to only show window on all workspaces if requested, to
- * not confuse other window managers that may take over
- */
- if (meta_prefs_get_workspaces_only_on_primary ())
- meta_window_on_all_workspaces_changed (window);
-
- if (window->fullscreen)
- {
- MetaGroup *group;
-
- /* If the window is fullscreen, it may be forcing
- * other windows in its group to a higher layer
- */
-
- meta_stack_freeze (window->display->stack);
- group = meta_window_get_group (window);
- if (group)
- meta_group_update_layers (group);
- meta_stack_thaw (window->display->stack);
- }
-
- meta_display_remove_pending_pings_for_window (window->display, window);
-
- /* safe to do this early as group.c won't re-add to the
- * group if window->unmanaging */
- meta_window_shutdown_group (window);
-
- /* If we have the focus, focus some other window.
- * This is done first, so that if the unmap causes
- * an EnterNotify the EnterNotify will have final say
- * on what gets focused, maintaining sloppy focus
- * invariants.
- */
- if (meta_window_appears_focused (window))
- meta_window_propagate_focus_appearance (window, FALSE);
- if (window->has_focus)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing default window since we're unmanaging %s",
- window->desc);
- meta_workspace_focus_default_window (workspace_manager->active_workspace,
- window,
- timestamp);
- }
- else
- {
- meta_topic (META_DEBUG_FOCUS,
- "Unmanaging window %s which doesn't currently have focus",
- window->desc);
- }
-
- g_assert (window->display->focus_window != window);
-
- if (window->struts)
- {
- g_slist_free_full (window->struts, g_free);
- window->struts = NULL;
-
- meta_topic (META_DEBUG_WORKAREA,
- "Unmanaging window %s which has struts, so invalidating work areas",
- window->desc);
- invalidate_work_areas (window);
- }
-
- g_clear_handle_id (&window->sync_request_timeout_id, g_source_remove);
-
- if (window->display->grab_window == window)
- meta_display_end_grab_op (window->display, timestamp);
-
- g_assert (window->display->grab_window != window);
-
- if (window->maximized_horizontally || window->maximized_vertically)
- unmaximize_window_before_freeing (window);
-
- meta_window_unqueue (window, META_QUEUE_CALC_SHOWING |
- META_QUEUE_MOVE_RESIZE |
- META_QUEUE_UPDATE_ICON);
-
- set_workspace_state (window, FALSE, NULL);
-
- g_assert (window->workspace == NULL);
-
-#ifndef G_DISABLE_CHECKS
- tmp = workspace_manager->workspaces;
- while (tmp != NULL)
- {
- MetaWorkspace *workspace = tmp->data;
-
- g_assert (g_list_find (workspace->windows, window) == NULL);
- g_assert (g_list_find (workspace->mru_list, window) == NULL);
-
- tmp = tmp->next;
- }
-#endif
-
- if (window->monitor)
- {
- const MetaLogicalMonitor *old = window->monitor;
-
- window->monitor = NULL;
- meta_window_main_monitor_changed (window, old);
- }
-
- if (meta_window_is_in_stack (window))
- meta_stack_remove (window->display->stack, window);
-
- /* If an undecorated window is being withdrawn, that will change the
- * stack as presented to the compositing manager, without actually
- * changing the stacking order of X windows.
- */
- meta_stack_tracker_queue_sync_stack (window->display->stack_tracker);
-
- if (window->display->autoraise_window == window)
- meta_display_remove_autoraise_callback (window->display);
-
- META_WINDOW_GET_CLASS (window)->unmanage (window);
-
- meta_prefs_remove_listener (prefs_changed_callback, window);
- meta_display_queue_check_fullscreen (window->display);
-
- g_signal_emit (window, window_signals[UNMANAGED], 0);
-
- g_object_unref (window);
-}
-
-static void
-set_wm_state (MetaWindow *window)
-{
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- meta_window_x11_set_wm_state (window);
-}
-
-static void
-set_net_wm_state (MetaWindow *window)
-{
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- meta_window_x11_set_net_wm_state (window);
-}
-
-static void
-set_allowed_actions_hint (MetaWindow *window)
-{
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- meta_window_x11_set_allowed_actions_hint (window);
-}
-
-/**
- * meta_window_located_on_workspace:
- * @window: a #MetaWindow
- * @workspace: a #MetaWorkspace
- *
- * Returns: whether @window is displayed on @workspace, or whether it
- * will be displayed on all workspaces.
- */
-gboolean
-meta_window_located_on_workspace (MetaWindow *window,
- MetaWorkspace *workspace)
-{
- return (window->on_all_workspaces) || (window->workspace == workspace);
-}
-
-static gboolean
-is_minimized_foreach (MetaWindow *window,
- void *data)
-{
- gboolean *result = data;
-
- *result = window->minimized;
- if (*result)
- return FALSE; /* stop as soon as we find one */
- else
- return TRUE;
-}
-
-static gboolean
-ancestor_is_minimized (MetaWindow *window)
-{
- gboolean is_minimized;
-
- is_minimized = FALSE;
-
- meta_window_foreach_ancestor (window, is_minimized_foreach, &is_minimized);
-
- return is_minimized;
-}
-
-/**
- * meta_window_showing_on_its_workspace:
- * @window: A #MetaWindow
- *
- * Returns: %TRUE if window would be visible, if its workspace was current
- */
-gboolean
-meta_window_showing_on_its_workspace (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- gboolean showing;
- gboolean is_desktop_or_dock;
- MetaWorkspace* workspace_of_window;
-
- showing = TRUE;
-
- /* 1. See if we're minimized */
- if (window->minimized)
- showing = FALSE;
-
- /* 2. See if we're in "show desktop" mode */
- is_desktop_or_dock = FALSE;
- is_desktop_or_dock_foreach (window,
- &is_desktop_or_dock);
-
- meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach,
- &is_desktop_or_dock);
-
- if (window->on_all_workspaces)
- workspace_of_window = workspace_manager->active_workspace;
- else if (window->workspace)
- workspace_of_window = window->workspace;
- else /* This only seems to be needed for startup */
- workspace_of_window = NULL;
-
- if (showing &&
- workspace_of_window && workspace_of_window->showing_desktop &&
- !is_desktop_or_dock)
- {
- meta_verbose ("We're showing the desktop on the workspace(s) that window %s is on",
- window->desc);
- showing = FALSE;
- }
-
- /* 3. See if an ancestor is minimized (note that
- * ancestor's "mapped" field may not be up to date
- * since it's being computed in this same idle queue)
- */
-
- if (showing)
- {
- if (ancestor_is_minimized (window))
- showing = FALSE;
- }
-
- return showing;
-}
-
-gboolean
-meta_window_should_be_showing (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
-#ifdef HAVE_WAYLAND
- if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
- !meta_wayland_surface_get_buffer (window->surface))
- return FALSE;
-#endif
-
- /* Windows should be showing if they're located on the
- * active workspace and they're showing on their own workspace. */
- return (meta_window_located_on_workspace (window, workspace_manager->active_workspace) &&
- meta_window_showing_on_its_workspace (window));
-}
-
-static void
-implement_showing (MetaWindow *window,
- gboolean showing)
-{
- /* Actually show/hide the window */
- meta_verbose ("Implement showing = %d for window %s",
- showing, window->desc);
-
- /* Some windows are not stackable until being showed, so add those now. */
- if (meta_window_is_stackable (window) && !meta_window_is_in_stack (window))
- meta_stack_add (window->display->stack, window);
-
- if (!showing)
- {
- /* When we manage a new window, we normally delay placing it
- * until it is is first shown, but if we're previewing hidden
- * windows we might want to know where they are on the screen,
- * so we should place the window even if we're hiding it rather
- * than showing it.
- * Force placing windows only when they should be already mapped,
- * see #751887
- */
- if (!window->placed && client_window_should_be_mapped (window))
- meta_window_force_placement (window, FALSE);
-
- meta_window_hide (window);
- }
- else
- meta_window_show (window);
-
- if (!window->override_redirect)
- sync_client_window_mapped (window);
-}
-
-static void
-meta_window_calc_showing (MetaWindow *window)
-{
- implement_showing (window, meta_window_should_be_showing (window));
-}
-
-static guint queue_later[NUMBER_OF_QUEUES] = {0, 0, 0};
-static GSList *queue_pending[NUMBER_OF_QUEUES] = {NULL, NULL, NULL};
-
-static int
-stackcmp (gconstpointer a, gconstpointer b)
-{
- MetaWindow *aw = (gpointer) a;
- MetaWindow *bw = (gpointer) b;
-
- return meta_stack_windows_cmp (aw->display->stack,
- aw, bw);
-}
-
-static gboolean
-idle_calc_showing (gpointer data)
-{
- MetaDisplay *display = meta_get_display ();
- GSList *tmp;
- GSList *copy;
- GSList *should_show;
- GSList *should_hide;
- GSList *unplaced;
- GSList *displays;
- guint queue_index = GPOINTER_TO_INT (data);
-
- COGL_TRACE_BEGIN_SCOPED (MetaWindowCalcShowing, "Window: Calc showing");
-
- g_return_val_if_fail (queue_pending[queue_index] != NULL, FALSE);
-
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Clearing the calc_showing queue");
-
- /* Work with a copy, for reentrancy. The allowed reentrancy isn't
- * complete; destroying a window while we're in here would result in
- * badness. But it's OK to queue/unqueue calc_showings.
- */
- copy = g_slist_copy (queue_pending[queue_index]);
- g_slist_free (queue_pending[queue_index]);
- queue_pending[queue_index] = NULL;
- queue_later[queue_index] = 0;
-
- destroying_windows_disallowed += 1;
-
- /* We map windows from top to bottom and unmap from bottom to
- * top, to avoid extra expose events. The exception is
- * for unplaced windows, which have to be mapped from bottom to
- * top so placement works.
- */
- should_show = NULL;
- should_hide = NULL;
- unplaced = NULL;
- displays = NULL;
-
- COGL_TRACE_BEGIN (MetaWindowCalcShowingCalc, "Window: Calc showing (calc)");
-
- tmp = copy;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- if (!window->placed)
- unplaced = g_slist_prepend (unplaced, window);
- else if (meta_window_should_be_showing (window))
- should_show = g_slist_prepend (should_show, window);
- else
- should_hide = g_slist_prepend (should_hide, window);
-
- tmp = tmp->next;
- }
-
- /* bottom to top */
- unplaced = g_slist_sort (unplaced, stackcmp);
- should_hide = g_slist_sort (should_hide, stackcmp);
- /* top to bottom */
- should_show = g_slist_sort (should_show, stackcmp);
- should_show = g_slist_reverse (should_show);
-
- COGL_TRACE_END (MetaWindowCalcShowingCalc);
-
- COGL_TRACE_BEGIN (MetaWindowCalcShowingUnplaced,
- "Window: Calc showing (calc unplaced)");
-
- tmp = unplaced;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- meta_window_calc_showing (window);
-
- tmp = tmp->next;
- }
-
- COGL_TRACE_END (MetaWindowCalcShowingUnplaced);
-
- meta_stack_freeze (display->stack);
-
- COGL_TRACE_BEGIN (MetaWindowCalcShowingShow, "Window: Calc showing (show)");
- tmp = should_show;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- implement_showing (window, TRUE);
-
- tmp = tmp->next;
- }
- COGL_TRACE_END (MetaWindowCalcShowingShow);
-
- COGL_TRACE_BEGIN (MetaWindowCalcShowingHide, "Window: Calc showing (hide)");
- tmp = should_hide;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- implement_showing (window, FALSE);
-
- tmp = tmp->next;
- }
- COGL_TRACE_END (MetaWindowCalcShowingHide);
-
- COGL_TRACE_BEGIN (MetaWindowCalcShowingSync,
- "Window: Calc showing (sync stack)");
- meta_stack_thaw (display->stack);
- COGL_TRACE_END (MetaWindowCalcShowingSync);
-
- tmp = copy;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- /* important to set this here for reentrancy -
- * if we queue a window again while it's in "copy",
- * then queue_calc_showing will just return since
- * we are still in the calc_showing queue
- */
- window->is_in_queues &= ~META_QUEUE_CALC_SHOWING;
-
- tmp = tmp->next;
- }
-
- if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK)
- {
- /* When display->mouse_mode is false, we want to ignore
- * EnterNotify events unless they come from mouse motion. To do
- * that, we set a sentinel property on the root window if we're
- * not in mouse_mode.
- */
- tmp = should_show;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
- MetaDisplay *display = window->display;
-
- if (display->x11_display && !display->mouse_mode)
- meta_x11_display_increment_focus_sentinel (display->x11_display);
-
- tmp = tmp->next;
- }
- }
-
- g_slist_free (copy);
-
- g_slist_free (unplaced);
- g_slist_free (should_show);
- g_slist_free (should_hide);
- g_slist_free (displays);
-
- destroying_windows_disallowed -= 1;
-
- return FALSE;
-}
-
-#ifdef WITH_VERBOSE_MODE
-static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] =
- {"calc_showing", "move_resize", "update_icon"};
-#endif
-
-static void
-meta_window_unqueue (MetaWindow *window, guint queuebits)
-{
- gint queuenum;
-
- for (queuenum=0; queuenum<NUMBER_OF_QUEUES; queuenum++)
- {
- if ((queuebits & 1<<queuenum) /* they have asked to unqueue */
- &&
- (window->is_in_queues & 1<<queuenum)) /* it's in the queue */
- {
-
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Removing %s from the %s queue",
- window->desc,
- meta_window_queue_names[queuenum]);
-
- /* Note that window may not actually be in the queue
- * because it may have been in "copy" inside the idle handler
- */
- queue_pending[queuenum] = g_slist_remove (queue_pending[queuenum], window);
- window->is_in_queues &= ~(1<<queuenum);
-
- /* Okay, so maybe we've used up all the entries in the queue.
- * In that case, we should kill the function that deals with
- * the queue, because there's nothing left for it to do.
- */
- if (queue_pending[queuenum] == NULL && queue_later[queuenum] != 0)
- {
- meta_later_remove (queue_later[queuenum]);
- queue_later[queuenum] = 0;
- }
- }
- }
-}
-
-static void
-meta_window_flush_calc_showing (MetaWindow *window)
-{
- if (window->is_in_queues & META_QUEUE_CALC_SHOWING)
- {
- meta_window_unqueue (window, META_QUEUE_CALC_SHOWING);
- meta_window_calc_showing (window);
- }
-}
-
-void
-meta_window_queue (MetaWindow *window, guint queuebits)
-{
- guint queuenum;
-
- /* Easier to debug by checking here rather than in the idle */
- g_return_if_fail (!window->override_redirect || (queuebits & META_QUEUE_MOVE_RESIZE) == 0);
-
- for (queuenum=0; queuenum<NUMBER_OF_QUEUES; queuenum++)
- {
- if (queuebits & 1<<queuenum)
- {
- /* Data which varies between queues.
- * Yes, these do look a lot like associative arrays:
- * I seem to be turning into a Perl programmer.
- */
-
- const MetaLaterType window_queue_later_when[NUMBER_OF_QUEUES] =
- {
- META_LATER_CALC_SHOWING, /* CALC_SHOWING */
- META_LATER_RESIZE, /* MOVE_RESIZE */
- META_LATER_BEFORE_REDRAW /* UPDATE_ICON */
- };
-
- const GSourceFunc window_queue_later_handler[NUMBER_OF_QUEUES] =
- {
- idle_calc_showing,
- idle_move_resize,
- idle_update_icon,
- };
-
- /* If we're about to drop the window, there's no point in putting
- * it on a queue.
- */
- if (window->unmanaging)
- break;
-
- /* If the window already claims to be in that queue, there's no
- * point putting it in the queue.
- */
- if (window->is_in_queues & 1<<queuenum)
- break;
-
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Putting %s in the %s queue",
- window->desc,
- meta_window_queue_names[queuenum]);
-
- /* So, mark it as being in this queue. */
- window->is_in_queues |= 1<<queuenum;
-
- /* There's not a lot of point putting things into a queue if
- * nobody's on the other end pulling them out. Therefore,
- * let's check to see whether an idle handler exists to do
- * that. If not, we'll create one.
- */
-
- if (queue_later[queuenum] == 0)
- queue_later[queuenum] = meta_later_add
- (
- window_queue_later_when[queuenum],
- window_queue_later_handler[queuenum],
- GUINT_TO_POINTER(queuenum),
- NULL
- );
-
- /* And now we actually put it on the queue. */
- queue_pending[queuenum] = g_slist_prepend (queue_pending[queuenum],
- window);
- }
- }
-}
-
-static gboolean
-intervening_user_event_occurred (MetaWindow *window)
-{
- guint32 compare;
- MetaWindow *focus_window;
-
- focus_window = window->display->focus_window;
-
- meta_topic (META_DEBUG_STARTUP,
- "COMPARISON:\n"
- " net_wm_user_time_set : %d\n"
- " net_wm_user_time : %u\n"
- " initial_timestamp_set: %d\n"
- " initial_timestamp : %u",
- window->net_wm_user_time_set,
- window->net_wm_user_time,
- window->initial_timestamp_set,
- window->initial_timestamp);
- if (focus_window != NULL)
- {
- meta_topic (META_DEBUG_STARTUP,
- "COMPARISON (continued):\n"
- " focus_window : %s\n"
- " fw->net_wm_user_time_set : %d\n"
- " fw->net_wm_user_time : %u",
- focus_window->desc,
- focus_window->net_wm_user_time_set,
- focus_window->net_wm_user_time);
- }
-
- /* We expect the most common case for not focusing a new window
- * to be when a hint to not focus it has been set. Since we can
- * deal with that case rapidly, we use special case it--this is
- * merely a preliminary optimization. :)
- */
- if ( ((window->net_wm_user_time_set == TRUE) &&
- (window->net_wm_user_time == 0))
- ||
- ((window->initial_timestamp_set == TRUE) &&
- (window->initial_timestamp == 0)))
- {
- meta_topic (META_DEBUG_STARTUP,
- "window %s explicitly requested no focus",
- window->desc);
- return TRUE;
- }
-
- if (!(window->net_wm_user_time_set) && !(window->initial_timestamp_set))
- {
- meta_topic (META_DEBUG_STARTUP,
- "no information about window %s found",
- window->desc);
- return FALSE;
- }
-
- if (focus_window != NULL &&
- !focus_window->net_wm_user_time_set)
- {
- meta_topic (META_DEBUG_STARTUP,
- "focus window, %s, doesn't have a user time set yet!",
- window->desc);
- return FALSE;
- }
-
- /* To determine the "launch" time of an application,
- * startup-notification can set the TIMESTAMP and the
- * application (usually via its toolkit such as gtk or qt) can
- * set the _NET_WM_USER_TIME. If both are set, we need to be
- * using the newer of the two values.
- *
- * See http://bugzilla.gnome.org/show_bug.cgi?id=573922
- */
- compare = 0;
- if (window->net_wm_user_time_set &&
- window->initial_timestamp_set)
- compare =
- XSERVER_TIME_IS_BEFORE (window->net_wm_user_time,
- window->initial_timestamp) ?
- window->initial_timestamp : window->net_wm_user_time;
- else if (window->net_wm_user_time_set)
- compare = window->net_wm_user_time;
- else if (window->initial_timestamp_set)
- compare = window->initial_timestamp;
-
- if ((focus_window != NULL) &&
- XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time))
- {
- meta_topic (META_DEBUG_STARTUP,
- "window %s focus prevented by other activity; %u < %u",
- window->desc,
- compare,
- focus_window->net_wm_user_time);
- return TRUE;
- }
- else
- {
- meta_topic (META_DEBUG_STARTUP,
- "new window %s with no intervening events",
- window->desc);
- return FALSE;
- }
-}
-
-/* This function is an ugly hack. It's experimental in nature and ought to be
- * replaced by a real hint from the app to the WM if we decide the experimental
- * behavior is worthwhile. The basic idea is to get more feedback about how
- * usage scenarios of "strict" focus users and what they expect. See #326159.
- */
-static gboolean
-window_is_terminal (MetaWindow *window)
-{
- if (window == NULL || window->res_class == NULL)
- return FALSE;
-
- /*
- * Compare res_class, which is not user-settable, and thus theoretically
- * a more-reliable indication of term-ness.
- */
-
- /* gnome-terminal -- if you couldn't guess */
- if (strcmp (window->res_class, "Gnome-terminal") == 0)
- return TRUE;
- /* xterm, rxvt, aterm */
- else if (strcmp (window->res_class, "XTerm") == 0)
- return TRUE;
- /* konsole, KDE's terminal program */
- else if (strcmp (window->res_class, "Konsole") == 0)
- return TRUE;
- /* rxvt-unicode */
- else if (strcmp (window->res_class, "URxvt") == 0)
- return TRUE;
- /* eterm */
- else if (strcmp (window->res_class, "Eterm") == 0)
- return TRUE;
- /* KTerm -- some terminal not KDE based; so not like Konsole */
- else if (strcmp (window->res_class, "KTerm") == 0)
- return TRUE;
- /* Multi-gnome-terminal */
- else if (strcmp (window->res_class, "Multi-gnome-terminal") == 0)
- return TRUE;
- /* mlterm ("multi lingual terminal emulator on X") */
- else if (strcmp (window->res_class, "mlterm") == 0)
- return TRUE;
- /* Terminal -- XFCE Terminal */
- else if (strcmp (window->res_class, "Terminal") == 0)
- return TRUE;
-
- return FALSE;
-}
-
-/* This function determines what state the window should have assuming that it
- * and the focus_window have no relation
- */
-static void
-window_state_on_map (MetaWindow *window,
- gboolean *takes_focus,
- gboolean *places_on_top)
-{
- gboolean intervening_events;
-
- intervening_events = intervening_user_event_occurred (window);
-
- *takes_focus = !intervening_events;
- *places_on_top = *takes_focus;
-
- /* don't initially focus windows that are intended to not accept
- * focus
- */
- if (!meta_window_is_focusable (window))
- {
- *takes_focus = FALSE;
- return;
- }
-
- /* Terminal usage may be different; some users intend to launch
- * many apps in quick succession or to just view things in the new
- * window while still interacting with the terminal. In that case,
- * apps launched from the terminal should not take focus. This
- * isn't quite the same as not allowing focus to transfer from
- * terminals due to new window map, but the latter is a much easier
- * approximation to enforce so we do that.
- */
- if (*takes_focus &&
- meta_prefs_get_focus_new_windows () == G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT &&
- !window->display->allow_terminal_deactivation &&
- window_is_terminal (window->display->focus_window) &&
- !meta_window_is_ancestor_of_transient (window->display->focus_window,
- window))
- {
- meta_topic (META_DEBUG_FOCUS,
- "focus_window is terminal; not focusing new window.");
- *takes_focus = FALSE;
- *places_on_top = FALSE;
- }
-
- switch (window->type)
- {
- case META_WINDOW_UTILITY:
- case META_WINDOW_TOOLBAR:
- *takes_focus = FALSE;
- *places_on_top = FALSE;
- break;
- case META_WINDOW_DOCK:
- case META_WINDOW_DESKTOP:
- case META_WINDOW_SPLASHSCREEN:
- case META_WINDOW_MENU:
- /* override redirect types: */
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_COMBO:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- /* don't focus any of these; places_on_top may be irrelevant for some of
- * these (e.g. dock)--but you never know--the focus window might also be
- * of the same type in some weird situation...
- */
- *takes_focus = FALSE;
- break;
- case META_WINDOW_NORMAL:
- case META_WINDOW_DIALOG:
- case META_WINDOW_MODAL_DIALOG:
- /* The default is correct for these */
- break;
- }
-}
-
-static gboolean
-windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
-{
- MetaRectangle w1rect, w2rect;
- meta_window_get_frame_rect (w1, &w1rect);
- meta_window_get_frame_rect (w2, &w2rect);
- return meta_rectangle_overlap (&w1rect, &w2rect);
-}
-
-/* Returns whether a new window would be covered by any
- * existing window on the same workspace that is set
- * to be "above" ("always on top"). A window that is not
- * set "above" would be underneath the new window anyway.
- *
- * We take "covered" to mean even partially covered, but
- * some people might prefer entirely covered. I think it
- * is more useful to behave this way if any part of the
- * window is covered, because a partial coverage could be
- * (say) ninety per cent and almost indistinguishable from total.
- */
-static gboolean
-window_would_be_covered (const MetaWindow *newbie)
-{
- MetaWorkspace *workspace = meta_window_get_workspace ((MetaWindow *)newbie);
- GList *tmp, *windows;
-
- windows = meta_workspace_list_windows (workspace);
-
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *w = tmp->data;
-
- if (w->wm_state_above && w != newbie)
- {
- /* We have found a window that is "above". Perhaps it overlaps. */
- if (windows_overlap (w, newbie))
- {
- g_list_free (windows); /* clean up... */
- return TRUE; /* yes, it does */
- }
- }
-
- tmp = tmp->next;
- }
-
- g_list_free (windows);
- return FALSE; /* none found */
-}
-
-void
-meta_window_force_placement (MetaWindow *window,
- gboolean force_move)
-{
- MetaMoveResizeFlags flags;
-
- if (window->placed)
- return;
-
- /* We have to recalc the placement here since other windows may
- * have been mapped/placed since we last did constrain_position
- */
-
- /* calc_placement is an efficiency hack to avoid
- * multiple placement calculations before we finally
- * show the window.
- */
- window->calc_placement = TRUE;
-
- flags = META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION;
- if (force_move)
- flags |= META_MOVE_RESIZE_FORCE_MOVE;
-
- meta_window_move_resize_internal (window,
- flags,
- META_GRAVITY_NORTH_WEST,
- window->unconstrained_rect);
- window->calc_placement = FALSE;
-
- /* don't ever do the initial position constraint thing again.
- * This is toggled here so that initially-iconified windows
- * still get placed when they are ultimately shown.
- */
- window->placed = TRUE;
-
- /* Don't want to accidentally reuse the fact that we had been denied
- * focus in any future constraints unless we're denied focus again.
- */
- window->denied_focus_and_not_transient = FALSE;
-}
-
-static void
-meta_window_show (MetaWindow *window)
-{
- gboolean did_show;
- gboolean takes_focus_on_map;
- gboolean place_on_top_on_map;
- gboolean needs_stacking_adjustment;
- MetaWindow *focus_window;
- gboolean notify_demands_attention = FALSE;
- MetaDisplay *display = window->display;
-
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Showing window %s, shaded: %d iconic: %d placed: %d",
- window->desc, window->shaded, window->iconic, window->placed);
-
- focus_window = window->display->focus_window; /* May be NULL! */
- did_show = FALSE;
- window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map);
- needs_stacking_adjustment = FALSE;
-
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Window %s %s focus on map, and %s place on top on map.",
- window->desc,
- takes_focus_on_map ? "does" : "does not",
- place_on_top_on_map ? "does" : "does not");
-
- /* Now, in some rare cases we should *not* put a new window on top.
- * These cases include certain types of windows showing for the first
- * time, and any window which would be covered because of another window
- * being set "above" ("always on top").
- *
- * FIXME: Although "place_on_top_on_map" and "takes_focus_on_map" are
- * generally based on the window type, there is a special case when the
- * focus window is a terminal for them both to be false; this should
- * probably rather be a term in the "if" condition below.
- */
-
- if ( focus_window != NULL && window->showing_for_first_time &&
- ( (!place_on_top_on_map && !takes_focus_on_map) ||
- window_would_be_covered (window) )
- ) {
- if (!meta_window_is_ancestor_of_transient (focus_window, window))
- {
- needs_stacking_adjustment = TRUE;
- if (!window->placed)
- window->denied_focus_and_not_transient = TRUE;
- }
- }
-
- if (!window->placed)
- {
- if (window->monitor &&
- meta_prefs_get_auto_maximize() &&
- window->showing_for_first_time &&
- window->has_maximize_func)
- {
- MetaRectangle work_area;
- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
- /* Automaximize windows that map with a size > MAX_UNMAXIMIZED_WINDOW_AREA of the work area */
- if (window->rect.width * window->rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA)
- {
- window->maximize_horizontally_after_placement = TRUE;
- window->maximize_vertically_after_placement = TRUE;
- }
- }
- meta_window_force_placement (window, FALSE);
- }
-
- if (needs_stacking_adjustment)
- {
- gboolean overlap;
-
- /* This window isn't getting focus on map. We may need to do some
- * special handing with it in regards to
- * - the stacking of the window
- * - the MRU position of the window
- * - the demands attention setting of the window
- *
- * Firstly, set the flag so we don't give the window focus anyway
- * and confuse people.
- */
-
- takes_focus_on_map = FALSE;
-
- overlap = windows_overlap (window, focus_window);
-
- /* We want alt tab to go to the denied-focus window */
- ensure_mru_position_after (window, focus_window);
-
- /* We don't want the denied-focus window to obscure the focus
- * window, and if we're in both click-to-focus mode and
- * raise-on-click mode then we want to maintain the invariant
- * that MRU order == stacking order. The need for this if
- * comes from the fact that in sloppy/mouse focus the focus
- * window may not overlap other windows and also can be
- * considered "below" them; this combination means that
- * placing the denied-focus window "below" the focus window
- * in the stack when it doesn't overlap it confusingly places
- * that new window below a lot of other windows.
- */
- if (overlap ||
- (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
- meta_prefs_get_raise_on_click ()))
- meta_window_stack_just_below (window, focus_window);
-
- /* If the window will be obscured by the focus window, then the
- * user might not notice the window appearing so set the
- * demands attention hint.
- *
- * We set the hint ourselves rather than calling
- * meta_window_set_demands_attention() because that would cause
- * a recalculation of overlap, and a call to set_net_wm_state()
- * which we are going to call ourselves here a few lines down.
- */
- if (overlap)
- {
- if (!window->wm_state_demands_attention)
- {
- window->wm_state_demands_attention = TRUE;
- notify_demands_attention = TRUE;
- }
- }
- }
-
- if (window->hidden)
- {
- meta_stack_freeze (window->display->stack);
- window->hidden = FALSE;
- meta_stack_thaw (window->display->stack);
- did_show = TRUE;
- }
-
- if (window->iconic)
- {
- window->iconic = FALSE;
- set_wm_state (window);
- }
-
- if (!window->visible_to_compositor)
- {
- MetaCompEffect effect = META_COMP_EFFECT_NONE;
-
- window->visible_to_compositor = TRUE;
-
- switch (window->pending_compositor_effect)
- {
- case META_COMP_EFFECT_CREATE:
- case META_COMP_EFFECT_UNMINIMIZE:
- effect = window->pending_compositor_effect;
- break;
- case META_COMP_EFFECT_NONE:
- case META_COMP_EFFECT_DESTROY:
- case META_COMP_EFFECT_MINIMIZE:
- break;
- }
-
- meta_compositor_show_window (window->display->compositor,
- window, effect);
- window->pending_compositor_effect = META_COMP_EFFECT_NONE;
- }
-
- /* We don't want to worry about all cases from inside
- * implement_showing(); we only want to worry about focus if this
- * window has not been shown before.
- */
- if (window->showing_for_first_time)
- {
- window->showing_for_first_time = FALSE;
- if (takes_focus_on_map)
- {
- guint32 timestamp;
-
- timestamp = meta_display_get_current_time_roundtrip (window->display);
-
- meta_window_focus (window, timestamp);
- }
- else if (display->x11_display)
- {
- /* Prevent EnterNotify events in sloppy/mouse focus from
- * erroneously focusing the window that had been denied
- * focus. FIXME: This introduces a race; I have a couple
- * ideas for a better way to accomplish the same thing, but
- * they're more involved so do it this way for now.
- */
- meta_x11_display_increment_focus_sentinel (display->x11_display);
- }
- }
-
- set_net_wm_state (window);
-
- if (did_show && window->struts)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Mapped window %s with struts, so invalidating work areas",
- window->desc);
- invalidate_work_areas (window);
- }
-
- if (did_show)
- meta_display_queue_check_fullscreen (window->display);
-
- /*
- * Now that we have shown the window, we no longer want to consider the
- * initial timestamp in any subsequent deliberations whether to focus this
- * window or not, so clear the flag.
- *
- * See http://bugzilla.gnome.org/show_bug.cgi?id=573922
- */
- window->initial_timestamp_set = FALSE;
-
- if (notify_demands_attention)
- {
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DEMANDS_ATTENTION]);
- g_signal_emit_by_name (window->display, "window-demands-attention",
- window);
- }
-
- if (did_show)
- g_signal_emit (window, window_signals[SHOWN], 0);
-}
-
-static void
-meta_window_hide (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- gboolean did_hide;
-
- meta_topic (META_DEBUG_WINDOW_STATE,
- "Hiding window %s", window->desc);
-
- if (window->visible_to_compositor)
- {
- MetaCompEffect effect = META_COMP_EFFECT_NONE;
-
- window->visible_to_compositor = FALSE;
-
- switch (window->pending_compositor_effect)
- {
- case META_COMP_EFFECT_CREATE:
- case META_COMP_EFFECT_UNMINIMIZE:
- case META_COMP_EFFECT_NONE:
- break;
- case META_COMP_EFFECT_DESTROY:
- case META_COMP_EFFECT_MINIMIZE:
- effect = window->pending_compositor_effect;
- break;
- }
-
- meta_compositor_hide_window (window->display->compositor, window, effect);
- window->pending_compositor_effect = META_COMP_EFFECT_NONE;
- }
-
- did_hide = FALSE;
-
- if (!window->hidden)
- {
- meta_stack_freeze (window->display->stack);
- window->hidden = TRUE;
- meta_stack_thaw (window->display->stack);
-
- did_hide = TRUE;
- }
-
- if (!window->iconic)
- {
- window->iconic = TRUE;
- set_wm_state (window);
- }
-
- set_net_wm_state (window);
-
- if (did_hide && window->struts)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Unmapped window %s with struts, so invalidating work areas",
- window->desc);
- invalidate_work_areas (window);
- }
-
- if (window->has_focus)
- {
- MetaWindow *not_this_one = NULL;
- MetaWorkspace *my_workspace = meta_window_get_workspace (window);
- guint32 timestamp = meta_display_get_current_time_roundtrip (window->display);
-
- /*
- * If this window is modal, passing the not_this_one window to
- * _focus_default_window() makes the focus to be given to this window's
- * ancestor. This can only be the case if the window is on the currently
- * active workspace; when it is not, we need to pass in NULL, so as to
- * focus the default window for the active workspace (this scenario
- * arises when we are switching workspaces).
- * We also pass in NULL if we are in the process of hiding all non-desktop
- * windows to avoid unexpected changes to the stacking order.
- */
- if (my_workspace == workspace_manager->active_workspace &&
- !my_workspace->showing_desktop)
- not_this_one = window;
-
- meta_workspace_focus_default_window (workspace_manager->active_workspace,
- not_this_one,
- timestamp);
- }
-
- if (did_hide)
- meta_display_queue_check_fullscreen (window->display);
-}
-
-static gboolean
-queue_calc_showing_func (MetaWindow *window,
- void *data)
-{
- meta_window_queue(window, META_QUEUE_CALC_SHOWING);
- return TRUE;
-}
-
-void
-meta_window_minimize (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- if (!window->minimized)
- {
- window->minimized = TRUE;
- window->pending_compositor_effect = META_COMP_EFFECT_MINIMIZE;
- meta_window_queue(window, META_QUEUE_CALC_SHOWING);
-
- meta_window_foreach_transient (window,
- queue_calc_showing_func,
- NULL);
-
- if (window->has_focus)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing default window due to minimization of focus window %s",
- window->desc);
- }
- else
- {
- meta_topic (META_DEBUG_FOCUS,
- "Minimizing window %s which doesn't have the focus",
- window->desc);
- }
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINIMIZED]);
- }
-}
-
-void
-meta_window_unminimize (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- if (window->minimized)
- {
- window->minimized = FALSE;
- window->pending_compositor_effect = META_COMP_EFFECT_UNMINIMIZE;
- meta_window_queue(window, META_QUEUE_CALC_SHOWING);
-
- meta_window_foreach_transient (window,
- queue_calc_showing_func,
- NULL);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINIMIZED]);
- }
-}
-
-static void
-ensure_size_hints_satisfied (MetaRectangle *rect,
- const XSizeHints *size_hints)
-{
- int minw, minh, maxw, maxh; /* min/max width/height */
- int basew, baseh, winc, hinc; /* base width/height, width/height increment */
- int extra_width, extra_height;
-
- minw = size_hints->min_width; minh = size_hints->min_height;
- maxw = size_hints->max_width; maxh = size_hints->max_height;
- basew = size_hints->base_width; baseh = size_hints->base_height;
- winc = size_hints->width_inc; hinc = size_hints->height_inc;
-
- /* First, enforce min/max size constraints */
- rect->width = CLAMP (rect->width, minw, maxw);
- rect->height = CLAMP (rect->height, minh, maxh);
-
- /* Now, verify size increment constraints are satisfied, or make them be */
- extra_width = (rect->width - basew) % winc;
- extra_height = (rect->height - baseh) % hinc;
-
- rect->width -= extra_width;
- rect->height -= extra_height;
-
- /* Adjusting width/height down, as done above, may violate minimum size
- * constraints, so one last fix.
- */
- if (rect->width < minw)
- rect->width += ((minw - rect->width)/winc + 1)*winc;
- if (rect->height < minh)
- rect->height += ((minh - rect->height)/hinc + 1)*hinc;
-}
-
-static void
-meta_window_save_rect (MetaWindow *window)
-{
- if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED_SIDE_BY_SIDE (window) || window->fullscreen))
- {
- /* save size/pos as appropriate args for move_resize */
- if (!window->maximized_horizontally)
- {
- window->saved_rect.x = window->rect.x;
- window->saved_rect.width = window->rect.width;
- }
- if (!window->maximized_vertically)
- {
- window->saved_rect.y = window->rect.y;
- window->saved_rect.height = window->rect.height;
- }
- }
-}
-
-void
-meta_window_maximize_internal (MetaWindow *window,
- MetaMaximizeFlags directions,
- MetaRectangle *saved_rect)
-{
- /* At least one of the two directions ought to be set */
- gboolean maximize_horizontally, maximize_vertically;
- maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL;
- maximize_vertically = directions & META_MAXIMIZE_VERTICAL;
- g_assert (maximize_horizontally || maximize_vertically);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Maximizing %s%s",
- window->desc,
- maximize_horizontally && maximize_vertically ? "" :
- maximize_horizontally ? " horizontally" :
- maximize_vertically ? " vertically" : "BUGGGGG");
-
- if (saved_rect != NULL)
- window->saved_rect = *saved_rect;
- else
- meta_window_save_rect (window);
-
- if (maximize_horizontally && maximize_vertically)
- window->saved_maximize = TRUE;
-
- window->maximized_horizontally =
- window->maximized_horizontally || maximize_horizontally;
- window->maximized_vertically =
- window->maximized_vertically || maximize_vertically;
-
- /* Update the edge constraints */
- update_edge_constraints (window);
-
- meta_window_recalc_features (window);
- set_net_wm_state (window);
-
- if (window->monitor && window->monitor->in_fullscreen)
- meta_display_queue_check_fullscreen (window->display);
-
- g_object_freeze_notify (G_OBJECT (window));
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]);
- g_object_thaw_notify (G_OBJECT (window));
-}
-
-void
-meta_window_maximize (MetaWindow *window,
- MetaMaximizeFlags directions)
-{
- MetaRectangle *saved_rect = NULL;
- gboolean maximize_horizontally, maximize_vertically;
-
- g_return_if_fail (!window->override_redirect);
-
- /* At least one of the two directions ought to be set */
- maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL;
- maximize_vertically = directions & META_MAXIMIZE_VERTICAL;
- g_assert (maximize_horizontally || maximize_vertically);
-
- /* Only do something if the window isn't already maximized in the
- * given direction(s).
- */
- if ((maximize_horizontally && !window->maximized_horizontally) ||
- (maximize_vertically && !window->maximized_vertically))
- {
- if (window->shaded && maximize_vertically)
- {
- /* Shading sucks anyway; I'm not adding a timestamp argument
- * to this function just for this niche usage & corner case.
- */
- guint32 timestamp =
- meta_display_get_current_time_roundtrip (window->display);
- meta_window_unshade (window, timestamp);
- }
-
- /* if the window hasn't been placed yet, we'll maximize it then
- */
- if (!window->placed)
- {
- window->maximize_horizontally_after_placement =
- window->maximize_horizontally_after_placement ||
- maximize_horizontally;
- window->maximize_vertically_after_placement =
- window->maximize_vertically_after_placement ||
- maximize_vertically;
- return;
- }
-
- if (window->tile_mode != META_TILE_NONE)
- {
- saved_rect = &window->saved_rect;
-
- window->maximized_vertically = FALSE;
- window->tile_mode = META_TILE_NONE;
- }
-
- meta_window_maximize_internal (window,
- directions,
- saved_rect);
-
- MetaRectangle old_frame_rect, old_buffer_rect;
-
- meta_window_get_frame_rect (window, &old_frame_rect);
- meta_window_get_buffer_rect (window, &old_buffer_rect);
-
- meta_compositor_size_change_window (window->display->compositor, window,
- META_SIZE_CHANGE_MAXIMIZE,
- &old_frame_rect, &old_buffer_rect);
-
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_STATE_CHANGED),
- META_GRAVITY_NORTH_WEST,
- window->unconstrained_rect);
- }
-}
-
-/**
- * meta_window_get_maximized:
- * @window: a #MetaWindow
- *
- * Gets the current maximization state of the window, as combination
- * of the %META_MAXIMIZE_HORIZONTAL and %META_MAXIMIZE_VERTICAL flags;
- *
- * Return value: current maximization state
- */
-MetaMaximizeFlags
-meta_window_get_maximized (MetaWindow *window)
-{
- return ((window->maximized_horizontally ? META_MAXIMIZE_HORIZONTAL : 0) |
- (window->maximized_vertically ? META_MAXIMIZE_VERTICAL : 0));
-}
-
-/**
- * meta_window_is_fullscreen:
- * @window: a #MetaWindow
- *
- * Return value: %TRUE if the window is currently fullscreen
- */
-gboolean
-meta_window_is_fullscreen (MetaWindow *window)
-{
- return window->fullscreen;
-}
-
-/**
- * meta_window_is_screen_sized:
- * @window: A #MetaWindow
- *
- * Return value: %TRUE if the window is occupies the
- * the whole screen (all monitors).
- */
-gboolean
-meta_window_is_screen_sized (MetaWindow *window)
-{
- MetaRectangle window_rect;
- int screen_width, screen_height;
-
- meta_display_get_size (window->display, &screen_width, &screen_height);
- meta_window_get_frame_rect (window, &window_rect);
-
- if (window_rect.x == 0 && window_rect.y == 0 &&
- window_rect.width == screen_width && window_rect.height == screen_height)
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * meta_window_is_monitor_sized:
- * @window: a #MetaWindow
- *
- * Return value: %TRUE if the window is occupies an entire monitor or
- * the whole screen.
- */
-gboolean
-meta_window_is_monitor_sized (MetaWindow *window)
-{
- if (!window->monitor)
- return FALSE;
-
- if (window->fullscreen)
- return TRUE;
-
- if (meta_window_is_screen_sized (window))
- return TRUE;
-
- if (window->override_redirect)
- {
- MetaRectangle window_rect, monitor_rect;
-
- meta_window_get_frame_rect (window, &window_rect);
- meta_display_get_monitor_geometry (window->display, window->monitor->number, &monitor_rect);
-
- if (meta_rectangle_equal (&window_rect, &monitor_rect))
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * meta_window_is_on_primary_monitor:
- * @window: a #MetaWindow
- *
- * Return value: %TRUE if the window is on the primary monitor
- */
-gboolean
-meta_window_is_on_primary_monitor (MetaWindow *window)
-{
- g_return_val_if_fail (window->monitor, FALSE);
-
- return window->monitor->is_primary;
-}
-
-static void
-meta_window_get_tile_fraction (MetaWindow *window,
- MetaTileMode tile_mode,
- double *fraction)
-{
- MetaWindow *tile_match;
-
- /* Make sure the tile match is up-to-date and matches the
- * passed in mode rather than the current state
- */
- tile_match = meta_window_find_tile_match (window, tile_mode);
-
- if (tile_mode == META_TILE_NONE)
- *fraction = -1.;
- else if (tile_mode == META_TILE_MAXIMIZED)
- *fraction = 1.;
- else if (tile_match)
- *fraction = 1. - tile_match->tile_hfraction;
- else if (META_WINDOW_TILED_SIDE_BY_SIDE (window))
- {
- if (window->tile_mode != tile_mode)
- *fraction = 1. - window->tile_hfraction;
- else
- *fraction = window->tile_hfraction;
- }
- else
- *fraction = .5;
-}
-
-static void
-meta_window_update_tile_fraction (MetaWindow *window,
- int new_w,
- int new_h)
-{
- MetaWindow *tile_match = window->tile_match;
- MetaRectangle work_area;
-
- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
- return;
-
- meta_window_get_work_area_for_monitor (window,
- window->tile_monitor_number,
- &work_area);
- window->tile_hfraction = (double)new_w / work_area.width;
-
- if (tile_match && window->display->grab_window == window)
- meta_window_tile (tile_match, tile_match->tile_mode);
-}
-
-static void
-update_edge_constraints (MetaWindow *window)
-{
- switch (window->tile_mode)
- {
- case META_TILE_NONE:
- window->edge_constraints.top = META_EDGE_CONSTRAINT_NONE;
- window->edge_constraints.right = META_EDGE_CONSTRAINT_NONE;
- window->edge_constraints.bottom = META_EDGE_CONSTRAINT_NONE;
- window->edge_constraints.left = META_EDGE_CONSTRAINT_NONE;
- break;
-
- case META_TILE_MAXIMIZED:
- window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR;
- break;
-
- case META_TILE_LEFT:
- window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR;
-
- if (window->tile_match)
- window->edge_constraints.right = META_EDGE_CONSTRAINT_WINDOW;
- else
- window->edge_constraints.right = META_EDGE_CONSTRAINT_NONE;
-
- window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR;
- break;
-
- case META_TILE_RIGHT:
- window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR;
-
- if (window->tile_match)
- window->edge_constraints.left = META_EDGE_CONSTRAINT_WINDOW;
- else
- window->edge_constraints.left = META_EDGE_CONSTRAINT_NONE;
- break;
- }
-
- /* h/vmaximize also modify the edge constraints */
- if (window->maximized_vertically)
- {
- window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR;
- }
-
- if (window->maximized_horizontally)
- {
- window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR;
- window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR;
- }
-}
-
-void
-meta_window_untile (MetaWindow *window)
-{
- window->tile_monitor_number =
- window->saved_maximize ? window->monitor->number
- : -1;
- window->tile_mode =
- window->saved_maximize ? META_TILE_MAXIMIZED
- : META_TILE_NONE;
-
- if (window->saved_maximize)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
- else
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
-}
-
-void
-meta_window_tile (MetaWindow *window,
- MetaTileMode tile_mode)
-{
- MetaMaximizeFlags directions;
- MetaRectangle old_frame_rect, old_buffer_rect;
-
- meta_window_get_tile_fraction (window, tile_mode, &window->tile_hfraction);
- window->tile_mode = tile_mode;
-
- /* Don't do anything if no tiling is requested */
- if (window->tile_mode == META_TILE_NONE)
- {
- window->tile_monitor_number = -1;
- return;
- }
- else if (window->tile_monitor_number < 0)
- {
- window->tile_monitor_number = window->monitor->number;
- }
-
- if (window->tile_mode == META_TILE_MAXIMIZED)
- directions = META_MAXIMIZE_BOTH;
- else
- directions = META_MAXIMIZE_VERTICAL;
-
- meta_window_maximize_internal (window, directions, NULL);
- meta_display_update_tile_preview (window->display, FALSE);
-
- /* Setup the edge constraints */
- update_edge_constraints (window);
-
- meta_window_get_frame_rect (window, &old_frame_rect);
- meta_window_get_buffer_rect (window, &old_buffer_rect);
-
- meta_compositor_size_change_window (window->display->compositor, window,
- META_SIZE_CHANGE_MAXIMIZE,
- &old_frame_rect, &old_buffer_rect);
-
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_STATE_CHANGED),
- META_GRAVITY_NORTH_WEST,
- window->unconstrained_rect);
-
- if (window->frame)
- meta_frame_queue_draw (window->frame);
-}
-
-MetaTileMode
-meta_window_get_tile_mode (MetaWindow *window)
-{
- return window->tile_mode;
-}
-
-void
-meta_window_restore_tile (MetaWindow *window,
- MetaTileMode mode,
- int width,
- int height)
-{
- meta_window_update_tile_fraction (window, width, height);
- meta_window_tile (window, mode);
-}
-
-static gboolean
-meta_window_can_tile_maximized (MetaWindow *window)
-{
- return window->has_maximize_func;
-}
-
-gboolean
-meta_window_can_tile_side_by_side (MetaWindow *window)
-{
- int monitor;
- MetaRectangle tile_area;
- MetaRectangle client_rect;
-
- if (!meta_window_can_tile_maximized (window))
- return FALSE;
-
- monitor = meta_display_get_current_monitor (window->display);
- meta_window_get_work_area_for_monitor (window, monitor, &tile_area);
-
- /* Do not allow tiling in portrait orientation */
- if (tile_area.height > tile_area.width)
- return FALSE;
-
- tile_area.width /= 2;
-
- meta_window_frame_rect_to_client_rect (window, &tile_area, &client_rect);
-
- return client_rect.width >= window->size_hints.min_width &&
- client_rect.height >= window->size_hints.min_height;
-}
-
-static void
-unmaximize_window_before_freeing (MetaWindow *window)
-{
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Unmaximizing %s just before freeing",
- window->desc);
-
- window->maximized_horizontally = FALSE;
- window->maximized_vertically = FALSE;
-
- if (window->withdrawn) /* See bug #137185 */
- {
- window->rect = window->saved_rect;
- set_net_wm_state (window);
- }
-#ifdef HAVE_WAYLAND
- else if (!meta_is_wayland_compositor ())
- {
- /* Do NOT update net_wm_state: this screen is closing,
- * it likely will be managed by another window manager
- * that will need the current _NET_WM_STATE atoms.
- * Moreover, it will need to know the unmaximized geometry,
- * therefore move_resize the window to saved_rect here
- * before closing it. */
- meta_window_move_resize_frame (window,
- FALSE,
- window->saved_rect.x,
- window->saved_rect.y,
- window->saved_rect.width,
- window->saved_rect.height);
- }
-#endif
-}
-
-static void
-meta_window_maybe_apply_size_hints (MetaWindow *window,
- MetaRectangle *target_rect)
-{
- meta_window_frame_rect_to_client_rect (window, target_rect, target_rect);
- ensure_size_hints_satisfied (target_rect, &window->size_hints);
- meta_window_client_rect_to_frame_rect (window, target_rect, target_rect);
-}
-
-void
-meta_window_unmaximize (MetaWindow *window,
- MetaMaximizeFlags directions)
-{
- gboolean unmaximize_horizontally, unmaximize_vertically;
-
- g_return_if_fail (!window->override_redirect);
-
- /* At least one of the two directions ought to be set */
- unmaximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL;
- unmaximize_vertically = directions & META_MAXIMIZE_VERTICAL;
- g_assert (unmaximize_horizontally || unmaximize_vertically);
-
- if (unmaximize_horizontally && unmaximize_vertically)
- window->saved_maximize = FALSE;
-
- /* Only do something if the window isn't already maximized in the
- * given direction(s).
- */
- if ((unmaximize_horizontally && window->maximized_horizontally) ||
- (unmaximize_vertically && window->maximized_vertically))
- {
- MetaRectangle *desired_rect;
- MetaRectangle target_rect;
- MetaRectangle work_area;
- MetaRectangle old_frame_rect, old_buffer_rect;
- gboolean has_target_size;
-
- meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
- meta_window_get_frame_rect (window, &old_frame_rect);
- meta_window_get_buffer_rect (window, &old_buffer_rect);
-
- if (unmaximize_vertically)
- window->tile_mode = META_TILE_NONE;
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Unmaximizing %s%s",
- window->desc,
- unmaximize_horizontally && unmaximize_vertically ? "" :
- unmaximize_horizontally ? " horizontally" :
- unmaximize_vertically ? " vertically" : "BUGGGGG");
-
- window->maximized_horizontally =
- window->maximized_horizontally && !unmaximize_horizontally;
- window->maximized_vertically =
- window->maximized_vertically && !unmaximize_vertically;
-
- /* Update the edge constraints */
- update_edge_constraints (window);
-
- /* recalc_features() will eventually clear the cached frame
- * extents, but we need the correct frame extents in the code below,
- * so invalidate the old frame extents manually up front.
- */
- meta_window_frame_size_changed (window);
-
- desired_rect = &window->saved_rect;
-
- /* Unmaximize to the saved_rect position in the direction(s)
- * being unmaximized.
- */
- target_rect = old_frame_rect;
-
- /* Avoid unmaximizing to "almost maximized" size when the previous size
- * is greater then 80% of the work area use MAX_UNMAXIMIZED_WINDOW_AREA of the work area as upper limit
- * while maintaining the aspect ratio.
- */
- if (unmaximize_horizontally && unmaximize_vertically &&
- desired_rect->width * desired_rect->height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA)
- {
- if (desired_rect->width > desired_rect->height)
- {
- float aspect = (float)desired_rect->height / (float)desired_rect->width;
- desired_rect->width = MAX (work_area.width * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_width);
- desired_rect->height = MAX (desired_rect->width * aspect, window->size_hints.min_height);
- }
- else
- {
- float aspect = (float)desired_rect->width / (float)desired_rect->height;
- desired_rect->height = MAX (work_area.height * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_height);
- desired_rect->width = MAX (desired_rect->height * aspect, window->size_hints.min_width);
- }
- }
-
- if (unmaximize_horizontally)
- {
- target_rect.x = desired_rect->x;
- target_rect.width = desired_rect->width;
- }
- if (unmaximize_vertically)
- {
- target_rect.y = desired_rect->y;
- target_rect.height = desired_rect->height;
- }
-
- /* Window's size hints may have changed while maximized, making
- * saved_rect invalid. #329152
- * Do not enforce limits, if no previous 'saved_rect' has been stored.
- */
- has_target_size = (target_rect.width > 0 && target_rect.height > 0);
- if (has_target_size)
- meta_window_maybe_apply_size_hints (window, &target_rect);
-
- meta_compositor_size_change_window (window->display->compositor, window,
- META_SIZE_CHANGE_UNMAXIMIZE,
- &old_frame_rect, &old_buffer_rect);
-
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_STATE_CHANGED |
- META_MOVE_RESIZE_UNMAXIMIZE),
- META_GRAVITY_NORTH_WEST,
- target_rect);
-
- /* When we unmaximize, if we're doing a mouse move also we could
- * get the window suddenly jumping to the upper left corner of
- * the workspace, since that's where it was when the grab op
- * started. So we need to update the grab anchor position.
- */
- if (meta_grab_op_is_moving (window->display->grab_op) &&
- window->display->grab_window == window)
- {
- window->display->grab_anchor_window_pos = target_rect;
- }
-
- meta_window_recalc_features (window);
- set_net_wm_state (window);
- if (!window->monitor->in_fullscreen)
- meta_display_queue_check_fullscreen (window->display);
- }
-
- g_object_freeze_notify (G_OBJECT (window));
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]);
- g_object_thaw_notify (G_OBJECT (window));
-}
-
-void
-meta_window_make_above (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_window_set_above (window, TRUE);
- meta_window_raise (window);
-}
-
-void
-meta_window_unmake_above (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_window_set_above (window, FALSE);
- meta_window_raise (window);
-}
-
-static void
-meta_window_set_above (MetaWindow *window,
- gboolean new_value)
-{
- new_value = new_value != FALSE;
- if (new_value == window->wm_state_above)
- return;
-
- window->wm_state_above = new_value;
- meta_window_update_layer (window);
- set_net_wm_state (window);
- meta_window_frame_size_changed (window);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ABOVE]);
-}
-
-void
-meta_window_make_fullscreen_internal (MetaWindow *window)
-{
- if (!window->fullscreen)
- {
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Fullscreening %s", window->desc);
-
- if (window->shaded)
- {
- /* Shading sucks anyway; I'm not adding a timestamp argument
- * to this function just for this niche usage & corner case.
- */
- guint32 timestamp =
- meta_display_get_current_time_roundtrip (window->display);
- meta_window_unshade (window, timestamp);
- }
-
- window->saved_rect_fullscreen = window->rect;
-
- window->fullscreen = TRUE;
-
- meta_stack_freeze (window->display->stack);
-
- meta_window_raise (window);
- meta_stack_thaw (window->display->stack);
-
- meta_window_recalc_features (window);
- set_net_wm_state (window);
-
- /* For the auto-minimize feature, if we fail to get focus */
- meta_display_queue_check_fullscreen (window->display);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_FULLSCREEN]);
- }
-}
-
-void
-meta_window_make_fullscreen (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- if (!window->fullscreen)
- {
- MetaRectangle old_frame_rect, old_buffer_rect;
-
- meta_window_get_frame_rect (window, &old_frame_rect);
- meta_window_get_buffer_rect (window, &old_buffer_rect);
-
- meta_compositor_size_change_window (window->display->compositor,
- window, META_SIZE_CHANGE_FULLSCREEN,
- &old_frame_rect, &old_buffer_rect);
-
- meta_window_make_fullscreen_internal (window);
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_STATE_CHANGED),
- META_GRAVITY_NORTH_WEST,
- window->unconstrained_rect);
- }
-}
-
-void
-meta_window_unmake_fullscreen (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- if (window->fullscreen)
- {
- MetaRectangle old_frame_rect, old_buffer_rect, target_rect;
- gboolean has_target_size;
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Unfullscreening %s", window->desc);
-
- window->fullscreen = FALSE;
- target_rect = window->saved_rect_fullscreen;
-
- meta_window_frame_size_changed (window);
- meta_window_get_frame_rect (window, &old_frame_rect);
- meta_window_get_buffer_rect (window, &old_buffer_rect);
-
- /* Window's size hints may have changed while maximized, making
- * saved_rect invalid. #329152
- * Do not enforce limits, if no previous 'saved_rect' has been stored.
- */
- has_target_size = (target_rect.width > 0 && target_rect.height > 0);
- if (has_target_size)
- meta_window_maybe_apply_size_hints (window, &target_rect);
-
- /* Need to update window->has_resize_func before we move_resize()
- */
- meta_window_recalc_features (window);
- set_net_wm_state (window);
-
- meta_compositor_size_change_window (window->display->compositor,
- window, META_SIZE_CHANGE_UNFULLSCREEN,
- &old_frame_rect, &old_buffer_rect);
-
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_STATE_CHANGED |
- META_MOVE_RESIZE_UNFULLSCREEN),
- META_GRAVITY_NORTH_WEST,
- target_rect);
-
- meta_display_queue_check_fullscreen (window->display);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_FULLSCREEN]);
- }
-}
-
-static void
-meta_window_clear_fullscreen_monitors (MetaWindow *window)
-{
- window->fullscreen_monitors.top = NULL;
- window->fullscreen_monitors.bottom = NULL;
- window->fullscreen_monitors.left = NULL;
- window->fullscreen_monitors.right = NULL;
-}
-
-void
-meta_window_update_fullscreen_monitors (MetaWindow *window,
- MetaLogicalMonitor *top,
- MetaLogicalMonitor *bottom,
- MetaLogicalMonitor *left,
- MetaLogicalMonitor *right)
-{
- if (top && bottom && left && right)
- {
- window->fullscreen_monitors.top = top;
- window->fullscreen_monitors.bottom = bottom;
- window->fullscreen_monitors.left = left;
- window->fullscreen_monitors.right = right;
- }
- else
- {
- meta_window_clear_fullscreen_monitors (window);
- }
-
- if (window->fullscreen)
- {
- meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
- }
-}
-
-gboolean
-meta_window_has_fullscreen_monitors (MetaWindow *window)
-{
- return window->fullscreen_monitors.top != NULL;
-}
-
-void
-meta_window_adjust_fullscreen_monitor_rect (MetaWindow *window,
- MetaRectangle *monitor_rect)
-{
- MetaWindowClass *window_class = META_WINDOW_GET_CLASS (window);
-
- if (window_class->adjust_fullscreen_monitor_rect)
- window_class->adjust_fullscreen_monitor_rect (window, monitor_rect);
-}
-
-void
-meta_window_shade (MetaWindow *window,
- guint32 timestamp)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Shading %s", window->desc);
- if (!window->shaded)
- {
- window->shaded = TRUE;
-
- meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
- meta_window_frame_size_changed (window);
-
- /* After queuing the calc showing, since _focus flushes it,
- * and we need to focus the frame
- */
- meta_topic (META_DEBUG_FOCUS,
- "Re-focusing window %s after shading it",
- window->desc);
- meta_window_focus (window, timestamp);
-
- set_net_wm_state (window);
- }
-}
-
-void
-meta_window_unshade (MetaWindow *window,
- guint32 timestamp)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Unshading %s", window->desc);
- if (window->shaded)
- {
- window->shaded = FALSE;
- meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
- meta_window_frame_size_changed (window);
-
- /* focus the window */
- meta_topic (META_DEBUG_FOCUS,
- "Focusing window %s after unshading it",
- window->desc);
- meta_window_focus (window, timestamp);
-
- set_net_wm_state (window);
- }
-}
-
-static gboolean
-unminimize_func (MetaWindow *window,
- void *data)
-{
- meta_window_unminimize (window);
- return TRUE;
-}
-
-static void
-unminimize_window_and_all_transient_parents (MetaWindow *window)
-{
- meta_window_unminimize (window);
- meta_window_foreach_ancestor (window, unminimize_func, NULL);
-}
-
-void
-meta_window_activate_full (MetaWindow *window,
- guint32 timestamp,
- MetaClientType source_indication,
- MetaWorkspace *workspace)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- gboolean allow_workspace_switch;
-
- if (window->unmanaging)
- {
- g_warning ("Trying to activate unmanaged window '%s'", window->desc);
- return;
- }
-
- meta_topic (META_DEBUG_FOCUS,
- "_NET_ACTIVE_WINDOW message sent for %s at time %u "
- "by client type %u.",
- window->desc, timestamp, source_indication);
-
- allow_workspace_switch = (timestamp != 0);
- if (timestamp != 0 &&
- XSERVER_TIME_IS_BEFORE (timestamp, window->display->last_user_time))
- {
- meta_topic (META_DEBUG_FOCUS,
- "last_user_time (%u) is more recent; ignoring "
- " _NET_ACTIVE_WINDOW message.",
- window->display->last_user_time);
- meta_window_set_demands_attention(window);
- return;
- }
-
- if (timestamp == 0)
- timestamp = meta_display_get_current_time_roundtrip (window->display);
-
- meta_window_set_user_time (window, timestamp);
-
- /* disable show desktop mode unless we're a desktop component */
- maybe_leave_show_desktop_mode (window);
-
- /* Get window on current or given workspace */
- if (workspace == NULL)
- workspace = workspace_manager->active_workspace;
-
- /* For non-transient windows, we just set up a pulsing indicator,
- rather than move windows or workspaces.
- See http://bugzilla.gnome.org/show_bug.cgi?id=482354 */
- if (window->transient_for == NULL &&
- !allow_workspace_switch &&
- !meta_window_located_on_workspace (window, workspace))
- {
- meta_window_set_demands_attention (window);
- /* We've marked it as demanding, don't need to do anything else. */
- return;
- }
- else if (window->transient_for != NULL)
- {
- /* Move transients to current workspace - preference dialogs should appear over
- the source window. */
- meta_window_change_workspace (window, workspace);
- }
-
- if (window->shaded)
- meta_window_unshade (window, timestamp);
-
- unminimize_window_and_all_transient_parents (window);
-
- if (meta_prefs_get_raise_on_click () ||
- source_indication == META_CLIENT_TYPE_PAGER)
- meta_window_raise (window);
-
- meta_topic (META_DEBUG_FOCUS,
- "Focusing window %s due to activation",
- window->desc);
-
- if (meta_window_located_on_workspace (window, workspace))
- meta_window_focus (window, timestamp);
- else
- meta_workspace_activate_with_focus (window->workspace, window, timestamp);
-
- meta_window_check_alive (window, timestamp);
-}
-
-/* This function exists since most of the functionality in window_activate
- * is useful for Mutter, but Mutter shouldn't need to specify a client
- * type for itself. ;-)
- */
-void
-meta_window_activate (MetaWindow *window,
- guint32 timestamp)
-{
- g_return_if_fail (!window->override_redirect);
-
- /* We're not really a pager, but the behavior we want is the same as if
- * we were such. If we change the pager behavior later, we could revisit
- * this and just add extra flags to window_activate.
- */
- meta_window_activate_full (window, timestamp, META_CLIENT_TYPE_PAGER, NULL);
-}
-
-void
-meta_window_activate_with_workspace (MetaWindow *window,
- guint32 timestamp,
- MetaWorkspace *workspace)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_window_activate_full (window, timestamp, META_CLIENT_TYPE_APPLICATION, workspace);
-}
-
-/**
- * meta_window_updates_are_frozen:
- * @window: a #MetaWindow
- *
- * Gets whether the compositor should be updating the window contents;
- * window content updates may be frozen at client request by setting
- * an odd value in the extended _NET_WM_SYNC_REQUEST_COUNTER counter
- * by the window manager during a resize operation while waiting for
- * the client to redraw.
- *
- * Return value: %TRUE if updates are currently frozen
- */
-gboolean
-meta_window_updates_are_frozen (MetaWindow *window)
-{
- return META_WINDOW_GET_CLASS (window)->are_updates_frozen (window);
-}
-
-static void
-meta_window_reposition (MetaWindow *window)
-{
- meta_window_move_resize_internal (window,
- (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION),
- META_GRAVITY_NORTH_WEST,
- window->rect);
-}
-
-static gboolean
-maybe_move_attached_window (MetaWindow *window,
- void *data)
-{
- if (window->hidden)
- return G_SOURCE_CONTINUE;
-
- if (meta_window_is_attached_dialog (window) ||
- meta_window_get_placement_rule (window))
- meta_window_reposition (window);
-
- return G_SOURCE_CONTINUE;
-}
-
-/**
- * meta_window_get_monitor:
- * @window: a #MetaWindow
- *
- * Gets index of the monitor that this window is on.
- *
- * Return Value: The index of the monitor in the screens monitor list, or -1
- * if the window has been recently unmanaged and does not have a monitor.
- */
-int
-meta_window_get_monitor (MetaWindow *window)
-{
- if (!window->monitor)
- return -1;
-
- return window->monitor->number;
-}
-
-MetaLogicalMonitor *
-meta_window_get_main_logical_monitor (MetaWindow *window)
-{
- return window->monitor;
-}
-
-static MetaLogicalMonitor *
-find_monitor_by_winsys_id (MetaWindow *window,
- uint64_t winsys_id)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- GList *logical_monitors, *l;
-
- logical_monitors =
- meta_monitor_manager_get_logical_monitors (monitor_manager);
-
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
-
- if (logical_monitor->winsys_id == winsys_id)
- return logical_monitor;
- }
-
- return NULL;
-}
-
-/* This is called when the monitor setup has changed. The window->monitor
- * reference is still "valid", but refer to the previous monitor setup */
-void
-meta_window_update_for_monitors_changed (MetaWindow *window)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- const MetaLogicalMonitor *old, *new;
-
- if (meta_window_has_fullscreen_monitors (window))
- meta_window_clear_fullscreen_monitors (window);
-
- if (window->override_redirect || window->type == META_WINDOW_DESKTOP)
- {
- meta_window_update_monitor (window,
- META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE);
- goto out;
- }
-
- old = window->monitor;
-
- /* Try the preferred output first */
- new = find_monitor_by_winsys_id (window, window->preferred_output_winsys_id);
-
- /* Otherwise, try to find the old output on a new monitor */
- if (old && !new)
- new = find_monitor_by_winsys_id (window, old->winsys_id);
-
- /* Fall back to primary if everything else failed */
- if (!new)
- new = meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
-
- if (window->tile_mode != META_TILE_NONE)
- {
- if (new)
- window->tile_monitor_number = new->number;
- else
- window->tile_monitor_number = -1;
- }
-
- if (new && old)
- {
- /* This will eventually reach meta_window_update_monitor that
- * will send leave/enter-monitor events. The old != new monitor
- * check will always fail (due to the new logical_monitors set) so
- * we will always send the events, even if the new and old monitor
- * index is the same. That is right, since the enumeration of the
- * monitors changed and the same index could be refereing
- * to a different monitor. */
- meta_window_move_between_rects (window,
- META_MOVE_RESIZE_FORCE_UPDATE_MONITOR,
- &old->rect,
- &new->rect);
- }
- else
- {
- meta_window_update_monitor (window,
- META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE);
- }
-
-out:
- g_assert (!window->monitor ||
- g_list_find (meta_monitor_manager_get_logical_monitors (monitor_manager),
- window->monitor));
-}
-
-void
-meta_window_update_monitor (MetaWindow *window,
- MetaWindowUpdateMonitorFlags flags)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- const MetaLogicalMonitor *old;
-
- old = window->monitor;
- META_WINDOW_GET_CLASS (window)->update_main_monitor (window, flags);
- if (old != window->monitor)
- {
- meta_window_on_all_workspaces_changed (window);
-
- /* If workspaces only on primary and we moved back to primary due to a user action,
- * ensure that the window is now in that workspace. We do this because while
- * the window is on a non-primary monitor it is always visible, so it would be
- * very jarring if it disappeared when it crossed the monitor border.
- * The one time we want it to both change to the primary monitor and a non-active
- * workspace is when dropping the window on some other workspace thumbnail directly.
- * That should be handled by explicitly moving the window before changing the
- * workspace.
- */
- if (meta_prefs_get_workspaces_only_on_primary () &&
- flags & META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP &&
- meta_window_is_on_primary_monitor (window) &&
- workspace_manager->active_workspace != window->workspace)
- meta_window_change_workspace (window, workspace_manager->active_workspace);
-
- meta_window_main_monitor_changed (window, old);
-
- /* If we're changing monitors, we need to update the has_maximize_func flag,
- * as the working area has changed. */
- meta_window_recalc_features (window);
- }
-}
-
-void
-meta_window_move_resize_internal (MetaWindow *window,
- MetaMoveResizeFlags flags,
- MetaGravity gravity,
- MetaRectangle frame_rect)
-{
- /* The rectangle here that's passed in *always* in "frame rect"
- * coordinates. That means the position of the frame's visible bounds,
- * with x and y being absolute (root window) coordinates.
- *
- * For an X11 framed window, the client window's server rectangle is
- * inset from this rectangle by the frame's visible borders, and the
- * frame window's server rectangle is outset by the invisible borders.
- *
- * For an X11 unframed window, the rectangle here directly matches
- * the server's rectangle, since the visible and invisible borders
- * are both 0.
- *
- * For an X11 CSD window, the client window's server rectangle is
- * outset from this rectagle by the client-specified frame extents.
- *
- * For a Wayland window, this rectangle can simply be sent directly
- * to the client.
- */
-
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- gboolean did_placement;
- MetaRectangle unconstrained_rect;
- MetaRectangle constrained_rect;
- MetaRectangle temporary_rect;
- int rel_x = 0;
- int rel_y = 0;
- MetaMoveResizeResultFlags result = 0;
- gboolean moved_or_resized = FALSE;
- MetaWindowUpdateMonitorFlags update_monitor_flags;
-
- g_return_if_fail (!window->override_redirect);
-
- /* The action has to be a move, a resize or the wayland client
- * acking our choice of size.
- */
- g_assert (flags & (META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION |
- META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE));
-
- did_placement = !window->placed && window->calc_placement;
-
- /* We don't need it in the idle queue anymore. */
- meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE);
-
- if ((flags & META_MOVE_RESIZE_RESIZE_ACTION) && (flags & META_MOVE_RESIZE_MOVE_ACTION))
- {
- /* We're both moving and resizing. Just use the passed in rect. */
- unconstrained_rect = frame_rect;
- }
- else if ((flags & META_MOVE_RESIZE_RESIZE_ACTION))
- {
- /* If this is only a resize, then ignore the position given in
- * the parameters and instead calculate the new position from
- * resizing the old rectangle with the given gravity. */
- meta_rectangle_resize_with_gravity (&window->rect,
- &unconstrained_rect,
- gravity,
- frame_rect.width,
- frame_rect.height);
- }
- else if ((flags & META_MOVE_RESIZE_MOVE_ACTION))
- {
- /* If this is only a move, then ignore the passed in size and
- * just use the existing size of the window. */
- unconstrained_rect.x = frame_rect.x;
- unconstrained_rect.y = frame_rect.y;
- unconstrained_rect.width = window->rect.width;
- unconstrained_rect.height = window->rect.height;
- }
- else if ((flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE))
- {
- /* This is a Wayland buffer acking our size. The new rect is
- * just the existing one we have. Ignore the passed-in rect
- * completely. */
- unconstrained_rect = window->rect;
- }
- else
- g_assert_not_reached ();
-
- constrained_rect = unconstrained_rect;
- temporary_rect = window->rect;
- if (flags & (META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION) &&
- !(flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE) &&
- !(flags & (META_MOVE_RESIZE_UNMAXIMIZE | META_MOVE_RESIZE_UNFULLSCREEN)) &&
- window->monitor)
- {
- MetaRectangle old_rect;
- meta_window_get_frame_rect (window, &old_rect);
-
- meta_window_constrain (window,
- flags,
- gravity,
- &old_rect,
- &constrained_rect,
- &temporary_rect,
- &rel_x,
- &rel_y);
- }
- else if (window->placement.rule)
- {
- rel_x = window->placement.pending.rel_x;
- rel_y = window->placement.pending.rel_y;
- }
-
- /* If we did placement, then we need to save the position that the window
- * was placed at to make sure that meta_window_move_resize_now places the
- * window correctly.
- */
- if (did_placement)
- {
- unconstrained_rect.x = constrained_rect.x;
- unconstrained_rect.y = constrained_rect.y;
- }
-
- /* Do the protocol-specific move/resize logic */
- META_WINDOW_GET_CLASS (window)->move_resize_internal (window,
- gravity,
- unconstrained_rect,
- constrained_rect,
- temporary_rect,
- rel_x,
- rel_y,
- flags, &result);
-
- if (result & META_MOVE_RESIZE_RESULT_MOVED)
- {
- moved_or_resized = TRUE;
- g_signal_emit (window, window_signals[POSITION_CHANGED], 0);
- }
-
- if (result & META_MOVE_RESIZE_RESULT_RESIZED)
- {
- moved_or_resized = TRUE;
- g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
- }
-
- if (moved_or_resized || did_placement)
- window->unconstrained_rect = unconstrained_rect;
-
- if ((moved_or_resized ||
- did_placement ||
- (result & META_MOVE_RESIZE_RESULT_STATE_CHANGED) != 0) &&
- window->known_to_compositor)
- {
- meta_compositor_sync_window_geometry (window->display->compositor,
- window,
- did_placement);
- }
-
- update_monitor_flags = META_WINDOW_UPDATE_MONITOR_FLAGS_NONE;
- if (flags & META_MOVE_RESIZE_USER_ACTION)
- update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP;
- if (flags & META_MOVE_RESIZE_FORCE_UPDATE_MONITOR)
- update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE;
-
- if (window->monitor)
- {
- uint64_t old_output_winsys_id;
-
- old_output_winsys_id = window->monitor->winsys_id;
-
- meta_window_update_monitor (window, update_monitor_flags);
-
- if (old_output_winsys_id != window->monitor->winsys_id &&
- flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_USER_ACTION)
- window->preferred_output_winsys_id = window->monitor->winsys_id;
- }
- else
- {
- meta_window_update_monitor (window, update_monitor_flags);
- }
-
- if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds)
- {
- cairo_region_destroy (window->frame_bounds);
- window->frame_bounds = NULL;
- }
-
- meta_window_foreach_transient (window, maybe_move_attached_window, NULL);
-
- meta_stack_update_window_tile_matches (window->display->stack,
- workspace_manager->active_workspace);
-}
-
-/**
- * meta_window_move_frame:
- * @window: a #MetaWindow
- * @user_op: bool to indicate whether or not this is a user operation
- * @root_x_nw: desired x pos
- * @root_y_nw: desired y pos
- *
- * Moves the window to the desired location on window's assigned
- * workspace, using the northwest edge of the frame as the reference,
- * instead of the actual window's origin, but only if a frame is present.
- * Otherwise, acts identically to meta_window_move().
- */
-void
-meta_window_move_frame (MetaWindow *window,
- gboolean user_op,
- int root_x_nw,
- int root_y_nw)
-{
- MetaMoveResizeFlags flags;
- MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
-
- g_return_if_fail (!window->override_redirect);
-
- flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_MOVE_ACTION;
- meta_window_move_resize_internal (window, flags, META_GRAVITY_NORTH_WEST, rect);
-}
-
-static void
-meta_window_move_between_rects (MetaWindow *window,
- MetaMoveResizeFlags move_resize_flags,
- const MetaRectangle *old_area,
- const MetaRectangle *new_area)
-{
- int rel_x, rel_y;
- double scale_x, scale_y;
-
- if (old_area)
- {
- rel_x = window->unconstrained_rect.x - old_area->x;
- rel_y = window->unconstrained_rect.y - old_area->y;
- scale_x = (double)new_area->width / old_area->width;
- scale_y = (double)new_area->height / old_area->height;
- }
- else
- {
- rel_x = rel_y = scale_x = scale_y = 0;
- }
-
- window->unconstrained_rect.x = new_area->x + rel_x * scale_x;
- window->unconstrained_rect.y = new_area->y + rel_y * scale_y;
- window->saved_rect.x = window->unconstrained_rect.x;
- window->saved_rect.y = window->unconstrained_rect.y;
-
- meta_window_move_resize_internal (window,
- move_resize_flags |
- META_MOVE_RESIZE_MOVE_ACTION |
- META_MOVE_RESIZE_RESIZE_ACTION,
- META_GRAVITY_NORTH_WEST,
- window->unconstrained_rect);
-}
-
-/**
- * meta_window_move_resize_frame:
- * @window: a #MetaWindow
- * @user_op: bool to indicate whether or not this is a user operation
- * @root_x_nw: new x
- * @root_y_nw: new y
- * @w: desired width
- * @h: desired height
- *
- * Resizes the window so that its outer bounds (including frame)
- * fit within the given rect
- */
-void
-meta_window_move_resize_frame (MetaWindow *window,
- gboolean user_op,
- int root_x_nw,
- int root_y_nw,
- int w,
- int h)
-{
- MetaMoveResizeFlags flags;
- MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
-
- g_return_if_fail (!window->override_redirect);
-
- flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION;
-
- meta_window_move_resize_internal (window, flags, META_GRAVITY_NORTH_WEST, rect);
-}
-
-/**
- * meta_window_move_to_monitor:
- * @window: a #MetaWindow
- * @monitor: desired monitor index
- *
- * Moves the window to the monitor with index @monitor, keeping
- * the relative position of the window's top left corner.
- */
-void
-meta_window_move_to_monitor (MetaWindow *window,
- int monitor)
-{
- MetaRectangle old_area, new_area;
-
- if (window->tile_mode != META_TILE_NONE)
- window->tile_monitor_number = monitor;
-
- meta_window_get_work_area_for_monitor (window,
- window->monitor->number,
- &old_area);
- meta_window_get_work_area_for_monitor (window,
- monitor,
- &new_area);
-
- if (window->unconstrained_rect.width == 0 ||
- window->unconstrained_rect.height == 0 ||
- !meta_rectangle_overlap (&window->unconstrained_rect, &old_area))
- {
- meta_window_move_between_rects (window, 0, NULL, &new_area);
- }
- else
- {
- if (monitor == window->monitor->number)
- return;
-
- meta_window_move_between_rects (window, 0, &old_area, &new_area);
- }
-
- window->preferred_output_winsys_id = window->monitor->winsys_id;
-
- if (window->fullscreen || window->override_redirect)
- meta_display_queue_check_fullscreen (window->display);
-}
-
-static void
-adjust_size_for_tile_match (MetaWindow *window,
- int *new_w,
- int *new_h)
-{
- MetaRectangle work_area, rect;
- MetaWindow *tile_match = window->tile_match;
-
- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window) || !tile_match)
- return;
-
- meta_window_get_work_area_for_monitor (window, window->tile_monitor_number, &work_area);
-
- /* Make sure the resize does not break minimum sizes */
- rect = work_area;
- rect.width = *new_w;
-
- meta_window_frame_rect_to_client_rect (window, &rect, &rect);
- *new_w += MAX(0, window->size_hints.min_width - rect.width);
-
- /* Make sure we're not resizing the tile match below its min width */
- rect = work_area;
- rect.width = work_area.width - *new_w;
-
- meta_window_frame_rect_to_client_rect (tile_match, &rect, &rect);
- *new_w -= MAX(0, tile_match->size_hints.min_width - rect.width);
-}
-
-void
-meta_window_resize_frame_with_gravity (MetaWindow *window,
- gboolean user_op,
- int w,
- int h,
- MetaGravity gravity)
-{
- MetaMoveResizeFlags flags;
- MetaRectangle rect;
-
- rect.width = w;
- rect.height = h;
-
- if (user_op)
- {
- /* When resizing in-tandem with a tile match, we need to respect
- * its minimum width
- */
- if (window->display->grab_window == window)
- adjust_size_for_tile_match (window, &w, &h);
- meta_window_update_tile_fraction (window, w, h);
- }
-
- flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_RESIZE_ACTION;
- meta_window_move_resize_internal (window, flags, gravity, rect);
-}
-
-static void
-meta_window_move_resize_now (MetaWindow *window)
-{
- meta_window_move_resize_frame (window, FALSE,
- window->unconstrained_rect.x,
- window->unconstrained_rect.y,
- window->unconstrained_rect.width,
- window->unconstrained_rect.height);
-}
-
-static gboolean
-idle_move_resize (gpointer data)
-{
- GSList *tmp;
- GSList *copy;
- guint queue_index = GPOINTER_TO_INT (data);
-
- meta_topic (META_DEBUG_GEOMETRY, "Clearing the move_resize queue");
-
- /* Work with a copy, for reentrancy. The allowed reentrancy isn't
- * complete; destroying a window while we're in here would result in
- * badness. But it's OK to queue/unqueue move_resizes.
- */
- copy = g_slist_copy (queue_pending[queue_index]);
- g_slist_free (queue_pending[queue_index]);
- queue_pending[queue_index] = NULL;
- queue_later[queue_index] = 0;
-
- destroying_windows_disallowed += 1;
-
- tmp = copy;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- /* As a side effect, sets window->move_resize_queued = FALSE */
- meta_window_move_resize_now (window);
-
- tmp = tmp->next;
- }
-
- g_slist_free (copy);
-
- destroying_windows_disallowed -= 1;
-
- return FALSE;
-}
-
-void
-meta_window_get_gravity_position (MetaWindow *window,
- MetaGravity gravity,
- int *root_x,
- int *root_y)
-{
- MetaRectangle frame_extents;
- int w, h;
- int x, y;
-
- w = window->rect.width;
- h = window->rect.height;
-
- if (gravity == META_GRAVITY_STATIC)
- {
- frame_extents = window->rect;
- if (window->frame)
- {
- frame_extents.x = window->frame->rect.x + window->frame->child_x;
- frame_extents.y = window->frame->rect.y + window->frame->child_y;
- }
- }
- else
- {
- if (window->frame == NULL)
- frame_extents = window->rect;
- else
- frame_extents = window->frame->rect;
- }
-
- x = frame_extents.x;
- y = frame_extents.y;
-
- switch (gravity)
- {
- case META_GRAVITY_NORTH:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_SOUTH:
- /* Find center of frame. */
- x += frame_extents.width / 2;
- /* Center client window on that point. */
- x -= w / 2;
- break;
-
- case META_GRAVITY_SOUTH_EAST:
- case META_GRAVITY_EAST:
- case META_GRAVITY_NORTH_EAST:
- /* Find right edge of frame */
- x += frame_extents.width;
- /* Align left edge of client at that point. */
- x -= w;
- break;
- default:
- break;
- }
-
- switch (gravity)
- {
- case META_GRAVITY_WEST:
- case META_GRAVITY_CENTER:
- case META_GRAVITY_EAST:
- /* Find center of frame. */
- y += frame_extents.height / 2;
- /* Center client window there. */
- y -= h / 2;
- break;
- case META_GRAVITY_SOUTH_WEST:
- case META_GRAVITY_SOUTH:
- case META_GRAVITY_SOUTH_EAST:
- /* Find south edge of frame */
- y += frame_extents.height;
- /* Place bottom edge of client there */
- y -= h;
- break;
- default:
- break;
- }
-
- if (root_x)
- *root_x = x;
- if (root_y)
- *root_y = y;
-}
-
-void
-meta_window_get_session_geometry (MetaWindow *window,
- int *x,
- int *y,
- int *width,
- int *height)
-{
- meta_window_get_gravity_position (window,
- window->size_hints.win_gravity,
- x, y);
-
- *width = (window->rect.width - window->size_hints.base_width) /
- window->size_hints.width_inc;
- *height = (window->rect.height - window->size_hints.base_height) /
- window->size_hints.height_inc;
-}
-
-/**
- * meta_window_get_buffer_rect:
- * @window: a #MetaWindow
- * @rect: (out): pointer to an allocated #MetaRectangle
- *
- * Gets the rectangle that the pixmap or buffer of @window occupies.
- *
- * For X11 windows, this is the server-side geometry of the toplevel
- * window.
- *
- * For Wayland windows, this is the bounding rectangle of the attached
- * buffer.
- */
-void
-meta_window_get_buffer_rect (const MetaWindow *window,
- MetaRectangle *rect)
-{
- *rect = window->buffer_rect;
-}
-
-/**
- * meta_window_client_rect_to_frame_rect:
- * @window: a #MetaWindow
- * @client_rect: client rectangle in root coordinates
- * @frame_rect: (out): location to store the computed corresponding frame bounds.
- *
- * Converts a desired bounds of the client window into the corresponding bounds
- * of the window frame (excluding invisible borders and client side shadows.)
- */
-void
-meta_window_client_rect_to_frame_rect (MetaWindow *window,
- MetaRectangle *client_rect,
- MetaRectangle *frame_rect)
-{
- if (!frame_rect)
- return;
-
- *frame_rect = *client_rect;
-
- /* The support for G_MAXINT here to mean infinity is a convenience for
- * constraints.c:get_size_limits() and not something that we provide
- * in other locations or document.
- */
- if (window->frame)
- {
- MetaFrameBorders borders;
- meta_frame_calc_borders (window->frame, &borders);
-
- frame_rect->x -= borders.visible.left;
- frame_rect->y -= borders.visible.top;
- if (frame_rect->width != G_MAXINT)
- frame_rect->width += borders.visible.left + borders.visible.right;
- if (frame_rect->height != G_MAXINT)
- frame_rect->height += borders.visible.top + borders.visible.bottom;
- }
- else
- {
- const GtkBorder *extents = &window->custom_frame_extents;
- frame_rect->x += extents->left;
- frame_rect->y += extents->top;
- if (frame_rect->width != G_MAXINT)
- frame_rect->width -= extents->left + extents->right;
- if (frame_rect->height != G_MAXINT)
- frame_rect->height -= extents->top + extents->bottom;
- }
-}
-
-/**
- * meta_window_frame_rect_to_client_rect:
- * @window: a #MetaWindow
- * @frame_rect: desired frame bounds for the window
- * @client_rect: (out): location to store the computed corresponding client rectangle.
- *
- * Converts a desired frame bounds for a window into the bounds of the client
- * window.
- */
-void
-meta_window_frame_rect_to_client_rect (MetaWindow *window,
- MetaRectangle *frame_rect,
- MetaRectangle *client_rect)
-{
- if (!client_rect)
- return;
-
- *client_rect = *frame_rect;
-
- if (window->frame)
- {
- MetaFrameBorders borders;
- meta_frame_calc_borders (window->frame, &borders);
-
- client_rect->x += borders.visible.left;
- client_rect->y += borders.visible.top;
- client_rect->width -= borders.visible.left + borders.visible.right;
- client_rect->height -= borders.visible.top + borders.visible.bottom;
- }
- else
- {
- const GtkBorder *extents = &window->custom_frame_extents;
- client_rect->x -= extents->left;
- client_rect->y -= extents->top;
- client_rect->width += extents->left + extents->right;
- client_rect->height += extents->top + extents->bottom;
- }
-}
-
-/**
- * meta_window_get_frame_rect:
- * @window: a #MetaWindow
- * @rect: (out): pointer to an allocated #MetaRectangle
- *
- * Gets the rectangle that bounds @window that is what the user thinks of
- * as the edge of the window. This doesn't include any extra reactive
- * area that we or the client adds to the window, or any area that the
- * client adds to draw a client-side shadow.
- */
-void
-meta_window_get_frame_rect (const MetaWindow *window,
- MetaRectangle *rect)
-{
- *rect = window->rect;
-}
-
-/**
- * meta_window_get_client_area_rect:
- * @window: a #MetaWindow
- * @rect: (out): pointer to a cairo rectangle
- *
- * Gets the rectangle for the boundaries of the client area, relative
- * to the buffer rect. If the window is shaded, the height of the
- * rectangle is 0.
- */
-void
-meta_window_get_client_area_rect (const MetaWindow *window,
- cairo_rectangle_int_t *rect)
-{
- MetaFrameBorders borders;
-
- meta_frame_calc_borders (window->frame, &borders);
-
- rect->x = borders.total.left;
- rect->y = borders.total.top;
-
- rect->width = window->buffer_rect.width - borders.total.left - borders.total.right;
- if (window->shaded)
- rect->height = 0;
- else
- rect->height = window->buffer_rect.height - borders.total.top - borders.total.bottom;
-}
-
-void
-meta_window_get_titlebar_rect (MetaWindow *window,
- MetaRectangle *rect)
-{
- meta_window_get_frame_rect (window, rect);
-
- /* The returned rectangle is relative to the frame rect. */
- rect->x = 0;
- rect->y = 0;
-
- if (window->frame)
- {
- rect->height = window->frame->child_y;
- }
- else
- {
- /* Pick an arbitrary height for a titlebar. We might want to
- * eventually have CSD windows expose their borders to us. */
- rect->height = 50;
- }
-}
-
-const char*
-meta_window_get_startup_id (MetaWindow *window)
-{
- if (window->startup_id == NULL)
- {
- MetaGroup *group;
-
- group = meta_window_get_group (window);
-
- if (group != NULL)
- return meta_group_get_startup_id (group);
- }
-
- return window->startup_id;
-}
-
-static MetaWindow*
-get_modal_transient (MetaWindow *window)
-{
- GSList *windows;
- GSList *tmp;
- MetaWindow *modal_transient;
-
- /* A window can't be the transient of itself, but this is just for
- * convenience in the loop below; we manually fix things up at the
- * end if no real modal transient was found.
- */
- modal_transient = window;
-
- windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *transient = tmp->data;
-
- if (transient->transient_for == modal_transient &&
- transient->type == META_WINDOW_MODAL_DIALOG)
- {
- modal_transient = transient;
- tmp = windows;
- continue;
- }
-
- tmp = tmp->next;
- }
-
- g_slist_free (windows);
-
- if (window == modal_transient)
- modal_transient = NULL;
-
- return modal_transient;
-}
-
-static gboolean
-meta_window_transient_can_focus (MetaWindow *window)
-{
-#ifdef HAVE_WAYLAND
- if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
- return meta_wayland_surface_get_buffer (window->surface) != NULL;
-#endif
-
- return TRUE;
-}
-
-/* XXX META_EFFECT_FOCUS */
-void
-meta_window_focus (MetaWindow *window,
- guint32 timestamp)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- MetaWindow *modal_transient;
-
- g_return_if_fail (!window->override_redirect);
-
- /* This is a oneshot flag */
- window->restore_focus_on_map = FALSE;
-
- meta_topic (META_DEBUG_FOCUS,
- "Setting input focus to window %s, input: %d focusable: %d",
- window->desc, window->input, meta_window_is_focusable (window));
-
- if (window->display->grab_window &&
- window->display->grab_window != window &&
- window->display->grab_window->all_keys_grabbed &&
- !window->display->grab_window->unmanaging)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Current focus window %s has global keygrab, not focusing window %s after all",
- window->display->grab_window->desc, window->desc);
- return;
- }
-
- modal_transient = get_modal_transient (window);
- if (modal_transient != NULL &&
- !modal_transient->unmanaging &&
- meta_window_transient_can_focus (modal_transient))
- {
- meta_topic (META_DEBUG_FOCUS,
- "%s has %s as a modal transient, so focusing it instead.",
- window->desc, modal_transient->desc);
- if (!meta_window_located_on_workspace (modal_transient, workspace_manager->active_workspace))
- meta_window_change_workspace (modal_transient, workspace_manager->active_workspace);
- window = modal_transient;
- }
-
- meta_window_flush_calc_showing (window);
-
- if ((!window->mapped || window->hidden) && !window->shaded)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Window %s is not showing, not focusing after all",
- window->desc);
- return;
- }
-
- META_WINDOW_GET_CLASS (window)->focus (window, timestamp);
-
- if (window->display->event_route == META_EVENT_ROUTE_NORMAL)
- {
- MetaBackend *backend = meta_get_backend ();
- ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
- clutter_stage_set_key_focus (stage, NULL);
- }
-
- if (window->close_dialog &&
- meta_close_dialog_is_visible (window->close_dialog))
- meta_close_dialog_focus (window->close_dialog);
-
- if (window->wm_state_demands_attention)
- meta_window_unset_demands_attention(window);
-
-/* meta_effect_run_focus(window, NULL, NULL); */
-}
-
-/* Workspace management. Invariants:
- *
- * - window->workspace describes the workspace the window is on.
- *
- * - workspace->windows is a list of windows that is located on
- * that workspace.
- *
- * - If the window is on_all_workspaces, then
- * window->workspace == NULL, but workspace->windows contains
- * the window.
- */
-
-static void
-set_workspace_state (MetaWindow *window,
- gboolean on_all_workspaces,
- MetaWorkspace *workspace)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- /* If we're on all workspaces, then our new workspace must be NULL,
- * otherwise it must be set, unless we're unmanaging. */
- if (on_all_workspaces)
- g_assert_null (workspace);
- else
- g_assert_true (window->unmanaging || workspace != NULL);
-
- /* If this is an override-redirect window, ensure that the only
- * times we're setting the workspace state is either during construction
- * to mark as on_all_workspaces, or when unmanaging to remove all the
- * workspaces. */
- if (window->override_redirect)
- g_return_if_fail ((window->constructing && on_all_workspaces) || window->unmanaging);
-
- if (on_all_workspaces == window->on_all_workspaces &&
- workspace == window->workspace &&
- !window->constructing)
- return;
-
- if (window->workspace)
- meta_workspace_remove_window (window->workspace, window);
- else if (window->on_all_workspaces)
- {
- GList *l;
- for (l = workspace_manager->workspaces; l != NULL; l = l->next)
- {
- MetaWorkspace *ws = l->data;
- meta_workspace_remove_window (ws, window);
- }
- }
-
- window->on_all_workspaces = on_all_workspaces;
- window->workspace = workspace;
-
- if (window->workspace)
- meta_workspace_add_window (window->workspace, window);
- else if (window->on_all_workspaces)
- {
- GList *l;
- for (l = workspace_manager->workspaces; l != NULL; l = l->next)
- {
- MetaWorkspace *ws = l->data;
- meta_workspace_add_window (ws, window);
- }
- }
-
- /* queue a move_resize since changing workspaces may change
- * the relevant struts
- */
- if (!window->override_redirect)
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
- meta_window_queue (window, META_QUEUE_CALC_SHOWING);
- meta_window_current_workspace_changed (window);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ON_ALL_WORKSPACES]);
- g_signal_emit (window, window_signals[WORKSPACE_CHANGED], 0);
-}
-
-static gboolean
-should_be_on_all_workspaces (MetaWindow *window)
-{
- if (window->always_sticky)
- return TRUE;
-
- if (window->on_all_workspaces_requested)
- return TRUE;
-
- if (window->override_redirect)
- return TRUE;
-
- if (meta_prefs_get_workspaces_only_on_primary () &&
- !window->unmanaging &&
- window->monitor &&
- !meta_window_is_on_primary_monitor (window))
- return TRUE;
-
- return FALSE;
-}
-
-void
-meta_window_on_all_workspaces_changed (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- gboolean on_all_workspaces = should_be_on_all_workspaces (window);
-
- if (window->on_all_workspaces == on_all_workspaces)
- return;
-
- MetaWorkspace *workspace;
-
- if (on_all_workspaces)
- {
- workspace = NULL;
- }
- else
- {
- /* We're coming out of the sticky state. Put the window on
- * the currently active workspace. */
- workspace = workspace_manager->active_workspace;
- }
-
- set_workspace_state (window, on_all_workspaces, workspace);
-}
-
-static void
-meta_window_change_workspace_without_transients (MetaWindow *window,
- MetaWorkspace *workspace)
-{
- /* Try to unstick the window if it's stuck. This doesn't
- * have any guarantee that we'll actually unstick the
- * window, since it could be stuck for other reasons. */
- if (window->on_all_workspaces_requested)
- meta_window_unstick (window);
-
- /* We failed to unstick the window. */
- if (window->on_all_workspaces)
- return;
-
- if (window->workspace == workspace)
- return;
-
- set_workspace_state (window, FALSE, workspace);
-}
-
-static gboolean
-change_workspace_foreach (MetaWindow *window,
- void *data)
-{
- meta_window_change_workspace_without_transients (window, data);
- return TRUE;
-}
-
-void
-meta_window_change_workspace (MetaWindow *window,
- MetaWorkspace *workspace)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_window_change_workspace_without_transients (window, workspace);
-
- meta_window_foreach_transient (window, change_workspace_foreach,
- workspace);
- meta_window_foreach_ancestor (window, change_workspace_foreach,
- workspace);
-}
-
-static void
-window_stick_impl (MetaWindow *window)
-{
- meta_verbose ("Sticking window %s current on_all_workspaces = %d",
- window->desc, window->on_all_workspaces);
-
- if (window->on_all_workspaces_requested)
- return;
-
- /* We don't change window->workspaces, because we revert
- * to that original workspace list if on_all_workspaces is
- * toggled back off.
- */
- window->on_all_workspaces_requested = TRUE;
- meta_window_on_all_workspaces_changed (window);
-}
-
-static void
-window_unstick_impl (MetaWindow *window)
-{
- if (!window->on_all_workspaces_requested)
- return;
-
- /* Revert to window->workspaces */
-
- window->on_all_workspaces_requested = FALSE;
- meta_window_on_all_workspaces_changed (window);
-}
-
-static gboolean
-stick_foreach_func (MetaWindow *window,
- void *data)
-{
- gboolean stick;
-
- stick = *(gboolean*)data;
- if (stick)
- window_stick_impl (window);
- else
- window_unstick_impl (window);
- return TRUE;
-}
-
-void
-meta_window_stick (MetaWindow *window)
-{
- gboolean stick = TRUE;
-
- g_return_if_fail (!window->override_redirect);
-
- window_stick_impl (window);
- meta_window_foreach_transient (window,
- stick_foreach_func,
- &stick);
-}
-
-void
-meta_window_unstick (MetaWindow *window)
-{
- gboolean stick = FALSE;
-
- g_return_if_fail (!window->override_redirect);
-
- window_unstick_impl (window);
- meta_window_foreach_transient (window,
- stick_foreach_func,
- &stick);
-}
-
-void
-meta_window_current_workspace_changed (MetaWindow *window)
-{
- META_WINDOW_GET_CLASS (window)->current_workspace_changed (window);
-}
-
-static gboolean
-find_root_ancestor (MetaWindow *window,
- void *data)
-{
- MetaWindow **ancestor = data;
-
- /* Overwrite the previously "most-root" ancestor with the new one found */
- *ancestor = window;
-
- /* We want this to continue until meta_window_foreach_ancestor quits because
- * there are no more valid ancestors.
- */
- return TRUE;
-}
-
-/**
- * meta_window_find_root_ancestor:
- * @window: a #MetaWindow
- *
- * Follow the chain of parents of @window, skipping transient windows,
- * and return the "root" window which has no non-transient parent.
- *
- * Returns: (transfer none): The root ancestor window
- */
-MetaWindow *
-meta_window_find_root_ancestor (MetaWindow *window)
-{
- MetaWindow *ancestor;
- ancestor = window;
- meta_window_foreach_ancestor (window, find_root_ancestor, &ancestor);
- return ancestor;
-}
-
-void
-meta_window_raise (MetaWindow *window)
-{
- MetaWindow *ancestor;
-
- g_return_if_fail (!window->override_redirect);
-
- ancestor = meta_window_find_root_ancestor (window);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Raising window %s, ancestor of %s",
- ancestor->desc, window->desc);
-
- /* Raise the ancestor of the window (if the window has no ancestor,
- * then ancestor will be set to the window itself); do this because
- * it's weird to see windows from other apps stacked between a child
- * and parent window of the currently active app. The stacking
- * constraints in stack.c then magically take care of raising all
- * the child windows appropriately.
- */
- if (window->display->stack == ancestor->display->stack)
- {
- meta_stack_raise (window->display->stack, ancestor);
- }
- else
- {
- meta_warning (
- "Either stacks aren't per screen or some window has a weird "
- "transient_for hint; window->display->stack != "
- "ancestor->screen->stack. window = %s, ancestor = %s.",
- window->desc, ancestor->desc);
- /* We could raise the window here, but don't want to do that twice and
- * so we let the case below handle that.
- */
- }
-
- /* Okay, so stacking constraints misses one case: If a window has
- * two children and we want to raise one of those children, then
- * raising the ancestor isn't enough; we need to also raise the
- * correct child. See bug 307875.
- */
- if (window != ancestor)
- meta_stack_raise (window->display->stack, window);
-
- g_signal_emit (window, window_signals[RAISED], 0);
-}
-
-void
-meta_window_lower (MetaWindow *window)
-{
- g_return_if_fail (!window->override_redirect);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Lowering window %s", window->desc);
-
- meta_stack_lower (window->display->stack, window);
-}
-
-/*
- * Move window to the requested workspace; append controls whether new WS
- * should be created if one does not exist.
- */
-void
-meta_window_change_workspace_by_index (MetaWindow *window,
- gint space_index,
- gboolean append)
-{
- MetaWorkspaceManager *workspace_manager;
- MetaWorkspace *workspace;
- MetaDisplay *display;
-
- g_return_if_fail (!window->override_redirect);
-
- if (space_index == -1)
- {
- meta_window_stick (window);
- return;
- }
-
- display = window->display;
- workspace_manager = display->workspace_manager;
-
- workspace =
- meta_workspace_manager_get_workspace_by_index (workspace_manager, space_index);
-
- if (!workspace && append)
- workspace = meta_workspace_manager_append_new_workspace (workspace_manager, FALSE, META_CURRENT_TIME);
-
- if (workspace)
- meta_window_change_workspace (window, workspace);
-}
-
-static void
-meta_window_appears_focused_changed (MetaWindow *window)
-{
- set_net_wm_state (window);
- meta_window_frame_size_changed (window);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_APPEARS_FOCUSED]);
-
- if (window->frame)
- meta_frame_queue_draw (window->frame);
-}
-
-static gboolean
-should_propagate_focus_appearance (MetaWindow *window)
-{
- /* Parents of attached modal dialogs should appear focused. */
- if (meta_window_is_attached_dialog (window))
- return TRUE;
-
- /* Parents of these sorts of override-redirect windows should
- * appear focused. */
- switch (window->type)
- {
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_COMBO:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- return TRUE;
- default:
- break;
- }
-
- return FALSE;
-}
-
-/**
- * meta_window_propagate_focus_appearance:
- * @window: the window to start propagating from
- * @focused: %TRUE if @window's ancestors should appear focused,
- * %FALSE if they should not.
- *
- * Adjusts the value of #MetaWindow:appears-focused on @window's
- * ancestors (but not @window itself). If @focused is %TRUE, each of
- * @window's ancestors will have its %attached_focus_window field set
- * to the current %focus_window. If @focused if %FALSE, each of
- * @window's ancestors will have its %attached_focus_window field
- * cleared if it is currently %focus_window.
- */
-static void
-meta_window_propagate_focus_appearance (MetaWindow *window,
- gboolean focused)
-{
- MetaWindow *child, *parent, *focus_window;
-
- focus_window = window->display->focus_window;
-
- child = window;
- parent = meta_window_get_transient_for (child);
- while (parent && (!focused || should_propagate_focus_appearance (child)))
- {
- gboolean child_focus_state_changed;
-
- if (focused)
- {
- if (parent->attached_focus_window == focus_window)
- break;
- child_focus_state_changed = (parent->attached_focus_window == NULL);
- parent->attached_focus_window = focus_window;
- }
- else
- {
- if (parent->attached_focus_window != focus_window)
- break;
- child_focus_state_changed = (parent->attached_focus_window != NULL);
- parent->attached_focus_window = NULL;
- }
-
- if (child_focus_state_changed && !parent->has_focus)
- {
- meta_window_appears_focused_changed (parent);
- }
-
- child = parent;
- parent = meta_window_get_transient_for (child);
- }
-}
-
-void
-meta_window_set_focused_internal (MetaWindow *window,
- gboolean focused)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- if (focused)
- {
- window->has_focus = TRUE;
- if (window->override_redirect)
- return;
-
- /* Move to the front of the focusing workspace's MRU list.
- * We should only be "removing" it from the MRU list if it's
- * not already there. Note that it's possible that we might
- * be processing this FocusIn after we've changed to a
- * different workspace; we should therefore update the MRU
- * list only if the window is actually on the active
- * workspace.
- */
- if (workspace_manager->active_workspace &&
- meta_window_located_on_workspace (window,
- workspace_manager->active_workspace))
- {
- GList* link;
- link = g_list_find (workspace_manager->active_workspace->mru_list,
- window);
- g_assert (link);
-
- workspace_manager->active_workspace->mru_list =
- g_list_remove_link (workspace_manager->active_workspace->mru_list,
- link);
- g_list_free (link);
-
- workspace_manager->active_workspace->mru_list =
- g_list_prepend (workspace_manager->active_workspace->mru_list,
- window);
- }
-
- if (window->frame)
- meta_frame_queue_draw (window->frame);
-
- /* Ungrab click to focus button since the sync grab can interfere
- * with some things you might do inside the focused window, by
- * causing the client to get funky enter/leave events.
- *
- * The reason we usually have a passive grab on the window is
- * so that we can intercept clicks and raise the window in
- * response. For click-to-focus we don't need that since the
- * focused window is already raised. When raise_on_click is
- * FALSE we also don't need that since we don't do anything
- * when the window is clicked.
- *
- * There is dicussion in bugs 102209, 115072, and 461577
- */
- if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
- !meta_prefs_get_raise_on_click())
- {
- meta_display_ungrab_focus_window_button (window->display, window);
- /* Since we ungrab with XIAnyModifier above, all button
- grabs go way so we need to re-grab the window buttons. */
- meta_display_grab_window_buttons (window->display, window->xwindow);
- }
-
- g_signal_emit (window, window_signals[FOCUS], 0);
-
- if (!window->attached_focus_window)
- meta_window_appears_focused_changed (window);
-
- meta_window_propagate_focus_appearance (window, TRUE);
- }
- else
- {
- window->has_focus = FALSE;
- if (window->override_redirect)
- return;
-
- meta_window_propagate_focus_appearance (window, FALSE);
-
- if (!window->attached_focus_window)
- meta_window_appears_focused_changed (window);
-
- /* Re-grab for click to focus and raise-on-click, if necessary */
- if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
- !meta_prefs_get_raise_on_click ())
- meta_display_grab_focus_window_button (window->display, window);
- }
-}
-
-/**
- * meta_window_get_icon_geometry:
- * @window: a #MetaWindow
- * @rect: (out): rectangle into which to store the returned geometry.
- *
- * Gets the location of the icon corresponding to the window. The location
- * will be provided set by the task bar or other user interface element
- * displaying the icon, and is relative to the root window.
- *
- * Return value: %TRUE if the icon geometry was successfully retrieved.
- */
-gboolean
-meta_window_get_icon_geometry (MetaWindow *window,
- MetaRectangle *rect)
-{
- g_return_val_if_fail (!window->override_redirect, FALSE);
-
- if (window->icon_geometry_set)
- {
- if (rect)
- *rect = window->icon_geometry;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * meta_window_set_icon_geometry:
- * @window: a #MetaWindow
- * @rect: (nullable): rectangle with the desired geometry or %NULL.
- *
- * Sets or unsets the location of the icon corresponding to the window. If
- * set, the location should correspond to a dock, task bar or other user
- * interface element displaying the icon, and is relative to the root window.
- */
-void
-meta_window_set_icon_geometry (MetaWindow *window,
- MetaRectangle *rect)
-{
- if (rect)
- {
- window->icon_geometry = *rect;
- window->icon_geometry_set = TRUE;
- }
- else
- {
- window->icon_geometry_set = FALSE;
- }
-}
-
-static void
-redraw_icon (MetaWindow *window)
-{
- /* We could probably be smart and just redraw the icon here,
- * instead of the whole frame.
- */
- if (window->frame)
- meta_frame_queue_draw (window->frame);
-}
-
-static void
-meta_window_update_icon_now (MetaWindow *window,
- gboolean force)
-{
- gboolean changed;
- cairo_surface_t *icon = NULL;
- cairo_surface_t *mini_icon;
-
- g_return_if_fail (!window->override_redirect);
-
- changed = META_WINDOW_GET_CLASS (window)->update_icon (window, &icon, &mini_icon);
-
- if (changed || force)
- {
- if (window->icon)
- cairo_surface_destroy (window->icon);
- window->icon = icon;
-
- if (window->mini_icon)
- cairo_surface_destroy (window->mini_icon);
- window->mini_icon = mini_icon;
-
- g_object_freeze_notify (G_OBJECT (window));
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ICON]);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINI_ICON]);
- g_object_thaw_notify (G_OBJECT (window));
-
- redraw_icon (window);
- }
-}
-
-static gboolean
-idle_update_icon (gpointer data)
-{
- GSList *tmp;
- GSList *copy;
- guint queue_index = GPOINTER_TO_INT (data);
-
- meta_topic (META_DEBUG_GEOMETRY, "Clearing the update_icon queue");
-
- /* Work with a copy, for reentrancy. The allowed reentrancy isn't
- * complete; destroying a window while we're in here would result in
- * badness. But it's OK to queue/unqueue update_icons.
- */
- copy = g_slist_copy (queue_pending[queue_index]);
- g_slist_free (queue_pending[queue_index]);
- queue_pending[queue_index] = NULL;
- queue_later[queue_index] = 0;
-
- destroying_windows_disallowed += 1;
-
- tmp = copy;
- while (tmp != NULL)
- {
- MetaWindow *window;
-
- window = tmp->data;
-
- meta_window_update_icon_now (window, FALSE);
- window->is_in_queues &= ~META_QUEUE_UPDATE_ICON;
-
- tmp = tmp->next;
- }
-
- g_slist_free (copy);
-
- destroying_windows_disallowed -= 1;
-
- return FALSE;
-}
-
-GList*
-meta_window_get_workspaces (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- if (window->on_all_workspaces)
- return workspace_manager->workspaces;
- else if (window->workspace != NULL)
- return window->workspace->list_containing_self;
- else if (window->constructing)
- return NULL;
- else
- g_assert_not_reached ();
- return NULL;
-}
-
-static void
-invalidate_work_areas (MetaWindow *window)
-{
- GList *tmp;
-
- tmp = meta_window_get_workspaces (window);
-
- while (tmp != NULL)
- {
- meta_workspace_invalidate_work_area (tmp->data);
- tmp = tmp->next;
- }
-}
-
-void
-meta_window_update_struts (MetaWindow *window)
-{
- if (META_WINDOW_GET_CLASS (window)->update_struts (window))
- invalidate_work_areas (window);
-}
-
-static void
-meta_window_type_changed (MetaWindow *window)
-{
- gboolean old_decorated = window->decorated;
- GObject *object = G_OBJECT (window);
-
- window->attached = meta_window_should_attach_to_parent (window);
- meta_window_recalc_features (window);
-
- if (!window->override_redirect)
- set_net_wm_state (window);
-
- /* Update frame */
- if (window->decorated)
- meta_window_ensure_frame (window);
- else
- meta_window_destroy_frame (window);
-
- /* update stacking constraints */
- meta_window_update_layer (window);
-
- meta_window_grab_keys (window);
-
- g_object_freeze_notify (object);
-
- if (old_decorated != window->decorated)
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DECORATED]);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_WINDOW_TYPE]);
-
- g_object_thaw_notify (object);
-}
-
-void
-meta_window_set_type (MetaWindow *window,
- MetaWindowType type)
-{
- if (window->type == type)
- return;
-
- window->type = type;
- meta_window_type_changed (window);
-}
-
-void
-meta_window_frame_size_changed (MetaWindow *window)
-{
- if (window->frame)
- meta_frame_clear_cached_borders (window->frame);
-}
-
-static void
-meta_window_get_default_skip_hints (MetaWindow *window,
- gboolean *skip_taskbar_out,
- gboolean *skip_pager_out)
-{
- META_WINDOW_GET_CLASS (window)->get_default_skip_hints (window, skip_taskbar_out, skip_pager_out);
-}
-
-static void
-meta_window_recalc_skip_features (MetaWindow *window)
-{
- switch (window->type)
- {
- /* Force skip taskbar/pager on these window types */
- case META_WINDOW_DESKTOP:
- case META_WINDOW_DOCK:
- case META_WINDOW_TOOLBAR:
- case META_WINDOW_MENU:
- case META_WINDOW_UTILITY:
- case META_WINDOW_SPLASHSCREEN:
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_COMBO:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- window->skip_taskbar = TRUE;
- window->skip_pager = TRUE;
- break;
-
- case META_WINDOW_DIALOG:
- case META_WINDOW_MODAL_DIALOG:
- /* only skip taskbar if we have a real transient parent
- (and ignore the application hints) */
- if (window->transient_for != NULL)
- window->skip_taskbar = TRUE;
- else
- window->skip_taskbar = window->skip_from_window_list;
- break;
-
- case META_WINDOW_NORMAL:
- {
- gboolean skip_taskbar_hint, skip_pager_hint;
- meta_window_get_default_skip_hints (window, &skip_taskbar_hint, &skip_pager_hint);
- window->skip_taskbar = skip_taskbar_hint | window->skip_from_window_list;
- window->skip_pager = skip_pager_hint | window->skip_from_window_list;
- }
- break;
- }
-}
-
-void
-meta_window_recalc_features (MetaWindow *window)
-{
- gboolean old_has_close_func;
- gboolean old_has_minimize_func;
- gboolean old_has_move_func;
- gboolean old_has_resize_func;
- gboolean old_has_shade_func;
- gboolean old_always_sticky;
- gboolean old_skip_taskbar;
-
- old_has_close_func = window->has_close_func;
- old_has_minimize_func = window->has_minimize_func;
- old_has_move_func = window->has_move_func;
- old_has_resize_func = window->has_resize_func;
- old_has_shade_func = window->has_shade_func;
- old_always_sticky = window->always_sticky;
- old_skip_taskbar = window->skip_taskbar;
-
- /* Use MWM hints initially */
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- window->decorated = window->mwm_decorated;
- else
- window->decorated = FALSE;
- window->border_only = window->mwm_border_only;
- window->has_close_func = window->mwm_has_close_func;
- window->has_minimize_func = window->mwm_has_minimize_func;
- window->has_maximize_func = window->mwm_has_maximize_func;
- window->has_move_func = window->mwm_has_move_func;
-
- window->has_resize_func = TRUE;
-
- /* If min_size == max_size, then don't allow resize */
- if (window->size_hints.min_width == window->size_hints.max_width &&
- window->size_hints.min_height == window->size_hints.max_height)
- window->has_resize_func = FALSE;
- else if (!window->mwm_has_resize_func)
- {
- /* We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the
- * authoritative source for that info. Some apps such as mplayer or
- * xine disable resize via MWM but not WM_NORMAL_HINTS, but that
- * leads to e.g. us not fullscreening their windows. Apps that set
- * MWM but not WM_NORMAL_HINTS are basically broken. We complain
- * about these apps but make them work.
- */
-
- meta_warning ("Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.",
- window->desc,
- window->size_hints.min_width,
- window->size_hints.min_height,
- window->size_hints.max_width,
- window->size_hints.max_height);
- }
-
- window->has_shade_func = TRUE;
- window->has_fullscreen_func = TRUE;
-
- window->always_sticky = FALSE;
-
- /* Semantic category overrides the MWM hints */
- if (window->type == META_WINDOW_TOOLBAR)
- window->decorated = FALSE;
-
- if (window->type == META_WINDOW_DESKTOP ||
- window->type == META_WINDOW_DOCK ||
- window->override_redirect)
- window->always_sticky = TRUE;
-
- if (window->override_redirect ||
- meta_window_get_frame_type (window) == META_FRAME_TYPE_LAST)
- {
- window->decorated = FALSE;
- window->has_close_func = FALSE;
- window->has_shade_func = FALSE;
-
- /* FIXME this keeps panels and things from using
- * NET_WM_MOVERESIZE; the problem is that some
- * panels (edge panels) have fixed possible locations,
- * and others ("floating panels") do not.
- *
- * Perhaps we should require edge panels to explicitly
- * disable movement?
- */
- window->has_move_func = FALSE;
- window->has_resize_func = FALSE;
- }
-
- if (window->type != META_WINDOW_NORMAL)
- {
- window->has_minimize_func = FALSE;
- window->has_maximize_func = FALSE;
- window->has_fullscreen_func = FALSE;
- }
-
- if (!window->has_resize_func)
- {
- window->has_maximize_func = FALSE;
- MetaRectangle display_rect = { 0 };
-
- meta_display_get_size (window->display, &display_rect.width,
- &display_rect.height);
-
- /* don't allow fullscreen if we can't resize, unless the size
- * is entire screen size (kind of broken, because we
- * actually fullscreen to monitor size not screen size)
- */
- if (window->size_hints.min_width == display_rect.width &&
- window->size_hints.min_height == display_rect.height)
- ; /* leave fullscreen available */
- else
- window->has_fullscreen_func = FALSE;
- }
-
- /* We leave fullscreen windows decorated, just push the frame outside
- * the screen. This avoids flickering to unparent them.
- *
- * Note that setting has_resize_func = FALSE here must come after the
- * above code that may disable fullscreen, because if the window
- * is not resizable purely due to fullscreen, we don't want to
- * disable fullscreen mode.
- */
- if (window->fullscreen)
- {
- window->has_shade_func = FALSE;
- window->has_move_func = FALSE;
- window->has_resize_func = FALSE;
- window->has_maximize_func = FALSE;
- }
-
- if (window->has_maximize_func && window->monitor)
- {
- MetaRectangle work_area, client_rect;
-
- meta_window_get_work_area_current_monitor (window, &work_area);
- meta_window_frame_rect_to_client_rect (window, &work_area, &client_rect);
-
- if (window->size_hints.min_width >= client_rect.width ||
- window->size_hints.min_height >= client_rect.height)
- window->has_maximize_func = FALSE;
- }
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Window %s fullscreen = %d not resizable, maximizable = %d fullscreenable = %d min size %dx%d max size %dx%d",
- window->desc,
- window->fullscreen,
- window->has_maximize_func, window->has_fullscreen_func,
- window->size_hints.min_width,
- window->size_hints.min_height,
- window->size_hints.max_width,
- window->size_hints.max_height);
-
- /* no shading if not decorated */
- if (!window->decorated || window->border_only)
- window->has_shade_func = FALSE;
-
- meta_window_recalc_skip_features (window);
-
- /* To prevent users from losing windows, let's prevent users from
- * minimizing skip-taskbar windows through the window decorations. */
- if (window->skip_taskbar)
- window->has_minimize_func = FALSE;
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Window %s decorated = %d border_only = %d has_close = %d has_minimize = %d has_maximize = %d has_move = %d has_shade = %d skip_taskbar = %d skip_pager = %d",
- window->desc,
- window->decorated,
- window->border_only,
- window->has_close_func,
- window->has_minimize_func,
- window->has_maximize_func,
- window->has_move_func,
- window->has_shade_func,
- window->skip_taskbar,
- window->skip_pager);
-
- if (old_skip_taskbar != window->skip_taskbar)
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_SKIP_TASKBAR]);
-
- /* FIXME:
- * Lame workaround for recalc_features being used overzealously.
- * The fix is to only recalc_features when something has
- * actually changed.
- */
- if (window->constructing ||
- old_has_close_func != window->has_close_func ||
- old_has_minimize_func != window->has_minimize_func ||
- old_has_move_func != window->has_move_func ||
- old_has_resize_func != window->has_resize_func ||
- old_has_shade_func != window->has_shade_func ||
- old_always_sticky != window->always_sticky)
- set_allowed_actions_hint (window);
-
- if (window->has_resize_func != old_has_resize_func)
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_RESIZEABLE]);
-
- meta_window_frame_size_changed (window);
-
- /* FIXME perhaps should ensure if we don't have a shade func,
- * we aren't shaded, etc.
- */
-}
-
-void
-meta_window_show_menu (MetaWindow *window,
- MetaWindowMenuType menu,
- int x,
- int y)
-{
- g_return_if_fail (!window->override_redirect);
- meta_compositor_show_window_menu (window->display->compositor, window, menu, x, y);
-}
-
-void
-meta_window_show_menu_for_rect (MetaWindow *window,
- MetaWindowMenuType menu,
- MetaRectangle *rect)
-{
- g_return_if_fail (!window->override_redirect);
- meta_compositor_show_window_menu_for_rect (window->display->compositor, window, menu, rect);
-}
-
-void
-meta_window_shove_titlebar_onscreen (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- MetaRectangle frame_rect;
- GList *onscreen_region;
- int horiz_amount, vert_amount;
-
- g_return_if_fail (!window->override_redirect);
-
- /* If there's no titlebar, don't bother */
- if (!window->frame)
- return;
-
- /* Get the basic info we need */
- meta_window_get_frame_rect (window, &frame_rect);
- onscreen_region = workspace_manager->active_workspace->screen_region;
-
- /* Extend the region (just in case the window is too big to fit on the
- * screen), then shove the window on screen, then return the region to
- * normal.
- */
- horiz_amount = frame_rect.width;
- vert_amount = frame_rect.height;
- meta_rectangle_expand_region (onscreen_region,
- horiz_amount,
- horiz_amount,
- 0,
- vert_amount);
- meta_rectangle_shove_into_region(onscreen_region,
- FIXED_DIRECTION_X,
- &frame_rect);
- meta_rectangle_expand_region (onscreen_region,
- -horiz_amount,
- -horiz_amount,
- 0,
- -vert_amount);
-
- meta_window_move_frame (window, FALSE, frame_rect.x, frame_rect.y);
-}
-
-gboolean
-meta_window_titlebar_is_onscreen (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- MetaRectangle titlebar_rect, frame_rect;
- GList *onscreen_region;
- gboolean is_onscreen;
-
- const int min_height_needed = 8;
- const float min_width_percent = 0.5;
- const int min_width_absolute = 50;
-
- /* Titlebar can't be offscreen if there is no titlebar... */
- if (!window->frame)
- return TRUE;
-
- /* Get the rectangle corresponding to the titlebar */
- meta_window_get_titlebar_rect (window, &titlebar_rect);
-
- /* Translate into screen coordinates */
- meta_window_get_frame_rect (window, &frame_rect);
- titlebar_rect.x = frame_rect.x;
- titlebar_rect.y = frame_rect.y;
-
- /* Run through the spanning rectangles for the screen and see if one of
- * them overlaps with the titlebar sufficiently to consider it onscreen.
- */
- is_onscreen = FALSE;
- onscreen_region = workspace_manager->active_workspace->screen_region;
- while (onscreen_region)
- {
- MetaRectangle *spanning_rect = onscreen_region->data;
- MetaRectangle overlap;
-
- meta_rectangle_intersect (&titlebar_rect, spanning_rect, &overlap);
- if (overlap.height > MIN (titlebar_rect.height, min_height_needed) &&
- overlap.width > MIN (titlebar_rect.width * min_width_percent,
- min_width_absolute))
- {
- is_onscreen = TRUE;
- break;
- }
-
- onscreen_region = onscreen_region->next;
- }
-
- return is_onscreen;
-}
-
-static gboolean
-check_moveresize_frequency (MetaWindow *window,
- gdouble *remaining)
-{
- int64_t current_time;
- const double max_resizes_per_second = 25.0;
- const double ms_between_resizes = 1000.0 / max_resizes_per_second;
- double elapsed;
-
- current_time = g_get_real_time ();
-
- /* If we are throttling via _NET_WM_SYNC_REQUEST, we don't need
- * an artificial timeout-based throttled */
- if (!window->disable_sync &&
- window->sync_request_alarm != None)
- return TRUE;
-
- elapsed = (current_time - window->display->grab_last_moveresize_time) / 1000;
-
- if (elapsed >= 0.0 && elapsed < ms_between_resizes)
- {
- meta_topic (META_DEBUG_RESIZING,
- "Delaying move/resize as only %g of %g ms elapsed",
- elapsed, ms_between_resizes);
-
- if (remaining)
- *remaining = (ms_between_resizes - elapsed);
-
- return FALSE;
- }
-
- meta_topic (META_DEBUG_RESIZING,
- " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)",
- elapsed / 1000.0, 1.0 / max_resizes_per_second);
-
- return TRUE;
-}
-
-static gboolean
-update_move_timeout (gpointer data)
-{
- MetaWindow *window = data;
-
- update_move (window,
- window->display->grab_last_edge_resistance_flags,
- window->display->grab_latest_motion_x,
- window->display->grab_latest_motion_y);
-
- return FALSE;
-}
-
-static void
-update_move_maybe_tile (MetaWindow *window,
- int shake_threshold,
- int x,
- int y)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
- MetaDisplay *display = window->display;
- MetaRectangle work_area;
-
- /* For side-by-side tiling we are interested in the inside vertical
- * edges of the work area of the monitor where the pointer is located,
- * and in the outside top edge for maximized tiling.
- *
- * For maximized tiling we use the outside edge instead of the
- * inside edge, because we don't want to force users to maximize
- * windows they are placing near the top of their screens.
- *
- * The "current" idea of meta_window_get_work_area_current_monitor() and
- * meta_screen_get_current_monitor() is slightly different: the former
- * refers to the monitor which contains the largest part of the window,
- * the latter to the one where the pointer is located.
- */
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
- if (!logical_monitor)
- return;
-
- meta_window_get_work_area_for_monitor (window,
- logical_monitor->number,
- &work_area);
-
- /* Check if the cursor is in a position which triggers tiling
- * and set tile_mode accordingly.
- */
- if (meta_window_can_tile_side_by_side (window) &&
- x >= logical_monitor->rect.x && x < (work_area.x + shake_threshold))
- display->preview_tile_mode = META_TILE_LEFT;
- else if (meta_window_can_tile_side_by_side (window) &&
- x >= work_area.x + work_area.width - shake_threshold &&
- x < (logical_monitor->rect.x + logical_monitor->rect.width))
- display->preview_tile_mode = META_TILE_RIGHT;
- else if (meta_window_can_tile_maximized (window) &&
- y >= logical_monitor->rect.y && y <= work_area.y)
- display->preview_tile_mode = META_TILE_MAXIMIZED;
- else
- display->preview_tile_mode = META_TILE_NONE;
-
- if (display->preview_tile_mode != META_TILE_NONE)
- window->tile_monitor_number = logical_monitor->number;
-}
-
-static void
-update_move (MetaWindow *window,
- MetaEdgeResistanceFlags flags,
- int x,
- int y)
-{
- int dx, dy;
- int new_x, new_y;
- MetaRectangle old;
- int shake_threshold;
- MetaDisplay *display = window->display;
-
- display->grab_latest_motion_x = x;
- display->grab_latest_motion_y = y;
-
- dx = x - display->grab_anchor_root_x;
- dy = y - display->grab_anchor_root_y;
-
- new_x = display->grab_anchor_window_pos.x + dx;
- new_y = display->grab_anchor_window_pos.y + dy;
-
- meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d",
- x, y,
- display->grab_anchor_root_x,
- display->grab_anchor_root_y,
- display->grab_anchor_window_pos.x,
- display->grab_anchor_window_pos.y,
- dx, dy);
-
- /* Don't bother doing anything if no move has been specified. (This
- * happens often, even in keyboard moving, due to the warping of the
- * pointer.
- */
- if (dx == 0 && dy == 0)
- return;
-
- /* Originally for detaching maximized windows, but we use this
- * for the zones at the sides of the monitor where trigger tiling
- * because it's about the right size
- */
-#define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6
- shake_threshold = meta_prefs_get_drag_threshold () *
- DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR;
-
- if (flags & META_EDGE_RESISTANCE_SNAP)
- {
- /* We don't want to tile while snapping. Also, clear any previous tile
- request. */
- display->preview_tile_mode = META_TILE_NONE;
- window->tile_monitor_number = -1;
- }
- else if (meta_prefs_get_edge_tiling () &&
- !META_WINDOW_MAXIMIZED (window) &&
- !META_WINDOW_TILED_SIDE_BY_SIDE (window))
- {
- update_move_maybe_tile (window, shake_threshold, x, y);
- }
-
- /* shake loose (unmaximize) maximized or tiled window if dragged beyond
- * the threshold in the Y direction. Tiled windows can also be pulled
- * loose via X motion.
- */
-
- if ((META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) ||
- (META_WINDOW_TILED_SIDE_BY_SIDE (window) && (MAX (ABS (dx), ABS (dy)) >= shake_threshold)))
- {
- double prop;
-
- /* Shake loose, so that the window snaps back to maximized
- * when dragged near the top; do not snap back if tiling
- * is enabled, as top edge tiling can be used in that case
- */
- window->shaken_loose = !meta_prefs_get_edge_tiling ();
- window->tile_mode = META_TILE_NONE;
-
- /* move the unmaximized window to the cursor */
- prop =
- ((double)(x - display->grab_initial_window_pos.x)) /
- ((double)display->grab_initial_window_pos.width);
-
- display->grab_initial_window_pos.x = x - window->saved_rect.width * prop;
-
- /* If we started dragging the window from above the top of the window,
- * pretend like we started dragging from the middle of the titlebar
- * instead, as the "correct" anchoring looks wrong. */
- if (display->grab_anchor_root_y < display->grab_initial_window_pos.y)
- {
- MetaRectangle titlebar_rect;
- meta_window_get_titlebar_rect (window, &titlebar_rect);
- display->grab_anchor_root_y = display->grab_initial_window_pos.y + titlebar_rect.height / 2;
- }
-
- window->saved_rect.x = display->grab_initial_window_pos.x;
- window->saved_rect.y = display->grab_initial_window_pos.y;
-
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
- return;
- }
-
- /* remaximize window on another monitor if window has been shaken
- * loose or it is still maximized (then move straight)
- */
- else if ((window->shaken_loose || META_WINDOW_MAXIMIZED (window)) &&
- window->tile_mode != META_TILE_LEFT && window->tile_mode != META_TILE_RIGHT)
- {
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- int n_logical_monitors;
- const MetaLogicalMonitor *wmonitor;
- MetaRectangle work_area;
- int monitor;
-
- window->tile_mode = META_TILE_NONE;
- wmonitor = window->monitor;
- n_logical_monitors =
- meta_monitor_manager_get_num_logical_monitors (monitor_manager);
-
- for (monitor = 0; monitor < n_logical_monitors; monitor++)
- {
- meta_window_get_work_area_for_monitor (window, monitor, &work_area);
-
- /* check if cursor is near the top of a monitor work area */
- if (x >= work_area.x &&
- x < (work_area.x + work_area.width) &&
- y >= work_area.y &&
- y < (work_area.y + shake_threshold))
- {
- /* move the saved rect if window will become maximized on an
- * other monitor so user isn't surprised on a later unmaximize
- */
- if (wmonitor->number != monitor)
- {
- window->saved_rect.x = work_area.x;
- window->saved_rect.y = work_area.y;
-
- if (window->frame)
- {
- window->saved_rect.x += window->frame->child_x;
- window->saved_rect.y += window->frame->child_y;
- }
-
- window->unconstrained_rect.x = window->saved_rect.x;
- window->unconstrained_rect.y = window->saved_rect.y;
-
- meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
-
- display->grab_initial_window_pos = work_area;
- display->grab_anchor_root_x = x;
- display->grab_anchor_root_y = y;
- window->shaken_loose = FALSE;
-
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
- }
-
- return;
- }
- }
- }
-
- /* Delay showing the tile preview slightly to make it more unlikely to
- * trigger it unwittingly, e.g. when shaking loose the window or moving
- * it to another monitor.
- */
- meta_display_update_tile_preview (window->display,
- window->tile_mode != META_TILE_NONE);
-
- meta_window_get_frame_rect (window, &old);
-
- /* Don't allow movement in the maximized directions or while tiled */
- if (window->maximized_horizontally || META_WINDOW_TILED_SIDE_BY_SIDE (window))
- new_x = old.x;
- if (window->maximized_vertically)
- new_y = old.y;
-
- /* Do any edge resistance/snapping */
- meta_window_edge_resistance_for_move (window,
- &new_x,
- &new_y,
- update_move_timeout,
- flags);
-
- meta_window_move_frame (window, TRUE, new_x, new_y);
-}
-
-static gboolean
-update_resize_timeout (gpointer data)
-{
- MetaWindow *window = data;
-
- update_resize (window,
- window->display->grab_last_edge_resistance_flags,
- window->display->grab_latest_motion_x,
- window->display->grab_latest_motion_y,
- TRUE);
- return FALSE;
-}
-
-static void
-update_resize (MetaWindow *window,
- MetaEdgeResistanceFlags flags,
- int x,
- int y,
- gboolean force)
-{
- int dx, dy;
- MetaGravity gravity;
- MetaRectangle new_rect;
- MetaRectangle old_rect;
- double remaining = 0;
-
- window->display->grab_latest_motion_x = x;
- window->display->grab_latest_motion_y = y;
-
- dx = x - window->display->grab_anchor_root_x;
- dy = y - window->display->grab_anchor_root_y;
-
- /* Attached modal dialogs are special in that size
- * changes apply to both sides, so that the dialog
- * remains centered to the parent.
- */
- if (meta_window_is_attached_dialog (window))
- {
- dx *= 2;
- dy *= 2;
- }
-
- new_rect.width = window->display->grab_anchor_window_pos.width;
- new_rect.height = window->display->grab_anchor_window_pos.height;
-
- /* Don't bother doing anything if no move has been specified. (This
- * happens often, even in keyboard resizing, due to the warping of the
- * pointer.
- */
- if (dx == 0 && dy == 0)
- return;
-
- if (window->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN)
- {
- MetaGrabOp op = META_GRAB_OP_WINDOW_BASE | META_GRAB_OP_WINDOW_FLAG_KEYBOARD;
-
- if (dx > 0)
- op |= META_GRAB_OP_WINDOW_DIR_EAST;
- else if (dx < 0)
- op |= META_GRAB_OP_WINDOW_DIR_WEST;
-
- if (dy > 0)
- op |= META_GRAB_OP_WINDOW_DIR_SOUTH;
- else if (dy < 0)
- op |= META_GRAB_OP_WINDOW_DIR_NORTH;
-
- window->display->grab_op = op;
-
- meta_window_update_keyboard_resize (window, TRUE);
- }
-
- if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST)
- new_rect.width += dx;
- else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST)
- new_rect.width -= dx;
-
- if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH)
- new_rect.height += dy;
- else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_NORTH)
- new_rect.height -= dy;
-
- meta_window_maybe_apply_size_hints (window, &new_rect);
-
- /* If we're waiting for a request for _NET_WM_SYNC_REQUEST, we'll
- * resize the window when the window responds, or when we time
- * the response out.
- */
- if (window->sync_request_timeout_id != 0)
- return;
-
- if (!check_moveresize_frequency (window, &remaining) && !force)
- {
- /* we are ignoring an event here, so we schedule a
- * compensation event when we would otherwise not ignore
- * an event. Otherwise we can become stuck if the user never
- * generates another event.
- */
- if (!window->display->grab_resize_timeout_id)
- {
- window->display->grab_resize_timeout_id =
- g_timeout_add ((int)remaining, update_resize_timeout, window);
- g_source_set_name_by_id (window->display->grab_resize_timeout_id,
- "[mutter] update_resize_timeout");
- }
-
- return;
- }
-
- /* Remove any scheduled compensation events */
- g_clear_handle_id (&window->display->grab_resize_timeout_id, g_source_remove);
-
- meta_window_get_frame_rect (window, &old_rect);
-
- /* One sided resizing ought to actually be one-sided, despite the fact that
- * aspect ratio windows don't interact nicely with the above stuff. So,
- * to avoid some nasty flicker, we enforce that.
- */
-
- if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) == 0)
- new_rect.width = old_rect.width;
-
- if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) == 0)
- new_rect.height = old_rect.height;
-
- /* compute gravity of client during operation */
- gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
- g_assert (gravity >= 0);
-
- /* Do any edge resistance/snapping */
- meta_window_edge_resistance_for_resize (window,
- &new_rect.width,
- &new_rect.height,
- gravity,
- update_resize_timeout,
- flags);
-
- meta_window_resize_frame_with_gravity (window, TRUE,
- new_rect.width, new_rect.height,
- gravity);
-
- /* Store the latest resize time, if we actually resized. */
- if (window->rect.width != old_rect.width ||
- window->rect.height != old_rect.height)
- window->display->grab_last_moveresize_time = g_get_real_time ();
-}
-
-static void
-maybe_maximize_tiled_window (MetaWindow *window)
-{
- MetaRectangle work_area;
- gint shake_threshold;
-
- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
- return;
-
- shake_threshold = meta_prefs_get_drag_threshold ();
-
- meta_window_get_work_area_for_monitor (window,
- window->tile_monitor_number,
- &work_area);
- if (window->rect.width >= work_area.width - shake_threshold)
- meta_window_maximize (window, META_MAXIMIZE_BOTH);
-}
-
-void
-meta_window_update_resize (MetaWindow *window,
- MetaEdgeResistanceFlags flags,
- int x, int y,
- gboolean force)
-{
- update_resize (window, flags, x, y, force);
-}
-
-static void
-end_grab_op (MetaWindow *window,
- const ClutterEvent *event)
-{
- ClutterModifierType modifiers;
- MetaEdgeResistanceFlags last_flags;
- gfloat x, y;
-
- clutter_event_get_coords (event, &x, &y);
- modifiers = clutter_event_get_state (event);
- meta_display_check_threshold_reached (window->display, x, y);
-
- /* If the user was snap moving then ignore the button
- * release because they may have let go of shift before
- * releasing the mouse button and they almost certainly do
- * not want a non-snapped movement to occur from the button
- * release.
- */
- last_flags = window->display->grab_last_edge_resistance_flags;
- if ((last_flags & META_EDGE_RESISTANCE_SNAP) == 0)
- {
- MetaEdgeResistanceFlags flags = META_EDGE_RESISTANCE_DEFAULT;
-
- if (modifiers & CLUTTER_SHIFT_MASK)
- flags |= META_EDGE_RESISTANCE_SNAP;
-
- if (modifiers & CLUTTER_CONTROL_MASK)
- flags |= META_EDGE_RESISTANCE_WINDOWS;
-
- if (meta_grab_op_is_moving (window->display->grab_op))
- {
- if (window->display->preview_tile_mode != META_TILE_NONE)
- meta_window_tile (window, window->display->preview_tile_mode);
- else
- update_move (window, flags, x, y);
- }
- else if (meta_grab_op_is_resizing (window->display->grab_op))
- {
- if (window->tile_match != NULL)
- flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS);
-
- update_resize (window, flags, x, y, TRUE);
- maybe_maximize_tiled_window (window);
- }
- }
- window->display->preview_tile_mode = META_TILE_NONE;
- meta_display_end_grab_op (window->display, clutter_event_get_time (event));
-}
-
-gboolean
-meta_window_handle_mouse_grab_op_event (MetaWindow *window,
- const ClutterEvent *event)
-{
- ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
- ClutterModifierType modifier_state;
- MetaEdgeResistanceFlags flags;
- gfloat x, y;
-
- switch (event->type)
- {
- case CLUTTER_TOUCH_BEGIN:
- if (!meta_display_is_pointer_emulating_sequence (window->display, sequence))
- return FALSE;
-
- return TRUE;
-
- case CLUTTER_BUTTON_PRESS:
- {
- ClutterModifierType grab_mods = meta_display_get_compositor_modifiers (window->display);
-
- /* This is the keybinding or menu case where we've
- * been dragging around the window without the button
- * pressed. */
-
- if ((meta_grab_op_is_mouse (window->display->grab_op) &&
- (event->button.modifier_state & grab_mods) == grab_mods &&
- window->display->grab_button != (int) event->button.button) ||
- meta_grab_op_is_keyboard (window->display->grab_op))
- {
- end_grab_op (window, event);
- return FALSE;
- }
- return TRUE;
- }
-
- case CLUTTER_TOUCH_END:
- if (!meta_display_is_pointer_emulating_sequence (window->display, sequence))
- return FALSE;
-
- end_grab_op (window, event);
- return TRUE;
-
- case CLUTTER_BUTTON_RELEASE:
- if (event->button.button == 1 ||
- event->button.button == (unsigned int) meta_prefs_get_mouse_button_resize ())
- end_grab_op (window, event);
-
- return TRUE;
-
- case CLUTTER_TOUCH_UPDATE:
- if (!meta_display_is_pointer_emulating_sequence (window->display, sequence))
- return FALSE;
-
- /* Fall through */
- case CLUTTER_MOTION:
- modifier_state = clutter_event_get_state (event);
- clutter_event_get_coords (event, &x, &y);
- flags = META_EDGE_RESISTANCE_DEFAULT;
-
- if (modifier_state & CLUTTER_SHIFT_MASK)
- flags |= META_EDGE_RESISTANCE_SNAP;
-
- if (modifier_state & CLUTTER_CONTROL_MASK)
- flags |= META_EDGE_RESISTANCE_WINDOWS;
-
- meta_display_check_threshold_reached (window->display, x, y);
- if (meta_grab_op_is_moving (window->display->grab_op))
- {
- update_move (window, flags, x, y);
- }
- else if (meta_grab_op_is_resizing (window->display->grab_op))
- {
- if (window->tile_match != NULL)
- flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS);
-
- update_resize (window, flags, x, y, FALSE);
- }
- return TRUE;
-
- case CLUTTER_TOUCH_CANCEL:
- end_grab_op (window, event);
- return FALSE;
-
- default:
- return FALSE;
- }
-}
-
-void
-meta_window_get_work_area_for_logical_monitor (MetaWindow *window,
- MetaLogicalMonitor *logical_monitor,
- MetaRectangle *area)
-{
- GList *tmp;
-
- g_assert (logical_monitor);
-
- /* Initialize to the whole monitor */
- *area = logical_monitor->rect;
-
- tmp = meta_window_get_workspaces (window);
- while (tmp != NULL)
- {
- MetaRectangle workspace_work_area;
- meta_workspace_get_work_area_for_logical_monitor (tmp->data,
- logical_monitor,
- &workspace_work_area);
- meta_rectangle_intersect (area,
- &workspace_work_area,
- area);
- tmp = tmp->next;
- }
-
- meta_topic (META_DEBUG_WORKAREA,
- "Window %s monitor %d has work area %d,%d %d x %d",
- window->desc, logical_monitor->number,
- area->x, area->y, area->width, area->height);
-}
-
-/**
- * meta_window_get_work_area_current_monitor:
- * @window: a #MetaWindow
- * @area: (out): a location to store the work area
- *
- * Get the work area for the monitor @window is currently on.
- */
-void
-meta_window_get_work_area_current_monitor (MetaWindow *window,
- MetaRectangle *area)
-{
- meta_window_get_work_area_for_monitor (window,
- window->monitor->number,
- area);
-}
-
-/**
- * meta_window_get_work_area_for_monitor:
- * @window: a #MetaWindow
- * @which_monitor: a moniotr to get the work area for
- * @area: (out): a location to store the work area
- *
- * Get the work area for @window, given the monitor index
- * @which_monitor.
- */
-void
-meta_window_get_work_area_for_monitor (MetaWindow *window,
- int which_monitor,
- MetaRectangle *area)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
-
- g_return_if_fail (which_monitor >= 0);
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
- which_monitor);
-
- meta_window_get_work_area_for_logical_monitor (window, logical_monitor, area);
-}
-
-/**
- * meta_window_get_work_area_all_monitors:
- * @window: a #MetaWindow
- * @area: (out): a location to store the work area
- *
- * Get the work area for all monitors for @window.
- */
-void
-meta_window_get_work_area_all_monitors (MetaWindow *window,
- MetaRectangle *area)
-{
- GList *tmp;
- MetaRectangle display_rect = { 0 };
-
- meta_display_get_size (window->display,
- &display_rect.width,
- &display_rect.height);
-
- /* Initialize to the whole display */
- *area = display_rect;
-
- tmp = meta_window_get_workspaces (window);
- while (tmp != NULL)
- {
- MetaRectangle workspace_work_area;
- meta_workspace_get_work_area_all_monitors (tmp->data,
- &workspace_work_area);
- meta_rectangle_intersect (area,
- &workspace_work_area,
- area);
- tmp = tmp->next;
- }
-
- meta_topic (META_DEBUG_WORKAREA,
- "Window %s has whole-screen work area %d,%d %d x %d",
- window->desc, area->x, area->y, area->width, area->height);
-}
-
-int
-meta_window_get_current_tile_monitor_number (MetaWindow *window)
-{
- int tile_monitor_number = window->tile_monitor_number;
-
- if (tile_monitor_number < 0)
- {
- meta_warning ("%s called with an invalid monitor number; using 0 instead", G_STRFUNC);
- tile_monitor_number = 0;
- }
-
- return tile_monitor_number;
-}
-
-void
-meta_window_get_tile_area (MetaWindow *window,
- MetaTileMode tile_mode,
- MetaRectangle *tile_area)
-{
- MetaRectangle work_area;
- int tile_monitor_number;
- double fraction;
-
- g_return_if_fail (tile_mode != META_TILE_NONE);
-
- tile_monitor_number = meta_window_get_current_tile_monitor_number (window);
-
- meta_window_get_work_area_for_monitor (window, tile_monitor_number, &work_area);
- meta_window_get_tile_fraction (window, tile_mode, &fraction);
-
- *tile_area = work_area;
- tile_area->width = round (tile_area->width * fraction);
-
- if (tile_mode == META_TILE_RIGHT)
- tile_area->x += work_area.width - tile_area->width;
-}
-
-gboolean
-meta_window_same_application (MetaWindow *window,
- MetaWindow *other_window)
-{
- MetaGroup *group = meta_window_get_group (window);
- MetaGroup *other_group = meta_window_get_group (other_window);
-
- return
- group!=NULL &&
- other_group!=NULL &&
- group==other_group;
-}
-
-/**
- * meta_window_is_client_decorated:
- *
- * Check if if the window has decorations drawn by the client.
- * (window->decorated refers only to whether we should add decorations)
- */
-gboolean
-meta_window_is_client_decorated (MetaWindow *window)
-{
- if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
- {
- /* Assume all Wayland clients draw decorations - not strictly
- * true but good enough for current purposes.
- */
- return TRUE;
- }
- else
- {
- /* Currently the implementation here is hackish -
- * has_custom_frame_extents() is set if _GTK_FRAME_EXTENTS is set
- * to any value even 0. GTK+ always sets _GTK_FRAME_EXTENTS for
- * client-side-decorated window, even if the value is 0 because
- * the window is maxized and has no invisible borders or shadows.
- */
- return window->has_custom_frame_extents;
- }
-}
-
-/**
- * meta_window_foreach_transient:
- * @window: a #MetaWindow
- * @func: (scope call) (closure user_data): Called for each window which is a transient of @window (transitively)
- * @user_data: User data
- *
- * Call @func for every window which is either transient for @window, or is
- * a transient of a window which is in turn transient for @window.
- * The order of window enumeration is not defined.
- *
- * Iteration will stop if @func at any point returns %FALSE.
- */
-void
-meta_window_foreach_transient (MetaWindow *window,
- MetaWindowForeachFunc func,
- void *user_data)
-{
- GSList *windows;
- GSList *tmp;
-
- windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
-
- tmp = windows;
- while (tmp != NULL)
- {
- MetaWindow *transient = tmp->data;
-
- if (meta_window_is_ancestor_of_transient (window, transient))
- {
- if (!(* func) (transient, user_data))
- break;
- }
-
- tmp = tmp->next;
- }
-
- g_slist_free (windows);
-}
-
-/**
- * meta_window_foreach_ancestor:
- * @window: a #MetaWindow
- * @func: (scope call) (closure user_data): Called for each window which is a transient parent of @window
- * @user_data: User data
- *
- * If @window is transient, call @func with the window for which it's transient,
- * repeatedly until either we find a non-transient window, or @func returns %FALSE.
- */
-void
-meta_window_foreach_ancestor (MetaWindow *window,
- MetaWindowForeachFunc func,
- void *user_data)
-{
- MetaWindow *w;
-
- w = window;
- do
- {
- if (w->transient_for == NULL)
- break;
-
- w = w->transient_for;
- }
- while (w && (* func) (w, user_data));
-}
-
-typedef struct
-{
- MetaWindow *ancestor;
- gboolean found;
-} FindAncestorData;
-
-static gboolean
-find_ancestor_func (MetaWindow *window,
- void *data)
-{
- FindAncestorData *d = data;
-
- if (window == d->ancestor)
- {
- d->found = TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * meta_window_is_ancestor_of_transient:
- * @window: a #MetaWindow
- * @transient: a #MetaWindow
- *
- * The function determines whether @window is an ancestor of @transient; it does
- * so by traversing the @transient's ancestors until it either locates @window
- * or reaches an ancestor that is not transient.
- *
- * Return Value: %TRUE if window is an ancestor of transient.
- */
-gboolean
-meta_window_is_ancestor_of_transient (MetaWindow *window,
- MetaWindow *transient)
-{
- FindAncestorData d;
-
- d.ancestor = window;
- d.found = FALSE;
-
- meta_window_foreach_ancestor (transient, find_ancestor_func, &d);
-
- return d.found;
-}
-
-/* Warp pointer to location appropriate for grab,
- * return root coordinates where pointer ended up.
- */
-static gboolean
-warp_grab_pointer (MetaWindow *window,
- MetaGrabOp grab_op,
- int *x,
- int *y)
-{
- MetaRectangle rect;
- MetaRectangle display_rect = { 0 };
- MetaDisplay *display;
- ClutterSeat *seat;
-
- display = window->display;
- meta_display_get_size (display,
- &display_rect.width,
- &display_rect.height);
-
- /* We may not have done begin_grab_op yet, i.e. may not be in a grab
- */
-
- meta_window_get_frame_rect (window, &rect);
-
- if (grab_op & META_GRAB_OP_WINDOW_DIR_WEST)
- *x = 0;
- else if (grab_op & META_GRAB_OP_WINDOW_DIR_EAST)
- *x = rect.width - 1;
- else
- *x = rect.width / 2;
-
- if (grab_op & META_GRAB_OP_WINDOW_DIR_NORTH)
- *y = 0;
- else if (grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH)
- *y = rect.height - 1;
- else
- *y = rect.height / 2;
-
- *x += rect.x;
- *y += rect.y;
-
- /* Avoid weird bouncing at the screen edge; see bug 154706 */
- *x = CLAMP (*x, 0, display_rect.width - 1);
- *y = CLAMP (*y, 0, display_rect.height - 1);
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Warping pointer to %d,%d with window at %d,%d",
- *x, *y, rect.x, rect.y);
-
- /* Need to update the grab positions so that the MotionNotify and other
- * events generated by the XWarpPointer() call below don't cause complete
- * funkiness. See bug 124582 and bug 122670.
- */
- display->grab_anchor_root_x = *x;
- display->grab_anchor_root_y = *y;
- display->grab_latest_motion_x = *x;
- display->grab_latest_motion_y = *y;
- meta_window_get_frame_rect (window,
- &display->grab_anchor_window_pos);
-
- seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
- clutter_seat_warp_pointer (seat, *x, *y);
-
- return TRUE;
-}
-
-void
-meta_window_begin_grab_op (MetaWindow *window,
- MetaGrabOp op,
- gboolean frame_action,
- guint32 timestamp)
-{
- int x, y;
-
- warp_grab_pointer (window,
- op, &x, &y);
-
- meta_display_begin_grab_op (window->display,
- window,
- op,
- FALSE,
- frame_action,
- 0 /* button */,
- 0,
- timestamp,
- x, y);
-}
-
-void
-meta_window_update_keyboard_resize (MetaWindow *window,
- gboolean update_cursor)
-{
- int x, y;
-
- warp_grab_pointer (window,
- window->display->grab_op,
- &x, &y);
-
- if (update_cursor)
- meta_display_update_cursor (window->display);
-}
-
-void
-meta_window_update_keyboard_move (MetaWindow *window)
-{
- int x, y;
-
- warp_grab_pointer (window,
- window->display->grab_op,
- &x, &y);
-}
-
-MetaStackLayer
-meta_window_get_default_layer (MetaWindow *window)
-{
- if (window->wm_state_below)
- return META_LAYER_BOTTOM;
- else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
- return META_LAYER_TOP;
- else
- return META_LAYER_NORMAL;
-}
-
-void
-meta_window_update_layer (MetaWindow *window)
-{
- MetaGroup *group;
-
- meta_stack_freeze (window->display->stack);
- group = meta_window_get_group (window);
- if (group)
- meta_group_update_layers (group);
- else
- meta_stack_update_layer (window->display->stack, window);
- meta_stack_thaw (window->display->stack);
-}
-
-/* ensure_mru_position_after ensures that window appears after
- * below_this_one in the active_workspace's mru_list (i.e. it treats
- * window as having been less recently used than below_this_one)
- */
-static void
-ensure_mru_position_after (MetaWindow *window,
- MetaWindow *after_this_one)
-{
- /* This is sort of slow since it runs through the entire list more
- * than once (especially considering the fact that we expect the
- * windows of interest to be the first two elements in the list),
- * but it doesn't matter while we're only using it on new window
- * map.
- */
-
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- GList* active_mru_list;
- GList* window_position;
- GList* after_this_one_position;
-
- active_mru_list = workspace_manager->active_workspace->mru_list;
- window_position = g_list_find (active_mru_list, window);
- after_this_one_position = g_list_find (active_mru_list, after_this_one);
-
- /* after_this_one_position is NULL when we switch workspaces, but in
- * that case we don't need to do any MRU shuffling so we can simply
- * return.
- */
- if (after_this_one_position == NULL)
- return;
-
- if (g_list_length (window_position) > g_list_length (after_this_one_position))
- {
- workspace_manager->active_workspace->mru_list =
- g_list_delete_link (workspace_manager->active_workspace->mru_list,
- window_position);
-
- workspace_manager->active_workspace->mru_list =
- g_list_insert_before (workspace_manager->active_workspace->mru_list,
- after_this_one_position->next,
- window);
- }
-}
-
-gboolean
-meta_window_is_in_stack (MetaWindow *window)
-{
- return window->stack_position >= 0;
-}
-
-void
-meta_window_stack_just_below (MetaWindow *window,
- MetaWindow *below_this_one)
-{
- g_return_if_fail (window != NULL);
- g_return_if_fail (below_this_one != NULL);
-
- if (window->stack_position > below_this_one->stack_position)
- {
- meta_topic (META_DEBUG_STACK,
- "Setting stack position of window %s to %d (making it below window %s).",
- window->desc,
- below_this_one->stack_position,
- below_this_one->desc);
- meta_window_set_stack_position (window, below_this_one->stack_position);
- }
- else
- {
- meta_topic (META_DEBUG_STACK,
- "Window %s was already below window %s.",
- window->desc, below_this_one->desc);
- }
-}
-
-void
-meta_window_stack_just_above (MetaWindow *window,
- MetaWindow *above_this_one)
-{
- g_return_if_fail (window != NULL);
- g_return_if_fail (above_this_one != NULL);
-
- if (window->stack_position < above_this_one->stack_position)
- {
- meta_topic (META_DEBUG_STACK,
- "Setting stack position of window %s to %d (making it above window %s).",
- window->desc,
- above_this_one->stack_position,
- above_this_one->desc);
- meta_window_set_stack_position (window, above_this_one->stack_position);
- }
- else
- {
- meta_topic (META_DEBUG_STACK,
- "Window %s was already above window %s.",
- window->desc, above_this_one->desc);
- }
-}
-
-/**
- * meta_window_get_user_time:
- * @window: a #MetaWindow
- *
- * The user time represents a timestamp for the last time the user
- * interacted with this window. Note this property is only available
- * for non-override-redirect windows.
- *
- * The property is set by Mutter initially upon window creation,
- * and updated thereafter on input events (key and button presses) seen by Mutter,
- * client updates to the _NET_WM_USER_TIME property (if later than the current time)
- * and when focusing the window.
- *
- * Returns: The last time the user interacted with this window.
- */
-guint32
-meta_window_get_user_time (MetaWindow *window)
-{
- return window->net_wm_user_time;
-}
-
-void
-meta_window_set_user_time (MetaWindow *window,
- 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.
- */
-
- g_return_if_fail (!window->override_redirect);
-
- /* Only update the time if this timestamp is newer... */
- if (window->net_wm_user_time_set &&
- XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))
- {
- meta_topic (META_DEBUG_STARTUP,
- "Window %s _NET_WM_USER_TIME not updated to %u, because it "
- "is less than %u",
- window->desc, timestamp, window->net_wm_user_time);
- }
- else
- {
- meta_topic (META_DEBUG_STARTUP,
- "Window %s has _NET_WM_USER_TIME of %u",
- window->desc, timestamp);
- window->net_wm_user_time_set = TRUE;
- window->net_wm_user_time = timestamp;
- if (XSERVER_TIME_IS_BEFORE (window->display->last_user_time, timestamp))
- window->display->last_user_time = timestamp;
-
- /* If this is a terminal, user interaction with it means the user likely
- * doesn't want to have focus transferred for now due to new windows.
- */
- if (meta_prefs_get_focus_new_windows () == G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT &&
- window_is_terminal (window))
- window->display->allow_terminal_deactivation = FALSE;
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_USER_TIME]);
- }
-}
-
-/**
- * meta_window_get_stable_sequence:
- * @window: A #MetaWindow
- *
- * The stable sequence number is a monotonicially increasing
- * unique integer assigned to each #MetaWindow upon creation.
- *
- * This number can be useful for sorting windows in a stable
- * fashion.
- *
- * Returns: Internal sequence number for this window
- */
-guint32
-meta_window_get_stable_sequence (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), 0);
-
- return window->stable_sequence;
-}
-
-/* Sets the demands_attention hint on a window, but only
- * if it's at least partially obscured (see #305882).
- */
-void
-meta_window_set_demands_attention (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
- MetaRectangle candidate_rect, other_rect;
- GList *stack = window->display->stack->sorted;
- MetaWindow *other_window;
- gboolean obscured = FALSE;
-
- MetaWorkspace *workspace = workspace_manager->active_workspace;
-
- if (window->wm_state_demands_attention)
- return;
-
- if (!meta_window_located_on_workspace (window, workspace))
- {
- /* windows on other workspaces are necessarily obscured */
- obscured = TRUE;
- }
- else if (window->minimized)
- {
- obscured = TRUE;
- }
- else
- {
- meta_window_get_frame_rect (window, &candidate_rect);
-
- /* The stack is sorted with the top windows first. */
-
- while (stack != NULL && stack->data != window)
- {
- other_window = stack->data;
- stack = stack->next;
-
- if (meta_window_located_on_workspace (other_window, workspace))
- {
- meta_window_get_frame_rect (other_window, &other_rect);
-
- if (meta_rectangle_overlap (&candidate_rect, &other_rect))
- {
- obscured = TRUE;
- break;
- }
- }
- }
- }
-
- if (obscured)
- {
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Marking %s as needing attention",
- window->desc);
-
- window->wm_state_demands_attention = TRUE;
- set_net_wm_state (window);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DEMANDS_ATTENTION]);
- g_signal_emit_by_name (window->display, "window-demands-attention",
- window);
- }
- else
- {
- /* If the window's in full view, there's no point setting the flag. */
-
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Not marking %s as needing attention because "
- "it's in full view",
- window->desc);
- }
-}
-
-void
-meta_window_unset_demands_attention (MetaWindow *window)
-{
- meta_topic (META_DEBUG_WINDOW_OPS,
- "Marking %s as not needing attention", window->desc);
-
- if (window->wm_state_demands_attention)
- {
- window->wm_state_demands_attention = FALSE;
- set_net_wm_state (window);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DEMANDS_ATTENTION]);
- }
-}
-
-/**
- * meta_window_get_frame: (skip)
- * @window: a #MetaWindow
- *
- */
-MetaFrame *
-meta_window_get_frame (MetaWindow *window)
-{
- return window->frame;
-}
-
-/**
- * meta_window_appears_focused:
- * @window: a #MetaWindow
- *
- * Determines if the window should be drawn with a focused appearance. This is
- * true for focused windows but also true for windows with a focused modal
- * dialog attached.
- *
- * Return value: %TRUE if the window should be drawn with a focused frame
- */
-gboolean
-meta_window_appears_focused (MetaWindow *window)
-{
- return window->has_focus || (window->attached_focus_window != NULL);
-}
-
-gboolean
-meta_window_has_focus (MetaWindow *window)
-{
- return window->has_focus;
-}
-
-gboolean
-meta_window_is_shaded (MetaWindow *window)
-{
- return window->shaded;
-}
-
-/**
- * meta_window_is_override_redirect:
- * @window: A #MetaWindow
- *
- * Returns: %TRUE if this window isn't managed by mutter; it will
- * control its own positioning and mutter won't draw decorations
- * among other things. In X terminology this is "override redirect".
- */
-gboolean
-meta_window_is_override_redirect (MetaWindow *window)
-{
- return window->override_redirect;
-}
-
-/**
- * meta_window_is_skip_taskbar:
- * @window: A #MetaWindow
- *
- * Gets whether this window should be ignored by task lists.
- *
- * Return value: %TRUE if the skip bar hint is set.
- */
-gboolean
-meta_window_is_skip_taskbar (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), FALSE);
-
- return window->skip_taskbar;
-}
-
-/**
- * meta_window_get_display:
- * @window: A #MetaWindow
- *
- * Returns: (transfer none): The display for @window
- */
-MetaDisplay *
-meta_window_get_display (MetaWindow *window)
-{
- return window->display;
-}
-
-/**
- * meta_window_get_xwindow: (skip)
- * @window: a #MetaWindow
- *
- */
-Window
-meta_window_get_xwindow (MetaWindow *window)
-{
- return window->xwindow;
-}
-
-MetaWindowType
-meta_window_get_window_type (MetaWindow *window)
-{
- return window->type;
-}
-
-/**
- * meta_window_get_workspace:
- * @window: a #MetaWindow
- *
- * Gets the #MetaWorkspace that the window is currently displayed on.
- * If the window is on all workspaces, returns the currently active
- * workspace.
- *
- * Return value: (transfer none): the #MetaWorkspace for the window
- */
-MetaWorkspace *
-meta_window_get_workspace (MetaWindow *window)
-{
- MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
-
- if (window->on_all_workspaces)
- return workspace_manager->active_workspace;
- else
- return window->workspace;
-}
-
-gboolean
-meta_window_is_on_all_workspaces (MetaWindow *window)
-{
- return window->on_all_workspaces;
-}
-
-gboolean
-meta_window_is_hidden (MetaWindow *window)
-{
- return window->hidden;
-}
-
-const char *
-meta_window_get_description (MetaWindow *window)
-{
- if (!window)
- return NULL;
-
- return window->desc;
-}
-
-/**
- * meta_window_get_wm_class:
- * @window: a #MetaWindow
- *
- * Return the current value of the name part of WM_CLASS X property.
- */
-const char *
-meta_window_get_wm_class (MetaWindow *window)
-{
- if (!window)
- return NULL;
-
- return window->res_class;
-}
-
-/**
- * meta_window_get_wm_class_instance:
- * @window: a #MetaWindow
- *
- * Return the current value of the instance part of WM_CLASS X property.
- */
-const char *
-meta_window_get_wm_class_instance (MetaWindow *window)
-{
- if (!window)
- return NULL;
-
- return window->res_name;
-}
-
-/**
- * meta_window_get_sandboxed_app_id:
- * @window: a #MetaWindow
- *
- * Gets an unique id for a sandboxed app (currently flatpaks and snaps are
- * supported).
- *
- * Return value: (transfer none): the sandboxed application ID or %NULL
- **/
-const char *
-meta_window_get_sandboxed_app_id (MetaWindow *window)
-{
- /* We're abusing this API here not to break the gnome shell assumptions
- * or adding a new function, to be renamed to generic names in new versions */
- return window->sandboxed_app_id;
-}
-
-/**
- * meta_window_get_gtk_theme_variant:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the theme variant or %NULL
- **/
-const char *
-meta_window_get_gtk_theme_variant (MetaWindow *window)
-{
- return window->gtk_theme_variant;
-}
-
-/**
- * meta_window_get_gtk_application_id:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the application ID
- **/
-const char *
-meta_window_get_gtk_application_id (MetaWindow *window)
-{
- return window->gtk_application_id;
-}
-
-/**
- * meta_window_get_gtk_unique_bus_name:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the unique name
- **/
-const char *
-meta_window_get_gtk_unique_bus_name (MetaWindow *window)
-{
- return window->gtk_unique_bus_name;
-}
-
-/**
- * meta_window_get_gtk_application_object_path:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the object path
- **/
-const char *
-meta_window_get_gtk_application_object_path (MetaWindow *window)
-{
- return window->gtk_application_object_path;
-}
-
-/**
- * meta_window_get_gtk_window_object_path:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the object path
- **/
-const char *
-meta_window_get_gtk_window_object_path (MetaWindow *window)
-{
- return window->gtk_window_object_path;
-}
-
-/**
- * meta_window_get_gtk_app_menu_object_path:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the object path
- **/
-const char *
-meta_window_get_gtk_app_menu_object_path (MetaWindow *window)
-{
- return window->gtk_app_menu_object_path;
-}
-
-/**
- * meta_window_get_gtk_menubar_object_path:
- * @window: a #MetaWindow
- *
- * Return value: (transfer none): the object path
- **/
-const char *
-meta_window_get_gtk_menubar_object_path (MetaWindow *window)
-{
- return window->gtk_menubar_object_path;
-}
-
-/**
- * meta_window_get_compositor_private:
- * @window: a #MetaWindow
- *
- * Gets the compositor's wrapper object for @window.
- *
- * Return value: (transfer none): the wrapper object.
- **/
-GObject *
-meta_window_get_compositor_private (MetaWindow *window)
-{
- if (!window)
- return NULL;
- return window->compositor_private;
-}
-
-void
-meta_window_set_compositor_private (MetaWindow *window, GObject *priv)
-{
- if (!window)
- return;
- window->compositor_private = priv;
-}
-
-const char *
-meta_window_get_role (MetaWindow *window)
-{
- if (!window)
- return NULL;
-
- return window->role;
-}
-
-/**
- * meta_window_get_title:
- * @window: a #MetaWindow
- *
- * Returns: the current title of the window.
- */
-const char *
-meta_window_get_title (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), NULL);
-
- return window->title;
-}
-
-MetaStackLayer
-meta_window_get_layer (MetaWindow *window)
-{
- return window->layer;
-}
-
-/**
- * meta_window_get_transient_for:
- * @window: a #MetaWindow
- *
- * Returns the #MetaWindow for the window that is pointed to by the
- * WM_TRANSIENT_FOR hint on this window (see XGetTransientForHint()
- * or XSetTransientForHint()). Metacity keeps transient windows above their
- * parents. A typical usage of this hint is for a dialog that wants to stay
- * above its associated window.
- *
- * Return value: (transfer none): the window this window is transient for, or
- * %NULL if the WM_TRANSIENT_FOR hint is unset or does not point to a toplevel
- * window that Metacity knows about.
- */
-MetaWindow *
-meta_window_get_transient_for (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), NULL);
-
- if (window->transient_for)
- return window->transient_for;
- else if (window->xtransient_for)
- return meta_x11_display_lookup_x_window (window->display->x11_display,
- window->xtransient_for);
- else
- return NULL;
-}
-
-/**
- * meta_window_get_pid:
- * @window: a #MetaWindow
- *
- * Returns the pid of the process that created this window, if available
- * to the windowing system.
- *
- * Note that the value returned by this is vulnerable to spoofing attacks
- * by the client.
- *
- * Return value: the pid, or 0 if not known.
- */
-pid_t
-meta_window_get_pid (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), 0);
-
- if (window->client_pid == 0)
- window->client_pid = META_WINDOW_GET_CLASS (window)->get_client_pid (window);
-
- return window->client_pid;
-}
-
-/**
- * meta_window_get_client_machine:
- * @window: a #MetaWindow
- *
- * Returns name of the client machine from which this windows was created,
- * if known (obtained from the WM_CLIENT_MACHINE property).
- *
- * Return value: (transfer none): the machine name, or NULL; the string is
- * owned by the window manager and should not be freed or modified by the
- * caller.
- */
-const char *
-meta_window_get_client_machine (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), NULL);
-
- return window->wm_client_machine;
-}
-
-/**
- * meta_window_is_remote:
- * @window: a #MetaWindow
- *
- * Returns: %TRUE if this window originates from a host
- * different from the one running mutter.
- */
-gboolean
-meta_window_is_remote (MetaWindow *window)
-{
- return window->is_remote;
-}
-
-/**
- * meta_window_get_mutter_hints:
- * @window: a #MetaWindow
- *
- * Gets the current value of the _MUTTER_HINTS property.
- *
- * The purpose of the hints is to allow fine-tuning of the Window Manager and
- * Compositor behaviour on per-window basis, and is intended primarily for
- * hints that are plugin-specific.
- *
- * The property is a list of colon-separated key=value pairs. The key names for
- * any plugin-specific hints must be suitably namespaced to allow for shared
- * use; 'mutter-' key prefix is reserved for internal use, and must not be used
- * by plugins.
- *
- * Return value: (transfer none): the _MUTTER_HINTS string, or %NULL if no hints
- * are set.
- */
-const char *
-meta_window_get_mutter_hints (MetaWindow *window)
-{
- g_return_val_if_fail (META_IS_WINDOW (window), NULL);
-
- return window->mutter_hints;
-}
-
-/**
- * meta_window_get_frame_type:
- * @window: a #MetaWindow
- *
- * Gets the type of window decorations that should be used for this window.
- *
- * Return value: the frame type
- */
-MetaFrameType
-meta_window_get_frame_type (MetaWindow *window)
-{
- MetaFrameType base_type = META_FRAME_TYPE_LAST;
-
- switch (window->type)
- {
- case META_WINDOW_NORMAL:
- base_type = META_FRAME_TYPE_NORMAL;
- break;
-
- case META_WINDOW_DIALOG:
- base_type = META_FRAME_TYPE_DIALOG;
- break;
-
- case META_WINDOW_MODAL_DIALOG:
- if (meta_window_is_attached_dialog (window))
- base_type = META_FRAME_TYPE_ATTACHED;
- else
- base_type = META_FRAME_TYPE_MODAL_DIALOG;
- break;
-
- case META_WINDOW_MENU:
- base_type = META_FRAME_TYPE_MENU;
- break;
-
- case META_WINDOW_UTILITY:
- base_type = META_FRAME_TYPE_UTILITY;
- break;
-
- case META_WINDOW_DESKTOP:
- case META_WINDOW_DOCK:
- case META_WINDOW_TOOLBAR:
- case META_WINDOW_SPLASHSCREEN:
- case META_WINDOW_DROPDOWN_MENU:
- case META_WINDOW_POPUP_MENU:
- case META_WINDOW_TOOLTIP:
- case META_WINDOW_NOTIFICATION:
- case META_WINDOW_COMBO:
- case META_WINDOW_DND:
- case META_WINDOW_OVERRIDE_OTHER:
- /* No frame */
- base_type = META_FRAME_TYPE_LAST;
- break;
- }
-
- if (base_type == META_FRAME_TYPE_LAST)
- {
- /* can't add border if undecorated */
- return META_FRAME_TYPE_LAST;
- }
- else if (window->border_only)
- {
- /* override base frame type */
- return META_FRAME_TYPE_BORDER;
- }
- else
- {
- return base_type;
- }
-}
-
-/**
- * meta_window_get_frame_bounds:
- * @window: a #MetaWindow
- *
- * Gets a region representing the outer bounds of the window's frame.
- *
- * Return value: (transfer none) (nullable): a #cairo_region_t
- * holding the outer bounds of the window, or %NULL if the window
- * doesn't have a frame.
- */
-cairo_region_t *
-meta_window_get_frame_bounds (MetaWindow *window)
-{
- if (!window->frame_bounds)
- {
- if (window->frame)
- window->frame_bounds = meta_frame_get_frame_bounds (window->frame);
- }
-
- return window->frame_bounds;
-}
-
-/**
- * meta_window_is_attached_dialog:
- * @window: a #MetaWindow
- *
- * Tests if @window is should be attached to its parent window.
- * (If the "attach_modal_dialogs" option is not enabled, this will
- * always return %FALSE.)
- *
- * Return value: whether @window should be attached to its parent
- */
-gboolean
-meta_window_is_attached_dialog (MetaWindow *window)
-{
- return window->attached;
-}
-
-/**
- * meta_window_get_tile_match:
- * @window: a #MetaWindow
- *
- * Returns the matching tiled window on the same monitor as @window. This is
- * the topmost tiled window in a complementary tile mode that is:
- *
- * - on the same monitor;
- * - on the same workspace;
- * - spanning the remaining monitor width;
- * - there is no 3rd window stacked between both tiled windows that's
- * partially visible in the common edge.
- *
- * Return value: (transfer none) (nullable): the matching tiled window or
- * %NULL if it doesn't exist.
- */
-MetaWindow *
-meta_window_get_tile_match (MetaWindow *window)
-{
- return window->tile_match;
-}
-
-void
-meta_window_compute_tile_match (MetaWindow *window)
-{
- window->tile_match = meta_window_find_tile_match (window, window->tile_mode);
-}
-
-static MetaWindow *
-meta_window_find_tile_match (MetaWindow *window,
- MetaTileMode current_mode)
-{
- MetaWindow *match;
- MetaStack *stack;
- MetaTileMode match_tile_mode = META_TILE_NONE;
-
- if (window->shaded || window->minimized)
- return NULL;
-
- if (current_mode == META_TILE_LEFT)
- match_tile_mode = META_TILE_RIGHT;
- else if (current_mode == META_TILE_RIGHT)
- match_tile_mode = META_TILE_LEFT;
- else
- return NULL;
-
- stack = window->display->stack;
-
- for (match = meta_stack_get_top (stack);
- match;
- match = meta_stack_get_below (stack, match, FALSE))
- {
- if (!match->shaded &&
- !match->minimized &&
- match->tile_mode == match_tile_mode &&
- match->tile_monitor_number == window->tile_monitor_number &&
- meta_window_get_workspace (match) == meta_window_get_workspace (window))
- break;
- }
-
- if (match)
- {
- MetaWindow *above, *bottommost, *topmost;
- MetaRectangle above_rect, bottommost_rect, topmost_rect;
-
- if (meta_stack_windows_cmp (window->display->stack, match, window) > 0)
- {
- topmost = match;
- bottommost = window;
- }
- else
- {
- topmost = window;
- bottommost = match;
- }
-
- meta_window_get_frame_rect (bottommost, &bottommost_rect);
- meta_window_get_frame_rect (topmost, &topmost_rect);
-
- /*
- * If we are looking for a tile match while actually being tiled,
- * rather than a match for a potential tile mode, then discard
- * windows with too much gap or overlap
- */
- if (window->tile_mode == current_mode &&
- !(meta_grab_op_is_resizing (window->display->grab_op) &&
- window->display->grab_window == window &&
- window->tile_match != NULL))
- {
- int threshold = meta_prefs_get_drag_threshold ();
- if (ABS (topmost_rect.x - bottommost_rect.x - bottommost_rect.width) > threshold &&
- ABS (bottommost_rect.x - topmost_rect.x - topmost_rect.width) > threshold)
- return NULL;
- }
-
- /*
- * If there's a window stacked in between which is partially visible
- * behind the topmost tile we don't consider the tiles to match.
- */
- for (above = meta_stack_get_above (stack, bottommost, FALSE);
- above && above != topmost;
- above = meta_stack_get_above (stack, above, FALSE))
- {
- if (above->minimized ||
- above->monitor != window->monitor ||
- meta_window_get_workspace (above) != meta_window_get_workspace (window))
- continue;
-
- meta_window_get_frame_rect (above, &above_rect);
-
- if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
- meta_rectangle_overlap (&above_rect, &topmost_rect))
- return NULL;
- }
- }
-
- return match;
-}
-
-void
-meta_window_set_title (MetaWindow *window,
- const char *title)
-{
- g_free (window->title);
- window->title = g_strdup (title);
-
- if (window->frame)
- meta_frame_update_title (window->frame);
-
- meta_window_update_desc (window);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_TITLE]);
-}
-
-void
-meta_window_set_wm_class (MetaWindow *window,
- const char *wm_class,
- const char *wm_instance)
-{
- g_free (window->res_class);
- g_free (window->res_name);
-
- window->res_name = g_strdup (wm_instance);
- window->res_class = g_strdup (wm_class);
-
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_WM_CLASS]);
-}
-
-void
-meta_window_set_gtk_dbus_properties (MetaWindow *window,
- const char *application_id,
- const char *unique_bus_name,
- const char *appmenu_path,
- const char *menubar_path,
- const char *application_object_path,
- const char *window_object_path)
-{
- g_object_freeze_notify (G_OBJECT (window));
-
- g_free (window->gtk_application_id);
- window->gtk_application_id = g_strdup (application_id);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_APPLICATION_ID]);
-
- g_free (window->gtk_unique_bus_name);
- window->gtk_unique_bus_name = g_strdup (unique_bus_name);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_UNIQUE_BUS_NAME]);
-
- g_free (window->gtk_app_menu_object_path);
- window->gtk_app_menu_object_path = g_strdup (appmenu_path);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_APP_MENU_OBJECT_PATH]);
-
- g_free (window->gtk_menubar_object_path);
- window->gtk_menubar_object_path = g_strdup (menubar_path);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_MENUBAR_OBJECT_PATH]);
-
- g_free (window->gtk_application_object_path);
- window->gtk_application_object_path = g_strdup (application_object_path);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_APPLICATION_OBJECT_PATH]);
-
- g_free (window->gtk_window_object_path);
- window->gtk_window_object_path = g_strdup (window_object_path);
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_WINDOW_OBJECT_PATH]);
-
- g_object_thaw_notify (G_OBJECT (window));
-}
-
-static gboolean
-check_transient_for_loop (MetaWindow *window,
- MetaWindow *parent)
-{
- while (parent)
- {
- if (parent == window)
- return TRUE;
- parent = parent->transient_for;
- }
-
- return FALSE;
-}
-
-gboolean
-meta_window_has_transient_type (MetaWindow *window)
-{
- return (window->type == META_WINDOW_DIALOG ||
- window->type == META_WINDOW_MODAL_DIALOG ||
- window->type == META_WINDOW_TOOLBAR ||
- window->type == META_WINDOW_MENU ||
- window->type == META_WINDOW_UTILITY);
-}
-
-void
-meta_window_set_transient_for (MetaWindow *window,
- MetaWindow *parent)
-{
- if (check_transient_for_loop (window, parent))
- {
- meta_warning ("Setting %s transient for %s would create a loop.",
- window->desc, parent->desc);
- return;
- }
-
- if (meta_window_appears_focused (window) && window->transient_for != NULL)
- meta_window_propagate_focus_appearance (window, FALSE);
-
- /* may now be a dialog */
- if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- {
- meta_window_x11_recalc_window_type (window);
-
- if (!window->constructing)
- {
- /* If the window attaches, detaches, or changes attached
- * parents, we need to destroy the MetaWindow and let a new one
- * be created (which happens as a side effect of
- * meta_window_unmanage()). The condition below is correct
- * because we know window->transient_for has changed.
- */
- if (window->attached || meta_window_should_attach_to_parent (window))
- {
- guint32 timestamp;
-
- timestamp =
- meta_display_get_current_time_roundtrip (window->display);
- meta_window_unmanage (window, timestamp);
- return;
- }
- }
- }
- else if (window->attached && parent == NULL)
- {
- guint32 timestamp;
-
- timestamp =
- meta_display_get_current_time_roundtrip (window->display);
- meta_window_unmanage (window, timestamp);
- return;
- }
- /* We know this won't create a reference cycle because we check for loops */
- g_clear_object (&window->transient_for);
- window->transient_for = parent ? g_object_ref (parent) : NULL;
-
- /* update stacking constraints */
- if (!window->override_redirect)
- meta_stack_update_transient (window->display->stack, window);
-
- /* possibly change its group. We treat being a window's transient as
- * equivalent to making it your group leader, to work around shortcomings
- * in programs such as xmms-- see #328211.
- */
- if (window->xtransient_for != None &&
- window->xgroup_leader != None &&
- window->xtransient_for != window->xgroup_leader)
- meta_window_group_leader_changed (window);
-
- if (!window->constructing && !window->override_redirect)
- meta_window_queue (window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
-
- if (meta_window_appears_focused (window) && window->transient_for != NULL)
- meta_window_propagate_focus_appearance (window, TRUE);
-}
-
-void
-meta_window_set_opacity (MetaWindow *window,
- guint8 opacity)
-{
- window->opacity = opacity;
-
- meta_compositor_window_opacity_changed (window->display->compositor, window);
-}
-
-static void
-reset_ignored_crossing_serials (MetaDisplay *display)
-{
- int i;
-
- i = 0;
- while (i < N_IGNORED_CROSSING_SERIALS)
- {
- display->ignored_crossing_serials[i] = 0;
- ++i;
- }
-}
-
-typedef struct
-{
- MetaWindow *window;
- int pointer_x;
- int pointer_y;
-} MetaFocusData;
-
-static void
-mouse_mode_focus (MetaWindow *window,
- guint32 timestamp)
-{
- MetaDisplay *display = window->display;
-
- if (window->override_redirect)
- return;
-
- if (window->type != META_WINDOW_DESKTOP)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s at time %u.", window->desc, timestamp);
-
- meta_window_focus (window, timestamp);
-
- if (meta_prefs_get_auto_raise ())
- meta_display_queue_autoraise_callback (display, window);
- else
- meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled");
- }
- else
- {
- /* In mouse focus mode, we defocus when the mouse *enters*
- * the DESKTOP window, instead of defocusing on LeaveNotify.
- * This is because having the mouse enter override-redirect
- * child windows unfortunately causes LeaveNotify events that
- * we can't distinguish from the mouse actually leaving the
- * toplevel window as we expect. But, since we filter out
- * EnterNotify events on override-redirect windows, this
- * alternative mechanism works great.
- */
- if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
- display->focus_window != NULL)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Unsetting focus from %s due to mouse entering "
- "the DESKTOP window",
- display->focus_window->desc);
- meta_display_unset_input_focus (display, timestamp);
- }
- }
-}
-
-static gboolean
-window_has_pointer_wayland (MetaWindow *window)
-{
- ClutterSeat *seat;
- ClutterInputDevice *dev;
- ClutterStage *stage;
- ClutterActor *pointer_actor, *window_actor;
-
- seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
- dev = clutter_seat_get_pointer (seat);
- stage = CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ()));
- pointer_actor = clutter_stage_get_device_actor (stage, dev, NULL);
- window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
-
- return pointer_actor && clutter_actor_contains (window_actor, pointer_actor);
-}
-
-static gboolean
-window_has_pointer_x11 (MetaWindow *window)
-{
- MetaX11Display *x11_display = window->display->x11_display;
- Window root, child;
- double root_x, root_y, x, y;
- XIButtonState buttons;
- XIModifierState mods;
- XIGroupState group;
-
- meta_x11_error_trap_push (x11_display);
- XIQueryPointer (x11_display->xdisplay,
- META_VIRTUAL_CORE_POINTER_ID,
- x11_display->xroot,
- &root, &child,
- &root_x, &root_y, &x, &y,
- &buttons, &mods, &group);
- meta_x11_error_trap_pop (x11_display);
- free (buttons.mask);
-
- return meta_x11_display_lookup_x_window (x11_display, child) == window;
-}
-
-gboolean
-meta_window_has_pointer (MetaWindow *window)
-{
- if (meta_is_wayland_compositor ())
- return window_has_pointer_wayland (window);
- else
- return window_has_pointer_x11 (window);
-}
-
-static gboolean
-window_focus_on_pointer_rest_callback (gpointer data)
-{
- MetaFocusData *focus_data = data;
- MetaWindow *window = focus_data->window;
- MetaDisplay *display = window->display;
- MetaBackend *backend = meta_get_backend ();
- MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
- graphene_point_t point;
- guint32 timestamp;
-
- if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
- goto out;
-
- meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
-
- if ((int) point.x != focus_data->pointer_x ||
- (int) point.y != focus_data->pointer_y)
- {
- focus_data->pointer_x = point.x;
- focus_data->pointer_y = point.y;
- return G_SOURCE_CONTINUE;
- }
-
- if (!meta_window_has_pointer (window))
- goto out;
-
- timestamp = meta_display_get_current_time_roundtrip (display);
- mouse_mode_focus (window, timestamp);
-
- out:
- display->focus_timeout_id = 0;
- return G_SOURCE_REMOVE;
-}
-
-/* The interval, in milliseconds, we use in focus-follows-mouse
- * mode to check whether the pointer has stopped moving after a
- * crossing event.
- */
-#define FOCUS_TIMEOUT_DELAY 25
-
-static void
-queue_focus_callback (MetaDisplay *display,
- MetaWindow *window,
- int pointer_x,
- int pointer_y)
-{
- MetaFocusData *focus_data;
-
- focus_data = g_new (MetaFocusData, 1);
- focus_data->window = window;
- focus_data->pointer_x = pointer_x;
- focus_data->pointer_y = pointer_y;
-
- g_clear_handle_id (&display->focus_timeout_id, g_source_remove);
-
- display->focus_timeout_id =
- g_timeout_add_full (G_PRIORITY_DEFAULT,
- FOCUS_TIMEOUT_DELAY,
- window_focus_on_pointer_rest_callback,
- focus_data,
- g_free);
- g_source_set_name_by_id (display->focus_timeout_id,
- "[mutter] window_focus_on_pointer_rest_callback");
-}
-
-void
-meta_window_handle_enter (MetaWindow *window,
- guint32 timestamp,
- guint root_x,
- guint root_y)
-{
- MetaDisplay *display = window->display;
-
- switch (meta_prefs_get_focus_mode ())
- {
- case G_DESKTOP_FOCUS_MODE_SLOPPY:
- case G_DESKTOP_FOCUS_MODE_MOUSE:
- display->mouse_mode = TRUE;
- if (window->type != META_WINDOW_DOCK)
- {
- if (meta_prefs_get_focus_change_on_pointer_rest())
- queue_focus_callback (display, window, root_x, root_y);
- else
- mouse_mode_focus (window, timestamp);
-
- /* stop ignoring stuff */
- reset_ignored_crossing_serials (display);
- }
- break;
- case G_DESKTOP_FOCUS_MODE_CLICK:
- break;
- }
-
- if (window->type == META_WINDOW_DOCK)
- meta_window_raise (window);
-}
-
-void
-meta_window_handle_leave (MetaWindow *window)
-{
- if (window->type == META_WINDOW_DOCK && !window->has_focus)
- meta_window_lower (window);
-}
-
-gboolean
-meta_window_handle_ui_frame_event (MetaWindow *window,
- const ClutterEvent *event)
-{
- if (!window->frame)
- return FALSE;
-
- return meta_ui_frame_handle_event (window->frame->ui_frame, event);
-}
-
-void
-meta_window_handle_ungrabbed_event (MetaWindow *window,
- const ClutterEvent *event)
-{
- MetaDisplay *display = window->display;
- gboolean unmodified;
- gboolean is_window_grab;
- gboolean is_window_button_grab_allowed;
- ClutterModifierType grab_mods, event_mods;
- ClutterInputDevice *source;
- gfloat x, y;
- guint button;
-
- if (window->unmanaging)
- return;
-
- if (event->type != CLUTTER_BUTTON_PRESS &&
- event->type != CLUTTER_TOUCH_BEGIN)
- return;
-
- if (event->type == CLUTTER_TOUCH_BEGIN)
- {
- ClutterEventSequence *sequence;
-
- button = 1;
- sequence = clutter_event_get_event_sequence (event);
- if (!meta_display_is_pointer_emulating_sequence (window->display, sequence))
- return;
- }
- else
- button = clutter_event_get_button (event);
-
- if (display->grab_op != META_GRAB_OP_NONE)
- return;
-
- /* Some windows might not ask for input, in which case we might be here
- * because we selected for ButtonPress on the root window. In that case,
- * we have to take special care not to act for an override-redirect window.
- */
- if (window->override_redirect)
- return;
-
- /* Don't focus panels--they must explicitly request focus.
- * See bug 160470
- */
- if (window->type != META_WINDOW_DOCK)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s due to button %u press (display.c)",
- window->desc, button);
- meta_window_focus (window, event->any.time);
- meta_window_check_alive (window, event->any.time);
- }
- else
- /* However, do allow terminals to lose focus due to new
- * window mappings after the user clicks on a panel.
- */
- display->allow_terminal_deactivation = TRUE;
-
- /* We have three passive button grabs:
- * - on any button, without modifiers => focuses and maybe raises the window
- * - on resize button, with modifiers => start an interactive resizing
- * (normally <Super>middle)
- * - on move button, with modifiers => start an interactive move
- * (normally <Super>left)
- * - on menu button, with modifiers => show the window menu
- * (normally <Super>right)
- *
- * We may get here because we actually have a button
- * grab on the window, or because we're a wayland
- * compositor and thus we see all the events, so we
- * need to check if the event is interesting.
- * We want an event that is not modified for a window.
- *
- * We may have other events on the window, for example
- * a click on a frame button, but that's not for us to
- * care about. Just let the event through.
- */
-
- grab_mods = meta_display_get_compositor_modifiers (display);
- event_mods = clutter_event_get_state (event);
- unmodified = (event_mods & grab_mods) == 0;
- source = clutter_event_get_source_device (event);
- is_window_button_grab_allowed = !display->focus_window ||
- !meta_window_shortcuts_inhibited (display->focus_window, source);
- is_window_grab = (is_window_button_grab_allowed &&
- ((event_mods & grab_mods) == grab_mods));
-
- clutter_event_get_coords (event, &x, &y);
-
- if (unmodified)
- {
- if (meta_prefs_get_raise_on_click ())
- meta_window_raise (window);
- else
- meta_topic (META_DEBUG_FOCUS,
- "Not raising window on click due to don't-raise-on-click option");
- }
- else if (is_window_grab && (int) button == meta_prefs_get_mouse_button_resize ())
- {
- if (window->has_resize_func)
- {
- gboolean north, south;
- gboolean west, east;
- MetaRectangle frame_rect;
- MetaGrabOp op = META_GRAB_OP_WINDOW_BASE;
-
- meta_window_get_frame_rect (window, &frame_rect);
-
- west = x < (frame_rect.x + 1 * frame_rect.width / 3);
- east = x > (frame_rect.x + 2 * frame_rect.width / 3);
- north = y < (frame_rect.y + 1 * frame_rect.height / 3);
- south = y > (frame_rect.y + 2 * frame_rect.height / 3);
-
- if (west)
- op |= META_GRAB_OP_WINDOW_DIR_WEST;
- if (east)
- op |= META_GRAB_OP_WINDOW_DIR_EAST;
- if (north)
- op |= META_GRAB_OP_WINDOW_DIR_NORTH;
- if (south)
- op |= META_GRAB_OP_WINDOW_DIR_SOUTH;
-
- if (op != META_GRAB_OP_WINDOW_BASE)
- meta_display_begin_grab_op (display,
- window,
- op,
- TRUE,
- FALSE,
- button,
- 0,
- event->any.time,
- x, y);
- }
- }
- else if (is_window_grab && (int) button == meta_prefs_get_mouse_button_menu ())
- {
- if (meta_prefs_get_raise_on_click ())
- meta_window_raise (window);
- meta_window_show_menu (window,
- META_WINDOW_MENU_WM,
- x, y);
- }
- else if (is_window_grab && (int) button == 1)
- {
- if (window->has_move_func)
- {
- meta_display_begin_grab_op (display,
- window,
- META_GRAB_OP_MOVING,
- TRUE,
- FALSE,
- button,
- 0,
- event->any.time,
- x, y);
- }
- }
-}
-
-gboolean
-meta_window_can_maximize (MetaWindow *window)
-{
- return window->has_maximize_func;
-}
-
-gboolean
-meta_window_can_minimize (MetaWindow *window)
-{
- return window->has_minimize_func;
-}
-
-gboolean
-meta_window_can_shade (MetaWindow *window)
-{
- return window->has_shade_func;
-}
-
-gboolean
-meta_window_can_close (MetaWindow *window)
-{
- return window->has_close_func;
-}
-
-gboolean
-meta_window_is_always_on_all_workspaces (MetaWindow *window)
-{
- return window->always_sticky;
-}
-
-gboolean
-meta_window_is_above (MetaWindow *window)
-{
- return window->wm_state_above;
-}
-
-gboolean
-meta_window_allows_move (MetaWindow *window)
-{
- return META_WINDOW_ALLOWS_MOVE (window);
-}
-
-gboolean
-meta_window_allows_resize (MetaWindow *window)
-{
- return META_WINDOW_ALLOWS_RESIZE (window);
-}
-
-void
-meta_window_set_urgent (MetaWindow *window,
- gboolean urgent)
-{
- if (window->urgent == urgent)
- return;
-
- window->urgent = urgent;
- g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_URGENT]);
-
- if (urgent)
- g_signal_emit_by_name (window->display, "window-marked-urgent", window);
-}
-
-void
-meta_window_grab_op_began (MetaWindow *window,
- MetaGrabOp op)
-{
- META_WINDOW_GET_CLASS (window)->grab_op_began (window, op);
-}
-
-void
-meta_window_grab_op_ended (MetaWindow *window,
- MetaGrabOp op)
-{
- META_WINDOW_GET_CLASS (window)->grab_op_ended (window, op);
-}
-
-void
-meta_window_emit_size_changed (MetaWindow *window)
-{
- g_signal_emit (window, window_signals[SIZE_CHANGED], 0);
-}
-
-MetaPlacementRule *
-meta_window_get_placement_rule (MetaWindow *window)
-{
- return window->placement.rule;
-}
-
-void
-meta_window_force_restore_shortcuts (MetaWindow *window,
- ClutterInputDevice *source)
-{
- META_WINDOW_GET_CLASS (window)->force_restore_shortcuts (window, source);
-}
-
-gboolean
-meta_window_shortcuts_inhibited (MetaWindow *window,
- ClutterInputDevice *source)
-{
- return META_WINDOW_GET_CLASS (window)->shortcuts_inhibited (window, source);
-}
-
-gboolean
-meta_window_is_focusable (MetaWindow *window)
-{
- g_return_val_if_fail (!window->unmanaging, FALSE);
-
- return META_WINDOW_GET_CLASS (window)->is_focusable (window);
-}
-
-gboolean
-meta_window_can_ping (MetaWindow *window)
-{
- g_return_val_if_fail (!window->unmanaging, FALSE);
-
- return META_WINDOW_GET_CLASS (window)->can_ping (window);
-}
-
-gboolean
-meta_window_is_stackable (MetaWindow *window)
-{
- return META_WINDOW_GET_CLASS (window)->is_stackable (window);
-}
-
-gboolean
-meta_window_is_focus_async (MetaWindow *window)
-{
- return META_WINDOW_GET_CLASS (window)->is_focus_async (window);
-}
-
-MetaStackLayer
-meta_window_calculate_layer (MetaWindow *window)
-{
- return META_WINDOW_GET_CLASS (window)->calculate_layer (window);
-}
-
-/**
- * meta_window_get_id:
- * @window: a #MetaWindow
- *
- * Returns the window id associated with window.
- *
- * Returns: The window id
- */
-uint64_t
-meta_window_get_id (MetaWindow *window)
-{
- return window->id;
-}
-
-/**
- * meta_window_get_client_type:
- * @window: a #MetaWindow
- *
- * Returns the #MetaWindowClientType of the window.
- *
- * Returns: The root ancestor window
- */
-MetaWindowClientType
-meta_window_get_client_type (MetaWindow *window)
-{
- return window->client_type;
-}
diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h
deleted file mode 100644
index a58b2347d..000000000
--- a/src/core/workspace-private.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/**
- * \file workspace.h Workspaces
- *
- * A workspace is a set of windows which all live on the same
- * screen. (You may also see the name "desktop" around the place,
- * which is the EWMH's name for the same thing.) Only one workspace
- * of a screen may be active at once; all windows on all other workspaces
- * are unmapped.
- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2004, 2005 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/>.
- */
-
-#ifndef META_WORKSPACE_PRIVATE_H
-#define META_WORKSPACE_PRIVATE_H
-
-#include "core/window-private.h"
-#include "meta/workspace.h"
-
-struct _MetaWorkspace
-{
- GObject parent_instance;
- MetaDisplay *display;
- MetaWorkspaceManager *manager;
-
- GList *windows;
-
- /* The "MRU list", or "most recently used" list, is a list of
- * MetaWindows ordered based on the time the the user interacted
- * with the window most recently.
- *
- * For historical reasons, we keep an MRU list per workspace.
- * It used to be used to calculate the default focused window,
- * but isn't anymore, as the window next in the stacking order
- * can sometimes be not the window the user interacted with last,
- */
- GList *mru_list;
-
- GList *list_containing_self;
-
- GHashTable *logical_monitor_data;
-
- MetaRectangle work_area_screen;
- GList *screen_region;
- GList *screen_edges;
- GList *monitor_edges;
- GSList *builtin_struts;
- GSList *all_struts;
- guint work_areas_invalid : 1;
-
- guint showing_desktop : 1;
-};
-
-struct _MetaWorkspaceClass
-{
- GObjectClass parent_class;
-};
-
-MetaWorkspace* meta_workspace_new (MetaWorkspaceManager *workspace_manager);
-void meta_workspace_remove (MetaWorkspace *workspace);
-void meta_workspace_add_window (MetaWorkspace *workspace,
- MetaWindow *window);
-void meta_workspace_remove_window (MetaWorkspace *workspace,
- MetaWindow *window);
-void meta_workspace_relocate_windows (MetaWorkspace *workspace,
- MetaWorkspace *new_home);
-
-void meta_workspace_get_work_area_for_logical_monitor (MetaWorkspace *workspace,
- MetaLogicalMonitor *logical_monitor,
- MetaRectangle *area);
-
-void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
-
-GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace);
-GList * meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
- MetaLogicalMonitor *logical_monitor);
-
-void meta_workspace_focus_default_window (MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- guint32 timestamp);
-
-const char* meta_workspace_get_name (MetaWorkspace *workspace);
-
-void meta_workspace_index_changed (MetaWorkspace *workspace);
-
-#endif
diff --git a/src/core/workspace.c b/src/core/workspace.c
deleted file mode 100644
index 321d3efb0..000000000
--- a/src/core/workspace.c
+++ /dev/null
@@ -1,1477 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2003 Rob Adams
- * Copyright (C) 2004, 2005 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:workspace
- * @title:MetaWorkspace
- * @short_description:Workspaces
- *
- * A workspace is a set of windows which all live on the same
- * screen. (You may also see the name "desktop" around the place,
- * which is the EWMH's name for the same thing.) Only one workspace
- * of a screen may be active at once; all windows on all other workspaces
- * are unmapped.
- */
-
-#include "config.h"
-
-#include "meta/workspace.h"
-
-#include <X11/Xatom.h>
-#include <string.h>
-
-#include "backends/meta-backend-private.h"
-#include "backends/meta-logical-monitor.h"
-#include "cogl/cogl.h"
-#include "core/boxes-private.h"
-#include "core/meta-workspace-manager-private.h"
-#include "core/workspace-private.h"
-#include "meta/compositor.h"
-#include "meta/meta-x11-errors.h"
-#include "meta/prefs.h"
-#include "x11/meta-x11-display-private.h"
-
-void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
-static void focus_ancestor_or_top_window (MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- guint32 timestamp);
-
-G_DEFINE_TYPE (MetaWorkspace, meta_workspace, G_TYPE_OBJECT);
-
-enum
-{
- PROP_0,
-
- PROP_N_WINDOWS,
- PROP_WORKSPACE_INDEX,
- PROP_ACTIVE,
-
- PROP_LAST,
-};
-
-static GParamSpec *obj_props[PROP_LAST];
-
-enum
-{
- WINDOW_ADDED,
- WINDOW_REMOVED,
-
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-typedef struct _MetaWorkspaceLogicalMonitorData
-{
- GList *logical_monitor_region;
- MetaRectangle logical_monitor_work_area;
-} MetaWorkspaceLogicalMonitorData;
-
-typedef struct _MetaWorkspaceFocusableAncestorData
-{
- MetaWorkspace *workspace;
- MetaWindow *out_window;
-} MetaWorkspaceFocusableAncestorData;
-
-static MetaWorkspaceLogicalMonitorData *
-meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace,
- MetaLogicalMonitor *logical_monitor)
-{
- if (!workspace->logical_monitor_data)
- return NULL;
- return g_hash_table_lookup (workspace->logical_monitor_data, logical_monitor);
-}
-
-static void
-workspace_logical_monitor_data_free (MetaWorkspaceLogicalMonitorData *data)
-{
- g_clear_pointer (&data->logical_monitor_region,
- meta_rectangle_free_list_and_elements);
- g_free (data);
-}
-
-static MetaWorkspaceLogicalMonitorData *
-meta_workspace_ensure_logical_monitor_data (MetaWorkspace *workspace,
- MetaLogicalMonitor *logical_monitor)
-{
- MetaWorkspaceLogicalMonitorData *data;
-
- data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor);
- if (data)
- return data;
-
- if (!workspace->logical_monitor_data)
- {
- workspace->logical_monitor_data =
- g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- (GDestroyNotify) workspace_logical_monitor_data_free);
- }
-
- data = g_new0 (MetaWorkspaceLogicalMonitorData, 1);
- g_hash_table_insert (workspace->logical_monitor_data, logical_monitor, data);
-
- return data;
-}
-
-static void
-meta_workspace_clear_logical_monitor_data (MetaWorkspace *workspace)
-{
- g_clear_pointer (&workspace->logical_monitor_data, g_hash_table_destroy);
-}
-
-static void
-meta_workspace_finalize (GObject *object)
-{
- /* Actual freeing done in meta_workspace_remove() for now */
- G_OBJECT_CLASS (meta_workspace_parent_class)->finalize (object);
-}
-
-static void
-meta_workspace_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_workspace_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MetaWorkspace *ws = META_WORKSPACE (object);
-
- switch (prop_id)
- {
- case PROP_N_WINDOWS:
- /*
- * This is reliable, but not very efficient; should we store
- * the list length ?
- */
- g_value_set_uint (value, g_list_length (ws->windows));
- break;
- case PROP_WORKSPACE_INDEX:
- g_value_set_uint (value, meta_workspace_index (ws));
- break;
- case PROP_ACTIVE:
- g_value_set_boolean (value, ws->manager->active_workspace == ws);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-meta_workspace_class_init (MetaWorkspaceClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = meta_workspace_finalize;
- object_class->get_property = meta_workspace_get_property;
- object_class->set_property = meta_workspace_set_property;
-
- signals[WINDOW_ADDED] = g_signal_new ("window-added",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- META_TYPE_WINDOW);
- signals[WINDOW_REMOVED] = g_signal_new ("window-removed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- META_TYPE_WINDOW);
-
- obj_props[PROP_N_WINDOWS] = g_param_spec_uint ("n-windows",
- "N Windows",
- "Number of windows",
- 0, G_MAXUINT, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_WORKSPACE_INDEX] = g_param_spec_uint ("workspace-index",
- "Workspace index",
- "The workspace's index",
- 0, G_MAXUINT, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_props[PROP_ACTIVE] = g_param_spec_boolean ("active",
- "Active",
- "Whether the workspace is currently active",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, PROP_LAST, obj_props);
-}
-
-static void
-meta_workspace_init (MetaWorkspace *workspace)
-{
-}
-
-MetaWorkspace *
-meta_workspace_new (MetaWorkspaceManager *workspace_manager)
-{
- MetaDisplay *display = workspace_manager->display;
- MetaWorkspace *workspace;
- GSList *windows, *l;
-
- workspace = g_object_new (META_TYPE_WORKSPACE, NULL);
-
- workspace->display = display;
- workspace->manager = workspace_manager;
-
- workspace_manager->workspaces =
- g_list_append (workspace_manager->workspaces, workspace);
- workspace->windows = NULL;
- workspace->mru_list = NULL;
-
- workspace->work_areas_invalid = TRUE;
- workspace->work_area_screen.x = 0;
- workspace->work_area_screen.y = 0;
- workspace->work_area_screen.width = 0;
- workspace->work_area_screen.height = 0;
-
- workspace->screen_region = NULL;
- workspace->screen_edges = NULL;
- workspace->monitor_edges = NULL;
- workspace->list_containing_self = g_list_prepend (NULL, workspace);
-
- workspace->builtin_struts = NULL;
- workspace->all_struts = NULL;
-
- workspace->showing_desktop = FALSE;
-
- /* make sure sticky windows are in our mru_list */
- windows = meta_display_list_windows (display, META_LIST_SORTED);
- for (l = windows; l; l = l->next)
- if (meta_window_located_on_workspace (l->data, workspace))
- meta_workspace_add_window (workspace, l->data);
- g_slist_free (windows);
-
- return workspace;
-}
-
-/**
- * workspace_free_all_struts:
- * @workspace: The workspace.
- *
- * Frees the combined struts list of a workspace.
- */
-static void
-workspace_free_all_struts (MetaWorkspace *workspace)
-{
- if (workspace->all_struts == NULL)
- return;
-
- g_slist_free_full (workspace->all_struts, g_free);
- workspace->all_struts = NULL;
-}
-
-/**
- * workspace_free_builtin_struts:
- * @workspace: The workspace.
- *
- * Frees the struts list set with meta_workspace_set_builtin_struts
- */
-static void
-workspace_free_builtin_struts (MetaWorkspace *workspace)
-{
- if (workspace->builtin_struts == NULL)
- return;
-
- g_slist_free_full (workspace->builtin_struts, g_free);
- workspace->builtin_struts = NULL;
-}
-
-/* Ensure that the workspace is empty by making sure that
- * all of our windows are on-all-workspaces. */
-static void
-assert_workspace_empty (MetaWorkspace *workspace)
-{
- GList *l;
- for (l = workspace->windows; l != NULL; l = l->next)
- {
- MetaWindow *window = l->data;
- g_assert (window->on_all_workspaces);
- }
-}
-
-void
-meta_workspace_remove (MetaWorkspace *workspace)
-{
- MetaWorkspaceManager *manager = workspace->display->workspace_manager;
-
- g_return_if_fail (workspace != manager->active_workspace);
-
- assert_workspace_empty (workspace);
-
- manager->workspaces =
- g_list_remove (manager->workspaces, workspace);
-
- meta_workspace_clear_logical_monitor_data (workspace);
-
- g_list_free (workspace->mru_list);
- g_list_free (workspace->list_containing_self);
-
- workspace_free_builtin_struts (workspace);
-
- /* screen.c:update_num_workspaces(), which calls us, removes windows from
- * workspaces first, which can cause the workareas on the workspace to be
- * invalidated (and hence for struts/regions/edges to be freed).
- * So, no point trying to double free it; that causes a crash
- * anyway. #361804.
- */
-
- if (!workspace->work_areas_invalid)
- {
- workspace_free_all_struts (workspace);
- meta_rectangle_free_list_and_elements (workspace->screen_region);
- meta_rectangle_free_list_and_elements (workspace->screen_edges);
- meta_rectangle_free_list_and_elements (workspace->monitor_edges);
- }
-
- g_object_unref (workspace);
-
- /* don't bother to reset names, pagers can just ignore
- * extra ones
- */
-}
-
-void
-meta_workspace_add_window (MetaWorkspace *workspace,
- MetaWindow *window)
-{
- g_return_if_fail (g_list_find (workspace->mru_list, window) == NULL);
-
- COGL_TRACE_BEGIN_SCOPED (MetaWorkspaceAddWindow,
- "Workspace (add window)");
-
- workspace->mru_list = g_list_prepend (workspace->mru_list, window);
-
- workspace->windows = g_list_prepend (workspace->windows, window);
-
- if (window->struts)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Invalidating work area of workspace %d since we're adding window %s to it",
- meta_workspace_index (workspace), window->desc);
- meta_workspace_invalidate_work_area (workspace);
- }
-
- g_signal_emit (workspace, signals[WINDOW_ADDED], 0, window);
- g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_N_WINDOWS]);
-}
-
-void
-meta_workspace_remove_window (MetaWorkspace *workspace,
- MetaWindow *window)
-{
- COGL_TRACE_BEGIN_SCOPED (MetaWorkspaceRemoveWindow,
- "Workspace (remove window)");
-
- workspace->windows = g_list_remove (workspace->windows, window);
-
- workspace->mru_list = g_list_remove (workspace->mru_list, window);
- g_assert (g_list_find (workspace->mru_list, window) == NULL);
-
- if (window->struts)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Invalidating work area of workspace %d since we're removing window %s from it",
- meta_workspace_index (workspace), window->desc);
- meta_workspace_invalidate_work_area (workspace);
- }
-
- g_signal_emit (workspace, signals[WINDOW_REMOVED], 0, window);
- g_object_notify (G_OBJECT (workspace), "n-windows");
-}
-
-void
-meta_workspace_relocate_windows (MetaWorkspace *workspace,
- MetaWorkspace *new_home)
-{
- GList *copy, *l;
-
- g_return_if_fail (workspace != new_home);
-
- /* can't modify list we're iterating over */
- copy = g_list_copy (workspace->windows);
-
- for (l = copy; l != NULL; l = l->next)
- {
- MetaWindow *window = l->data;
-
- if (!window->on_all_workspaces)
- meta_window_change_workspace (window, new_home);
- }
-
- g_list_free (copy);
-
- assert_workspace_empty (workspace);
-}
-
-void
-meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
-{
- GList *l;
-
- for (l = workspace->windows; l != NULL; l = l->next)
- meta_window_queue (l->data, META_QUEUE_CALC_SHOWING);
-}
-
-static void
-workspace_switch_sound(MetaWorkspace *from,
- MetaWorkspace *to)
-{
- MetaSoundPlayer *player;
- MetaWorkspaceLayout layout;
- int i, nw, x, y, fi, ti;
- const char *e;
-
- nw = meta_workspace_manager_get_n_workspaces (from->manager);
- fi = meta_workspace_index(from);
- ti = meta_workspace_index(to);
-
- meta_workspace_manager_calc_workspace_layout (from->manager,
- nw,
- fi,
- &layout);
-
- for (i = 0; i < nw; i++)
- if (layout.grid[i] == ti)
- break;
-
- if (i >= nw)
- {
- meta_bug("Failed to find destination workspace in layout");
- goto finish;
- }
-
- y = i / layout.cols;
- x = i % layout.cols;
-
- /* We priorize horizontal over vertical movements here. The
- rationale for this is that horizontal movements are probably more
- interesting for sound effects because speakers are usually
- positioned on a horizontal and not a vertical axis. i.e. your
- spatial "Woosh!" effects will easily be able to encode horizontal
- movement but not such much vertical movement. */
-
- if (x < layout.current_col)
- e = "desktop-switch-left";
- else if (x > layout.current_col)
- e = "desktop-switch-right";
- else if (y < layout.current_row)
- e = "desktop-switch-up";
- else if (y > layout.current_row)
- e = "desktop-switch-down";
- else
- {
- meta_bug("Uh, origin and destination workspace at same logic position!");
- goto finish;
- }
-
- player = meta_display_get_sound_player (from->display);
- meta_sound_player_play_from_theme (player, e, "Desktop switched", NULL);
-
- finish:
- meta_workspace_manager_free_workspace_layout (&layout);
-}
-
-/**
- * meta_workspace_activate_with_focus:
- * @workspace: a #MetaWorkspace
- * @focus_this: the #MetaWindow to be focused, or %NULL
- * @timestamp: timestamp for @focus_this
- *
- * Switches to @workspace and possibly activates the window @focus_this.
- *
- * The window @focus_this is activated by calling meta_window_activate()
- * which will unminimize it and transient parents, raise it and give it
- * the focus.
- *
- * If a window is currently being moved by the user, it will be
- * moved to @workspace.
- *
- * The advantage of calling this function instead of meta_workspace_activate()
- * followed by meta_window_activate() is that it happens as a unit, so
- * no other window gets focused first before @focus_this.
- */
-void
-meta_workspace_activate_with_focus (MetaWorkspace *workspace,
- MetaWindow *focus_this,
- guint32 timestamp)
-{
- MetaWorkspace *old;
- MetaWindow *move_window;
- MetaCompositor *comp;
- MetaWorkspaceLayout layout1, layout2;
- gint num_workspaces, current_space, new_space;
- MetaMotionDirection direction;
-
- meta_verbose ("Activating workspace %d",
- meta_workspace_index (workspace));
-
- if (workspace->manager->active_workspace == workspace)
- {
- if (focus_this)
- meta_window_activate (focus_this, timestamp);
- return;
- }
-
- /* Free any cached pointers to the workspaces's edges from
- * a current resize or move operation */
- meta_display_cleanup_edges (workspace->display);
-
- if (workspace->manager->active_workspace)
- workspace_switch_sound (workspace->manager->active_workspace, workspace);
-
- /* Note that old can be NULL; e.g. when starting up */
- old = workspace->manager->active_workspace;
-
- workspace->manager->active_workspace = workspace;
-
- g_signal_emit_by_name (workspace->manager, "active-workspace-changed");
-
- g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_ACTIVE]);
-
- if (old == NULL)
- return;
-
- g_object_notify_by_pspec (G_OBJECT (old), obj_props[PROP_ACTIVE]);
-
- /* If the "show desktop" mode is active for either the old workspace
- * or the new one *but not both*, then update the
- * _net_showing_desktop hint
- */
- if (old->showing_desktop != workspace->showing_desktop)
- g_signal_emit_by_name (workspace->manager, "showing-desktop-changed");
-
- move_window = NULL;
- if (meta_grab_op_is_moving (workspace->display->grab_op))
- move_window = workspace->display->grab_window;
-
- if (move_window != NULL)
- {
- /* We put the window on the new workspace, flip spaces,
- * then remove from old workspace, so the window
- * never gets unmapped and we maintain the button grab
- * on it.
- *
- * \bug This comment appears to be the reverse of what happens
- */
- if (!meta_window_located_on_workspace (move_window, workspace))
- meta_window_change_workspace (move_window, workspace);
- }
-
- meta_workspace_queue_calc_showing (old);
- meta_workspace_queue_calc_showing (workspace);
-
- /*
- * Notify the compositor that the active workspace is changing.
- */
- comp = meta_display_get_compositor (workspace->display);
- direction = 0;
-
- current_space = meta_workspace_index (old);
- new_space = meta_workspace_index (workspace);
- num_workspaces = meta_workspace_manager_get_n_workspaces (workspace->manager);
- meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces,
- current_space, &layout1);
-
- meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces,
- new_space, &layout2);
-
- if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL)
- {
- if (layout1.current_col > layout2.current_col)
- direction = META_MOTION_RIGHT;
- else if (layout1.current_col < layout2.current_col)
- direction = META_MOTION_LEFT;
- }
- else
- {
- if (layout1.current_col < layout2.current_col)
- direction = META_MOTION_RIGHT;
- else if (layout1.current_col > layout2.current_col)
- direction = META_MOTION_LEFT;
- }
-
- if (layout1.current_row < layout2.current_row)
- {
- if (!direction)
- direction = META_MOTION_DOWN;
- else if (direction == META_MOTION_RIGHT)
- direction = META_MOTION_DOWN_RIGHT;
- else
- direction = META_MOTION_DOWN_LEFT;
- }
-
- if (layout1.current_row > layout2.current_row)
- {
- if (!direction)
- direction = META_MOTION_UP;
- else if (direction == META_MOTION_RIGHT)
- direction = META_MOTION_UP_RIGHT;
- else
- direction = META_MOTION_UP_LEFT;
- }
-
- meta_workspace_manager_free_workspace_layout (&layout1);
- meta_workspace_manager_free_workspace_layout (&layout2);
-
- meta_compositor_switch_workspace (comp, old, workspace, direction);
-
- /* This needs to be done after telling the compositor we are switching
- * workspaces since focusing a window will cause it to be immediately
- * shown and that would confuse the compositor if it didn't know we
- * were in a workspace switch.
- */
- if (focus_this)
- {
- meta_window_activate (focus_this, timestamp);
- }
- else if (move_window)
- {
- meta_window_raise (move_window);
- }
- else
- {
- meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace");
- meta_workspace_focus_default_window (workspace, NULL, timestamp);
- }
-
- meta_workspace_manager_workspace_switched (workspace->manager, current_space,
- new_space, direction);
-}
-
-void
-meta_workspace_activate (MetaWorkspace *workspace,
- guint32 timestamp)
-{
- meta_workspace_activate_with_focus (workspace, NULL, timestamp);
-}
-
-int
-meta_workspace_index (MetaWorkspace *workspace)
-{
- int ret;
-
- ret = g_list_index (workspace->manager->workspaces, workspace);
-
- if (ret < 0)
- meta_bug ("Workspace does not exist to index!");
-
- return ret;
-}
-
-void
-meta_workspace_index_changed (MetaWorkspace *workspace)
-{
- GList *l;
- for (l = workspace->windows; l != NULL; l = l->next)
- {
- MetaWindow *win = l->data;
- meta_window_current_workspace_changed (win);
- }
-
- g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_WORKSPACE_INDEX]);
-}
-
-/**
- * meta_workspace_list_windows:
- * @workspace: a #MetaWorkspace
- *
- * Gets windows contained on the workspace, including workspace->windows
- * and also sticky windows. Override-redirect windows are not included.
- *
- * Return value: (transfer container) (element-type MetaWindow): the list of windows.
- */
-GList*
-meta_workspace_list_windows (MetaWorkspace *workspace)
-{
- GSList *display_windows, *l;
- GList *workspace_windows;
-
- display_windows = meta_display_list_windows (workspace->display,
- META_LIST_DEFAULT);
-
- workspace_windows = NULL;
- for (l = display_windows; l != NULL; l = l->next)
- {
- MetaWindow *window = l->data;
-
- if (meta_window_located_on_workspace (window, workspace))
- workspace_windows = g_list_prepend (workspace_windows,
- window);
- }
-
- g_slist_free (display_windows);
-
- return workspace_windows;
-}
-
-void
-meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
-{
- GList *windows, *l;
-
- if (workspace->work_areas_invalid)
- {
- meta_topic (META_DEBUG_WORKAREA,
- "Work area for workspace %d is already invalid",
- meta_workspace_index (workspace));
- return;
- }
-
- meta_topic (META_DEBUG_WORKAREA,
- "Invalidating work area for workspace %d",
- meta_workspace_index (workspace));
-
- /* If we are in the middle of a resize or move operation, we
- * might have cached pointers to the workspace's edges */
- if (workspace == workspace->manager->active_workspace)
- meta_display_cleanup_edges (workspace->display);
-
- meta_workspace_clear_logical_monitor_data (workspace);
-
- workspace_free_all_struts (workspace);
-
- meta_rectangle_free_list_and_elements (workspace->screen_region);
- meta_rectangle_free_list_and_elements (workspace->screen_edges);
- meta_rectangle_free_list_and_elements (workspace->monitor_edges);
- workspace->screen_region = NULL;
- workspace->screen_edges = NULL;
- workspace->monitor_edges = NULL;
-
- workspace->work_areas_invalid = TRUE;
-
- /* redo the size/position constraints on all windows */
- windows = meta_workspace_list_windows (workspace);
-
- for (l = windows; l != NULL; l = l->next)
- {
- MetaWindow *w = l->data;
- meta_window_queue (w, META_QUEUE_MOVE_RESIZE);
- }
-
- g_list_free (windows);
-
- meta_display_queue_workarea_recalc (workspace->display);
-}
-
-static MetaStrut *
-copy_strut(MetaStrut *original)
-{
- return g_memdup2 (original, sizeof (MetaStrut));
-}
-
-static GSList *
-copy_strut_list(GSList *original)
-{
- GSList *result = NULL;
-
- for (; original != NULL; original = original->next)
- result = g_slist_prepend (result, copy_strut (original->data));
-
- return g_slist_reverse (result);
-}
-
-static void
-ensure_work_areas_validated (MetaWorkspace *workspace)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- GList *windows;
- GList *tmp;
- GList *logical_monitors, *l;
- MetaRectangle display_rect = { 0 };
- MetaRectangle work_area;
-
- if (!workspace->work_areas_invalid)
- return;
-
- g_assert (workspace->all_struts == NULL);
- g_assert (workspace->screen_region == NULL);
- g_assert (workspace->screen_edges == NULL);
- g_assert (workspace->monitor_edges == NULL);
-
- meta_display_get_size (workspace->display,
- &display_rect.width,
- &display_rect.height);
-
- /* STEP 1: Get the list of struts */
-
- workspace->all_struts = copy_strut_list (workspace->builtin_struts);
-
- windows = meta_workspace_list_windows (workspace);
- for (tmp = windows; tmp != NULL; tmp = tmp->next)
- {
- MetaWindow *win = tmp->data;
- GSList *s_iter;
-
- for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next) {
- workspace->all_struts = g_slist_prepend (workspace->all_struts,
- copy_strut(s_iter->data));
- }
- }
- g_list_free (windows);
-
- /* STEP 2: Get the maximal/spanning rects for the onscreen and
- * on-single-monitor regions
- */
- g_assert (workspace->screen_region == NULL);
-
- logical_monitors =
- meta_monitor_manager_get_logical_monitors (monitor_manager);
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
- MetaWorkspaceLogicalMonitorData *data;
-
- g_assert (!meta_workspace_get_logical_monitor_data (workspace,
- logical_monitor));
-
- data = meta_workspace_ensure_logical_monitor_data (workspace,
- logical_monitor);
- data->logical_monitor_region =
- meta_rectangle_get_minimal_spanning_set_for_region (
- &logical_monitor->rect,
- workspace->all_struts);
- }
-
- workspace->screen_region =
- meta_rectangle_get_minimal_spanning_set_for_region (
- &display_rect,
- workspace->all_struts);
-
- /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
- * monitors.
- */
- work_area = display_rect; /* start with the screen */
- if (workspace->screen_region == NULL)
- work_area = meta_rect (0, 0, -1, -1);
- else
- meta_rectangle_clip_to_region (workspace->screen_region,
- FIXED_DIRECTION_NONE,
- &work_area);
-
- /* Lots of paranoia checks, forcing work_area_screen to be sane */
-#define MIN_SANE_AREA 100
- if (work_area.width < MIN_SANE_AREA &&
- work_area.width != display_rect.width)
- {
- meta_warning ("struts occupy an unusually large percentage of the screen; "
- "available remaining width = %d < %d",
- work_area.width, MIN_SANE_AREA);
- if (work_area.width < 1)
- {
- work_area.x = (display_rect.width - MIN_SANE_AREA)/2;
- work_area.width = MIN_SANE_AREA;
- }
- else
- {
- int amount = (MIN_SANE_AREA - work_area.width)/2;
- work_area.x -= amount;
- work_area.width += 2*amount;
- }
- }
- if (work_area.height < MIN_SANE_AREA &&
- work_area.height != display_rect.height)
- {
- meta_warning ("struts occupy an unusually large percentage of the screen; "
- "available remaining height = %d < %d",
- work_area.height, MIN_SANE_AREA);
- if (work_area.height < 1)
- {
- work_area.y = (display_rect.height - MIN_SANE_AREA)/2;
- work_area.height = MIN_SANE_AREA;
- }
- else
- {
- int amount = (MIN_SANE_AREA - work_area.height)/2;
- work_area.y -= amount;
- work_area.height += 2*amount;
- }
- }
- workspace->work_area_screen = work_area;
- meta_topic (META_DEBUG_WORKAREA,
- "Computed work area for workspace %d: %d,%d %d x %d",
- meta_workspace_index (workspace),
- workspace->work_area_screen.x,
- workspace->work_area_screen.y,
- workspace->work_area_screen.width,
- workspace->work_area_screen.height);
-
- /* Now find the work areas for each monitor */
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
- MetaWorkspaceLogicalMonitorData *data;
-
- data = meta_workspace_get_logical_monitor_data (workspace,
- logical_monitor);
- work_area = logical_monitor->rect;
-
- if (!data->logical_monitor_region)
- /* FIXME: constraints.c untested with this, but it might be nice for
- * a screen reader or magnifier.
- */
- work_area = meta_rect (work_area.x, work_area.y, -1, -1);
- else
- meta_rectangle_clip_to_region (data->logical_monitor_region,
- FIXED_DIRECTION_NONE,
- &work_area);
-
- data->logical_monitor_work_area = work_area;
-
- meta_topic (META_DEBUG_WORKAREA,
- "Computed work area for workspace %d "
- "monitor %d: %d,%d %d x %d",
- meta_workspace_index (workspace),
- logical_monitor->number,
- data->logical_monitor_work_area.x,
- data->logical_monitor_work_area.y,
- data->logical_monitor_work_area.width,
- data->logical_monitor_work_area.height);
- }
-
- /* STEP 4: Make sure the screen_region is nonempty (separate from step 2
- * since it relies on step 3).
- */
- if (workspace->screen_region == NULL)
- {
- MetaRectangle *nonempty_region;
- nonempty_region = g_new (MetaRectangle, 1);
- *nonempty_region = workspace->work_area_screen;
- workspace->screen_region = g_list_prepend (NULL, nonempty_region);
- }
-
- /* STEP 5: Cache screen and monitor edges for edge resistance and snapping */
- g_assert (workspace->screen_edges == NULL);
- g_assert (workspace->monitor_edges == NULL);
- workspace->screen_edges =
- meta_rectangle_find_onscreen_edges (&display_rect,
- workspace->all_struts);
- tmp = NULL;
- for (l = logical_monitors; l; l = l->next)
- {
- MetaLogicalMonitor *logical_monitor = l->data;
-
- tmp = g_list_prepend (tmp, &logical_monitor->rect);
- }
- workspace->monitor_edges =
- meta_rectangle_find_nonintersected_monitor_edges (tmp,
- workspace->all_struts);
- g_list_free (tmp);
-
- /* We're all done, YAAY! Record that everything has been validated. */
- workspace->work_areas_invalid = FALSE;
-}
-
-static gboolean
-strut_lists_equal (GSList *l,
- GSList *m)
-{
- for (; l && m; l = l->next, m = m->next)
- {
- MetaStrut *a = l->data;
- MetaStrut *b = m->data;
-
- if (a->side != b->side ||
- !meta_rectangle_equal (&a->rect, &b->rect))
- return FALSE;
- }
-
- return l == NULL && m == NULL;
-}
-
-/**
- * meta_workspace_set_builtin_struts:
- * @workspace: a #MetaWorkspace
- * @struts: (element-type Meta.Strut) (transfer none): list of #MetaStrut
- *
- * Sets a list of struts that will be used in addition to the struts
- * of the windows in the workspace when computing the work area of
- * the workspace.
- */
-void
-meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
- GSList *struts)
-{
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaDisplay *display = workspace->display;
- MetaRectangle display_rect = { 0 };
- GSList *l;
-
- meta_display_get_size (display, &display_rect.width, &display_rect.height);
-
- for (l = struts; l; l = l->next)
- {
- MetaStrut *strut = l->data;
- MetaLogicalMonitor *logical_monitor;
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager,
- &strut->rect);
-
- switch (strut->side)
- {
- case META_SIDE_TOP:
- if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- logical_monitor,
- META_DISPLAY_UP))
- continue;
-
- strut->rect.height += strut->rect.y;
- strut->rect.y = 0;
- break;
- case META_SIDE_BOTTOM:
- if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- logical_monitor,
- META_DISPLAY_DOWN))
- continue;
-
- strut->rect.height = display_rect.height - strut->rect.y;
- break;
- case META_SIDE_LEFT:
- if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- logical_monitor,
- META_DISPLAY_LEFT))
- continue;
-
- strut->rect.width += strut->rect.x;
- strut->rect.x = 0;
- break;
- case META_SIDE_RIGHT:
- if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
- logical_monitor,
- META_DISPLAY_RIGHT))
- continue;
-
- strut->rect.width = display_rect.width - strut->rect.x;
- break;
- }
- }
-
- /* Reordering doesn't actually matter, so we don't catch all
- * no-impact changes, but this is just a (possibly unnecessary
- * anyways) optimization */
- if (strut_lists_equal (struts, workspace->builtin_struts))
- return;
-
- workspace_free_builtin_struts (workspace);
- workspace->builtin_struts = copy_strut_list (struts);
-
- meta_workspace_invalidate_work_area (workspace);
-}
-
-void
-meta_workspace_get_work_area_for_logical_monitor (MetaWorkspace *workspace,
- MetaLogicalMonitor *logical_monitor,
- MetaRectangle *area)
-{
- meta_workspace_get_work_area_for_monitor (workspace,
- logical_monitor->number,
- area);
-}
-
-/**
- * meta_workspace_get_work_area_for_monitor:
- * @workspace: a #MetaWorkspace
- * @which_monitor: a monitor index
- * @area: (out): location to store the work area
- *
- * Stores the work area for @which_monitor on @workspace
- * in @area.
- */
-void
-meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
- int which_monitor,
- MetaRectangle *area)
-{
- MetaBackend *backend = meta_get_backend();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
- MetaLogicalMonitor *logical_monitor;
- MetaWorkspaceLogicalMonitorData *data;
-
- logical_monitor =
- meta_monitor_manager_get_logical_monitor_from_number (monitor_manager,
- which_monitor);
- g_return_if_fail (logical_monitor != NULL);
-
- ensure_work_areas_validated (workspace);
- data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor);
-
- g_return_if_fail (data != NULL);
-
- *area = data->logical_monitor_work_area;
-}
-
-/**
- * meta_workspace_get_work_area_all_monitors:
- * @workspace: a #MetaWorkspace
- * @area: (out): location to store the work area
- *
- * Stores the work area in @area.
- */
-void
-meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
- MetaRectangle *area)
-{
- ensure_work_areas_validated (workspace);
-
- *area = workspace->work_area_screen;
-}
-
-GList*
-meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
-{
- ensure_work_areas_validated (workspace);
-
- return workspace->screen_region;
-}
-
-GList *
-meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
- MetaLogicalMonitor *logical_monitor)
-{
- MetaWorkspaceLogicalMonitorData *data;
-
- ensure_work_areas_validated (workspace);
-
- data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor);
-
- return data->logical_monitor_region;
-}
-
-#ifdef WITH_VERBOSE_MODE
-static const char *
-meta_motion_direction_to_string (MetaMotionDirection direction)
-{
- switch (direction)
- {
- case META_MOTION_UP:
- return "Up";
- case META_MOTION_DOWN:
- return "Down";
- case META_MOTION_LEFT:
- return "Left";
- case META_MOTION_RIGHT:
- return "Right";
- case META_MOTION_UP_RIGHT:
- return "Up-Right";
- case META_MOTION_DOWN_RIGHT:
- return "Down-Right";
- case META_MOTION_UP_LEFT:
- return "Up-Left";
- case META_MOTION_DOWN_LEFT:
- return "Down-Left";
- }
-
- return "Unknown";
-}
-#endif /* WITH_VERBOSE_MODE */
-
-/**
- * meta_workspace_get_neighbor:
- * @workspace: a #MetaWorkspace
- * @direction: a #MetaMotionDirection, relative to @workspace
- *
- * Calculate and retrieve the workspace that is next to @workspace,
- * according to @direction and the current workspace layout, as set
- * by meta_screen_override_workspace_layout().
- *
- * Returns: (transfer none): the workspace next to @workspace, or
- * @workspace itself if the neighbor would be outside the layout
- */
-MetaWorkspace*
-meta_workspace_get_neighbor (MetaWorkspace *workspace,
- MetaMotionDirection direction)
-{
- MetaWorkspaceLayout layout;
- int i, current_space, num_workspaces;
- gboolean ltr;
-
- current_space = meta_workspace_index (workspace);
- num_workspaces = meta_workspace_manager_get_n_workspaces (workspace->manager);
- meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces,
- current_space, &layout);
-
- meta_verbose ("Getting neighbor of %d in direction %s",
- current_space, meta_motion_direction_to_string (direction));
-
- ltr = (meta_get_locale_direction () == META_LOCALE_DIRECTION_LTR);
-
- switch (direction)
- {
- case META_MOTION_LEFT:
- layout.current_col -= ltr ? 1 : -1;
- break;
- case META_MOTION_RIGHT:
- layout.current_col += ltr ? 1 : -1;
- break;
- case META_MOTION_UP:
- layout.current_row -= 1;
- break;
- case META_MOTION_DOWN:
- layout.current_row += 1;
- break;
- default:;
- }
-
- if (layout.current_col < 0)
- layout.current_col = 0;
- if (layout.current_col >= layout.cols)
- layout.current_col = layout.cols - 1;
- if (layout.current_row < 0)
- layout.current_row = 0;
- if (layout.current_row >= layout.rows)
- layout.current_row = layout.rows - 1;
-
- i = layout.grid[layout.current_row * layout.cols + layout.current_col];
-
- if (i < 0)
- i = current_space;
-
- if (i >= num_workspaces)
- meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid",
- i);
-
- meta_verbose ("Neighbor workspace is %d at row %d col %d",
- i, layout.current_row, layout.current_col);
-
- meta_workspace_manager_free_workspace_layout (&layout);
-
- return meta_workspace_manager_get_workspace_by_index (workspace->manager, i);
-}
-
-const char*
-meta_workspace_get_name (MetaWorkspace *workspace)
-{
- return meta_prefs_get_workspace_name (meta_workspace_index (workspace));
-}
-
-void
-meta_workspace_focus_default_window (MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- guint32 timestamp)
-{
- if (timestamp == META_CURRENT_TIME)
- meta_warning ("META_CURRENT_TIME used to choose focus window; "
- "focus window may not be correct.");
-
- if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
- !workspace->display->mouse_mode)
- focus_ancestor_or_top_window (workspace, not_this_one, timestamp);
- else
- {
- MetaWindow * window;
- window = meta_display_get_pointer_window (workspace->display, not_this_one);
- if (window &&
- window->type != META_WINDOW_DOCK &&
- window->type != META_WINDOW_DESKTOP)
- {
- if (timestamp == META_CURRENT_TIME)
- {
-
- /* We would like for this to never happen. However, if
- * it does happen then we kludge since using META_CURRENT_TIME
- * can mean ugly race conditions--and we can avoid these
- * by allowing EnterNotify events (which come with
- * timestamps) to handle focus.
- */
-
- meta_topic (META_DEBUG_FOCUS,
- "Not focusing mouse window %s because EnterNotify events should handle that",
- window->desc);
- }
- else
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing mouse window %s", window->desc);
- meta_window_focus (window, timestamp);
- }
-
- if (workspace->display->autoraise_window != window &&
- meta_prefs_get_auto_raise ())
- {
- meta_display_queue_autoraise_callback (workspace->display, window);
- }
- }
- else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY)
- focus_ancestor_or_top_window (workspace, not_this_one, timestamp);
- else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Setting focus to no_focus_window, since no valid "
- "window to focus found.");
- meta_display_unset_input_focus (workspace->display, timestamp);
- }
- }
-}
-
-static gboolean
-find_focusable_ancestor (MetaWindow *window,
- gpointer user_data)
-{
- MetaWorkspaceFocusableAncestorData *data = user_data;
-
- if (!window->unmanaging &&
- window->mapped &&
- !window->hidden &&
- meta_window_is_focusable (window) &&
- meta_window_located_on_workspace (window, data->workspace) &&
- meta_window_showing_on_its_workspace (window))
- {
- data->out_window = window;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-try_to_set_focus_and_check (MetaWindow *window,
- MetaWindow *not_this_one,
- uint32_t timestamp)
-{
- meta_window_focus (window, timestamp);
-
- /* meta_focus_window() will not change focus for clients using the
- * "globally active input" model of input handling, hence defeating
- * the assumption that focus should be changed for such windows.
- * See https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7
- */
- if (meta_window_is_focus_async (window))
- return TRUE;
-
- /* meta_window_focus() does not guarantee that focus will end up
- * where we expect, it can fail for various reasons, better check
- * it did not actually changed or even left focus to the window we
- * explicitly want to avoid.
- */
- if (not_this_one &&
- meta_display_get_focus_window (window->display) == not_this_one)
- {
- meta_warning ("Failed to focus window %s while avoiding %s",
- window->desc, not_this_one->desc);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Focus ancestor of not_this_one if there is one */
-static void
-focus_ancestor_or_top_window (MetaWorkspace *workspace,
- MetaWindow *not_this_one,
- guint32 timestamp)
-{
- MetaWindow *window = NULL;
-
- if (not_this_one)
- meta_topic (META_DEBUG_FOCUS,
- "Focusing MRU window excluding %s", not_this_one->desc);
- else
- meta_topic (META_DEBUG_FOCUS,
- "Focusing MRU window");
-
- /* First, check to see if we need to focus an ancestor of a window */
- if (not_this_one)
- {
- MetaWindow *ancestor;
- MetaWorkspaceFocusableAncestorData data;
-
- data = (MetaWorkspaceFocusableAncestorData) {
- .workspace = workspace,
- };
- meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data);
- ancestor = data.out_window;
-
- if (ancestor)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing %s, ancestor of %s",
- ancestor->desc, not_this_one->desc);
-
- if (try_to_set_focus_and_check (ancestor, not_this_one, timestamp))
- {
- /* Also raise the window if in click-to-focus */
- if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
- meta_window_raise (ancestor);
-
- return;
- }
- }
- }
-
- window = meta_stack_get_default_focus_window (workspace->display->stack,
- workspace,
- not_this_one);
-
- if (window)
- {
- meta_topic (META_DEBUG_FOCUS,
- "Focusing workspace MRU window %s", window->desc);
- if (try_to_set_focus_and_check (window, not_this_one, timestamp))
- {
- /* Also raise the window if in click-to-focus */
- if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
- meta_window_raise (window);
-
- return;
- }
- }
-
- meta_topic (META_DEBUG_FOCUS,
- "No MRU window to focus found; focusing no_focus_window.");
- meta_display_unset_input_focus (workspace->display, timestamp);
-}
-
-/**
- * meta_workspace_get_display:
- * @workspace: a #MetaWorkspace
- *
- * Gets the #MetaDisplay that the workspace is part of.
- *
- * Return value: (transfer none): the #MetaDisplay for the workspace
- */
-MetaDisplay *
-meta_workspace_get_display (MetaWorkspace *workspace)
-{
- return workspace->display;
-}