Compare commits

...

5 Commits

Author SHA1 Message Date
0c4fdb2d31 window-x11: Cleanup header and shuffle function locations
The functions meta_window_x11_create_sync_request_alarm() and
meta_window_x11_destroy_sync_request_alarm() are not used outside
MetaWindowX11 now, and don't need to be exposed in window-x11.h

Remove them from window-x11.h and shuffle these functions to
before their first usage, to avoid having to add their prototypes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/372
2019-02-13 08:05:49 +00:00
4504a313f7 window: Trap X11 warp pointer errors on MetaBackendX11
Only the X11 backend cares about trapping X11 errors when
warping pointers, and there is no reason for it to be done
by MetaWindow.

Move the push()/pop() calls to MetaBackendX11, and simplify
warp_grab_pointer() by removing the boolean return value
that is not being used anywhere.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/372
2019-02-13 08:05:49 +00:00
ed7fc825e1 window: Delegate meta_window_has_pointer to subclasses
meta_window_has_pointer() is already aware of X11 or Wayland
specific implementations, but it makes more sense to have it
implemented by the subclasses themselves.

Move the Wayland and X11 code paths to their respective subclasses
through a new vfunc MetaWindowClass.has_pointer().

https://gitlab.gnome.org/GNOME/mutter/merge_requests/372
2019-02-13 08:05:49 +00:00
43307c6b84 window: Delegate map and unmap to subclasses
As of now, the base class MetaWindow is calling into X11
API when mapping and unmapping a window. Even on purely
Wayland clients.

Fix that by moving those calls to MetaWindow subclasses.
On MetaWindowX11, it calls into X11 APIs, and the Wayland
implementation is stub.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/372
2019-02-13 08:05:49 +00:00
b4d55325d7 window: Move _NET_WM_SYNC_REQUEST and family to MetaWindowX11
The code to react to _NET_WM_SYNC_REQUEST and family (counter,
alarm, etc) currently lives in MetaWindow, even though most of
its management is done by MetaWindowX11.

In an ideal Wayland-as-default world, MetaWindow is completely
agnostic to the display server implementation, delegating to
MetaWindowX11 and MetaWindowWayland their respective display
server internals.

To help this goal, move the X11-specific code to deal with
_NET_WM_SYNC_REQUEST to MetaWindowX11.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/372
2019-02-13 08:05:49 +00:00
10 changed files with 371 additions and 237 deletions

View File

@ -52,6 +52,7 @@
#include "compositor/compositor-private.h"
#include "core/display-private.h"
#include "meta/meta-cursor-tracker.h"
#include "meta/meta-x11-errors.h"
#include "meta/util.h"
struct _MetaBackendX11Private
@ -598,6 +599,10 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
MetaDisplay *display = meta_get_display ();
if (display)
meta_x11_error_trap_push (display->x11_display);
XIWarpPointer (priv->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
@ -605,6 +610,10 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
meta_backend_x11_get_xwindow (x11),
0, 0, 0, 0,
x, y);
if (display &&
meta_x11_error_trap_pop_with_return (display->x11_display) != Success)
meta_verbose ("Failed to warp pointer\n");
}
static MetaLogicalMonitor *

View File

@ -30,6 +30,7 @@
#include "meta/meta-x11-errors.h"
#include "meta/window.h"
#include "x11/meta-x11-display-private.h"
#include "x11/window-x11.h"
struct _MetaWindowActorX11
{
@ -366,9 +367,12 @@ meta_window_actor_x11_queue_frame_drawn (MetaWindowActor *actor,
if (meta_window_actor_is_destroyed (actor))
return;
g_assert (META_IS_WINDOW_X11 (window));
frame = g_slice_new0 (FrameData);
frame->frame_counter = -1;
frame->sync_request_serial = window->sync_request_serial;
frame->sync_request_serial =
meta_window_x11_get_sync_request_serial (META_WINDOW_X11 (window));
actor_x11->frames = g_list_prepend (actor_x11->frames, frame);
@ -485,13 +489,14 @@ meta_window_actor_x11_constructed (GObject *object)
MetaWindowActor *window_actor = META_WINDOW_ACTOR (object);
MetaWindow *window =
meta_window_actor_get_meta_window (window_actor);
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
G_OBJECT_CLASS (meta_window_actor_x11_parent_class)->constructed (object);
/* If a window doesn't start off with updates frozen, we should
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
*/
if (window->extended_sync_request_counter &&
if (meta_window_x11_has_extended_sync_request_counter (window_x11) &&
!meta_window_updates_are_frozen (window))
meta_window_actor_queue_frame_drawn (window_actor, FALSE);
}

View File

@ -403,9 +403,6 @@ struct _MetaWindow
/* if TRUE we have a grab on the focus click buttons */
guint have_focus_click_grab : 1;
/* if TRUE, application is buggy and SYNC resizing is turned off */
guint disable_sync : 1;
/* if TRUE, window is attached to its parent */
guint attached : 1;
@ -431,21 +428,9 @@ struct _MetaWindow
/* _NET_WM_WINDOW_OPACITY rescaled to 0xFF */
guint8 opacity;
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
guint extended_sync_request_counter : 1;
/* Note: can be NULL */
GSList *struts;
/* XSync update counter */
XSyncCounter sync_request_counter;
gint64 sync_request_serial;
gint64 sync_request_wait_serial;
guint sync_request_timeout_id;
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
XSyncAlarm sync_request_alarm;
/* Number of UnmapNotify that are caused by us, if
* we get UnmapNotify with none pending then the client
* is withdrawing the window.
@ -532,6 +517,8 @@ struct _MetaWindowClass
void (*manage) (MetaWindow *window);
void (*unmanage) (MetaWindow *window);
void (*map) (MetaWindow *window);
void (*unmap) (MetaWindow *window);
void (*ping) (MetaWindow *window,
guint32 serial);
void (*delete) (MetaWindow *window,
@ -570,6 +557,7 @@ struct _MetaWindowClass
gboolean (*is_stackable) (MetaWindow *window);
gboolean (*can_ping) (MetaWindow *window);
gboolean (*are_updates_frozen) (MetaWindow *window);
gboolean (*has_pointer) (MetaWindow *window);
};
/* These differ from window->has_foo_func in that they consider

View File

@ -82,7 +82,6 @@
#include "meta/group.h"
#include "meta/meta-cursor-tracker.h"
#include "meta/meta-enum-types.h"
#include "meta/meta-x11-errors.h"
#include "meta/prefs.h"
#include "ui/ui.h"
#include "x11/meta-x11-display-private.h"
@ -799,6 +798,7 @@ client_window_should_be_mapped (MetaWindow *window)
static void
sync_client_window_mapped (MetaWindow *window)
{
MetaWindowClass *window_class = META_WINDOW_GET_CLASS (window);
gboolean should_be_mapped = client_window_should_be_mapped (window);
g_return_if_fail (!window->override_redirect);
@ -808,17 +808,15 @@ sync_client_window_mapped (MetaWindow *window)
window->mapped = should_be_mapped;
meta_x11_error_trap_push (window->display->x11_display);
if (should_be_mapped)
{
XMapWindow (window->display->x11_display->xdisplay, window->xwindow);
window_class->map (window);
}
else
{
XUnmapWindow (window->display->x11_display->xdisplay, window->xwindow);
window_class->unmap (window);
window->unmaps_pending ++;
}
meta_x11_error_trap_pop (window->display->x11_display);
}
static gboolean
@ -999,11 +997,6 @@ _meta_window_shared_new (MetaDisplay *display,
window->workspace = NULL;
window->sync_request_counter = None;
window->sync_request_serial = 0;
window->sync_request_timeout_id = 0;
window->sync_request_alarm = None;
meta_window_update_sandboxed_app_id (window);
meta_window_update_desc (window);
@ -1083,7 +1076,6 @@ _meta_window_shared_new (MetaDisplay *display,
window->calc_placement = FALSE;
window->shaken_loose = FALSE;
window->have_focus_click_grab = FALSE;
window->disable_sync = FALSE;
window->unmaps_pending = 0;
@ -1528,12 +1520,6 @@ meta_window_unmanage (MetaWindow *window,
invalidate_work_areas (window);
}
if (window->sync_request_timeout_id)
{
g_source_remove (window->sync_request_timeout_id);
window->sync_request_timeout_id = 0;
}
if (window->display->grab_window == window)
meta_display_end_grab_op (window->display, timestamp);
@ -5948,8 +5934,8 @@ check_moveresize_frequency (MetaWindow *window,
/* If we are throttling via _NET_WM_SYNC_REQUEST, we don't need
* an artificial timeout-based throttled */
if (!window->disable_sync &&
window->sync_request_alarm != None)
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11 &&
meta_window_x11_has_sync_request_alarm (META_WINDOW_X11 (window)))
return TRUE;
elapsed = time_diff (&current_time, &window->display->grab_last_moveresize_time);
@ -6311,7 +6297,8 @@ update_resize (MetaWindow *window,
* resize the window when the window responds, or when we time
* the response out.
*/
if (window->sync_request_timeout_id != 0)
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11 &&
meta_window_x11_is_sync_request_scheduled (META_WINDOW_X11 (window)))
return;
if (!check_moveresize_frequency (window, &remaining) && !force)
@ -6823,7 +6810,7 @@ meta_window_is_ancestor_of_transient (MetaWindow *window,
/* Warp pointer to location appropriate for grab,
* return root coordinates where pointer ended up.
*/
static gboolean
static void
warp_grab_pointer (MetaWindow *window,
MetaGrabOp grab_op,
int *x,
@ -6864,8 +6851,6 @@ warp_grab_pointer (MetaWindow *window,
*x = CLAMP (*x, 0, display_rect.width - 1);
*y = CLAMP (*y, 0, display_rect.height - 1);
meta_x11_error_trap_push (display->x11_display);
meta_topic (META_DEBUG_WINDOW_OPS,
"Warping pointer to %d,%d with window at %d,%d\n",
*x, *y, rect.x, rect.y);
@ -6881,19 +6866,8 @@ warp_grab_pointer (MetaWindow *window,
meta_window_get_frame_rect (window,
&display->grab_anchor_window_pos);
{
MetaBackend *backend = meta_get_backend ();
meta_backend_warp_pointer (backend, *x, *y);
}
if (meta_x11_error_trap_pop_with_return (display->x11_display) != Success)
{
meta_verbose ("Failed to warp pointer for window %s\n",
window->desc);
return FALSE;
}
return TRUE;
meta_backend_warp_pointer (meta_get_backend (), *x, *y);
}
void
@ -8118,51 +8092,10 @@ mouse_mode_focus (MetaWindow *window,
}
}
static gboolean
window_has_pointer_wayland (MetaWindow *window)
{
ClutterDeviceManager *dm;
ClutterInputDevice *dev;
ClutterActor *pointer_actor, *window_actor;
dm = clutter_device_manager_get_default ();
dev = clutter_device_manager_get_core_device (dm, CLUTTER_POINTER_DEVICE);
pointer_actor = clutter_input_device_get_pointer_actor (dev);
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
return pointer_actor && clutter_actor_contains (window_actor, pointer_actor);
}
static gboolean
window_has_pointer_x11 (MetaWindow *window)
{
MetaX11Display *x11_display = window->display->x11_display;
Window root, child;
double root_x, root_y, x, y;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
meta_x11_error_trap_push (x11_display);
XIQueryPointer (x11_display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
x11_display->xroot,
&root, &child,
&root_x, &root_y, &x, &y,
&buttons, &mods, &group);
meta_x11_error_trap_pop (x11_display);
free (buttons.mask);
return meta_x11_display_lookup_x_window (x11_display, child) == window;
}
gboolean
meta_window_has_pointer (MetaWindow *window)
{
if (meta_is_wayland_compositor ())
return window_has_pointer_wayland (window);
else
return window_has_pointer_x11 (window);
return META_WINDOW_GET_CLASS (window)->has_pointer (window);
}
static gboolean

View File

@ -111,6 +111,16 @@ meta_window_wayland_unmanage (MetaWindow *window)
meta_display_unregister_wayland_window (window->display, window);
}
static void
meta_window_wayland_map (MetaWindow *window)
{
}
static void
meta_window_wayland_unmap (MetaWindow *window)
{
}
static void
meta_window_wayland_ping (MetaWindow *window,
guint32 serial)
@ -611,6 +621,21 @@ meta_window_wayland_are_updates_frozen (MetaWindow *window)
return !wl_window->has_been_shown;
}
static gboolean
meta_window_wayland_has_pointer (MetaWindow *window)
{
ClutterDeviceManager *dm;
ClutterInputDevice *dev;
ClutterActor *pointer_actor, *window_actor;
dm = clutter_device_manager_get_default ();
dev = clutter_device_manager_get_core_device (dm, CLUTTER_POINTER_DEVICE);
pointer_actor = clutter_input_device_get_pointer_actor (dev);
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
return pointer_actor && clutter_actor_contains (window_actor, pointer_actor);
}
static void
meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
{
@ -618,6 +643,8 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
window_class->manage = meta_window_wayland_manage;
window_class->unmanage = meta_window_wayland_unmanage;
window_class->map = meta_window_wayland_map;
window_class->unmap = meta_window_wayland_unmap;
window_class->ping = meta_window_wayland_ping;
window_class->delete = meta_window_wayland_delete;
window_class->kill = meta_window_wayland_kill;
@ -634,6 +661,7 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
window_class->is_stackable = meta_window_wayland_is_stackable;
window_class->can_ping = meta_window_wayland_can_ping;
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
window_class->has_pointer = meta_window_wayland_has_pointer;
}
MetaWindow *

View File

@ -71,6 +71,21 @@ meta_window_xwayland_shortcuts_inhibited (MetaWindow *window,
return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source);
}
static gboolean
meta_window_xwayland_has_pointer (MetaWindow *window)
{
ClutterDeviceManager *dm;
ClutterInputDevice *dev;
ClutterActor *pointer_actor, *window_actor;
dm = clutter_device_manager_get_default ();
dev = clutter_device_manager_get_core_device (dm, CLUTTER_POINTER_DEVICE);
pointer_actor = clutter_input_device_get_pointer_actor (dev);
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
return pointer_actor && clutter_actor_contains (window_actor, pointer_actor);
}
static void
meta_window_xwayland_get_property (GObject *object,
guint prop_id,
@ -117,6 +132,7 @@ meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass)
window_class->force_restore_shortcuts = meta_window_xwayland_force_restore_shortcuts;
window_class->shortcuts_inhibited = meta_window_xwayland_shortcuts_inhibited;
window_class->has_pointer = meta_window_xwayland_has_pointer;
gobject_class->get_property = meta_window_xwayland_get_property;
gobject_class->set_property = meta_window_xwayland_set_property;

View File

@ -1068,34 +1068,9 @@ reload_update_counter (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (value->type != META_PROP_VALUE_INVALID)
{
meta_window_x11_destroy_sync_request_alarm (window);
window->sync_request_counter = None;
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
if (value->v.xcounter_list.n_counters == 0)
{
meta_warning ("_NET_WM_SYNC_REQUEST_COUNTER is empty\n");
return;
}
if (value->v.xcounter_list.n_counters == 1)
{
window->sync_request_counter = value->v.xcounter_list.counters[0];
window->extended_sync_request_counter = FALSE;
}
else
{
window->sync_request_counter = value->v.xcounter_list.counters[1];
window->extended_sync_request_counter = TRUE;
}
meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx (extended=%s)\n",
window->sync_request_counter,
window->extended_sync_request_counter ? "true" : "false");
if (window->extended_sync_request_counter)
meta_window_x11_create_sync_request_alarm (window);
}
meta_window_x11_setup_sync_request_counter (window_x11, value);
}
#define FLAG_TOGGLED_ON(old,new,flag) \

View File

@ -25,6 +25,8 @@
#include "core/window-private.h"
#include "x11/iconcache.h"
#include "x11/window-x11.h"
#include "x11/xprops.h"
G_BEGIN_DECLS
@ -72,8 +74,28 @@ struct _MetaWindowX11Private
MetaIconCache icon_cache;
Pixmap wm_hints_pixmap;
Pixmap wm_hints_mask;
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
XSyncAlarm sync_request_alarm;
/* XSync update counter */
XSyncCounter sync_request_counter;
int64_t sync_request_serial;
int64_t sync_request_wait_serial;
guint sync_request_timeout_id;
/* if TRUE, application is buggy and SYNC resizing is turned off */
gboolean disable_sync;
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
gboolean extended_sync_request_counter;
};
void meta_window_x11_setup_sync_request_counter (MetaWindowX11 *window_x11,
MetaPropValue *value);
G_END_DECLS
#endif

View File

@ -510,6 +510,97 @@ meta_window_apply_session_info (MetaWindow *window,
}
}
static void
meta_window_x11_create_sync_request_alarm (MetaWindow *window)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
MetaX11Display *x11_display = window->display->x11_display;
XSyncAlarmAttributes values;
XSyncValue init;
if (priv->sync_request_counter == None ||
priv->sync_request_alarm != None)
return;
meta_x11_error_trap_push (x11_display);
/* In the new (extended style), the counter value is initialized by
* the client before mapping the window. In the old style, we're
* responsible for setting the initial value of the counter.
*/
if (priv->extended_sync_request_counter)
{
if (!XSyncQueryCounter(x11_display->xdisplay,
priv->sync_request_counter,
&init))
{
meta_x11_error_trap_pop_with_return (x11_display);
priv->sync_request_counter = None;
return;
}
priv->sync_request_serial =
XSyncValueLow32 (init) + ((gint64)XSyncValueHigh32 (init) << 32);
}
else
{
XSyncIntToValue (&init, 0);
XSyncSetCounter (x11_display->xdisplay,
priv->sync_request_counter, init);
priv->sync_request_serial = 0;
}
values.trigger.counter = priv->sync_request_counter;
values.trigger.test_type = XSyncPositiveComparison;
/* Initialize to one greater than the current value */
values.trigger.value_type = XSyncRelative;
XSyncIntToValue (&values.trigger.wait_value, 1);
/* After triggering, increment test_value by this until
* until the test condition is false */
XSyncIntToValue (&values.delta, 1);
/* we want events (on by default anyway) */
values.events = True;
priv->sync_request_alarm = XSyncCreateAlarm (x11_display->xdisplay,
XSyncCACounter |
XSyncCAValueType |
XSyncCAValue |
XSyncCATestType |
XSyncCADelta |
XSyncCAEvents,
&values);
if (meta_x11_error_trap_pop_with_return (x11_display) == Success)
meta_x11_display_register_sync_alarm (x11_display, &priv->sync_request_alarm, window);
else
{
priv->sync_request_alarm = None;
priv->sync_request_counter = None;
}
}
static void
meta_window_x11_destroy_sync_request_alarm (MetaWindow *window)
{
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (META_WINDOW_X11 (window));
MetaX11Display *x11_display = window->display->x11_display;
if (priv->sync_request_alarm != None)
{
/* Has to be unregistered _before_ clearing the structure field */
meta_x11_display_unregister_sync_alarm (x11_display, priv->sync_request_alarm);
XSyncDestroyAlarm (x11_display->xdisplay,
priv->sync_request_alarm);
priv->sync_request_alarm = None;
}
}
static void
meta_window_x11_manage (MetaWindow *window)
{
@ -588,6 +679,12 @@ meta_window_x11_unmanage (MetaWindow *window)
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
if (priv->sync_request_timeout_id)
{
g_source_remove (priv->sync_request_timeout_id);
priv->sync_request_timeout_id = 0;
}
meta_x11_error_trap_push (x11_display);
meta_window_x11_destroy_sync_request_alarm (window);
@ -703,6 +800,28 @@ meta_window_x11_can_ping (MetaWindow *window)
return priv->wm_ping;
}
static void
meta_window_x11_map (MetaWindow *window)
{
meta_x11_error_trap_push (window->display->x11_display);
XMapWindow (window->display->x11_display->xdisplay,
window->xwindow);
meta_x11_error_trap_pop (window->display->x11_display);
}
static void
meta_window_x11_unmap (MetaWindow *window)
{
meta_x11_error_trap_push (window->display->x11_display);
XUnmapWindow (window->display->x11_display->xdisplay,
window->xwindow);
meta_x11_error_trap_pop (window->display->x11_display);
}
static void
meta_window_x11_ping (MetaWindow *window,
guint32 serial)
@ -895,7 +1014,7 @@ meta_window_x11_grab_op_began (MetaWindow *window,
if (meta_grab_op_is_resizing (op))
{
if (window->sync_request_counter != None)
if (priv->sync_request_counter != None)
meta_window_x11_create_sync_request_alarm (window);
if (window->size_hints.width_inc > 2 || window->size_hints.height_inc > 2)
@ -1038,18 +1157,20 @@ static gboolean
sync_request_timeout (gpointer data)
{
MetaWindow *window = data;
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (META_WINDOW_X11 (window));
window->sync_request_timeout_id = 0;
priv->sync_request_timeout_id = 0;
/* We have now waited for more than a second for the
* application to respond to the sync request
*/
window->disable_sync = TRUE;
priv->disable_sync = TRUE;
/* Reset the wait serial, so we don't continue freezing
* window updates
*/
window->sync_request_wait_serial = 0;
priv->sync_request_wait_serial = 0;
meta_compositor_sync_updates_frozen (window->display->compositor, window);
if (window == window->display->grab_window &&
@ -1068,6 +1189,9 @@ sync_request_timeout (gpointer data)
static void
send_sync_request (MetaWindow *window)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
MetaX11Display *x11_display = window->display->x11_display;
XClientMessageEvent ev;
gint64 wait_serial;
@ -1079,9 +1203,9 @@ send_sync_request (MetaWindow *window)
* for the old style. The increment of 240 is specified by the EWMH
* and is (1 second) * (60fps) * (an increment of 4 per frame).
*/
wait_serial = window->sync_request_serial + 240;
wait_serial = priv->sync_request_serial + 240;
window->sync_request_wait_serial = wait_serial;
priv->sync_request_wait_serial = wait_serial;
ev.type = ClientMessage;
ev.window = window->xwindow;
@ -1096,7 +1220,7 @@ send_sync_request (MetaWindow *window)
ev.data.l[1] = meta_display_get_current_time (window->display);
ev.data.l[2] = wait_serial & G_GUINT64_CONSTANT(0xffffffff);
ev.data.l[3] = wait_serial >> 32;
ev.data.l[4] = window->extended_sync_request_counter ? 1 : 0;
ev.data.l[4] = priv->extended_sync_request_counter ? 1 : 0;
/* We don't need to trap errors here as we are already
* inside an error_trap_push()/pop() pair.
@ -1108,10 +1232,10 @@ send_sync_request (MetaWindow *window)
* if this time expires, we consider the window unresponsive
* and resize it unsynchonized.
*/
window->sync_request_timeout_id = g_timeout_add (1000,
sync_request_timeout,
window);
g_source_set_name_by_id (window->sync_request_timeout_id,
priv->sync_request_timeout_id = g_timeout_add (1000,
sync_request_timeout,
window);
g_source_set_name_by_id (priv->sync_request_timeout_id,
"[mutter] sync_request_timeout");
meta_compositor_sync_updates_frozen (window->display->compositor, window);
@ -1329,7 +1453,7 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
* will be left undisturbed for us to paint to the screen until
* the client finishes redrawing.
*/
if (window->extended_sync_request_counter)
if (priv->extended_sync_request_counter)
configure_frame_first = TRUE;
else
configure_frame_first = size_dx + size_dy >= 0;
@ -1357,10 +1481,10 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
if (window == window->display->grab_window &&
meta_grab_op_is_resizing (window->display->grab_op) &&
!window->disable_sync &&
window->sync_request_counter != None &&
window->sync_request_alarm != None &&
window->sync_request_timeout_id == 0)
!priv->disable_sync &&
priv->sync_request_counter != None &&
priv->sync_request_alarm != None &&
priv->sync_request_timeout_id == 0)
{
send_sync_request (window);
}
@ -1696,16 +1820,43 @@ meta_window_x11_is_stackable (MetaWindow *window)
static gboolean
meta_window_x11_are_updates_frozen (MetaWindow *window)
{
if (window->extended_sync_request_counter &&
window->sync_request_serial % 2 == 1)
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
if (priv->extended_sync_request_counter &&
priv->sync_request_serial % 2 == 1)
return TRUE;
if (window->sync_request_serial < window->sync_request_wait_serial)
if (priv->sync_request_serial < priv->sync_request_wait_serial)
return TRUE;
return FALSE;
}
static gboolean
meta_window_x11_has_pointer (MetaWindow *window)
{
MetaX11Display *x11_display = window->display->x11_display;
Window root, child;
double root_x, root_y, x, y;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
meta_x11_error_trap_push (x11_display);
XIQueryPointer (x11_display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
x11_display->xroot,
&root, &child,
&root_x, &root_y, &x, &y,
&buttons, &mods, &group);
meta_x11_error_trap_pop (x11_display);
free (buttons.mask);
return meta_x11_display_lookup_x_window (x11_display, child) == window;
}
static void
meta_window_x11_class_init (MetaWindowX11Class *klass)
{
@ -1713,6 +1864,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
window_class->manage = meta_window_x11_manage;
window_class->unmanage = meta_window_x11_unmanage;
window_class->map = meta_window_x11_map;
window_class->unmap = meta_window_x11_unmap;
window_class->ping = meta_window_x11_ping;
window_class->delete = meta_window_x11_delete;
window_class->kill = meta_window_x11_kill;
@ -1733,6 +1886,7 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
window_class->is_stackable = meta_window_x11_is_stackable;
window_class->can_ping = meta_window_x11_can_ping;
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
window_class->has_pointer = meta_window_x11_has_pointer;
}
void
@ -3558,121 +3712,38 @@ meta_window_x11_set_allowed_actions_hint (MetaWindow *window)
#undef MAX_N_ACTIONS
}
void
meta_window_x11_create_sync_request_alarm (MetaWindow *window)
{
MetaX11Display *x11_display = window->display->x11_display;
XSyncAlarmAttributes values;
XSyncValue init;
if (window->sync_request_counter == None ||
window->sync_request_alarm != None)
return;
meta_x11_error_trap_push (x11_display);
/* In the new (extended style), the counter value is initialized by
* the client before mapping the window. In the old style, we're
* responsible for setting the initial value of the counter.
*/
if (window->extended_sync_request_counter)
{
if (!XSyncQueryCounter(x11_display->xdisplay,
window->sync_request_counter,
&init))
{
meta_x11_error_trap_pop_with_return (x11_display);
window->sync_request_counter = None;
return;
}
window->sync_request_serial =
XSyncValueLow32 (init) + ((gint64)XSyncValueHigh32 (init) << 32);
}
else
{
XSyncIntToValue (&init, 0);
XSyncSetCounter (x11_display->xdisplay,
window->sync_request_counter, init);
window->sync_request_serial = 0;
}
values.trigger.counter = window->sync_request_counter;
values.trigger.test_type = XSyncPositiveComparison;
/* Initialize to one greater than the current value */
values.trigger.value_type = XSyncRelative;
XSyncIntToValue (&values.trigger.wait_value, 1);
/* After triggering, increment test_value by this until
* until the test condition is false */
XSyncIntToValue (&values.delta, 1);
/* we want events (on by default anyway) */
values.events = True;
window->sync_request_alarm = XSyncCreateAlarm (x11_display->xdisplay,
XSyncCACounter |
XSyncCAValueType |
XSyncCAValue |
XSyncCATestType |
XSyncCADelta |
XSyncCAEvents,
&values);
if (meta_x11_error_trap_pop_with_return (x11_display) == Success)
meta_x11_display_register_sync_alarm (x11_display, &window->sync_request_alarm, window);
else
{
window->sync_request_alarm = None;
window->sync_request_counter = None;
}
}
void
meta_window_x11_destroy_sync_request_alarm (MetaWindow *window)
{
MetaX11Display *x11_display = window->display->x11_display;
if (window->sync_request_alarm != None)
{
/* Has to be unregistered _before_ clearing the structure field */
meta_x11_display_unregister_sync_alarm (x11_display, window->sync_request_alarm);
XSyncDestroyAlarm (x11_display->xdisplay,
window->sync_request_alarm);
window->sync_request_alarm = None;
}
}
void
meta_window_x11_update_sync_request_counter (MetaWindow *window,
gint64 new_counter_value)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
gboolean needs_frame_drawn = FALSE;
gboolean no_delay_frame = FALSE;
if (window->extended_sync_request_counter && new_counter_value % 2 == 0)
if (priv->extended_sync_request_counter && new_counter_value % 2 == 0)
{
needs_frame_drawn = TRUE;
no_delay_frame = new_counter_value == window->sync_request_serial + 1;
no_delay_frame = new_counter_value == priv->sync_request_serial + 1;
}
window->sync_request_serial = new_counter_value;
priv->sync_request_serial = new_counter_value;
meta_compositor_sync_updates_frozen (window->display->compositor, window);
if (window == window->display->grab_window &&
meta_grab_op_is_resizing (window->display->grab_op) &&
new_counter_value >= window->sync_request_wait_serial &&
(!window->extended_sync_request_counter || new_counter_value % 2 == 0) &&
window->sync_request_timeout_id)
new_counter_value >= priv->sync_request_wait_serial &&
(!priv->extended_sync_request_counter || new_counter_value % 2 == 0) &&
priv->sync_request_timeout_id)
{
meta_topic (META_DEBUG_RESIZING,
"Alarm event received last motion x = %d y = %d\n",
window->display->grab_latest_motion_x,
window->display->grab_latest_motion_y);
g_source_remove (window->sync_request_timeout_id);
window->sync_request_timeout_id = 0;
g_source_remove (priv->sync_request_timeout_id);
priv->sync_request_timeout_id = 0;
/* This means we are ready for another configure;
* no pointer round trip here, to keep in sync */
@ -3687,7 +3758,7 @@ meta_window_x11_update_sync_request_counter (MetaWindow *window,
* the application has come to its senses (maybe it was just
* busy with a pagefault or a long computation).
*/
window->disable_sync = FALSE;
priv->disable_sync = FALSE;
if (needs_frame_drawn)
meta_compositor_queue_frame_drawn (window->display->compositor, window,
@ -3699,3 +3770,86 @@ meta_window_x11_get_toplevel_xwindow (MetaWindow *window)
{
return window->frame ? window->frame->xwindow : window->xwindow;
}
int64_t
meta_window_x11_get_sync_request_serial (MetaWindowX11 *window_x11)
{
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
g_return_val_if_fail (META_IS_WINDOW_X11 (window_x11), -1);
return priv->sync_request_serial;
}
gboolean
meta_window_x11_has_sync_request_alarm (MetaWindowX11 *window_x11)
{
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
g_return_val_if_fail (META_IS_WINDOW_X11 (window_x11), FALSE);
return !priv->disable_sync &&
priv->sync_request_alarm != None;
}
gboolean
meta_window_x11_is_sync_request_scheduled (MetaWindowX11 *window_x11)
{
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
g_return_val_if_fail (META_IS_WINDOW_X11 (window_x11), FALSE);
return priv->sync_request_timeout_id != 0;
}
gboolean
meta_window_x11_has_extended_sync_request_counter (MetaWindowX11 *window_x11)
{
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
g_return_val_if_fail (META_IS_WINDOW_X11 (window_x11), FALSE);
return priv->extended_sync_request_counter;
}
void
meta_window_x11_setup_sync_request_counter (MetaWindowX11 *window_x11,
MetaPropValue *value)
{
MetaWindowX11Private *priv =
meta_window_x11_get_instance_private (window_x11);
MetaWindow *window = META_WINDOW (window_x11);
if (value->type == META_PROP_VALUE_INVALID)
return;
meta_window_x11_destroy_sync_request_alarm (window);
priv->sync_request_counter = None;
if (value->v.xcounter_list.n_counters == 0)
{
meta_warning ("_NET_WM_SYNC_REQUEST_COUNTER is empty\n");
return;
}
if (value->v.xcounter_list.n_counters == 1)
{
priv->sync_request_counter = value->v.xcounter_list.counters[0];
priv->extended_sync_request_counter = FALSE;
}
else
{
priv->sync_request_counter = value->v.xcounter_list.counters[1];
priv->extended_sync_request_counter = TRUE;
}
meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx (extended=%s)\n",
priv->sync_request_counter,
priv->extended_sync_request_counter ? "true" : "false");
if (priv->extended_sync_request_counter)
meta_window_x11_create_sync_request_alarm (window);
}

View File

@ -59,8 +59,6 @@ void meta_window_x11_set_wm_delete_window (MetaWindow *window,
gboolean delete_window);
void meta_window_x11_set_allowed_actions_hint (MetaWindow *window);
void meta_window_x11_create_sync_request_alarm (MetaWindow *window);
void meta_window_x11_destroy_sync_request_alarm (MetaWindow *window);
void meta_window_x11_update_sync_request_counter (MetaWindow *window,
gint64 new_counter_value);
@ -81,4 +79,10 @@ void meta_window_x11_configure_notify (MetaWindow *window,
Window meta_window_x11_get_toplevel_xwindow (MetaWindow *window);
int64_t meta_window_x11_get_sync_request_serial (MetaWindowX11 *window_x11);
gboolean meta_window_x11_is_sync_request_scheduled (MetaWindowX11 *window_x11);
gboolean meta_window_x11_has_sync_request_alarm (MetaWindowX11 *window_x11);
gboolean meta_window_x11_has_extended_sync_request_counter (MetaWindowX11 *window_x11);
#endif