Merge branch '212_menu_keybind'

* 212_menu_keybind:
  Menubar: support Home and End actions for Menubar.
  Menu: implement drop/execute menu by hotkey.
  Ticket #212: implement keybinding for menu.
This commit is contained in:
Andrew Borodin 2019-06-09 12:07:01 +03:00
commit 934a2d9314
7 changed files with 195 additions and 126 deletions

View File

@ -13,6 +13,7 @@
#define KEYMAP_SECTION_MAIN_EXT "main:xmap" #define KEYMAP_SECTION_MAIN_EXT "main:xmap"
#define KEYMAP_SECTION_PANEL "panel" #define KEYMAP_SECTION_PANEL "panel"
#define KEYMAP_SECTION_DIALOG "dialog" #define KEYMAP_SECTION_DIALOG "dialog"
#define KEYMAP_SECTION_MENU "menu"
#define KEYMAP_SECTION_INPUT "input" #define KEYMAP_SECTION_INPUT "input"
#define KEYMAP_SECTION_LISTBOX "listbox" #define KEYMAP_SECTION_LISTBOX "listbox"
#define KEYMAP_SECTION_TREE "tree" #define KEYMAP_SECTION_TREE "tree"

View File

@ -39,12 +39,15 @@
#include "lib/tty/tty.h" #include "lib/tty/tty.h"
#include "lib/skin.h" #include "lib/skin.h"
#include "lib/tty/key.h" /* key macros */ #include "lib/tty/key.h" /* key macros */
#include "lib/keybind.h" /* global_keymap_t */
#include "lib/strutil.h" #include "lib/strutil.h"
#include "lib/widget.h" #include "lib/widget.h"
#include "lib/event.h" /* mc_event_raise() */ #include "lib/event.h" /* mc_event_raise() */
/*** global variables ****************************************************************************/ /*** global variables ****************************************************************************/
const global_keymap_t *menu_map;
/*** file scope macro definitions ****************************************************************/ /*** file scope macro definitions ****************************************************************/
#define MENUENTRY(x) ((menu_entry_t *)(x)) #define MENUENTRY(x) ((menu_entry_t *)(x))
@ -397,28 +400,36 @@ menubar_up (WMenuBar * menubar)
static void static void
menubar_first (WMenuBar * menubar) menubar_first (WMenuBar * menubar)
{ {
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected)); if (menubar->is_dropped)
if (menu->selected == 0)
return;
menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
menu->selected = 0;
while (TRUE)
{ {
menu_entry_t *entry; menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected)); if (menu->selected == 0)
return;
if ((entry == NULL) || (entry->command == CK_IgnoreKey)) menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
menu->selected++;
else menu->selected = 0;
break;
while (TRUE)
{
menu_entry_t *entry;
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
if ((entry == NULL) || (entry->command == CK_IgnoreKey))
menu->selected++;
else
break;
}
menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
}
else
{
menubar->selected = 0;
menubar_draw (menubar);
} }
menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -426,46 +437,92 @@ menubar_first (WMenuBar * menubar)
static void static void
menubar_last (WMenuBar * menubar) menubar_last (WMenuBar * menubar)
{ {
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected)); if (menubar->is_dropped)
const unsigned int len = g_list_length (menu->entries);
menu_entry_t *entry;
if (menu->selected == len - 1)
return;
menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
menu->selected = len;
do
{ {
menu->selected--; menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected)); const unsigned int len = g_list_length (menu->entries);
} menu_entry_t *entry;
while ((entry == NULL) || (entry->command == CK_IgnoreKey));
menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR); if (menu->selected == len - 1)
return;
menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
menu->selected = len;
do
{
menu->selected--;
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
}
while ((entry == NULL) || (entry->command == CK_IgnoreKey));
menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
}
else
{
menubar->selected = g_list_length (menubar->menu) - 1;
menubar_draw (menubar);
}
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static int static cb_ret_t
menubar_handle_key (WMenuBar * menubar, int key) menubar_try_drop_menu (WMenuBar * menubar, int hotkey)
{ {
/* Lowercase */ GList *i;
if (isascii (key))
key = g_ascii_tolower (key);
if (is_abort_char (key)) for (i = menubar->menu; i != NULL; i = g_list_next (i))
{ {
menubar_finish (menubar); menu_t *menu = MENU (i->data);
return 1;
if (menu->text.hotkey != NULL && hotkey == g_ascii_tolower (menu->text.hotkey[0]))
{
menubar_drop (menubar, g_list_position (menubar->menu, i));
return MSG_HANDLED;
}
} }
/* menubar help or menubar navigation */ return MSG_NOT_HANDLED;
switch (key) }
/* --------------------------------------------------------------------------------------------- */
static cb_ret_t
menubar_try_exec_menu (WMenuBar * menubar, int hotkey)
{
menu_t *menu;
GList *i;
menu = g_list_nth_data (menubar->menu, menubar->selected);
for (i = menu->entries; i != NULL; i = g_list_next (i))
{ {
case KEY_F (1): const menu_entry_t *entry = MENUENTRY (i->data);
if (entry != NULL && entry->text.hotkey != NULL
&& hotkey == g_ascii_tolower (entry->text.hotkey[0]))
{
menu->selected = g_list_position (menu->entries, i);
menubar_execute (menubar);
return MSG_HANDLED;
}
}
return MSG_NOT_HANDLED;
}
/* --------------------------------------------------------------------------------------------- */
static cb_ret_t
menubar_execute_cmd (WMenuBar * menubar, unsigned long command, int key)
{
cb_ret_t ret = MSG_HANDLED;
switch (command)
{
case CK_Help:
{ {
ev_help_t event_data = { NULL, NULL }; ev_help_t event_data = { NULL, NULL };
@ -477,98 +534,65 @@ menubar_handle_key (WMenuBar * menubar, int key)
mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data); mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
menubar_draw (menubar); menubar_draw (menubar);
return 1;
} }
break;
case KEY_LEFT: case CK_Left:
case XCTRL ('b'):
menubar_left (menubar); menubar_left (menubar);
return 1; break;
case CK_Right:
case KEY_RIGHT:
case XCTRL ('f'):
menubar_right (menubar); menubar_right (menubar);
return 1; break;
case CK_Up:
if (menubar->is_dropped)
menubar_up (menubar);
break;
case CK_Down:
if (menubar->is_dropped)
menubar_down (menubar);
else
menubar_drop (menubar, menubar->selected);
break;
case CK_Home:
menubar_first (menubar);
break;
case CK_End:
menubar_last (menubar);
break;
case CK_Enter:
if (menubar->is_dropped)
menubar_execute (menubar);
else
menubar_drop (menubar, menubar->selected);
break;
case CK_Quit:
menubar_finish (menubar);
break;
default: default:
if (menubar->is_dropped)
ret = menubar_try_exec_menu (menubar, key);
else
ret = menubar_try_drop_menu (menubar, key);
break; break;
} }
if (!menubar->is_dropped) return ret;
{ }
GList *i;
/* drop menu by hotkey */ /* --------------------------------------------------------------------------------------------- */
for (i = menubar->menu; i != NULL; i = g_list_next (i))
{
menu_t *menu = MENU (i->data);
if ((menu->text.hotkey != NULL) && (key == g_ascii_tolower (menu->text.hotkey[0]))) static int
{ menubar_handle_key (WMenuBar * menubar, int key)
menubar_drop (menubar, g_list_position (menubar->menu, i)); {
return 1; unsigned long cmd;
}
}
/* drop menu by Enter or Dowwn key */ cmd = keybind_lookup_keymap_command (menu_map, key);
if (key == KEY_ENTER || key == XCTRL ('n') || key == KEY_DOWN || key == '\n')
menubar_drop (menubar, menubar->selected);
return 1; return (cmd == CK_IgnoreKey
} || menubar_execute_cmd (menubar, cmd,
key) == MSG_NOT_HANDLED) ? MSG_NOT_HANDLED : MSG_HANDLED;
{
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
GList *i;
/* execute menu command by hotkey */
for (i = menu->entries; i != NULL; i = g_list_next (i))
{
const menu_entry_t *entry = MENUENTRY (i->data);
if ((entry != NULL) && (entry->command != CK_IgnoreKey)
&& (entry->text.hotkey != NULL) && (key == g_ascii_tolower (entry->text.hotkey[0])))
{
menu->selected = g_list_position (menu->entries, i);
menubar_execute (menubar);
return 1;
}
}
/* menu execute by Enter or menu navigation */
switch (key)
{
case KEY_ENTER:
case '\n':
menubar_execute (menubar);
return 1;
case KEY_HOME:
case ALT ('<'):
menubar_first (menubar);
break;
case KEY_END:
case ALT ('>'):
menubar_last (menubar);
break;
case KEY_DOWN:
case XCTRL ('n'):
menubar_down (menubar);
break;
case KEY_UP:
case XCTRL ('p'):
menubar_up (menubar);
break;
default:
break;
}
}
return 0;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */

View File

@ -143,6 +143,17 @@ ScreenList = alt-prime
ScreenNext = alt-rbrace ScreenNext = alt-rbrace
ScreenPrev = alt-lbrace ScreenPrev = alt-lbrace
[menu]
Help = f1
Left = left; ctrl-b
Right = right; ctrl-f
Up = up; ctrl-p
Down = down; ctrl-n
Home = home; alt-lt; ctr-a
End = end; alt-gt ctrl-e
Enter = enter
Quit = F10; esc; ctrl-g
[input] [input]
Home = ctrl-a; alt-lt; home; a1 Home = ctrl-a; alt-lt; home; a1
End = ctrl-e; alt-gt; end; c1 End = ctrl-e; alt-gt; end; c1

View File

@ -143,6 +143,17 @@ ScreenList = alt-prime
ScreenNext = alt-rbrace ScreenNext = alt-rbrace
ScreenPrev = alt-lbrace ScreenPrev = alt-lbrace
[menu]
Help = f1
Left = left; ctrl-b
Right = right; ctrl-f
Up = up; ctrl-p
Down = down; ctrl-n
Home = home; alt-lt; ctr-a
End = end; alt-gt ctrl-e
Enter = enter
Quit = F10; esc; ctrl-g
[input] [input]
Home = ctrl-a; alt-lt; home; a1 Home = ctrl-a; alt-lt; home; a1
End = ctrl-e; alt-gt; end; c1 End = ctrl-e; alt-gt; end; c1

View File

@ -38,6 +38,7 @@ GArray *main_keymap = NULL;
GArray *main_x_keymap = NULL; GArray *main_x_keymap = NULL;
GArray *panel_keymap = NULL; GArray *panel_keymap = NULL;
GArray *dialog_keymap = NULL; GArray *dialog_keymap = NULL;
GArray *menu_keymap = NULL;
GArray *input_keymap = NULL; GArray *input_keymap = NULL;
GArray *listbox_keymap = NULL; GArray *listbox_keymap = NULL;
GArray *tree_keymap = NULL; GArray *tree_keymap = NULL;
@ -55,6 +56,7 @@ GArray *diff_keymap = NULL;
const global_keymap_t *main_map = NULL; const global_keymap_t *main_map = NULL;
const global_keymap_t *main_x_map = NULL; const global_keymap_t *main_x_map = NULL;
const global_keymap_t *panel_map = NULL; const global_keymap_t *panel_map = NULL;
const global_keymap_t *menu_map = NULL;
const global_keymap_t *tree_map = NULL; const global_keymap_t *tree_map = NULL;
const global_keymap_t *help_map = NULL; const global_keymap_t *help_map = NULL;
@ -225,6 +227,20 @@ static const global_keymap_ini_t default_dialog_keymap[] = {
{NULL, NULL} {NULL, NULL}
}; };
/* menubar */
static const global_keymap_ini_t default_menu_keymap[] = {
{"Help", "f1"},
{"Left", "left; ctrl-b"},
{"Right", "right; ctrl-f"},
{"Up", "up; ctrl-p"},
{"Down", "down; enter; ctrl-n"},
{"Home", "home; alt-lt; ctrl-a"},
{"End", "end; alt-gt; ctrl-e"},
{"Enter", "enter"},
{"Quit", "f10; ctrl-g; esc"},
{NULL, NULL}
};
/* input line */ /* input line */
static const global_keymap_ini_t default_input_keymap[] = { static const global_keymap_ini_t default_input_keymap[] = {
/* Motion */ /* Motion */
@ -590,6 +606,7 @@ create_default_keymap (void)
create_default_keymap_section (keymap, KEYMAP_SECTION_MAIN_EXT, default_main_x_keymap); create_default_keymap_section (keymap, KEYMAP_SECTION_MAIN_EXT, default_main_x_keymap);
create_default_keymap_section (keymap, KEYMAP_SECTION_PANEL, default_panel_keymap); create_default_keymap_section (keymap, KEYMAP_SECTION_PANEL, default_panel_keymap);
create_default_keymap_section (keymap, KEYMAP_SECTION_DIALOG, default_dialog_keymap); create_default_keymap_section (keymap, KEYMAP_SECTION_DIALOG, default_dialog_keymap);
create_default_keymap_section (keymap, KEYMAP_SECTION_MENU, default_menu_keymap);
create_default_keymap_section (keymap, KEYMAP_SECTION_INPUT, default_input_keymap); create_default_keymap_section (keymap, KEYMAP_SECTION_INPUT, default_input_keymap);
create_default_keymap_section (keymap, KEYMAP_SECTION_LISTBOX, default_listbox_keymap); create_default_keymap_section (keymap, KEYMAP_SECTION_LISTBOX, default_listbox_keymap);
create_default_keymap_section (keymap, KEYMAP_SECTION_TREE, default_tree_keymap); create_default_keymap_section (keymap, KEYMAP_SECTION_TREE, default_tree_keymap);

View File

@ -17,6 +17,7 @@ extern GArray *main_keymap;
extern GArray *main_x_keymap; extern GArray *main_x_keymap;
extern GArray *panel_keymap; extern GArray *panel_keymap;
extern GArray *dialog_keymap; extern GArray *dialog_keymap;
extern GArray *menu_keymap;
extern GArray *input_keymap; extern GArray *input_keymap;
extern GArray *listbox_keymap; extern GArray *listbox_keymap;
extern GArray *tree_keymap; extern GArray *tree_keymap;
@ -31,10 +32,10 @@ extern GArray *viewer_hex_keymap;
extern GArray *diff_keymap; extern GArray *diff_keymap;
#endif #endif
extern const global_keymap_t *main_map; extern const global_keymap_t *main_map;
extern const global_keymap_t *main_x_map; extern const global_keymap_t *main_x_map;
extern const global_keymap_t *panel_map; extern const global_keymap_t *panel_map;
extern const global_keymap_t *menu_map;
extern const global_keymap_t *tree_map; extern const global_keymap_t *tree_map;
extern const global_keymap_t *help_map; extern const global_keymap_t *help_map;

View File

@ -1365,6 +1365,9 @@ load_keymap_defs (gboolean load_from_file)
dialog_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t)); dialog_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t));
load_keymap_from_section (KEYMAP_SECTION_DIALOG, dialog_keymap, mc_global_keymap); load_keymap_from_section (KEYMAP_SECTION_DIALOG, dialog_keymap, mc_global_keymap);
menu_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t));
load_keymap_from_section (KEYMAP_SECTION_MENU, menu_keymap, mc_global_keymap);
input_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t)); input_keymap = g_array_new (TRUE, FALSE, sizeof (global_keymap_t));
load_keymap_from_section (KEYMAP_SECTION_INPUT, input_keymap, mc_global_keymap); load_keymap_from_section (KEYMAP_SECTION_INPUT, input_keymap, mc_global_keymap);
@ -1401,6 +1404,7 @@ load_keymap_defs (gboolean load_from_file)
main_x_map = (global_keymap_t *) main_x_keymap->data; main_x_map = (global_keymap_t *) main_x_keymap->data;
panel_map = (global_keymap_t *) panel_keymap->data; panel_map = (global_keymap_t *) panel_keymap->data;
dialog_map = (global_keymap_t *) dialog_keymap->data; dialog_map = (global_keymap_t *) dialog_keymap->data;
menu_map = (global_keymap_t *) menu_keymap->data;
input_map = (global_keymap_t *) input_keymap->data; input_map = (global_keymap_t *) input_keymap->data;
listbox_map = (global_keymap_t *) listbox_keymap->data; listbox_map = (global_keymap_t *) listbox_keymap->data;
tree_map = (global_keymap_t *) tree_keymap->data; tree_map = (global_keymap_t *) tree_keymap->data;