Remmina - The GTK+ Remote Desktop Client  v1.4.33
Remmina is a remote desktop client written in GTK+, aiming to be useful for system administrators and travellers, who need to work with lots of remote computers in front of either large monitors or tiny netbooks. Remmina supports multiple network protocols in an integrated and consistent user interface. Currently RDP, VNC, NX, XDMCP and SSH are supported.
rdp_settings.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2010-2011 Vic Lee
4  * Copyright (C) 2014-2015 Antenore Gatta, Fabio Castelli, Giovanni Panozzo
5  * Copyright (C) 2016-2023 Antenore Gatta, Giovanni Panozzo
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  * In addition, as a special exception, the copyright holders give
23  * permission to link the code of portions of this program with the
24  * OpenSSL library under certain conditions as described in each
25  * individual source file, and distribute linked combinations
26  * including the two.
27  * You must obey the GNU General Public License in all respects
28  * for all of the code used other than OpenSSL. * If you modify
29  * file(s) with this exception, you may extend this exception to your
30  * version of the file(s), but you are not obligated to do so. * If you
31  * do not wish to do so, delete this exception statement from your
32  * version. * If you delete this exception statement from all source
33  * files in the program, then also delete it here.
34  *
35  */
36 
37 #include "rdp_settings.h"
38 #include <freerdp/locale/keyboard.h>
39 
40 static guint keyboard_layout = 0;
41 static guint rdp_keyboard_layout = 0;
42 static gchar *rdp_keyboard_remapping_list = NULL;
43 
45 {
46  TRACE_CALL(__func__);
47 #if FREERDP_CHECK_VERSION(2, 3, 0)
48  rdp_keyboard_remapping_list = g_strdup(
49  remmina_plugin_service->pref_get_value("rdp_kbd_remap"));
50  REMMINA_PLUGIN_DEBUG("rdp_keyboard_remapping_list: %s", rdp_keyboard_remapping_list);
52 #else
53  keyboard_layout = freerdp_keyboard_init(rdp_keyboard_layout);
54 #endif
55 }
56 
58 {
59  TRACE_CALL(__func__);
60  gchar *value;
61 
62  value = remmina_plugin_service->pref_get_value("rdp_keyboard_layout");
63 
64  if (value && value[0])
65  rdp_keyboard_layout = strtoul(value, NULL, 16);
66 
67  g_free(value);
68 
70 }
71 
73 {
74  TRACE_CALL(__func__);
75  return keyboard_layout;
76 }
77 
78 #define REMMINA_TYPE_PLUGIN_RDPSET_GRID (remmina_rdp_settings_grid_get_type())
79 #define REMMINA_RDPSET_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), REMMINA_TYPE_PLUGIN_RDPSET_GRID, RemminaPluginRdpsetGrid))
80 #define REMMINA_RDPSET_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), REMMINA_TYPE_PLUGIN_RDPSET_GRID, RemminaPluginRdpsetGridClass))
81 #define REMMINA_IS_PLUGIN_RDPSET_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), REMMINA_TYPE_PLUGIN_RDPSET_GRID))
82 #define REMMINA_IS_PLUGIN_RDPSET_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), REMMINA_TYPE_PLUGIN_RDPSET_GRID))
83 #define REMMINA_RDPSET_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), REMMINA_TYPE_PLUGIN_RDPSET_GRID, RemminaPluginRdpsetGridClass))
84 
85 typedef struct _RemminaPluginRdpsetGrid {
86  GtkGrid grid;
87 
88  GtkWidget * keyboard_layout_label;
89  GtkWidget * keyboard_layout_combo;
90  GtkListStore * keyboard_layout_store;
91 
92  GtkWidget * quality_combo;
93  GtkListStore * quality_store;
94  GtkWidget * wallpaper_check;
95  GtkWidget * windowdrag_check;
96  GtkWidget * menuanimation_check;
97  GtkWidget * theme_check;
98  GtkWidget * cursorshadow_check;
99  GtkWidget * cursorblinking_check;
100  GtkWidget * fontsmoothing_check;
101  GtkWidget * composition_check;
104  GtkWidget * reconnect_attempts;
105  GtkWidget * kbd_remap;
106 
107  /* FreeRDP /scale-desktop: Scaling of desktop app */
109  /* FreeRDP /scale-device: Scaling of appstore app */
112  /* FreeRDP /orientation: Orientation of display */
115 
116  guint quality_values[10];
118 
120  GtkGridClass parent_class;
122 
123 GType remmina_rdp_settings_grid_get_type(void) G_GNUC_CONST;
124 
125 G_DEFINE_TYPE(RemminaPluginRdpsetGrid, remmina_rdp_settings_grid, GTK_TYPE_GRID)
126 
127 static void remmina_rdp_settings_grid_class_init(RemminaPluginRdpsetGridClass *klass)
128 {
129  TRACE_CALL(__func__);
130 }
131 
132 static void remmina_rdp_settings_grid_destroy(GtkWidget *widget, gpointer data)
133 {
134  TRACE_CALL(__func__);
135  gchar *s;
136  guint new_layout;
137  GtkTreeIter iter;
139  gint val;
140 
141  grid = REMMINA_RDPSET_GRID(widget);
142 
143  if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->keyboard_layout_combo), &iter)) {
144  gtk_tree_model_get(GTK_TREE_MODEL(grid->keyboard_layout_store), &iter, 0, &new_layout, -1);
145 
146  if (new_layout != rdp_keyboard_layout) {
147  rdp_keyboard_layout = new_layout;
148  s = g_strdup_printf("%X", new_layout);
149  remmina_plugin_service->pref_set_value("rdp_keyboard_layout", s);
150  g_free(s);
151 
153  }
154  }
155 
156  remmina_plugin_service->pref_set_value("rdp_use_client_keymap",
157  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->use_client_keymap_check)) ? "1" : "0");
158 
159  remmina_plugin_service->pref_set_value("rdp_disable_smooth_scrolling",
160  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->disable_smooth_scrolling_check)) ? "1" : "0");
161 
162  remmina_plugin_service->pref_set_value("rdp_reconnect_attempts",
163  gtk_entry_get_text(GTK_ENTRY(grid->reconnect_attempts)));
164 
165  remmina_plugin_service->pref_set_value("rdp_kbd_remap",
166  gtk_entry_get_text(GTK_ENTRY(grid->kbd_remap)));
167 
168  s = g_strdup_printf("%X", grid->quality_values[0]);
169  remmina_plugin_service->pref_set_value("rdp_quality_0", s);
170  g_free(s);
171 
172  s = g_strdup_printf("%X", grid->quality_values[1]);
173  remmina_plugin_service->pref_set_value("rdp_quality_1", s);
174  g_free(s);
175 
176  s = g_strdup_printf("%X", grid->quality_values[2]);
177  remmina_plugin_service->pref_set_value("rdp_quality_2", s);
178  g_free(s);
179 
180  s = g_strdup_printf("%X", grid->quality_values[9]);
181  remmina_plugin_service->pref_set_value("rdp_quality_9", s);
182  g_free(s);
183 
184  if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->device_scale_factor_combo), &iter))
185  gtk_tree_model_get(GTK_TREE_MODEL(grid->device_scale_factor_store), &iter, 0, &val, -1);
186  else
187  val = 0;
188  s = g_strdup_printf("%d", val);
189  remmina_plugin_service->pref_set_value("rdp_deviceScaleFactor", s);
190  g_free(s);
191 
192  val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin));
193  s = g_strdup_printf("%d", val);
194  remmina_plugin_service->pref_set_value("rdp_desktopScaleFactor", s);
195  g_free(s);
196 
197  if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->desktop_orientation_combo), &iter))
198  gtk_tree_model_get(GTK_TREE_MODEL(grid->desktop_orientation_store), &iter, 0, &val, -1);
199  else
200  val = 0;
201  s = g_strdup_printf("%d", val);
202  remmina_plugin_service->pref_set_value("rdp_desktopOrientation", s);
203  g_free(s);
204 }
205 
207 {
208  TRACE_CALL(__func__);
209  gint i;
210  gchar *s;
211  GtkTreeIter iter;
212  RDP_KEYBOARD_LAYOUT *layouts;
213 
214  gtk_list_store_append(grid->keyboard_layout_store, &iter);
215  gtk_list_store_set(grid->keyboard_layout_store, &iter, 0, 0, 1, _("<Auto-detect>"), -1);
216 
217  if (rdp_keyboard_layout == 0)
218  gtk_combo_box_set_active(GTK_COMBO_BOX(grid->keyboard_layout_combo), 0);
219 
220  gtk_label_set_text(GTK_LABEL(grid->keyboard_layout_label), "-");
221 
222  layouts = freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD | RDP_KEYBOARD_LAYOUT_TYPE_VARIANT);
223 
224  for (i = 0; layouts[i].code; i++) {
225  s = g_strdup_printf("%08X - %s", layouts[i].code, layouts[i].name);
226  gtk_list_store_append(grid->keyboard_layout_store, &iter);
227  gtk_list_store_set(grid->keyboard_layout_store, &iter, 0, layouts[i].code, 1, s, -1);
228 
229  if (rdp_keyboard_layout == layouts[i].code)
230  gtk_combo_box_set_active(GTK_COMBO_BOX(grid->keyboard_layout_combo), i + 1);
231 
232  if (keyboard_layout == layouts[i].code)
233  gtk_label_set_text(GTK_LABEL(grid->keyboard_layout_label), s);
234 
235  g_free(s);
236  }
237 
238  freerdp_keyboard_layouts_free(layouts);
239 }
240 
242 {
243  TRACE_CALL(__func__);
244  GtkTreeIter iter;
245 
246  gtk_list_store_append(grid->device_scale_factor_store, &iter);
247  gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 0, 1, _("<Not set>"), -1);
248  gtk_list_store_append(grid->device_scale_factor_store, &iter);
249  gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 100, 1, "100%", -1);
250  gtk_list_store_append(grid->device_scale_factor_store, &iter);
251  gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 140, 1, "140%", -1);
252  gtk_list_store_append(grid->device_scale_factor_store, &iter);
253  gtk_list_store_set(grid->device_scale_factor_store, &iter, 0, 180, 1, "180%", -1);
254 }
255 
257 {
258  TRACE_CALL(__func__);
259  GtkTreeIter iter;
260 
261  gtk_list_store_append(grid->desktop_orientation_store, &iter);
262  gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 0, 1, "0°", -1);
263  gtk_list_store_append(grid->desktop_orientation_store, &iter);
264  gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 90, 1, "90°", -1);
265  gtk_list_store_append(grid->desktop_orientation_store, &iter);
266  gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 180, 1, "180°", -1);
267  gtk_list_store_append(grid->desktop_orientation_store, &iter);
268  gtk_list_store_set(grid->desktop_orientation_store, &iter, 0, 270, 1, "270°", -1);
269 }
270 
272 {
273  TRACE_CALL(__func__);
274  gchar *value;
275  GtkTreeIter iter;
276 
277  gtk_list_store_append(grid->quality_store, &iter);
278  gtk_list_store_set(grid->quality_store, &iter, 0, -1, 1, _("<Choose a quality level to edit…>"), -1);
279  gtk_list_store_append(grid->quality_store, &iter);
280  gtk_list_store_set(grid->quality_store, &iter, 0, 0, 1, _("Poor (fastest)"), -1);
281  gtk_list_store_append(grid->quality_store, &iter);
282  gtk_list_store_set(grid->quality_store, &iter, 0, 1, 1, _("Medium"), -1);
283  gtk_list_store_append(grid->quality_store, &iter);
284  gtk_list_store_set(grid->quality_store, &iter, 0, 2, 1, _("Good"), -1);
285  gtk_list_store_append(grid->quality_store, &iter);
286  gtk_list_store_set(grid->quality_store, &iter, 0, 9, 1, _("Best (slowest)"), -1);
287 
288  memset(grid->quality_values, 0, sizeof(grid->quality_values));
289 
290  value = remmina_plugin_service->pref_get_value("rdp_quality_0");
291  grid->quality_values[0] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_0);
292  g_free(value);
293 
294  value = remmina_plugin_service->pref_get_value("rdp_quality_1");
295  grid->quality_values[1] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_1);
296  g_free(value);
297 
298  value = remmina_plugin_service->pref_get_value("rdp_quality_2");
299  grid->quality_values[2] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_2);
300  g_free(value);
301 
302  value = remmina_plugin_service->pref_get_value("rdp_quality_9");
303  grid->quality_values[9] = (value && value[0] ? strtoul(value, NULL, 16) : DEFAULT_QUALITY_9);
304  g_free(value);
305 }
306 
308 {
309  TRACE_CALL(__func__);
310  GtkTreeIter iter;
311  guint i = 0;
312 
313  if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->device_scale_factor_combo), &iter))
314  gtk_tree_model_get(GTK_TREE_MODEL(grid->device_scale_factor_store), &iter, 0, &i, -1);
315  if (i == 0) {
316  gtk_widget_set_sensitive(GTK_WIDGET(grid->desktop_scale_factor_spin), FALSE);
317  gtk_spin_button_set_range(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), 0, 0);
318  gtk_spin_button_set_value(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), 0);
319  } else {
320  gtk_widget_set_sensitive(GTK_WIDGET(grid->desktop_scale_factor_spin), TRUE);
321  gtk_spin_button_set_range(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), 100, 500);
322  // gtk_spin_button_set_value(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), i);
323  }
324 }
325 
327 {
328  TRACE_CALL(__func__);
329  guint v;
330  guint i = 0;
331  GtkTreeIter iter;
332  gboolean sensitive;
333 
334  if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->quality_combo), &iter)) {
335  gtk_tree_model_get(GTK_TREE_MODEL(grid->quality_store), &iter, 0, &i, -1);
336  sensitive = (i != -1);
337 
338  if (sensitive)
339  v = grid->quality_values[i];
340  else
341  v = 0x3f; /* All checkboxes disabled */
342 
343  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->wallpaper_check), (v & 1) == 0);
344  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->windowdrag_check), (v & 2) == 0);
345  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->menuanimation_check), (v & 4) == 0);
346  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->theme_check), (v & 8) == 0);
347  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->cursorshadow_check), (v & 0x20) == 0);
348  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->cursorblinking_check), (v & 0x40) == 0);
349  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->fontsmoothing_check), (v & 0x80) != 0);
350  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grid->composition_check), (v & 0x100) != 0);
351 
352 
353  gtk_widget_set_sensitive(GTK_WIDGET(grid->wallpaper_check), sensitive);
354  gtk_widget_set_sensitive(GTK_WIDGET(grid->windowdrag_check), sensitive);
355  gtk_widget_set_sensitive(GTK_WIDGET(grid->menuanimation_check), sensitive);
356  gtk_widget_set_sensitive(GTK_WIDGET(grid->theme_check), sensitive);
357  gtk_widget_set_sensitive(GTK_WIDGET(grid->cursorshadow_check), sensitive);
358  gtk_widget_set_sensitive(GTK_WIDGET(grid->cursorblinking_check), sensitive);
359  gtk_widget_set_sensitive(GTK_WIDGET(grid->fontsmoothing_check), sensitive);
360  gtk_widget_set_sensitive(GTK_WIDGET(grid->composition_check), sensitive);
361  }
362 }
363 
365 {
366  TRACE_CALL(__func__);
367  guint v;
368  guint i = 0;
369  GtkTreeIter iter;
370 
371  if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(grid->quality_combo), &iter)) {
372  gtk_tree_model_get(GTK_TREE_MODEL(grid->quality_store), &iter, 0, &i, -1);
373  if (i != -1) {
374  v = 0;
375  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->wallpaper_check)) ? 0 : 1);
376  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->windowdrag_check)) ? 0 : 2);
377  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->menuanimation_check)) ? 0 : 4);
378  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->theme_check)) ? 0 : 8);
379  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->cursorshadow_check)) ? 0 : 0x20);
380  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->cursorblinking_check)) ? 0 : 0x40);
381  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->fontsmoothing_check)) ? 0x80 : 0);
382  v |= (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(grid->composition_check)) ? 0x100 : 0);
383  grid->quality_values[i] = v;
384  }
385  }
386 }
387 
388 static void remmina_rdp_settings_set_combo_active_item(GtkComboBox *combo, int itemval)
389 {
390  GtkTreeIter iter;
391  int i;
392  GtkTreeModel *m;
393  gboolean valid;
394 
395  m = gtk_combo_box_get_model(combo);
396  if (!m)
397  return;
398 
399  valid = gtk_tree_model_get_iter_first(m, &iter);
400  while (valid) {
401  gtk_tree_model_get(m, &iter, 0, &i, -1);
402  if (i == itemval)
403  gtk_combo_box_set_active_iter(combo, &iter);
404  valid = gtk_tree_model_iter_next(m, &iter);
405  }
406 }
407 
409 {
410  TRACE_CALL(__func__);
411  gchar *s;
412  GtkWidget *widget;
413  GtkCellRenderer *renderer;
414  int desktopOrientation, desktopScaleFactor, deviceScaleFactor;
415 
416  /* Create the grid */
417  g_signal_connect(G_OBJECT(grid), "destroy", G_CALLBACK(remmina_rdp_settings_grid_destroy), NULL);
418  gtk_grid_set_row_homogeneous(GTK_GRID(grid), FALSE);
419  gtk_grid_set_column_homogeneous(GTK_GRID(grid), FALSE);
420  gtk_container_set_border_width(GTK_CONTAINER(grid), 8);
421  gtk_grid_set_row_spacing(GTK_GRID(grid), 4);
422  gtk_grid_set_column_spacing(GTK_GRID(grid), 4);
423 
424  /* Create the content */
425  widget = gtk_label_new(_("Keyboard layout"));
426  gtk_widget_show(widget);
427  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
428  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
429  gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
430  gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
431  gtk_widget_set_margin_top(GTK_WIDGET(widget), 18);
432  gtk_grid_attach(GTK_GRID(grid), widget, 0, 0, 1, 1);
433 
434  grid->keyboard_layout_store = gtk_list_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
435  widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->keyboard_layout_store));
436  gtk_widget_show(widget);
437  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
438  gtk_grid_attach(GTK_GRID(grid), widget, 1, 0, 2, 1);
439 
440  renderer = gtk_cell_renderer_text_new();
441  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
442  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
443  grid->keyboard_layout_combo = widget;
444 
445  widget = gtk_label_new("-");
446  gtk_widget_show(widget);
447  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
448  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
449  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
450  gtk_grid_attach(GTK_GRID(grid), widget, 1, 1, 2, 1);
451  grid->keyboard_layout_label = widget;
452 
454 
455  widget = gtk_check_button_new_with_label(_("Use client keyboard mapping"));
456  gtk_widget_show(widget);
457  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
458  gtk_grid_attach(GTK_GRID(grid), widget, 1, 2, 1, 1);
459  grid->use_client_keymap_check = widget;
460 
461  s = remmina_plugin_service->pref_get_value("rdp_use_client_keymap");
462  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
463  s && s[0] == '1' ? TRUE : FALSE);
464  g_free(s);
465 
466  widget = gtk_label_new(_("Keyboard scancode remapping"));
467  gtk_widget_show(widget);
468  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
469  gtk_grid_attach(GTK_GRID(grid), widget, 1, 3, 1, 1);
470  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
471  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
472  widget = gtk_entry_new();
473  gtk_widget_show(widget);
474  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_END);
475  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
476  gtk_grid_attach(GTK_GRID(grid), widget, 2, 3, 1, 1);
477  gtk_entry_set_width_chars(GTK_ENTRY(widget), 32);
478 #if FREERDP_CHECK_VERSION(2, 3, 0)
479  /* This is the default, but we set it to make things crystal clear */
480  gtk_widget_set_sensitive (widget, TRUE);
481  gtk_widget_set_tooltip_text(widget, _("List of key=value,… pairs to remap scancodes. E.g. 0x56=0x29,0x29=0x56"));
482 #else
483  gtk_widget_set_sensitive (widget, FALSE);
484  gtk_widget_set_tooltip_text(widget, _("FreeRDP > 2.3.0 is required to map scancodes"));
485 #endif
486  s = remmina_plugin_service->pref_get_value("rdp_kbd_remap");
487  if (s && s[0])
488  gtk_entry_set_text(GTK_ENTRY(widget), s);
489  g_free(s);
490  grid->kbd_remap = widget;
491 
492  widget = gtk_label_new(_("Quality settings"));
493  gtk_widget_show(widget);
494  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
495  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
496  gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
497  gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
498  gtk_grid_attach(GTK_GRID(grid), widget, 0, 4, 1, 1);
499 
500  grid->quality_store = gtk_list_store_new(2, G_TYPE_UINT, G_TYPE_STRING);
501  widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->quality_store));
502  gtk_widget_show(widget);
503  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
504  gtk_grid_attach(GTK_GRID(grid), widget, 1, 4, 2, 1);
505 
506  renderer = gtk_cell_renderer_text_new();
507  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
508  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
509  g_signal_connect(G_OBJECT(widget), "changed",
510  G_CALLBACK(remmina_rdp_settings_quality_on_changed), grid);
511  grid->quality_combo = widget;
512 
514 
515  widget = gtk_check_button_new_with_label(_("Wallpaper"));
516  gtk_widget_show(widget);
517  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
518  gtk_grid_attach(GTK_GRID(grid), widget, 1, 5, 1, 1);
519  g_signal_connect(G_OBJECT(widget), "toggled",
521  grid->wallpaper_check = widget;
522 
523  widget = gtk_check_button_new_with_label(_("Window drag"));
524  gtk_widget_show(widget);
525  gtk_grid_attach(GTK_GRID(grid), widget, 2, 5, 1, 1);
526  g_signal_connect(G_OBJECT(widget), "toggled",
528  grid->windowdrag_check = widget;
529 
530  widget = gtk_check_button_new_with_label(_("Menu animation"));
531  gtk_widget_show(widget);
532  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
533  gtk_grid_attach(GTK_GRID(grid), widget, 1, 6, 1, 1);
534  g_signal_connect(G_OBJECT(widget), "toggled",
536  grid->menuanimation_check = widget;
537 
538  widget = gtk_check_button_new_with_label(_("Theme"));
539  gtk_widget_show(widget);
540  gtk_grid_attach(GTK_GRID(grid), widget, 2, 6, 1, 1);
541  g_signal_connect(G_OBJECT(widget), "toggled",
543  grid->theme_check = widget;
544 
545  widget = gtk_check_button_new_with_label(_("Cursor shadow"));
546  gtk_widget_show(widget);
547  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
548  gtk_grid_attach(GTK_GRID(grid), widget, 1, 7, 1, 1);
549  g_signal_connect(G_OBJECT(widget), "toggled",
551  grid->cursorshadow_check = widget;
552 
553  widget = gtk_check_button_new_with_label(_("Cursor blinking"));
554  gtk_widget_show(widget);
555  gtk_grid_attach(GTK_GRID(grid), widget, 2, 7, 1, 1);
556  g_signal_connect(G_OBJECT(widget), "toggled",
558  grid->cursorblinking_check = widget;
559 
560  widget = gtk_check_button_new_with_label(_("Font smoothing"));
561  gtk_widget_show(widget);
562  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
563  gtk_grid_attach(GTK_GRID(grid), widget, 1, 8, 1, 1);
564  g_signal_connect(G_OBJECT(widget), "toggled",
566  grid->fontsmoothing_check = widget;
567 
568  widget = gtk_check_button_new_with_label(_("Composition"));
569  gtk_widget_show(widget);
570  gtk_grid_attach(GTK_GRID(grid), widget, 2, 8, 1, 1);
571  g_signal_connect(G_OBJECT(widget), "toggled",
573  grid->composition_check = widget;
574 
575  gtk_combo_box_set_active(GTK_COMBO_BOX(grid->quality_combo), 0);
576 
577 
578  widget = gtk_label_new(_("Remote scale factor"));
579  gtk_widget_show(widget);
580  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
581  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
582  gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
583  gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
584  gtk_grid_attach(GTK_GRID(grid), widget, 0, 9, 1, 1);
585 
586  grid->device_scale_factor_store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
587  grid->desktop_orientation_store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
588 
589  remmina_rdp_settings_get_orientation_scale_prefs(&desktopOrientation, &desktopScaleFactor, &deviceScaleFactor);
592 
593  widget = gtk_label_new(_("Desktop scale factor %"));
594  gtk_widget_show(widget);
595  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
596  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
597  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
598  gtk_grid_attach(GTK_GRID(grid), widget, 1, 9, 1, 1);
599 
600  widget = gtk_spin_button_new_with_range(0, 10000, 1);
601  gtk_widget_show(widget);
602  gtk_grid_attach(GTK_GRID(grid), widget, 2, 9, 1, 1);
603  grid->desktop_scale_factor_spin = widget;
604 
605  widget = gtk_label_new(_("Device scale factor %"));
606  gtk_widget_show(widget);
607  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
608  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
609  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
610  gtk_grid_attach(GTK_GRID(grid), widget, 1, 10, 1, 1);
611 
612  widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->device_scale_factor_store));
613  gtk_widget_show(widget);
614  gtk_grid_attach(GTK_GRID(grid), widget, 2, 10, 1, 1);
615 
616  renderer = gtk_cell_renderer_text_new();
617  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
618  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
619  grid->device_scale_factor_combo = widget;
620 
621  remmina_rdp_settings_set_combo_active_item(GTK_COMBO_BOX(grid->device_scale_factor_combo), deviceScaleFactor);
622  gtk_spin_button_set_value(GTK_SPIN_BUTTON(grid->desktop_scale_factor_spin), (gdouble)desktopScaleFactor);
623 
624  g_signal_connect(G_OBJECT(widget), "changed",
625  G_CALLBACK(remmina_rdp_settings_appscale_on_changed), grid);
627 
628  widget = gtk_label_new(_("Desktop orientation"));
629  gtk_widget_show(widget);
630  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
631  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
632  gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
633  gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
634  gtk_grid_attach(GTK_GRID(grid), widget, 0, 11, 1, 1);
635 
636  widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(grid->desktop_orientation_store));
637  gtk_widget_show(widget);
638  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
639  gtk_grid_attach(GTK_GRID(grid), widget, 1, 11, 2, 1);
640 
641  renderer = gtk_cell_renderer_text_new();
642  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
643  gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 1);
644  grid->desktop_orientation_combo = widget;
645 
646  remmina_rdp_settings_set_combo_active_item(GTK_COMBO_BOX(grid->desktop_orientation_combo), desktopOrientation);
647 
648  widget = gtk_label_new(_("Input device settings"));
649  gtk_widget_show(widget);
650  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
651  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
652  gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
653  gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
654  gtk_grid_attach(GTK_GRID(grid), widget, 0, 12, 1, 1);
655 
656  widget = gtk_check_button_new_with_label(_("Disable smooth scrolling"));
657  gtk_widget_show(widget);
658  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
659  gtk_grid_attach(GTK_GRID(grid), widget, 1, 12, 2, 1);
660  grid->disable_smooth_scrolling_check = widget;
661 
662  s = remmina_plugin_service->pref_get_value("rdp_disable_smooth_scrolling");
663  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
664  s && s[0] == '1' ? TRUE : FALSE);
665  g_free(s);
666 
667  widget = gtk_label_new(_("General settings"));
668  gtk_widget_show(widget);
669  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
670  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
671  gtk_widget_set_margin_end(GTK_WIDGET(widget), 6);
672  gtk_widget_set_margin_start(GTK_WIDGET(widget), 18);
673  gtk_grid_attach(GTK_GRID(grid), widget, 0, 13, 1, 1);
674  widget = gtk_label_new(_("Reconnect attempts number"));
675  gtk_widget_show(widget);
676  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
677  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
678  gtk_widget_set_margin_start(GTK_WIDGET(widget), 6);
679  gtk_grid_attach(GTK_GRID(grid), widget, 1, 13, 1, 1);
680  widget = gtk_entry_new();
681  gtk_widget_show(widget);
682  gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_END);
683  gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
684  gtk_grid_attach(GTK_GRID(grid), widget, 2, 13, 1, 1);
685  gtk_entry_set_input_purpose(GTK_ENTRY(widget), GTK_INPUT_PURPOSE_NUMBER);
686  gtk_entry_set_input_hints(GTK_ENTRY(widget), GTK_INPUT_HINT_NONE);
687  gtk_widget_set_tooltip_text(widget, _("The maximum number of reconnect attempts upon an RDP disconnect (default: 20)"));
688  s = remmina_plugin_service->pref_get_value("rdp_reconnect_attempts");
689  if (s && s[0])
690  gtk_entry_set_text(GTK_ENTRY(widget), s);
691  g_free(s);
692  grid->reconnect_attempts = widget;
693 
694 }
695 
697 {
698  TRACE_CALL(__func__);
699  GtkWidget *widget;
700 
701  widget = GTK_WIDGET(g_object_new(REMMINA_TYPE_PLUGIN_RDPSET_GRID, NULL));
702  gtk_widget_show(widget);
703 
704  return widget;
705 }
706 
707 void remmina_rdp_settings_get_orientation_scale_prefs(int *desktopOrientation, int *desktopScaleFactor, int *deviceScaleFactor)
708 {
709  TRACE_CALL(__func__);
710 
711  /* See https://msdn.microsoft.com/en-us/library/cc240510.aspx */
712 
713  int orientation, dpsf, desf;
714  gchar *s;
715 
716  *desktopOrientation = *desktopScaleFactor = *deviceScaleFactor = 0;
717 
718  s = remmina_plugin_service->pref_get_value("rdp_desktopOrientation");
719  orientation = s ? atoi(s) : 0;
720  g_free(s);
721  if (orientation != 90 && orientation != 180 && orientation != 270)
722  orientation = 0;
723  *desktopOrientation = orientation;
724 
725  s = remmina_plugin_service->pref_get_value("rdp_desktopScaleFactor");
726  dpsf = s ? atoi(s) : 0;
727  g_free(s);
728  if (dpsf < 100 || dpsf > 500)
729  return;
730 
731  s = remmina_plugin_service->pref_get_value("rdp_deviceScaleFactor");
732  desf = s ? atoi(s) : 0;
733  g_free(s);
734  if (desf != 100 && desf != 140 && desf != 180)
735  return;
736 
737  *desktopScaleFactor = dpsf;
738  *deviceScaleFactor = desf;
739 }
GtkListStore * device_scale_factor_store
Definition: rdp_settings.c:110
GtkWidget * composition_check
Definition: rdp_settings.c:101
GtkWidget * keyboard_layout_label
Definition: rdp_settings.c:88
static void remmina_rdp_settings_grid_load_devicescalefactor_combo(RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:241
static guint keyboard_layout
Definition: rdp_settings.c:40
GtkListStore * desktop_orientation_store
Definition: rdp_settings.c:113
GtkWidget * reconnect_attempts
Definition: rdp_settings.c:104
GtkWidget * fontsmoothing_check
Definition: rdp_settings.c:100
static guint rdp_keyboard_layout
Definition: rdp_settings.c:41
GtkListStore * quality_store
Definition: rdp_settings.c:93
static void remmina_rdp_settings_grid_init(RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:408
GtkWidget * disable_smooth_scrolling_check
Definition: rdp_settings.c:103
GType remmina_rdp_settings_grid_get_type(void)
Definition: rdp_settings.c:123
GtkWidget * cursorblinking_check
Definition: rdp_settings.c:99
static void remmina_rdp_settings_grid_load_layout(RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:206
GtkWidget * wallpaper_check
Definition: rdp_settings.c:94
void remmina_rdp_settings_get_orientation_scale_prefs(int *desktopOrientation, int *desktopScaleFactor, int *deviceScaleFactor)
Definition: rdp_settings.c:707
static void remmina_rdp_settings_quality_option_on_toggled(GtkToggleButton *togglebutton, RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:364
GtkWidget * menuanimation_check
Definition: rdp_settings.c:96
void remmina_rdp_settings_init(void)
Definition: rdp_settings.c:57
struct _RemminaPluginRdpsetGridClass RemminaPluginRdpsetGridClass
static void remmina_rdp_settings_grid_load_quality(RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:271
GtkWidget * desktop_scale_factor_spin
Definition: rdp_settings.c:108
void(* pref_set_value)(const gchar *key, const gchar *value)
Definition: plugin.h:226
struct _RemminaPluginRdpsetGrid RemminaPluginRdpsetGrid
GtkWidget * use_client_keymap_check
Definition: rdp_settings.c:102
G_DEFINE_TYPE(RemminaConnectionWindow, rcw, GTK_TYPE_WINDOW)
Definition: rcw.c:81
static RemminaPluginService * remmina_plugin_service
static void remmina_rdp_settings_kbd_init(void)
Definition: rdp_settings.c:44
gchar *(* pref_get_value)(const gchar *key)
Definition: plugin.h:227
static gchar * rdp_keyboard_remapping_list
Definition: rdp_settings.c:42
GtkWidget * cursorshadow_check
Definition: rdp_settings.c:98
GtkWidget * remmina_rdp_settings_new(RemminaPrefPlugin *plugin)
Definition: rdp_settings.c:696
GtkWidget * desktop_orientation_combo
Definition: rdp_settings.c:114
static void remmina_rdp_settings_set_combo_active_item(GtkComboBox *combo, int itemval)
Definition: rdp_settings.c:388
static void remmina_rdp_settings_appscale_on_changed(GtkComboBox *widget, RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:307
static void remmina_rdp_settings_grid_destroy(GtkWidget *widget, gpointer data)
Definition: rdp_settings.c:132
GtkWidget * windowdrag_check
Definition: rdp_settings.c:95
GtkWidget * device_scale_factor_combo
Definition: rdp_settings.c:111
GtkWidget * keyboard_layout_combo
Definition: rdp_settings.c:89
static void remmina_rdp_settings_grid_load_desktoporientation_combo(RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:256
static void remmina_rdp_settings_quality_on_changed(GtkComboBox *widget, RemminaPluginRdpsetGrid *grid)
Definition: rdp_settings.c:326
GtkListStore * keyboard_layout_store
Definition: rdp_settings.c:90
guint remmina_rdp_settings_get_keyboard_layout(void)
Definition: rdp_settings.c:72