From ad852b6b56e43bdd7dda1389f54051cf92c0fad9 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 24 Apr 2007 06:30:16 +0000 Subject: [PATCH] add support for _NET_WM_SYNC_REQUEST --- openbox/client.c | 35 +++++++++-- openbox/client.h | 13 ++++ openbox/event.c | 28 +++++++++ openbox/extensions.c | 13 ++++ openbox/extensions.h | 8 +++ openbox/moveresize.c | 147 ++++++++++++++++++++++++++++++++++++++----- openbox/moveresize.h | 7 +++ openbox/prop.c | 6 +- openbox/prop.h | 6 +- openbox/screen.c | 10 ++- 10 files changed, 247 insertions(+), 26 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index 4dad9882..5eeda998 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -940,6 +940,9 @@ static void client_get_all(ObClient *self) (min/max sizes), so we're ready to set up the decorations/functions */ client_setup_decor_and_functions(self); +#ifdef SYNC + client_update_sync_request_counter(self); +#endif client_get_client_machine(self); client_get_colormap(self); client_update_title(self); @@ -1291,18 +1294,37 @@ void client_update_protocols(ObClient *self) if (PROP_GETA32(self->window, wm_protocols, atom, &proto, &num_return)) { for (i = 0; i < num_return; ++i) { - if (proto[i] == prop_atoms.wm_delete_window) { + if (proto[i] == prop_atoms.wm_delete_window) /* this means we can request the window to close */ self->delete_window = TRUE; - } else if (proto[i] == prop_atoms.wm_take_focus) + else if (proto[i] == prop_atoms.wm_take_focus) /* if this protocol is requested, then the window will be notified whenever we want it to receive focus */ self->focus_notify = TRUE; +#ifdef SYNC + else if (proto[i] == prop_atoms.net_wm_sync_request) + /* if this protocol is requested, then the resizing the + window will be synchronized between the frame and the + client */ + self->sync_request = TRUE; +#endif } g_free(proto); } } +#ifdef SYNC +void client_update_sync_request_counter(ObClient *self) +{ + guint32 i; + + if (PROP_GET32(self->window, net_wm_sync_request_counter, cardinal, &i)) { + self->sync_counter = i; + } else + self->sync_counter = None; +} +#endif + static void client_get_gravity(ObClient *self) { XWindowAttributes wattrib; @@ -3097,10 +3119,11 @@ void client_activate(ObClient *self, gboolean here, gboolean user) to activate it or not (a parent or group member is currently active)? */ - ob_debug("Want to activate window 0x%x with time %u (last time %u), " - "source=%s\n", - self->window, event_curtime, last_time, - (user ? "user" : "application")); + ob_debug_type(OB_DEBUG_FOCUS, + "Want to activate window 0x%x with time %u (last time %u), " + "source=%s\n", + self->window, event_curtime, last_time, + (user ? "user" : "application")); if (!user && event_curtime && last_time && !event_time_after(event_curtime, last_time)) diff --git a/openbox/client.h b/openbox/client.h index e9a13041..69f5aa5f 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -219,6 +219,15 @@ struct _ObClient /*! Notify the window when it receives focus? */ gboolean focus_notify; +#ifdef SYNC + /*! The client wants to sync during resizes */ + gboolean sync_request; + /*! The XSync counter used for synchronizing during resizes */ + guint32 sync_counter; + /*! The value we're waiting for the counter to reach */ + gulong sync_counter_value; +#endif + /*! The window uses shape extension to be non-rectangular? */ gboolean shaped; @@ -546,6 +555,10 @@ void client_update_transient_for(ObClient *self); /*! Update the protocols that the window supports and adjusts things if they change */ void client_update_protocols(ObClient *self); +#ifdef SYNC +/*! Updates the window's sync request counter for resizes */ +void client_update_sync_request_counter(ObClient *self); +#endif /*! Updates the window's colormap */ void client_update_colormap(ObClient *self, Colormap colormap); /*! Updates the WMNormalHints and adjusts things if they change */ diff --git a/openbox/event.c b/openbox/event.c index 5a2fe05b..2d807aae 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -211,6 +211,13 @@ static Window event_get_window(XEvent *e) window = None; } } else +#endif +#ifdef SYNC + if (extensions_sync && + e->type == extensions_sync_event_basep + XSyncAlarmNotify) + { + window = None; + } else #endif window = e->xany.window; } @@ -244,6 +251,13 @@ static void event_set_curtime(XEvent *e) t = e->xcrossing.time; break; default: +#ifdef SYNC + if (extensions_sync && + e->type == extensions_sync_event_basep + XSyncAlarmNotify) + { + t = ((XSyncAlarmNotifyEvent*)e)->time; + } +#endif /* if more event types are anticipated, get their timestamp explicitly */ break; @@ -537,6 +551,15 @@ static void event_process(const XEvent *ec, gpointer data) e->xconfigurerequest.value_mask, &xwc); xerror_set_ignore(FALSE); } +#ifdef SYNC + else if (extensions_sync && + e->type == extensions_sync_event_basep + XSyncAlarmNotify) + { + XSyncAlarmNotifyEvent *se = (XSyncAlarmNotifyEvent*)e; + if (se->alarm == moveresize_alarm && moveresize_in_progress) + moveresize_event(e); + } +#endif /* user input (action-bound) events */ if (e->type == ButtonPress || e->type == ButtonRelease || @@ -1172,6 +1195,11 @@ static void event_handle_client(ObClient *client, XEvent *e) else if (msgtype == prop_atoms.net_wm_user_time) { client_update_user_time(client); } +#ifdef SYNC + else if (msgtype == prop_atoms.net_wm_sync_request_counter) { + client_update_sync_request_counter(client); + } +#endif else if (msgtype == prop_atoms.sm_client_id) { client_update_sm_client_id(client); } diff --git a/openbox/extensions.c b/openbox/extensions.c index 967424f4..5b64bc64 100644 --- a/openbox/extensions.c +++ b/openbox/extensions.c @@ -21,6 +21,7 @@ #include "geom.h" #include "extensions.h" #include "screen.h" +#include "debug.h" gboolean extensions_xkb = FALSE; gint extensions_xkb_event_basep; @@ -30,6 +31,8 @@ gboolean extensions_xinerama = FALSE; gint extensions_xinerama_event_basep; gboolean extensions_randr = FALSE; gint extensions_randr_event_basep; +gboolean extensions_sync = FALSE; +gint extensions_sync_event_basep; void extensions_query_all() { @@ -59,6 +62,16 @@ void extensions_query_all() XRRQueryExtension(ob_display, &extensions_randr_event_basep, &junk); #endif + +#ifdef SYNC + extensions_sync = + XSyncQueryExtension(ob_display, &extensions_sync_event_basep, + &junk) && + XSyncInitialize(ob_display, &junk, &junk); + if (!extensions_sync) + ob_debug("X Sync extension is not present on the server or is an " + "incompatible version"); +#endif } void extensions_xinerama_screens(Rect **xin_areas, guint *nxin) diff --git a/openbox/extensions.h b/openbox/extensions.h index c6771067..3fbac871 100644 --- a/openbox/extensions.h +++ b/openbox/extensions.h @@ -36,6 +36,9 @@ #ifdef XRANDR #include #endif +#ifdef SYNC +#include +#endif #include @@ -59,6 +62,11 @@ extern gboolean extensions_randr; /*! Base for events for the Randr extension */ extern gint extensions_randr_event_basep; +/*! Does the display have the Sync extension? */ +extern gboolean extensions_sync; +/*! Base for events for the Sync extension */ +extern gint extensions_sync_event_basep; + void extensions_query_all(); void extensions_xinerama_screens(Rect **areas, guint *nxin); diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 1033d6b0..39fdd45d 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -28,6 +28,9 @@ #include "popup.h" #include "moveresize.h" #include "config.h" +#include "event.h" +#include "debug.h" +#include "extensions.h" #include "render/render.h" #include "render/theme.h" @@ -36,6 +39,9 @@ gboolean moveresize_in_progress = FALSE; ObClient *moveresize_client = NULL; +#ifdef SYNC +XSyncAlarm moveresize_alarm = None; +#endif static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */ @@ -44,6 +50,9 @@ static gint cur_x, cur_y; static guint button; static guint32 corner; static ObCorner lockcorner; +#ifdef SYNC +static gboolean waiting_for_sync; +#endif static ObPopup *popup = NULL; @@ -164,6 +173,47 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) else g_assert_not_reached(); +#ifdef SYNC + if (!moving && extensions_shape && moveresize_client->sync_request && + moveresize_client->sync_counter) + { + /* Initialize values for the resize syncing, and create an alarm for + the client's xsync counter */ + + XSyncValue val; + XSyncAlarmAttributes aa; + + /* set the counter to an initial value */ + XSyncIntToValue(&val, 0); + XSyncSetCounter(ob_display, moveresize_client->sync_counter, val); + + /* this will be incremented when we tell the client what we're + looking for */ + moveresize_client->sync_counter_value = 0; + + /* the next sequence we're waiting for with the alarm */ + XSyncIntToValue(&val, 1); + + /* set an alarm on the counter */ + aa.trigger.counter = moveresize_client->sync_counter; + aa.trigger.wait_value = val; + aa.trigger.value_type = XSyncAbsolute; + aa.trigger.test_type = XSyncPositiveTransition; + aa.events = True; + XSyncIntToValue(&aa.delta, 1); + moveresize_alarm = XSyncCreateAlarm(ob_display, + XSyncCACounter | + XSyncCAValue | + XSyncCAValueType | + XSyncCATestType | + XSyncCADelta | + XSyncCAEvents, + &aa); + + waiting_for_sync = FALSE; + } +#endif + grab_pointer(TRUE, FALSE, cur); grab_keyboard(TRUE); } @@ -180,6 +230,14 @@ void moveresize_end(gboolean cancel) (cancel ? start_cx : cur_x), (cancel ? start_cy : cur_y)); } else { +#ifdef SYNC + /* turn off the alarm */ + if (moveresize_alarm != None) { + XSyncDestroyAlarm(ob_display, moveresize_alarm); + moveresize_alarm = None; + } +#endif + client_configure(moveresize_client, lockcorner, moveresize_client->area.x, moveresize_client->area.y, @@ -209,24 +267,56 @@ static void do_move(gboolean resist) moveresize_client->frame->area.y); } -static void do_resize(gboolean resist) +static void do_resize() { - /* resist_size_* needs the frame size */ - cur_x += moveresize_client->frame->size.left + - moveresize_client->frame->size.right; - cur_y += moveresize_client->frame->size.top + - moveresize_client->frame->size.bottom; +#ifdef SYNC + gint x, y, w, h, lw, lh; + + /* see if it is actually going to resize */ + x = moveresize_client->area.x; + y = moveresize_client->area.y; + w = cur_x; + h = cur_y; + client_try_configure(moveresize_client, lockcorner, &x, &y, &w, &h, + &lw, &lh, TRUE); + if (w == moveresize_client->area.width && + h == moveresize_client->area.height) + { + return; + } - if (resist) { - resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner); - resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner); + if (extensions_sync && moveresize_client->sync_request && + moveresize_client->sync_counter) + { + XEvent ce; + XSyncValue val; + + /* are we already waiting for the sync counter to catch up? */ + if (waiting_for_sync) + return; + + /* increment the value we're waiting for */ + ++moveresize_client->sync_counter_value; + XSyncIntToValue(&val, moveresize_client->sync_counter_value); + + /* tell the client what we're waiting for */ + ce.xclient.type = ClientMessage; + ce.xclient.message_type = prop_atoms.wm_protocols; + ce.xclient.display = ob_display; + ce.xclient.window = moveresize_client->window; + ce.xclient.format = 32; + ce.xclient.data.l[0] = prop_atoms.net_wm_sync_request; + ce.xclient.data.l[1] = event_curtime; + ce.xclient.data.l[2] = XSyncValueLow32(val); + ce.xclient.data.l[3] = XSyncValueHigh32(val); + ce.xclient.data.l[4] = 0l; + XSendEvent(ob_display, moveresize_client->window, FALSE, + NoEventMask, &ce); + + waiting_for_sync = TRUE; } +#endif - cur_x -= moveresize_client->frame->size.left + - moveresize_client->frame->size.right; - cur_y -= moveresize_client->frame->size.top + - moveresize_client->frame->size.bottom; - client_configure(moveresize_client, lockcorner, moveresize_client->area.x, moveresize_client->area.y, cur_x, cur_y, TRUE, FALSE); @@ -243,6 +333,25 @@ static void do_resize(gboolean resist) moveresize_client->logical_size.height); } +static void calc_resize(gboolean resist) +{ + /* resist_size_* needs the frame size */ + cur_x += moveresize_client->frame->size.left + + moveresize_client->frame->size.right; + cur_y += moveresize_client->frame->size.top + + moveresize_client->frame->size.bottom; + + if (resist) { + resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner); + resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner); + } + + cur_x -= moveresize_client->frame->size.left + + moveresize_client->frame->size.right; + cur_y -= moveresize_client->frame->size.top + + moveresize_client->frame->size.bottom; +} + void moveresize_event(XEvent *e) { g_assert(moveresize_in_progress); @@ -304,7 +413,8 @@ void moveresize_event(XEvent *e) } else g_assert_not_reached(); - do_resize(TRUE); + calc_resize(TRUE); + do_resize(); } } else if (e->type == KeyPress) { if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) @@ -382,4 +492,11 @@ void moveresize_event(XEvent *e) } } } +#ifdef SYNC + else if (e->type == extensions_sync_event_basep + XSyncAlarmNotify) + { + waiting_for_sync = FALSE; /* we got our sync... */ + do_resize(); /* ...so try resize if there is more change pending */ + } +#endif } diff --git a/openbox/moveresize.h b/openbox/moveresize.h index 5a099567..410b5544 100644 --- a/openbox/moveresize.h +++ b/openbox/moveresize.h @@ -21,10 +21,17 @@ #include +#ifdef SYNC +#include +#endif + struct _ObClient; extern gboolean moveresize_in_progress; extern struct _ObClient *moveresize_client; +#ifdef SYNC +extern XSyncAlarm moveresize_alarm; +#endif void moveresize_startup(gboolean reconfig); void moveresize_shutdown(gboolean reconfig); diff --git a/openbox/prop.c b/openbox/prop.c index f0cca6c0..49eeef9e 100644 --- a/openbox/prop.c +++ b/openbox/prop.c @@ -91,7 +91,11 @@ void prop_startup() CREATE(net_frame_extents, "_NET_FRAME_EXTENTS"); /* CREATE(net_wm_ping, "_NET_WM_PING"); */ - +#ifdef SYNC + CREATE(net_wm_sync_request, "_NET_WM_SYNC_REQUEST"); + CREATE(net_wm_sync_request_counter, "_NET_WM_SYNC_REQUEST_COUNTER"); +#endif + CREATE(net_wm_window_type_desktop, "_NET_WM_WINDOW_TYPE_DESKTOP"); CREATE(net_wm_window_type_dock, "_NET_WM_WINDOW_TYPE_DOCK"); CREATE(net_wm_window_type_toolbar, "_NET_WM_WINDOW_TYPE_TOOLBAR"); diff --git a/openbox/prop.h b/openbox/prop.h index 1d3445f8..09ca25ce 100644 --- a/openbox/prop.h +++ b/openbox/prop.h @@ -99,7 +99,11 @@ typedef struct Atoms { Atom net_frame_extents; /* application protocols */ -/* Atom Atom net_wm_ping; */ +/* Atom net_wm_ping; */ +#ifdef SYNC + Atom net_wm_sync_request; + Atom net_wm_sync_request_counter; +#endif Atom net_wm_window_type_desktop; Atom net_wm_window_type_dock; diff --git a/openbox/screen.c b/openbox/screen.c index 587dc647..71748d65 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -206,6 +206,9 @@ gboolean screen_annex() /* set the _NET_SUPPORTED_ATOMS hint */ num_support = 55; +#ifdef SYNC + num_support += 2; +#endif i = 0; supported = g_new(gulong, num_support); supported[i++] = prop_atoms.net_wm_full_placement; @@ -262,11 +265,12 @@ gboolean screen_annex() supported[i++] = prop_atoms.net_wm_moveresize; supported[i++] = prop_atoms.net_wm_user_time; supported[i++] = prop_atoms.net_frame_extents; +#ifdef SYNC + supported[i++] = prop_atoms.net_wm_sync_request; + supported[i++] = prop_atoms.net_wm_sync_request_counter; +#endif supported[i++] = prop_atoms.ob_wm_state_undecorated; g_assert(i == num_support); -/* - supported[] = prop_atoms.net_wm_action_stick; -*/ PROP_SETA32(RootWindow(ob_display, ob_screen), net_supported, atom, supported, num_support); -- 2.44.0