summaryrefslogtreecommitdiffstats
path: root/src/remmina_key_chooser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/remmina_key_chooser.c')
-rw-r--r--src/remmina_key_chooser.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/remmina_key_chooser.c b/src/remmina_key_chooser.c
new file mode 100644
index 0000000..69a87c7
--- /dev/null
+++ b/src/remmina_key_chooser.c
@@ -0,0 +1,146 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2009-2010 Vic Lee
+ * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
+ * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. * If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. * If you
+ * do not wish to do so, delete this exception statement from your
+ * version. * If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ *
+ */
+
+#include <glib/gi18n.h>
+#include "remmina_key_chooser.h"
+#include "remmina_public.h"
+#include "remmina/remmina_trace_calls.h"
+
+/* Handle key-presses on the GtkEventBox */
+static gboolean remmina_key_chooser_dialog_on_key_press(GtkWidget *widget, GdkEventKey *event, RemminaKeyChooserArguments *arguments)
+{
+ TRACE_CALL(__func__);
+ if (!arguments->use_modifiers || !event->is_modifier) {
+ arguments->state = event->state;
+ arguments->keyval = gdk_keyval_to_lower(event->keyval);
+ gtk_dialog_response(GTK_DIALOG(gtk_widget_get_toplevel(widget)),
+ event->keyval == GDK_KEY_Escape ? GTK_RESPONSE_CANCEL : GTK_RESPONSE_OK);
+ }
+ return TRUE;
+}
+
+/* User option to use key modifiers when selecting keyboard shortcuts */
+void remmina_key_chooser_dialog_set_option_modifier(GtkWidget *widget, gboolean state, RemminaKeyChooserArguments *arguments)
+{
+ TRACE_CALL(__func__);
+ gtk_switch_set_state(GTK_SWITCH(widget), state);
+ arguments->use_modifiers = state;
+}
+
+/* Show a key chooser dialog and return the keyval for the selected key */
+RemminaKeyChooserArguments* remmina_key_chooser_new(GtkWindow *parent_window, gboolean use_modifiers)
+{
+ TRACE_CALL(__func__);
+ GtkBuilder *builder = remmina_public_gtk_builder_new_from_resource ("/org/remmina/Remmina/src/../data/ui/remmina_key_chooser.glade");
+ GtkDialog *dialog;
+ RemminaKeyChooserArguments *arguments;
+ arguments = g_new0(RemminaKeyChooserArguments, 1);
+ arguments->state = 0;
+ arguments->use_modifiers = use_modifiers;
+
+ /* Setup the dialog */
+ dialog = GTK_DIALOG(gtk_builder_get_object(builder, "KeyChooserDialog"));
+ gtk_window_set_transient_for(GTK_WINDOW(dialog), parent_window);
+
+ /* Connect the key modifier switch signal */
+ g_signal_connect(gtk_builder_get_object(builder, "switch_option_key_modifier"), "state-set",
+ G_CALLBACK(remmina_key_chooser_dialog_set_option_modifier), arguments);
+
+ /* Connect the GtkEventBox signal */
+ g_signal_connect(gtk_builder_get_object(builder, "eventbox_key_chooser"), "key-press-event",
+ G_CALLBACK(remmina_key_chooser_dialog_on_key_press), arguments);
+
+ /* Show the dialog and destroy it after the use */
+ arguments->response = gtk_dialog_run(dialog);
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+ /* The delete button set the keyval 0 */
+ if (arguments->response == GTK_RESPONSE_REJECT)
+ arguments->keyval = 0;
+ return arguments;
+}
+
+/* Get the uppercase character value of a keyval */
+gchar* remmina_key_chooser_get_value(guint keyval, guint state)
+{
+ TRACE_CALL(__func__);
+
+ if (!keyval)
+ return g_strdup(KEY_CHOOSER_NONE);
+
+ return g_strdup_printf("%s%s%s%s%s%s%s",
+ (state & GDK_SHIFT_MASK) ? KEY_MODIFIER_SHIFT : "",
+ (state & GDK_CONTROL_MASK) ? KEY_MODIFIER_CTRL : "",
+ (state & GDK_MOD1_MASK) ? KEY_MODIFIER_ALT : "",
+ (state & GDK_SUPER_MASK) ? KEY_MODIFIER_SUPER : "",
+ (state & GDK_HYPER_MASK) ? KEY_MODIFIER_HYPER : "",
+ (state & GDK_META_MASK) ? KEY_MODIFIER_META : "",
+ gdk_keyval_name(gdk_keyval_to_upper(keyval)));
+}
+
+/* Get the keyval of a (lowercase) character value */
+guint remmina_key_chooser_get_keyval(const gchar *value)
+{
+ TRACE_CALL(__func__);
+ gchar *patterns[] =
+ {
+ KEY_MODIFIER_SHIFT,
+ KEY_MODIFIER_CTRL,
+ KEY_MODIFIER_ALT,
+ KEY_MODIFIER_SUPER,
+ KEY_MODIFIER_HYPER,
+ KEY_MODIFIER_META,
+ NULL
+ };
+ gint i;
+ gchar *tmpvalue;
+ gchar *newvalue;
+ guint keyval;
+
+ if (g_strcmp0(value, KEY_CHOOSER_NONE) == 0)
+ return 0;
+
+ /* Remove any modifier text before to get the keyval */
+ newvalue = g_strdup(value);
+ for (i = 0; i < g_strv_length(patterns); i++) {
+ tmpvalue = remmina_public_str_replace(newvalue, patterns[i], "");
+ g_free(newvalue);
+ newvalue = g_strdup(tmpvalue);
+ g_free(tmpvalue);
+ }
+ keyval = gdk_keyval_to_lower(gdk_keyval_from_name(newvalue));
+ g_free(newvalue);
+ return keyval;
+}