2428 | 2428 |
.change_state = virt_viewer_app_action_auto_resize },
|
2429 | 2429 |
};
|
2430 | 2430 |
|
2431 | |
struct VirtViewerActionAccels {
|
|
2431 |
static const struct {
|
|
2432 |
const char *name;
|
2432 | 2433 |
const char *action;
|
2433 | |
const char *accels[3];
|
|
2434 |
const gchar *default_accels[3];
|
|
2435 |
} hotkey_defaults[] = {
|
|
2436 |
{ "toggle-fullscreen", "win.fullscreen", {"F11", NULL, NULL} },
|
|
2437 |
{ "zoom-in", "win.zoom-in", { "<Ctrl>plus", "<Ctrl>KP_Add", NULL } },
|
|
2438 |
{ "zoom-out", "win.zoom-out", { "<Ctrl>minus", "<Ctrl>KP_Subtract", NULL } },
|
|
2439 |
{ "zoom-reset", "win.zoom-reset", { "<Ctrl>0", "<Ctrl>KP_0", NULL } },
|
|
2440 |
{ "release-cursor", "win.release-cursor", {"<Shift>F12", NULL, NULL} },
|
|
2441 |
{ "smartcard-insert", "app.smartcard-insert", {"<Shift>F8", NULL, NULL} },
|
|
2442 |
{ "smartcard-remove", "app.smartcard-remove", {"<Shift>F9", NULL, NULL} },
|
|
2443 |
{ "secure-attention", "win.secure-attention", {"<Ctrl><Alt>End", NULL, NULL} },
|
|
2444 |
{ "usb-device-reset", "win.usb-device-reset", {"<Ctrl><Shift>r", NULL, NULL} },
|
2434 | 2445 |
};
|
2435 | 2446 |
|
2436 | |
static const struct VirtViewerActionAccels action_accels[] = {
|
2437 | |
{ "win.fullscreen", {"F11", NULL, NULL} },
|
2438 | |
{ "win.zoom-in", { "<Ctrl>plus", "<Ctrl>KP_Add", NULL } },
|
2439 | |
{ "win.zoom-out", { "<Ctrl>minus", "<Ctrl>KP_Subtract", NULL } },
|
2440 | |
{ "win.zoom-reset", { "<Ctrl>0", "<Ctrl>KP_0", NULL } },
|
2441 | |
{ "win.release-cursor", {"<Shift>F12", NULL, NULL} },
|
2442 | |
{ "app.smartcard-insert", {"<Shift>F8", NULL, NULL} },
|
2443 | |
{ "app.smartcard-remove", {"<Shift>F9", NULL, NULL} },
|
2444 | |
{ "win.secure-attention", {"<Ctrl><Alt>End", NULL, NULL} },
|
2445 | |
{ "win.usb-device-reset", {"<Ctrl><Shift>r", NULL, NULL} },
|
2446 | |
};
|
|
2447 |
static gchar **hotkey_names;
|
2447 | 2448 |
|
2448 | 2449 |
static void
|
2449 | 2450 |
virt_viewer_app_on_application_startup(GApplication *app)
|
|
2467 | 2468 |
|
2468 | 2469 |
priv->resource = virt_viewer_get_resource();
|
2469 | 2470 |
|
2470 | |
for (i = 0 ; i < G_N_ELEMENTS(action_accels); i++) {
|
2471 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(app),
|
2472 | |
action_accels[i].action,
|
2473 | |
action_accels[i].accels);
|
2474 | |
}
|
2475 | |
|
2476 | 2471 |
virt_viewer_app_set_debug(opt_debug);
|
2477 | 2472 |
virt_viewer_app_set_fullscreen(self, opt_fullscreen);
|
2478 | 2473 |
|
|
2482 | 2477 |
priv->quit_on_disconnect = opt_kiosk ? opt_kiosk_quit : TRUE;
|
2483 | 2478 |
|
2484 | 2479 |
priv->main_window = virt_viewer_app_window_new(self,
|
2485 | |
virt_viewer_app_get_first_monitor(self));
|
|
2480 |
virt_viewer_app_get_first_monitor(self));
|
2486 | 2481 |
priv->main_notebook = GTK_WIDGET(virt_viewer_window_get_notebook(priv->main_window));
|
2487 | 2482 |
priv->initial_display_map = virt_viewer_app_get_monitor_mapping_for_section(self, "fallback");
|
2488 | 2483 |
|
2489 | 2484 |
virt_viewer_app_set_kiosk(self, opt_kiosk);
|
|
2485 |
|
|
2486 |
hotkey_names = g_new(gchar*, G_N_ELEMENTS(hotkey_defaults) + 1);
|
|
2487 |
for (i = 0 ; i < G_N_ELEMENTS(hotkey_defaults); i++) {
|
|
2488 |
hotkey_names[i] = g_strdup(hotkey_defaults[i].name);
|
|
2489 |
gtk_application_set_accels_for_action(GTK_APPLICATION(app),
|
|
2490 |
hotkey_defaults[i].action,
|
|
2491 |
hotkey_defaults[i].default_accels);
|
|
2492 |
}
|
|
2493 |
hotkey_names[i] = NULL;
|
|
2494 |
|
2490 | 2495 |
virt_viewer_app_set_hotkeys(self, opt_hotkeys);
|
2491 | 2496 |
|
2492 | 2497 |
if (opt_zoom < MIN_ZOOM_LEVEL || opt_zoom > MAX_ZOOM_LEVEL) {
|
|
2815 | 2820 |
g_object_notify(G_OBJECT(self), "enable-accel");
|
2816 | 2821 |
}
|
2817 | 2822 |
|
|
2823 |
gchar**
|
|
2824 |
virt_viewer_app_get_hotkey_names(void)
|
|
2825 |
{
|
|
2826 |
return hotkey_names;
|
|
2827 |
}
|
|
2828 |
|
2818 | 2829 |
void
|
2819 | 2830 |
virt_viewer_app_clear_hotkeys(VirtViewerApp *self)
|
2820 | 2831 |
{
|
2821 | 2832 |
gint i;
|
2822 | 2833 |
const gchar *no_accels[] = { NULL };
|
2823 | 2834 |
|
2824 | |
for (i = 0 ; i < G_N_ELEMENTS(action_accels); i++) {
|
|
2835 |
for (i = 0 ; i < G_N_ELEMENTS(hotkey_defaults); i++) {
|
2825 | 2836 |
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
2826 | |
action_accels[i].action,
|
|
2837 |
hotkey_defaults[i].action,
|
2827 | 2838 |
no_accels);
|
2828 | 2839 |
}
|
|
2840 |
}
|
|
2841 |
|
|
2842 |
void
|
|
2843 |
virt_viewer_app_set_hotkey(VirtViewerApp *self, const gchar *hotkey_name,
|
|
2844 |
const gchar *hotkey)
|
|
2845 |
{
|
|
2846 |
g_return_if_fail(VIRT_VIEWER_IS_APP(self));
|
|
2847 |
|
|
2848 |
const gchar *action = NULL;
|
|
2849 |
int i;
|
|
2850 |
for (i = 0; i < G_N_ELEMENTS(hotkey_defaults); i++) {
|
|
2851 |
if (g_str_equal(hotkey_name, hotkey_defaults[i].name)) {
|
|
2852 |
action = hotkey_defaults[i].action;
|
|
2853 |
break;
|
|
2854 |
}
|
|
2855 |
}
|
|
2856 |
if (action == NULL) {
|
|
2857 |
g_warning("Unknown hotkey name %s", hotkey_name);
|
|
2858 |
return;
|
|
2859 |
}
|
|
2860 |
|
|
2861 |
gchar *accel = spice_hotkey_to_gtk_accelerator(hotkey);
|
|
2862 |
const gchar *accels[] = { accel, NULL };
|
|
2863 |
guint accel_key;
|
|
2864 |
GdkModifierType accel_mods;
|
|
2865 |
/*
|
|
2866 |
* First try the spice translated accel.
|
|
2867 |
* Works for basic modifiers and single letters/numbers
|
|
2868 |
* where forced uppercasing matches GTK key names
|
|
2869 |
*/
|
|
2870 |
gtk_accelerator_parse(accels[0], &accel_key, &accel_mods);
|
|
2871 |
if (accel_key == 0 && accel_mods == 0) {
|
|
2872 |
/* Fallback to native GTK accels to cope with
|
|
2873 |
* case sensitive accels
|
|
2874 |
*/
|
|
2875 |
accels[0] = hotkey;
|
|
2876 |
gtk_accelerator_parse(accels[0], &accel_key, &accel_mods);
|
|
2877 |
}
|
|
2878 |
if (accel_key == 0 && accel_mods == 0) {
|
|
2879 |
g_warning("Invalid hotkey '%s' for '%s'", hotkey, hotkey_name);
|
|
2880 |
g_free(accel);
|
|
2881 |
return;
|
|
2882 |
}
|
|
2883 |
|
|
2884 |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), action, accels);
|
|
2885 |
g_free(accel);
|
2829 | 2886 |
}
|
2830 | 2887 |
|
2831 | 2888 |
void
|
|
2849 | 2906 |
virt_viewer_app_clear_hotkeys(self);
|
2850 | 2907 |
|
2851 | 2908 |
for (hotkey = hotkeys; *hotkey != NULL; hotkey++) {
|
2852 | |
gchar *key = strstr(*hotkey, "=");
|
2853 | |
const gchar *value = (key == NULL) ? NULL : (*key = '\0', key + 1);
|
|
2909 |
gchar *eq = strstr(*hotkey, "=");
|
|
2910 |
const gchar *value = (eq == NULL) ? NULL : (*eq = '\0', eq + 1);
|
2854 | 2911 |
if (value == NULL || *value == '\0') {
|
2855 | |
g_warning("missing value for key '%s'", *hotkey);
|
|
2912 |
g_warning("Missing value for hotkey '%s'", *hotkey);
|
2856 | 2913 |
continue;
|
2857 | 2914 |
}
|
2858 | 2915 |
|
2859 | |
gchar *accel = spice_hotkey_to_gtk_accelerator(value);
|
2860 | |
guint accel_key;
|
2861 | |
GdkModifierType accel_mods;
|
2862 | |
const gchar *accels[] = { accel, NULL };
|
2863 | |
|
2864 | |
/*
|
2865 | |
* First try the spice translated accel.
|
2866 | |
* Works for basic modifiers and single letters/numbers
|
2867 | |
* where forced uppercasing matches GTK key names
|
2868 | |
*/
|
2869 | |
gtk_accelerator_parse(accels[0], &accel_key, &accel_mods);
|
2870 | |
|
2871 | |
if (accel_key == 0 && accel_mods == 0) {
|
2872 | |
/* Fallback to native GTK accels to cope with
|
2873 | |
* case sensitive accels
|
2874 | |
*/
|
2875 | |
accels[0] = value;
|
2876 | |
gtk_accelerator_parse(accels[0], &accel_key, &accel_mods);
|
2877 | |
}
|
2878 | |
|
2879 | |
if (accel_key == 0 && accel_mods == 0) {
|
2880 | |
g_warning("Invalid value '%s' for key '%s'", value, *hotkey);
|
2881 | |
g_free(accel);
|
2882 | |
continue;
|
2883 | |
}
|
2884 | |
|
2885 | |
if (g_str_equal(*hotkey, "toggle-fullscreen")) {
|
2886 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.fullscreen", accels);
|
2887 | |
} else if (g_str_equal(*hotkey, "release-cursor")) {
|
2888 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.release-cursor", accels);
|
2889 | |
} else if (g_str_equal(*hotkey, "zoom-reset")) {
|
2890 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-reset", accels);
|
2891 | |
} else if (g_str_equal(*hotkey, "zoom-out")) {
|
2892 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-out", accels);
|
2893 | |
} else if (g_str_equal(*hotkey, "zoom-in")) {
|
2894 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-in", accels);
|
2895 | |
} else if (g_str_equal(*hotkey, "secure-attention")) {
|
2896 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.secure-attention", accels);
|
2897 | |
} else if (g_str_equal(*hotkey, "smartcard-insert")) {
|
2898 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-insert", accels);
|
2899 | |
} else if (g_str_equal(*hotkey, "smartcard-remove")) {
|
2900 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-remove", accels);
|
2901 | |
} else if (g_str_equal(*hotkey, "usb-device-reset")) {
|
2902 | |
gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.usb-device-reset", accels);
|
2903 | |
} else {
|
2904 | |
g_warning("Unknown hotkey command %s", *hotkey);
|
2905 | |
}
|
2906 | |
g_free(accel);
|
|
2916 |
virt_viewer_app_set_hotkey(self, *hotkey, value);
|
2907 | 2917 |
}
|
2908 | 2918 |
g_strfreev(hotkeys);
|
2909 | 2919 |
|