mutter/src/core/display.c

3193 lines
90 KiB
C
Raw Normal View History

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2014-05-02 09:34:02 -04:00
/*
2001-05-30 11:36:31 -04:00
* 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
2014-05-02 09:34:02 -04:00
*
2001-05-30 11:36:31 -04:00
* 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.
2014-05-02 09:34:02 -04:00
*
2001-05-30 11:36:31 -04:00
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
2001-05-30 11:36:31 -04:00
*/
/**
* SECTION:display
* @title: MetaDisplay
* @short_description: Mutter X display handler
*
* The display is represented as a #MetaDisplay struct.
*/
#define _XOPEN_SOURCE 600 /* for gethostname() */
#include <config.h>
#include "display-private.h"
#include "events.h"
#include "util-private.h"
#include <meta/main.h>
#include "screen-private.h"
#include "window-private.h"
#include "frame.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include <meta/prefs.h>
#include "workspace-private.h"
#include "bell.h"
#include <meta/compositor.h>
#include <meta/compositor-mutter.h>
2001-06-09 23:17:15 -04:00
#include <X11/Xatom.h>
2015-07-06 00:58:45 -04:00
#include <meta/meta-enum-types.h>
#include "meta-idle-monitor-dbus.h"
#include "meta-cursor-tracker-private.h"
#include <meta/meta-backend.h>
#include "backends/native/meta-backend-native.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/meta-stage.h"
#include "backends/meta-input-settings-private.h"
#include <clutter/x11/clutter-x11.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <X11/extensions/shape.h>
#include <X11/Xcursor/Xcursor.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#include <stdlib.h>
2001-06-09 23:17:15 -04:00
#include <string.h>
#include <unistd.h>
2001-05-30 11:36:31 -04:00
2014-08-15 12:48:55 -04:00
#include "x11/events.h"
#include "x11/window-x11.h"
#include "x11/window-props.h"
#include "x11/group-props.h"
#include "x11/xprops.h"
2014-08-13 20:19:35 -04:00
#ifdef HAVE_WAYLAND
#include "wayland/meta-xwayland-private.h"
#include "wayland/meta-wayland-tablet-seat.h"
#include "wayland/meta-wayland-tablet-pad.h"
2014-08-13 20:19:35 -04:00
#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;
G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
/* Signals */
enum
{
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,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_FOCUS_WINDOW
};
static guint display_signals [LAST_SIGNAL] = { 0 };
/*
* 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 const char *gnome_wm_keybindings = "Mutter";
static const char *net_wm_name = "Mutter";
static void update_cursor_theme (void);
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_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[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, G_TYPE_UINT, 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, 3,
META_TYPE_SCREEN,
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, 3,
META_TYPE_SCREEN,
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);
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 */
if (ping_data->ping_timeout_id != 0)
g_source_remove (ping_data->ping_timeout_id);
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 void
enable_compositor (MetaDisplay *display)
{
if (!META_DISPLAY_HAS_COMPOSITE (display) ||
!META_DISPLAY_HAS_DAMAGE (display))
{
meta_warning ("Missing %s extension required for compositing",
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" : "damage");
return;
}
int version = (display->composite_major_version * 10) + display->composite_minor_version;
if (version < 3)
{
meta_warning ("Your version of COMPOSITE is too old.");
return;
}
if (!display->compositor)
display->compositor = meta_compositor_new (display);
meta_compositor_manage (display->compositor);
}
static void
meta_display_init (MetaDisplay *disp)
{
/* Some stuff could go in here that's currently in _open,
* but it doesn't really matter. */
}
/**
* meta_set_wm_name: (skip)
* @wm_name: value for _NET_WM_NAME
*
* Set the value to use for the _NET_WM_NAME property. To take effect,
* it is necessary to call this function before meta_init().
*/
void
meta_set_wm_name (const char *wm_name)
{
g_return_if_fail (the_display == NULL);
net_wm_name = wm_name;
}
/**
* meta_set_gnome_wm_keybindings: (skip)
* @wm_keybindings: value for _GNOME_WM_KEYBINDINGS
*
* Set the value to use for the _GNOME_WM_KEYBINDINGS property. To take
* effect, it is necessary to call this function before meta_init().
*/
void
meta_set_gnome_wm_keybindings (const char *wm_keybindings)
{
g_return_if_fail (the_display == NULL);
gnome_wm_keybindings = wm_keybindings;
}
void
meta_display_cancel_touch (MetaDisplay *display)
{
2014-08-13 20:19:35 -04:00
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor;
if (!meta_is_wayland_compositor ())
return;
compositor = meta_wayland_compositor_get_default ();
meta_wayland_touch_cancel (compositor->seat->touch);
2014-08-13 20:19:35 -04:00
#endif
}
static void
gesture_tracker_state_changed (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state,
MetaDisplay *display)
{
if (meta_is_wayland_compositor ())
{
if (state == META_SEQUENCE_ACCEPTED)
meta_display_cancel_touch (display);
}
else
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
int event_mode;
if (state == META_SEQUENCE_ACCEPTED)
event_mode = XIAcceptTouch;
else if (state == META_SEQUENCE_REJECTED)
event_mode = XIRejectTouch;
else
return;
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
clutter_x11_event_sequence_get_touch_detail (sequence),
DefaultRootWindow (display->xdisplay), event_mode);
}
}
static void
on_startup_notification_changed (MetaStartupNotification *sn,
gpointer sequence,
MetaDisplay *display)
{
if (!display->screen)
return;
g_slist_free (display->screen->startup_sequences);
display->screen->startup_sequences =
meta_startup_notification_get_sequences (display->startup_notification);
g_signal_emit_by_name (display->screen, "startup-sequence-changed", sequence);
}
/**
* meta_display_open:
*
* Opens a new display, sets it up, initialises all the X extensions
* we will need, and adds it to the list of displays.
*
* Returns: %TRUE if the display was opened successfully, and %FALSE
* otherwise-- that is, if the display doesn't exist or it already
* has a window manager.
*/
2001-05-30 11:36:31 -04:00
gboolean
meta_display_open (void)
2001-05-30 11:36:31 -04:00
{
MetaDisplay *display;
2001-05-30 11:36:31 -04:00
Display *xdisplay;
MetaScreen *screen;
int i;
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
guint32 timestamp;
Window old_active_xwindow = None;
/* A list of all atom names, so that we can intern them in one go. */
2015-09-23 19:13:59 -04:00
const char *atom_names[] = {
#define item(x) #x,
#include <x11/atomnames.h>
#undef item
2001-06-04 02:17:52 -04:00
};
2001-06-02 00:14:18 -04:00
Atom atoms[G_N_ELEMENTS(atom_names)];
2014-05-02 09:34:02 -04:00
meta_verbose ("Opening display '%s'\n", XDisplayName (NULL));
2001-05-30 11:36:31 -04:00
xdisplay = meta_ui_get_display ();
2014-05-02 09:34:02 -04:00
2001-05-30 11:36:31 -04:00
if (xdisplay == NULL)
{
meta_warning (_("Failed to open X Window System display '%s'\n"),
XDisplayName (NULL));
2001-05-30 11:36:31 -04:00
return FALSE;
}
2014-08-13 20:19:35 -04:00
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
meta_xwayland_complete_init ();
2014-08-13 20:19:35 -04:00
#endif
2001-05-31 02:42:58 -04:00
if (meta_is_syncing ())
XSynchronize (xdisplay, True);
2014-05-02 09:34:02 -04:00
g_assert (the_display == NULL);
display = the_display = g_object_new (META_TYPE_DISPLAY, NULL);
2001-06-02 21:33:27 -04:00
display->closing = 0;
2014-05-02 09:34:02 -04:00
2001-06-02 21:33:27 -04:00
/* here we use XDisplayName which is what the user
* probably put in, vs. DisplayString(display) which is
* canonicalized by XOpenDisplay()
*/
display->name = g_strdup (XDisplayName (NULL));
display->xdisplay = xdisplay;
display->display_opening = TRUE;
display->pending_pings = NULL;
display->autoraise_timeout_id = 0;
display->autoraise_window = NULL;
display->focus_window = NULL;
display->focus_serial = 0;
display->server_focus_window = None;
display->server_focus_serial = 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 */
2014-05-02 09:34:02 -04:00
meta_bell_init (display);
meta_display_init_keys (display);
2001-06-09 01:14:43 -04:00
meta_prefs_add_listener (prefs_changed_callback, display);
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
2015-09-23 19:13:59 -04:00
XInternAtoms (display->xdisplay, (char **)atom_names, G_N_ELEMENTS (atom_names),
2001-06-09 01:14:43 -04:00
False, atoms);
2015-09-23 19:24:33 -04:00
i = 0;
#define item(x) display->atom_##x = atoms[i++];
#include <x11/atomnames.h>
#undef item
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (display);
2014-05-02 09:34:02 -04:00
2001-06-10 15:23:28 -04:00
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
*/
display->leader_window = None;
display->timestamp_pinging_window = None;
display->monitor_cache_invalidated = TRUE;
display->groups_by_leader = NULL;
display->screen = NULL;
2014-05-02 09:34:02 -04:00
2001-06-19 23:01:26 -04:00
/* Get events */
meta_display_init_events (display);
2014-08-15 12:48:55 -04:00
meta_display_init_events_x11 (display);
display->xids = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);
display->stamps = g_hash_table_new (g_int64_hash,
g_int64_equal);
display->wayland_windows = g_hash_table_new (NULL, NULL);
i = 0;
while (i < N_IGNORED_CROSSING_SERIALS)
{
display->ignored_crossing_serials[i] = 0;
++i;
}
2014-05-02 09:34:02 -04:00
display->current_time = CurrentTime;
display->sentinel_counter = 0;
display->grab_resize_timeout_id = 0;
display->grab_have_keyboard = FALSE;
2014-05-02 09:34:02 -04:00
display->last_bell_time = 0;
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
display->grab_edge_resistance_data = NULL;
Merge of all the changes on the constraints_experiments branch. This is 2005-11-18 Elijah Newren <newren@gmail.com> Merge of all the changes on the constraints_experiments branch. This is just a summary, to get the full ChangeLog of those changes (approx. 2000 lines): cvs -q -z3 update -Pd -r constraints_experiments cvs -q -z3 diff -pu -r CONSTRAINTS_EXPERIMENTS_BRANCHPOINT ChangeLog Bugs fixed: unfiled - constraints.c is overly complicated[1] unfiled - constraints.c is not robust when all constraints cannot simultaneously be met (constraints need to be prioritized) unfiled - keep-titlebar-onscreen constraint is decoration unaware (since get_outermost_onscreen_positions() forgets to include decorations) unfiled - keyboard snap-moving and snap-resizing snap to hidden edges 109553 - gravity w/ simultaneous move & resize doesn't work 113601 - maximize vertical and horizontal should toggle and be constrained 122196 - windows show up under vertical panels 122670 - jerky/random resizing of window via keyboard[2] 124582 - keyboard and mouse snap-resizing and snap-moving erroneously moves the window multidimensionally 136307 - don't allow apps to resize themselves off the screen (*cough* filechooser *cough*) 142016, 143784 - windows should not span multiple xineramas unless placed there by the user 143145 - clamp new windows to screensize and force them onscreen, if they'll fit 144126 - Handle pathological strut lists sanely[3] 149867 - fixed aspect ratio windows are difficult to resize[4] 152898 - make screen edges consistent; allow easy slamming of windows into the left, right, and bottom edges of the screen too. 154706 - bouncing weirdness at screen edge with keyboard moving or resizing 156699 - avoid struts when placing windows, if possible (nasty a11y blocker) 302456 - dragging offscreen too restrictive 304857 - wireframe moving off the top of the screen is misleading 308521 - make uni-directional resizing easier with alt-middle-drag and prevent the occasional super annoying resize-the-wrong-side(s) behavior 312007 - snap-resize moves windows with a minimum size constraint 312104 - resizing the top of a window can cause the bottom to grow 319351 - don't instantly snap on mouse-move-snapping, remove braindeadedness of having order of releasing shift and releasing button press matter so much [1] fixed in my opinion, anyway. [2] Actually, it's not totally fixed--it's just annoying instead of almost completely unusable. Matthias had a suggestion that may fix the remainder of the problems (see http://tinyurl.com/bwzuu). [3] This bug was originally about not-quite-so-pathological cases but was left open for the worse cases. The code from the branch handles the remainder of the cases mentioned in this bug. [4] Actually, although it's far better there's still some minor issues left: a slight drift that's only noticeable after lots of resizing, and potential problems with partially onscreen constraints due to not clearing any fixed_directions flags (aspect ratio windows get resized in both directions and thus aren't fixed in one of them) New feature: 81704 - edge resistance for user move and resize operations; in particular 3 different kinds of resistance are implemented: Pixel-Distance: window movement is resisted when it aligns with an edge unless the movement is greater than a threshold number of pixels Timeout: window movement past an edge is prevented until a certain amount of time has elapsed during the operation since the first request to move it past that edge Keyboard-Buildup: when moving or resizing with the keyboard, once a window is aligned with a certain edge it cannot move past until the correct direction has been pressed enough times (e.g. 2 or 3 times) Major changes: - constraints.c has been rewritten; very few lines of code from the old version remain. There is a comment near the top of the function explaining the basics of how the new framework works. A more detailed explanation can be found in doc/how-constraints-works.txt - edge-resistance.[ch] are new files implementing edge-resistance. - boxes.[ch] are new files containing low-level error-prone functions used heavily in constraints.c and edge-resistance.c, among various places throughout the code. testboxes.c contains a thorough testsuite for the boxes.[ch] functions compiled into a program, testboxes. - meta_window_move_resize_internal() *must* be told the gravity of the associated operation (if it's just a move operation, the gravity will be ignored, but for resize and move+resize the correct value is needed) - the craziness of different values that meta_window_move_resize_internal() accepts has been documented in a large comment at the beginning of the function. It may be possible to clean this up some, but until then things will remain as they were before--caller beware. - screen and xinerama usable areas (i.e. places not covered by e.g. panels) are cached in the workspace now, as are the screen and xinerama edges. These get updated with the workarea in src/workspace.c:ensure_work_areas_validated()
2005-11-19 09:58:50 -05:00
{
int major, minor;
display->have_xsync = FALSE;
2014-05-02 09:34:02 -04:00
display->xsync_error_base = 0;
display->xsync_event_base = 0;
/* I don't think we really have to fill these in */
major = SYNC_MAJOR_VERSION;
minor = SYNC_MINOR_VERSION;
2014-05-02 09:34:02 -04:00
if (!XSyncQueryExtension (display->xdisplay,
&display->xsync_event_base,
&display->xsync_error_base) ||
!XSyncInitialize (display->xdisplay,
&major, &minor))
{
display->xsync_error_base = 0;
display->xsync_event_base = 0;
}
else
{
display->have_xsync = TRUE;
XSyncSetPriority (display->xdisplay, None, 10);
}
meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
major, minor,
display->xsync_error_base,
display->xsync_event_base);
}
{
display->have_shape = FALSE;
2014-05-02 09:34:02 -04:00
display->shape_error_base = 0;
display->shape_event_base = 0;
2014-05-02 09:34:02 -04:00
if (!XShapeQueryExtension (display->xdisplay,
&display->shape_event_base,
&display->shape_error_base))
{
display->shape_error_base = 0;
display->shape_event_base = 0;
}
else
display->have_shape = TRUE;
2014-05-02 09:34:02 -04:00
meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
display->shape_error_base,
display->shape_event_base);
}
{
display->have_composite = FALSE;
display->composite_error_base = 0;
display->composite_event_base = 0;
if (!XCompositeQueryExtension (display->xdisplay,
&display->composite_event_base,
&display->composite_error_base))
{
display->composite_error_base = 0;
display->composite_event_base = 0;
2014-05-02 09:34:02 -04:00
}
else
{
display->composite_major_version = 0;
display->composite_minor_version = 0;
if (XCompositeQueryVersion (display->xdisplay,
&display->composite_major_version,
&display->composite_minor_version))
{
display->have_composite = TRUE;
}
else
{
display->composite_major_version = 0;
display->composite_minor_version = 0;
}
}
meta_verbose ("Attempted to init Composite, found error base %d event base %d "
"extn ver %d %d\n",
display->composite_error_base,
display->composite_event_base,
display->composite_major_version,
display->composite_minor_version);
display->have_damage = FALSE;
display->damage_error_base = 0;
display->damage_event_base = 0;
if (!XDamageQueryExtension (display->xdisplay,
&display->damage_event_base,
&display->damage_error_base))
{
display->damage_error_base = 0;
display->damage_event_base = 0;
2014-05-02 09:34:02 -04:00
}
else
display->have_damage = TRUE;
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
display->damage_error_base,
display->damage_event_base);
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
if (XFixesQueryExtension (display->xdisplay,
&display->xfixes_event_base,
&display->xfixes_error_base))
{
int xfixes_major, xfixes_minor;
XFixesQueryVersion (display->xdisplay, &xfixes_major, &xfixes_minor);
if (xfixes_major * 100 + xfixes_minor < 500)
meta_fatal ("Mutter requires XFixes 5.0");
}
else
{
meta_fatal ("Mutter requires XFixes 5.0");
}
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
display->xfixes_error_base,
display->xfixes_event_base);
}
{
int major = 2, minor = 3;
gboolean has_xi = FALSE;
if (XQueryExtension (display->xdisplay,
"XInputExtension",
&display->xinput_opcode,
&display->xinput_error_base,
&display->xinput_event_base))
{
if (XIQueryVersion (display->xdisplay, &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version >= 22)
has_xi = TRUE;
#ifdef HAVE_XI23
if (version >= 23)
display->have_xinput_23 = TRUE;
#endif /* HAVE_XI23 */
}
}
if (!has_xi)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
update_cursor_theme ();
/* Create the leader window here. Set its properties and
* use the timestamp from one of the PropertyNotify events
* that will follow.
*/
{
gulong data[1];
XEvent event;
/* We only care about the PropertyChangeMask in the next 30 or so lines of
* code. Note that gdk will at some point unset the PropertyChangeMask for
* this window, so we can't rely on it still being set later. See bug
* 354213 for details.
*/
display->leader_window =
meta_create_offscreen_window (display->xdisplay,
DefaultRootWindow (display->xdisplay),
PropertyChangeMask);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__NET_WM_NAME,
net_wm_name);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__GNOME_WM_KEYBINDINGS,
gnome_wm_keybindings);
2014-05-02 09:34:02 -04:00
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__MUTTER_VERSION,
VERSION);
data[0] = display->leader_window;
XChangeProperty (display->xdisplay,
display->leader_window,
display->atom__NET_SUPPORTING_WM_CHECK,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
XWindowEvent (display->xdisplay,
display->leader_window,
PropertyChangeMask,
&event);
timestamp = event.xproperty.time;
/* Make it painfully clear that we can't rely on PropertyNotify events on
* this window, as per bug 354213.
*/
XSelectInput(display->xdisplay,
display->leader_window,
NoEventMask);
}
/* Make a little window used only for pinging the server for timestamps; note
* that meta_create_offscreen_window already selects for PropertyChangeMask.
*/
display->timestamp_pinging_window =
meta_create_offscreen_window (display->xdisplay,
DefaultRootWindow (display->xdisplay),
PropertyChangeMask);
display->last_focus_time = timestamp;
display->last_user_time = timestamp;
display->compositor = NULL;
/* Mutter used to manage all X screens of the display in a single process, but
* now it always manages exactly one screen - the default screen retrieved
* from GDK.
*/
screen = meta_screen_new (display, timestamp);
if (!screen)
{
/* This would typically happen because all the screens already
* have window managers.
*/
meta_display_close (display, timestamp);
return FALSE;
}
display->screen = screen;
if (!meta_is_wayland_compositor ())
meta_prop_get_window (display, display->screen->xroot,
display->atom__NET_ACTIVE_WINDOW,
&old_active_xwindow);
display->startup_notification = meta_startup_notification_get (display);
g_signal_connect (display->startup_notification, "changed",
G_CALLBACK (on_startup_notification_changed), display);
meta_screen_init_workspaces (screen);
enable_compositor (display);
meta_screen_create_guard_window (screen);
/* 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_screen_manage_all_windows (screen);
if (old_active_xwindow != None)
{
MetaWindow *old_active_window = meta_display_lookup_x_window (display, old_active_xwindow);
if (old_active_window)
meta_window_focus (old_active_window, timestamp);
else
meta_display_focus_the_no_focus_window (display, display->screen, timestamp);
}
else
meta_display_focus_the_no_focus_window (display, display->screen, timestamp);
meta_idle_monitor_init_dbus ();
/* Done opening new display */
display->display_opening = FALSE;
2001-05-30 11:36:31 -04:00
return TRUE;
}
2001-06-03 14:33:59 -04:00
static gint
ptrcmp (gconstpointer a, gconstpointer b)
{
if (a < b)
return -1;
else if (a > b)
return 1;
else
return 0;
2001-05-30 11:36:31 -04:00
}
/**
* 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.
*/
2001-06-24 04:09:10 -04:00
GSList*
meta_display_list_windows (MetaDisplay *display,
MetaListWindowsFlags flags)
2001-05-30 11:36:31 -04:00
{
2001-06-03 14:33:59 -04:00
GSList *winlist;
2001-06-24 04:09:10 -04:00
GSList *prev;
GSList *tmp;
GHashTableIter iter;
gpointer key, value;
2001-06-03 14:33:59 -04:00
winlist = NULL;
g_hash_table_iter_init (&iter, 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);
}
2001-06-03 14:33:59 -04:00
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);
}
2001-06-24 04:09:10 -04:00
/* Uniquify the list, since both frame windows and plain
* windows are in the hash
*/
2001-06-03 14:33:59 -04:00
winlist = g_slist_sort (winlist, ptrcmp);
2001-06-24 04:09:10 -04:00
prev = NULL;
tmp = winlist;
while (tmp != NULL)
{
GSList *next;
next = tmp->next;
2014-05-02 09:34:02 -04:00
2001-06-24 04:09:10 -04:00
if (next &&
next->data == tmp->data)
{
/* Delete tmp from list */
if (prev)
prev->next = next;
if (tmp == winlist)
winlist = next;
2014-05-02 09:34:02 -04:00
2001-06-24 04:09:10 -04:00
g_slist_free_1 (tmp);
/* leave prev unchanged */
}
else
{
prev = tmp;
}
2014-05-02 09:34:02 -04:00
2001-06-24 04:09:10 -04:00
tmp = next;
}
if (flags & META_LIST_SORTED)
winlist = g_slist_sort (winlist, mru_cmp);
2001-06-24 04:09:10 -04:00
return winlist;
}
void
meta_display_close (MetaDisplay *display,
guint32 timestamp)
2001-06-24 04:09:10 -04:00
{
g_assert (display != NULL);
g_assert (display == the_display);
if (display->closing != 0)
{
/* The display's already been closed. */
return;
}
display->closing += 1;
meta_prefs_remove_listener (prefs_changed_callback, display);
2014-05-02 09:34:02 -04:00
meta_display_remove_autoraise_callback (display);
g_clear_object (&display->startup_notification);
g_clear_object (&display->gesture_tracker);
if (display->focus_timeout_id)
g_source_remove (display->focus_timeout_id);
display->focus_timeout_id = 0;
2001-06-19 23:01:26 -04:00
/* Stop caring about events */
2014-08-15 12:48:55 -04:00
meta_display_free_events_x11 (display);
meta_display_free_events (display);
2014-05-02 09:34:02 -04:00
meta_screen_free (display->screen, timestamp);
/* Must be after all calls to meta_window_unmanage() since they
2001-06-04 00:58:22 -04:00
* unregister windows
*/
g_hash_table_destroy (display->xids);
g_hash_table_destroy (display->wayland_windows);
2001-06-09 17:58:30 -04:00
2001-06-10 15:23:28 -04:00
if (display->leader_window != None)
XDestroyWindow (display->xdisplay, display->leader_window);
2001-06-19 23:01:26 -04:00
XFlush (display->xdisplay);
meta_display_free_window_prop_hooks (display);
lengthen to 15 seconds 2002-11-30 Havoc Pennington <hp@pobox.com> * src/screen.c (STARTUP_TIMEOUT): lengthen to 15 seconds * src/util.c (utf8_fputs): hmm, return a value * src/screen.c (meta_screen_apply_startup_properties): new function to apply initial workspace based on startup sequence. * src/window.c (meta_window_new): load _NET_STARTUP_ID (meta_window_get_startup_id): new function * src/window-props.c (meta_display_init_window_prop_hooks): add hooks for _NET_STARTUP_ID * src/display.c (event_callback): send property events to groups. * src/xprops.c (meta_prop_get_values): make a type of INVALID mean to ignore that property (don't fetch its value). * src/group.c (meta_group_property_notify): new function * src/screen.c (set_supported_hint): support _NET_STARTUP_ID * src/display.c (meta_display_open): add _NET_STARTUP_ID to atoms we initialize * src/group-private.h: private header shared between group-props.c, group.c * src/group-props.h, src/group-props.c: new files to contain functions for retrieving group properties * src/window.c (meta_window_same_application): change this a bit to work with new definition of group * src/group.c (meta_window_get_group): always create a group for every window, using the window's own ID as group leader if required. * src/window.c (update_wm_hints): handle changes to group leader * src/group.c (meta_window_group_leader_changed): new function * src/display.h (struct _MetaDisplay): _NET_WM_WINDOW_TYPE_SPLASH, not SPLASHSCREEN. Reported by Gregory Merchan and Matthias Clasen. * src/screen.c (startup_sequence_timeout): when timing out a startup sequence, send a remove message, don't just time it out locally.
2002-11-30 22:58:04 -05:00
meta_display_free_group_prop_hooks (display);
2014-05-02 09:34:02 -04:00
2001-05-30 11:36:31 -04:00
g_free (display->name);
meta_display_shutdown_keys (display);
if (display->compositor)
meta_compositor_destroy (display->compositor);
2014-05-02 09:34:02 -04:00
2009-02-03 04:11:32 -05:00
g_object_unref (display);
the_display = NULL;
2001-05-30 11:36:31 -04:00
meta_quit (META_EXIT_SUCCESS);
2001-05-30 11:36:31 -04:00
}
/**
* 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.
*/
2001-05-30 23:30:58 -04:00
MetaDisplay*
meta_display_for_x_display (Display *xdisplay)
{
if (the_display->xdisplay == xdisplay)
return the_display;
2001-05-30 23:30:58 -04:00
meta_warning ("Could not find display for X display %p, probably going to crash\n",
xdisplay);
2014-05-02 09:34:02 -04:00
2001-05-30 23:30:58 -04:00
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)
2001-05-31 02:42:58 -04:00
{
return the_display;
2001-05-31 02:42:58 -04:00
}
static inline gboolean
grab_op_is_window (MetaGrabOp op)
{
return 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)
2001-07-25 23:14:45 -04:00
{
if (!grab_op_is_window (op))
return FALSE;
2001-07-25 23:14:45 -04:00
return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) != 0;
2001-07-25 23:14:45 -04:00
}
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;
2014-05-02 09:34:02 -04:00
return !meta_grab_op_is_resizing (op);
}
/**
2016-03-10 10:48:45 -05:00
* 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;
}
static Bool
find_timestamp_predicate (Display *xdisplay,
XEvent *ev,
XPointer arg)
{
MetaDisplay *display = (MetaDisplay *) arg;
return (ev->type == PropertyNotify &&
ev->xproperty.atom == display->atom__MUTTER_TIMESTAMP_PING);
}
Fix a variety of focus race conditions in all focus modes, or at least 2004-10-04 Elijah Newren <newren@math.utah.edu> Fix a variety of focus race conditions in all focus modes, or at least make them harder to trigger (fixes #152000) * src/core.[ch] (meta_core_user_lower_and_unfocus): add a timestamp parameter; pass it along to meta_workspace_focus_default_window * src/display.[ch] (meta_display_get_current_time_roundtrip): new function * src/display.c (event_callback): pass a timestamp to the meta_workspace_activate and meta_workspace_focus_default_window function calls * src/frames.c (meta_frames_button_press_event): pass a timestamp to meta_core_user_lower_and_unfocus * src/keybindings.c (handle_activate_workspace): pass a timestamp to meta_workspace_activate, (process_workspace_switch_grab): pass a timestamp to meta_workspace_focus_default_window and meta_workspace_activate, (handle_toggle_desktop): pass a timestamp to meta_workspace_focus_default_window, (do_handle_move_to_workspace): pass a timestamp to meta_workspace_activate_with_focus, (handle_workspace_switch): meta_workspace_activate * src/screen.c (meta_screen_new): pass a timestamp to meta_workspace_activate * src/window.c (meta_window_free): pass a timestamp to meta_workspace_focus_default_window, (idle_calc_showing): don't increment the focus sentinel here, (meta_window_minimize): pass a timestamp to meta_workspace_focus_default_window, (meta_window_client_message), pass a timestamp to meta_workspace_focus_default_window * src/workspace.h (meta_workspace_activate): add timestamp parameter, (meta_workspace_activate_with_focus): add timestamp parameter, (meta_workspace_focus_default_window): add timestamp parameter * src/workspace.c (meta_workspace_focus_mru_window): make this function take a timestamp and use it for meta_window_focus or XSetInputFocus, (meta_workspace_activate_with_focus): make this function take a timestamp and pass it along to meta_window_focus and meta_workspace_focus_default_window, (meta_workspace_activate): make this function take a timestamp and pass it to meta_workspace_activate_with_focus), (meta_workspace_focus_default_window): make this function take a timestamp, warn if its 0 but try to handle that case sanely, and pass the timestamp on to meta_window_focus or meta_workspace_focus_mru_window or XSetInputFocus
2004-10-04 16:32:59 -04:00
/* Get a timestamp, even if it means a roundtrip */
guint32
meta_display_get_current_time_roundtrip (MetaDisplay *display)
{
guint32 timestamp;
2014-05-02 09:34:02 -04:00
Fix a variety of focus race conditions in all focus modes, or at least 2004-10-04 Elijah Newren <newren@math.utah.edu> Fix a variety of focus race conditions in all focus modes, or at least make them harder to trigger (fixes #152000) * src/core.[ch] (meta_core_user_lower_and_unfocus): add a timestamp parameter; pass it along to meta_workspace_focus_default_window * src/display.[ch] (meta_display_get_current_time_roundtrip): new function * src/display.c (event_callback): pass a timestamp to the meta_workspace_activate and meta_workspace_focus_default_window function calls * src/frames.c (meta_frames_button_press_event): pass a timestamp to meta_core_user_lower_and_unfocus * src/keybindings.c (handle_activate_workspace): pass a timestamp to meta_workspace_activate, (process_workspace_switch_grab): pass a timestamp to meta_workspace_focus_default_window and meta_workspace_activate, (handle_toggle_desktop): pass a timestamp to meta_workspace_focus_default_window, (do_handle_move_to_workspace): pass a timestamp to meta_workspace_activate_with_focus, (handle_workspace_switch): meta_workspace_activate * src/screen.c (meta_screen_new): pass a timestamp to meta_workspace_activate * src/window.c (meta_window_free): pass a timestamp to meta_workspace_focus_default_window, (idle_calc_showing): don't increment the focus sentinel here, (meta_window_minimize): pass a timestamp to meta_workspace_focus_default_window, (meta_window_client_message), pass a timestamp to meta_workspace_focus_default_window * src/workspace.h (meta_workspace_activate): add timestamp parameter, (meta_workspace_activate_with_focus): add timestamp parameter, (meta_workspace_focus_default_window): add timestamp parameter * src/workspace.c (meta_workspace_focus_mru_window): make this function take a timestamp and use it for meta_window_focus or XSetInputFocus, (meta_workspace_activate_with_focus): make this function take a timestamp and pass it along to meta_window_focus and meta_workspace_focus_default_window, (meta_workspace_activate): make this function take a timestamp and pass it to meta_workspace_activate_with_focus), (meta_workspace_focus_default_window): make this function take a timestamp, warn if its 0 but try to handle that case sanely, and pass the timestamp on to meta_window_focus or meta_workspace_focus_mru_window or XSetInputFocus
2004-10-04 16:32:59 -04:00
timestamp = meta_display_get_current_time (display);
if (timestamp == CurrentTime)
{
XEvent property_event;
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_TIMESTAMP_PING,
XA_STRING, 8, PropModeAppend, NULL, 0);
XIfEvent (display->xdisplay,
&property_event,
find_timestamp_predicate,
(XPointer) display);
Fix a variety of focus race conditions in all focus modes, or at least 2004-10-04 Elijah Newren <newren@math.utah.edu> Fix a variety of focus race conditions in all focus modes, or at least make them harder to trigger (fixes #152000) * src/core.[ch] (meta_core_user_lower_and_unfocus): add a timestamp parameter; pass it along to meta_workspace_focus_default_window * src/display.[ch] (meta_display_get_current_time_roundtrip): new function * src/display.c (event_callback): pass a timestamp to the meta_workspace_activate and meta_workspace_focus_default_window function calls * src/frames.c (meta_frames_button_press_event): pass a timestamp to meta_core_user_lower_and_unfocus * src/keybindings.c (handle_activate_workspace): pass a timestamp to meta_workspace_activate, (process_workspace_switch_grab): pass a timestamp to meta_workspace_focus_default_window and meta_workspace_activate, (handle_toggle_desktop): pass a timestamp to meta_workspace_focus_default_window, (do_handle_move_to_workspace): pass a timestamp to meta_workspace_activate_with_focus, (handle_workspace_switch): meta_workspace_activate * src/screen.c (meta_screen_new): pass a timestamp to meta_workspace_activate * src/window.c (meta_window_free): pass a timestamp to meta_workspace_focus_default_window, (idle_calc_showing): don't increment the focus sentinel here, (meta_window_minimize): pass a timestamp to meta_workspace_focus_default_window, (meta_window_client_message), pass a timestamp to meta_workspace_focus_default_window * src/workspace.h (meta_workspace_activate): add timestamp parameter, (meta_workspace_activate_with_focus): add timestamp parameter, (meta_workspace_focus_default_window): add timestamp parameter * src/workspace.c (meta_workspace_focus_mru_window): make this function take a timestamp and use it for meta_window_focus or XSetInputFocus, (meta_workspace_activate_with_focus): make this function take a timestamp and pass it along to meta_window_focus and meta_workspace_focus_default_window, (meta_workspace_activate): make this function take a timestamp and pass it to meta_workspace_activate_with_focus), (meta_workspace_focus_default_window): make this function take a timestamp, warn if its 0 but try to handle that case sanely, and pass the timestamp on to meta_window_focus or meta_workspace_focus_mru_window or XSetInputFocus
2004-10-04 16:32:59 -04:00
timestamp = property_event.xproperty.time;
}
meta_display_sanity_check_timestamps (display, timestamp);
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
Fix a variety of focus race conditions in all focus modes, or at least 2004-10-04 Elijah Newren <newren@math.utah.edu> Fix a variety of focus race conditions in all focus modes, or at least make them harder to trigger (fixes #152000) * src/core.[ch] (meta_core_user_lower_and_unfocus): add a timestamp parameter; pass it along to meta_workspace_focus_default_window * src/display.[ch] (meta_display_get_current_time_roundtrip): new function * src/display.c (event_callback): pass a timestamp to the meta_workspace_activate and meta_workspace_focus_default_window function calls * src/frames.c (meta_frames_button_press_event): pass a timestamp to meta_core_user_lower_and_unfocus * src/keybindings.c (handle_activate_workspace): pass a timestamp to meta_workspace_activate, (process_workspace_switch_grab): pass a timestamp to meta_workspace_focus_default_window and meta_workspace_activate, (handle_toggle_desktop): pass a timestamp to meta_workspace_focus_default_window, (do_handle_move_to_workspace): pass a timestamp to meta_workspace_activate_with_focus, (handle_workspace_switch): meta_workspace_activate * src/screen.c (meta_screen_new): pass a timestamp to meta_workspace_activate * src/window.c (meta_window_free): pass a timestamp to meta_workspace_focus_default_window, (idle_calc_showing): don't increment the focus sentinel here, (meta_window_minimize): pass a timestamp to meta_workspace_focus_default_window, (meta_window_client_message), pass a timestamp to meta_workspace_focus_default_window * src/workspace.h (meta_workspace_activate): add timestamp parameter, (meta_workspace_activate_with_focus): add timestamp parameter, (meta_workspace_focus_default_window): add timestamp parameter * src/workspace.c (meta_workspace_focus_mru_window): make this function take a timestamp and use it for meta_window_focus or XSetInputFocus, (meta_workspace_activate_with_focus): make this function take a timestamp and pass it along to meta_window_focus and meta_workspace_focus_default_window, (meta_workspace_activate): make this function take a timestamp and pass it to meta_workspace_activate_with_focus), (meta_workspace_focus_default_window): make this function take a timestamp, warn if its 0 but try to handle that case sanely, and pass the timestamp on to meta_window_focus or meta_workspace_focus_mru_window or XSetInputFocus
2004-10-04 16:32:59 -04:00
return timestamp;
}
/**
* 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;
2014-05-02 09:34:02 -04:00
/* 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;
}
2014-05-02 09:34:02 -04:00
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.
2014-05-02 09:34:02 -04:00
*/
if (meta_stack_get_top (window->screen->stack) != window)
{
if (meta_window_has_pointer (window))
meta_window_raise (window);
else
2014-05-02 09:34:02 -04:00
meta_topic (META_DEBUG_FOCUS,
"Pointer not inside window, not raising %s\n",
window->desc);
}
return G_SOURCE_REMOVE;
}
void
meta_display_queue_autoraise_callback (MetaDisplay *display,
MetaWindow *window)
{
2014-05-02 09:34:02 -04:00
meta_topic (META_DEBUG_FOCUS,
"Queuing an autoraise timeout for %s with delay %d\n",
window->desc,
meta_prefs_get_auto_raise_delay ());
2014-05-02 09:34:02 -04:00
if (display->autoraise_timeout_id != 0)
g_source_remove (display->autoraise_timeout_id);
2014-05-02 09:34:02 -04:00
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)
{
2014-08-13 20:19:35 -04:00
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWindow *focus_window = NULL;
MetaBackend *backend = meta_get_backend ();
MetaStage *stage = META_STAGE (meta_backend_get_stage (backend));
if (!meta_display_windows_are_interactable (display))
focus_window = NULL;
else if (meta_display_xwindow_is_a_no_focus_window (display, display->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);
meta_wayland_seat_repick (compositor->seat);
2014-08-13 20:19:35 -04:00
#endif
}
void
meta_display_update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial,
gboolean focused_by_us)
{
display->focus_serial = serial;
display->focused_by_us = focused_by_us;
if (display->focus_xwindow == xwindow &&
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\n",
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;
display->focus_xwindow = None;
meta_window_set_focused_internal (previous, FALSE);
}
display->focus_window = window;
display->focus_xwindow = xwindow;
if (display->focus_window)
{
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
display->focus_window->desc, serial);
meta_window_set_focused_internal (display->focus_window, TRUE);
}
else
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
g_object_notify (G_OBJECT (display), "focus-window");
meta_display_update_active_window_hint (display);
}
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 == CurrentTime)
{
*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;
}
static void
request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *meta_window,
Window xwindow,
guint32 timestamp)
{
gulong serial;
if (meta_display_timestamp_too_old (display, &timestamp))
return;
meta_error_trap_push (display);
/* In order for mutter to know that the focus request succeeded, we track
* the serial of the "focus request" we made, but if we take the serial
* of the XSetInputFocus request, then there's no way to determine the
* difference between focus events as a result of the SetInputFocus and
* focus events that other clients send around the same time. Ensure that
* we know which is which by making two requests that the server will
* process at the same time.
*/
XGrabServer (display->xdisplay);
serial = XNextRequest (display->xdisplay);
XSetInputFocus (display->xdisplay,
xwindow,
RevertToPointerRoot,
timestamp);
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_FOCUS_SET,
XA_STRING, 8, PropModeAppend, NULL, 0);
XUngrabServer (display->xdisplay);
XFlush (display->xdisplay);
meta_display_update_focus_window (display,
meta_window,
xwindow,
serial,
TRUE);
meta_error_trap_pop (display);
display->last_focus_time = timestamp;
if (meta_window == NULL || meta_window != display->autoraise_window)
meta_display_remove_autoraise_callback (display);
}
MetaWindow*
meta_display_lookup_x_window (MetaDisplay *display,
Window xwindow)
{
return g_hash_table_lookup (display->xids, &xwindow);
}
void
meta_display_register_x_window (MetaDisplay *display,
Window *xwindowp,
MetaWindow *window)
{
g_return_if_fail (g_hash_table_lookup (display->xids, xwindowp) == NULL);
2014-05-02 09:34:02 -04:00
g_hash_table_insert (display->xids, xwindowp, window);
}
void
meta_display_unregister_x_window (MetaDisplay *display,
Window xwindow)
{
g_return_if_fail (g_hash_table_lookup (display->xids, &xwindow) != NULL);
g_hash_table_remove (display->xids, &xwindow);
}
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))
return meta_display_lookup_x_window (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 tempory
* 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;
}
/* We store sync alarms in the window ID hash table, because they are
* just more types of XIDs in the same global space, but we have
* typesafe functions to register/unregister for readability.
*/
MetaWindow*
meta_display_lookup_sync_alarm (MetaDisplay *display,
XSyncAlarm alarm)
{
return g_hash_table_lookup (display->xids, &alarm);
}
void
meta_display_register_sync_alarm (MetaDisplay *display,
XSyncAlarm *alarmp,
MetaWindow *window)
{
g_return_if_fail (g_hash_table_lookup (display->xids, alarmp) == NULL);
g_hash_table_insert (display->xids, alarmp, window);
}
void
meta_display_unregister_sync_alarm (MetaDisplay *display,
XSyncAlarm alarm)
{
g_return_if_fail (g_hash_table_lookup (display->xids, &alarm) != NULL);
g_hash_table_remove (display->xids, &alarm);
}
void
meta_display_notify_window_created (MetaDisplay *display,
MetaWindow *window)
{
g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
}
2013-10-03 18:03:53 -04:00
/**
* meta_display_xwindow_is_a_no_focus_window:
* @display: A #MetaDisplay
* @xwindow: An X11 window
*
* Returns: %TRUE iff window is one of mutter's internal "no focus" windows
* (there is one per screen) which will have the focus when there is no
* actual client window focused.
*/
gboolean
meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
Window xwindow)
{
return xwindow == display->screen->no_focus_window;
}
static MetaCursor
meta_cursor_for_grab_op (MetaGrabOp op)
{
switch (op)
2001-07-25 23:14:45 -04:00
{
case META_GRAB_OP_RESIZING_SE:
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
return META_CURSOR_SE_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_S:
case META_GRAB_OP_KEYBOARD_RESIZING_S:
return META_CURSOR_SOUTH_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_SW:
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
return META_CURSOR_SW_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_N:
case META_GRAB_OP_KEYBOARD_RESIZING_N:
return META_CURSOR_NORTH_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_NE:
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
return META_CURSOR_NE_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_NW:
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
return META_CURSOR_NW_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_W:
case META_GRAB_OP_KEYBOARD_RESIZING_W:
return META_CURSOR_WEST_RESIZE;
2001-07-25 23:14:45 -04:00
break;
case META_GRAB_OP_RESIZING_E:
case META_GRAB_OP_KEYBOARD_RESIZING_E:
return META_CURSOR_EAST_RESIZE;
2001-07-25 23:14:45 -04:00
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;
2001-07-25 23:14:45 -04:00
default:
break;
}
return META_CURSOR_DEFAULT;
2001-07-25 23:14:45 -04:00
}
void
meta_display_update_cursor (MetaDisplay *display)
{
meta_screen_set_cursor (display->screen, 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 (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 ();
}
}
2001-07-11 02:22:00 -04:00
gboolean
meta_display_begin_grab_op (MetaDisplay *display,
MetaScreen *screen,
2001-07-11 02:22:00 -04:00
MetaWindow *window,
MetaGrabOp op,
gboolean pointer_already_grabbed,
gboolean frame_action,
2001-07-11 02:22:00 -04:00
int button,
gulong modmask, /* XXX - ignored */
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
guint32 timestamp,
2001-07-11 02:22:00 -04:00
int root_x,
int root_y)
{
MetaBackend *backend = meta_get_backend ();
MetaWindow *grab_window = NULL;
MetaEventRoute event_route;
2014-04-28 17:11:47 -04:00
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\n",
op, window->desc, button, pointer_already_grabbed,
Merge reduced_resources mode patch from the branch. Offers wireframe and 2003-10-12 Havoc Pennington <hp@redhat.com> Merge reduced_resources mode patch from the branch. Offers wireframe and no-animations. * src/window.c (implement_showing): no animation if we are in reduced resources mode * src/prefs.c: add REDUCED_RESOURCES pref * src/window.c (meta_window_update_keyboard_resize): fix to modify grab_anchor_window_pos to grab_wireframe_rect if appropriate instead of window->rect * src/display.h (struct _MetaDisplay): add grab_start_serial used to avoid responding to events that occurred prior to the grab initialization. Still broken in various ways, specifically EnterNotify that occurred prior to XGrabPointer is processed as if it occurred after. * src/window.c (meta_window_update_keyboard_move): add this instead of meta_window_warp_pointer() crack * src/effects.c (meta_effects_update_wireframe): draw a kind of grid for the wireframe, instead of just a rectangle, like twm * src/screen.c (meta_screen_new): line width of 3 for the XOR gc "Reduced resources" mode based on wireframe patch from Erwann Chenede. Still pretty buggy. * src/keybindings.c (process_keyboard_move_grab) (process_keyboard_resize_grab): add gruesome wireframe hacks * src/display.c (meta_display_end_grab_op): end wireframe (meta_display_begin_grab_op): begin wireframe * src/effects.c (meta_effects_end_wireframe) (meta_effects_update_wireframe, meta_effects_begin_wireframe): routines to draw the wireframe stuff * src/window.c (window_should_be_showing): hide window when doing wireframe, commented out as it breaks grab * src/window.c (meta_window_refresh_resize_popup): handle wireframe * src/screen.c (meta_screen_new): create a screen->root_xor_gc for use in drawing wireframes * src/frames.c (meta_frames_push_delay_exposes): repaint everything before we delay
2003-10-12 02:25:38 -04:00
root_x, root_y);
2001-07-11 02:22:00 -04:00
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\n",
op, window->desc, display->grab_op,
display->grab_window ? display->grab_window->desc : "none");
2001-07-11 02:22:00 -04:00
return FALSE;
}
2001-07-25 23:14:45 -04:00
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;
2014-04-23 10:38:30 -04:00
2001-07-11 02:22:00 -04:00
if (pointer_already_grabbed)
2001-07-25 23:14:45 -04:00
display->grab_have_pointer = TRUE;
/* 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->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
timestamp);
XSync (display->xdisplay, False);
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
display->grab_have_pointer = TRUE;
2001-07-11 02:22:00 -04:00
if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op))
2001-07-11 02:22:00 -04:00
{
meta_topic (META_DEBUG_WINDOW_OPS, "XIGrabDevice() failed\n");
2001-07-11 02:22:00 -04:00
return FALSE;
}
/* Grab keys when beginning window ops; see #126497 */
if (event_route == META_EVENT_ROUTE_WINDOW_OP)
2001-07-11 02:22:00 -04:00
{
display->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp);
2001-07-11 02:22:00 -04:00
if (!display->grab_have_keyboard)
{
meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer\n");
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
display->grab_have_pointer = FALSE;
2001-07-11 02:22:00 -04:00
return FALSE;
}
}
2014-04-28 17:11:47 -04:00
display->event_route = event_route;
2001-07-11 02:22:00 -04:00
display->grab_op = op;
display->grab_window = grab_window;
2001-07-11 02:22:00 -04:00
display->grab_button = button;
display->grab_tile_mode = grab_window->tile_mode;
display->grab_tile_monitor_number = grab_window->tile_monitor_number;
Merge reduced_resources mode patch from the branch. Offers wireframe and 2003-10-12 Havoc Pennington <hp@redhat.com> Merge reduced_resources mode patch from the branch. Offers wireframe and no-animations. * src/window.c (implement_showing): no animation if we are in reduced resources mode * src/prefs.c: add REDUCED_RESOURCES pref * src/window.c (meta_window_update_keyboard_resize): fix to modify grab_anchor_window_pos to grab_wireframe_rect if appropriate instead of window->rect * src/display.h (struct _MetaDisplay): add grab_start_serial used to avoid responding to events that occurred prior to the grab initialization. Still broken in various ways, specifically EnterNotify that occurred prior to XGrabPointer is processed as if it occurred after. * src/window.c (meta_window_update_keyboard_move): add this instead of meta_window_warp_pointer() crack * src/effects.c (meta_effects_update_wireframe): draw a kind of grid for the wireframe, instead of just a rectangle, like twm * src/screen.c (meta_screen_new): line width of 3 for the XOR gc "Reduced resources" mode based on wireframe patch from Erwann Chenede. Still pretty buggy. * src/keybindings.c (process_keyboard_move_grab) (process_keyboard_resize_grab): add gruesome wireframe hacks * src/display.c (meta_display_end_grab_op): end wireframe (meta_display_begin_grab_op): begin wireframe * src/effects.c (meta_effects_end_wireframe) (meta_effects_update_wireframe, meta_effects_begin_wireframe): routines to draw the wireframe stuff * src/window.c (window_should_be_showing): hide window when doing wireframe, commented out as it breaks grab * src/window.c (meta_window_refresh_resize_popup): handle wireframe * src/screen.c (meta_screen_new): create a screen->root_xor_gc for use in drawing wireframes * src/frames.c (meta_frames_push_delay_exposes): repaint everything before we delay
2003-10-12 02:25:38 -04:00
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.tv_sec = 0;
display->grab_last_moveresize_time.tv_usec = 0;
Merge of all the changes on the constraints_experiments branch. This is 2005-11-18 Elijah Newren <newren@gmail.com> Merge of all the changes on the constraints_experiments branch. This is just a summary, to get the full ChangeLog of those changes (approx. 2000 lines): cvs -q -z3 update -Pd -r constraints_experiments cvs -q -z3 diff -pu -r CONSTRAINTS_EXPERIMENTS_BRANCHPOINT ChangeLog Bugs fixed: unfiled - constraints.c is overly complicated[1] unfiled - constraints.c is not robust when all constraints cannot simultaneously be met (constraints need to be prioritized) unfiled - keep-titlebar-onscreen constraint is decoration unaware (since get_outermost_onscreen_positions() forgets to include decorations) unfiled - keyboard snap-moving and snap-resizing snap to hidden edges 109553 - gravity w/ simultaneous move & resize doesn't work 113601 - maximize vertical and horizontal should toggle and be constrained 122196 - windows show up under vertical panels 122670 - jerky/random resizing of window via keyboard[2] 124582 - keyboard and mouse snap-resizing and snap-moving erroneously moves the window multidimensionally 136307 - don't allow apps to resize themselves off the screen (*cough* filechooser *cough*) 142016, 143784 - windows should not span multiple xineramas unless placed there by the user 143145 - clamp new windows to screensize and force them onscreen, if they'll fit 144126 - Handle pathological strut lists sanely[3] 149867 - fixed aspect ratio windows are difficult to resize[4] 152898 - make screen edges consistent; allow easy slamming of windows into the left, right, and bottom edges of the screen too. 154706 - bouncing weirdness at screen edge with keyboard moving or resizing 156699 - avoid struts when placing windows, if possible (nasty a11y blocker) 302456 - dragging offscreen too restrictive 304857 - wireframe moving off the top of the screen is misleading 308521 - make uni-directional resizing easier with alt-middle-drag and prevent the occasional super annoying resize-the-wrong-side(s) behavior 312007 - snap-resize moves windows with a minimum size constraint 312104 - resizing the top of a window can cause the bottom to grow 319351 - don't instantly snap on mouse-move-snapping, remove braindeadedness of having order of releasing shift and releasing button press matter so much [1] fixed in my opinion, anyway. [2] Actually, it's not totally fixed--it's just annoying instead of almost completely unusable. Matthias had a suggestion that may fix the remainder of the problems (see http://tinyurl.com/bwzuu). [3] This bug was originally about not-quite-so-pathological cases but was left open for the worse cases. The code from the branch handles the remainder of the cases mentioned in this bug. [4] Actually, although it's far better there's still some minor issues left: a slight drift that's only noticeable after lots of resizing, and potential problems with partially onscreen constraints due to not clearing any fixed_directions flags (aspect ratio windows get resized in both directions and thus aren't fixed in one of them) New feature: 81704 - edge resistance for user move and resize operations; in particular 3 different kinds of resistance are implemented: Pixel-Distance: window movement is resisted when it aligns with an edge unless the movement is greater than a threshold number of pixels Timeout: window movement past an edge is prevented until a certain amount of time has elapsed during the operation since the first request to move it past that edge Keyboard-Buildup: when moving or resizing with the keyboard, once a window is aligned with a certain edge it cannot move past until the correct direction has been pressed enough times (e.g. 2 or 3 times) Major changes: - constraints.c has been rewritten; very few lines of code from the old version remain. There is a comment near the top of the function explaining the basics of how the new framework works. A more detailed explanation can be found in doc/how-constraints-works.txt - edge-resistance.[ch] are new files implementing edge-resistance. - boxes.[ch] are new files containing low-level error-prone functions used heavily in constraints.c and edge-resistance.c, among various places throughout the code. testboxes.c contains a thorough testsuite for the boxes.[ch] functions compiled into a program, testboxes. - meta_window_move_resize_internal() *must* be told the gravity of the associated operation (if it's just a move operation, the gravity will be ignored, but for resize and move+resize the correct value is needed) - the craziness of different values that meta_window_move_resize_internal() accepts has been documented in a large comment at the beginning of the function. It may be possible to clean this up some, but until then things will remain as they were before--caller beware. - screen and xinerama usable areas (i.e. places not covered by e.g. panels) are cached in the workspace now, as are the screen and xinerama edges. These get updated with the workarea in src/workspace.c:ensure_work_areas_validated()
2005-11-19 09:58:50 -05:00
display->grab_last_user_action_was_snap = FALSE;
display->grab_frame_action = frame_action;
meta_display_update_cursor (display);
if (display->grab_resize_timeout_id)
{
g_source_remove (display->grab_resize_timeout_id);
display->grab_resize_timeout_id = 0;
}
2014-04-28 17:11:47 -04:00
meta_topic (META_DEBUG_WINDOW_OPS,
"Grab op %u on window %s successful\n",
display->grab_op, window ? window->desc : "(null)");
2001-07-11 02:22:00 -04:00
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,
screen, display->grab_window, display->grab_op);
2014-04-28 17:11:47 -04:00
if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
meta_window_grab_op_began (display->grab_window, display->grab_op);
2001-07-11 02:22:00 -04:00
return TRUE;
}
void
meta_display_end_grab_op (MetaDisplay *display,
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
guint32 timestamp)
2001-07-11 02:22:00 -04:00
{
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\n", grab_op, timestamp);
if (display->event_route == META_EVENT_ROUTE_NORMAL ||
display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
2001-07-11 02:22:00 -04:00
return;
g_assert (grab_window != NULL);
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->screen, grab_window, grab_op);
/* 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)
{
2014-04-20 13:04:32 -04:00
/* 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.
*/
2014-04-20 13:04:32 -04:00
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);
}
2001-07-11 02:22:00 -04:00
if (display->grab_have_pointer)
{
MetaBackend *backend = meta_get_backend ();
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
}
2001-07-11 02:22:00 -04:00
if (display->grab_have_keyboard)
{
meta_topic (META_DEBUG_WINDOW_OPS,
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
"Ungrabbing all keys timestamp %u\n", timestamp);
meta_window_ungrab_all_keys (grab_window, timestamp);
}
display->event_route = META_EVENT_ROUTE_NORMAL;
2001-07-11 02:22:00 -04:00
display->grab_window = NULL;
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
meta_display_update_cursor (display);
if (display->grab_resize_timeout_id)
{
g_source_remove (display->grab_resize_timeout_id);
display->grab_resize_timeout_id = 0;
}
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
2001-07-25 23:14:45 -04:00
}
/**
* 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_increment_event_serial (MetaDisplay *display)
{
/* We just make some random X request */
XDeleteProperty (display->xdisplay, display->leader_window,
display->atom__MOTIF_WM_HINTS);
}
void
meta_display_update_active_window_hint (MetaDisplay *display)
{
gulong data[1];
if (display->closing)
return; /* Leave old value for a replacement */
if (display->focus_window)
data[0] = display->focus_window->xwindow;
else
data[0] = None;
meta_error_trap_push (display);
XChangeProperty (display->xdisplay, display->screen->xroot,
display->atom__NET_ACTIVE_WINDOW,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (display);
}
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;
2014-05-02 09:34:02 -04:00
Refactor thrice-duplicated queue code in window.c. Closes #376760. 2007-06-10 Thomas Thurman <thomas@thurman.org.uk> Refactor thrice-duplicated queue code in window.c. Closes #376760. * src/window.c (meta_window_queue, meta_window_unqueue): New functions. * src/window.[ch] (meta_window_unqueue_*, meta_window_queue_*): Removed functions. * src/window.c (meta_window_new_with_attrs, meta_window_free, meta_window_flush_calc_showing, queue_calc_showing_func, meta_window_minimize, meta_window_unminimize, meta_window_maximize, meta_window_make_fullscreen, meta_window_shade, meta_window_unshade, meta_window_move_resize_internal, window_stick_impl, window_unstick_impl, meta_window_client_message, process_property_notify): Modified to use new queueing functions. * src/window.c (idle_move_resize, idle_update_icon, idle_calc_showing): update to receive queue number from pointer. * src/window.h (MetaQueueType): new enum. * src/window.h (MetaWindow): *_queued replaced with is_in_queue bitfield. * src/core.c (meta_core_queue_frame_resize): * src/display.c (event_callback, meta_display_queue_retheme_all_windows): Using new queueing functions. * src/frame.c (meta_window_destroy_frame): Using new queueing functions. * src/screen.c (queue_resize, meta_screen_resize_func, queue_windows_showing): Using new queueing functions. * src/window-props.c (reload_mwm_hints, reload_wm_hints, reload_transient_for): Using new queueing functions. * src/workspace.c (meta_workspace_add_window, meta_workspace_remove_window, meta_workspace_queue_calc_showing, meta_workspace_invalidate_work_area): Using new queueing functions. svn path=/trunk/; revision=3236
2007-06-10 21:15:33 -04:00
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_frame_size_changed (window);
if (window->frame)
{
meta_frame_queue_draw (window->frame);
}
2014-05-02 09:34:02 -04:00
tmp = tmp->next;
}
g_slist_free (windows);
}
void
meta_display_retheme_all (void)
{
meta_display_queue_retheme_all_windows (meta_get_display ());
}
static void
set_cursor_theme (Display *xdisplay)
{
XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ());
XcursorSetDefaultSize (xdisplay, meta_prefs_get_cursor_size ());
}
static void
update_cursor_theme (void)
{
{
MetaDisplay *display = meta_get_display ();
set_cursor_theme (display->xdisplay);
if (display->screen)
meta_screen_update_cursor (display->screen);
}
{
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
set_cursor_theme (xdisplay);
}
}
}
/*
* 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 ()->xdisplay, is_syncing);
}
}
/*
* How long, in milliseconds, we should wait after pinging a window
* before deciding it's not going to get back to us.
*/
#define PING_TIMEOUT_DELAY 5000
/**
* 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\n",
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)
{
MetaDisplay *display = window->display;
MetaPingData *ping_data;
if (serial == 0)
{
meta_warning ("Tried to ping a window with a bad serial! Not allowed.\n");
return;
}
if (!window->can_ping)
return;
ping_data = g_new (MetaPingData, 1);
ping_data->window = window;
ping_data->serial = serial;
ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
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\n",
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 repsonse
*
* 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\n", 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\n",
ping_data->serial);
/* Remove the ping data from the list */
display->pending_pings = g_slist_remove (display->pending_pings,
ping_data);
/* Remove the timeout */
if (ping_data->ping_timeout_id != 0)
{
g_source_remove (ping_data->ping_timeout_id);
ping_data->ping_timeout_id = 0;
}
meta_window_set_alive (ping_data->window, TRUE);
ping_data_free (ping_data);
break;
}
}
}
2014-03-18 20:57:32 -04:00
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)) \
2014-03-18 20:57:32 -04:00
|| ((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);
Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode <halfline@hawaii.rr.com> Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window.
2003-08-15 18:09:55 -04:00
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;
}
Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode <halfline@hawaii.rr.com> Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window.
2003-08-15 18:09:55 -04:00
tmp = workspace->mru_list;
while (tmp != start)
{
MetaWindow *window = tmp->data;
Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode <halfline@hawaii.rr.com> Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window.
2003-08-15 18:09:55 -04:00
if (IN_TAB_CHAIN (window, type))
return window;
tmp = tmp->next;
2014-05-02 09:34:02 -04:00
}
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);
Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode <halfline@hawaii.rr.com> Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window.
2003-08-15 18:09:55 -04:00
g_return_val_if_fail (workspace != NULL, NULL);
tmp = start;
2014-05-02 09:34:02 -04:00
if (skip_last)
tmp = tmp->prev;
while (tmp != NULL)
{
MetaWindow *window = tmp->data;
if (IN_TAB_CHAIN (window, type))
return window;
tmp = tmp->prev;
}
Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode <halfline@hawaii.rr.com> Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window.
2003-08-15 18:09:55 -04:00
tmp = g_list_last (workspace->mru_list);
while (tmp != start)
{
MetaWindow *window = tmp->data;
Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode <halfline@hawaii.rr.com> Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window.
2003-08-15 18:09:55 -04:00
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 conains 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 &&
l_window->workspace != 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);
2014-05-02 09:34:02 -04:00
return tab_list;
}
/**
* meta_display_get_tab_next:
* @display: a #MetaDisplay
* @type: type of tab list
* @workspace: origin workspace
* @window: (nullable): starting window
2014-05-02 09:34:02 -04:00
* @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;
2014-05-02 09:34:02 -04:00
if (window != NULL)
{
g_assert (window->display == display);
2014-05-02 09:34:02 -04:00
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
{
2014-05-02 09:34:02 -04:00
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;
2014-05-02 09:34:02 -04:00
if (window != NULL &&
IN_TAB_CHAIN (window, type) &&
(workspace == NULL ||
meta_window_located_on_workspace (window, workspace)))
return window;
else
return NULL;
}
int
meta_resize_gravity_from_grab_op (MetaGrabOp op)
{
int gravity;
2014-05-02 09:34:02 -04:00
gravity = -1;
switch (op)
{
case META_GRAB_OP_RESIZING_SE:
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
gravity = NorthWestGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_S:
case META_GRAB_OP_RESIZING_S:
gravity = NorthGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
case META_GRAB_OP_RESIZING_SW:
gravity = NorthEastGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_N:
case META_GRAB_OP_RESIZING_N:
gravity = SouthGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
case META_GRAB_OP_RESIZING_NE:
gravity = SouthWestGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
case META_GRAB_OP_RESIZING_NW:
gravity = SouthEastGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_E:
case META_GRAB_OP_RESIZING_E:
gravity = WestGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_W:
case META_GRAB_OP_RESIZING_W:
gravity = EastGravity;
break;
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
gravity = CenterGravity;
break;
default:
break;
}
return gravity;
}
void
meta_display_unmanage_screen (MetaDisplay *display,
MetaScreen *screen,
guint32 timestamp)
{
meta_verbose ("Unmanaging screen %d on display %s\n",
meta_ui_get_screen_number (), display->name);
meta_display_close (display, timestamp);
}
void
meta_display_unmanage_windows_for_screen (MetaDisplay *display,
MetaScreen *screen,
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);
2014-05-02 09:34:02 -04:00
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->screen->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;
2014-05-02 09:34:02 -04:00
if (pref == META_PREF_AUDIBLE_BELL)
{
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
}
else if (pref == META_PREF_CURSOR_THEME ||
pref == META_PREF_CURSOR_SIZE)
{
update_cursor_theme ();
}
}
CVS2003-05-29 Rob Adams <robadams@ucla.edu> CVS2003-05-29 Rob Adams <robadams@ucla.edu> Use a new property _METACITY_SENTINEL to eliminate a race condition that causes focus to behave badly with sloppy/mouse focus when lots of windows are mapped/unmapped, such as with a workspace switch. The EnterNotify events on a display are ignored until the PropertyNotify sent after all the window maps is received. This is a fix for #110970. * src/display.[ch]: New _METACITY_SENTINEL atom. (event_callback): ignore EnterNotify if the sentinel isn't clear, and decrement the sentinel counter when the PropertyNotify is received. (meta_display_increment_focus_sentinel): new function. Increments the sentinel counter and updates the property on a root window on this display. (meta_display_decrement_focus_sentinel): Decrement the sentinel counter. (meta_display_focus_sentinel_clear): returns whether the sentinel counter is zero. * src/window.c (idle_calc_showing): after showing windows, call meta_display_increment_focus_sentinel on each display for windows to be shown. * src/workspace.[ch] (meta_workspace_activate_with_focus): new function activates a workspace and focuses a particular window after the workspace is activated. (meta_workspace_activate): now just a wrapper for meta_workspace_activate_with_focus * src/keybindings.c: use new meta_workspace_activate_with_focus function to ensure that focus will follow the focused window through the workspace switch. : ----------------------------------------------------------------------
2003-05-30 16:24:00 -04:00
void
meta_display_increment_focus_sentinel (MetaDisplay *display)
{
unsigned long data[1];
data[0] = meta_display_get_current_time (display);
2014-05-02 09:34:02 -04:00
CVS2003-05-29 Rob Adams <robadams@ucla.edu> CVS2003-05-29 Rob Adams <robadams@ucla.edu> Use a new property _METACITY_SENTINEL to eliminate a race condition that causes focus to behave badly with sloppy/mouse focus when lots of windows are mapped/unmapped, such as with a workspace switch. The EnterNotify events on a display are ignored until the PropertyNotify sent after all the window maps is received. This is a fix for #110970. * src/display.[ch]: New _METACITY_SENTINEL atom. (event_callback): ignore EnterNotify if the sentinel isn't clear, and decrement the sentinel counter when the PropertyNotify is received. (meta_display_increment_focus_sentinel): new function. Increments the sentinel counter and updates the property on a root window on this display. (meta_display_decrement_focus_sentinel): Decrement the sentinel counter. (meta_display_focus_sentinel_clear): returns whether the sentinel counter is zero. * src/window.c (idle_calc_showing): after showing windows, call meta_display_increment_focus_sentinel on each display for windows to be shown. * src/workspace.[ch] (meta_workspace_activate_with_focus): new function activates a workspace and focuses a particular window after the workspace is activated. (meta_workspace_activate): now just a wrapper for meta_workspace_activate_with_focus * src/keybindings.c: use new meta_workspace_activate_with_focus function to ensure that focus will follow the focused window through the workspace switch. : ----------------------------------------------------------------------
2003-05-30 16:24:00 -04:00
XChangeProperty (display->xdisplay,
display->screen->xroot,
display->atom__MUTTER_SENTINEL,
CVS2003-05-29 Rob Adams <robadams@ucla.edu> CVS2003-05-29 Rob Adams <robadams@ucla.edu> Use a new property _METACITY_SENTINEL to eliminate a race condition that causes focus to behave badly with sloppy/mouse focus when lots of windows are mapped/unmapped, such as with a workspace switch. The EnterNotify events on a display are ignored until the PropertyNotify sent after all the window maps is received. This is a fix for #110970. * src/display.[ch]: New _METACITY_SENTINEL atom. (event_callback): ignore EnterNotify if the sentinel isn't clear, and decrement the sentinel counter when the PropertyNotify is received. (meta_display_increment_focus_sentinel): new function. Increments the sentinel counter and updates the property on a root window on this display. (meta_display_decrement_focus_sentinel): Decrement the sentinel counter. (meta_display_focus_sentinel_clear): returns whether the sentinel counter is zero. * src/window.c (idle_calc_showing): after showing windows, call meta_display_increment_focus_sentinel on each display for windows to be shown. * src/workspace.[ch] (meta_workspace_activate_with_focus): new function activates a workspace and focuses a particular window after the workspace is activated. (meta_workspace_activate): now just a wrapper for meta_workspace_activate_with_focus * src/keybindings.c: use new meta_workspace_activate_with_focus function to ensure that focus will follow the focused window through the workspace switch. : ----------------------------------------------------------------------
2003-05-30 16:24:00 -04:00
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
2014-05-02 09:34:02 -04:00
CVS2003-05-29 Rob Adams <robadams@ucla.edu> CVS2003-05-29 Rob Adams <robadams@ucla.edu> Use a new property _METACITY_SENTINEL to eliminate a race condition that causes focus to behave badly with sloppy/mouse focus when lots of windows are mapped/unmapped, such as with a workspace switch. The EnterNotify events on a display are ignored until the PropertyNotify sent after all the window maps is received. This is a fix for #110970. * src/display.[ch]: New _METACITY_SENTINEL atom. (event_callback): ignore EnterNotify if the sentinel isn't clear, and decrement the sentinel counter when the PropertyNotify is received. (meta_display_increment_focus_sentinel): new function. Increments the sentinel counter and updates the property on a root window on this display. (meta_display_decrement_focus_sentinel): Decrement the sentinel counter. (meta_display_focus_sentinel_clear): returns whether the sentinel counter is zero. * src/window.c (idle_calc_showing): after showing windows, call meta_display_increment_focus_sentinel on each display for windows to be shown. * src/workspace.[ch] (meta_workspace_activate_with_focus): new function activates a workspace and focuses a particular window after the workspace is activated. (meta_workspace_activate): now just a wrapper for meta_workspace_activate_with_focus * src/keybindings.c: use new meta_workspace_activate_with_focus function to ensure that focus will follow the focused window through the workspace switch. : ----------------------------------------------------------------------
2003-05-30 16:24:00 -04:00
display->sentinel_counter += 1;
}
void
meta_display_decrement_focus_sentinel (MetaDisplay *display)
{
display->sentinel_counter -= 1;
if (display->sentinel_counter < 0)
display->sentinel_counter = 0;
}
gboolean
meta_display_focus_sentinel_clear (MetaDisplay *display)
{
return (display->sentinel_counter == 0);
}
void
meta_display_sanity_check_timestamps (MetaDisplay *display,
guint32 timestamp)
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
{
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time))
{
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
meta_warning ("last_focus_time (%u) is greater than comparison "
"timestamp (%u). This most likely represents a buggy "
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
"client sending inaccurate timestamps in messages such as "
"_NET_ACTIVE_WINDOW. Trying to work around...\n",
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
display->last_focus_time, timestamp);
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
display->last_focus_time = timestamp;
}
if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time))
{
GSList *windows;
GSList *tmp;
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
meta_warning ("last_user_time (%u) is greater than comparison "
"timestamp (%u). This most likely represents a buggy "
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
"client sending inaccurate timestamps in messages such as "
"_NET_ACTIVE_WINDOW. Trying to work around...\n",
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
display->last_user_time, timestamp);
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
display->last_user_time = timestamp;
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
tmp = windows;
while (tmp != NULL)
{
MetaWindow *window = tmp->data;
2014-05-02 09:34:02 -04:00
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time))
{
meta_warning ("%s appears to be one of the offending windows "
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
"with a timestamp of %u. Working around...\n",
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
window->desc, window->net_wm_user_time);
meta_window_set_user_time (window, timestamp);
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
}
Big patch to cover about 6 different issues in order to correct rare 2005-02-20 Elijah Newren <newren@gmail.com> Big patch to cover about 6 different issues in order to correct rare problems with timestamps (make sure window selected in tasklist actually gets focus, sanity check timestamps to avoid rogue apps hosing the system, correct the updating of net_wm_user_time, correctly handle timestamps of 0 when comparing xserver timestamps for those who have had their systems up for over 25 days or so, add some debugging information to verbose logs, some code cleanups). Fixes all issues listed in #167358. * src/display.h: (struct _MetaDisplay): clarify comment on last_focus_time, introduce a new variable--last_user_time, (XSERVER_TIME_IS_BEFORE macro): put this functionality into a separate macro and then introduce a new macro with this name that uses the old one but adds additional special-case checks for timestamps that are 0, (comment to meta_display_set_input_focus_window): add information about how last_user_time should be used in this function * src/display.c (santiy_check_timestamps): new function, (meta_display_open): intialize display->last_user_time, (meta_display_get_current_time_roundtrip): use the timestamp, which is known to be good, in order to sanity_check_timestamps, (event_callback): use the new meta_window_ste_user_time() function in order to correct problems, use the timestamp of KeyPress and ButtonPress events, which are known to be good, in order to sanity_check_timestamps, (timestamp_too_old): new function for common behavior of meta_display_focus_the_no_focus_window and meta_display_set_input_focus_window, with added checking for display->last_user_time in addition to display->last_focus_time, (meta_display_set_input_focus_window): replace some of the code with a call to timestamp_too_old(), (meta_display_focus_the_no_focus_window): replace some of th ecode with a call to timestamp_too_old() * src/window.h: (meta_window_set_user_time): new function to abstract the many things that need to be done when updating the net_wm_user_time of any window * src/window.c: (meta_window_activate): add debugging spew, make sure the comparison is made with last_user_time NOT last_focus_time, use meta_window_set_user_time() function in order to correct problems, (meta_window_client_message): add a newline to a debugging message to make them easier to read, (meta_window_set_user_time): new function * src/window-props.c (reload_net_wm_user_time): use the new meta_window_ste_user_time() function in order to correct problems
2005-02-20 12:14:16 -05:00
tmp = tmp->next;
}
g_slist_free (windows);
}
}
void
2014-05-02 09:34:02 -04:00
meta_display_set_input_focus_window (MetaDisplay *display,
MetaWindow *window,
gboolean focus_frame,
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
guint32 timestamp)
{
request_xserver_input_focus_change (display,
window->screen,
window,
focus_frame ? window->frame->xwindow : window->xwindow,
timestamp);
}
void
meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
Window window,
guint32 timestamp)
{
request_xserver_input_focus_change (display,
screen,
NULL,
window,
timestamp);
}
void
meta_display_focus_the_no_focus_window (MetaDisplay *display,
MetaScreen *screen,
Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ 2006-09-13 Elijah Newren <newren gmail com> * src/common.h (MetaWindowMenuFunc): * src/core.[ch] (meta_core_user_lower_and_unfocus, meta_core_user_focus, meta_core_show_window_menu, meta_core_begin_grab_op, meta_core_end_grab_op): * src/delete.c (delete_ping_reply_func, delete_ping_timeout_func, meta_window_delete): * src/display.[ch] (struct MetaDisplay, struct MetaPingData, sanity_check_timestamps, meta_display_open, event_callback, meta_spew_event, meta_display_set_grab_op_cursor, meta_display_begin_grab_op, meta_display_end_grab_op, meta_display_ping_timeout, meta_display_ping_window, process_pong_message, timestamp_too_old, meta_display_set_input_focus_window): * src/keybindings.[ch] (grab_keyboard, ungrab_keyboard, meta_screen_grab_all_keys, meta_window_grab_all_keys, meta_window_ungrab_all_keys, error_on_generic_command, error_on_command, error_on_terminal_command): * src/metacity-dialog.c (on_realize, warn_about_no_sm_support, error_about_command, main): * src/screen.[ch] (struct _MetaScreen, meta_screen_new, meta_screen_show_desktop, meta_screen_apply_startup_properties): * src/session.c (warn_about_lame_clients_and_finish_interact): * src/window.[ch] (struct _MetaWindow, intervening_user_event_occurred, window_activate, meta_window_delete, meta_window_focus, meta_window_send_icccm_message, meta_window_client_message, menu_callback, meta_window_show_menu, struct EventScannerData, check_use_this_motion_notify, meta_window_begin_grab_op, meta_window_set_user_time): * src/workspace.[ch] (focus_ancestor_or_mru_window, meta_workspace_activate_with_focus, meta_workspace_activate, meta_workspace_focus_default_window, focus_ancestor_or_mru_window): Fix issues on 64-bit machines with timestamps by using guint32 (like gtk+ does) instead of Time. #348305
2006-09-13 12:32:33 -04:00
guint32 timestamp)
{
request_xserver_input_focus_change (display,
screen,
NULL,
screen->no_focus_window,
timestamp);
}
void
meta_display_remove_autoraise_callback (MetaDisplay *display)
{
if (display->autoraise_timeout_id != 0)
{
g_source_remove (display->autoraise_timeout_id);
display->autoraise_timeout_id = 0;
display->autoraise_window = NULL;
}
}
void
meta_display_overlay_key_activate (MetaDisplay *display)
{
g_signal_emit (display, display_signals[OVERLAY_KEY], 0);
}
void
2013-10-03 18:03:53 -04:00
meta_display_accelerator_activate (MetaDisplay *display,
guint action,
ClutterKeyEvent *event)
{
g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
2013-10-03 18:03:53 -04:00
0, action,
clutter_input_device_get_device_id (event->device),
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_get_xinput_opcode: (skip)
* @display: a #MetaDisplay
*
*/
int
meta_display_get_xinput_opcode (MetaDisplay *display)
{
return display->xinput_opcode;
}
/**
* 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 (meta_get_backend ()))
{
return (META_DISPLAY_HAS_XINPUT_23 (display) &&
!meta_is_wayland_compositor());
}
g_assert_not_reached ();
}
/**
* meta_display_get_xdisplay: (skip)
* @display: a #MetaDisplay
*
*/
Display *
meta_display_get_xdisplay (MetaDisplay *display)
{
return display->xdisplay;
}
/**
* meta_display_get_compositor: (skip)
* @display: a #MetaDisplay
*
*/
MetaCompositor *
meta_display_get_compositor (MetaDisplay *display)
{
return display->compositor;
}
gboolean
meta_display_has_shape (MetaDisplay *display)
{
return META_DISPLAY_HAS_SHAPE (display);
}
/**
* 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;
}
2014-05-02 09:34:02 -04:00
int
meta_display_get_damage_event_base (MetaDisplay *display)
{
return display->damage_event_base;
}
int
meta_display_get_shape_event_base (MetaDisplay *display)
{
return display->shape_event_base;
}
/**
* 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;
}
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return meta_cursor_create_x_cursor (display->xdisplay, cursor);
}
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_set_alarm_filter (MetaDisplay *display,
MetaAlarmFilter filter,
gpointer data)
{
g_return_if_fail (filter == NULL || display->alarm_filter == NULL);
display->alarm_filter = filter;
display->alarm_filter_data = data;
}
void
meta_display_request_pad_osd (MetaDisplay *display,
ClutterInputDevice *pad,
gboolean edition_mode)
{
MetaInputSettings *input_settings;
const gchar *layout_path = NULL;
ClutterActor *osd;
MetaLogicalMonitor *logical_monitor;
gint monitor_idx;
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_settings = meta_backend_get_input_settings (meta_get_backend ());
if (input_settings)
{
settings = meta_input_settings_get_tablet_settings (input_settings, pad);
logical_monitor =
meta_input_settings_get_tablet_logical_monitor (input_settings, pad);
#ifdef HAVE_LIBWACOM
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
pad);
layout_path = libwacom_get_layout_filename (wacom_device);
#endif
}
if (!layout_path || !settings)
return;
if (logical_monitor)
{
monitor_idx =
meta_screen_get_monitor_index_for_rect (display->screen,
&logical_monitor->rect);
}
else
{
monitor_idx = meta_screen_get_current_monitor (display->screen);
}
g_signal_emit (display, display_signals[SHOW_PAD_OSD], 0,
pad, settings, layout_path,
edition_mode, monitor_idx, &osd);
if (osd)
{
display->current_pad_osd = osd;
g_object_add_weak_pointer (G_OBJECT (display->current_pad_osd),
(gpointer *) &display->current_pad_osd);
}
g_object_unref (settings);
}
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 */
if (action_type == META_PAD_ACTION_BUTTON)
{
MetaInputSettings *settings;
settings = meta_backend_get_input_settings (meta_get_backend ());
label = meta_input_settings_get_pad_button_action_label (settings, pad, 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;
}