Hotkeys API: Difference between revisions
(Start section on basic operation of the hotkeys code) |
|||
Line 20: | Line 20: | ||
(''todo'': add some fake syntax highlighting with CSS to the example)<br><br> | (''todo'': add some fake syntax highlighting with CSS to the example)<br><br> | ||
The first column contains UI action names, as declared in uiactions.c, and the second column contains key names with (optional) modifiers. | The first column contains UI action names, as declared in uiactions.c, and the second column contains key names with (optional) modifiers. | ||
So the "reset-soft" action can be triggered with Alt+F9. Modifier keys are referred to with angular brackets and key names are simple strings, taken from X11's [https://cgit.freedesktop.org/xorg/proto/x11proto/tree/keysymdef.h keysymdef.h] header, with the <tt>XK_</tt> prefix stripped. | So the "reset-soft" action can be triggered with Alt+F9. Modifier keys are referred to with angular brackets and key names are simple strings, taken from X11's [https://cgit.freedesktop.org/xorg/proto/x11proto/tree/keysymdef.h keysymdef.h] header, with the <tt>XK_</tt> prefix stripped. | ||
=== Keysyms === | |||
The VICE [https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/arch/shared/hotkeys/vhkkeysyms.h src/arch/shared/hotkeys/vhkkeysyms.h] header contains copies of some of the X11 defines -- which are referred to in the code as "<i>keysyms</i> -- prefixed with <tt>VHK_</tt> instead of <tt>XK_</tt>. | |||
=== Modifiers === | |||
Modifiers are special keys like Alt, Control and Shift. The API uses the term <i>modifier</i> for a single modifier key, while a combination is referred to as a <i>modifier mask</i>, or <i>modmask</i>. The defines for the modifiers are also present in the <tt>vhkkeysyms.h</tt> header: | |||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
#define VHK_MOD_NONE 0x0000 | #define VHK_MOD_NONE 0x0000 | ||
Line 32: | Line 39: | ||
#define VHK_MOD_SUPER 0x0080 | #define VHK_MOD_SUPER 0x0080 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Combining these defines with OR results in a <i>modmask</i>. | |||
Code using the hotkeys API can translate between modifier values and strings with the functions declared in the <tt>vhkkeysyms.h</tt> header: | |||
<syntaxhighlight lang="C"> | |||
uint32_t vhk_keysym_from_name (const char *name); | |||
const char *vhk_keysym_name (uint32_t vice_keysym); | |||
uint32_t vhk_modifier_from_name(const char *name, const char **endptr); | |||
char *vhk_modmask_name (uint32_t vice_modmask); | |||
</syntaxhighlight> | |||
== Mechanism == | |||
The hotkeys system is split into a few distinct components: | |||
First there's the basic framework already in place that does most of the heavy lifting, that code resides in [https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/arch/shared/hotkeys/ src/arch/shared/hotkeys/] and is UI toolkit and OS/architecture-agnostic. This will be referred to as the VICE side of the code, the API refers to VICE-specific defines and functions with a <tt><i>vice</i></tt> affix, for example a function argument called <tt><i>vice</i>_keysym</tt> or the function <tt>ui_hotkeys_vhk_filename_<i>vice</i>()</tt>. | |||
Second there's the arch-specific code that needs to be implemented for each arch/UI using the hotkeys API. This code should be placed in <tt>src/arch/<i>ui-name</i></tt>, for example the Gtk3-specific hotkeys code resides in <tt>src/arch/gtk3/</tt>. The API refers to the UI/arch/OS-specific bits with an <tt><i>arch</i></tt> affix, and this documentation might refer to UI-specific things with <i>arch</i> as well. | |||
The arch-specific code is required to implement a few "virtual" functions for VICE to use, the prototypes for these are available in [https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/uiapi.h src/uiapi.h].<br> | |||
At present the required functions are: | |||
<syntaxhighlight lang="C"> | |||
void ui_hotkeys_arch_init(void); | |||
void ui_hotkeys_arch_shutdown(void); | |||
void ui_hotkeys_arch_install_by_map(vhk_map_t *map); | |||
void ui_hotkeys_arch_update_by_map (vhk_map_t *map, | |||
uint32_t vice_keysym, | |||
uint32_t vice_modmask); | |||
void ui_hotkeys_arch_remove_by_map (vhk_map_t *map); | |||
uint32_t ui_hotkeys_arch_keysym_from_arch (uint32_t arch_keysym); | |||
uint32_t ui_hotkeys_arch_keysym_to_arch (uint32_t vice_keysym); | |||
uint32_t ui_hotkeys_arch_modifier_from_arch(uint32_t arch_mod); | |||
uint32_t ui_hotkeys_arch_modifier_to_arch (uint32_t vice_mod); | |||
uint32_t ui_hotkeys_arch_modmask_from_arch (uint32_t arch_modmask); | |||
uint32_t ui_hotkeys_arch_modmask_to_arch (uint32_t vice_modmask); | |||
</syntaxhighlight> | |||
More on these later. |
Revision as of 22:15, 1 June 2023
The "new" hotkeys system as used in the Gtk3 UI is described here. The plan is to make this the only API for hotkeys in VICE, porting SDL over to this system and having any future UIs/ports use this as well.
Terminology
What is referred to here as "hotkeys" are keyboard shortcuts to activate UI elements such as dialogs and control emulator behavior (such as Warp mode, Pause, Reset, Quit). Another term for these is "(keyboard) accelerators" as used by Gtk+. I'll try to use "hotkeys" for VICE's API and "accelerators" for the Gtk+ implementation, but don't shoot me if I mix them up somewhere down the line.
Basic concepts
The hotkeys system is closely linked with the UI Actions system. In the Gtk3 UI the hotkeys are mapped to UI action IDs when parsing hotkey (.vhk) files. For any menu item that triggers a UI action the hotkey is used to set an accelerator label on the item (e.g. "Alt+Z"), but hotkeys can also be assigned to UI actions that do not have a corresponding menu item.
In the Gtk3 UI the accelerator labels on the menu items are cosmetic, we use GClosures for hotkey signal handlers so they also work in fullscreen mode and without a corresponding menu item.
A hotkey is in essence a simple key with optional modifier keys that maps to a UI action. Here's a snippet of a hotkey (data/C64/gtk3-hotkeys.vhk) file:
# "File" - monitor, reset, quit monitor-open <Alt>h reset-soft <Alt>F9 reset-hard <Alt>F12 quit <Alt>q
(todo: add some fake syntax highlighting with CSS to the example)
The first column contains UI action names, as declared in uiactions.c, and the second column contains key names with (optional) modifiers.
So the "reset-soft" action can be triggered with Alt+F9. Modifier keys are referred to with angular brackets and key names are simple strings, taken from X11's keysymdef.h header, with the XK_ prefix stripped.
Keysyms
The VICE src/arch/shared/hotkeys/vhkkeysyms.h header contains copies of some of the X11 defines -- which are referred to in the code as "keysyms -- prefixed with VHK_ instead of XK_.
Modifiers
Modifiers are special keys like Alt, Control and Shift. The API uses the term modifier for a single modifier key, while a combination is referred to as a modifier mask, or modmask. The defines for the modifiers are also present in the vhkkeysyms.h header:
#define VHK_MOD_NONE 0x0000
#define VHK_MOD_ALT 0x0001
#define VHK_MOD_COMMAND 0x0002
#define VHK_MOD_CONTROL 0x0004
#define VHK_MOD_HYPER 0x0008
#define VHK_MOD_META 0x0010
#define VHK_MOD_OPTION 0x0020
#define VHK_MOD_SHIFT 0x0040
#define VHK_MOD_SUPER 0x0080
Combining these defines with OR results in a modmask.
Code using the hotkeys API can translate between modifier values and strings with the functions declared in the vhkkeysyms.h header:
uint32_t vhk_keysym_from_name (const char *name);
const char *vhk_keysym_name (uint32_t vice_keysym);
uint32_t vhk_modifier_from_name(const char *name, const char **endptr);
char *vhk_modmask_name (uint32_t vice_modmask);
Mechanism
The hotkeys system is split into a few distinct components:
First there's the basic framework already in place that does most of the heavy lifting, that code resides in src/arch/shared/hotkeys/ and is UI toolkit and OS/architecture-agnostic. This will be referred to as the VICE side of the code, the API refers to VICE-specific defines and functions with a vice affix, for example a function argument called vice_keysym or the function ui_hotkeys_vhk_filename_vice().
Second there's the arch-specific code that needs to be implemented for each arch/UI using the hotkeys API. This code should be placed in src/arch/ui-name, for example the Gtk3-specific hotkeys code resides in src/arch/gtk3/. The API refers to the UI/arch/OS-specific bits with an arch affix, and this documentation might refer to UI-specific things with arch as well.
The arch-specific code is required to implement a few "virtual" functions for VICE to use, the prototypes for these are available in src/uiapi.h.
At present the required functions are:
void ui_hotkeys_arch_init(void);
void ui_hotkeys_arch_shutdown(void);
void ui_hotkeys_arch_install_by_map(vhk_map_t *map);
void ui_hotkeys_arch_update_by_map (vhk_map_t *map,
uint32_t vice_keysym,
uint32_t vice_modmask);
void ui_hotkeys_arch_remove_by_map (vhk_map_t *map);
uint32_t ui_hotkeys_arch_keysym_from_arch (uint32_t arch_keysym);
uint32_t ui_hotkeys_arch_keysym_to_arch (uint32_t vice_keysym);
uint32_t ui_hotkeys_arch_modifier_from_arch(uint32_t arch_mod);
uint32_t ui_hotkeys_arch_modifier_to_arch (uint32_t vice_mod);
uint32_t ui_hotkeys_arch_modmask_from_arch (uint32_t arch_modmask);
uint32_t ui_hotkeys_arch_modmask_to_arch (uint32_t vice_modmask);
More on these later.