From 746859c1017e9cdf73eb91470e795f0c4b98b21a Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 2 Feb 2008 11:22:17 -0500 Subject: [PATCH] if windows on screen are going to be moved, then do the ReplayPointer before that occurs, so it goes to the right window. if they are not, then just wait until after the actions are run (for kdesktop's sake really) --- openbox/actions.c | 20 +++++++++++++++++++- openbox/actions.h | 11 +++++++++-- openbox/actions/desktop.c | 2 ++ openbox/mouse.c | 22 ++++++++++++++++++---- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/openbox/actions.c b/openbox/actions.c index a236b581..b7ba5b44 100644 --- a/openbox/actions.c +++ b/openbox/actions.c @@ -23,6 +23,7 @@ #include "event.h" #include "config.h" #include "client.h" +#include "openbox.h" #include "debug.h" #include "actions/all.h" @@ -35,6 +36,7 @@ static ObActionsAct* actions_build_act_from_string(const gchar *name); static ObActionsAct *interactive_act = NULL; static guint interactive_initial_state = 0; +static gboolean replay_pointer = FALSE; struct _ObActionsDefinition { guint ref; @@ -222,6 +224,16 @@ static void actions_setup_data(ObActionsData *data, data->client = client; } +void actions_set_need_pointer_replay_before_move(gboolean replay) +{ + replay_pointer = replay; +} + +gboolean actions_get_need_pointer_replay_before_move() +{ + return replay_pointer; +} + void actions_run_acts(GSList *acts, ObUserAction uact, guint state, @@ -334,8 +346,14 @@ gboolean actions_interactive_input_event(XEvent *e) void actions_client_move(ObActionsData *data, gboolean start) { static gulong ignore_start = 0; - if (start) + if (start) { ignore_start = event_start_ignore_all_enters(); + if (replay_pointer) { + /* replay the pointer event before any windows move */ + XAllowEvents(ob_display, ReplayPointer, event_curtime); + replay_pointer = FALSE; + } + } else if (config_focus_follow && data->context != OB_FRAME_CONTEXT_CLIENT) { diff --git a/openbox/actions.h b/openbox/actions.h index 477e4ba1..6db6f8d6 100644 --- a/openbox/actions.h +++ b/openbox/actions.h @@ -74,9 +74,16 @@ gboolean actions_act_is_interactive(ObActionsAct *act); void actions_act_ref(ObActionsAct *act); void actions_act_unref(ObActionsAct *act); -/*! Pass in a GSList of ObActionsAct's to be run. - @return TRUE if an action is in interactive state, FALSE is none are +/*! When this is true, an XAllowEvents with ReplayPointer will be called + if an action is going to maybe try moving windows around on screen (or + map/unmap windows) */ +void actions_set_need_pointer_replay_before_move(gboolean replay); +/*! Returns if a ReplayPointer is still needed. If it was called while running + actions then this will be false */ +gboolean actions_get_need_pointer_replay_before_move(); + +/*! Pass in a GSList of ObActionsAct's to be run. */ void actions_run_acts(GSList *acts, ObUserAction uact, guint state, diff --git a/openbox/actions/desktop.c b/openbox/actions/desktop.c index 69275252..d939ed51 100644 --- a/openbox/actions/desktop.c +++ b/openbox/actions/desktop.c @@ -140,12 +140,14 @@ static gboolean run_func(ObActionsData *data, gpointer options) if (d < screen_num_desktops && d != screen_desktop) { gboolean go = TRUE; + actions_client_move(data, TRUE); if (o->send && data->client && client_normal(data->client)) { client_set_desktop(data->client, d, o->follow, FALSE); go = o->follow; } if (go) screen_set_desktop(d, TRUE); + actions_client_move(data, FALSE); } return FALSE; } diff --git a/openbox/mouse.c b/openbox/mouse.c index 66615585..711317ec 100644 --- a/openbox/mouse.c +++ b/openbox/mouse.c @@ -225,6 +225,17 @@ void mouse_event(ObClient *client, XEvent *e) button = e->xbutton.button; state = e->xbutton.state; + /* if the binding was in a client context, then we need to call + XAllowEvents with ReplayPointer at some point, to send the event + through to the client. when this happens though depends. if + windows are going to be moved on screen, then the click will end + up going somewhere wrong, so have the action system perform the + ReplayPointer for us if that is the case. */ + if (CLIENT_CONTEXT(context, client)) + actions_set_need_pointer_replay_before_move(TRUE); + else + actions_set_need_pointer_replay_before_move(FALSE); + fire_binding(OB_MOUSE_ACTION_PRESS, context, client, e->xbutton.state, e->xbutton.button, @@ -235,11 +246,14 @@ void mouse_event(ObClient *client, XEvent *e) if (grab_on_pointer()) button = 0; - if (CLIENT_CONTEXT(context, client)) { - /* Replay the event, so it goes to the client*/ + /* replay the pointer event if it hasn't been replayed yet (i.e. no + windows were moved) */ + if (actions_get_need_pointer_replay_before_move()) XAllowEvents(ob_display, ReplayPointer, event_curtime); - /* Fall through to the release case! */ - } else + + /* in the client context, we won't get a button release because of the + way it is grabbed, so just fake one */ + if (!CLIENT_CONTEXT(context, client)) break; case ButtonRelease: -- 2.44.0