]> Dogcows Code - chaz/openbox/commitdiff
move the keyboard and mouse plugins into the kernel for mucho sexiness.
authorDana Jansens <danakj@orodu.net>
Tue, 12 Aug 2003 07:26:16 +0000 (07:26 +0000)
committerDana Jansens <danakj@orodu.net>
Tue, 12 Aug 2003 07:26:16 +0000 (07:26 +0000)
make workspace changing a grabbed/interactive process like focus cycling is, with the popup and all.
this is some hot shit.

29 files changed:
ChangeLog
Makefile.am
openbox/.cvsignore
openbox/action.c
openbox/action.h
openbox/client.c
openbox/config.c
openbox/config.h
openbox/event.c
openbox/focus.c
openbox/keyboard.c [new file with mode: 0644]
openbox/keyboard.h [new file with mode: 0644]
openbox/keytree.c [new file with mode: 0644]
openbox/keytree.h [new file with mode: 0644]
openbox/menu.c
openbox/menu.h
openbox/mouse.c [moved from plugins/mouse/mouse.c with 50% similarity]
openbox/mouse.h [new file with mode: 0644]
openbox/openbox.c
openbox/plugin.c
openbox/screen.c
openbox/screen.h
openbox/translate.c [moved from plugins/mouse/translate.c with 67% similarity]
openbox/translate.h [new file with mode: 0644]
plugins/menu/client_menu.c
plugins/mouse/.cvsignore [deleted file]
plugins/mouse/Makefile [deleted file]
plugins/mouse/mouse.h [deleted file]
plugins/mouse/translate.h [deleted file]

index 703f5ff4c60159d7159b32962d5e1732076da91b..c4b7c2ba277ec3fbf422cf94629c9042d2e7c9c9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+2003-08-12  xor@zed.orodu.net  <xor@zed>
+
+       * kernel/event.c:
+       keep event_lasttime at the last time an event has come in so far, don't regress when events come out of order. props to shrimpx for this patch.
+
+2003-08-11  woodblock  <woodblock@zed>
+
+       * kernel/menu.c, kernel/menu.h, kernel/menu_render.c, plugins/menu/fifo_menu.c, plugins/menu/timed_menu.c, render/theme.c, render/theme.h:
+       Some fixes and new bugs. Someone else can do the menus because it is
+       clear no one gives a fuck what I think and no one else wants a window
+       manager that doesn't suck the same balls as every other window manager.
+
+2003-08-10  xor@zed.orodu.net  <xor@zed>
+
+       * kernel/client.c:
+       save the frame decorations in client_configure_full before causing the fake frame adjust, since that loses its old value.
+
+2003-08-10  xor@zed.orodu.net  <xor@zed>
+
+       * framerender.c:
+       clear the window after setting the background color, this isnt implicit
+
+2003-08-09  xor@zed.orodu.net  <xor@zed>
+
+       * focus.c, popup.c, popup.h, screen.c, timer.c, timer.h:
+       changes to the timer api, pass the timer to the callback function.
+       add a desktop-switch popup with the desktop's name
+
+2003-08-07  woodblock  <woodblock@zed>
+
+       * event.c:
+       Fix lock up when not using a session manager and doing fd management.
+
+2003-08-05  xor@zed.orodu.net  <xor@zed>
+
+       * screen.c: dont ignore topleft layouts
+
+       * frame.c:
+       dont map the tl/tr invisible grips when the grip decors are turned off
+
+       * client.c, frame.c, frame.h, framerender.c:
+       a couple frame layout bugfixes hidden inside all this.. wee
+       fixes for maximizing windows:
+        - when you toggledecor, it will reconfigure once, but the new constraints from the decor changes would not be in effect when the window was resized to the contranits. fixed by calling frame_adjust_area first thing ni client_configure_fulll with fake=TRUE which will recalc all the frame geometry without resizing/redrawing anything in the frame. this way the decor can take effect in the geometries.
+        - when maxed horizontally, make the client fill the screen, but dont do this by just making it wider than the screen, fit it to the screen and adjust the titlebar/handle as appropriate to keep it all on the screen.
+        - when maxed horizontally and vertically, remove the handle from the decorations
+
+       * client.c:
+       when setting up decor on a window, it needs to reconfigure twice if the decor changes, cuz the constraints need the new frame sizes to work right
+
+       * moveresize.c:
+       make the position dislpayed in the moving popup offset by the top/left struts so that 0,0 is inside teh struts not neccessarily at the screen edge
+
+2003-08-03  xor@zed.orodu.net  <xor@zed>
+
+       * client.c, config.c, config.h, moveresize.c:
+       kill non-opaque move/resize
+       add an option for redrawing/resizing the client window while resizing, when disabled the client is not touched until the resize is complete.
+
+       * framerender.c: give the plate the same background color as its border
+
 2003-08-03  xor@zed.orodu.net  <xor@zed>
 
        * data/rc3, kernel/client.c, kernel/config.c, kernel/config.h, kernel/moveresize.c:
index 3cca337e11aa95be76e598331e1e5dfdaa78d533..cb82d10f9c523865e1e2d4ca631ebdd263f250b0 100644 (file)
@@ -28,8 +28,6 @@ bin_PROGRAMS = \
 plugin_LTLIBRARIES = \
        plugins/resistance/resistance.la \
        plugins/placement/placement.la \
-       plugins/mouse/mouse.la \
-       plugins/keyboard/keyboard.la \
        plugins/menu/timed_menu.la \
        plugins/menu/fifo_menu.la \
        plugins/menu/client_menu.la \
@@ -157,10 +155,16 @@ kernel_openbox_SOURCES = \
        kernel/grab.h \
        kernel/group.c \
        kernel/group.h \
+       kernel/keyboard.c \
+       kernel/keyboard.h \
+       kernel/keytree.c \
+       kernel/keytree.h \
        kernel/menu.c \
        kernel/menu.h \
        kernel/menu_render.c \
        kernel/misc.h \
+       kernel/mouse.c \
+       kernel/mouse.h \
        kernel/moveresize.c \
        kernel/moveresize.h \
        kernel/mwm.h \
@@ -182,6 +186,8 @@ kernel_openbox_SOURCES = \
        kernel/startup.h \
        kernel/timer.c \
        kernel/timer.h \
+       kernel/translate.c \
+       kernel/translate.h \
        kernel/window.c \
        kernel/window.h \
        kernel/xerror.c \
@@ -238,44 +244,6 @@ plugins_placement_placement_la_SOURCES = \
        plugins/placement/history.c \
        plugins/placement/history.h
 
-## plugins/mouse ##
-
-plugins_mouse_mouse_la_CPPFLAGS = \
-       $(XFT_CFLAGS) \
-       $(GLIB_CFLAGS) \
-       $(LIBSN_CFLAGS) \
-       $(XML_CFLAGS) \
-       -DPLUGINDIR=\"$(plugindir)\" \
-       -DG_LOG_DOMAIN=\"Plugin-Mouse\"
-plugins_mouse_mouse_la_LDFLAGS = \
-       -module \
-       -avoid-version
-plugins_mouse_mouse_la_SOURCES = \
-       plugins/mouse/mouse.c \
-       plugins/mouse/mouse.h \
-       plugins/mouse/translate.c \
-       plugins/mouse/translate.h
-
-## plugins/mouse ##
-
-plugins_keyboard_keyboard_la_CPPFLAGS = \
-       $(XFT_CFLAGS) \
-       $(GLIB_CFLAGS) \
-       $(LIBSN_CFLAGS) \
-       $(XML_CFLAGS) \
-       -DPLUGINDIR=\"$(plugindir)\" \
-       -DG_LOG_DOMAIN=\"Plugin-Keyboard\"
-plugins_keyboard_keyboard_la_LDFLAGS = \
-       -module \
-       -avoid-version
-plugins_keyboard_keyboard_la_SOURCES = \
-       plugins/keyboard/keyboard.c \
-       plugins/keyboard/keyboard.h \
-       plugins/keyboard/tree.c \
-       plugins/keyboard/tree.h \
-       plugins/keyboard/translate.c \
-       plugins/keyboard/translate.h
-
 ## plugins/menu ##
 
 plugins_menu_timed_menu_la_CPPFLAGS = \
index e982b46214fdf12bd743b4bd8c6dc4c0794afb07..ab5b29ab83dd4d5eb87b15e0033a4ebca44e0e3f 100644 (file)
@@ -29,3 +29,6 @@ xerror.lo
 .deps
 openbox
 .dirstamp
+keyboard.lo
+mouse.lo
+keytree.lo
index d59c55143a6e85435ca455c3861cee56d9489150..275ba96a42c1088cb5db8499e875786080be1866 100644 (file)
 typedef struct ActionString {
     char *name;
     void (*func)(union ActionData *);
-    void (*setup)(Action *);
+    void (*setup)(ObAction *);
 } ActionString;
 
-Action *action_new(void (*func)(union ActionData *data))
+ObAction *action_new(void (*func)(union ActionData *data))
 {
-    Action *a = g_new0(Action, 1);
+    ObAction *a = g_new0(ObAction, 1);
     a->func = func;
 
     return a;
 }
 
-void action_free(Action *a)
+void action_free(ObAction *a)
 {
     if (a == NULL) return;
 
@@ -40,137 +40,209 @@ void action_free(Action *a)
     g_free(a);
 }
 
-void setup_action_directional_focus_north(Action *a)
+void setup_action_directional_focus_north(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_NORTH;
 }
 
-void setup_action_directional_focus_east(Action *a)
+void setup_action_directional_focus_east(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_EAST;
 }
 
-void setup_action_directional_focus_south(Action *a)
+void setup_action_directional_focus_south(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_SOUTH;
 }
 
-void setup_action_directional_focus_west(Action *a)
+void setup_action_directional_focus_west(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_WEST;
 }
 
-void setup_action_directional_focus_northeast(Action *a)
+void setup_action_directional_focus_northeast(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_NORTHEAST;
 }
 
-void setup_action_directional_focus_southeast(Action *a)
+void setup_action_directional_focus_southeast(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_SOUTHEAST;
 }
 
-void setup_action_directional_focus_southwest(Action *a)
+void setup_action_directional_focus_southwest(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_SOUTHWEST;
 }
 
-void setup_action_directional_focus_northwest(Action *a)
+void setup_action_directional_focus_northwest(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_NORTHWEST;
 }
 
-void setup_action_send_to_desktop(Action *a)
+void setup_action_send_to_desktop(ObAction *a)
 {
-    a->data.sendto.follow = TRUE;
 }
 
-void setup_action_send_to_desktop_direction(Action *a)
+void setup_action_send_to_desktop_prev(ObAction *a)
 {
+    a->data.sendtodir.dir = OB_DIRECTION_WEST;
+    a->data.sendtodir.linear = TRUE;
     a->data.sendtodir.wrap = TRUE;
-    a->data.sendtodir.follow = TRUE;
 }
 
-void setup_action_desktop_direction(Action *a)
+void setup_action_send_to_desktop_next(ObAction *a)
 {
+    a->data.sendtodir.dir = OB_DIRECTION_EAST;
+    a->data.sendtodir.linear = TRUE;
+    a->data.sendtodir.wrap = TRUE;
+}
+
+void setup_action_send_to_desktop_left(ObAction *a)
+{
+    a->data.sendtodir.dir = OB_DIRECTION_WEST;
+    a->data.sendtodir.linear = FALSE;
+    a->data.sendtodir.wrap = TRUE;
+}
+
+void setup_action_send_to_desktop_right(ObAction *a)
+{
+    a->data.sendtodir.dir = OB_DIRECTION_EAST;
+    a->data.sendtodir.linear = FALSE;
+    a->data.sendtodir.wrap = TRUE;
+}
+
+void setup_action_send_to_desktop_up(ObAction *a)
+{
+    a->data.sendtodir.dir = OB_DIRECTION_NORTH;
+    a->data.sendtodir.linear = FALSE;
+    a->data.sendtodir.wrap = TRUE;
+}
+
+void setup_action_send_to_desktop_down(ObAction *a)
+{
+    a->data.sendtodir.dir = OB_DIRECTION_SOUTH;
+    a->data.sendtodir.linear = FALSE;
+    a->data.sendtodir.wrap = TRUE;
+}
+
+void setup_action_desktop_prev(ObAction *a)
+{
+    a->data.desktopdir.dir = OB_DIRECTION_WEST;
+    a->data.desktopdir.linear = TRUE;
+    a->data.desktopdir.wrap = TRUE;
+}
+
+void setup_action_desktop_next(ObAction *a)
+{
+    a->data.desktopdir.dir = OB_DIRECTION_EAST;
+    a->data.desktopdir.linear = TRUE;
+    a->data.desktopdir.wrap = TRUE;
+}
+
+void setup_action_desktop_left(ObAction *a)
+{
+    a->data.desktopdir.dir = OB_DIRECTION_WEST;
+    a->data.desktopdir.linear = FALSE;
+    a->data.desktopdir.wrap = TRUE;
+}
+
+void setup_action_desktop_right(ObAction *a)
+{
+    a->data.desktopdir.dir = OB_DIRECTION_EAST;
+    a->data.desktopdir.linear = FALSE;
+    a->data.desktopdir.wrap = TRUE;
+}
+
+void setup_action_desktop_up(ObAction *a)
+{
+    a->data.desktopdir.dir = OB_DIRECTION_NORTH;
+    a->data.desktopdir.linear = FALSE;
     a->data.desktopdir.wrap = TRUE;
 }
 
-void setup_action_move_keyboard(Action *a)
+void setup_action_desktop_down(ObAction *a)
+{
+    a->data.desktopdir.dir = OB_DIRECTION_SOUTH;
+    a->data.desktopdir.linear = FALSE;
+    a->data.desktopdir.wrap = TRUE;
+}
+
+void setup_action_move_keyboard(ObAction *a)
 {
     a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard;
 }
 
-void setup_action_move(Action *a)
+void setup_action_move(ObAction *a)
 {
     a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move;
 }
 
-void setup_action_resize(Action *a)
+void setup_action_resize(ObAction *a)
 {
     a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft;
 }
 
-void setup_action_resize_keyboard(Action *a)
+void setup_action_resize_keyboard(ObAction *a)
 {
     a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard;
 }
 
-void setup_action_cycle_windows_linear_next(Action *a)
+void setup_action_cycle_windows_linear_next(ObAction *a)
 {
     a->data.cycle.linear = TRUE;
     a->data.cycle.forward = TRUE;
 }
 
-void setup_action_cycle_windows_linear_previous(Action *a)
+void setup_action_cycle_windows_linear_previous(ObAction *a)
 {
     a->data.cycle.linear = TRUE;
     a->data.cycle.forward = FALSE;
 }
 
-void setup_action_cycle_windows_next(Action *a)
+void setup_action_cycle_windows_next(ObAction *a)
 {
     a->data.cycle.linear = FALSE;
     a->data.cycle.forward = TRUE;
 }
 
-void setup_action_cycle_windows_previous(Action *a)
+void setup_action_cycle_windows_previous(ObAction *a)
 {
     a->data.cycle.linear = FALSE;
     a->data.cycle.forward = FALSE;
 }
 
-void setup_action_movetoedge_north(Action *a)
+void setup_action_movetoedge_north(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_NORTH;
 }
 
-void setup_action_movetoedge_south(Action *a)
+void setup_action_movetoedge_south(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_SOUTH;
 }
 
-void setup_action_movetoedge_east(Action *a)
+void setup_action_movetoedge_east(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_EAST;
 }
 
-void setup_action_movetoedge_west(Action *a)
+void setup_action_movetoedge_west(ObAction *a)
 {
     a->data.diraction.direction = OB_DIRECTION_WEST;
 }
 
-void setup_action_top_layer(Action *a)
+void setup_action_top_layer(ObAction *a)
 {
     a->data.layer.layer = 1;
 }
 
-void setup_action_normal_layer(Action *a)
+void setup_action_normal_layer(ObAction *a)
 {
     a->data.layer.layer = 0;
 }
 
-void setup_action_bottom_layer(Action *a)
+void setup_action_bottom_layer(ObAction *a)
 {
     a->data.layer.layer = -1;
 }
@@ -357,50 +429,70 @@ ActionString actionstrings[] =
         action_send_to_desktop,
         setup_action_send_to_desktop
     },
+    {
+        "sendtodesktopnext",
+        action_send_to_desktop_dir,
+        setup_action_send_to_desktop_next
+    },
+    {
+        "sendtodesktopprevious",
+        action_send_to_desktop_dir,
+        setup_action_send_to_desktop_prev
+    },
     {
         "sendtodesktopright",
-        action_send_to_desktop_right,
-        setup_action_send_to_desktop_direction
+        action_send_to_desktop_dir,
+        setup_action_send_to_desktop_right
     },
     {
         "sendtodesktopleft",
-        action_send_to_desktop_left,
-        setup_action_send_to_desktop_direction
+        action_send_to_desktop_dir,
+        setup_action_send_to_desktop_left
     },
     {
         "sendtodesktopup",
-        action_send_to_desktop_up,
-        setup_action_send_to_desktop_direction
+        action_send_to_desktop_dir,
+        setup_action_send_to_desktop_up
     },
     {
         "sendtodesktopdown",
-        action_send_to_desktop_down,
-        setup_action_send_to_desktop_direction
+        action_send_to_desktop_dir,
+        setup_action_send_to_desktop_down
     },
     {
         "desktop",
         action_desktop,
         NULL
     },
+    {
+        "desktopnext",
+        action_desktop_dir,
+        setup_action_desktop_next
+    },
+    {
+        "desktopprevious",
+        action_desktop_dir,
+        setup_action_desktop_prev
+    },
     {
         "desktopright",
-        action_desktop_right,
-        setup_action_desktop_direction
+        action_desktop_dir,
+        setup_action_desktop_right
     },
     {
         "desktopleft",
-        action_desktop_left,
-        setup_action_desktop_direction
+        action_desktop_dir,
+        setup_action_desktop_left
     },
     {
         "desktopup",
-        action_desktop_up,
-        setup_action_desktop_direction
+        action_desktop_dir,
+        setup_action_desktop_up
     },
     {
         "desktopdown",
-        action_desktop_down,
-        setup_action_desktop_direction
+        action_desktop_dir,
+        setup_action_desktop_down
     },
     {
         "toggledecorations",
@@ -529,9 +621,9 @@ ActionString actionstrings[] =
     }
 };
 
-Action *action_from_string(char *name)
+ObAction *action_from_string(char *name)
 {
-    Action *a = NULL;
+    ObAction *a = NULL;
     int i;
 
     for (i = 0; actionstrings[i].name; i++)
@@ -544,10 +636,10 @@ Action *action_from_string(char *name)
     return a;
 }
 
-Action *action_parse(xmlDocPtr doc, xmlNodePtr node)
+ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node)
 {
     char *actname;
-    Action *act = NULL;
+    ObAction *act = NULL;
     xmlNodePtr n;
 
     if (parse_attr_string("name", node, &actname)) {
@@ -572,21 +664,13 @@ Action *action_parse(xmlDocPtr doc, xmlNodePtr node)
                        act->func == action_resize_relative_vert) {
                 if ((n = parse_find_node("delta", node->xmlChildrenNode)))
                     act->data.relative.delta = parse_int(doc, n);
-            } else if (act->func == action_desktop_right ||
-                       act->func == action_desktop_left ||
-                       act->func == action_desktop_up ||
-                       act->func == action_desktop_down) {
+            } else if (act->func == action_desktop_dir) {
                 if ((n = parse_find_node("wrap", node->xmlChildrenNode))) {
                     act->data.desktopdir.wrap = parse_bool(doc, n);
                 }
-            } else if (act->func == action_send_to_desktop_right ||
-                       act->func == action_send_to_desktop_left ||
-                       act->func == action_send_to_desktop_up ||
-                       act->func == action_send_to_desktop_down) {
+            } else if (act->func == action_send_to_desktop_dir) {
                 if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
                     act->data.sendtodir.wrap = parse_bool(doc, n);
-                if ((n = parse_find_node("follow", node->xmlChildrenNode)))
-                    act->data.sendtodir.follow = parse_bool(doc, n);
             }
         }
         g_free(actname);
@@ -802,8 +886,8 @@ void action_send_to_desktop(union ActionData *data)
 
     if (data->sendto.desk < screen_num_desktops ||
         data->sendto.desk == DESKTOP_ALL) {
-        client_set_desktop(c, data->sendto.desk, data->sendto.follow);
-        if (data->sendto.follow) screen_set_desktop(data->sendto.desk);
+        client_set_desktop(c, data->sendto.desk, TRUE);
+        screen_set_desktop(data->sendto.desk);
     }
 }
 
@@ -814,114 +898,34 @@ void action_desktop(union ActionData *data)
         screen_set_desktop(data->desktop.desk);
 }
 
-static void cur_row_col(guint *r, guint *c)
+void action_desktop_dir(union ActionData *data)
 {
-    switch (screen_desktop_layout.orientation) {
-    case OB_ORIENTATION_HORZ:
-        switch (screen_desktop_layout.start_corner) {
-        case OB_CORNER_TOPLEFT:
-            *r = screen_desktop / screen_desktop_layout.columns;
-            *c = screen_desktop % screen_desktop_layout.columns;
-            break;
-        case OB_CORNER_BOTTOMLEFT:
-            *r = screen_desktop_layout.rows - 1 -
-                screen_desktop / screen_desktop_layout.columns;
-            *c = screen_desktop % screen_desktop_layout.columns;
-            break;
-        case OB_CORNER_TOPRIGHT:
-            *r = screen_desktop / screen_desktop_layout.columns;
-            *c = screen_desktop_layout.columns - 1 -
-                screen_desktop % screen_desktop_layout.columns;
-            break;
-        case OB_CORNER_BOTTOMRIGHT:
-            *r = screen_desktop_layout.rows - 1 -
-                screen_desktop / screen_desktop_layout.columns;
-            *c = screen_desktop_layout.columns - 1 -
-                screen_desktop % screen_desktop_layout.columns;
-            break;
-        }
-        break;
-    case OB_ORIENTATION_VERT:
-        switch (screen_desktop_layout.start_corner) {
-        case OB_CORNER_TOPLEFT:
-            *r = screen_desktop % screen_desktop_layout.rows;
-            *c = screen_desktop / screen_desktop_layout.rows;
-            break;
-        case OB_CORNER_BOTTOMLEFT:
-            *r = screen_desktop_layout.rows - 1 -
-                screen_desktop % screen_desktop_layout.rows;
-            *c = screen_desktop / screen_desktop_layout.rows;
-            break;
-        case OB_CORNER_TOPRIGHT:
-            *r = screen_desktop % screen_desktop_layout.rows;
-            *c = screen_desktop_layout.columns - 1 -
-                screen_desktop / screen_desktop_layout.rows;
-            break;
-        case OB_CORNER_BOTTOMRIGHT:
-            *r = screen_desktop_layout.rows - 1 -
-                screen_desktop % screen_desktop_layout.rows;
-            *c = screen_desktop_layout.columns - 1 -
-                screen_desktop / screen_desktop_layout.rows;
-            break;
-        }
-        break;
-    }
+    guint d;
+
+    d = screen_cycle_desktop(data->desktopdir.dir, data->desktopdir.wrap,
+                             data->sendtodir.linear,
+                             data->desktopdir.final, data->desktopdir.cancel);
+    screen_set_desktop(d);
 }
 
-static guint translate_row_col(guint r, guint c)
-{
-    switch (screen_desktop_layout.orientation) {
-    case OB_ORIENTATION_HORZ:
-        switch (screen_desktop_layout.start_corner) {
-        case OB_CORNER_TOPLEFT:
-            return r % screen_desktop_layout.rows *
-                screen_desktop_layout.columns +
-                c % screen_desktop_layout.columns;
-        case OB_CORNER_BOTTOMLEFT:
-            return (screen_desktop_layout.rows - 1 -
-                    r % screen_desktop_layout.rows) *
-                screen_desktop_layout.columns +
-                c % screen_desktop_layout.columns;
-        case OB_CORNER_TOPRIGHT:
-            return r % screen_desktop_layout.rows *
-                screen_desktop_layout.columns +
-                (screen_desktop_layout.columns - 1 -
-                 c % screen_desktop_layout.columns);
-        case OB_CORNER_BOTTOMRIGHT:
-            return (screen_desktop_layout.rows - 1 -
-                    r % screen_desktop_layout.rows) *
-                screen_desktop_layout.columns +
-                (screen_desktop_layout.columns - 1 -
-                 c % screen_desktop_layout.columns);
-        }
-    case OB_ORIENTATION_VERT:
-        switch (screen_desktop_layout.start_corner) {
-        case OB_CORNER_TOPLEFT:
-            return c % screen_desktop_layout.columns *
-                screen_desktop_layout.rows +
-                r % screen_desktop_layout.rows;
-        case OB_CORNER_BOTTOMLEFT:
-            return c % screen_desktop_layout.columns *
-                screen_desktop_layout.rows +
-                (screen_desktop_layout.rows - 1 -
-                 r % screen_desktop_layout.rows);
-        case OB_CORNER_TOPRIGHT:
-            return (screen_desktop_layout.columns - 1 -
-                    c % screen_desktop_layout.columns) *
-                screen_desktop_layout.rows +
-                r % screen_desktop_layout.rows;
-        case OB_CORNER_BOTTOMRIGHT:
-            return (screen_desktop_layout.columns - 1 -
-                    c % screen_desktop_layout.columns) *
-                screen_desktop_layout.rows +
-                (screen_desktop_layout.rows - 1 -
-                 r % screen_desktop_layout.rows);
-        }
-    }
-    g_assert_not_reached();
-    return 0;
+void action_send_to_desktop_dir(union ActionData *data)
+{
+    ObClient *c = data->sendtodir.c;
+    guint d;
+
+    if (!c || !client_normal(c)) return;
+
+    d = screen_cycle_desktop(data->sendtodir.dir, data->sendtodir.wrap,
+                             data->sendtodir.linear,
+                             data->sendtodir.final, data->sendtodir.cancel);
+
+    g_message("sendto %d", d);
+
+    client_set_desktop(c, d, TRUE);
+    screen_set_desktop(d);
 }
 
+#if 0
 void action_desktop_right(union ActionData *data)
 {
     guint r, c, d;
@@ -939,7 +943,8 @@ void action_desktop_right(union ActionData *data)
     }
     d = translate_row_col(r, c);
     if (d < screen_num_desktops)
-        screen_set_desktop(d);
+        screen_cycle_desktop(d, data->desktopdir.final,
+                             data->desktopdir.cancel);
 }
 
 void action_send_to_desktop_right(union ActionData *data)
@@ -963,7 +968,9 @@ void action_send_to_desktop_right(union ActionData *data)
     d = translate_row_col(r, c);
     if (d < screen_num_desktops) {
         client_set_desktop(cl, d, data->sendtodir.follow);
-        if (data->sendtodir.follow) screen_set_desktop(d);
+        if (data->sendtodir.follow)
+            screen_cycle_desktop(d, data->desktopdir.final,
+                                 data->desktopdir.cancel);
     }
 }
 
@@ -984,7 +991,8 @@ void action_desktop_left(union ActionData *data)
     }
     d = translate_row_col(r, c);
     if (d < screen_num_desktops)
-        screen_set_desktop(d);
+        screen_cycle_desktop(d, data->desktopdir.final,
+                             data->desktopdir.cancel);
 }
 
 void action_send_to_desktop_left(union ActionData *data)
@@ -1008,7 +1016,9 @@ void action_send_to_desktop_left(union ActionData *data)
     d = translate_row_col(r, c);
     if (d < screen_num_desktops) {
         client_set_desktop(cl, d, data->sendtodir.follow);
-        if (data->sendtodir.follow) screen_set_desktop(d);
+        if (data->sendtodir.follow)
+            screen_cycle_desktop(d, data->desktopdir.final,
+                                 data->desktopdir.cancel);
     }
 }
 
@@ -1029,7 +1039,8 @@ void action_desktop_down(union ActionData *data)
     }
     d = translate_row_col(r, c);
     if (d < screen_num_desktops)
-        screen_set_desktop(d);
+        screen_cycle_desktop(d, data->desktopdir.final,
+                             data->desktopdir.cancel);
 }
 
 void action_send_to_desktop_down(union ActionData *data)
@@ -1051,7 +1062,9 @@ void action_send_to_desktop_down(union ActionData *data)
         d = translate_row_col(r, c);
         if (d < screen_num_desktops) {
             client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
-            if (data->sendtodir.follow) screen_set_desktop(d);
+            if (data->sendtodir.follow)
+                screen_cycle_desktop(d, data->desktopdir.final,
+                                     data->desktopdir.cancel);
         }
     }
 }
@@ -1073,7 +1086,8 @@ void action_desktop_up(union ActionData *data)
     }
     d = translate_row_col(r, c);
     if (d < screen_num_desktops)
-        screen_set_desktop(d);
+        screen_cycle_desktop(d, data->desktopdir.final,
+                             data->desktopdir.cancel);
 }
 
 void action_send_to_desktop_up(union ActionData *data)
@@ -1095,10 +1109,13 @@ void action_send_to_desktop_up(union ActionData *data)
         d = translate_row_col(r, c);
         if (d < screen_num_desktops) {
             client_set_desktop(data->sendtodir.c, d, data->sendtodir.follow);
-            if (data->sendtodir.follow) screen_set_desktop(d);
+            if (data->sendtodir.follow)
+                screen_cycle_desktop(d, data->desktopdir.final,
+                                     data->desktopdir.cancel);
         }
     }
 }
+#endif
 
 void action_toggle_decorations(union ActionData *data)
 {
index 3abf7f2bf1fa786e96d708c39ff79d9974c691fe..3ac3ee6761c96b15993a1931d462cacb80051441 100644 (file)
@@ -4,6 +4,8 @@
 #include "misc.h"
 #include "parser/parse.h"
 
+typedef struct _ObAction ObAction;
+
 /* These have to all have a Client* at the top even if they don't use it, so
    that I can set it blindly later on. So every function will have a Client*
    available (possibly NULL though) if it wants it.
@@ -40,8 +42,11 @@ struct SendToDesktop {
 
 struct SendToDesktopDirection {
     struct _ObClient *c;
+    ObDirection dir;
     gboolean wrap;
-    gboolean follow;
+    gboolean linear;
+    gboolean final;
+    gboolean cancel;
 };
 
 struct Desktop {
@@ -56,7 +61,11 @@ struct Layer {
 
 struct DesktopDirection {
     struct _ObClient *c;
+    ObDirection dir;
     gboolean wrap;
+    gboolean linear;
+    gboolean final;
+    gboolean cancel;
 };
 
 struct MoveResize {
@@ -98,15 +107,15 @@ union ActionData {
     struct Layer layer;
 };
 
-typedef struct {
+struct _ObAction {
     /* The func member acts like an enum to tell which one of the structs in
        the data union are valid.
     */
     void (*func)(union ActionData *data);
     union ActionData data;
-} Action;
+};
 
-Action *action_new(void (*func)(union ActionData *data));
+ObAction *action_new(void (*func)(union ActionData *data));
 
 /* Creates a new Action from the name of the action
    A few action types need data set after making this call still. Check if
@@ -120,9 +129,9 @@ Action *action_new(void (*func)(union ActionData *data));
    action_resize_relative_vert - the delta
 */
 
-Action *action_from_string(char *name);
-Action *action_parse(xmlDocPtr doc, xmlNodePtr node);
-void action_free(Action *a);
+ObAction *action_from_string(char *name);
+ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node);
+void action_free(ObAction *a);
 
 /* Execute */
 void action_execute(union ActionData *data);
@@ -181,23 +190,11 @@ void action_toggle_maximize_vert(union ActionData *data);
 /* SendToDesktop */
 void action_send_to_desktop(union ActionData *data);
 /* SendToDesktopDirection */
-void action_send_to_desktop_right(union ActionData *data);
-/* SendToDesktopDirection */
-void action_send_to_desktop_left(union ActionData *data);
-/* SendToDesktopDirection */
-void action_send_to_desktop_up(union ActionData *data);
-/* SendToDesktopDirection */
-void action_send_to_desktop_down(union ActionData *data);
+void action_send_to_desktop_dir(union ActionData *data);
 /* Desktop */
 void action_desktop(union ActionData *data);
 /* DesktopDirection */
-void action_desktop_right(union ActionData *data);
-/* DesktopDirection */
-void action_desktop_left(union ActionData *data);
-/* DesktopDirection */
-void action_desktop_up(union ActionData *data);
-/* DesktopDirection */
-void action_desktop_down(union ActionData *data);
+void action_desktop_dir(union ActionData *data);
 /* ClientAction */
 void action_toggle_decorations(union ActionData *data);
 /* MoveResize */
index 191fa9943331ac148f61659861e090f9272f77d1..b5e2a3cfdf6472e12214cafc57057dd9eb906e72 100644 (file)
@@ -18,6 +18,8 @@
 #include "group.h"
 #include "config.h"
 #include "menu.h"
+#include "keyboard.h"
+#include "mouse.h"
 #include "render/render.h"
 
 #include <glib.h>
@@ -327,6 +329,9 @@ void client_manage(Window window)
     /* update the list hints */
     client_set_list();
 
+    keyboard_grab_for_client(self, TRUE);
+    mouse_grab_for_client(self, TRUE);
+
     dispatch_client(Event_Client_Mapped, self, 0, 0);
 
     ob_debug("Managed window 0x%lx (%s)\n", window, self->class);
@@ -355,6 +360,9 @@ void client_unmanage(ObClient *self)
     dispatch_client(Event_Client_Destroy, self, 0, 0);
     g_assert(self != NULL);
 
+    keyboard_grab_for_client(self, FALSE);
+    mouse_grab_for_client(self, FALSE);
+
     /* remove the window from our save set */
     XChangeSaveSet(ob_display, self->window, SetModeDelete);
 
@@ -1097,7 +1105,7 @@ void client_setup_decor_and_functions(ObClient *self)
     /* finally, the user can have requested no decorations, which overrides
        everything */
     if (!self->decorate)
-        self->decorations = 0;
+        self->decorations = OB_FRAME_DECOR_BORDER;
 
     /* if we don't have a titlebar, then we cannot shade! */
     if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
@@ -1705,7 +1713,7 @@ void client_configure_full(ObClient *self, ObCorner anchor,
                            gboolean force_reply)
 {
     gboolean moved = FALSE, resized = FALSE;
-    gint fdecor = self->frame->decorations;
+    guint fdecor = self->frame->decorations;
 
     /* make the frame recalculate its dimentions n shit without changing
        anything visible for real, this way the constraints below can work with
index 1ffc155a86c05dedb2399374c2aa0354aaef78fb..5444e013a500b20b7fb15cdcdf378ec3da0520a1 100644 (file)
@@ -1,4 +1,7 @@
 #include "config.h"
+#include "keyboard.h"
+#include "mouse.h"
+#include "prop.h"
 #include "parser/parse.h"
 
 gboolean config_focus_new;
@@ -25,6 +28,151 @@ ObOrientation   config_dock_orient;
 gboolean        config_dock_hide;
 guint           config_dock_hide_timeout;
 
+gint config_mouse_threshold;
+gint config_mouse_dclicktime;
+
+/*
+
+<keybind key="C-x">
+  <action name="ChangeDesktop">
+    <desktop>3</desktop>
+  </action>
+</keybind>
+
+*/
+
+static void parse_key(xmlDocPtr doc, xmlNodePtr node, GList *keylist)
+{
+    char *key;
+    ObAction *action;
+    xmlNodePtr n, nact;
+    GList *it;
+
+    n = parse_find_node("keybind", node);
+    while (n) {
+        if (parse_attr_string("key", n, &key)) {
+            keylist = g_list_append(keylist, key);
+
+            parse_key(doc, n->xmlChildrenNode, keylist);
+
+            it = g_list_last(keylist);
+            g_free(it->data);
+            keylist = g_list_delete_link(keylist, it);
+        }
+        n = parse_find_node("keybind", n->next);
+    }
+    if (keylist) {
+        nact = parse_find_node("action", node);
+        while (nact) {
+            if ((action = action_parse(doc, nact))) {
+                /* validate that its okay for a key binding */
+                if (action->func == action_moveresize &&
+                    action->data.moveresize.corner !=
+                    prop_atoms.net_wm_moveresize_move_keyboard &&
+                    action->data.moveresize.corner !=
+                    prop_atoms.net_wm_moveresize_size_keyboard) {
+                    action_free(action);
+                    action = NULL;
+                }
+
+                if (action)
+                    keyboard_bind(keylist, action);
+            }
+            nact = parse_find_node("action", nact->next);
+        }
+    }
+}
+
+static void parse_keyboard(xmlDocPtr doc, xmlNodePtr node, void *d)
+{
+    parse_key(doc, node->xmlChildrenNode, NULL);
+}
+
+static int threshold;
+static int dclicktime;
+/*
+
+<context name="Titlebar"> 
+  <mousebind button="Left" action="Press">
+    <action name="Raise"></action>
+  </mousebind>
+</context>
+
+*/
+
+static void parse_mouse(xmlDocPtr doc, xmlNodePtr node, void *d)
+{
+    xmlNodePtr n, nbut, nact;
+    char *buttonstr;
+    char *contextstr;
+    ObMouseAction mact;
+    ObAction *action;
+
+    node = node->xmlChildrenNode;
+    
+    if ((n = parse_find_node("dragThreshold", node)))
+        threshold = parse_int(doc, n);
+    if ((n = parse_find_node("doubleClickTime", node)))
+        dclicktime = parse_int(doc, n);
+
+    n = parse_find_node("context", node);
+    while (n) {
+        if (!parse_attr_string("name", n, &contextstr))
+            goto next_n;
+        nbut = parse_find_node("mousebind", n->xmlChildrenNode);
+        while (nbut) {
+            if (!parse_attr_string("button", nbut, &buttonstr))
+                goto next_nbut;
+            if (parse_attr_contains("press", nbut, "action"))
+                mact = MouseAction_Press;
+            else if (parse_attr_contains("release", nbut, "action"))
+                mact = MouseAction_Release;
+            else if (parse_attr_contains("click", nbut, "action"))
+                mact = MouseAction_Click;
+            else if (parse_attr_contains("doubleclick", nbut,"action"))
+                mact = MouseAction_DClick;
+            else if (parse_attr_contains("drag", nbut, "action"))
+                mact = MouseAction_Motion;
+            else
+                goto next_nbut;
+            nact = parse_find_node("action", nbut->xmlChildrenNode);
+            while (nact) {
+                if ((action = action_parse(doc, nact))) {
+                    /* validate that its okay for a mouse binding*/
+                    if (mact == MouseAction_Motion) {
+                        if (action->func != action_moveresize ||
+                            action->data.moveresize.corner ==
+                            prop_atoms.net_wm_moveresize_move_keyboard ||
+                            action->data.moveresize.corner ==
+                            prop_atoms.net_wm_moveresize_size_keyboard) {
+                            action_free(action);
+                            action = NULL;
+                        }
+                    } else {
+                        if (action->func == action_moveresize &&
+                            action->data.moveresize.corner !=
+                            prop_atoms.net_wm_moveresize_move_keyboard &&
+                            action->data.moveresize.corner !=
+                            prop_atoms.net_wm_moveresize_size_keyboard) {
+                            action_free(action);
+                            action = NULL;
+                        }
+                    }
+                    if (action)
+                        mouse_bind(buttonstr, contextstr, mact, action);
+                }
+                nact = parse_find_node("action", nact->next);
+            }
+            g_free(buttonstr);
+        next_nbut:
+            nbut = parse_find_node("mousebind", nbut->next);
+        }
+        g_free(contextstr);
+    next_n:
+        n = parse_find_node("context", n->next);
+    }
+}
+
 static void parse_focus(xmlDocPtr doc, xmlNodePtr node, void *d)
 {
     xmlNodePtr n;
@@ -190,6 +338,13 @@ void config_startup()
     config_dock_hide_timeout = 3000;
 
     parse_register("dock", parse_dock, NULL);
+
+    parse_register("keyboard", parse_keyboard, NULL);
+
+    config_mouse_threshold = 3;
+    config_mouse_dclicktime = 200;
+
+    parse_register("mouse", parse_mouse, NULL);
 }
 
 void config_shutdown()
index d10617d018eaf58f48c09ee535711473617787d2..413ff184408c0e081912e902c906311482a670dc 100644 (file)
@@ -52,6 +52,11 @@ extern int config_desktops_num;
 /*! Names for the desktops */
 extern GSList *config_desktops_names;
 
+/*! Number of pixels a drag must go before being considered a drag */
+extern gint config_mouse_threshold;
+/*! Number of milliseconds within which 2 clicks must occur to be a
+  double-click */
+extern gint config_mouse_dclicktime;
 
 void config_startup();
 void config_shutdown();
index b5e15a3c894fdaf6cdf8ec392040e671bdbd98fc..97f01fb6f3d305424c055a21c196ac75d022761c 100644 (file)
@@ -8,6 +8,8 @@
 #include "screen.h"
 #include "frame.h"
 #include "menu.h"
+#include "keyboard.h"
+#include "mouse.h"
 #include "framerender.h"
 #include "focus.h"
 #include "moveresize.h"
@@ -541,13 +543,23 @@ static void event_process(XEvent *e)
         }
 
     /* user input (action-bound) events */
-    /*
     if (e->type == ButtonPress || e->type == ButtonRelease ||
-        e->type == MotionNotify)
-        mouse_event(e, client);
-    else if (e->type == KeyPress || e->type == KeyRelease)
-        ;
-    */
+        e->type == MotionNotify || e->type == KeyPress ||
+        e->type == KeyRelease)
+    {
+        ObFrameContext context;
+
+        context = frame_context(client, e->xany.window);
+
+        if (!keyboard_process_interactive_grab(e, &client, &context)) {
+
+            if (e->type == ButtonPress || e->type == ButtonRelease ||
+                e->type == MotionNotify)
+                mouse_event(client, context, e);
+            else if (e->type == KeyPress)
+                keyboard_event(client, e);
+        }
+    }
 
     /* dispatch the event to registered handlers */
     dispatch_x(e, client);
index 1642261dac685967365b8aaf3889c79980498436..9949dea3a68fb337ad79a025e75b5985450d45ed 100644 (file)
@@ -262,7 +262,7 @@ static void popup_cycle(ObClient *c, gboolean show)
 }
 
 ObClient *focus_cycle(gboolean forward, gboolean linear, gboolean done,
-                    gboolean cancel)
+                      gboolean cancel)
 {
     static ObClient *first = NULL;
     static ObClient *t = NULL;
@@ -281,8 +281,6 @@ ObClient *focus_cycle(gboolean forward, gboolean linear, gboolean done,
             client_activate(focus_cycle_target);
         goto done_cycle;
     }
-    if (!first)
-        grab_pointer(TRUE, None);
 
     if (!first) first = focus_client;
     if (!focus_cycle_target) focus_cycle_target = focus_client;
@@ -331,7 +329,6 @@ done_cycle:
     order = NULL;
 
     popup_cycle(ft, FALSE);
-    grab_pointer(FALSE, None);
 
     return NULL;
 }
diff --git a/openbox/keyboard.c b/openbox/keyboard.c
new file mode 100644 (file)
index 0000000..607941d
--- /dev/null
@@ -0,0 +1,265 @@
+#include "focus.h"
+#include "screen.h"
+#include "frame.h"
+#include "openbox.h"
+#include "event.h"
+#include "grab.h"
+#include "client.h"
+#include "action.h"
+#include "prop.h"
+#include "timer.h"
+#include "keytree.h"
+#include "keyboard.h"
+#include "translate.h"
+
+#include <glib.h>
+
+KeyBindingTree *keyboard_firstnode;
+
+static KeyBindingTree *curpos;
+static ObTimer *chain_timer;
+static gboolean interactive_grab;
+static guint grabbed_state;
+static ObClient *grabbed_client;
+static ObAction *grabbed_action;
+static ObFrameContext grabbed_context;
+
+static void grab_for_window(Window win, gboolean grab)
+{
+    KeyBindingTree *p;
+
+    ungrab_all_keys(win);
+
+    if (grab) {
+        p = curpos ? curpos->first_child : keyboard_firstnode;
+        while (p) {
+            grab_key(p->key, p->state, win, GrabModeAsync);
+            p = p->next_sibling;
+        }
+    }
+}
+
+void keyboard_grab_for_client(ObClient *c, gboolean grab)
+{
+    grab_for_window(c->window, grab);
+}
+
+static void grab_keys(gboolean grab)
+{
+    GList *it;
+
+    grab_for_window(screen_support_win, grab);
+    for (it = client_list; it; it = g_list_next(it))
+        grab_for_window(((ObClient*)it->data)->frame->window, grab);
+}
+
+void keyboard_reset_chains()
+{
+    if (chain_timer) {
+        timer_stop(chain_timer);
+        chain_timer = NULL;
+    }
+    if (curpos) {
+        curpos = NULL;
+        grab_keys(TRUE);
+    }
+}
+
+static void chain_timeout(ObTimer *t, void *data)
+{
+    keyboard_reset_chains();
+}
+
+gboolean keyboard_bind(GList *keylist, ObAction *action)
+{
+    KeyBindingTree *tree, *t;
+    gboolean conflict;
+
+    g_assert(keylist != NULL);
+    g_assert(action != NULL);
+
+    if (!(tree = tree_build(keylist)))
+        return FALSE;
+
+    if ((t = tree_find(tree, &conflict)) != NULL) {
+       /* already bound to something, use the existing tree */
+        tree_destroy(tree);
+        tree = NULL;
+    } else
+        t = tree;
+    while (t->first_child) t = t->first_child;
+
+    if (conflict) {
+        g_warning("conflict with binding");
+        tree_destroy(tree);
+        return FALSE;
+    }
+
+    /* set the action */
+    t->actions = g_slist_append(t->actions, action);
+    /* assimilate this built tree into the main tree. assimilation
+       destroys/uses the tree */
+    if (tree) tree_assimilate(tree);
+
+    return TRUE;
+}
+
+void keyboard_interactive_grab(guint state, ObClient *client,
+                               ObFrameContext context, ObAction *action)
+{
+    if (!interactive_grab && grab_keyboard(TRUE)) {
+        interactive_grab = TRUE;
+        grabbed_state = state;
+        grabbed_client = client;
+        grabbed_action = action;
+        grabbed_context = context;
+        grab_pointer(TRUE, None);
+    }
+}
+
+gboolean keyboard_process_interactive_grab(const XEvent *e,
+                                           ObClient **client,
+                                           ObFrameContext *context)
+{
+    gboolean handled = FALSE;
+    gboolean done = FALSE;
+
+    if (interactive_grab) {
+        *client = grabbed_client;
+        *context = grabbed_context;
+    }
+
+    if ((e->type == KeyRelease && 
+         !(grabbed_state & e->xkey.state)))
+        done = TRUE;
+    else if (e->type == KeyPress) {
+        if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
+            done = TRUE;
+        else if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
+            if (grabbed_action->func == action_cycle_windows) {
+                grabbed_action->data.cycle.cancel = TRUE;
+            }
+            if (grabbed_action->func == action_desktop_dir) {
+                grabbed_action->data.desktopdir.cancel = TRUE;
+            }
+            if (grabbed_action->func == action_send_to_desktop_dir)
+            {
+                grabbed_action->data.sendtodir.cancel = TRUE;
+            }
+            done = TRUE;
+        }
+    }
+    if (done) { 
+        if (grabbed_action->func == action_cycle_windows) {
+            grabbed_action->data.cycle.final = TRUE;
+        }
+        if (grabbed_action->func == action_desktop_dir) {
+            grabbed_action->data.desktopdir.final = TRUE;
+        }
+        if (grabbed_action->func == action_send_to_desktop_dir) {
+            grabbed_action->data.sendtodir.final = TRUE;
+        }
+
+        grabbed_action->func(&grabbed_action->data);
+
+        interactive_grab = FALSE;
+        grab_keyboard(FALSE);
+        grab_pointer(FALSE, None);
+        keyboard_reset_chains();
+
+        handled = TRUE;
+    }
+
+    return handled;
+}
+
+void keyboard_event(ObClient *client, const XEvent *e)
+{
+    KeyBindingTree *p;
+
+    g_assert(e->type == KeyPress);
+
+    if (curpos == NULL)
+        p = keyboard_firstnode;
+    else
+        p = curpos->first_child;
+    while (p) {
+        if (p->key == e->xkey.keycode &&
+            p->state == e->xkey.state) {
+            if (p->first_child != NULL) { /* part of a chain */
+                if (chain_timer) timer_stop(chain_timer);
+                /* 5 second timeout for chains */
+                chain_timer = timer_start(5000*1000, chain_timeout,
+                                          NULL);
+                curpos = p;
+                grab_keys(TRUE);
+            } else {
+                GSList *it;
+                for (it = p->actions; it; it = it->next) {
+                    ObAction *act = it->data;
+                    if (act->func != NULL) {
+                        act->data.any.c = client;
+
+                        if (act->func == action_cycle_windows)
+                        {
+                            act->data.cycle.final = FALSE;
+                            act->data.cycle.cancel = FALSE;
+                        }
+                        if (act->func == action_desktop_dir)
+                        {
+                            act->data.desktopdir.final = FALSE;
+                            act->data.desktopdir.cancel = FALSE;
+                        }
+                        if (act->func == action_send_to_desktop_dir)
+                        {
+                            act->data.sendtodir.final = FALSE;
+                            act->data.sendtodir.cancel = FALSE;
+                        }
+
+                        if (act->func == action_moveresize)
+                        {
+                            screen_pointer_pos(&act->data.moveresize.x,
+                                               &act->data.moveresize.y);
+                        }
+
+                        if ((act->func == action_cycle_windows ||
+                             act->func == action_desktop_dir ||
+                             act->func == action_send_to_desktop_dir))
+                        {
+                            keyboard_interactive_grab(e->xkey.state, client,
+                                                      0, act);
+                        }
+
+                        if (act->func == action_showmenu)
+                        {
+                            act->data.showmenu.x =
+                                e->xkey.x_root;
+                            act->data.showmenu.y =
+                                e->xkey.y_root;
+                        }
+
+                        act->data.any.c = client;
+                        act->func(&act->data);
+                    }
+                }
+
+                keyboard_reset_chains();
+            }
+            break;
+        }
+        p = p->next_sibling;
+    }
+}
+
+void keyboard_startup()
+{
+    grab_keys(TRUE);
+}
+
+void keyboard_shutdown()
+{
+    tree_destroy(keyboard_firstnode);
+    keyboard_firstnode = NULL;
+    grab_keys(FALSE);
+}
+
diff --git a/openbox/keyboard.h b/openbox/keyboard.h
new file mode 100644 (file)
index 0000000..aa17122
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef ob__keybaord_h
+#define ob__keybaord_h
+
+#include "keytree.h"
+#include "frame.h"
+
+#include <glib.h>
+#include <X11/Xlib.h>
+
+struct _ObClient;
+struct _ObAction;
+
+extern KeyBindingTree *keyboard_firstnode;
+
+void keyboard_startup();
+void keyboard_shutdown();
+
+gboolean keyboard_bind(GList *keylist, ObAction *action);
+
+void keyboard_event(struct _ObClient *client, const XEvent *e);
+void keyboard_reset_chains();
+
+void keyboard_interactive_grab(guint state, struct _ObClient *client,
+                               ObFrameContext context,
+                               struct _ObAction *action);
+gboolean keyboard_process_interactive_grab(const XEvent *e,
+                                           struct _ObClient **client,
+                                           ObFrameContext *context);
+
+void keyboard_grab_for_client(struct _ObClient *c, gboolean grab);
+
+#endif
diff --git a/openbox/keytree.c b/openbox/keytree.c
new file mode 100644 (file)
index 0000000..9aa2ea9
--- /dev/null
@@ -0,0 +1,112 @@
+#include "keyboard.h"
+#include "translate.h"
+#include <glib.h>
+
+void tree_destroy(KeyBindingTree *tree)
+{
+    KeyBindingTree *c;
+
+    while (tree) {
+       tree_destroy(tree->next_sibling);
+       c = tree->first_child;
+       if (c == NULL) {
+           GList *it;
+            GSList *sit;
+           for (it = tree->keylist; it != NULL; it = it->next)
+               g_free(it->data);
+           g_list_free(tree->keylist);
+           for (sit = tree->actions; sit != NULL; sit = sit->next)
+                action_free(sit->data);
+           g_slist_free(tree->actions);
+       }
+       g_free(tree);
+       tree = c;
+    }
+}
+
+KeyBindingTree *tree_build(GList *keylist)
+{
+    GList *it;
+    KeyBindingTree *ret = NULL, *p;
+
+    if (g_list_length(keylist) <= 0)
+       return NULL; /* nothing in the list.. */
+
+    for (it = g_list_last(keylist); it != NULL; it = it->prev) {
+       p = ret;
+       ret = g_new0(KeyBindingTree, 1);
+       if (p == NULL) {
+           GList *it;
+
+           /* this is the first built node, the bottom node of the tree */
+           ret->keylist = g_list_copy(keylist); /* shallow copy */
+           for (it = ret->keylist; it != NULL; it = it->next) /* deep copy */
+               it->data = g_strdup(it->data);
+       }
+       ret->first_child = p;
+       if (!translate_key(it->data, &ret->state, &ret->key)) {
+           tree_destroy(ret);
+           return NULL;
+       }
+    }
+    return ret;
+}
+
+void tree_assimilate(KeyBindingTree *node)
+{
+    KeyBindingTree *a, *b, *tmp, *last;
+
+    if (keyboard_firstnode == NULL) {
+       /* there are no nodes at this level yet */
+       keyboard_firstnode = node;
+    } else {
+       a = keyboard_firstnode;
+       last = a;
+       b = node;
+       while (a) {
+           last = a;
+           if (!(a->state == b->state && a->key == b->key)) {
+               a = a->next_sibling;
+           } else {
+               tmp = b;
+               b = b->first_child;
+               g_free(tmp);
+               a = a->first_child;
+           }
+       }
+       if (!(last->state == b->state && last->key == b->key))
+           last->next_sibling = b;
+       else {
+           last->first_child = b->first_child;
+           g_free(b);
+       }
+    }
+}
+
+KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict)
+{
+    KeyBindingTree *a, *b;
+
+    *conflict = FALSE;
+
+    a = keyboard_firstnode;
+    b = search;
+    while (a && b) {
+       if (!(a->state == b->state && a->key == b->key)) {
+           a = a->next_sibling;
+       } else {
+           if ((a->first_child == NULL) == (b->first_child == NULL)) {
+               if (a->first_child == NULL) {
+                   /* found it! (return the actual node, not the search's) */
+                   return a;
+               }
+           } else {
+               *conflict = TRUE;
+               return NULL; /* the chain status' don't match (conflict!) */
+           }
+           b = b->first_child;
+           a = a->first_child;
+       }
+    }
+    return NULL; /* it just isn't in here */
+}
diff --git a/openbox/keytree.h b/openbox/keytree.h
new file mode 100644 (file)
index 0000000..0c61e47
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __plugin_keyboard_tree_h
+#define __plugin_keyboard_tree_h
+
+#include "action.h"
+
+#include <glib.h>
+
+typedef struct KeyBindingTree {
+    guint state;
+    guint key;
+    GList *keylist;
+    GSList *actions; /* list of Action pointers */
+
+    /* the next binding in the tree at the same level */
+    struct KeyBindingTree *next_sibling; 
+    /* the first child of this binding (next binding in a chained sequence).*/
+    struct KeyBindingTree *first_child;
+} KeyBindingTree;
+
+void tree_destroy(KeyBindingTree *tree);
+KeyBindingTree *tree_build(GList *keylist);
+void tree_assimilate(KeyBindingTree *node);
+KeyBindingTree *tree_find(KeyBindingTree *search, gboolean *conflict);
+
+#endif
index 00a2bc2b221ab4b44dda1d9e5a26772c9acd1fda..0f2eff429925e1f4744415c32f43e995d0013611 100644 (file)
@@ -27,7 +27,7 @@ static void parse_menu(xmlDocPtr doc, xmlNodePtr node, void *data)
 void parse_menu_full(xmlDocPtr doc, xmlNodePtr node, void *data,
                        gboolean newmenu)
 {
-    Action *act;
+    ObAction *act;
     xmlNodePtr nact;
 
     gchar *id = NULL, *title = NULL, *label = NULL, *plugin;
@@ -233,7 +233,7 @@ void menu_free(char *name)
     g_hash_table_remove(menu_hash, name);
 }
 
-ObMenuEntry *menu_entry_new_full(char *label, Action *action,
+ObMenuEntry *menu_entry_new_full(char *label, ObAction *action,
                                ObMenuEntryRenderType render_type,
                                gpointer submenu)
 {
index 3b7c1c3840477ff0757b19fc30d914ad7e720a41..2ecbb5cdef846ab2c0b62210c51a303026fdbaf6 100644 (file)
@@ -103,7 +103,7 @@ struct _ObMenuEntry
     char *label;
     ObMenu *parent;
 
-    Action *action;    
+    ObAction *action;    
     
     ObMenuEntryRenderType render_type;
     gboolean hilite;
@@ -155,7 +155,7 @@ void menu_hide(ObMenu *self);
 
 void menu_clear(ObMenu *self);
 
-ObMenuEntry *menu_entry_new_full(char *label, Action *action,
+ObMenuEntry *menu_entry_new_full(char *label, ObAction *action,
                                ObMenuEntryRenderType render_type,
                                gpointer submenu);
 
similarity index 50%
rename from plugins/mouse/mouse.c
rename to openbox/mouse.c
index 913a2e4a2d1887fc9d1c22397bca400974791d6d..ac0fb1d2b777ac033320ba334f135ae845f798b7 100644 (file)
-#include "kernel/openbox.h"
-#include "kernel/dispatch.h"
-#include "kernel/action.h"
-#include "kernel/event.h"
-#include "kernel/client.h"
-#include "kernel/prop.h"
-#include "kernel/grab.h"
-#include "kernel/frame.h"
-#include "parser/parse.h"
+#include "openbox.h"
+#include "config.h"
+#include "action.h"
+#include "event.h"
+#include "client.h"
+#include "prop.h"
+#include "grab.h"
+#include "frame.h"
 #include "translate.h"
 #include "mouse.h"
+#include "keyboard.h"
 #include <glib.h>
 
-static int threshold;
-static int dclicktime;
-/*
-
-<context name="Titlebar"> 
-  <mousebind button="Left" action="Press">
-    <action name="Raise"></action>
-  </mousebind>
-</context>
-
-*/
-
-static void parse_xml(xmlDocPtr doc, xmlNodePtr node, void *d)
-{
-    xmlNodePtr n, nbut, nact;
-    char *buttonstr;
-    char *contextstr;
-    MouseAction mact;
-    Action *action;
-
-    node = node->xmlChildrenNode;
-    
-    if ((n = parse_find_node("dragThreshold", node)))
-        threshold = parse_int(doc, n);
-    if ((n = parse_find_node("doubleClickTime", node)))
-        dclicktime = parse_int(doc, n);
-
-    n = parse_find_node("context", node);
-    while (n) {
-        if (!parse_attr_string("name", n, &contextstr))
-            goto next_n;
-        nbut = parse_find_node("mousebind", n->xmlChildrenNode);
-        while (nbut) {
-            if (!parse_attr_string("button", nbut, &buttonstr))
-                goto next_nbut;
-            if (parse_attr_contains("press", nbut, "action"))
-                mact = MouseAction_Press;
-            else if (parse_attr_contains("release", nbut, "action"))
-                mact = MouseAction_Release;
-            else if (parse_attr_contains("click", nbut, "action"))
-                mact = MouseAction_Click;
-            else if (parse_attr_contains("doubleclick", nbut,"action"))
-                mact = MouseAction_DClick;
-            else if (parse_attr_contains("drag", nbut, "action"))
-                mact = MouseAction_Motion;
-            else
-                goto next_nbut;
-            nact = parse_find_node("action", nbut->xmlChildrenNode);
-            while (nact) {
-                if ((action = action_parse(doc, nact))) {
-                    /* validate that its okay for a mouse binding*/
-                    if (mact == MouseAction_Motion) {
-                        if (action->func != action_moveresize ||
-                            action->data.moveresize.corner ==
-                            prop_atoms.net_wm_moveresize_move_keyboard ||
-                            action->data.moveresize.corner ==
-                            prop_atoms.net_wm_moveresize_size_keyboard) {
-                            action_free(action);
-                            action = NULL;
-                        }
-                    } else {
-                        if (action->func == action_moveresize &&
-                            action->data.moveresize.corner !=
-                            prop_atoms.net_wm_moveresize_move_keyboard &&
-                            action->data.moveresize.corner !=
-                            prop_atoms.net_wm_moveresize_size_keyboard) {
-                            action_free(action);
-                            action = NULL;
-                        }
-                    }
-                    if (action)
-                        mbind(buttonstr, contextstr, mact, action);
-                }
-                nact = parse_find_node("action", nact->next);
-            }
-            g_free(buttonstr);
-        next_nbut:
-            nbut = parse_find_node("mousebind", nbut->next);
-        }
-        g_free(contextstr);
-    next_n:
-        n = parse_find_node("context", n->next);
-    }
-}
-
-void plugin_setup_config()
-{
-    threshold = 3;
-    dclicktime = 200;
-    parse_register("mouse", parse_xml, NULL);
-}
+typedef struct {
+    guint state;
+    guint button;
+    GSList *actions[NUM_MOUSEACTION]; /* lists of Action pointers */
+} ObMouseBinding;
 
 /* Array of GSList*s of PointerBinding*s. */
 static GSList *bound_contexts[OB_FRAME_NUM_CONTEXTS];
 
-static void grab_for_client(ObClient *client, gboolean grab)
+void mouse_grab_for_client(ObClient *client, gboolean grab)
 {
     int i;
     GSList *it;
@@ -114,7 +28,7 @@ static void grab_for_client(ObClient *client, gboolean grab)
     for (i = 0; i < OB_FRAME_NUM_CONTEXTS; ++i)
         for (it = bound_contexts[i]; it != NULL; it = it->next) {
             /* grab/ungrab the button */
-            MouseBinding *b = it->data;
+            ObMouseBinding *b = it->data;
             Window win;
             int mode;
             unsigned int mask;
@@ -143,7 +57,7 @@ static void grab_all_clients(gboolean grab)
     GList *it;
 
     for (it = client_list; it != NULL; it = it->next)
-       grab_for_client(it->data, grab);
+       mouse_grab_for_client(it->data, grab);
 }
 
 static void clearall()
@@ -155,7 +69,7 @@ static void clearall()
         for (it = bound_contexts[i]; it != NULL; it = it->next) {
             int j;
 
-            MouseBinding *b = it->data;
+            ObMouseBinding *b = it->data;
             for (j = 0; j < NUM_MOUSEACTION; ++j) {
                 GSList *it;
                 for (it = b->actions[j]; it; it = it->next) {
@@ -169,12 +83,14 @@ static void clearall()
     }
 }
 
-static void fire_button(MouseAction a, ObFrameContext context,
+static void fire_button(ObMouseAction a, ObFrameContext context,
                         ObClient *c, guint state,
                         guint button, int x, int y)
 {
     GSList *it;
-    MouseBinding *b;
+    ObMouseBinding *b;
+
+    g_message("%d %d %d", context, state, button);
 
     for (it = bound_contexts[context]; it != NULL; it = it->next) {
         b = it->data;
@@ -185,7 +101,7 @@ static void fire_button(MouseAction a, ObFrameContext context,
     if (it == NULL) return;
 
     for (it = b->actions[a]; it; it = it->next) {
-        Action *act = it->data;
+        ObAction *act = it->data;
         if (act->func != NULL) {
             act->data.any.c = c;
 
@@ -196,17 +112,35 @@ static void fire_button(MouseAction a, ObFrameContext context,
                 act->data.showmenu.y = y;
             }
 
+            if (act->func == action_desktop_dir)
+            {
+                act->data.desktopdir.final = FALSE;
+                act->data.desktopdir.cancel = FALSE;
+            }
+            if (act->func == action_send_to_desktop_dir)
+            {
+                act->data.sendtodir.final = FALSE;
+                act->data.sendtodir.cancel = FALSE;
+            }
+
+            if ((act->func == action_desktop_dir ||
+                 act->func == action_send_to_desktop_dir)) {
+                keyboard_interactive_grab(state, c, context, act);
+            }
+
+            g_message("acting");
+
             act->func(&act->data);
         }
     }
 }
 
-static void fire_motion(MouseAction a, ObFrameContext context, ObClient *c,
+static void fire_motion(ObMouseAction a, ObFrameContext context, ObClient *c,
                         guint state, guint button, int x_root, int y_root,
                         guint32 corner)
 {
     GSList *it;
-    MouseBinding *b;
+    ObMouseBinding *b;
 
     for (it = bound_contexts[context]; it != NULL; it = it->next) {
         b = it->data;
@@ -217,7 +151,7 @@ static void fire_motion(MouseAction a, ObFrameContext context, ObClient *c,
     if (it == NULL) return;
 
     for (it = b->actions[a]; it; it = it->next) {
-        Action *act = it->data;
+        ObAction *act = it->data;
         if (act->func != NULL) {
             act->data.any.c = c;
 
@@ -255,38 +189,27 @@ static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
     }
 }
 
-static void event(ObEvent *e, void *foo)
+void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
 {
     static Time ltime;
     static guint button = 0, state = 0, lbutton = 0;
+
     static Window lwindow = None;
     static int px, py;
     gboolean click = FALSE;
     gboolean dclick = FALSE;
-    ObFrameContext context;
     
     switch (e->type) {
-    case Event_Client_Mapped:
-        grab_for_client(e->data.c.client, TRUE);
-        break;
-
-    case Event_Client_Destroy:
-        grab_for_client(e->data.c.client, FALSE);
-        break;
-
-    case Event_X_ButtonPress:
-        context = frame_context(e->data.x.client,
-                                e->data.x.e->xbutton.window);
-
-        px = e->data.x.e->xbutton.x_root;
-        py = e->data.x.e->xbutton.y_root;
-        button = e->data.x.e->xbutton.button;
-        state = e->data.x.e->xbutton.state;
+    case ButtonPress:
+        px = e->xbutton.x_root;
+        py = e->xbutton.y_root;
+        button = e->xbutton.button;
+        state = e->xbutton.state;
 
         fire_button(MouseAction_Press, context,
-                    e->data.x.client, e->data.x.e->xbutton.state,
-                    e->data.x.e->xbutton.button,
-                    e->data.x.e->xbutton.x_root, e->data.x.e->xbutton.y_root);
+                    client, e->xbutton.state,
+                    e->xbutton.button,
+                    e->xbutton.x_root, e->xbutton.y_root);
 
         if (context == OB_FRAME_CONTEXT_CLIENT) {
             /* Replay the event, so it goes to the client*/
@@ -295,30 +218,29 @@ static void event(ObEvent *e, void *foo)
         } else
             break;
 
-    case Event_X_ButtonRelease:
-        context = frame_context(e->data.x.client,
-                                e->data.x.e->xbutton.window);
-        if (e->data.x.e->xbutton.button == button) {
+    case ButtonRelease:
+        if (e->xbutton.button == button) {
             /* clicks are only valid if its released over the window */
             int junk1, junk2;
             Window wjunk;
             guint ujunk, b, w, h;
-            XGetGeometry(ob_display, e->data.x.e->xbutton.window,
+            XGetGeometry(ob_display, e->xbutton.window,
                          &wjunk, &junk1, &junk2, &w, &h, &b, &ujunk);
-            if (e->data.x.e->xbutton.x >= (signed)-b &&
-                e->data.x.e->xbutton.y >= (signed)-b &&
-                e->data.x.e->xbutton.x < (signed)(w+b) &&
-                e->data.x.e->xbutton.y < (signed)(h+b)) {
+            if (e->xbutton.x >= (signed)-b &&
+                e->xbutton.y >= (signed)-b &&
+                e->xbutton.x < (signed)(w+b) &&
+                e->xbutton.y < (signed)(h+b)) {
                 click = TRUE;
                 /* double clicks happen if there were 2 in a row! */
                 if (lbutton == button &&
-                    lwindow == e->data.x.e->xbutton.window &&
-                    e->data.x.e->xbutton.time - dclicktime <= ltime) {
+                    lwindow == e->xbutton.window &&
+                    e->xbutton.time - config_mouse_dclicktime <=
+                    ltime) {
                     dclick = TRUE;
                     lbutton = 0;
                 } else {
                     lbutton = button;
-                    lwindow = e->data.x.e->xbutton.window;
+                    lwindow = e->xbutton.window;
                 }
             } else {
                 lbutton = 0;
@@ -327,35 +249,34 @@ static void event(ObEvent *e, void *foo)
 
             button = 0;
             state = 0;
-            ltime = e->data.x.e->xbutton.time;
+            ltime = e->xbutton.time;
         }
         fire_button(MouseAction_Release, context,
-                    e->data.x.client, e->data.x.e->xbutton.state,
-                    e->data.x.e->xbutton.button,
-                    e->data.x.e->xbutton.x_root, e->data.x.e->xbutton.y_root);
+                    client, e->xbutton.state,
+                    e->xbutton.button,
+                    e->xbutton.x_root, e->xbutton.y_root);
         if (click)
             fire_button(MouseAction_Click, context,
-                        e->data.x.client, e->data.x.e->xbutton.state,
-                        e->data.x.e->xbutton.button,
-                        e->data.x.e->xbutton.x_root,
-                        e->data.x.e->xbutton.y_root);
+                        client, e->xbutton.state,
+                        e->xbutton.button,
+                        e->xbutton.x_root,
+                        e->xbutton.y_root);
         if (dclick)
             fire_button(MouseAction_DClick, context,
-                        e->data.x.client, e->data.x.e->xbutton.state,
-                        e->data.x.e->xbutton.button,
-                        e->data.x.e->xbutton.x_root,
-                        e->data.x.e->xbutton.y_root);
+                        client, e->xbutton.state,
+                        e->xbutton.button,
+                        e->xbutton.x_root,
+                        e->xbutton.y_root);
         break;
 
-    case Event_X_MotionNotify:
+    case MotionNotify:
         if (button) {
-            if (ABS(e->data.x.e->xmotion.x_root - px) >= threshold ||
-                ABS(e->data.x.e->xmotion.y_root - py) >= threshold) {
+            if (ABS(e->xmotion.x_root - px) >=
+                config_mouse_threshold ||
+                ABS(e->xmotion.y_root - py) >=
+                config_mouse_threshold) {
                 guint32 corner;
 
-                context = frame_context(e->data.x.client,
-                                        e->data.x.e->xmotion.window);
-
                 /* You can't drag on buttons */
                 if (context == OB_FRAME_CONTEXT_MAXIMIZE ||
                     context == OB_FRAME_CONTEXT_ALLDESKTOPS ||
@@ -365,26 +286,26 @@ static void event(ObEvent *e, void *foo)
                     context == OB_FRAME_CONTEXT_CLOSE)
                     break;
 
-                if (!e->data.x.client)
+                if (!client)
                     corner = prop_atoms.net_wm_moveresize_size_bottomright;
                 else
                     corner =
-                        pick_corner(e->data.x.e->xmotion.x_root,
-                                    e->data.x.e->xmotion.y_root,
-                                    e->data.x.client->frame->area.x,
-                                    e->data.x.client->frame->area.y,
+                        pick_corner(e->xmotion.x_root,
+                                    e->xmotion.y_root,
+                                    client->frame->area.x,
+                                    client->frame->area.y,
                                     /* use the client size because the frame
                                        can be differently sized (shaded
                                        windows) and we want this based on the
                                        clients size */
-                                    e->data.x.client->area.width +
-                                    e->data.x.client->frame->size.left +
-                                    e->data.x.client->frame->size.right,
-                                    e->data.x.client->area.height +
-                                    e->data.x.client->frame->size.top +
-                                    e->data.x.client->frame->size.bottom);
+                                    client->area.width +
+                                    client->frame->size.left +
+                                    client->frame->size.right,
+                                    client->area.height +
+                                    client->frame->size.top +
+                                    client->frame->size.bottom);
                 fire_motion(MouseAction_Motion, context,
-                            e->data.x.client, state, button, px, py, corner);
+                            client, state, button, px, py, corner);
                 button = 0;
                 state = 0;
             }
@@ -396,12 +317,12 @@ static void event(ObEvent *e, void *foo)
     }
 }
 
-gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
-               Action *action)
+gboolean mouse_bind(char *buttonstr, char *contextstr, ObMouseAction mact,
+                    ObAction *action)
 {
     guint state, button;
     ObFrameContext context;
-    MouseBinding *b;
+    ObMouseBinding *b;
     GSList *it;
 
     if (!translate_button(buttonstr, &state, &button)) {
@@ -429,7 +350,7 @@ gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
     grab_all_clients(FALSE);
 
     /* add the binding */
-    b = g_new0(MouseBinding, 1);
+    b = g_new0(ObMouseBinding, 1);
     b->state = state;
     b->button = button;
     b->actions[mact] = g_slist_append(NULL, action);
@@ -440,17 +361,12 @@ gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
     return TRUE;
 }
 
-void plugin_startup()
+void mouse_startup()
 {
-    dispatch_register(Event_Client_Mapped | Event_Client_Destroy |
-                      Event_X_ButtonPress | Event_X_ButtonRelease |
-                      Event_X_MotionNotify, (EventHandler)event, NULL);
 }
 
-void plugin_shutdown()
+void mouse_shutdown()
 {
-    dispatch_register(0, (EventHandler)event, NULL);
-
     grab_all_clients(FALSE);
     clearall();
 }
diff --git a/openbox/mouse.h b/openbox/mouse.h
new file mode 100644 (file)
index 0000000..a5e8f9a
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef ob__mouse_h
+#define ob__mouse_h
+
+#include "action.h"
+#include "frame.h"
+
+#include <X11/Xlib.h>
+
+typedef enum {
+    MouseAction_Press,
+    MouseAction_Release,
+    MouseAction_Click,
+    MouseAction_DClick,
+    MouseAction_Motion,
+    NUM_MOUSEACTION
+} ObMouseAction;
+
+void mouse_startup();
+void mouse_shutdown();
+
+gboolean mouse_bind(char *buttonstr, char *contextstr, ObMouseAction mact,
+                    ObAction *action);
+
+void mouse_event(struct _ObClient *client, ObFrameContext context, XEvent *e);
+
+void mouse_grab_for_client(struct _ObClient *client, gboolean grab);
+
+#endif
index 7f141d6f3892d1dc451e913f9bb7264ce965bb24..631395cc826b522c428d113bf149f1070e1e5085 100644 (file)
@@ -13,6 +13,8 @@
 #include "focus.h"
 #include "moveresize.h"
 #include "frame.h"
+#include "keyboard.h"
+#include "mouse.h"
 #include "extensions.h"
 #include "grab.h"
 #include "plugin.h"
@@ -243,6 +245,8 @@ int main(int argc, char **argv)
         group_startup();
        client_startup();
         dock_startup();
+        keyboard_startup();
+        mouse_startup();
 
         /* call startup for all the plugins */
         plugin_startall();
@@ -259,6 +263,8 @@ int main(int argc, char **argv)
        client_unmanage_all();
 
         plugin_shutdown(); /* calls all the plugins' shutdown functions */
+        mouse_shutdown();
+        keyboard_shutdown();
         dock_shutdown();
        client_shutdown();
         group_shutdown();
index cd17d215a41ce0d091baaf47d0deefb6792d09a3..e95d03e9444a4100ce8f64552766e9352ef4cb3f 100644 (file)
@@ -156,8 +156,6 @@ void plugin_loadall()
 
     if (io == NULL) {
         /* load the default plugins */
-        plugin_open("keyboard");
-        plugin_open("mouse");
         plugin_open("placement");
         plugin_open("resistance");
 
index 4f9e6a2c89af68a9a8578196d0d37044ab06907f..6c9042a99edb1b3b51d10a6cbb5ecbea60b9c95d 100644 (file)
@@ -4,6 +4,7 @@
 #include "xerror.h"
 #include "prop.h"
 #include "startup.h"
+#include "grab.h"
 #include "timer.h"
 #include "config.h"
 #include "screen.h"
@@ -25,6 +26,7 @@
 #  include <sys/types.h>
 #  include <unistd.h>
 #endif
+#include <assert.h>
 
 /*! The event mask to grab on the root window */
 #define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
@@ -45,7 +47,6 @@ static Rect  **area; /* array of desktop holding array of xinerama areas */
 static Rect  *monitor_area;
 
 static Popup *desktop_cycle_popup;
-static ObTimer *popup_timer = NULL;
 
 #ifdef USE_LIBSN
 static SnMonitorContext *sn_context;
@@ -420,36 +421,6 @@ void screen_set_num_desktops(guint num)
        screen_set_desktop(num - 1);
 }
 
-static void popup_cycle_hide(ObTimer *t, void *d)
-{
-    timer_stop(t);
-    popup_timer = NULL;
-
-    popup_hide(desktop_cycle_popup);
-}
-
-static void popup_cycle_show()
-{
-    Rect *a;
-
-    a = screen_physical_area_monitor(0);
-    popup_position(desktop_cycle_popup, CenterGravity,
-                   a->x + a->width / 2, a->y + a->height / 2);
-    /* XXX the size and the font extents need to be related on some level
-     */
-    popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
-
-    popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
-
-    popup_show(desktop_cycle_popup,
-               screen_desktop_names[screen_desktop], NULL);
-
-    g_message("%s", screen_desktop_names[screen_desktop]);
-
-    if (popup_timer) timer_stop(popup_timer);
-    popup_timer = timer_start(G_USEC_PER_SEC / 2, popup_cycle_hide, NULL);
-}
-
 void screen_set_desktop(guint num)
 {
     GList *it;
@@ -498,12 +469,250 @@ void screen_set_desktop(guint num)
     ob_debug("/switch fallback\n");
 #endif
 
-    if (ob_state() == OB_STATE_RUNNING)
-        popup_cycle_show();
-
     dispatch_ob(Event_Ob_Desktop, num, old);
 }
 
+static void get_row_col(guint d, guint *r, guint *c)
+{
+    switch (screen_desktop_layout.orientation) {
+    case OB_ORIENTATION_HORZ:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            *r = d / screen_desktop_layout.columns;
+            *c = d % screen_desktop_layout.columns;
+            break;
+        case OB_CORNER_BOTTOMLEFT:
+            *r = screen_desktop_layout.rows - 1 -
+                d / screen_desktop_layout.columns;
+            *c = d % screen_desktop_layout.columns;
+            break;
+        case OB_CORNER_TOPRIGHT:
+            *r = d / screen_desktop_layout.columns;
+            *c = screen_desktop_layout.columns - 1 -
+                d % screen_desktop_layout.columns;
+            break;
+        case OB_CORNER_BOTTOMRIGHT:
+            *r = screen_desktop_layout.rows - 1 -
+                d / screen_desktop_layout.columns;
+            *c = screen_desktop_layout.columns - 1 -
+                d % screen_desktop_layout.columns;
+            break;
+        }
+        break;
+    case OB_ORIENTATION_VERT:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            *r = d % screen_desktop_layout.rows;
+            *c = d / screen_desktop_layout.rows;
+            break;
+        case OB_CORNER_BOTTOMLEFT:
+            *r = screen_desktop_layout.rows - 1 -
+                d % screen_desktop_layout.rows;
+            *c = d / screen_desktop_layout.rows;
+            break;
+        case OB_CORNER_TOPRIGHT:
+            *r = d % screen_desktop_layout.rows;
+            *c = screen_desktop_layout.columns - 1 -
+                d / screen_desktop_layout.rows;
+            break;
+        case OB_CORNER_BOTTOMRIGHT:
+            *r = screen_desktop_layout.rows - 1 -
+                d % screen_desktop_layout.rows;
+            *c = screen_desktop_layout.columns - 1 -
+                d / screen_desktop_layout.rows;
+            break;
+        }
+        break;
+    }
+}
+
+static guint translate_row_col(guint r, guint c)
+{
+    switch (screen_desktop_layout.orientation) {
+    case OB_ORIENTATION_HORZ:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            return r % screen_desktop_layout.rows *
+                screen_desktop_layout.columns +
+                c % screen_desktop_layout.columns;
+        case OB_CORNER_BOTTOMLEFT:
+            return (screen_desktop_layout.rows - 1 -
+                    r % screen_desktop_layout.rows) *
+                screen_desktop_layout.columns +
+                c % screen_desktop_layout.columns;
+        case OB_CORNER_TOPRIGHT:
+            return r % screen_desktop_layout.rows *
+                screen_desktop_layout.columns +
+                (screen_desktop_layout.columns - 1 -
+                 c % screen_desktop_layout.columns);
+        case OB_CORNER_BOTTOMRIGHT:
+            return (screen_desktop_layout.rows - 1 -
+                    r % screen_desktop_layout.rows) *
+                screen_desktop_layout.columns +
+                (screen_desktop_layout.columns - 1 -
+                 c % screen_desktop_layout.columns);
+        }
+    case OB_ORIENTATION_VERT:
+        switch (screen_desktop_layout.start_corner) {
+        case OB_CORNER_TOPLEFT:
+            return c % screen_desktop_layout.columns *
+                screen_desktop_layout.rows +
+                r % screen_desktop_layout.rows;
+        case OB_CORNER_BOTTOMLEFT:
+            return c % screen_desktop_layout.columns *
+                screen_desktop_layout.rows +
+                (screen_desktop_layout.rows - 1 -
+                 r % screen_desktop_layout.rows);
+        case OB_CORNER_TOPRIGHT:
+            return (screen_desktop_layout.columns - 1 -
+                    c % screen_desktop_layout.columns) *
+                screen_desktop_layout.rows +
+                r % screen_desktop_layout.rows;
+        case OB_CORNER_BOTTOMRIGHT:
+            return (screen_desktop_layout.columns - 1 -
+                    c % screen_desktop_layout.columns) *
+                screen_desktop_layout.rows +
+                (screen_desktop_layout.rows - 1 -
+                 r % screen_desktop_layout.rows);
+        }
+    }
+    g_assert_not_reached();
+    return 0;
+}
+
+static void popup_cycle(guint d, gboolean show)
+{
+    Rect *a;
+
+    if (!show) {
+        popup_hide(desktop_cycle_popup);
+    } else {
+        a = screen_physical_area_monitor(0);
+        popup_position(desktop_cycle_popup, CenterGravity,
+                       a->x + a->width / 2, a->y + a->height / 2);
+        /* XXX the size and the font extents need to be related on some level
+         */
+        popup_size(desktop_cycle_popup, POPUP_WIDTH, POPUP_HEIGHT);
+
+        popup_set_text_align(desktop_cycle_popup, RR_JUSTIFY_CENTER);
+
+        popup_show(desktop_cycle_popup,
+                   screen_desktop_names[d], NULL);
+    }
+}
+
+guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
+                           gboolean done, gboolean cancel)
+{
+    static gboolean first = TRUE;
+    static gboolean lin;
+    static guint origd, d;
+    guint r, c;
+
+    if (cancel) {
+        d = origd;
+        goto done_cycle;
+    } else if (done) {
+        screen_set_desktop(d);
+        goto done_cycle;
+    }
+    if (first) {
+        first = FALSE;
+        lin = linear;
+        d = origd = screen_desktop;
+    }
+
+    get_row_col(d, &r, &c);
+
+    if (lin) {
+        g_message("linear %d", d);
+        switch (dir) {
+        case OB_DIRECTION_EAST:
+            if (d < screen_num_desktops - 1)
+                ++d;
+            else if (wrap)
+                d = 0;
+            break;
+        case OB_DIRECTION_WEST:
+            if (d > 0)
+                --d;
+            else if (wrap)
+                d = screen_num_desktops - 1;
+            break;
+        default:
+            assert(0);
+            return screen_desktop;
+        }
+        g_message("linear %d done", d);
+    } else {
+        switch (dir) {
+        case OB_DIRECTION_EAST:
+            ++c;
+            if (c >= screen_desktop_layout.columns) {
+                if (!wrap) return d = screen_desktop;
+                c = 0;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                ++c;
+            }
+            break;
+        case OB_DIRECTION_WEST:
+            --c;
+            if (c >= screen_desktop_layout.columns) {
+                if (!wrap) return d = screen_desktop;
+                c = screen_desktop_layout.columns - 1;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                --c;
+            }
+            break;
+        case OB_DIRECTION_SOUTH:
+            ++r;
+            if (r >= screen_desktop_layout.rows) {
+                if (!wrap) return d = screen_desktop;
+                r = 0;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                ++r;
+            }
+            break;
+        case OB_DIRECTION_NORTH:
+            --r;
+            if (r >= screen_desktop_layout.rows) {
+                if (!wrap) return d = screen_desktop;
+                r = screen_desktop_layout.rows - 1;
+            }
+            d = translate_row_col(r, c);
+            if (d >= screen_num_desktops) {
+                if (!wrap) return d = screen_desktop;
+                --r;
+            }
+            break;
+        default:
+            assert(0);
+            return d = screen_desktop;
+        }
+
+        d = translate_row_col(r, c);
+    }
+
+    popup_cycle(d, TRUE);
+    return d;
+
+done_cycle:
+    first = TRUE;
+
+    popup_cycle(0, FALSE);
+
+    return d = screen_desktop;
+}
+
 void screen_update_layout()
 {
     ObOrientation orient;
index 1c687036e5a1cb96d2b4be9b56bba033cfac500a..696423e2becc04dbc84f63617fbc2e56997b2157 100644 (file)
@@ -45,6 +45,9 @@ void screen_resize();
 void screen_set_num_desktops(guint num);
 /*! Change the current desktop */
 void screen_set_desktop(guint num);
+/*! Interactively change desktops */
+guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear,
+                           gboolean done, gboolean cancel);
 
 /*! Shows and focuses the desktop and hides all the client windows, or
   returns to the normal state, showing client windows. */
similarity index 67%
rename from plugins/mouse/translate.c
rename to openbox/translate.c
index aebe5557887717602efbf91b8e1607521b80b2bd..9b4c1406e9af9ebb966e4ee798ce25153fb1faf9 100644 (file)
@@ -63,3 +63,47 @@ translation_fail:
     g_strfreev(parsed);
     return ret;
 }
+
+gboolean translate_key(char *str, guint *state, guint *keycode)
+{
+    char **parsed;
+    char *l;
+    int i;
+    gboolean ret = FALSE;
+    KeySym sym;
+
+    parsed = g_strsplit(str, "-", -1);
+    
+    /* first, find the key (last token) */
+    l = NULL;
+    for (i = 0; parsed[i] != NULL; ++i)
+       l = parsed[i];
+    if (l == NULL)
+       goto translation_fail;
+
+    /* figure out the mod mask */
+    *state = 0;
+    for (i = 0; parsed[i] != l; ++i) {
+       guint m = translate_modifier(parsed[i]);
+       if (!m) goto translation_fail;
+       *state |= m;
+    }
+
+    /* figure out the keycode */
+    sym = XStringToKeysym(l);
+    if (sym == NoSymbol) {
+       g_warning("Invalid key name '%s' in key binding.", l);
+       goto translation_fail;
+    }
+    *keycode = XKeysymToKeycode(ob_display, sym);
+    if (!*keycode) {
+       g_warning("Key '%s' does not exist on the display.", l); 
+       goto translation_fail;
+    }
+
+    ret = TRUE;
+
+translation_fail:
+    g_strfreev(parsed);
+    return ret;
+}
diff --git a/openbox/translate.h b/openbox/translate.h
new file mode 100644 (file)
index 0000000..5afab50
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef ob__translate_h
+#define ob__translate_h
+
+#include <glib.h>
+
+gboolean translate_button(gchar *str, guint *state, guint *keycode);
+gboolean translate_key(gchar *str, guint *state, guint *keycode);
+
+#endif
index a13d3f3850c4554c746bca254c344ba66cbb3443..c45d2a432a27bc295626e6dba4524519797c22bf 100644 (file)
@@ -52,7 +52,7 @@ void client_send_to_update(ObMenu *self)
         ob_debug("update\n");
         for (i = 0; i < screen_num_desktops; ++i) {
             ObMenuEntry *e;
-            Action *a = action_from_string("sendtodesktop");
+            ObAction *a = action_from_string("sendtodesktop");
             a->data.sendto.desk = i;
             a->data.sendto.follow = FALSE;
             e = menu_entry_new(screen_desktop_names[i], a);
diff --git a/plugins/mouse/.cvsignore b/plugins/mouse/.cvsignore
deleted file mode 100644 (file)
index 9d1b860..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-mouse.la
-.libs
-.deps
-.dirstamp
-plugins_mouse_mouse_la-mouse.lo
-plugins_mouse_mouse_la-translate.lo
diff --git a/plugins/mouse/Makefile b/plugins/mouse/Makefile
deleted file mode 100644 (file)
index cfc4653..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-all clean install:
-       $(MAKE) -C ../.. -$(MAKEFLAGS) $@
-
-.PHONY: all clean install
diff --git a/plugins/mouse/mouse.h b/plugins/mouse/mouse.h
deleted file mode 100644 (file)
index 408ae96..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __plugin_mouse_mouse_h
-#define __plugin_mouse_mouse_h
-
-#include "../../kernel/action.h"
-
-typedef enum {
-    MouseAction_Press,
-    MouseAction_Release,
-    MouseAction_Click,
-    MouseAction_DClick,
-    MouseAction_Motion,
-    NUM_MOUSEACTION
-} MouseAction;
-
-typedef struct {
-    guint state;
-    guint button;
-    GSList *actions[NUM_MOUSEACTION]; /* lists of Action pointers */
-} MouseBinding;
-
-gboolean mbind(char *buttonstr, char *contextstr, MouseAction mact,
-               Action *action);
-
-#endif
diff --git a/plugins/mouse/translate.h b/plugins/mouse/translate.h
deleted file mode 100644 (file)
index a2fcfc9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __plugin_mouse_translate_h
-#define __plugin_mouse_translate_h
-
-#include <glib.h>
-
-gboolean translate_button(char *str, guint *state, guint *keycode);
-
-#endif
This page took 0.099389 seconds and 4 git commands to generate.