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_monitor.c
Go to the documentation of this file.
1 /*
2  * Remmina - The GTK+ Remote Desktop Client
3  * Copyright (C) 2016-2020 Antenore Gatta, Giovanni Panozzo
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  * In addition, as a special exception, the copyright holders give
21  * permission to link the code of portions of this program with the
22  * OpenSSL library under certain conditions as described in each
23  * individual source file, and distribute linked combinations
24  * including the two.
25  * You must obey the GNU General Public License in all respects
26  * for all of the code used other than OpenSSL. * If you modify
27  * file(s) with this exception, you may extend this exception to your
28  * version of the file(s), but you are not obligated to do so. * If you
29  * do not wish to do so, delete this exception statement from your
30  * version. * If you delete this exception statement from all source
31  * files in the program, then also delete it here.
32  *
33  */
34 
35 #include "rdp_plugin.h"
36 #include "rdp_monitor.h"
37 
39 gint remmina_rdp_utils_strpos(const gchar *haystack, const gchar *needle)
40 {
41  TRACE_CALL(__func__);
42  const gchar *sub;
43 
44  if (!*needle)
45  return -1;
46 
47  sub = strstr(haystack, needle);
48  if (!sub)
49  return -1;
50 
51  return sub - haystack;
52 }
53 
54 /* https://github.com/adlocode/xfwm4/blob/1d21be9ffc0fa1cea91905a07d1446c5227745f4/common/xfwm-common.c */
55 
56 
68 void remmina_rdp_monitor_get (rfContext *rfi, gchar **monitorids, guint32 *maxwidth, guint32 *maxheight)
69 {
70  TRACE_CALL(__func__);
71 
72  GdkDisplay *display;
73  GdkMonitor *monitor;
74  gboolean has_custom_monitors = FALSE;
75 
76  gboolean primary_found = FALSE;
77 
78  gint n_monitors;
79  gint scale;
80  gint index = 0;
81  gint count = 0;
82 
83  static gchar buffer[256];
84  gint buffer_offset = 0;
85 
86  GdkRectangle geometry = { 0, 0, 0, 0 };
87  GdkRectangle tempgeom = { 0, 0, 0, 0 };
88  GdkRectangle destgeom = { 0, 0, 0, 0 };
89  rdpSettings* settings;
90  if (!rfi || !rfi->settings)
91  return;
92 
93  settings = rfi->settings;
94 
95  *maxwidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
96  *maxheight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
97 
98  display = gdk_display_get_default ();
99  n_monitors = gdk_display_get_n_monitors(display);
100 
101  /* Get monitor at windows curently in use */
102  //w = gtk_widget_get_window(rfi->drawing_area);
103 
104  //current_monitor = gdk_display_get_monitor_at_window (display, w);
105 
106  /* we got monitorids as options */
107  if (*monitorids)
108  has_custom_monitors = TRUE;
109 
110  rdpMonitor* base = (rdpMonitor *)freerdp_settings_get_pointer(settings, FreeRDP_MonitorDefArray);
111  for (gint i = 0; i < n_monitors; ++i) {
112  rdpMonitor* current;
113  if (has_custom_monitors) {
114  REMMINA_PLUGIN_DEBUG("We have custom monitors");
115  gchar itoc[11];
116  snprintf(itoc, sizeof(itoc), "%d", i);
117  if (remmina_rdp_utils_strpos(*monitorids, itoc) < 0 ) {
118  REMMINA_PLUGIN_DEBUG("Monitor n %d it's out of the provided list", i);
119  index += 1;
120  continue;
121  }
122  }
123 
124  monitor = gdk_display_get_monitor(display, i);
125  if (monitor == NULL) {
126  REMMINA_PLUGIN_DEBUG("Monitor n %d does not exist or is not active", i);
127  index +=1;
128  continue;
129  }
130 
131  monitor = gdk_display_get_monitor(display, index);
132  current = &base[index];
133  REMMINA_PLUGIN_DEBUG("Monitor n %d", index);
134  /* If the desktop env in use doesn't have the working area concept
135  * gdk_monitor_get_workarea will return the monitor geometry*/
136  //gdk_monitor_get_workarea (monitor, &geometry);
137  gdk_monitor_get_geometry (monitor, &geometry);
138  current->x = geometry.x;
139  REMMINA_PLUGIN_DEBUG("Monitor n %d x: %d", index, geometry.x);
140  current->y = geometry.y;
141  REMMINA_PLUGIN_DEBUG("Monitor n %d y: %d", index, geometry.y);
142  /* geometry contain the application geometry, to obtain the real one
143  * we must multiply by the scale factor */
144  scale = gdk_monitor_get_scale_factor (monitor);
145  REMMINA_PLUGIN_DEBUG("Monitor n %d scale: %d", index, scale);
146  geometry.x *= scale;
147  geometry.y *= scale;
148  geometry.width *= scale;
149  geometry.height *= scale;
150  REMMINA_PLUGIN_DEBUG("Monitor n %d width: %d", index, geometry.width);
151  REMMINA_PLUGIN_DEBUG("Monitor n %d height: %d", index, geometry.height);
152  current->width = geometry.width;
153  current->height = geometry.height;
154  current->attributes.physicalHeight = gdk_monitor_get_height_mm (monitor);
155  REMMINA_PLUGIN_DEBUG("Monitor n %d physical height: %d", i, current->attributes.physicalHeight);
156  current->attributes.physicalWidth = gdk_monitor_get_width_mm (monitor);
157  REMMINA_PLUGIN_DEBUG("Monitor n %d physical width: %d", i, current->attributes.physicalWidth);
158  current->orig_screen = index;
159  if (!primary_found) {
160  freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, current->x);
161  freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, current->y);
162  }
163  if (gdk_monitor_is_primary(monitor)) {
164  REMMINA_PLUGIN_DEBUG ("Primary monitor found with id: %d", index);
165  current->is_primary = TRUE;
166  primary_found = TRUE;
167  if (current->x != 0 || current->y != 0)
168  {
169  REMMINA_PLUGIN_DEBUG ("Primary monitor not at 0,0 coordinates: %d", index);
170  freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, current->x);
171  freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, current->y);
172  }
173  } else {
174  if (!primary_found && current->x == 0 &&
175  current->y == 0)
176  {
177  REMMINA_PLUGIN_DEBUG ("Monitor %d has 0,0 coordinates", index);
178  current->is_primary = TRUE;
179  freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, current->x);
180  freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, current->y);
181  primary_found = TRUE;
182  REMMINA_PLUGIN_DEBUG ("Primary monitor set to id: %d", index);
183  }
184  }
185  REMMINA_PLUGIN_DEBUG ("Local X Shift: %d", freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftX));
186  REMMINA_PLUGIN_DEBUG ("Local Y Shift: %d", freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftY));
187  //current->x =
188  //current->x - freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftX);
189  //REMMINA_PLUGIN_DEBUG("Monitor n %d calculated x: %d", index, current->x);
190  //current->y =
191  //current->y - freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftY);
192  //REMMINA_PLUGIN_DEBUG("Monitor n %d calculated y: %d", index, current->y);
193 
194  if (buffer_offset == 0)
195  buffer_offset = g_sprintf(buffer + buffer_offset, "%d", i);
196  else
197  buffer_offset = g_sprintf(buffer + buffer_offset, ",%d", i);
198  REMMINA_PLUGIN_DEBUG("Monitor IDs buffer: %s", buffer);
199  gdk_rectangle_union(&tempgeom, &geometry, &destgeom);
200  memcpy(&tempgeom, &destgeom, sizeof tempgeom);
201  count++;
202  index++;
203 
204  }
205  freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, index);
206  /* Subtract monitor shift from monitor variables for server-side use.
207  * We maintain monitor shift value as Window requires the primary monitor to have a
208  * coordinate of 0,0 In some X configurations, no monitor may have a coordinate of 0,0. This
209  * can also be happen if the user requests specific monitors from the command-line as well.
210  * So, we make sure to translate our primary monitor's upper-left corner to 0,0 on the
211  * server.
212  */
213  for (gint i = 0; i < freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); i++)
214  {
215  rdpMonitor* current = &base[i];
216  current->x =
217  current->x - freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftX);
218  REMMINA_PLUGIN_DEBUG("Monitor n %d calculated x: %d", i, current->x);
219  current->y =
220  current->y - freerdp_settings_get_uint32(settings, FreeRDP_MonitorLocalShiftY);
221  REMMINA_PLUGIN_DEBUG("Monitor n %d calculated y: %d", i, current->y);
222  }
223 
224  REMMINA_PLUGIN_DEBUG("%d monitors on %d have been configured", freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount), count);
225  *maxwidth = destgeom.width;
226  *maxheight = destgeom.height;
227  REMMINA_PLUGIN_DEBUG("maxw and maxh: %ux%u", *maxwidth, *maxheight);
228  if (n_monitors > 1)
229  freerdp_settings_set_bool(rfi->settings, FreeRDP_SupportMonitorLayoutPdu, TRUE);
230  *monitorids = g_strdup(buffer);
231 }
gint remmina_rdp_utils_strpos(const gchar *haystack, const gchar *needle)
Utility functions should be moved somewhere else
Definition: rdp_monitor.c:39
rdpSettings * settings
Definition: rdp_plugin.h:327
void remmina_rdp_monitor_get(rfContext *rfi, gchar **monitorids, guint32 *maxwidth, guint32 *maxheight)
Set the MonitorIDs, the maxwidth and maxheight.
Definition: rdp_monitor.c:68