X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Factions%2Fdesktop.c;h=8dadf550af3b2ea2787015be50528e48ce8c7a2d;hb=be9637e40317eb36e5a5357d3f58e3af21c81df4;hp=6da47740c9800b60faa6e71f31a02e2eb05c5f77;hpb=4044b942e74b59599e82bb4834a730c32e49820d;p=chaz%2Fopenbox diff --git a/openbox/actions/desktop.c b/openbox/actions/desktop.c index 6da47740..8dadf550 100644 --- a/openbox/actions/desktop.c +++ b/openbox/actions/desktop.c @@ -1,63 +1,569 @@ #include "openbox/actions.h" #include "openbox/screen.h" -#include +#include "openbox/client.h" +#include "openbox/openbox.h" +#include "obt/keyboard.h" + +typedef enum { + LAST, + CURRENT, + RELATIVE, + ABSOLUTE +} SwitchType; typedef struct { - gboolean last; - guint desktop; + SwitchType type; + union { + struct { + guint desktop; + } abs; + + struct { + gboolean linear; + gboolean wrap; + ObDirection dir; + } rel; + } u; + gboolean send; + gboolean follow; + gboolean interactive; } Options; -static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); -static void free_func(gpointer options); +static gpointer setup_go_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static void free_func(gpointer o); static gboolean run_func(ObActionsData *data, gpointer options); -void action_desktop_startup() +static gboolean i_pre_func(guint state, gpointer options); +static gboolean i_input_func(guint initial_state, + XEvent *e, + ObtIC *ic, + gpointer options, + gboolean *used); +static void i_post_func(gpointer options); + +/* 3.4-compatibility */ +static gpointer setup_go_last_func(xmlNodePtr node); +static gpointer setup_send_last_func(xmlNodePtr node); +static gpointer setup_go_abs_func(xmlNodePtr node); +static gpointer setup_go_next_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_next_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_go_prev_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_prev_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_go_left_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_left_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_go_right_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_right_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_go_up_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_up_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_go_down_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); +static gpointer setup_send_down_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post); + +void action_desktop_startup(void) { - actions_register("Desktop", - setup_func, - free_func, - run_func, - NULL, NULL); + actions_register_i("GoToDesktop", setup_go_func, free_func, run_func); + actions_register_i("SendToDesktop", setup_send_func, free_func, run_func); + /* 3.4-compatibility */ + actions_register("DesktopLast", setup_go_last_func, free_func, run_func); + actions_register("SendToDesktopLast", setup_send_last_func, + free_func, run_func); + actions_register("Desktop", setup_go_abs_func, free_func, run_func); + actions_register_i("DesktopNext", setup_go_next_func, free_func, run_func); + actions_register_i("SendToDesktopNext", setup_send_next_func, + free_func, run_func); + actions_register_i("DesktopPrevious", setup_go_prev_func, + free_func, run_func); + actions_register_i("SendToDesktopPrevious", setup_send_prev_func, + free_func, run_func); + actions_register_i("DesktopLeft", setup_go_left_func, free_func, run_func); + actions_register_i("SendToDesktopLeft", setup_send_left_func, + free_func, run_func); + actions_register_i("DesktopRight", setup_go_right_func, + free_func, run_func); + actions_register_i("SendToDesktopRight", setup_send_right_func, + free_func, run_func); + actions_register_i("DesktopUp", setup_go_up_func, free_func, run_func); + actions_register_i("SendToDesktopUp", setup_send_up_func, + free_func, run_func); + actions_register_i("DesktopDown", setup_go_down_func, free_func, run_func); + actions_register_i("SendToDesktopDown", setup_send_down_func, + free_func, run_func); } -static gpointer setup_func(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) +static gpointer setup_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) { xmlNodePtr n; Options *o; - o = g_new0(Options, 1); + o = g_slice_new0(Options); + /* don't go anywhere if there are no options given */ + o->type = ABSOLUTE; + o->u.abs.desktop = screen_desktop; + /* wrap by default - it's handy! */ + o->u.rel.wrap = TRUE; - if ((n = parse_find_node("desktop", node))) { - gchar *s = parse_string(doc, n); + if ((n = obt_xml_find_node(node, "to"))) { + gchar *s = obt_xml_node_string(n); if (!g_ascii_strcasecmp(s, "last")) - o->last = TRUE; - else - o->desktop = parse_int(doc, n) - 1; + o->type = LAST; + else if (!g_ascii_strcasecmp(s, "current")) + o->type = CURRENT; + else if (!g_ascii_strcasecmp(s, "next")) { + o->type = RELATIVE; + o->u.rel.linear = TRUE; + o->u.rel.dir = OB_DIRECTION_EAST; + } + else if (!g_ascii_strcasecmp(s, "previous")) { + o->type = RELATIVE; + o->u.rel.linear = TRUE; + o->u.rel.dir = OB_DIRECTION_WEST; + } + else if (!g_ascii_strcasecmp(s, "north") || + !g_ascii_strcasecmp(s, "up")) { + o->type = RELATIVE; + o->u.rel.dir = OB_DIRECTION_NORTH; + } + else if (!g_ascii_strcasecmp(s, "south") || + !g_ascii_strcasecmp(s, "down")) { + o->type = RELATIVE; + o->u.rel.dir = OB_DIRECTION_SOUTH; + } + else if (!g_ascii_strcasecmp(s, "west") || + !g_ascii_strcasecmp(s, "left")) { + o->type = RELATIVE; + o->u.rel.dir = OB_DIRECTION_WEST; + } + else if (!g_ascii_strcasecmp(s, "east") || + !g_ascii_strcasecmp(s, "right")) { + o->type = RELATIVE; + o->u.rel.dir = OB_DIRECTION_EAST; + } + else { + o->type = ABSOLUTE; + o->u.abs.desktop = atoi(s) - 1; + } g_free(s); } + + if ((n = obt_xml_find_node(node, "wrap"))) + o->u.rel.wrap = obt_xml_node_bool(n); + return o; } -static void free_func(gpointer options) + +static gpointer setup_go_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) { - Options *o = options; + Options *o; + + o = setup_func(node, pre, input, cancel, post); + if (o->type == RELATIVE) { + o->interactive = TRUE; + *pre = i_pre_func; + *input = i_input_func; + *post = i_post_func; + } + + return o; +} + +static gpointer setup_send_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + xmlNodePtr n; + Options *o; + + o = setup_func(node, pre, input, cancel, post); + if ((n = obt_xml_find_node(node, "desktop"))) { + /* 3.4 compatibility */ + o->u.abs.desktop = obt_xml_node_int(n) - 1; + o->type = ABSOLUTE; + } + o->send = TRUE; + o->follow = TRUE; + + if ((n = obt_xml_find_node(node, "follow"))) + o->follow = obt_xml_node_bool(n); + + if (o->type == RELATIVE && o->follow) { + o->interactive = TRUE; + *pre = i_pre_func; + *input = i_input_func; + *post = i_post_func; + } + + return o; +} - g_free(o); +static void free_func(gpointer o) +{ + g_slice_free(Options, o); } -/* Always return FALSE because its not interactive */ static gboolean run_func(ObActionsData *data, gpointer options) { Options *o = options; guint d; - if (o->last) + switch (o->type) { + case LAST: d = screen_last_desktop; + break; + case CURRENT: + d = screen_desktop; + break; + case ABSOLUTE: + d = o->u.abs.desktop; + break; + case RELATIVE: + d = screen_find_desktop(screen_desktop, + o->u.rel.dir, o->u.rel.wrap, o->u.rel.linear); + break; + default: + g_assert_not_reached(); + } + + if (d < screen_num_desktops && + (d != screen_desktop || + (data->client && data->client->desktop != screen_desktop))) { + gboolean go = TRUE; + + actions_client_move(data, TRUE); + if (o->send && data->client && client_normal(data->client)) { + client_set_desktop(data->client, d, o->follow, FALSE); + go = o->follow; + } + + if (go) { + screen_set_desktop(d, TRUE); + if (data->client) + client_bring_helper_windows(data->client); + } + + actions_client_move(data, FALSE); + } + + return o->interactive; +} + +static gboolean i_input_func(guint initial_state, + XEvent *e, + ObtIC *ic, + gpointer options, + gboolean *used) +{ + guint mods, initial_mods; + + initial_mods = obt_keyboard_only_modmasks(initial_state); + mods = obt_keyboard_only_modmasks(e->xkey.state); + if (e->type == KeyRelease) { + /* remove from the state the mask of the modifier key being + released, if it is a modifier key being released that is */ + mods &= ~obt_keyboard_keyevent_to_modmask(e); + } + + if (e->type == KeyPress) { + KeySym sym = obt_keyboard_keypress_to_keysym(e); + + /* Escape cancels no matter what */ + if (sym == XK_Escape) + return FALSE; + + /* There were no modifiers and they pressed enter */ + else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods) + return FALSE; + } + /* They released the modifiers */ + else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods)) + { + return FALSE; + } + + return TRUE; +} + +static gboolean i_pre_func(guint initial_state, gpointer options) +{ + guint initial_mods = obt_keyboard_only_modmasks(initial_state); + if (!initial_mods) { + Options *o = options; + o->interactive = FALSE; + return FALSE; + } + else { + screen_show_desktop_popup(screen_desktop, TRUE); + return TRUE; + } +} + +static void i_post_func(gpointer options) +{ + screen_hide_desktop_popup(); +} + +/* 3.4-compatilibity */ +static gpointer setup_follow(xmlNodePtr node) +{ + xmlNodePtr n; + Options *o = g_slice_new0(Options); + o->send = TRUE; + o->follow = TRUE; + if ((n = obt_xml_find_node(node, "follow"))) + o->follow = obt_xml_node_bool(n); + return o; +} + +static gpointer setup_go_last_func(xmlNodePtr node) +{ + Options *o = g_slice_new0(Options); + o->type = LAST; + return o; +} + +static gpointer setup_send_last_func(xmlNodePtr node) +{ + Options *o = setup_follow(node); + o->type = LAST; + return o; +} + +static gpointer setup_go_abs_func(xmlNodePtr node) +{ + xmlNodePtr n; + Options *o = g_slice_new0(Options); + o->type = ABSOLUTE; + if ((n = obt_xml_find_node(node, "desktop"))) + o->u.abs.desktop = obt_xml_node_int(n) - 1; else - d = o->desktop; + o->u.abs.desktop = screen_desktop; + return o; +} + +static void setup_rel(Options *o, xmlNodePtr node, gboolean lin, + ObDirection dir, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsIPostFunc *post) +{ + xmlNodePtr n; + + o->type = RELATIVE; + o->u.rel.linear = lin; + o->u.rel.dir = dir; + o->u.rel.wrap = TRUE; + + if ((n = obt_xml_find_node(node, "wrap"))) + o->u.rel.wrap = obt_xml_node_bool(n); + + if (input) { + o->interactive = TRUE; + *pre = i_pre_func; + *input = i_input_func; + *post = i_post_func; + } +} + +static gpointer setup_go_next_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = g_slice_new0(Options); + setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post); + return o; +} + +static gpointer setup_send_next_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = setup_follow(node); + setup_rel(o, node, TRUE, OB_DIRECTION_EAST, + pre, (o->follow ? input : NULL), post); + return o; +} + +static gpointer setup_go_prev_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = g_slice_new0(Options); + setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post); + return o; +} + +static gpointer setup_send_prev_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = setup_follow(node); + setup_rel(o, node, TRUE, OB_DIRECTION_WEST, + pre, (o->follow ? input : NULL), post); + return o; +} + +static gpointer setup_go_left_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = g_slice_new0(Options); + setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post); + return o; +} + +static gpointer setup_send_left_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = setup_follow(node); + setup_rel(o, node, FALSE, OB_DIRECTION_WEST, + pre, (o->follow ? input : NULL), post); + return o; +} - if (d < screen_num_desktops) - screen_set_desktop(d, TRUE); +static gpointer setup_go_right_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = g_slice_new0(Options); + setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post); + return o; +} - return FALSE; +static gpointer setup_send_right_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = setup_follow(node); + setup_rel(o, node, FALSE, OB_DIRECTION_EAST, + pre, (o->follow ? input : NULL), post); + return o; +} + +static gpointer setup_go_up_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = g_slice_new0(Options); + setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post); + return o; +} + +static gpointer setup_send_up_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = setup_follow(node); + setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, + pre, (o->follow ? input : NULL), post); + return o; +} + +static gpointer setup_go_down_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = g_slice_new0(Options); + setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post); + return o; +} + +static gpointer setup_send_down_func(xmlNodePtr node, + ObActionsIPreFunc *pre, + ObActionsIInputFunc *input, + ObActionsICancelFunc *cancel, + ObActionsIPostFunc *post) +{ + Options *o = setup_follow(node); + setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, + pre, (o->follow ? input : NULL), post); + return o; }