From ba1c5357a1b796b2844d44002ee1d6ab78cd06e1 Mon Sep 17 00:00:00 2001 From: braph Date: Fri, 27 Sep 2019 01:25:56 +0200 Subject: [PATCH] alsamixer: added mouse support Mouse support has been added for mixer_widget.c, card_select.c and proc_files.c. In the mixer widget the mouse is handled as follows: - After an element has been printed in mixer_display.c, a call to clickable_set() will store the coordinates of the drawn area plus the command enum that should be executed on click. An optional argument holds an index which points to the selected mixer control. - on_mouse_click() searches for a matching rectangle, focuses the mixer control and returns the command enum. In the menu widgets, the menu_driver() function handles mouse input. Signed-off-by: Benjamin Abendroth Signed-off-by: Jaroslav Kysela --- alsamixer/Makefile.am | 2 + alsamixer/bindings.h | 7 +- alsamixer/card_select.c | 34 +++------ alsamixer/mainloop.c | 1 + alsamixer/menu_widget.c | 63 +++++++++++++++++ alsamixer/menu_widget.h | 9 +++ alsamixer/mixer_clickable.c | 136 ++++++++++++++++++++++++++++++++++++ alsamixer/mixer_clickable.h | 21 ++++++ alsamixer/mixer_display.c | 35 ++++++++-- alsamixer/mixer_widget.c | 89 ++++++++++++++++++++++- alsamixer/mixer_widget.h | 3 + alsamixer/proc_files.c | 36 +++------- 12 files changed, 377 insertions(+), 59 deletions(-) create mode 100644 alsamixer/menu_widget.c create mode 100644 alsamixer/menu_widget.h create mode 100644 alsamixer/mixer_clickable.c create mode 100644 alsamixer/mixer_clickable.h diff --git a/alsamixer/Makefile.am b/alsamixer/Makefile.am index 3fe7a74..d1021f9 100644 --- a/alsamixer/Makefile.am +++ b/alsamixer/Makefile.am @@ -10,6 +10,8 @@ alsamixer_SOURCES = card_select.c card_select.h \ die.c die.h \ mainloop.c mainloop.h \ mem.c mem.h \ + menu_widget.c menu_widget.h \ + mixer_clickable.c mixer_clickable.h \ mixer_controls.c mixer_controls.h \ mixer_display.c mixer_display.h \ mixer_widget.c mixer_widget.h \ diff --git a/alsamixer/bindings.h b/alsamixer/bindings.h index 1e9dd6d..fa2e8d3 100644 --- a/alsamixer/bindings.h +++ b/alsamixer/bindings.h @@ -51,7 +51,12 @@ enum mixer_command { CMD_MIXER_TOGGLE_MUTE, CMD_MIXER_TOGGLE_CAPTURE, CMD_MIXER_BALANCE_CONTROL, - CMD_MIXER_REFRESH + CMD_MIXER_REFRESH, + + // Mouse + CMD_MIXER_MOUSE_CLICK_MUTE, + CMD_MIXER_MOUSE_CLICK_VOLUME_BAR, + CMD_MIXER_MOUSE_CLICK_CONTROL_ENUM, }; enum textbox_command { diff --git a/alsamixer/card_select.c b/alsamixer/card_select.c index e970203..6762ecd 100644 --- a/alsamixer/card_select.c +++ b/alsamixer/card_select.c @@ -28,10 +28,10 @@ #include "utils.h" #include "colors.h" #include "widget.h" +#include "menu_widget.h" #include "mixer_widget.h" #include "device_name.h" #include "card_select.h" -#include "bindings.h" struct card { struct card *next; @@ -60,33 +60,15 @@ static void on_key_enter(void) } } -static void on_menu_key(int key) -{ - if (key < ARRAY_SIZE(textbox_bindings)) { - key = textbox_bindings[key]; - if (key >= CMD_TEXTBOX___MIN_MENU_COMMAND && - key <= CMD_TEXTBOX___MAX_MENU_COMMAND) - menu_driver(menu, key + KEY_MAX); - } -} - static void on_handle_key(int key) { - switch (key) { - case 27: - case KEY_CANCEL: - case 'q': - case 'Q': - list_widget.close(); - break; - case 10: - case 13: - case KEY_ENTER: - on_key_enter(); - break; - default: - on_menu_key(key); - break; + switch (menu_widget_handle_key(menu, key)) { + case KEY_ENTER: + on_key_enter(); + break; + case KEY_CANCEL: + list_widget.close(); + break; } } diff --git a/alsamixer/mainloop.c b/alsamixer/mainloop.c index a50109b..e80f232 100644 --- a/alsamixer/mainloop.c +++ b/alsamixer/mainloop.c @@ -50,6 +50,7 @@ void initialize_curses(bool use_color) #endif window_size_changed(); /* update screen_lines/cols */ init_colors(use_color); + mousemask(ALL_MOUSE_EVENTS, NULL); snd_lib_error_set_handler(black_hole_error_handler); } diff --git a/alsamixer/menu_widget.c b/alsamixer/menu_widget.c new file mode 100644 index 0000000..30940a7 --- /dev/null +++ b/alsamixer/menu_widget.c @@ -0,0 +1,63 @@ +#include "menu_widget.h" +#include "colors.h" +#include "utils.h" +#include "bindings.h" + +/* Returns + * - KEY_CANCEL: close is requested + * - KEY_ENTER: item is selected + * - -1: no action + */ +int menu_widget_handle_key(MENU *menu, int key) +{ + MEVENT m; + + switch (key) { + case 27: + case KEY_CANCEL: + case 'q': + case 'Q': + return KEY_CANCEL; + case '\n': + case '\r': + case KEY_ENTER: + return KEY_ENTER; + + case KEY_MOUSE: + switch (menu_driver(menu, KEY_MOUSE)) { + case E_UNKNOWN_COMMAND: + /* If you double-click an item a REQ_TOGGLE_ITEM is generated + * and E_UNKNOWN_COMMAND is returned. (man menu_driver) */ + return KEY_ENTER; + case E_REQUEST_DENIED: + /* If menu did not handle KEY_MOUSE is has to be removed from + * input queue to prevent an infinite loop. */ + key = wgetch(menu_win(menu)); + if (key == KEY_MOUSE) { + if (getmouse(&m) == ERR) + return -1; + if (m.bstate & (BUTTON4_PRESSED|BUTTON4_CLICKED)) + menu_driver(menu, REQ_UP_ITEM); +#if NCURSES_MOUSE_VERSION > 1 + else if (m.bstate & (BUTTON5_PRESSED|BUTTON5_CLICKED)) + menu_driver(menu, REQ_DOWN_ITEM); +#endif + else + return KEY_CANCEL; + } + else if (key > 0) + ungetch(key); + } + return -1; + + default: + if (key < ARRAY_SIZE(textbox_bindings)) { + key = textbox_bindings[key]; + if (key >= CMD_TEXTBOX___MIN_MENU_COMMAND && + key <= CMD_TEXTBOX___MAX_MENU_COMMAND) + menu_driver(menu, key + KEY_MAX); + } + + return -1; + } +} diff --git a/alsamixer/menu_widget.h b/alsamixer/menu_widget.h new file mode 100644 index 0000000..ad3ed0e --- /dev/null +++ b/alsamixer/menu_widget.h @@ -0,0 +1,9 @@ +#ifndef MENU_WIDGET_H_INCLUDED +#define MENU_WIDGET_H_INCLUDED + +#include "widget.h" +#include + +int menu_widget_handle_key(MENU *menu, int key); + +#endif diff --git a/alsamixer/mixer_clickable.c b/alsamixer/mixer_clickable.c new file mode 100644 index 0000000..c772f37 --- /dev/null +++ b/alsamixer/mixer_clickable.c @@ -0,0 +1,136 @@ +#include +#include +#include "mixer_clickable.h" + +extern int screen_cols; +extern int screen_lines; + +static struct clickable_rect *clickable_rects = NULL; +static unsigned int clickable_rects_count = 0; +static unsigned int last_rect = 0; + +/* Using 0 instead of -1 for marking free rectangles allows us to use + * memset for `freeing` all rectangles at once. + * Zero is actually a valid coordinate in ncurses, but since we don't have + * any clickables in the top line this is fine. */ +#define FREE_MARKER 0 +#define RECT_IS_FREE(RECT) ((RECT).y1 == FREE_MARKER) +#define RECT_FREE(RECT) ((RECT).y1 = FREE_MARKER) + +void clickable_set(int y1, int x1, int y2, int x2, command_enum command, int arg1) { + struct clickable_rect* tmp; + unsigned int i; + + for (i = last_rect; i < clickable_rects_count; ++i) { + if (RECT_IS_FREE(clickable_rects[i])) { + last_rect = i; + goto SET_CLICKABLE_DATA; + } + } + + for (i = 0; i < last_rect; ++i) { + if (RECT_IS_FREE(clickable_rects[i])) { + last_rect = i; + goto SET_CLICKABLE_DATA; + } + } + + last_rect = clickable_rects_count; + tmp = realloc(clickable_rects, (clickable_rects_count + 8) * sizeof(*clickable_rects)); + if (!tmp) { + free(clickable_rects); + clickable_rects = NULL; + clickable_rects_count = 0; + last_rect = 0; + return; + } + clickable_rects = tmp; +#if FREE_MARKER == 0 + memset(clickable_rects + clickable_rects_count, 0, 8 * sizeof(*clickable_rects)); +#else + for (i = clickable_rects_count; i < clickable_rects_count + 8; ++i) + RECT_FREE(clickable_rects[i]); +#endif + clickable_rects_count += 8; + +SET_CLICKABLE_DATA: + clickable_rects[last_rect] = (struct clickable_rect) { + .y1 = y1, + .x1 = x1, + .x2 = x2, + .y2 = y2, + .command = command, + .arg1 = arg1 + }; +} + +void clickable_set_relative(WINDOW *win, int y1, int x1, int y2, int x2, command_enum command, int arg1) { + int y, x; + getyx(win, y, x); + y1 = y + y1; + x1 = x + x1; + y2 = y + y2; + x2 = x + x2; + clickable_set(y1, x1, y2, x2, command, arg1); +} + +void clickable_clear(int y1, int x1, int y2, int x2) { +#define IS_IN_RECT(Y, X) (Y >= y1 && Y <= y2 && X >= x1 && X <= x2) + unsigned int i; + + if (x1 == 0 && x2 == -1 && y2 == -1) { + if (y1 == 0) { + // Optimize case: clear all +#if FREE_MARKER == 0 + if (clickable_rects) + memset(clickable_rects, 0, + clickable_rects_count * sizeof(*clickable_rects)); +#else + for (i = 0; i < clickable_rects_count; ++i) + RECT_FREE(clickable_rects[i]); +#endif + } + else { + // Optimize case: clear all lines beyond y1 + for (i = 0; i < clickable_rects_count; ++i) { + if (clickable_rects[i].y2 >= y1) + RECT_FREE(clickable_rects[i]); + } + } + return; + } + + if (y2 < 0) + y2 = screen_lines + y2 + 1; + if (x2 < 0) + x2 = screen_cols + x2 + 1; + + for (i = 0; i < clickable_rects_count; ++i) { + if (!RECT_IS_FREE(clickable_rects[i]) && ( + IS_IN_RECT(clickable_rects[i].y1, clickable_rects[i].x1) || + IS_IN_RECT(clickable_rects[i].y2, clickable_rects[i].x2) + )) + { + RECT_FREE(clickable_rects[i]); + } + } +} + +struct clickable_rect* clickable_find(int y, int x) { + unsigned int i; + + for (i = 0; i < clickable_rects_count; ++i) { + if ( + !RECT_IS_FREE(clickable_rects[i]) && + y >= clickable_rects[i].y1 && + x >= clickable_rects[i].x1 && + y <= clickable_rects[i].y2 && + x <= clickable_rects[i].x2 + ) + { + return &clickable_rects[i]; + } + } + + return NULL; +} diff --git a/alsamixer/mixer_clickable.h b/alsamixer/mixer_clickable.h new file mode 100644 index 0000000..792c711 --- /dev/null +++ b/alsamixer/mixer_clickable.h @@ -0,0 +1,21 @@ +#ifndef MIXER_CLICKABLE_H +#define MIXER_CLICKABLE_H + +#include CURSESINC +#include "bindings.h" + +struct clickable_rect { + short y1; + short x1; + short y2; + short x2; + command_enum command; + int arg1; +}; + +void clickable_set(int y1, int x1, int y2, int x2, command_enum command, int arg1); +void clickable_set_relative(WINDOW *win, int y1, int x1, int y2, int x2, command_enum command, int arg1); +void clickable_clear(int y1, int x1, int y2, int x2); +struct clickable_rect* clickable_find(int y, int x); + +#endif diff --git a/alsamixer/mixer_display.c b/alsamixer/mixer_display.c index b1f79d0..2f45ab3 100644 --- a/alsamixer/mixer_display.c +++ b/alsamixer/mixer_display.c @@ -34,6 +34,7 @@ #include "mixer_widget.h" #include "mixer_controls.h" #include "mixer_display.h" +#include "mixer_clickable.h" enum align { ALIGN_LEFT, @@ -109,6 +110,7 @@ void init_mixer_layout(void) unsigned int label_width_left, label_width_right; unsigned int right_x, i; + clickable_clear(0, 0, -1, -1); screen_too_small = screen_lines < 14 || screen_cols < 12; has_info_items = screen_lines >= 6; if (!has_info_items) @@ -135,9 +137,12 @@ void init_mixer_layout(void) display_string_in_field(1 + i, 2, labels_left[i], label_width_left, ALIGN_RIGHT); if (label_width_right) - for (i = 0; i < 4; ++i) + for (i = 0; i < 4; ++i) { display_string_in_field(1 + i, right_x, labels_right[i], label_width_right, ALIGN_LEFT); + clickable_set(1 + i, right_x, 1 + i, right_x + label_width_right - 1, + CMD_MIXER_HELP + i, -1); + } } void display_card_info(void) @@ -197,6 +202,7 @@ void display_view_mode(void) bool has_view_mode; int i; + clickable_clear(3, 0, 3, 30); if (!has_info_items) return; @@ -204,10 +210,10 @@ void display_view_mode(void) for (i = 0; i < 3; ++i) widths[i] = get_mbs_width(modes[i]); if (4 + widths[0] + 6 + widths[1] + 6 + widths[2] + 1 <= info_items_width) { - wmove(mixer_widget.window, 3, info_items_left); + wmove(mixer_widget.window, 3, info_items_left - 1); wattrset(mixer_widget.window, attr_mixer_text); for (i = 0; i < 3; ++i) { - wprintw(mixer_widget.window, "F%c:", '3' + i); + wprintw(mixer_widget.window, " F%c:", '3' + i); if (has_view_mode && (int)view_mode == i) { wattrset(mixer_widget.window, attr_mixer_active); wprintw(mixer_widget.window, "[%s]", modes[i]); @@ -215,8 +221,8 @@ void display_view_mode(void) } else { wprintw(mixer_widget.window, " %s ", modes[i]); } - if (i < 2) - waddch(mixer_widget.window, ' '); + clickable_set_relative(mixer_widget.window, 0, -(widths[i] + 5), 0, -1, + CMD_WITH_ARG(CMD_MIXER_SET_VIEW_MODE, i), -1); } } else { wattrset(mixer_widget.window, attr_mixer_active); @@ -322,6 +328,7 @@ static void clear_controls_display(void) { int i; + clickable_clear(5, 0, -1, -1); wattrset(mixer_widget.window, attr_mixer_frame); for (i = 5; i < screen_lines - 1; ++i) mvwprintw(mixer_widget.window, i, 1, "%*s", screen_cols - 2, ""); @@ -483,6 +490,8 @@ static void display_control(unsigned int control_index) frame_left + c + 1, ch); } } + clickable_set(base_y - volume_height, frame_left + 1, base_y, frame_left + 2, + CMD_MIXER_MOUSE_CLICK_VOLUME_BAR, control_index); if (control->flags & IS_ACTIVE) wattrset(mixer_widget.window, attr_mixer_active); if (!(control->flags & HAS_VOLUME_1)) { @@ -520,6 +529,8 @@ static void display_control(unsigned int control_index) switches[1] ? _("O")[0] | (control->flags & IS_ACTIVE ? attr_ctl_nomute : 0) : _("M")[0] | (control->flags & IS_ACTIVE ? attr_ctl_mute : 0)); + clickable_set(base_y + 1, frame_left + 1, base_y + 1, frame_left + 2, + CMD_MIXER_MOUSE_CLICK_MUTE, control_index); } if (control->flags & TYPE_CSWITCH) { @@ -534,10 +545,14 @@ static void display_control(unsigned int control_index) wattrset(mixer_widget.window, switches[0] ? attr_ctl_capture : attr_ctl_nocapture); /* TRANSLATORS: "left"; no more than two characters */ display_string_in_field(cswitch_y - 1, frame_left - 2, switches[0] ? _("L") : "", 2, ALIGN_RIGHT); + clickable_set(cswitch_y - 1, frame_left - 2, cswitch_y - 1, frame_left - 1, + CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, LEFT), control_index); if (control->flags & IS_ACTIVE) wattrset(mixer_widget.window, switches[1] ? attr_ctl_capture : attr_ctl_nocapture); /* TRANSLATORS: "right"; no more than two characters */ display_string_in_field(cswitch_y - 1, frame_left + 4, switches[1] ? _("R") : "", 2, ALIGN_LEFT); + clickable_set(cswitch_y - 1, frame_left + 4, cswitch_y - 1, frame_left + 5, + CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, RIGHT), control_index); /* TRANSLATORS: no more than eight characters */ s = _("CAPTURE"); if (switches[0] || switches[1]) { @@ -554,6 +569,8 @@ static void display_control(unsigned int control_index) wattrset(mixer_widget.window, attr_ctl_nocapture); display_string_in_field(cswitch_y, frame_left - 2, buf, 8, ALIGN_CENTER); } + clickable_set(cswitch_y, frame_left - 2, cswitch_y, frame_left - 2 + 8, + CMD_WITH_ARG(CMD_MIXER_TOGGLE_CAPTURE, LEFT|RIGHT), control_index); } if (control->flags & TYPE_ENUM) { @@ -566,6 +583,8 @@ static void display_control(unsigned int control_index) if (control->flags & IS_ACTIVE) wattrset(mixer_widget.window, attr_mixer_active); display_string_centered_in_control(base_y, col, buf, control_width); + clickable_set_relative(mixer_widget.window, 0, -control_name_width, 0, -2, + CMD_MIXER_MOUSE_CLICK_CONTROL_ENUM, control_index); } if (control_index == focus_control_index) { @@ -584,6 +603,8 @@ static void display_control(unsigned int control_index) wattrset(mixer_widget.window, attr_ctl_label_inactive); } display_string_centered_in_control(name_y, col, control->name, control_name_width); + clickable_set_relative(mixer_widget.window, -1, -control_name_width, 0, -2, + CMD_WITH_ARG(CMD_MIXER_FOCUS_CONTROL, control_index), -1); if (channel_name_y > name_y) { if (control->flags & IS_MULTICH) { switch (control->flags & MULTICH_MASK) { @@ -630,6 +651,10 @@ static void display_scroll_indicators(void) mvwaddch(mixer_widget.window, y, 0, left); mvwaddch(mixer_widget.window, y, screen_cols - 1, right); } + clickable_set(y0, 0, y1, 0, + CMD_WITH_ARG(CMD_MIXER_PREVIOUS, visible_controls), -1); + clickable_set(y0, screen_cols - 1, y1, screen_cols - 1, + CMD_WITH_ARG(CMD_MIXER_NEXT, visible_controls), -1); } void display_controls(void) diff --git a/alsamixer/mixer_widget.c b/alsamixer/mixer_widget.c index b1bd61e..160124f 100644 --- a/alsamixer/mixer_widget.c +++ b/alsamixer/mixer_widget.c @@ -34,6 +34,7 @@ #include "proc_files.h" #include "card_select.h" #include "volume_mapping.h" +#include "mixer_clickable.h" #include "mixer_controls.h" #include "mixer_display.h" #include "mixer_widget.h" @@ -54,6 +55,9 @@ unsigned int current_control_flags; bool control_values_changed; bool controls_changed; +unsigned int mouse_wheel_step = 1; +bool mouse_wheel_focuses_control = 1; + static int elem_callback(snd_mixer_elem_t *elem, unsigned int mask) { if (mask == SND_CTL_EVENT_MASK_REMOVE) { @@ -462,12 +466,95 @@ static void balance_volumes(void) display_controls(); } +static int on_mouse_key() { + MEVENT m; + command_enum cmd = 0; + unsigned int channels = LEFT | RIGHT; + unsigned int index; + struct control *control; + struct clickable_rect *rect; + + if (getmouse(&m) == ERR) + return 0; + + if (m.bstate & ( + BUTTON1_PRESSED|BUTTON1_RELEASED| + BUTTON2_PRESSED|BUTTON2_RELEASED| + BUTTON3_PRESSED|BUTTON3_RELEASED)) + return 0; + + rect = clickable_find(m.y, m.x); + if (rect) + cmd = rect->command; + +#if NCURSES_MOUSE_VERSION > 1 + if (m.bstate & (BUTTON4_CLICKED|BUTTON4_PRESSED|BUTTON5_CLICKED|BUTTON5_PRESSED)) { + switch (cmd) { + case CMD_MIXER_MOUSE_CLICK_CONTROL_ENUM: + focus_control_index = rect->arg1; + return CMD_WITH_ARG(( + m.bstate & (BUTTON4_CLICKED|BUTTON4_PRESSED) + ? CMD_MIXER_CONTROL_UP + : CMD_MIXER_CONTROL_DOWN + ), 1); + + case CMD_MIXER_MOUSE_CLICK_VOLUME_BAR: + if (mouse_wheel_focuses_control) + focus_control_index = rect->arg1; + + default: + return CMD_WITH_ARG(( + m.bstate & (BUTTON4_CLICKED|BUTTON4_PRESSED) + ? CMD_MIXER_CONTROL_UP + : CMD_MIXER_CONTROL_DOWN + ), mouse_wheel_step); + } + } +#endif + + /* If the rectangle has got an argument (value != -1) it is used for + * setting `focus_control_index` */ + if (rect && rect->arg1 >= 0) + focus_control_index = rect->arg1; + + switch (cmd) { + case CMD_MIXER_MOUSE_CLICK_VOLUME_BAR: + if (m.bstate & (BUTTON3_CLICKED|BUTTON3_DOUBLE_CLICKED|BUTTON3_TRIPLE_CLICKED)) + channels = m.x - rect->x1 + 1; + return CMD_WITH_ARG(CMD_MIXER_CONTROL_SET_PERCENT_LEFT + channels - 1, + (100 * (rect->y2 - m.y) / (rect->y2 - rect->y1)) // volume + ); + + case CMD_MIXER_MOUSE_CLICK_MUTE: + if (m.bstate & (BUTTON3_CLICKED|BUTTON3_DOUBLE_CLICKED|BUTTON3_TRIPLE_CLICKED)) + channels = m.x - rect->x1 + 1; + return CMD_WITH_ARG(CMD_MIXER_TOGGLE_MUTE, channels); + + case CMD_MIXER_MOUSE_CLICK_CONTROL_ENUM: + control = get_focus_control(TYPE_ENUM); + if (control && + (snd_mixer_selem_get_enum_item(control->elem, 0, &index) >= 0)) { + return (index == 0 + ? CMD_WITH_ARG(CMD_MIXER_CONTROL_UP, 100) + : CMD_WITH_ARG(CMD_MIXER_CONTROL_DOWN, 1)); + } + break; + + default: + return cmd; // non-mouse command + } + + return 0; // failed mouse command +} + static void on_handle_key(int key) { int arg; command_enum cmd; - if (key < ARRAY_SIZE(mixer_bindings)) + if (key == KEY_MOUSE) + cmd = on_mouse_key(); + else if (key < ARRAY_SIZE(mixer_bindings)) cmd = mixer_bindings[key]; else return; diff --git a/alsamixer/mixer_widget.h b/alsamixer/mixer_widget.h index 5b1cfcc..3b6f474 100644 --- a/alsamixer/mixer_widget.h +++ b/alsamixer/mixer_widget.h @@ -32,6 +32,9 @@ extern unsigned int current_control_flags; extern bool control_values_changed; extern bool controls_changed; +extern unsigned int mouse_wheel_step; +extern bool mouse_wheel_focuses_control; + void create_mixer_object(struct snd_mixer_selem_regopt *selem_regopt); void create_mixer_widget(void); void mixer_shutdown(void); diff --git a/alsamixer/proc_files.c b/alsamixer/proc_files.c index 9d3fe3f..5ae7ae9 100644 --- a/alsamixer/proc_files.c +++ b/alsamixer/proc_files.c @@ -28,42 +28,26 @@ #include "widget.h" #include "textbox.h" #include "proc_files.h" -#include "bindings.h" +#include "menu_widget.h" static struct widget proc_widget; static ITEM *items[7]; static unsigned int items_count; static MENU *menu; -static void on_menu_key(int key) -{ - if (key < ARRAY_SIZE(textbox_bindings)) { - key = textbox_bindings[key]; - if (key >= CMD_TEXTBOX___MIN_MENU_COMMAND && - key <= CMD_TEXTBOX___MAX_MENU_COMMAND) - menu_driver(menu, key + KEY_MAX); - } -} - static void on_handle_key(int key) { ITEM *item; - switch (key) { - case 27: - case KEY_CANCEL: - proc_widget.close(); - break; - case 10: - case 13: - case KEY_ENTER: - item = current_item(menu); - if (item) - show_textfile(item_name(item)); - break; - default: - on_menu_key(key); - break; + switch (menu_widget_handle_key(menu, key)) { + case KEY_ENTER: + item = current_item(menu); + if (item) + show_textfile(item_name(item)); + break; + case KEY_CANCEL: + proc_widget.close(); + break; } } -- 2.47.1