if windows on screen are going to be moved, then do the ReplayPointer before that...
authorDana Jansens <danakj@orodu.net>
Sat, 2 Feb 2008 16:22:17 +0000 (11:22 -0500)
committerDana Jansens <danakj@orodu.net>
Sat, 2 Feb 2008 16:22:17 +0000 (11:22 -0500)
openbox/actions.c
openbox/actions.h
openbox/actions/desktop.c
openbox/mouse.c

index a236b58..b7ba5b4 100644 (file)
@@ -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)
     {
index 477e4ba..6db6f8d 100644 (file)
@@ -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,
index 6927525..d939ed5 100644 (file)
@@ -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;
 }
index 6661558..711317e 100644 (file)
@@ -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: