From 0a997601ab5aaaf3b859e0c058b6e1f465134053 Mon Sep 17 00:00:00 2001 From: Paul Donohue Date: Sun, 25 Apr 2021 11:46:55 -0400 Subject: [PATCH] src: Unify hotkey setup from command line and config file This is mostly just code de-duplication and cleanup. The only functional change is that the case-sensitive accel support from the command-line hotkey handling now also applies to the config file. Signed-off-by: Paul Donohue --- src/virt-viewer-app.c | 156 ++++++++++++++++++++++------------------- src/virt-viewer-app.h | 2 + src/virt-viewer-file.c | 35 ++------- tests/test-hotkeys.c | 8 +-- 4 files changed, 94 insertions(+), 107 deletions(-) diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c index 3cfb3b4..f2f61ce 100644 --- a/src/virt-viewer-app.c +++ b/src/virt-viewer-app.c @@ -2429,22 +2429,23 @@ static GActionEntry actions[] = { .change_state = virt_viewer_app_action_auto_resize }, }; -struct VirtViewerActionAccels { +static const struct { + const char *name; const char *action; - const char *accels[3]; + const gchar *default_accels[3]; +} hotkey_defaults[] = { + { "toggle-fullscreen", "win.fullscreen", {"F11", NULL, NULL} }, + { "zoom-in", "win.zoom-in", { "plus", "KP_Add", NULL } }, + { "zoom-out", "win.zoom-out", { "minus", "KP_Subtract", NULL } }, + { "zoom-reset", "win.zoom-reset", { "0", "KP_0", NULL } }, + { "release-cursor", "win.release-cursor", {"F12", NULL, NULL} }, + { "smartcard-insert", "app.smartcard-insert", {"F8", NULL, NULL} }, + { "smartcard-remove", "app.smartcard-remove", {"F9", NULL, NULL} }, + { "secure-attention", "win.secure-attention", {"End", NULL, NULL} }, + { "usb-device-reset", "win.usb-device-reset", {"r", NULL, NULL} }, }; -static const struct VirtViewerActionAccels action_accels[] = { - { "win.fullscreen", {"F11", NULL, NULL} }, - { "win.zoom-in", { "plus", "KP_Add", NULL } }, - { "win.zoom-out", { "minus", "KP_Subtract", NULL } }, - { "win.zoom-reset", { "0", "KP_0", NULL } }, - { "win.release-cursor", {"F12", NULL, NULL} }, - { "app.smartcard-insert", {"F8", NULL, NULL} }, - { "app.smartcard-remove", {"F9", NULL, NULL} }, - { "win.secure-attention", {"End", NULL, NULL} }, - { "win.usb-device-reset", {"r", NULL, NULL} }, -}; +static gchar **hotkey_names; static void virt_viewer_app_on_application_startup(GApplication *app) @@ -2468,12 +2469,6 @@ virt_viewer_app_on_application_startup(GApplication *app) priv->resource = virt_viewer_get_resource(); - for (i = 0 ; i < G_N_ELEMENTS(action_accels); i++) { - gtk_application_set_accels_for_action(GTK_APPLICATION(app), - action_accels[i].action, - action_accels[i].accels); - } - virt_viewer_app_set_debug(opt_debug); virt_viewer_app_set_fullscreen(self, opt_fullscreen); @@ -2483,11 +2478,21 @@ virt_viewer_app_on_application_startup(GApplication *app) priv->quit_on_disconnect = opt_kiosk ? opt_kiosk_quit : TRUE; priv->main_window = virt_viewer_app_window_new(self, - virt_viewer_app_get_first_monitor(self)); + virt_viewer_app_get_first_monitor(self)); priv->main_notebook = GTK_WIDGET(virt_viewer_window_get_notebook(priv->main_window)); priv->initial_display_map = virt_viewer_app_get_monitor_mapping_for_section(self, "fallback"); virt_viewer_app_set_kiosk(self, opt_kiosk); + + hotkey_names = g_new(gchar*, G_N_ELEMENTS(hotkey_defaults) + 1); + for (i = 0 ; i < G_N_ELEMENTS(hotkey_defaults); i++) { + hotkey_names[i] = g_strdup(hotkey_defaults[i].name); + gtk_application_set_accels_for_action(GTK_APPLICATION(app), + hotkey_defaults[i].action, + hotkey_defaults[i].default_accels); + } + hotkey_names[i] = NULL; + virt_viewer_app_set_hotkeys(self, opt_hotkeys); if (opt_zoom < MIN_ZOOM_LEVEL || opt_zoom > MAX_ZOOM_LEVEL) { @@ -2816,19 +2821,71 @@ virt_viewer_app_set_enable_accel(VirtViewerApp *self, gboolean enable) g_object_notify(G_OBJECT(self), "enable-accel"); } +gchar** +virt_viewer_app_get_hotkey_names(void) +{ + return hotkey_names; +} + void virt_viewer_app_clear_hotkeys(VirtViewerApp *self) { gint i; const gchar *no_accels[] = { NULL }; - for (i = 0 ; i < G_N_ELEMENTS(action_accels); i++) { + for (i = 0 ; i < G_N_ELEMENTS(hotkey_defaults); i++) { gtk_application_set_accels_for_action(GTK_APPLICATION(self), - action_accels[i].action, + hotkey_defaults[i].action, no_accels); } } +void +virt_viewer_app_set_hotkey(VirtViewerApp *self, const gchar *hotkey_name, + const gchar *hotkey) +{ + g_return_if_fail(VIRT_VIEWER_IS_APP(self)); + + const gchar *action = NULL; + int i; + for (i = 0; i < G_N_ELEMENTS(hotkey_defaults); i++) { + if (g_str_equal(hotkey_name, hotkey_defaults[i].name)) { + action = hotkey_defaults[i].action; + break; + } + } + if (action == NULL) { + g_warning("Unknown hotkey name %s", hotkey_name); + return; + } + + gchar *accel = spice_hotkey_to_gtk_accelerator(hotkey); + const gchar *accels[] = { accel, NULL }; + guint accel_key; + GdkModifierType accel_mods; + /* + * First try the spice translated accel. + * Works for basic modifiers and single letters/numbers + * where forced uppercasing matches GTK key names + */ + gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); + if (accel_key == 0 && accel_mods == 0) { + /* Fallback to native GTK accels to cope with + * case sensitive accels + */ + accels[0] = hotkey; + gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); + } + if (accel_key == 0 && accel_mods == 0) { + g_warning("Invalid hotkey '%s' for '%s'", hotkey, hotkey_name); + g_free(accel); + return; + } + + gtk_application_set_accels_for_action(GTK_APPLICATION(self), action, accels); + g_free(accel); +} + void virt_viewer_app_set_hotkeys(VirtViewerApp *self, const gchar *hotkeys_str) { @@ -2850,61 +2907,14 @@ virt_viewer_app_set_hotkeys(VirtViewerApp *self, const gchar *hotkeys_str) virt_viewer_app_clear_hotkeys(self); for (hotkey = hotkeys; *hotkey != NULL; hotkey++) { - gchar *key = strstr(*hotkey, "="); - const gchar *value = (key == NULL) ? NULL : (*key = '\0', key + 1); + gchar *eq = strstr(*hotkey, "="); + const gchar *value = (eq == NULL) ? NULL : (*eq = '\0', eq + 1); if (value == NULL || *value == '\0') { - g_warning("missing value for key '%s'", *hotkey); + g_warning("Missing value for hotkey '%s'", *hotkey); continue; } - gchar *accel = spice_hotkey_to_gtk_accelerator(value); - guint accel_key; - GdkModifierType accel_mods; - const gchar *accels[] = { accel, NULL }; - - /* - * First try the spice translated accel. - * Works for basic modifiers and single letters/numbers - * where forced uppercasing matches GTK key names - */ - gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); - - if (accel_key == 0 && accel_mods == 0) { - /* Fallback to native GTK accels to cope with - * case sensitive accels - */ - accels[0] = value; - gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); - } - - if (accel_key == 0 && accel_mods == 0) { - g_warning("Invalid value '%s' for key '%s'", value, *hotkey); - g_free(accel); - continue; - } - - if (g_str_equal(*hotkey, "toggle-fullscreen")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.fullscreen", accels); - } else if (g_str_equal(*hotkey, "release-cursor")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.release-cursor", accels); - } else if (g_str_equal(*hotkey, "zoom-reset")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-reset", accels); - } else if (g_str_equal(*hotkey, "zoom-out")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-out", accels); - } else if (g_str_equal(*hotkey, "zoom-in")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-in", accels); - } else if (g_str_equal(*hotkey, "secure-attention")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.secure-attention", accels); - } else if (g_str_equal(*hotkey, "smartcard-insert")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-insert", accels); - } else if (g_str_equal(*hotkey, "smartcard-remove")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-remove", accels); - } else if (g_str_equal(*hotkey, "usb-device-reset")) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.usb-device-reset", accels); - } else { - g_warning("Unknown hotkey command %s", *hotkey); - } - g_free(accel); + virt_viewer_app_set_hotkey(self, *hotkey, value); } g_strfreev(hotkeys); diff --git a/src/virt-viewer-app.h b/src/virt-viewer-app.h index 39786b1..5281ab6 100644 --- a/src/virt-viewer-app.h +++ b/src/virt-viewer-app.h @@ -72,6 +72,8 @@ gboolean virt_viewer_app_activate(VirtViewerApp *self, GError **error); gboolean virt_viewer_app_initial_connect(VirtViewerApp *self, GError **error); gboolean virt_viewer_app_get_direct(VirtViewerApp *self); void virt_viewer_app_set_direct(VirtViewerApp *self, gboolean direct); +char** virt_viewer_app_get_hotkey_names(void); +void virt_viewer_app_set_hotkey(VirtViewerApp *self, const gchar *hotkey_name, const gchar *hotkey); void virt_viewer_app_set_hotkeys(VirtViewerApp *self, const gchar *hotkeys); void virt_viewer_app_set_attach(VirtViewerApp *self, gboolean attach); gboolean virt_viewer_app_get_attach(VirtViewerApp *self); diff --git a/src/virt-viewer-file.c b/src/virt-viewer-file.c index 5f8c028..c1312e6 100644 --- a/src/virt-viewer-file.c +++ b/src/virt-viewer-file.c @@ -883,17 +883,6 @@ virt_viewer_file_set_ovirt_admin(VirtViewerFile* self, gint value) g_object_notify(G_OBJECT(self), "ovirt-admin"); } -static void -spice_hotkey_set_accel(VirtViewerApp *app, const gchar *action_name, const gchar *key) -{ - gchar *accel = spice_hotkey_to_gtk_accelerator(key); - const gchar *accels[] = { accel, NULL }; - - gtk_application_set_accels_for_action(GTK_APPLICATION(app), action_name, accels); - - g_free(accel); -} - static gboolean virt_viewer_file_check_min_version(VirtViewerFile *self, GError **error) { @@ -969,28 +958,14 @@ virt_viewer_file_fill_app(VirtViewerFile* self, VirtViewerApp *app, GError **err virt_viewer_app_clear_hotkeys(app); { + gchar **hotkey_names = virt_viewer_app_get_hotkey_names(); gchar *val; - static const struct { - const char *prop; - const char *action_name; - } accels[] = { - { "release-cursor", "win.release-cursor" }, - { "toggle-fullscreen", "win.fullscreen" }, - { "zoom-in", "win.zoom-in" }, - { "zoom-out", "win.zoom-out" }, - { "zoom-reset", "win.zoom-reset" }, - { "smartcard-insert", "app.smartcard-insert" }, - { "smartcard-remove", "app.smartcard-remove" }, - { "secure-attention", "win.secure-attention" }, - { "usb-device-reset", "win.usb-device-reset" }, - }; int i; - - for (i = 0; i < G_N_ELEMENTS(accels); i++) { - if (!virt_viewer_file_is_set(self, accels[i].prop)) + for (i = 0; i < g_strv_length(hotkey_names); i++) { + if (!virt_viewer_file_is_set(self, hotkey_names[i])) continue; - g_object_get(self, accels[i].prop, &val, NULL); - spice_hotkey_set_accel(app, accels[i].action_name, val); + g_object_get(self, hotkey_names[i], &val, NULL); + virt_viewer_app_set_hotkey(app, hotkey_names[i], val); g_free(val); } } diff --git a/tests/test-hotkeys.c b/tests/test-hotkeys.c index e6ac36b..37f9eb7 100644 --- a/tests/test-hotkeys.c +++ b/tests/test-hotkeys.c @@ -89,19 +89,19 @@ test_hotkeys_bad(void) { "no_value", G_LOG_LEVEL_WARNING, - "missing value for key 'no_value'" + "Missing value for hotkey 'no_value'" },{ "smartcard-insert=", G_LOG_LEVEL_WARNING, - "missing value for key 'smartcard-insert'" + "Missing value for hotkey 'smartcard-insert'" },{ "toggle-fullscreen=A,unknown_command=B", G_LOG_LEVEL_WARNING, - "Unknown hotkey command unknown_command" + "Unknown hotkey name unknown_command" },{ "secure-attention=value", G_LOG_LEVEL_WARNING, - "Invalid value 'value' for key 'secure-attention'" + "Invalid hotkey 'value' for 'secure-attention'" }, };