remmina_key_chooser.c 4.77 KB
Newer Older
Antenore Gatta's avatar
Antenore Gatta committed
1 2 3 4
/*
 * Remmina - The GTK+ Remote Desktop Client
 * Copyright (C) 2009-2010 Vic Lee
 * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5
 * Copyright (C) 2016-2019 Antenore Gatta, Giovanni Panozzo
Antenore Gatta's avatar
Antenore Gatta committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * 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.
 *
 */
36

37 38
#include <gtk/gtk.h>
#include <glib/gi18n.h>
39
#include "remmina_key_chooser.h"
40
#include "remmina_public.h"
41
#include "remmina/remmina_trace_calls.h"
42

43 44
/* Handle key-presses on the GtkEventBox */
static gboolean remmina_key_chooser_dialog_on_key_press(GtkWidget *widget, GdkEventKey *event, RemminaKeyChooserArguments *arguments)
45
{
46
	TRACE_CALL(__func__);
Antenore Gatta's avatar
Antenore Gatta committed
47
	if (!arguments->use_modifiers || !event->is_modifier) {
48 49 50
		arguments->state = event->state;
		arguments->keyval = gdk_keyval_to_lower(event->keyval);
		gtk_dialog_response(GTK_DIALOG(gtk_widget_get_toplevel(widget)),
Antenore Gatta's avatar
Antenore Gatta committed
51
			event->keyval == GDK_KEY_Escape ? GTK_RESPONSE_CANCEL : GTK_RESPONSE_OK);
52
	}
53
	return TRUE;
54 55
}

56
/* Show a key chooser dialog and return the keyval for the selected key */
57
RemminaKeyChooserArguments* remmina_key_chooser_new(GtkWindow *parent_window, gboolean use_modifiers)
58
{
59
	TRACE_CALL(__func__);
60 61 62 63 64 65 66 67 68 69
	GtkBuilder *builder = remmina_public_gtk_builder_new_from_file("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);
Muflone's avatar
Muflone committed
70 71
	/* Connect the GtkEventBox signal */
	g_signal_connect(gtk_builder_get_object(builder, "eventbox_key_chooser"), "key-press-event",
Antenore Gatta's avatar
Antenore Gatta committed
72
		G_CALLBACK(remmina_key_chooser_dialog_on_key_press), arguments);
73
	/* Show the dialog and destroy it after the use */
74
	arguments->response = gtk_dialog_run(dialog);
75
	gtk_widget_destroy(GTK_WIDGET(dialog));
76
	/* The delete button set the keyval 0 */
77
	if (arguments->response == GTK_RESPONSE_REJECT)
78 79
		arguments->keyval = 0;
	return arguments;
80 81
}

82 83
/* Get the uppercase character value of a keyval */
gchar* remmina_key_chooser_get_value(guint keyval, guint state)
84
{
85
	TRACE_CALL(__func__);
86 87

	if (!keyval)
88
		return g_strdup(KEY_CHOOSER_NONE);
89 90

	return g_strdup_printf("%s%s%s%s%s%s%s",
Antenore Gatta's avatar
Antenore Gatta committed
91 92 93 94 95 96 97
		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)));
98 99
}

100 101
/* Get the keyval of a (lowercase) character value */
guint remmina_key_chooser_get_keyval(const gchar *value)
102
{
103
	TRACE_CALL(__func__);
104 105 106 107 108 109 110 111 112
	gchar *patterns[] =
	{
		KEY_MODIFIER_SHIFT,
		KEY_MODIFIER_CTRL,
		KEY_MODIFIER_ALT,
		KEY_MODIFIER_SUPER,
		KEY_MODIFIER_HYPER,
		KEY_MODIFIER_META,
		NULL
113 114 115 116 117 118 119 120
	};
	gint i;
	gchar *tmpvalue;
	gchar *newvalue;
	guint keyval;

	if (g_strcmp0(value, KEY_CHOOSER_NONE) == 0)
		return 0;
121

122 123
	/* Remove any modifier text before to get the keyval */
	newvalue = g_strdup(value);
Antenore Gatta's avatar
Antenore Gatta committed
124
	for (i = 0; i < g_strv_length(patterns); i++) {
125 126 127 128
		tmpvalue = remmina_public_str_replace(newvalue, patterns[i], "");
		g_free(newvalue);
		newvalue = g_strdup(tmpvalue);
		g_free(tmpvalue);
129
	}
130 131 132
	keyval = gdk_keyval_to_lower(gdk_keyval_from_name(newvalue));
	g_free(newvalue);
	return keyval;
133
}