summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openbox/actions.c20
-rw-r--r--openbox/actions.h11
-rw-r--r--openbox/actions/desktop.c2
-rw-r--r--openbox/mouse.c22
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: