Commit bc59846e4a2d90bbb3dfb39153967966e2e7642b Parent: 136ce650d2a24c163a7bd3f41fded1e2e1fcbc03 Author: mcol <mcol@posteo.net> Date: 2021-03-07 16:09:49 +0000 Committer: mcol <mcol@posteo.net> Committed: 2021-03-07 16:09:49 +0000 Use handlers for both client and bound actions This refactors the handling of strings used to specify actions and their arguments, so that that is all contained with parse.c, and actions are (almost) always accessed via the action_map array. This is used for both `bind` actions and direct cli actions.
src/types.h Modified
@@ -193,7 +193,6 @@ enum wlr_keyboard_modifier mods; uint32_t key; action action; - action begin; void *data; }; @@ -237,7 +236,7 @@ struct wlr_box geo; // negative values represent a percentage of the output's geometry }; -struct value_map { +struct dict { const char *name; const int value; };
src/parse.h Modified
@@ -3,10 +3,9 @@ #include "types.h" -int _get(struct value_map *values, const int len, const char *name); +int _get(struct dict *values, const int len, const char *name); #define get(arr, name) _get(arr, sizeof(arr) / sizeof(arr[0]), name) -bool wlr_box_from_str(char* str, struct wlr_box *box); bool dir_handler(void **data, char *args); bool str_handler(void **data, char *args); bool motion_handler(void **data, char *args);
src/parse.c Modified
@@ -6,7 +6,7 @@ /* To get the length of these arrays we need to calculate that before passing * them to the getter so the macro in the header hides this. */ -int _get(struct value_map *values, const int len, const char *name) { +int _get(struct dict *values, const int len, const char *name) { for (int i = 0; i < len; i++) { if (strcasecmp(values[i].name, name) == 0) return values[i].value; @@ -15,7 +15,7 @@ } -bool wlr_box_from_str(char* str, struct wlr_box *box) { +static bool wlr_box_from_str(char* str, struct wlr_box *box) { // turns e.g. 1920x1800+500+500 into a wlr_box char *w, *h, *x, *y; if (str) { @@ -69,7 +69,7 @@ } -static struct value_map dirs[] = { +static struct dict dirs[] = { { "up", UP }, { "right", RIGHT }, { "down", DOWN },
src/keybind.c Modified
@@ -4,7 +4,7 @@ #include "types.h" -static struct value_map mods[] = { +static struct dict mods[] = { { "shift", WLR_MODIFIER_SHIFT }, { "caps", WLR_MODIFIER_CAPS }, { "ctrl", WLR_MODIFIER_CTRL }, @@ -16,7 +16,7 @@ }; -static struct value_map mouse_keys[] = { +static struct dict mouse_keys[] = { { "motion", MOTION }, { "scroll", SCROLL }, { "drag1", DRAG1 }, @@ -26,89 +26,9 @@ }; -static struct { - const char *name; - const action action; - bool (*data_handler)(void **data, char *args); -} action_map[] = { - { "terminate", &terminate, NULL }, - { "exec", &exec_command, &str_handler }, - { "close_window", &close_window, NULL }, - { "move_window", &move_window, NULL }, - { "focus", &focus_in_direction, &dir_handler }, - { "next_desk", &next_desk, NULL }, - { "prev_desk", &prev_desk, NULL }, - { "pan_desk", &pan_desk, &motion_handler }, - { "reset_zoom", &reset_zoom, NULL }, - { "zoom", &zoom, &str_handler }, - { "set_mark", &set_mark, NULL }, - { "go_to_mark", &go_to_mark, NULL }, - { "toggle_fullscreen", &toggle_fullscreen, NULL }, - { "halfimize", &halfimize, &dir_handler }, - { "maximize", &maximize, NULL }, - { "send_to_desk", &send_to_desk, &str_handler }, - { "scratchpad", &toggle_scratchpad, &scratchpad_handler }, - { "to_region", &to_region, &box_handler }, -}; - - -static struct { - const char *name; - const action action; - const action begin; -} pinch_map[] = { - { "zoom", &zoom_pinch, &zoom_pinch_begin }, -}; - - -static struct { - const char *name; - const action action; -} scroll_map[] = { - { "zoom", &zoom_scroll }, - { "pan_desk", &pan_desk }, -}; - - -static bool assign_action(const char *name, char *args, struct binding *kb, char * response) { - kb->action = NULL; - kb->data = NULL; - size_t i; - - switch (kb->key) { - case PINCH: - for (i = 0; i < sizeof(pinch_map) / sizeof(pinch_map[0]); i++) { - if (strcmp(pinch_map[i].name, name) == 0) { - kb->action = pinch_map[i].action; - kb->begin = pinch_map[i].begin; - return true; - } - } - break; - case SCROLL: - for (i = 0; i < sizeof(scroll_map) / sizeof(scroll_map[0]); i++) { - if (strcmp(scroll_map[i].name, name) == 0) { - kb->action = scroll_map[i].action; - return true; - } - } - break; - default: - for (i = 0; i < sizeof(action_map) / sizeof(action_map[0]); i++) { - if (strcmp(action_map[i].name, name) == 0) { - kb->action = action_map[i].action; - if (action_map[i].data_handler != NULL) { - if (!action_map[i].data_handler(&kb->data, args)){ - sprintf(response, "Command malformed/incomplete."); - return false; - } - } - return true; - } - } - } - - return false; +static bool assign_action(char *name, char *args, struct binding *kb, char *response) { + // TODO: remove + return get_action(name, &kb->action, args, &kb->data, response, kb->key); }
src/input.c Modified
@@ -45,7 +45,7 @@ break; case PINCH: wimp.on_pinch = kb->action; - wimp.on_pinch_begin = kb->begin; + wimp.on_pinch_begin = *(action* )kb->data; break; } wimp.cursor_mode = CURSOR_MOD;
src/action.h Modified
@@ -3,30 +3,14 @@ #include "types.h" +bool get_action(char *name, action *action, char *args, void **data, char *response, int flag); bool do_action(char *message, char *response); -void terminate(void *data); -void exec_command(void *data); -void change_vt(void *data); -void close_window(void *data); -void move_window(void *data); -void focus_in_direction(void *data); -void next_desk(void *data); -void prev_desk(void *data); -void pan_desk(void *data); -void reset_zoom(void *data); -void zoom(void *data); -void zoom_scroll(void *data); -void zoom_pinch(void *data); -void zoom_pinch_begin(void *data); -void set_mark(void *data); +void change_vt(void *data); // this action is handled a little differently to the others void actually_set_mark(const xkb_keysym_t sym); -void go_to_mark(void *data); void actually_go_to_mark(void *data); + +// these actions are needed in other files +void pan_desk(void *data); void toggle_fullscreen(void *data); -void halfimize(void *data); -void maximize(void *data); -void send_to_desk(void *data); -void toggle_scratchpad(void *data); -void to_region(void *data); #endif
src/action.c Modified
@@ -8,108 +8,145 @@ #include "cursor.h" #include "desk.h" #include "output.h" +#include "parse.h" #include "scratchpad.h" #include "shell.h" #include "types.h" -bool do_action(char *message, char *response) { - char *s; - bool handled = true; - - if (!strcasecmp(message, "terminate")) { - terminate(NULL); - } - - else if (!strcasecmp(message, "exec")) { - if ((s = strtok(NULL, "\n\r"))) { - exec_command(s); - } - } - - else if (!strcasecmp(message, "change_vt")) { - if ((s = strtok(NULL, " \t\n\r"))) { - int vt = strtod(s, NULL); - if (vt && 0 < vt && vt <= 12) { - change_vt(&vt); - } else { - sprintf(response, "Expected a number from 1 to 12"); - } - } - } - - else if (!strcasecmp(message, "close_window")) { - close_window(NULL); - } - - else if (!strcasecmp(message, "move_window")) { - char *x, *y; - if ( - (x = strtok(NULL, " \t\n\r")) && (y = strtok(NULL, " \t\n\r")) - && is_number_perc(x) && is_number_perc(y) - && (is_number(x) == is_number(y)) - ) { - struct motion motion; - if (is_number(x)) { - motion.dx = atoi(x); - motion.dy = atoi(y); - motion.is_percentage = false; - move_window(&motion); - } else { - if ((x = strtok(x, "%")) && (y = strtok(y, "%"))) { - motion.dx = atoi(x); - motion.dy = atoi(y); - motion.is_percentage = true; - move_window(&motion); - } else { - sprintf(response, "Expected args in the form of 'x y' or 'x%% y%%'"); +static void terminate(void *data); +static void exec_command(void *data); +static void close_window(void *data); +static void move_window(void *data); +static void focus_in_direction(void *data); +static void next_desk(void *data); +static void prev_desk(void *data); +static void reset_zoom(void *data); +static void zoom(void *data); +static void set_mark(void *data); +static void go_to_mark(void *data); +static void halfimize(void *data); +static void maximize(void *data); +static void send_to_desk(void *data); +static void toggle_scratchpad(void *data); +static void to_region(void *data); +static void zoom_pinch(void *data); +static void zoom_pinch_begin(void *data); +static void zoom_scroll(void *data); + + +static struct { + const char *name; + const action action; + const action begin; +} pinch_map[] = { + { "zoom", &zoom_pinch, &zoom_pinch_begin }, +}; + + +static struct { + const char *name; + const action action; +} scroll_map[] = { + { "zoom", &zoom_scroll }, + { "pan_desk", &pan_desk }, +}; + + +static struct { + const char *name; + const action action; + bool (*data_handler)(void **data, char *args); +} action_map[] = { + { "terminate", &terminate, NULL }, + { "exec", &exec_command, &str_handler }, + { "close_window", &close_window, NULL }, + { "move_window", &move_window, NULL }, + { "focus", &focus_in_direction, &dir_handler }, + { "next_desk", &next_desk, NULL }, + { "prev_desk", &prev_desk, NULL }, + { "pan_desk", &pan_desk, &motion_handler }, + { "reset_zoom", &reset_zoom, NULL }, + { "zoom", &zoom, &str_handler }, + { "set_mark", &set_mark, NULL }, + { "go_to_mark", &go_to_mark, NULL }, + { "toggle_fullscreen", &toggle_fullscreen, NULL }, + { "halfimize", &halfimize, &dir_handler }, + { "maximize", &maximize, NULL }, + { "send_to_desk", &send_to_desk, &str_handler }, + { "scratchpad", &toggle_scratchpad, &scratchpad_handler }, + { "to_region", &to_region, &box_handler }, +}; + + +bool get_action( + char *name, action *found, char *args, void **data, char *response, int flag +) { + // flag can be PINCH or SCROLL to access their actions, otherwise neither + *data = NULL; + size_t i; + + switch (flag) { + case PINCH: + for (i = 0; i < sizeof(pinch_map) / sizeof(pinch_map[0]); i++) { + if (strcmp(pinch_map[i].name, name) == 0) { + *found = pinch_map[i].action; + action begin = pinch_map[i].begin; + *data = calloc(1, sizeof(action)); + *(action *)(*data) = begin; + return true; } } - } else { - sprintf(response, "Expected args in the form of 'x y' or 'x%% y%%'"); - } - } + break; - else if (!strcasecmp(message, "focus_in_direction")) { - if ((s = strtok(NULL, " \t\n\r"))) { - struct wlr_box box; - if (wlr_box_from_str(s, &box)) { - to_region(&box); + case SCROLL: + for (i = 0; i < sizeof(scroll_map) / sizeof(scroll_map[0]); i++) { + if (strcmp(scroll_map[i].name, name) == 0) { + *found = scroll_map[i].action; + return true; + } } - } - } + break; - else if (!strcasecmp(message, "next_desk")) { - next_desk(NULL); - } + default: + for (i = 0; i < sizeof(action_map) / sizeof(action_map[0]); i++) { + if (strcmp(action_map[i].name, name) == 0) { + *found = action_map[i].action; - else if (!strcasecmp(message, "prev_desk")) { - prev_desk(NULL); - } + if (action_map[i].data_handler != NULL) { + if (!action_map[i].data_handler(data, args)) { + sprintf(response, "Command malformed/incomplete."); + return false; + } + } - else if (!strcasecmp(message, "to_region")) { - if ((s = strtok(NULL, " \t\n\r"))) { - struct wlr_box box; - if (wlr_box_from_str(s, &box)) { - to_region(&box); + return true; + } } - } } - else { - handled = false; - } + return false; +} - return handled; + +bool do_action(char *message, char *response) { + void *data; + action action; + if (get_action(message, &action, strtok(NULL, "\n\r"), &data, response, 0)) { + (*action)(data); + return true; + } else { + return false; + } } -void terminate(void *data) { +static void terminate(void *data) { wl_display_terminate(wimp.display); } -void exec_command(void *data) { +static void exec_command(void *data) { pid_t pid = fork(); if (pid == 0) { if (execl("/bin/sh", "/bin/sh", "-c", data, (void *)NULL) == -1) { @@ -130,7 +167,7 @@ } -void close_window(void *data) { +static void close_window(void *data) { struct wlr_surface *surface = wimp.seat->keyboard_state.focused_surface; if (surface) { struct wlr_xdg_surface *xdg_surface = surface->role_data; @@ -141,7 +178,7 @@ } -void move_window(void *data) { +static void move_window(void *data) { struct view *view; if (wimp.grabbed_view) { view = wimp.grabbed_view; @@ -180,7 +217,7 @@ } -void focus_in_direction(void *data) { +static void focus_in_direction(void *data) { if (wl_list_empty(&wimp.current_desk->views)) { return; } @@ -226,7 +263,7 @@ } -void next_desk(void *data) { +static void next_desk(void *data) { struct desk *desk; if (wimp.current_desk->index + 1 == wimp.desk_count) { desk = wl_container_of(wimp.desks.next, desk, link); @@ -237,7 +274,7 @@ } -void prev_desk(void *data) { +static void prev_desk(void *data) { struct desk *desk; if (wimp.current_desk->index == 0) { desk = wl_container_of(wimp.desks.prev, desk, link); @@ -270,7 +307,7 @@ } -void zoom(void *data) { +static void zoom(void *data) { /* Passed value (data) is the percentage step (+ve or -ve) */ struct desk *desk = wimp.current_desk; double f = 1 + (*(double*)data / 100); @@ -296,13 +333,13 @@ } -void reset_zoom(void *data) { +static void reset_zoom(void *data) { double dz = 100 * 1 / wimp.current_desk->zoom - 100; zoom(&dz); } -void zoom_scroll(void *data) { +static void zoom_scroll(void *data) { struct motion motion = *(struct motion*)data; double dz = - motion.dx - motion.dy; zoom(&dz); @@ -312,19 +349,19 @@ static double zoom_pinch_initial; -void zoom_pinch(void *data) { +static void zoom_pinch(void *data) { double scale = *(double*)data; double dz = 100 * scale * zoom_pinch_initial / wimp.current_desk->zoom - 100; zoom(&dz); } -void zoom_pinch_begin(void *data) { +static void zoom_pinch_begin(void *data) { zoom_pinch_initial = wimp.current_desk->zoom; } -void set_mark(void *data) { +static void set_mark(void *data) { struct mark *mark = calloc(1, sizeof(struct mark)); struct desk *desk = wimp.current_desk; mark->desk = desk; @@ -381,7 +418,7 @@ } -void go_to_mark(void *data) { +static void go_to_mark(void *data) { wimp.mark_waiting = true; damage_mark_indicator(); } @@ -442,7 +479,7 @@ } -void halfimize(void *data) { +static void halfimize(void *data) { struct wlr_surface *surface = wimp.seat->keyboard_state.focused_surface; if (!surface || !wlr_surface_is_xdg_surface(surface) || wl_list_empty(&wimp.current_desk->views)) { return; @@ -497,7 +534,7 @@ } -void maximize(void *data) { +static void maximize(void *data) { struct wlr_surface *surface = wimp.seat->keyboard_state.focused_surface; if (!surface || !wlr_surface_is_xdg_surface(surface) || wl_list_empty(&wimp.current_desk->views)) { return; @@ -523,7 +560,7 @@ } -void send_to_desk(void *data) { +static void send_to_desk(void *data) { struct view *view = wl_container_of(wimp.current_desk->views.next, view, link); int index = *(double*)data - 1; unfullscreen(); @@ -531,7 +568,7 @@ } -void toggle_scratchpad(void *data) { +static void toggle_scratchpad(void *data) { struct scratchpad *scratchpad = scratchpad_from_id(*(int *)data); if (scratchpad->view) { @@ -558,7 +595,7 @@ } -void to_region(void *data) { +static void to_region(void *data) { struct wlr_box *box = (struct wlr_box *)data; struct wlr_box *extents = wlr_output_layout_get_box(wimp.output_layout, NULL);