summaryrefslogtreecommitdiffstats
path: root/plugins/rdp/rdp_settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/rdp/rdp_settings.c')
-rw-r--r--plugins/rdp/rdp_settings.c759
1 files changed, 759 insertions, 0 deletions
diff --git a/plugins/rdp/rdp_settings.c b/plugins/rdp/rdp_settings.c
new file mode 100644
index 0000000..7a3d4aa
--- /dev/null
+++ b/plugins/rdp/rdp_settings.c
@@ -0,0 +1,759 @@
+/*
+ * Remmina - The GTK+ Remote Desktop Client
+ * Copyright (C) 2010-2011 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 "rdp_settings.h"
+#include <freerdp/locale/keyboard.h>
+
+static guint keyboard_layout = 0;
+static guint rdp_keyboard_layout = 0;
+static gchar *rdp_keyboard_remapping_list = NULL;
+
+static void remmina_rdp_settings_kbd_init(void)
+{
+ TRACE_CALL(__func__);
+#if FREERDP_CHECK_VERSION(2, 3, 0)
+ rdp_keyboard_remapping_list = g_strdup(
+ remmina_plugin_service->pref_get_value("rdp_kbd_remap"));
+ REMMINA_PLUGIN_DEBUG("rdp_keyboard_remapping_list: %s", rdp_keyboard_remapping_list);
+ keyboard_layout = freerdp_keyboard_init_ex(rdp_keyboard_layout, rdp_keyboard_remapping_list);
+#else
+ keyboard_layout = freerdp_keyboard_init(rdp_keyboard_layout);
+#endif
+}
+
+void remmina_rdp_settings_init(void)
+{
+ TRACE_CALL(__func__);
+ gchar *value;
+
+ value = remmina_plugin_service->pref_get_value("rdp_keyboard_layout");
+
+ if (value && value[0])
+ rdp_keyboard_layout = strtoul(value, NULL, 16);
+
+ g_free(value);
+
+ remmina_rdp_settings_kbd_init();
+}
+
+guint remmina_rdp_settings_get_keyboard_layout(void)
+{
+ TRACE_CALL(__func__);
+ return keyboard_layout;
+}
+
+#define REMMINA_TYPE_PLUGIN_RDPSET_GRID (remmina_rdp_settings_grid_get_type())
+#define REMMINA_RDPSET_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), REMMINA_TYPE_PLUGIN_RDPSET_GRID, RemminaPluginRdpsetGrid))
+#define REMMINA_RDPSET_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), REMMINA_TYPE_PLUGIN_RDPSET_GRID, RemminaPluginRdpsetGridClass))
+#define REMMINA_IS_PLUGIN_RDPSET_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), REMMINA_TYPE_PLUGIN_RDPSET_GRID))
+#define REMMINA_IS_PLUGIN_RDPSET_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), REMMINA_TYPE_PLUGIN_RDPSET_GRID))
+#define REMMINA_RDPSET_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), REMMINA_TYPE_PLUGIN_RDPSET_GRID, RemminaPluginRdpsetGridClass))
+
+typedef struct _RemminaPluginRdpsetGrid {
+ GtkGrid grid;
+
+ GtkWidget * keyboard_layout_label;
+ GtkWidget * keyboard_layout_combo;
+ GtkListStore * keyboard_layout_store;
+
+ GtkWidget * quality_combo;
+ GtkListStore * quality_store;
+ GtkWidget * wallpaper_check;
+ GtkWidget * windowdrag_check;
+ GtkWidget * menuanimation_check;
+ GtkWidget * theme_check;
+ GtkWidget * cursorshadow_check;
+ GtkWidget * cursorblinking_check;
+ GtkWidget * fontsmoothing_check;
+ GtkWidget * composition_check;
+ GtkWidget * use_client_keymap_check;
+ GtkWidget * disable_smooth_scrolling_check;
+ GtkWidget * reconnect_attempts;
+ GtkWidget * kbd_remap;
+
+ /* FreeRDP /scale-desktop: Scaling of desktop app */
+ GtkWidget * desktop_scale_factor_spin;
+ /* FreeRDP /scale-device: Scaling of appstore app */
+ GtkListStore * device_scale_factor_store;
+ GtkWidget * device_scale_factor_combo;
+ /* FreeRDP /orientation: Orientation of display */
+ GtkListStore * desktop_orientation_store;
+ GtkWidget * desktop_orientation_combo;
+
+ guint quality_values[10];
+} RemminaPluginRdpsetGrid;
+
+typedef struct _RemminaPluginRdpsetGridClass {
+ GtkGridClass parent_class;
+} RemminaPluginRdpsetGridClass;
+
+GType remmina_rdp_settings_grid_get_type(void) G_GNUC_CONST;
+
+G_DEFINE_TYPE(RemminaPluginRdpsetGrid, remmina_rdp_settings_grid, GTK_TYPE_GRID)
+
+static void remmina_rdp_settings_grid_class_init(RemminaPluginRdpsetGridClass *klass)
+{
+ TRACE_CALL(__func__);
+}
+
+static void remmina_rdp_settings_grid_destroy(GtkWidget *widget, gpointer data)
+{
+ TRACE_CALL(__func__);
+ gchar *s;
+ guint new_layout;
+ GtkTreeIter iter;
+ RemminaPluginRdpsetGrid *grid;
+ gint val;
+
+ grid = REMMINA_RDPSET_GRID(widget);
+
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->keyboard_layout_combo), &iter)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(grid->keyboard_layout_store), &iter, 0, &new_layout, -1);
+
+ if (new_layout != rdp_keyboard_layout) {
+ rdp_keyboard_layout = new_layout;
+ s = g_strdup_printf("%X", new_layout);
+ remmina_plugin_service->pref_set_value("rdp_keyboard_layout", s);
+ g_free(s);
+
+ remmina_rdp_settings_kbd_init();
+ }
+ }
+
+ remmina_plugin_service->pref_set_value("rdp_use_client_keymap",
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->use_client_keymap_check)) ? "1" : "0");
+
+ remmina_plugin_service->pref_set_value("rdp_disable_smooth_scrolling",
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->disable_smooth_scrolling_check)) ? "1" : "0");
+
+ remmina_plugin_service->pref_set_value("rdp_reconnect_attempts",
+ gtk_entry_get_text(GTK_ENTRY(grid->reconnect_attempts)));
+
+ remmina_plugin_service->pref_set_value("rdp_kbd_remap",
+ gtk_entry_get_text(GTK_ENTRY(grid->kbd_remap)));
+
+ s = g_strdup_printf("%X", grid->quality_values[0]);
+ remmina_plugin_service->pref_set_value("rdp_quality_0", s);
+ g_free(s);
+
+ s = g_strdup_printf("%X", grid->quality_values[1]);
+ remmina_plugin_service->pref_set_value("rdp_quality_1", s);
+ g_free(s);
+
+ s = g_strdup_printf("%X", grid->quality_values[2]);
+ remmina_plugin_service->pref_set_value("rdp_quality_2", s);
+ g_free(s);
+
+ s = g_strdup_printf("%X", grid->quality_values[9]);
+ remmina_plugin_service->pref_set_value("rdp_quality_9", s);
+ g_free(s);
+
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->device_scale_factor_combo), &iter))
+ gtk_tree_model_get(GTK_TREE_MODEL(grid->device_scale_factor_store), &iter, 0, &val, -1);
+ else
+ val = 0;
+ s = g_strdup_printf("%d", val);
+ remmina_plugin_service->pref_set_value("rdp_deviceScaleFactor", s);
+ g_free(s);
+
+ val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin));
+ s = g_strdup_printf("%d", val);
+ remmina_plugin_service->pref_set_value("rdp_desktopScaleFactor", s);
+ g_free(s);
+
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->desktop_orientation_combo), &iter))
+ gtk_tree_model_get(GTK_TREE_MODEL(grid->desktop_orientation_store), &iter, 0, &val, -1);
+ else
+ val = 0;
+ s = g_strdup_printf("%d", val);
+ remmina_plugin_service->pref_set_value("rdp_desktopOrientation", s);
+ g_free(s);
+}
+
+static void remmina_rdp_settings_grid_load_layout(RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ gchar *s;
+ GtkTreeIter iter;
+ RDP_KEYBOARD_LAYOUT *layouts;
+
+ gtk_list_store_append(grid->keyboard_layout_store, &iter);
+ gtk_list_store_set(grid->keyboard_layout_store, &iter, 0, 0, 1, _("<Auto-detect>"), -1);
+
+ if (rdp_keyboard_layout == 0)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(grid->keyboard_layout_combo), 0);
+
+ gtk_label_set_text(GTK_LABEL(grid->keyboard_layout_label), "-");
+
+#if FREERDP_VERSION_MAJOR >= 3
+ size_t layout_count = 0;
+ layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_VARIANT, &layout_count);
+
+ for (DWORD i = 0; i < layout_count; i++) {
+ s = g_strdup_printf("%08X - %s", layouts[i].code, layouts[i].name);
+ gtk_list_store_append(grid->keyboard_layout_store, &iter);
+ gtk_list_store_set(grid->keyboard_layout_store, &iter, 0, layouts[i].code, 1, s, -1);
+
+ if (rdp_keyboard_layout == layouts[i].code)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(grid->keyboard_layout_combo), i + 1);
+
+ if (keyboard_layout == layouts[i].code)
+ gtk_label_set_text(GTK_LABEL(grid->keyboard_layout_label), s);
+
+ g_free(s);
+ }
+
+ freerdp_keyboard_layouts_free(layouts, layout_count);
+#else
+ layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
+
+ for (DWORD i = 0; layouts[i].code; i++) {
+ s = g_strdup_printf("%08X - %s", layouts[i].code, layouts[i].name);
+ gtk_list_store_append(grid->keyboard_layout_store, &iter);
+ gtk_list_store_set(grid->keyboard_layout_store, &iter, 0, layouts[i].code, 1, s, -1);
+
+ if (rdp_keyboard_layout == layouts[i].code)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(grid->keyboard_layout_combo), i + 1);
+
+ if (keyboard_layout == layouts[i].code)
+ gtk_label_set_text(GTK_LABEL(grid->keyboard_layout_label), s);
+
+ g_free(s);
+ }
+
+ freerdp_keyboard_layouts_free(layouts);
+#endif
+}
+
+static void remmina_rdp_settings_grid_load_devicescalefactor_combo(RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ GtkTreeIter iter;
+
+ gtk_list_store_append(grid->device_scale_factor_store, &iter);
+ gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 0, 1, _("<Not set>"), -1);
+ gtk_list_store_append(grid->device_scale_factor_store, &iter);
+ gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 100, 1, "100%", -1);
+ gtk_list_store_append(grid->device_scale_factor_store, &iter);
+ gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 140, 1, "140%", -1);
+ gtk_list_store_append(grid->device_scale_factor_store, &iter);
+ gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 180, 1, "180%", -1);
+}
+
+static void remmina_rdp_settings_grid_load_desktoporientation_combo(RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ GtkTreeIter iter;
+
+ gtk_list_store_append(grid->desktop_orientation_store, &iter);
+ gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 0, 1, "0°", -1);
+ gtk_list_store_append(grid->desktop_orientation_store, &iter);
+ gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 90, 1, "90°", -1);
+ gtk_list_store_append(grid->desktop_orientation_store, &iter);
+ gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 180, 1, "180°", -1);
+ gtk_list_store_append(grid->desktop_orientation_store, &iter);
+ gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 270, 1, "270°", -1);
+}
+
+static void remmina_rdp_settings_grid_load_quality(RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ gchar *value;
+ GtkTreeIter iter;
+
+ gtk_list_store_append(grid->quality_store, &iter);
+ gtk_list_store_set(grid->quality_store, &iter, 0, -1, 1, _("<Choose a quality level to edit…>"), -1);
+ gtk_list_store_append(grid->quality_store, &iter);
+ gtk_list_store_set(grid->quality_store, &iter, 0, 0, 1, _("Poor (fastest)"), -1);
+ gtk_list_store_append(grid->quality_store, &iter);
+ gtk_list_store_set(grid->quality_store, &iter, 0, 1, 1, _("Medium"), -1);
+ gtk_list_store_append(grid->quality_store, &iter);
+ gtk_list_store_set(grid->quality_store, &iter, 0, 2, 1, _("Good"), -1);
+ gtk_list_store_append(grid->quality_store, &iter);
+ gtk_list_store_set(grid->quality_store, &iter, 0, 9, 1, _("Best (slowest)"), -1);
+
+ memset(grid->quality_values, 0, sizeof(grid->quality_values));
+
+ value = remmina_plugin_service->pref_get_value("rdp_quality_0");
+ grid->quality_values[0] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_0);
+ g_free(value);
+
+ value = remmina_plugin_service->pref_get_value("rdp_quality_1");
+ grid->quality_values[1] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_1);
+ g_free(value);
+
+ value = remmina_plugin_service->pref_get_value("rdp_quality_2");
+ grid->quality_values[2] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_2);
+ g_free(value);
+
+ value = remmina_plugin_service->pref_get_value("rdp_quality_9");
+ grid->quality_values[9] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_9);
+ g_free(value);
+}
+
+static void remmina_rdp_settings_appscale_on_changed(GtkComboBox *widget, RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ GtkTreeIter iter;
+ guint i = 0;
+
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->device_scale_factor_combo), &iter))
+ gtk_tree_model_get(GTK_TREE_MODEL(grid->device_scale_factor_store), &iter, 0, &i, -1);
+ if (i == 0) {
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->desktop_scale_factor_spin), FALSE);
+ gtk_spin_button_set_range(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), 0, 0);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), 0);
+ } else {
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->desktop_scale_factor_spin), TRUE);
+ gtk_spin_button_set_range(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), 100, 500);
+ // gtk_spin_button_set_value(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), i);
+ }
+}
+
+static void remmina_rdp_settings_quality_on_changed(GtkComboBox *widget, RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ guint v;
+ guint i = 0;
+ GtkTreeIter iter;
+ gboolean sensitive;
+
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->quality_combo), &iter)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(grid->quality_store), &iter, 0, &i, -1);
+ sensitive = (i != -1);
+
+ if (sensitive)
+ v = grid->quality_values[i];
+ else
+ v = 0x3f; /* All checkboxes disabled */
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->wallpaper_check), (v & 1) == 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->windowdrag_check), (v & 2) == 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->menuanimation_check), (v & 4) == 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->theme_check), (v & 8) == 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->cursorshadow_check), (v & 0x20) == 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->cursorblinking_check), (v & 0x40) == 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->fontsmoothing_check), (v & 0x80) != 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->composition_check), (v & 0x100) != 0);
+
+
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->wallpaper_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->windowdrag_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->menuanimation_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->theme_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->cursorshadow_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->cursorblinking_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->fontsmoothing_check), sensitive);
+ gtk_widget_set_sensitive(GTK_WIDGET(grid->composition_check), sensitive);
+ }
+}
+
+static void remmina_rdp_settings_quality_option_on_toggled(GtkToggleButton *togglebutton, RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ guint v;
+ guint i = 0;
+ GtkTreeIter iter;
+
+ if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->quality_combo), &iter)) {
+ gtk_tree_model_get(GTK_TREE_MODEL(grid->quality_store), &iter, 0, &i, -1);
+ if (i != -1) {
+ v = 0;
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->wallpaper_check)) ? 0 : 1);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->windowdrag_check)) ? 0 : 2);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->menuanimation_check)) ? 0 : 4);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->theme_check)) ? 0 : 8);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->cursorshadow_check)) ? 0 : 0x20);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->cursorblinking_check)) ? 0 : 0x40);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->fontsmoothing_check)) ? 0x80 : 0);
+ v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->composition_check)) ? 0x100 : 0);
+ grid->quality_values[i] = v;
+ }
+ }
+}
+
+static void remmina_rdp_settings_set_combo_active_item(GtkComboBox *combo, int itemval)
+{
+ GtkTreeIter iter;
+ int i;
+ GtkTreeModel *m;
+ gboolean valid;
+
+ m = gtk_combo_box_get_model(combo);
+ if (!m)
+ return;
+
+ valid = gtk_tree_model_get_iter_first(m, &iter);
+ while (valid) {
+ gtk_tree_model_get(m, &iter, 0, &i, -1);
+ if (i == itemval)
+ gtk_combo_box_set_active_iter(combo, &iter);
+ valid = gtk_tree_model_iter_next(m, &iter);
+ }
+}
+
+static void remmina_rdp_settings_grid_init(RemminaPluginRdpsetGrid *grid)
+{
+ TRACE_CALL(__func__);
+ gchar *s;
+ GtkWidget *widget;
+ GtkCellRenderer *renderer;
+ int desktopOrientation, desktopScaleFactor, deviceScaleFactor;
+
+ /* Create the grid */
+ g_signal_connect(G_OBJECT(grid), "destroy", G_CALLBACK(remmina_rdp_settings_grid_destroy), NULL);
+ gtk_grid_set_row_homogeneous(GTK_GRID(grid), FALSE);
+ gtk_grid_set_column_homogeneous(GTK_GRID(grid), FALSE);
+ gtk_container_set_border_width(GTK_CONTAINER(grid), 8);
+ gtk_grid_set_row_spacing(GTK_GRID(grid), 4);
+ gtk_grid_set_column_spacing(GTK_GRID(grid), 4);
+
+ /* Create the content */
+ widget = gtk_label_new(_("Keyboard layout"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
+ gtk_widget_set_margin_top(GTK_WIDGET(widget), 18);
+ gtk_grid_attach(GTK_GRID(grid), widget, 0, 0, 1, 1);
+
+ grid->keyboard_layout_store = gtk_list_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
+ widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->keyboard_layout_store));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 0, 2, 1);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
+ grid->keyboard_layout_combo = widget;
+
+ widget = gtk_label_new("-");
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 1, 2, 1);
+ grid->keyboard_layout_label = widget;
+
+ remmina_rdp_settings_grid_load_layout(grid);
+
+ widget = gtk_check_button_new_with_label(_("Use client keyboard mapping"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 2, 1, 1);
+ grid->use_client_keymap_check = widget;
+
+ s = remmina_plugin_service->pref_get_value("rdp_use_client_keymap");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
+ s && s[0] == '1' ? TRUE : FALSE);
+ g_free(s);
+
+ widget = gtk_label_new(_("Keyboard scancode remapping"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 3, 1, 1);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ widget = gtk_entry_new();
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_END);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 3, 1, 1);
+ gtk_entry_set_width_chars(GTK_ENTRY(widget), 32);
+#if FREERDP_CHECK_VERSION(2, 3, 0)
+ /* This is the default, but we set it to make things crystal clear */
+ gtk_widget_set_sensitive (widget, TRUE);
+ gtk_widget_set_tooltip_text(widget, _("List of key=value,… pairs to remap scancodes. E.g. 0x56=0x29,0x29=0x56"));
+#else
+ gtk_widget_set_sensitive (widget, FALSE);
+ gtk_widget_set_tooltip_text(widget, _("FreeRDP > 2.3.0 is required to map scancodes"));
+#endif
+ s = remmina_plugin_service->pref_get_value("rdp_kbd_remap");
+ if (s && s[0])
+ gtk_entry_set_text(GTK_ENTRY(widget), s);
+ g_free(s);
+ grid->kbd_remap = widget;
+
+ widget = gtk_label_new(_("Quality settings"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
+ gtk_grid_attach(GTK_GRID(grid), widget, 0, 4, 1, 1);
+
+ grid->quality_store = gtk_list_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
+ widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->quality_store));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 4, 2, 1);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
+ g_signal_connect(G_OBJECT(widget), "changed",
+ G_CALLBACK(remmina_rdp_settings_quality_on_changed), grid);
+ grid->quality_combo = widget;
+
+ remmina_rdp_settings_grid_load_quality(grid);
+
+ widget = gtk_check_button_new_with_label(_("Wallpaper"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 5, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->wallpaper_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Window drag"));
+ gtk_widget_show(widget);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 5, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->windowdrag_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Menu animation"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 6, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->menuanimation_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Theme"));
+ gtk_widget_show(widget);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 6, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->theme_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Cursor shadow"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 7, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->cursorshadow_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Cursor blinking"));
+ gtk_widget_show(widget);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 7, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->cursorblinking_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Font smoothing"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 8, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->fontsmoothing_check = widget;
+
+ widget = gtk_check_button_new_with_label(_("Composition"));
+ gtk_widget_show(widget);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 8, 1, 1);
+ g_signal_connect(G_OBJECT(widget), "toggled",
+ G_CALLBACK(remmina_rdp_settings_quality_option_on_toggled), grid);
+ grid->composition_check = widget;
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(grid->quality_combo), 0);
+
+
+ widget = gtk_label_new(_("Remote scale factor"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
+ gtk_grid_attach(GTK_GRID(grid), widget, 0, 9, 1, 1);
+
+ grid->device_scale_factor_store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
+ grid->desktop_orientation_store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
+
+ remmina_rdp_settings_get_orientation_scale_prefs(&desktopOrientation, &desktopScaleFactor, &deviceScaleFactor);
+ remmina_rdp_settings_grid_load_devicescalefactor_combo(grid);
+ remmina_rdp_settings_grid_load_desktoporientation_combo(grid);
+
+ widget = gtk_label_new(_("Desktop scale factor %"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 9, 1, 1);
+
+ widget = gtk_spin_button_new_with_range(0, 10000, 1);
+ gtk_widget_show(widget);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 9, 1, 1);
+ grid->desktop_scale_factor_spin = widget;
+
+ widget = gtk_label_new(_("Device scale factor %"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 10, 1, 1);
+
+ widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->device_scale_factor_store));
+ gtk_widget_show(widget);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 10, 1, 1);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
+ grid->device_scale_factor_combo = widget;
+
+ remmina_rdp_settings_set_combo_active_item(GTK_COMBO_BOX(grid->device_scale_factor_combo), deviceScaleFactor);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), (gdouble)desktopScaleFactor);
+
+ g_signal_connect(G_OBJECT(widget), "changed",
+ G_CALLBACK(remmina_rdp_settings_appscale_on_changed), grid);
+ remmina_rdp_settings_appscale_on_changed(GTK_COMBO_BOX(grid->device_scale_factor_combo), grid);
+
+ widget = gtk_label_new(_("Desktop orientation"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
+ gtk_grid_attach(GTK_GRID(grid), widget, 0, 11, 1, 1);
+
+ widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->desktop_orientation_store));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 11, 2, 1);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
+ grid->desktop_orientation_combo = widget;
+
+ remmina_rdp_settings_set_combo_active_item(GTK_COMBO_BOX(grid->desktop_orientation_combo), desktopOrientation);
+
+ widget = gtk_label_new(_("Input device settings"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
+ gtk_grid_attach(GTK_GRID(grid), widget, 0, 12, 1, 1);
+
+ widget = gtk_check_button_new_with_label(_("Disable smooth scrolling"));
+ gtk_widget_show(widget);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 12, 2, 1);
+ grid->disable_smooth_scrolling_check = widget;
+
+ s = remmina_plugin_service->pref_get_value("rdp_disable_smooth_scrolling");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
+ s && s[0] == '1' ? TRUE : FALSE);
+ g_free(s);
+
+ widget = gtk_label_new(_("General settings"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
+ gtk_grid_attach(GTK_GRID(grid), widget, 0, 13, 1, 1);
+ widget = gtk_label_new(_("Reconnect attempts number"));
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
+ gtk_grid_attach(GTK_GRID(grid), widget, 1, 13, 1, 1);
+ widget = gtk_entry_new();
+ gtk_widget_show(widget);
+ gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_END);
+ gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
+ gtk_grid_attach(GTK_GRID(grid), widget, 2, 13, 1, 1);
+ gtk_entry_set_input_purpose(GTK_ENTRY(widget), GTK_INPUT_PURPOSE_NUMBER);
+ gtk_entry_set_input_hints(GTK_ENTRY(widget), GTK_INPUT_HINT_NONE);
+ gtk_widget_set_tooltip_text(widget, _("The maximum number of reconnect attempts upon an RDP disconnect (default: 20)"));
+ s = remmina_plugin_service->pref_get_value("rdp_reconnect_attempts");
+ if (s && s[0])
+ gtk_entry_set_text(GTK_ENTRY(widget), s);
+ g_free(s);
+ grid->reconnect_attempts = widget;
+
+}
+
+GtkWidget *remmina_rdp_settings_new(RemminaPrefPlugin* plugin)
+{
+ TRACE_CALL(__func__);
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET(g_object_new(REMMINA_TYPE_PLUGIN_RDPSET_GRID, NULL));
+ gtk_widget_show(widget);
+
+ return widget;
+}
+
+void remmina_rdp_settings_get_orientation_scale_prefs(int *desktopOrientation, int *desktopScaleFactor, int *deviceScaleFactor)
+{
+ TRACE_CALL(__func__);
+
+ /* See https://msdn.microsoft.com/en-us/library/cc240510.aspx */
+
+ int orientation, dpsf, desf;
+ gchar *s;
+
+ *desktopOrientation = *desktopScaleFactor = *deviceScaleFactor = 0;
+
+ s = remmina_plugin_service->pref_get_value("rdp_desktopOrientation");
+ orientation = s ? atoi(s) : 0;
+ g_free(s);
+ if (orientation != 90 && orientation != 180 && orientation != 270)
+ orientation = 0;
+ *desktopOrientation = orientation;
+
+ s = remmina_plugin_service->pref_get_value("rdp_desktopScaleFactor");
+ dpsf = s ? atoi(s) : 0;
+ g_free(s);
+ if (dpsf < 100 || dpsf > 500)
+ return;
+
+ s = remmina_plugin_service->pref_get_value("rdp_deviceScaleFactor");
+ desf = s ? atoi(s) : 0;
+ g_free(s);
+ if (desf != 100 && desf != 140 && desf != 180)
+ return;
+
+ *desktopScaleFactor = dpsf;
+ *deviceScaleFactor = desf;
+}