From 5a7953b36aa0e23ae21f707d9fb8b6b9e882946d Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 19 May 2003 03:52:25 +0000 Subject: [PATCH] 2 in 1 again.. a) directional focus actions b) action system changes i.e. use structs/arrays for convertings strings to actions instead of gross if-else chains --- openbox/action.c | 625 +++++++++++++++++++++++++++++++++++------------ openbox/action.h | 9 + openbox/client.c | 95 +++++++ openbox/client.h | 14 ++ 4 files changed, 592 insertions(+), 151 deletions(-) diff --git a/openbox/action.c b/openbox/action.c index 6206ccf4..9aeeff58 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -12,6 +12,12 @@ #include +typedef struct ActionString { + char *name; + void (*func)(union ActionData *); + void (*setup)(Action *); +} ActionString; + Action *action_new(void (*func)(union ActionData *data)) { Action *a = g_new0(Action, 1); @@ -33,160 +39,468 @@ void action_free(Action *a) g_free(a); } +void setup_action_directional_focus_north(Action *a) +{ + a->data.dfocus.direction = Direction_North; +} + +void setup_action_directional_focus_east(Action *a) +{ + a->data.dfocus.direction = Direction_East; +} + +void setup_action_directional_focus_south(Action *a) +{ + a->data.dfocus.direction = Direction_South; +} + +void setup_action_directional_focus_west(Action *a) +{ + a->data.dfocus.direction = Direction_West; +} + +void setup_action_directional_focus_northeast(Action *a) +{ + a->data.dfocus.direction = Direction_NorthEast; +} + +void setup_action_directional_focus_southeast(Action *a) +{ + a->data.dfocus.direction = Direction_SouthEast; +} + +void setup_action_directional_focus_southwest(Action *a) +{ + a->data.dfocus.direction = Direction_SouthWest; +} + +void setup_action_directional_focus_northwest(Action *a) +{ + a->data.dfocus.direction = Direction_NorthWest; +} + +void setup_action_send_to_desktop(Action *a) +{ + a->data.sendto.follow = TRUE; +} + +void setup_action_send_to_np_desktop(Action *a) +{ + a->data.sendtonextprev.wrap = FALSE; + a->data.sendtonextprev.follow = TRUE; +} + +void setup_action_send_to_np_desktop_wrap(Action *a) +{ + a->data.sendtonextprev.wrap = TRUE; + a->data.sendtonextprev.follow = TRUE; +} + +void setup_action_np_desktop(Action *a) +{ + a->data.nextprevdesktop.wrap = FALSE; +} + +void setup_action_np_desktop_wrap(Action *a) +{ + a->data.nextprevdesktop.wrap = TRUE; +} + +void setup_action_move_keyboard(Action *a) +{ + a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard; +} + +void setup_action_move(Action *a) +{ + a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move; +} + +void setup_action_resize(Action *a) +{ + a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft; +} + +void setup_action_resize_keyboard(Action *a) +{ + a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard; +} + +void setup_action_cycle_windows_linear_next(Action *a) +{ + a->data.cycle.linear = TRUE; + a->data.cycle.forward = TRUE; +} + +void setup_action_cycle_windows_linear_previous(Action *a) +{ + a->data.cycle.linear = TRUE; + a->data.cycle.forward = FALSE; +} + +void setup_action_cycle_windows_next(Action *a) +{ + a->data.cycle.linear = FALSE; + a->data.cycle.forward = TRUE; +} + +void setup_action_cycle_windows_previous(Action *a) +{ + a->data.cycle.linear = FALSE; + a->data.cycle.forward = FALSE; +} + +ActionString actionstrings[] = +{ + { + "execute", + action_execute, + NULL + }, + { + "directionalfocusnorth", + action_directional_focus, + setup_action_directional_focus_north + }, + { + "directionalfocuseast", + action_directional_focus, + setup_action_directional_focus_east + }, + { + "directionalfocussouth", + action_directional_focus, + setup_action_directional_focus_south + }, + { + "directionalfocuswest", + action_directional_focus, + setup_action_directional_focus_west + }, + { + "directionalfocusnortheast", + action_directional_focus, + setup_action_directional_focus_northeast + }, + { + "directionalfocussoutheast", + action_directional_focus, + setup_action_directional_focus_southeast + }, + { + "directionalfocussouthwest", + action_directional_focus, + setup_action_directional_focus_southwest + }, + { + "directionalfocusnorthwest", + action_directional_focus, + setup_action_directional_focus_northwest + }, + { + "focus", + action_focus, + NULL, + }, + { + "unfocus", + action_unfocus, + NULL + }, + { + "iconify", + action_iconify, + NULL + }, + { + "raise", + action_raise, + NULL + }, + { + "lower", + action_lower, + NULL + }, + { + "focusraise", + action_focusraise, + NULL + }, + { + "close", + action_close, + NULL + }, + { + "kill", + action_kill, + NULL + }, + { + "shadelower", + action_shadelower, + NULL + }, + { + "unshaderaise", + action_unshaderaise, + NULL + }, + { + "shade", + action_shade, + NULL + }, + { + "unshade", + action_unshade, + NULL + }, + { + "toggleshade", + action_toggle_shade, + NULL + }, + { + "toggleomnipresent", + action_toggle_omnipresent, + NULL + }, + { + "moverelativehorz", + action_move_relative_horz, + NULL + }, + { + "moverelativevert", + action_move_relative_vert, + NULL + }, + { + "resizerelativehorz", + action_resize_relative_horz, + NULL + }, + { + "resizerelativevert", + action_resize_relative_vert, + NULL + }, + { + "maximizefull", + action_maximize_full, + NULL + }, + { + "unmaximizefull", + action_unmaximize_full, + NULL + }, + { + "togglemaximizefull", + action_toggle_maximize_full, + NULL + }, + { + "maximizehorz", + action_maximize_horz, + NULL + }, + { + "unmaximizehorz", + action_unmaximize_horz, + NULL + }, + { + "togglemaximizehorz", + action_toggle_maximize_horz, + NULL + }, + { + "maximizevert", + action_maximize_vert, + NULL + }, + { + "unmaximizevert", + action_unmaximize_vert, + NULL + }, + { + "togglemaximizevert", + action_toggle_maximize_vert, + NULL + }, + { + "sendtodesktop", + action_send_to_desktop, + setup_action_send_to_desktop + }, + { + "sendtonextdesktop", + action_send_to_next_desktop, + setup_action_send_to_np_desktop + }, + { + "sendtonextdesktopwrap", + action_send_to_next_desktop, + setup_action_send_to_np_desktop_wrap + }, + { + "sendtopreviousdesktop", + action_send_to_previous_desktop, + setup_action_send_to_np_desktop + }, + { + "sendtopreviousdesktopwrap", + action_send_to_previous_desktop, + setup_action_send_to_np_desktop_wrap + }, + { + "desktop", + action_desktop, + NULL + }, + { + "nextdesktop", + action_next_desktop, + setup_action_np_desktop + }, + { + "nextdesktopwrap", + action_next_desktop, + setup_action_np_desktop_wrap + }, + { + "previousdesktop", + action_previous_desktop, + setup_action_np_desktop + }, + { + "previousdesktopwrap", + action_previous_desktop, + setup_action_np_desktop_wrap + }, + { + "nextdesktopcolumn", + action_next_desktop_column, + setup_action_np_desktop + }, + { + "nextdesktopcolumnwrap", + action_next_desktop_column, + setup_action_np_desktop_wrap + }, + { + "previousdesktopcolumn", + action_previous_desktop_column, + setup_action_np_desktop + }, + { + "previousdesktopcolumnwrap", + action_previous_desktop_column, + setup_action_np_desktop_wrap + }, + { + "nextdesktoprow", + action_next_desktop_row, + setup_action_np_desktop + }, + { + "nextdesktoprowwrap", + action_next_desktop_row, + setup_action_np_desktop_wrap + }, + { + "previousdesktoprow", + action_previous_desktop_row, + setup_action_np_desktop + }, + { + "previousdesktoprowwrap", + action_previous_desktop_row, + setup_action_np_desktop_wrap + }, + { + "toggledecorations", + action_toggle_decorations, + NULL + }, + { + "keyboardmove", + action_moveresize, + setup_action_move_keyboard + }, + { + "move", + action_moveresize, + setup_action_move + }, + { + "resize", + action_moveresize, + setup_action_resize + }, + { + "keyboardresize", + action_moveresize, + setup_action_resize_keyboard + }, + { + "restart", + action_restart, + NULL + }, + { + "exit", + action_exit, + NULL + }, + { + "showmenu", + action_showmenu, + NULL + }, + { + "nextwindowlinear", + action_cycle_windows, + setup_action_cycle_windows_linear_next + }, + { + "previouswindowlinear", + action_cycle_windows, + setup_action_cycle_windows_linear_previous + }, + { + "nextwindow", + action_cycle_windows, + setup_action_cycle_windows_next + }, + { + "previouswindow", + action_cycle_windows, + setup_action_cycle_windows_previous + }, + { + NULL, + NULL, + NULL + } +}; + Action *action_from_string(char *name) { Action *a = NULL; - if (!g_ascii_strcasecmp(name, "execute")) { - a = action_new(action_execute); - } else if (!g_ascii_strcasecmp(name, "focus")) { - a = action_new(action_focus); - } else if (!g_ascii_strcasecmp(name, "unfocus")) { - a = action_new(action_unfocus); - } else if (!g_ascii_strcasecmp(name, "iconify")) { - a = action_new(action_iconify); - } else if (!g_ascii_strcasecmp(name, "raise")) { - a = action_new(action_raise); - } else if (!g_ascii_strcasecmp(name, "lower")) { - a = action_new(action_lower); - } else if (!g_ascii_strcasecmp(name, "focusraise")) { - a = action_new(action_focusraise); - } else if (!g_ascii_strcasecmp(name, "close")) { - a = action_new(action_close); - } else if (!g_ascii_strcasecmp(name, "kill")) { - a = action_new(action_kill); - } else if (!g_ascii_strcasecmp(name, "shadelower")) { - a = action_new(action_shadelower); - } else if (!g_ascii_strcasecmp(name, "unshaderaise")) { - a = action_new(action_unshaderaise); - } else if (!g_ascii_strcasecmp(name, "shade")) { - a = action_new(action_shade); - } else if (!g_ascii_strcasecmp(name, "unshade")) { - a = action_new(action_unshade); - } else if (!g_ascii_strcasecmp(name, "toggleshade")) { - a = action_new(action_toggle_shade); - } else if (!g_ascii_strcasecmp(name, "toggleomnipresent")) { - a = action_new(action_toggle_omnipresent); - } else if (!g_ascii_strcasecmp(name, "moverelativehorz")) { - a = action_new(action_move_relative_horz); - } else if (!g_ascii_strcasecmp(name, "moverelativevert")) { - a = action_new(action_move_relative_vert); - } else if (!g_ascii_strcasecmp(name, "resizerelativehorz")) { - a = action_new(action_resize_relative_horz); - } else if (!g_ascii_strcasecmp(name, "resizerelativevert")) { - a = action_new(action_resize_relative_vert); - } else if (!g_ascii_strcasecmp(name, "maximizefull")) { - a = action_new(action_maximize_full); - } else if (!g_ascii_strcasecmp(name, "unmaximizefull")) { - a = action_new(action_unmaximize_full); - } else if (!g_ascii_strcasecmp(name, "togglemaximizefull")) { - a = action_new(action_toggle_maximize_full); - } else if (!g_ascii_strcasecmp(name, "maximizehorz")) { - a = action_new(action_maximize_horz); - } else if (!g_ascii_strcasecmp(name, "unmaximizehorz")) { - a = action_new(action_unmaximize_horz); - } else if (!g_ascii_strcasecmp(name, "togglemaximizehorz")) { - a = action_new(action_toggle_maximize_horz); - } else if (!g_ascii_strcasecmp(name, "maximizevert")) { - a = action_new(action_maximize_vert); - } else if (!g_ascii_strcasecmp(name, "unmaximizevert")) { - a = action_new(action_unmaximize_vert); - } else if (!g_ascii_strcasecmp(name, "togglemaximizevert")) { - a = action_new(action_toggle_maximize_vert); - } else if (!g_ascii_strcasecmp(name, "sendtodesktop")) { - a = action_new(action_send_to_desktop); - a->data.sendto.follow = TRUE; - } else if (!g_ascii_strcasecmp(name, "sendtonextdesktop")) { - a = action_new(action_send_to_next_desktop); - a->data.sendtonextprev.wrap = FALSE; - a->data.sendtonextprev.follow = TRUE; - } else if (!g_ascii_strcasecmp(name, "sendtonextdesktopwrap")) { - a = action_new(action_send_to_next_desktop); - a->data.sendtonextprev.wrap = TRUE; - a->data.sendtonextprev.follow = TRUE; - } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktop")) { - a = action_new(action_send_to_previous_desktop); - a->data.sendtonextprev.wrap = FALSE; - a->data.sendtonextprev.follow = TRUE; - } else if (!g_ascii_strcasecmp(name, "sendtopreviousdesktopwrap")) { - a = action_new(action_send_to_previous_desktop); - a->data.sendtonextprev.wrap = TRUE; - a->data.sendtonextprev.follow = TRUE; - } else if (!g_ascii_strcasecmp(name, "desktop")) { - a = action_new(action_desktop); - } else if (!g_ascii_strcasecmp(name, "nextdesktop")) { - a = action_new(action_next_desktop); - a->data.nextprevdesktop.wrap = FALSE; - } else if (!g_ascii_strcasecmp(name, "nextdesktopwrap")) { - a = action_new(action_next_desktop); - a->data.nextprevdesktop.wrap = TRUE; - } else if (!g_ascii_strcasecmp(name, "previousdesktop")) { - a = action_new(action_previous_desktop); - a->data.nextprevdesktop.wrap = FALSE; - } else if (!g_ascii_strcasecmp(name, "previousdesktopwrap")) { - a = action_new(action_previous_desktop); - a->data.nextprevdesktop.wrap = TRUE; - } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumn")) { - a = action_new(action_next_desktop_column); - a->data.nextprevdesktop.wrap = FALSE; - } else if (!g_ascii_strcasecmp(name, "nextdesktopcolumnwrap")) { - a = action_new(action_next_desktop_column); - a->data.nextprevdesktop.wrap = TRUE; - } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumn")) { - a = action_new(action_previous_desktop_column); - a->data.nextprevdesktop.wrap = FALSE; - } else if (!g_ascii_strcasecmp(name, "previousdesktopcolumnwrap")) { - a = action_new(action_previous_desktop_column); - a->data.nextprevdesktop.wrap = TRUE; - } else if (!g_ascii_strcasecmp(name, "nextdesktoprow")) { - a = action_new(action_next_desktop_row); - a->data.nextprevdesktop.wrap = FALSE; - } else if (!g_ascii_strcasecmp(name, "nextdesktoprowwrap")) { - a = action_new(action_next_desktop_row); - a->data.nextprevdesktop.wrap = TRUE; - } else if (!g_ascii_strcasecmp(name, "previousdesktoprow")) { - a = action_new(action_previous_desktop_row); - a->data.nextprevdesktop.wrap = FALSE; - } else if (!g_ascii_strcasecmp(name, "previousdesktoprowwrap")) { - a = action_new(action_previous_desktop_row); - a->data.nextprevdesktop.wrap = TRUE; - } else if (!g_ascii_strcasecmp(name, "toggledecorations")) { - a = action_new(action_toggle_decorations); - } else if (!g_ascii_strcasecmp(name, "keyboardmove")) { - a = action_new(action_moveresize); - a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard; - } else if (!g_ascii_strcasecmp(name, "move")) { - a = action_new(action_moveresize); - a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move; - } else if (!g_ascii_strcasecmp(name, "resize")) { - a = action_new(action_moveresize); - a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft; - } else if (!g_ascii_strcasecmp(name, "keyboardresize")) { - a = action_new(action_moveresize); - a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard; - } else if (!g_ascii_strcasecmp(name, "restart")) { - a = action_new(action_restart); - } else if (!g_ascii_strcasecmp(name, "exit")) { - a = action_new(action_exit); - } else if (!g_ascii_strcasecmp(name, "showmenu")) { - a = action_new(action_showmenu); - } else if (!g_ascii_strcasecmp(name, "nextwindowlinear")) { - a = action_new(action_cycle_windows); - a->data.cycle.linear = TRUE; - a->data.cycle.forward = TRUE; - } else if (!g_ascii_strcasecmp(name, "previouswindowlinear")) { - a = action_new(action_cycle_windows); - a->data.cycle.linear = TRUE; - a->data.cycle.forward = FALSE; - } else if (!g_ascii_strcasecmp(name, "nextwindow")) { - a = action_new(action_cycle_windows); - a->data.cycle.linear = FALSE; - a->data.cycle.forward = TRUE; - } else if (!g_ascii_strcasecmp(name, "previouswindow")) { - a = action_new(action_cycle_windows); - a->data.cycle.linear = FALSE; - a->data.cycle.forward = FALSE; - } - + int i; + + for (i = 0; actionstrings[i].name; i++) + if (!g_ascii_strcasecmp(name, actionstrings[i].name)) { + a = action_new(actionstrings[i].func); + if (actionstrings[i].setup) + actionstrings[i].setup(a); + break; + } return a; } @@ -689,3 +1003,12 @@ void action_cycle_windows(union ActionData *data) data->cycle.cancel); } +void action_directional_focus(union ActionData *data) +{ + Client *nf; + + if (!data->dfocus.c) + return; + if ((nf = client_find_directional(data->dfocus.c, data->dfocus.direction))) + client_activate(nf); +} diff --git a/openbox/action.h b/openbox/action.h index 6e0b6c52..e0ea0d56 100644 --- a/openbox/action.h +++ b/openbox/action.h @@ -12,6 +12,11 @@ struct AnyAction { Client *c; }; +struct DirectionalFocus { + Client *c; + int direction; +}; + struct Execute { Client *c; char *path; @@ -73,6 +78,7 @@ struct CycleWindows { union ActionData { struct AnyAction any; + struct DirectionalFocus dfocus; struct Execute execute; struct ClientAction client; struct MoveResizeRelative relative; @@ -106,6 +112,7 @@ Action *action_new(void (*func)(union ActionData *data)); action_resize_relative_horz - the delta action_resize_relative_vert - the delta */ + Action *action_from_string(char *name); void action_free(Action *a); @@ -197,4 +204,6 @@ void action_exit(union ActionData *data); void action_showmenu(union ActionData *data); /* CycleWindows */ void action_cycle_windows(union ActionData *data); + +void action_directional_focus(union ActionData *data); #endif diff --git a/openbox/client.c b/openbox/client.c index 8efed96a..75a3bc25 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -2344,3 +2344,98 @@ Icon *client_icon(Client *self, int w, int h) return &self->icons[si]; return &self->icons[li]; } + +/* this be mostly ripped from fvwm */ +Client *client_find_directional(Client *c, Direction dir) +{ + int my_cx, my_cy, his_cx, his_cy; + int offset = 0; + int distance = 0; + int score, best_score; + Client *best_client, *cur; + GList *it; + + if(!client_list) + return NULL; + + /* first, find the centre coords of the currently focused window */ + my_cx = c->frame->area.x + c->frame->area.width / 2; + my_cy = c->frame->area.y + c->frame->area.height / 2; + + best_score = -1; + best_client = NULL; + + for(it = g_list_first(client_list); it; it = it->next) { + cur = it->data; + + /* the currently selected window isn't interesting */ + if(cur == c) + continue; + if (!client_normal(cur)) + continue; + if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + continue; + if(cur->iconic) + continue; + if(client_focus_target(cur) == cur && + !(cur->can_focus || cur->focus_notify)) + continue; + + /* find the centre coords of this window, from the + * currently focused window's point of view */ + his_cx = (cur->frame->area.x - my_cx) + + cur->frame->area.width / 2; + his_cy = (cur->frame->area.y - my_cy) + + cur->frame->area.height / 2; + + if(dir > 3) { + int tx; + /* Rotate the diagonals 45 degrees counterclockwise. + * To do this, multiply the matrix /+h +h\ with the + * vector (x y). \-h +h/ + * h = sqrt(0.5). We can set h := 1 since absolute + * distance doesn't matter here. */ + tx = his_cx + his_cy; + his_cy = -his_cx + his_cy; + his_cx = tx; + } + + switch(dir) { + case Direction_North : + case Direction_South : + case Direction_NorthEast : + case Direction_SouthWest : + offset = (his_cx < 0) ? -his_cx : his_cx; + distance = (dir == Direction_North || dir == Direction_NorthEast) ? + -his_cy : his_cy; + break; + case Direction_East : + case Direction_West : + case Direction_SouthEast : + case Direction_NorthWest : + offset = (his_cy < 0) ? -his_cy : his_cy; + distance = (dir == Direction_West || dir == Direction_NorthWest) ? + -his_cx : his_cx; + break; + } + + /* the target must be in the requested direction */ + if(distance <= 0) + continue; + + /* Calculate score for this window. The smaller the better. */ + score = distance + offset; + + /* windows more than 45 degrees off the direction are + * heavily penalized and will only be chosen if nothing + * else within a million pixels */ + if(offset > distance) + score += 1000000; + + if(best_score == -1 || score < best_score) + best_client = cur, + best_score = score; + } + + return best_client; +} diff --git a/openbox/client.h b/openbox/client.h index b4e0494d..ca410558 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -110,6 +110,17 @@ typedef enum { Decor_Close = 1 << 8 /*!< Display a close button */ } Decoration; +/*! The directions used by client_find_directional */ +typedef enum { + Direction_North, + Direction_East, + Direction_South, + Direction_West, + Direction_NorthEast, + Direction_SouthEast, + Direction_SouthWest, + Direction_NorthWest +} Direction; typedef struct Client { ObWindow obwin; @@ -483,4 +494,7 @@ Client *client_search_focus_tree_full(Client *self); */ Client *client_search_modal_child(Client *self); +/*! Return the "closest" client in the given direction */ +Client *client_find_directional(Client *c, Direction dir); + #endif -- 2.45.2