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 <git@PaulSD.com>
This commit is contained in:
Paul Donohue 2021-04-25 11:46:55 -04:00 committed by Daniel P. Berrangé
parent af644ec423
commit 0a997601ab
4 changed files with 94 additions and 107 deletions

View File

@ -2429,22 +2429,23 @@ static GActionEntry actions[] = {
.change_state = virt_viewer_app_action_auto_resize }, .change_state = virt_viewer_app_action_auto_resize },
}; };
struct VirtViewerActionAccels { static const struct {
const char *name;
const char *action; 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", { "<Ctrl>plus", "<Ctrl>KP_Add", NULL } },
{ "zoom-out", "win.zoom-out", { "<Ctrl>minus", "<Ctrl>KP_Subtract", NULL } },
{ "zoom-reset", "win.zoom-reset", { "<Ctrl>0", "<Ctrl>KP_0", NULL } },
{ "release-cursor", "win.release-cursor", {"<Shift>F12", NULL, NULL} },
{ "smartcard-insert", "app.smartcard-insert", {"<Shift>F8", NULL, NULL} },
{ "smartcard-remove", "app.smartcard-remove", {"<Shift>F9", NULL, NULL} },
{ "secure-attention", "win.secure-attention", {"<Ctrl><Alt>End", NULL, NULL} },
{ "usb-device-reset", "win.usb-device-reset", {"<Ctrl><Shift>r", NULL, NULL} },
}; };
static const struct VirtViewerActionAccels action_accels[] = { static gchar **hotkey_names;
{ "win.fullscreen", {"F11", NULL, NULL} },
{ "win.zoom-in", { "<Ctrl>plus", "<Ctrl>KP_Add", NULL } },
{ "win.zoom-out", { "<Ctrl>minus", "<Ctrl>KP_Subtract", NULL } },
{ "win.zoom-reset", { "<Ctrl>0", "<Ctrl>KP_0", NULL } },
{ "win.release-cursor", {"<Shift>F12", NULL, NULL} },
{ "app.smartcard-insert", {"<Shift>F8", NULL, NULL} },
{ "app.smartcard-remove", {"<Shift>F9", NULL, NULL} },
{ "win.secure-attention", {"<Ctrl><Alt>End", NULL, NULL} },
{ "win.usb-device-reset", {"<Ctrl><Shift>r", NULL, NULL} },
};
static void static void
virt_viewer_app_on_application_startup(GApplication *app) 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(); 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_debug(opt_debug);
virt_viewer_app_set_fullscreen(self, opt_fullscreen); 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->quit_on_disconnect = opt_kiosk ? opt_kiosk_quit : TRUE;
priv->main_window = virt_viewer_app_window_new(self, 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->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"); priv->initial_display_map = virt_viewer_app_get_monitor_mapping_for_section(self, "fallback");
virt_viewer_app_set_kiosk(self, opt_kiosk); 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); virt_viewer_app_set_hotkeys(self, opt_hotkeys);
if (opt_zoom < MIN_ZOOM_LEVEL || opt_zoom > MAX_ZOOM_LEVEL) { 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"); g_object_notify(G_OBJECT(self), "enable-accel");
} }
gchar**
virt_viewer_app_get_hotkey_names(void)
{
return hotkey_names;
}
void void
virt_viewer_app_clear_hotkeys(VirtViewerApp *self) virt_viewer_app_clear_hotkeys(VirtViewerApp *self)
{ {
gint i; gint i;
const gchar *no_accels[] = { NULL }; 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), gtk_application_set_accels_for_action(GTK_APPLICATION(self),
action_accels[i].action, hotkey_defaults[i].action,
no_accels); 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 void
virt_viewer_app_set_hotkeys(VirtViewerApp *self, const gchar *hotkeys_str) 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); virt_viewer_app_clear_hotkeys(self);
for (hotkey = hotkeys; *hotkey != NULL; hotkey++) { for (hotkey = hotkeys; *hotkey != NULL; hotkey++) {
gchar *key = strstr(*hotkey, "="); gchar *eq = strstr(*hotkey, "=");
const gchar *value = (key == NULL) ? NULL : (*key = '\0', key + 1); const gchar *value = (eq == NULL) ? NULL : (*eq = '\0', eq + 1);
if (value == NULL || *value == '\0') { if (value == NULL || *value == '\0') {
g_warning("missing value for key '%s'", *hotkey); g_warning("Missing value for hotkey '%s'", *hotkey);
continue; continue;
} }
gchar *accel = spice_hotkey_to_gtk_accelerator(value); virt_viewer_app_set_hotkey(self, *hotkey, 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);
} }
g_strfreev(hotkeys); g_strfreev(hotkeys);

View File

@ -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_initial_connect(VirtViewerApp *self, GError **error);
gboolean virt_viewer_app_get_direct(VirtViewerApp *self); gboolean virt_viewer_app_get_direct(VirtViewerApp *self);
void virt_viewer_app_set_direct(VirtViewerApp *self, gboolean direct); 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_hotkeys(VirtViewerApp *self, const gchar *hotkeys);
void virt_viewer_app_set_attach(VirtViewerApp *self, gboolean attach); void virt_viewer_app_set_attach(VirtViewerApp *self, gboolean attach);
gboolean virt_viewer_app_get_attach(VirtViewerApp *self); gboolean virt_viewer_app_get_attach(VirtViewerApp *self);

View File

@ -883,17 +883,6 @@ virt_viewer_file_set_ovirt_admin(VirtViewerFile* self, gint value)
g_object_notify(G_OBJECT(self), "ovirt-admin"); 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 static gboolean
virt_viewer_file_check_min_version(VirtViewerFile *self, GError **error) 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); virt_viewer_app_clear_hotkeys(app);
{ {
gchar **hotkey_names = virt_viewer_app_get_hotkey_names();
gchar *val; 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; int i;
for (i = 0; i < g_strv_length(hotkey_names); i++) {
for (i = 0; i < G_N_ELEMENTS(accels); i++) { if (!virt_viewer_file_is_set(self, hotkey_names[i]))
if (!virt_viewer_file_is_set(self, accels[i].prop))
continue; continue;
g_object_get(self, accels[i].prop, &val, NULL); g_object_get(self, hotkey_names[i], &val, NULL);
spice_hotkey_set_accel(app, accels[i].action_name, val); virt_viewer_app_set_hotkey(app, hotkey_names[i], val);
g_free(val); g_free(val);
} }
} }

View File

@ -89,19 +89,19 @@ test_hotkeys_bad(void)
{ {
"no_value", "no_value",
G_LOG_LEVEL_WARNING, G_LOG_LEVEL_WARNING,
"missing value for key 'no_value'" "Missing value for hotkey 'no_value'"
},{ },{
"smartcard-insert=", "smartcard-insert=",
G_LOG_LEVEL_WARNING, G_LOG_LEVEL_WARNING,
"missing value for key 'smartcard-insert'" "Missing value for hotkey 'smartcard-insert'"
},{ },{
"toggle-fullscreen=A,unknown_command=B", "toggle-fullscreen=A,unknown_command=B",
G_LOG_LEVEL_WARNING, G_LOG_LEVEL_WARNING,
"Unknown hotkey command unknown_command" "Unknown hotkey name unknown_command"
},{ },{
"secure-attention=value", "secure-attention=value",
G_LOG_LEVEL_WARNING, G_LOG_LEVEL_WARNING,
"Invalid value 'value' for key 'secure-attention'" "Invalid hotkey 'value' for 'secure-attention'"
}, },
}; };