]> Dogcows Code - chaz/openbox/blobdiff - plugins/mouse/mouse.c
add send-tos with the mouse wheel
[chaz/openbox] / plugins / mouse / mouse.c
index 5dd39db39d59597a02200e02ed929c06b92ec97e..6165744f0b1d299a882751b7cc7203eceb9c5eeb 100644 (file)
@@ -1,13 +1,22 @@
 #include "../../kernel/openbox.h"
 #include "../../kernel/dispatch.h"
 #include "../../kernel/action.h"
+#include "../../kernel/event.h"
 #include "../../kernel/client.h"
 #include "../../kernel/frame.h"
+#include "../../kernel/grab.h"
 #include "../../kernel/engine.h"
 #include "translate.h"
 #include "mouse.h"
+#include "mouserc_parse.h"
 #include <glib.h>
 
+void plugin_setup_config()
+{
+}
+
+static int drag_threshold = 3;
+
 /* GData of GSList*s of PointerBinding*s. */
 static GData *bound_contexts;
 
@@ -16,40 +25,33 @@ struct foreach_grab_temp {
     gboolean grab;
 };
 
-static void grab_button(Client *client, guint state, guint button,
-                       GQuark context, gboolean grab)
-{
-    Window win;
-    int mode = GrabModeAsync;
-    unsigned int mask;
-
-    if (context == g_quark_try_string("frame")) {
-       win = client->frame->window;
-       mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
-    } else if (context == g_quark_try_string("client")) {
-       win = client->frame->plate;
-       mode = GrabModeSync; /* this is handled in pointer_event */
-       mask = ButtonPressMask; /* can't catch more than this with Sync mode
-                                  the release event is manufactured in
-                                  pointer_fire */
-    } else return;
-
-    if (grab)
-        /* XXX grab all lock keys */
-       XGrabButton(ob_display, button, state, win, FALSE, mask, mode,
-                   GrabModeAsync, None, None);
-    else
-        /* XXX ungrab all lock keys */
-       XUngrabButton(ob_display, button, state, win);
-}
-
 static void foreach_grab(GQuark key, gpointer data, gpointer user_data)
 {
     struct foreach_grab_temp *d = user_data;
     GSList *it;
     for (it = data; it != NULL; it = it->next) {
+        /* grab/ungrab the button */
        MouseBinding *b = it->data;
-       grab_button(d->client, b->state, b->button, key, d->grab);
+        Window win;
+        int mode;
+        unsigned int mask;
+
+        if (key == g_quark_try_string("frame")) {
+            win = d->client->frame->window;
+            mode = GrabModeAsync;
+            mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
+        } else if (key == g_quark_try_string("client")) {
+            win = d->client->frame->plate;
+            mode = GrabModeSync; /* this is handled in event */
+            mask = ButtonPressMask; /* can't catch more than this with Sync
+                                       mode the release event is manufactured
+                                       in event */
+        } else return;
+
+        if (d->grab)
+            grab_button(b->button, b->state, win, mask, mode);
+        else
+            ungrab_button(b->button, b->state, win);
     }
 }
   
@@ -78,7 +80,8 @@ static void foreach_clear(GQuark key, gpointer data, gpointer user_data)
 
         MouseBinding *b = it->data;
        for (i = 0; i < NUM_MOUSEACTION; ++i)
-            action_free(b->action[i]);
+            if (b->action[i] != NULL)
+                action_free(b->action[i]);
         g_free(b);
     }
     g_slist_free(data);
@@ -184,6 +187,7 @@ static void event(ObEvent *e, void *foo)
     static Corner corner = Corner_TopLeft;
     gboolean click = FALSE;
     gboolean dclick = FALSE;
+    GQuark context;
 
     switch (e->type) {
     case Event_Client_Mapped:
@@ -196,9 +200,7 @@ static void event(ObEvent *e, void *foo)
 
     case Event_X_ButtonPress:
         if (!button) {
-            if (e->data.x.client == NULL)
-                corner = Corner_TopLeft;
-            else {
+            if (e->data.x.client != NULL) {
                 cx = e->data.x.client->frame->area.x;
                 cy = e->data.x.client->frame->area.y;
                 cw = e->data.x.client->frame->area.width;
@@ -206,79 +208,87 @@ static void event(ObEvent *e, void *foo)
                 px = e->data.x.e->xbutton.x_root;
                 py = e->data.x.e->xbutton.y_root;
                 corner = pick_corner(px, py, cx, cy, cw, ch);
-                button = e->data.x.e->xbutton.button;
             }
+            button = e->data.x.e->xbutton.button;
         }
-        fire_button(MouseAction_Press,
-                    engine_get_context(e->data.x.client,
-                                       e->data.x.e->xbutton.window),
+        context = engine_get_context(e->data.x.client,
+                                     e->data.x.e->xbutton.window);
+
+        fire_button(MouseAction_Press, context,
                     e->data.x.client, e->data.x.e->xbutton.state,
                     e->data.x.e->xbutton.button);
-        break;
+
+        if (context == g_quark_try_string("client")) {
+            /* Replay the event, so it goes to the client*/
+            XAllowEvents(ob_display, ReplayPointer, event_lasttime);
+            /* Fall through to the release case! */
+        } else
+            break;
 
     case Event_X_ButtonRelease:
+        context = engine_get_context(e->data.x.client,
+                                     e->data.x.e->xbutton.window);
         if (e->data.x.e->xbutton.button == button) {
             /* end drags */
             if (drag) {
-                fire_motion(MouseAction_Motion,
-                            engine_get_context(e->data.x.client,
-                                               e->data.x.e->xbutton.window),
+                fire_motion(MouseAction_Motion, context,
                             e->data.x.client, e->data.x.e->xbutton.state,
                             e->data.x.e->xbutton.button,
                             cx, cy, cw, ch, dx, dy, TRUE, corner);
-            }
-
-            /* clicks are only valid if its released over the window */
-           if (e->data.x.e->xbutton.x >= 0 && e->data.x.e->xbutton.y >= 0) {
-               int junk;
-               Window wjunk;
-               guint ujunk, w, h;
-               XGetGeometry(ob_display, e->data.x.e->xbutton.window,
-                             &wjunk, &junk, &junk, &w, &h, &ujunk, &ujunk);
-               if (e->data.x.e->xbutton.x < (signed)w &&
-                    e->data.x.e->xbutton.y < (signed)h) {
-                   click =TRUE;
-                    /* double clicks happen if there were 2 in a row! */
-                    if (lbutton == button &&
-                        e->data.x.e->xbutton.time - 300 <= ltime)
-                        dclick = TRUE;
-                }
-                lbutton = button;
-           } else
+                drag = FALSE;
+                
                 lbutton = 0;
+            } else {
+                /* clicks are only valid if its released over the window */
+                if (e->data.x.e->xbutton.x >= 0 &&
+                    e->data.x.e->xbutton.y >= 0) {
+                    int junk;
+                    Window wjunk;
+                    guint ujunk, w, h;
+                    XGetGeometry(ob_display, e->data.x.e->xbutton.window,
+                                 &wjunk, &junk, &junk, &w, &h, &ujunk, &ujunk);
+                    if (e->data.x.e->xbutton.x < (signed)w &&
+                        e->data.x.e->xbutton.y < (signed)h) {
+                        click =TRUE;
+                        /* double clicks happen if there were 2 in a row! */
+                        if (lbutton == button &&
+                            e->data.x.e->xbutton.time - 300 <= ltime)
+                            dclick = TRUE;
+                    }
+                    lbutton = button;
+                } else
+                    lbutton = 0;
+            }
 
             button = 0;
             ltime = e->data.x.e->xbutton.time;
         }
-        fire_button(MouseAction_Press,
-                    engine_get_context(e->data.x.client,
-                                       e->data.x.e->xbutton.window),
+        fire_button(MouseAction_Press, context,
                     e->data.x.client, e->data.x.e->xbutton.state,
                     e->data.x.e->xbutton.button);
         if (click)
-            fire_button(MouseAction_Click,
-                        engine_get_context(e->data.x.client,
-                                           e->data.x.e->xbutton.window),
+            fire_button(MouseAction_Click, context,
                         e->data.x.client, e->data.x.e->xbutton.state,
                         e->data.x.e->xbutton.button);
         if (dclick)
-            fire_button(MouseAction_DClick,
-                        engine_get_context(e->data.x.client,
-                                           e->data.x.e->xbutton.window),
+            fire_button(MouseAction_DClick, context,
                         e->data.x.client, e->data.x.e->xbutton.state,
                         e->data.x.e->xbutton.button);
         break;
 
     case Event_X_MotionNotify:
         if (button) {
-            drag = TRUE;
             dx = e->data.x.e->xmotion.x_root - px;
             dy = e->data.x.e->xmotion.y_root - py;
-            fire_motion(MouseAction_Motion,
-                        engine_get_context(e->data.x.client,
-                                           e->data.x.e->xbutton.window),
-                        e->data.x.client, e->data.x.e->xmotion.state,
-                        button, cx, cy, cw, ch, dx, dy, FALSE, corner);
+            if (ABS(dx) >= drag_threshold || ABS(dy) >= drag_threshold)
+                drag = TRUE;
+            if (drag) {
+                context = engine_get_context(e->data.x.client,
+                                             e->data.x.e->xbutton.window);
+                fire_motion(MouseAction_Motion, context,
+                            e->data.x.client, e->data.x.e->xmotion.state,
+                            button, cx, cy, cw, ch, dx, dy, FALSE, corner);
+            }
         }
         break;
 
@@ -287,25 +297,27 @@ static void event(ObEvent *e, void *foo)
     }
 }
 
-static gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
-                      Action *action)
+gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
+               Action *action)
 {
     guint state, button;
     GQuark context;
     MouseBinding *b;
     GSList *it;
-    guint i;
 
     if (!translate_button(buttonstr, &state, &button)) {
-        g_warning("invalid button");
+        g_warning("invalid button '%s'", buttonstr);
         return FALSE;
     }
 
+    contextstr = g_ascii_strdown(contextstr, -1);
     context = g_quark_try_string(contextstr);
     if (!context) {
-        g_warning("invalid context");
+        g_warning("invalid context '%s'", contextstr);
+        g_free(contextstr);
         return FALSE;
     }
+    g_free(contextstr);
 
     for (it = g_datalist_id_get_data(&bound_contexts, context);
         it != NULL; it = it->next){
@@ -324,12 +336,9 @@ static gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
     grab_all_clients(FALSE);
 
     /* add the binding */
-    b = g_new(MouseBinding, 1);
+    b = g_new0(MouseBinding, 1);
     b->state = state;
     b->button = button;
-    for (i = 0; i < NUM_MOUSEACTION; ++i)
-        if (i != mact)
-            b->action[i] = NULL;
     b->action[mact] = action;
     g_datalist_id_set_data(&bound_contexts, context, 
         g_slist_append(g_datalist_id_get_data(&bound_contexts, context), b));
@@ -339,41 +348,13 @@ static gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
     return TRUE;
 }
 
-static void binddef()
-{
-    Action *a;
-
-    /* When creating an Action struct, all of the data elements in the
-       appropriate struct need to be set, except the Client*, which will be set
-       at call-time when then action function is used.
-
-       For action_move and action_resize, the 'x', 'y', and 'final' data
-       elements should not be set, as they are set at call-time.       
-    */
-
-    a = action_new(action_move);
-    mbind("1", "titlebar", MouseAction_Motion, a);
-    a = action_new(action_move);
-    mbind("1", "handle", MouseAction_Motion, a);
-    a = action_new(action_move);
-    mbind("A-1", "frame", MouseAction_Motion, a);
-
-    a = action_new(action_resize);
-    mbind("1", "blcorner", MouseAction_Motion, a);
-    a = action_new(action_resize);
-    mbind("1", "brcorner", MouseAction_Motion, a);
-    a = action_new(action_resize);
-    mbind("A-3", "frame", MouseAction_Motion, a);
-}
-
 void plugin_startup()
 {
     dispatch_register(Event_Client_Mapped | Event_Client_Destroy |
                       Event_X_ButtonPress | Event_X_ButtonRelease |
                       Event_X_MotionNotify, (EventHandler)event, NULL);
 
-    /* XXX parse a config */
-    binddef();
+    mouserc_parse();
 }
 
 void plugin_shutdown()
This page took 0.029296 seconds and 4 git commands to generate.