From 0d98c4fa7c29b9dec4da74380f4d0e695be53349 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 27 Apr 2010 18:45:22 -0400 Subject: [PATCH] fix XSYNCronization of resizes (especially with two monitors). 1) a ConfigureNotify must always follow a Sync notification 2) determine the final size of the window with its position else struts are not applied properly for (partly) maximized windows 3) set the sync counter to a value when managing a new window --- openbox/client.c | 10 +++++++++- openbox/event.c | 6 ++++++ openbox/moveresize.c | 45 +++++++++++++++++++++++++++----------------- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index 8acbf841..ae97606d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1551,7 +1551,13 @@ void client_update_sync_request_counter(ObClient *self) if (OBT_PROP_GET32(self->window, NET_WM_SYNC_REQUEST_COUNTER, CARDINAL,&i)) { + XSyncValue val; + self->sync_counter = i; + + /* this must be set when managing a new window according to EWMH */ + XSyncIntToValue(&val, 0); + XSyncSetCounter(obt_display, self->sync_counter, val); } else self->sync_counter = None; } @@ -3082,9 +3088,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, used to follow the same rules as above, but _Java_ Swing can't handle this. So just to appease Swing, when user = TRUE, we always send a synthetic ConfigureNotify to give the window its root coordinates. + Lastly, if force_reply is TRUE, we always send a + ConfigureNotify, which is needed during a resize with XSYNCronization. */ if ((!user && !resized && (rootmoved || force_reply)) || - (user && final && rootmoved)) + (user && ((!resized && force_reply) || (final && rootmoved)))) { XEvent event; diff --git a/openbox/event.c b/openbox/event.c index 9905d973..cfa3b4e3 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -1659,6 +1659,12 @@ static void event_handle_client(ObClient *client, XEvent *e) } #ifdef SYNC else if (msgtype == OBT_PROP_ATOM(NET_WM_SYNC_REQUEST_COUNTER)) { + /* if they are resizing right now this would cause weird behaviour. + if one day a user reports clients stop resizing, then handle + this better by resetting a new XSync alarm and stuff on the + new counter, but I expect it will never happen */ + if (moveresize_client == client) + moveresize_end(FALSE); client_update_sync_request_counter(client); } #endif diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 8ee88fcf..966ac742 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -41,6 +41,7 @@ /* how far windows move and resize with the keyboard arrows */ #define KEY_DIST 8 +#define SYNC_TIMEOUTS 4 gboolean moveresize_in_progress = FALSE; ObClient *moveresize_client = NULL; @@ -58,7 +59,7 @@ static ObDirection edge_warp_dir = -1; static gboolean edge_warp_odd = FALSE; static ObDirection key_resize_edge = -1; #ifdef SYNC -static gboolean waiting_for_sync; +static guint waiting_for_sync; #endif static ObPopup *popup = NULL; @@ -291,7 +292,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) XSyncCAEvents, &aa); - waiting_for_sync = FALSE; + waiting_for_sync = 0; } #endif } @@ -355,29 +356,34 @@ static void do_resize(void) { gint x, y, w, h, lw, lh; - /* see if it is actually going to resize */ - x = 0; - y = 0; + /* see if it is actually going to resize + USE cur_x AND cur_y HERE ! Otherwise the try_configure won't know + what struts to use !! + */ + x = cur_x; + y = cur_y; w = cur_w; h = cur_h; client_try_configure(moveresize_client, &x, &y, &w, &h, &lw, &lh, TRUE); if (!(w == moveresize_client->area.width && - h == moveresize_client->area.height)) + h == moveresize_client->area.height) && + /* if waiting_for_sync == 0, then we aren't waiting. + if it is > SYNC_TIMEOUTS, then we have timed out + that many times already, so forget about waiting more */ + (waiting_for_sync == 0 || waiting_for_sync > SYNC_TIMEOUTS)) { - #ifdef SYNC if (config_resize_redraw && obt_display_extension_sync && - moveresize_client->sync_request && moveresize_client->sync_counter && + /* don't send another sync when one is pending */ + waiting_for_sync == 0 && + moveresize_client->sync_request && + moveresize_client->sync_counter && !moveresize_client->not_responding) { 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); @@ -396,7 +402,7 @@ static void do_resize(void) XSendEvent(obt_display, moveresize_client->window, FALSE, NoEventMask, &ce); - waiting_for_sync = TRUE; + waiting_for_sync = 1; obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func); obt_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2, @@ -405,8 +411,10 @@ static void do_resize(void) } #endif + /* force a ConfigureNotify, it is part of the spec for SYNC resizing + and MUST follow the sync counter notification */ client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h, - TRUE, FALSE, FALSE); + TRUE, FALSE, TRUE); } /* this would be better with a fixed width font ... XXX can do it better @@ -421,10 +429,13 @@ static void do_resize(void) #ifdef SYNC static gboolean sync_timeout_func(gpointer data) { - waiting_for_sync = FALSE; /* we timed out waiting for our sync... */ + ++waiting_for_sync; /* we timed out waiting for our sync... */ do_resize(); /* ...so let any pending resizes through */ - return FALSE; /* don't repeat */ + if (waiting_for_sync > SYNC_TIMEOUTS) + return FALSE; /* don't repeat */ + else + return TRUE; /* keep waiting */ } #endif @@ -970,7 +981,7 @@ gboolean moveresize_event(XEvent *e) #ifdef SYNC else if (e->type == obt_display_extension_sync_basep + XSyncAlarmNotify) { - waiting_for_sync = FALSE; /* we got our sync... */ + waiting_for_sync = 0; /* we got our sync... */ do_resize(); /* ...so try resize if there is more change pending */ used = TRUE; } -- 2.45.2