From c90da6da781932c2d178bfb7e39ec1d5003543b7 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 12 Aug 2003 07:26:16 +0000 Subject: [PATCH] move the keyboard and mouse plugins into the kernel for mucho sexiness. make workspace changing a grabbed/interactive process like focus cycling is, with the popup and all. this is some hot shit. --- ChangeLog | 61 ++++ Makefile.am | 48 +--- openbox/.cvsignore | 3 + openbox/action.c | 367 +++++++++++++------------ openbox/action.h | 39 ++- openbox/client.c | 12 +- openbox/config.c | 155 +++++++++++ openbox/config.h | 5 + openbox/event.c | 24 +- openbox/focus.c | 5 +- openbox/keyboard.c | 265 ++++++++++++++++++ openbox/keyboard.h | 32 +++ openbox/keytree.c | 112 ++++++++ openbox/keytree.h | 25 ++ openbox/menu.c | 4 +- openbox/menu.h | 4 +- {plugins/mouse => openbox}/mouse.c | 284 +++++++------------ openbox/mouse.h | 28 ++ openbox/openbox.c | 6 + openbox/plugin.c | 2 - openbox/screen.c | 277 ++++++++++++++++--- openbox/screen.h | 3 + {plugins/mouse => openbox}/translate.c | 44 +++ openbox/translate.h | 9 + plugins/menu/client_menu.c | 2 +- plugins/mouse/.cvsignore | 6 - plugins/mouse/Makefile | 4 - plugins/mouse/mouse.h | 24 -- plugins/mouse/translate.h | 8 - 29 files changed, 1343 insertions(+), 515 deletions(-) create mode 100644 openbox/keyboard.c create mode 100644 openbox/keyboard.h create mode 100644 openbox/keytree.c create mode 100644 openbox/keytree.h rename {plugins/mouse => openbox}/mouse.c (50%) create mode 100644 openbox/mouse.h rename {plugins/mouse => openbox}/translate.c (67%) create mode 100644 openbox/translate.h delete mode 100644 plugins/mouse/.cvsignore delete mode 100644 plugins/mouse/Makefile delete mode 100644 plugins/mouse/mouse.h delete mode 100644 plugins/mouse/translate.h diff --git a/ChangeLog b/ChangeLog index 703f5ff4..c4b7c2ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,64 @@ +2003-08-12 xor@zed.orodu.net + + * 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 + + * 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 + + * 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 + + * framerender.c: + clear the window after setting the background color, this isnt implicit + +2003-08-09 xor@zed.orodu.net + + * 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 + + * event.c: + Fix lock up when not using a session manager and doing fd management. + +2003-08-05 xor@zed.orodu.net + + * 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 + + * 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 * data/rc3, kernel/client.c, kernel/config.c, kernel/config.h, kernel/moveresize.c: diff --git a/Makefile.am b/Makefile.am index 3cca337e..cb82d10f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 = \ diff --git a/openbox/.cvsignore b/openbox/.cvsignore index e982b462..ab5b29ab 100644 --- a/openbox/.cvsignore +++ b/openbox/.cvsignore @@ -29,3 +29,6 @@ xerror.lo .deps openbox .dirstamp +keyboard.lo +mouse.lo +keytree.lo diff --git a/openbox/action.c b/openbox/action.c index d59c5514..275ba96a 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -16,18 +16,18 @@ 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) { diff --git a/openbox/action.h b/openbox/action.h index 3abf7f2b..3ac3ee67 100644 --- a/openbox/action.h +++ b/openbox/action.h @@ -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 */ diff --git a/openbox/client.c b/openbox/client.c index 191fa994..b5e2a3cf 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -18,6 +18,8 @@ #include "group.h" #include "config.h" #include "menu.h" +#include "keyboard.h" +#include "mouse.h" #include "render/render.h" #include @@ -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 diff --git a/openbox/config.c b/openbox/config.c index 1ffc155a..5444e013 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -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; + +/* + + + + 3 + + + +*/ + +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; +/* + + + + + + + +*/ + +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() diff --git a/openbox/config.h b/openbox/config.h index d10617d0..413ff184 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -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(); diff --git a/openbox/event.c b/openbox/event.c index b5e15a3c..97f01fb6 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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); diff --git a/openbox/focus.c b/openbox/focus.c index 1642261d..9949dea3 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -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 index 00000000..607941dd --- /dev/null +++ b/openbox/keyboard.c @@ -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 + +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 index 00000000..aa171221 --- /dev/null +++ b/openbox/keyboard.h @@ -0,0 +1,32 @@ +#ifndef ob__keybaord_h +#define ob__keybaord_h + +#include "keytree.h" +#include "frame.h" + +#include +#include + +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 index 00000000..9aa2ea95 --- /dev/null +++ b/openbox/keytree.c @@ -0,0 +1,112 @@ +#include "keyboard.h" +#include "translate.h" +#include + +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 index 00000000..0c61e478 --- /dev/null +++ b/openbox/keytree.h @@ -0,0 +1,25 @@ +#ifndef __plugin_keyboard_tree_h +#define __plugin_keyboard_tree_h + +#include "action.h" + +#include + +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 diff --git a/openbox/menu.c b/openbox/menu.c index 00a2bc2b..0f2eff42 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -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) { diff --git a/openbox/menu.h b/openbox/menu.h index 3b7c1c38..2ecbb5cd 100644 --- a/openbox/menu.h +++ b/openbox/menu.h @@ -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); diff --git a/plugins/mouse/mouse.c b/openbox/mouse.c similarity index 50% rename from plugins/mouse/mouse.c rename to openbox/mouse.c index 913a2e4a..ac0fb1d2 100644 --- a/plugins/mouse/mouse.c +++ b/openbox/mouse.c @@ -1,112 +1,26 @@ -#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 -static int threshold; -static int dclicktime; -/* - - - - - - - -*/ - -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 index 00000000..a5e8f9a8 --- /dev/null +++ b/openbox/mouse.h @@ -0,0 +1,28 @@ +#ifndef ob__mouse_h +#define ob__mouse_h + +#include "action.h" +#include "frame.h" + +#include + +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 diff --git a/openbox/openbox.c b/openbox/openbox.c index 7f141d6f..631395cc 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -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(); diff --git a/openbox/plugin.c b/openbox/plugin.c index cd17d215..e95d03e9 100644 --- a/openbox/plugin.c +++ b/openbox/plugin.c @@ -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"); diff --git a/openbox/screen.c b/openbox/screen.c index 4f9e6a2c..6c9042a9 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -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 # include #endif +#include /*! 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; diff --git a/openbox/screen.h b/openbox/screen.h index 1c687036..696423e2 100644 --- a/openbox/screen.h +++ b/openbox/screen.h @@ -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. */ diff --git a/plugins/mouse/translate.c b/openbox/translate.c similarity index 67% rename from plugins/mouse/translate.c rename to openbox/translate.c index aebe5557..9b4c1406 100644 --- a/plugins/mouse/translate.c +++ b/openbox/translate.c @@ -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 index 00000000..5afab50f --- /dev/null +++ b/openbox/translate.h @@ -0,0 +1,9 @@ +#ifndef ob__translate_h +#define ob__translate_h + +#include + +gboolean translate_button(gchar *str, guint *state, guint *keycode); +gboolean translate_key(gchar *str, guint *state, guint *keycode); + +#endif diff --git a/plugins/menu/client_menu.c b/plugins/menu/client_menu.c index a13d3f38..c45d2a43 100644 --- a/plugins/menu/client_menu.c +++ b/plugins/menu/client_menu.c @@ -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 index 9d1b8607..00000000 --- a/plugins/mouse/.cvsignore +++ /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 index cfc46539..00000000 --- a/plugins/mouse/Makefile +++ /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 index 408ae964..00000000 --- a/plugins/mouse/mouse.h +++ /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 index a2fcfc90..00000000 --- a/plugins/mouse/translate.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __plugin_mouse_translate_h -#define __plugin_mouse_translate_h - -#include - -gboolean translate_button(char *str, guint *state, guint *keycode); - -#endif -- 2.44.0