Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* Copyright (C) 2017 Red Hat, Inc. |
3 |
|
|
* |
4 |
|
|
* This program is free software; you can redistribute it and/or modify |
5 |
|
|
* it under the terms of the GNU General Public License as published by |
6 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
7 |
|
|
* (at your option) any later version. |
8 |
|
|
* |
9 |
|
|
* This program is distributed in the hope that it will be useful, |
10 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
|
|
* GNU General Public License for more details. |
13 |
|
|
* |
14 |
|
|
* You should have received a copy of the GNU General Public License |
15 |
|
|
* along with this program; if not, write to the Free Software |
16 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
17 |
|
|
* |
18 |
|
|
*/ |
19 |
|
|
|
20 |
|
|
#include <float.h> |
21 |
|
|
#include <math.h> |
22 |
|
|
#include <gio/gio.h> |
23 |
|
|
|
24 |
|
|
#include "cc-display-config-dbus.h" |
25 |
|
|
|
26 |
|
|
#define MODE_BASE_FORMAT "siiddad" |
27 |
|
|
#define MODE_FORMAT "(" MODE_BASE_FORMAT "a{sv})" |
28 |
|
|
#define MODES_FORMAT "a" MODE_FORMAT |
29 |
|
|
#define MONITOR_SPEC_FORMAT "(ssss)" |
30 |
|
|
#define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})" |
31 |
|
|
#define MONITORS_FORMAT "a" MONITOR_FORMAT |
32 |
|
|
|
33 |
|
|
#define LOGICAL_MONITOR_MONITORS_FORMAT "a" MONITOR_SPEC_FORMAT |
34 |
|
|
#define LOGICAL_MONITOR_FORMAT "(iidub" LOGICAL_MONITOR_MONITORS_FORMAT "a{sv})" |
35 |
|
|
#define LOGICAL_MONITORS_FORMAT "a" LOGICAL_MONITOR_FORMAT |
36 |
|
|
|
37 |
|
|
#define CURRENT_STATE_FORMAT "(u" MONITORS_FORMAT LOGICAL_MONITORS_FORMAT "a{sv})" |
38 |
|
|
|
39 |
|
|
typedef enum _CcDisplayModeFlags |
40 |
|
|
{ |
41 |
|
|
MODE_PREFERRED = 1 << 0, |
42 |
|
|
MODE_CURRENT = 1 << 1, |
43 |
|
|
MODE_INTERLACED = 1 << 2, |
44 |
|
|
} CcDisplayModeFlags; |
45 |
|
|
|
46 |
|
|
struct _CcDisplayModeDBus |
47 |
|
|
{ |
48 |
|
|
CcDisplayMode parent_instance; |
49 |
|
|
CcDisplayMonitorDBus *monitor; |
50 |
|
|
|
51 |
|
|
char *id; |
52 |
|
|
int width; |
53 |
|
|
int height; |
54 |
|
|
double refresh_rate; |
55 |
|
|
CcDisplayModeRefreshRateMode refresh_rate_mode; |
56 |
|
|
double preferred_scale; |
57 |
|
|
GArray *supported_scales; |
58 |
|
|
guint32 flags; |
59 |
|
|
}; |
60 |
|
|
|
61 |
|
✗ |
G_DEFINE_TYPE (CcDisplayModeDBus, |
62 |
|
|
cc_display_mode_dbus, |
63 |
|
|
CC_TYPE_DISPLAY_MODE) |
64 |
|
|
|
65 |
|
|
static gboolean |
66 |
|
✗ |
cc_display_mode_dbus_equal (const CcDisplayModeDBus *m1, |
67 |
|
|
const CcDisplayModeDBus *m2) |
68 |
|
|
{ |
69 |
|
✗ |
if (!m1 && !m2) |
70 |
|
✗ |
return TRUE; |
71 |
|
✗ |
else if (!m1 || !m2) |
72 |
|
✗ |
return FALSE; |
73 |
|
|
|
74 |
|
✗ |
return m1->width == m2->width && |
75 |
|
✗ |
m1->height == m2->height && |
76 |
|
✗ |
m1->refresh_rate == m2->refresh_rate && |
77 |
|
✗ |
m1->refresh_rate_mode == m2->refresh_rate_mode && |
78 |
|
✗ |
(m1->flags & MODE_INTERLACED) == (m2->flags & MODE_INTERLACED); |
79 |
|
|
} |
80 |
|
|
|
81 |
|
|
static gboolean |
82 |
|
✗ |
cc_display_mode_dbus_is_clone_mode (CcDisplayMode *pself) |
83 |
|
|
{ |
84 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
85 |
|
|
|
86 |
|
✗ |
return !self->id; |
87 |
|
|
} |
88 |
|
|
|
89 |
|
|
static void |
90 |
|
✗ |
cc_display_mode_dbus_get_resolution (CcDisplayMode *pself, |
91 |
|
|
int *w, int *h) |
92 |
|
|
{ |
93 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
94 |
|
|
|
95 |
|
✗ |
if (w) |
96 |
|
✗ |
*w = self->width; |
97 |
|
✗ |
if (h) |
98 |
|
✗ |
*h = self->height; |
99 |
|
✗ |
} |
100 |
|
|
|
101 |
|
|
static GArray * cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself); |
102 |
|
|
|
103 |
|
|
static double |
104 |
|
✗ |
cc_display_mode_dbus_get_preferred_scale (CcDisplayMode *pself) |
105 |
|
|
{ |
106 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
107 |
|
|
|
108 |
|
✗ |
return self->preferred_scale; |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
static gboolean |
112 |
|
✗ |
cc_display_mode_dbus_is_supported_scale (CcDisplayMode *pself, |
113 |
|
|
double scale) |
114 |
|
|
{ |
115 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
116 |
|
|
|
117 |
|
|
guint i; |
118 |
|
✗ |
for (i = 0; i < self->supported_scales->len; i++) |
119 |
|
|
{ |
120 |
|
✗ |
double v = g_array_index (self->supported_scales, double, i); |
121 |
|
|
|
122 |
|
✗ |
if (G_APPROX_VALUE (v, scale, DBL_EPSILON)) |
123 |
|
✗ |
return TRUE; |
124 |
|
|
} |
125 |
|
✗ |
return FALSE; |
126 |
|
|
} |
127 |
|
|
|
128 |
|
|
static CcDisplayModeRefreshRateMode |
129 |
|
✗ |
cc_display_mode_dbus_get_refresh_rate_mode (CcDisplayMode *pself) |
130 |
|
|
{ |
131 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
132 |
|
|
|
133 |
|
✗ |
return self->refresh_rate_mode; |
134 |
|
|
} |
135 |
|
|
|
136 |
|
|
static gboolean |
137 |
|
✗ |
cc_display_mode_dbus_is_interlaced (CcDisplayMode *pself) |
138 |
|
|
{ |
139 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
140 |
|
|
|
141 |
|
✗ |
return !!(self->flags & MODE_INTERLACED); |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
static gboolean |
145 |
|
✗ |
cc_display_mode_dbus_is_preferred (CcDisplayMode *pself) |
146 |
|
|
{ |
147 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
148 |
|
|
|
149 |
|
✗ |
return !!(self->flags & MODE_PREFERRED); |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
static int |
153 |
|
✗ |
cc_display_mode_dbus_get_freq (CcDisplayMode *pself) |
154 |
|
|
{ |
155 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
156 |
|
|
|
157 |
|
✗ |
return self->refresh_rate; |
158 |
|
|
} |
159 |
|
|
|
160 |
|
|
static double |
161 |
|
✗ |
cc_display_mode_dbus_get_freq_f (CcDisplayMode *pself) |
162 |
|
|
{ |
163 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
164 |
|
|
|
165 |
|
✗ |
return self->refresh_rate; |
166 |
|
|
} |
167 |
|
|
|
168 |
|
|
static void |
169 |
|
✗ |
cc_display_mode_dbus_init (CcDisplayModeDBus *self) |
170 |
|
|
{ |
171 |
|
✗ |
self->supported_scales = g_array_new (FALSE, FALSE, sizeof (double)); |
172 |
|
✗ |
} |
173 |
|
|
|
174 |
|
|
static void |
175 |
|
✗ |
cc_display_mode_dbus_finalize (GObject *object) |
176 |
|
|
{ |
177 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (object); |
178 |
|
|
|
179 |
|
✗ |
g_free (self->id); |
180 |
|
✗ |
g_array_free (self->supported_scales, TRUE); |
181 |
|
|
|
182 |
|
✗ |
G_OBJECT_CLASS (cc_display_mode_dbus_parent_class)->finalize (object); |
183 |
|
✗ |
} |
184 |
|
|
|
185 |
|
|
static void |
186 |
|
✗ |
cc_display_mode_dbus_class_init (CcDisplayModeDBusClass *klass) |
187 |
|
|
{ |
188 |
|
✗ |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
189 |
|
✗ |
CcDisplayModeClass *parent_class = CC_DISPLAY_MODE_CLASS (klass); |
190 |
|
|
|
191 |
|
✗ |
gobject_class->finalize = cc_display_mode_dbus_finalize; |
192 |
|
|
|
193 |
|
✗ |
parent_class->is_clone_mode = cc_display_mode_dbus_is_clone_mode; |
194 |
|
✗ |
parent_class->get_resolution = cc_display_mode_dbus_get_resolution; |
195 |
|
✗ |
parent_class->get_supported_scales = cc_display_mode_dbus_get_supported_scales; |
196 |
|
✗ |
parent_class->get_preferred_scale = cc_display_mode_dbus_get_preferred_scale; |
197 |
|
✗ |
parent_class->get_refresh_rate_mode = cc_display_mode_dbus_get_refresh_rate_mode; |
198 |
|
✗ |
parent_class->is_interlaced = cc_display_mode_dbus_is_interlaced; |
199 |
|
✗ |
parent_class->is_preferred = cc_display_mode_dbus_is_preferred; |
200 |
|
✗ |
parent_class->get_freq = cc_display_mode_dbus_get_freq; |
201 |
|
✗ |
parent_class->get_freq_f = cc_display_mode_dbus_get_freq_f; |
202 |
|
✗ |
} |
203 |
|
|
|
204 |
|
|
static CcDisplayModeDBus * |
205 |
|
✗ |
cc_display_mode_dbus_new_virtual (int width, |
206 |
|
|
int height, |
207 |
|
|
double preferred_scale, |
208 |
|
|
GArray *supported_scales) |
209 |
|
|
{ |
210 |
|
✗ |
g_autoptr(GVariant) properties_variant = NULL; |
211 |
|
|
CcDisplayModeDBus *self; |
212 |
|
|
|
213 |
|
✗ |
self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL); |
214 |
|
|
|
215 |
|
✗ |
self->width = width; |
216 |
|
✗ |
self->height = height; |
217 |
|
✗ |
self->preferred_scale = preferred_scale; |
218 |
|
✗ |
self->supported_scales = g_array_ref (supported_scales); |
219 |
|
|
|
220 |
|
✗ |
return self; |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
static CcDisplayModeDBus * |
224 |
|
✗ |
cc_display_mode_dbus_new (CcDisplayMonitorDBus *monitor, |
225 |
|
|
GVariant *variant) |
226 |
|
|
{ |
227 |
|
|
double d; |
228 |
|
✗ |
g_autoptr(GVariantIter) scales_iter = NULL; |
229 |
|
✗ |
g_autoptr(GVariant) properties_variant = NULL; |
230 |
|
|
gboolean is_current; |
231 |
|
|
gboolean is_preferred; |
232 |
|
|
gboolean is_interlaced; |
233 |
|
|
char *refresh_rate_mode_str; |
234 |
|
✗ |
CcDisplayModeDBus *self = g_object_new (CC_TYPE_DISPLAY_MODE_DBUS, NULL); |
235 |
|
|
|
236 |
|
✗ |
self->monitor = monitor; |
237 |
|
|
|
238 |
|
✗ |
g_variant_get (variant, "(" MODE_BASE_FORMAT "@a{sv})", |
239 |
|
|
&self->id, |
240 |
|
|
&self->width, |
241 |
|
|
&self->height, |
242 |
|
|
&self->refresh_rate, |
243 |
|
|
&self->preferred_scale, |
244 |
|
|
&scales_iter, |
245 |
|
|
&properties_variant); |
246 |
|
|
|
247 |
|
✗ |
while (g_variant_iter_next (scales_iter, "d", &d)) |
248 |
|
✗ |
g_array_append_val (self->supported_scales, d); |
249 |
|
|
|
250 |
|
✗ |
if (!g_variant_lookup (properties_variant, "is-current", "b", &is_current)) |
251 |
|
✗ |
is_current = FALSE; |
252 |
|
✗ |
if (!g_variant_lookup (properties_variant, "is-preferred", "b", &is_preferred)) |
253 |
|
✗ |
is_preferred = FALSE; |
254 |
|
✗ |
if (!g_variant_lookup (properties_variant, "is-interlaced", "b", &is_interlaced)) |
255 |
|
✗ |
is_interlaced = FALSE; |
256 |
|
✗ |
if (!g_variant_lookup (properties_variant, "refresh-rate-mode", "s", &refresh_rate_mode_str)) |
257 |
|
✗ |
refresh_rate_mode_str = "fixed"; |
258 |
|
|
|
259 |
|
✗ |
if (is_current) |
260 |
|
✗ |
self->flags |= MODE_CURRENT; |
261 |
|
✗ |
if (is_preferred) |
262 |
|
✗ |
self->flags |= MODE_PREFERRED; |
263 |
|
✗ |
if (is_interlaced) |
264 |
|
✗ |
self->flags |= MODE_INTERLACED; |
265 |
|
|
|
266 |
|
✗ |
if (g_strcmp0 (refresh_rate_mode_str, "fixed") == 0) |
267 |
|
✗ |
self->refresh_rate_mode = MODE_REFRESH_RATE_MODE_FIXED; |
268 |
|
✗ |
else if (g_strcmp0 (refresh_rate_mode_str, "variable") == 0) |
269 |
|
✗ |
self->refresh_rate_mode = MODE_REFRESH_RATE_MODE_VARIABLE; |
270 |
|
|
|
271 |
|
✗ |
return self; |
272 |
|
|
} |
273 |
|
|
|
274 |
|
|
|
275 |
|
|
#define CC_TYPE_DISPLAY_LOGICAL_MONITOR (cc_display_logical_monitor_get_type ()) |
276 |
|
✗ |
G_DECLARE_FINAL_TYPE (CcDisplayLogicalMonitor, cc_display_logical_monitor, |
277 |
|
|
CC, DISPLAY_LOGICAL_MONITOR, GObject) |
278 |
|
|
|
279 |
|
|
struct _CcDisplayLogicalMonitor |
280 |
|
|
{ |
281 |
|
|
GObject parent_instance; |
282 |
|
|
|
283 |
|
|
int x; |
284 |
|
|
int y; |
285 |
|
|
double scale; |
286 |
|
|
CcDisplayRotation rotation; |
287 |
|
|
gboolean primary; |
288 |
|
|
|
289 |
|
|
GHashTable *monitors; |
290 |
|
|
}; |
291 |
|
|
|
292 |
|
✗ |
G_DEFINE_TYPE (CcDisplayLogicalMonitor, |
293 |
|
|
cc_display_logical_monitor, |
294 |
|
|
G_TYPE_OBJECT) |
295 |
|
|
|
296 |
|
|
static gboolean |
297 |
|
✗ |
cc_display_logical_monitor_equal (const CcDisplayLogicalMonitor *m1, |
298 |
|
|
const CcDisplayLogicalMonitor *m2) |
299 |
|
|
{ |
300 |
|
✗ |
if (!m1 && !m2) |
301 |
|
✗ |
return TRUE; |
302 |
|
✗ |
else if (!m1 || !m2) |
303 |
|
✗ |
return FALSE; |
304 |
|
|
|
305 |
|
✗ |
return m1->x == m2->x && |
306 |
|
✗ |
m1->y == m2->y && |
307 |
|
✗ |
G_APPROX_VALUE (m1->scale, m2->scale, DBL_EPSILON) && |
308 |
|
✗ |
m1->rotation == m2->rotation && |
309 |
|
✗ |
m1->primary == m2->primary; |
310 |
|
|
} |
311 |
|
|
|
312 |
|
|
static void |
313 |
|
✗ |
cc_display_logical_monitor_init (CcDisplayLogicalMonitor *self) |
314 |
|
|
{ |
315 |
|
✗ |
self->scale = 1.0; |
316 |
|
✗ |
self->monitors = g_hash_table_new (NULL, NULL); |
317 |
|
✗ |
} |
318 |
|
|
|
319 |
|
|
static void |
320 |
|
✗ |
cc_display_logical_monitor_finalize (GObject *object) |
321 |
|
|
{ |
322 |
|
✗ |
CcDisplayLogicalMonitor *self = CC_DISPLAY_LOGICAL_MONITOR (object); |
323 |
|
|
|
324 |
|
✗ |
g_warn_if_fail (g_hash_table_size (self->monitors) == 0); |
325 |
|
✗ |
g_clear_pointer (&self->monitors, g_hash_table_destroy); |
326 |
|
|
|
327 |
|
✗ |
G_OBJECT_CLASS (cc_display_logical_monitor_parent_class)->finalize (object); |
328 |
|
✗ |
} |
329 |
|
|
|
330 |
|
|
static void |
331 |
|
✗ |
cc_display_logical_monitor_class_init (CcDisplayLogicalMonitorClass *klass) |
332 |
|
|
{ |
333 |
|
✗ |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
334 |
|
|
|
335 |
|
✗ |
gobject_class->finalize = cc_display_logical_monitor_finalize; |
336 |
|
✗ |
} |
337 |
|
|
|
338 |
|
|
|
339 |
|
|
typedef enum _CcDisplayMonitorUnderscanning |
340 |
|
|
{ |
341 |
|
|
UNDERSCANNING_UNSUPPORTED = 0, |
342 |
|
|
UNDERSCANNING_DISABLED, |
343 |
|
|
UNDERSCANNING_ENABLED |
344 |
|
|
} CcDisplayMonitorUnderscanning; |
345 |
|
|
|
346 |
|
|
struct _CcDisplayMonitorDBus |
347 |
|
|
{ |
348 |
|
|
CcDisplayMonitor parent_instance; |
349 |
|
|
CcDisplayConfigDBus *config; |
350 |
|
|
|
351 |
|
|
gchar *connector_name; |
352 |
|
|
gchar *vendor_name; |
353 |
|
|
gchar *product_name; |
354 |
|
|
gchar *product_serial; |
355 |
|
|
gchar *display_name; |
356 |
|
|
|
357 |
|
|
int width_mm; |
358 |
|
|
int height_mm; |
359 |
|
|
gboolean builtin; |
360 |
|
|
CcDisplayMonitorUnderscanning underscanning; |
361 |
|
|
CcDisplayMonitorPrivacy privacy_screen; |
362 |
|
|
int max_width; |
363 |
|
|
int max_height; |
364 |
|
|
int min_refresh_rate; |
365 |
|
|
|
366 |
|
|
GList *modes; |
367 |
|
|
CcDisplayMode *current_mode; |
368 |
|
|
CcDisplayMode *preferred_mode; |
369 |
|
|
|
370 |
|
|
gboolean supports_variable_refresh_rate; |
371 |
|
|
|
372 |
|
|
CcDisplayLogicalMonitor *logical_monitor; |
373 |
|
|
}; |
374 |
|
|
|
375 |
|
✗ |
G_DEFINE_TYPE (CcDisplayMonitorDBus, |
376 |
|
|
cc_display_monitor_dbus, |
377 |
|
|
CC_TYPE_DISPLAY_MONITOR) |
378 |
|
|
|
379 |
|
|
static void |
380 |
|
|
register_logical_monitor (CcDisplayConfigDBus *self, |
381 |
|
|
CcDisplayLogicalMonitor *logical_monitor); |
382 |
|
|
static void |
383 |
|
|
cc_display_config_dbus_set_primary (CcDisplayConfigDBus *self, |
384 |
|
|
CcDisplayMonitorDBus *new_primary); |
385 |
|
|
static void |
386 |
|
|
cc_display_config_dbus_unset_primary (CcDisplayConfigDBus *self, |
387 |
|
|
CcDisplayMonitorDBus *old_primary); |
388 |
|
|
static void |
389 |
|
|
cc_display_config_dbus_ensure_non_offset_coords (CcDisplayConfigDBus *self); |
390 |
|
|
static void |
391 |
|
|
cc_display_config_dbus_append_right (CcDisplayConfigDBus *self, |
392 |
|
|
CcDisplayLogicalMonitor *monitor); |
393 |
|
|
static void |
394 |
|
|
cc_display_config_dbus_make_linear (CcDisplayConfigDBus *self); |
395 |
|
|
|
396 |
|
|
|
397 |
|
|
static const char * |
398 |
|
✗ |
cc_display_monitor_dbus_get_display_name (CcDisplayMonitor *pself) |
399 |
|
|
{ |
400 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
401 |
|
|
|
402 |
|
✗ |
if (self->display_name) |
403 |
|
✗ |
return self->display_name; |
404 |
|
|
|
405 |
|
✗ |
return self->connector_name; |
406 |
|
|
} |
407 |
|
|
|
408 |
|
|
static const char * |
409 |
|
✗ |
cc_display_monitor_dbus_get_connector_name (CcDisplayMonitor *pself) |
410 |
|
|
{ |
411 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
412 |
|
|
|
413 |
|
✗ |
return self->connector_name; |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
static gboolean |
417 |
|
✗ |
cc_display_monitor_dbus_is_builtin (CcDisplayMonitor *pself) |
418 |
|
|
{ |
419 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
420 |
|
|
|
421 |
|
✗ |
return self->builtin; |
422 |
|
|
} |
423 |
|
|
|
424 |
|
|
static gboolean |
425 |
|
✗ |
cc_display_monitor_dbus_is_primary (CcDisplayMonitor *pself) |
426 |
|
|
{ |
427 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
428 |
|
|
|
429 |
|
✗ |
if (self->logical_monitor) |
430 |
|
✗ |
return self->logical_monitor->primary; |
431 |
|
|
|
432 |
|
✗ |
return FALSE; |
433 |
|
|
} |
434 |
|
|
|
435 |
|
|
static void |
436 |
|
✗ |
cc_display_monitor_dbus_set_primary (CcDisplayMonitor *pself, |
437 |
|
|
gboolean primary) |
438 |
|
|
{ |
439 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
440 |
|
|
|
441 |
|
✗ |
if (primary) |
442 |
|
✗ |
cc_display_config_dbus_set_primary (self->config, self); |
443 |
|
|
else |
444 |
|
✗ |
cc_display_config_dbus_unset_primary (self->config, self); |
445 |
|
✗ |
} |
446 |
|
|
|
447 |
|
|
static gboolean |
448 |
|
✗ |
cc_display_monitor_dbus_is_active (CcDisplayMonitor *pself) |
449 |
|
|
{ |
450 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
451 |
|
|
|
452 |
|
✗ |
return self->logical_monitor != NULL; |
453 |
|
|
} |
454 |
|
|
|
455 |
|
|
static void |
456 |
|
✗ |
cc_display_monitor_dbus_set_logical_monitor (CcDisplayMonitorDBus *self, |
457 |
|
|
CcDisplayLogicalMonitor *logical_monitor) |
458 |
|
|
{ |
459 |
|
✗ |
gboolean was_primary = FALSE; |
460 |
|
|
|
461 |
|
✗ |
if (self->logical_monitor) |
462 |
|
|
{ |
463 |
|
✗ |
was_primary = self->logical_monitor->primary; |
464 |
|
✗ |
if (was_primary) |
465 |
|
✗ |
cc_display_config_dbus_unset_primary (self->config, self); |
466 |
|
✗ |
g_hash_table_remove (self->logical_monitor->monitors, self); |
467 |
|
✗ |
g_object_unref (self->logical_monitor); |
468 |
|
|
} |
469 |
|
|
|
470 |
|
✗ |
self->logical_monitor = logical_monitor; |
471 |
|
|
|
472 |
|
✗ |
if (self->logical_monitor) |
473 |
|
|
{ |
474 |
|
✗ |
g_hash_table_add (self->logical_monitor->monitors, self); |
475 |
|
✗ |
g_object_ref (self->logical_monitor); |
476 |
|
|
/* unset primary with NULL will select this monitor if it is the only one.*/ |
477 |
|
✗ |
if (was_primary) |
478 |
|
✗ |
cc_display_config_dbus_set_primary (self->config, self); |
479 |
|
|
else |
480 |
|
✗ |
cc_display_config_dbus_unset_primary (self->config, NULL); |
481 |
|
|
} |
482 |
|
✗ |
} |
483 |
|
|
|
484 |
|
|
static void |
485 |
|
✗ |
cc_display_monitor_dbus_set_active (CcDisplayMonitor *pself, |
486 |
|
|
gboolean active) |
487 |
|
|
{ |
488 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
489 |
|
|
|
490 |
|
✗ |
if (!self->current_mode && active) |
491 |
|
|
{ |
492 |
|
✗ |
if (self->preferred_mode) |
493 |
|
✗ |
self->current_mode = self->preferred_mode; |
494 |
|
✗ |
else if (self->modes) |
495 |
|
✗ |
self->current_mode = (CcDisplayMode *) self->modes->data; |
496 |
|
|
else |
497 |
|
✗ |
g_warning ("Couldn't find a mode to activate monitor at %s", self->connector_name); |
498 |
|
|
} |
499 |
|
|
|
500 |
|
✗ |
if (!self->logical_monitor && active) |
501 |
|
✗ |
{ |
502 |
|
|
CcDisplayLogicalMonitor *logical_monitor; |
503 |
|
✗ |
logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL); |
504 |
|
✗ |
cc_display_monitor_dbus_set_logical_monitor (self, logical_monitor); |
505 |
|
✗ |
cc_display_config_dbus_append_right (self->config, logical_monitor); |
506 |
|
✗ |
register_logical_monitor (self->config, logical_monitor); |
507 |
|
|
} |
508 |
|
✗ |
else if (self->logical_monitor && !active) |
509 |
|
|
{ |
510 |
|
✗ |
cc_display_monitor_dbus_set_logical_monitor (self, NULL); |
511 |
|
|
} |
512 |
|
|
|
513 |
|
✗ |
g_signal_emit_by_name (self, "active"); |
514 |
|
✗ |
} |
515 |
|
|
|
516 |
|
|
static CcDisplayRotation |
517 |
|
✗ |
cc_display_monitor_dbus_get_rotation (CcDisplayMonitor *pself) |
518 |
|
|
{ |
519 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
520 |
|
|
|
521 |
|
✗ |
if (self->logical_monitor) |
522 |
|
✗ |
return self->logical_monitor->rotation; |
523 |
|
|
|
524 |
|
✗ |
return CC_DISPLAY_ROTATION_NONE; |
525 |
|
|
} |
526 |
|
|
|
527 |
|
|
static void |
528 |
|
✗ |
cc_display_monitor_dbus_set_rotation (CcDisplayMonitor *pself, |
529 |
|
|
CcDisplayRotation rotation) |
530 |
|
|
{ |
531 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
532 |
|
|
|
533 |
|
✗ |
if (!self->logical_monitor) |
534 |
|
✗ |
return; |
535 |
|
|
|
536 |
|
✗ |
if (self->logical_monitor->rotation != rotation) |
537 |
|
|
{ |
538 |
|
✗ |
self->logical_monitor->rotation = rotation; |
539 |
|
|
|
540 |
|
✗ |
g_signal_emit_by_name (self, "rotation"); |
541 |
|
|
} |
542 |
|
|
} |
543 |
|
|
|
544 |
|
|
static gboolean |
545 |
|
✗ |
cc_display_monitor_dbus_supports_rotation (CcDisplayMonitor *pself, |
546 |
|
|
CcDisplayRotation rotation) |
547 |
|
|
{ |
548 |
|
✗ |
return TRUE; |
549 |
|
|
} |
550 |
|
|
|
551 |
|
|
static void |
552 |
|
✗ |
cc_display_monitor_dbus_get_physical_size (CcDisplayMonitor *pself, |
553 |
|
|
int *w, int *h) |
554 |
|
|
{ |
555 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
556 |
|
|
|
557 |
|
✗ |
if (w) |
558 |
|
✗ |
*w = self->width_mm; |
559 |
|
✗ |
if (h) |
560 |
|
✗ |
*h = self->height_mm; |
561 |
|
✗ |
} |
562 |
|
|
|
563 |
|
|
static void |
564 |
|
✗ |
cc_display_monitor_dbus_get_geometry (CcDisplayMonitor *pself, |
565 |
|
|
int *x, int *y, int *w, int *h) |
566 |
|
|
{ |
567 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
568 |
|
✗ |
CcDisplayMode *mode = NULL; |
569 |
|
|
|
570 |
|
✗ |
if (self->logical_monitor) |
571 |
|
|
{ |
572 |
|
✗ |
if (x) |
573 |
|
✗ |
*x = self->logical_monitor->x; |
574 |
|
✗ |
if (y) |
575 |
|
✗ |
*y = self->logical_monitor->y; |
576 |
|
|
} |
577 |
|
|
else |
578 |
|
|
{ |
579 |
|
✗ |
if (x) |
580 |
|
✗ |
*x = -1; |
581 |
|
✗ |
if (y) |
582 |
|
✗ |
*y = -1; |
583 |
|
|
} |
584 |
|
|
|
585 |
|
✗ |
if (self->current_mode) |
586 |
|
✗ |
mode = self->current_mode; |
587 |
|
✗ |
else if (self->preferred_mode) |
588 |
|
✗ |
mode = self->preferred_mode; |
589 |
|
✗ |
else if (self->modes) |
590 |
|
✗ |
mode = CC_DISPLAY_MODE (self->modes->data); |
591 |
|
|
|
592 |
|
✗ |
if (mode) |
593 |
|
✗ |
cc_display_mode_get_resolution (mode, w, h); |
594 |
|
|
else |
595 |
|
|
{ |
596 |
|
✗ |
g_warning ("Monitor at %s has no modes?", self->connector_name); |
597 |
|
✗ |
if (w) |
598 |
|
✗ |
*w = -1; |
599 |
|
✗ |
if (h) |
600 |
|
✗ |
*h = -1; |
601 |
|
|
} |
602 |
|
✗ |
} |
603 |
|
|
|
604 |
|
|
static int |
605 |
|
✗ |
cc_display_monitor_dbus_get_min_freq (CcDisplayMonitor *pself) |
606 |
|
|
{ |
607 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
608 |
|
|
|
609 |
|
✗ |
return self->min_refresh_rate; |
610 |
|
|
} |
611 |
|
|
|
612 |
|
|
static CcDisplayMode * |
613 |
|
✗ |
cc_display_monitor_dbus_get_mode (CcDisplayMonitor *pself) |
614 |
|
|
{ |
615 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
616 |
|
|
|
617 |
|
✗ |
return self->current_mode; |
618 |
|
|
} |
619 |
|
|
|
620 |
|
|
static CcDisplayMode * |
621 |
|
✗ |
cc_display_monitor_dbus_get_preferred_mode (CcDisplayMonitor *pself) |
622 |
|
|
{ |
623 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
624 |
|
|
|
625 |
|
✗ |
return self->preferred_mode; |
626 |
|
|
} |
627 |
|
|
|
628 |
|
|
static guint32 |
629 |
|
✗ |
cc_display_monitor_dbus_get_id (CcDisplayMonitor *pself) |
630 |
|
|
{ |
631 |
|
✗ |
return 0; |
632 |
|
|
} |
633 |
|
|
|
634 |
|
|
static GList * |
635 |
|
✗ |
cc_display_monitor_dbus_get_modes (CcDisplayMonitor *pself) |
636 |
|
|
{ |
637 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
638 |
|
|
|
639 |
|
✗ |
return self->modes; |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
static gboolean |
643 |
|
✗ |
cc_display_monitor_dbus_supports_variable_refresh_rate (CcDisplayMonitor *pself) |
644 |
|
|
{ |
645 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
646 |
|
|
|
647 |
|
✗ |
return self->supports_variable_refresh_rate; |
648 |
|
|
} |
649 |
|
|
|
650 |
|
|
static gboolean |
651 |
|
✗ |
cc_display_monitor_dbus_supports_underscanning (CcDisplayMonitor *pself) |
652 |
|
|
{ |
653 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
654 |
|
|
|
655 |
|
✗ |
return self->underscanning != UNDERSCANNING_UNSUPPORTED; |
656 |
|
|
} |
657 |
|
|
|
658 |
|
|
static gboolean |
659 |
|
✗ |
cc_display_monitor_dbus_get_underscanning (CcDisplayMonitor *pself) |
660 |
|
|
{ |
661 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
662 |
|
|
|
663 |
|
✗ |
return self->underscanning == UNDERSCANNING_ENABLED; |
664 |
|
|
} |
665 |
|
|
|
666 |
|
|
static CcDisplayMonitorPrivacy |
667 |
|
✗ |
cc_display_monitor_dbus_get_privacy (CcDisplayMonitor *pself) |
668 |
|
|
{ |
669 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
670 |
|
|
|
671 |
|
✗ |
return self->privacy_screen; |
672 |
|
|
} |
673 |
|
|
|
674 |
|
|
static void |
675 |
|
✗ |
cc_display_monitor_dbus_set_underscanning (CcDisplayMonitor *pself, |
676 |
|
|
gboolean underscanning) |
677 |
|
|
{ |
678 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
679 |
|
|
|
680 |
|
✗ |
if (self->underscanning == UNDERSCANNING_UNSUPPORTED) |
681 |
|
✗ |
return; |
682 |
|
|
|
683 |
|
✗ |
if (underscanning) |
684 |
|
✗ |
self->underscanning = UNDERSCANNING_ENABLED; |
685 |
|
|
else |
686 |
|
✗ |
self->underscanning = UNDERSCANNING_DISABLED; |
687 |
|
|
} |
688 |
|
|
|
689 |
|
|
static CcDisplayMode * |
690 |
|
✗ |
cc_display_monitor_dbus_get_closest_mode (CcDisplayMonitorDBus *self, |
691 |
|
|
int width, |
692 |
|
|
int height, |
693 |
|
|
double refresh_rate, |
694 |
|
|
CcDisplayModeRefreshRateMode refresh_rate_mode, |
695 |
|
|
guint32 flags) |
696 |
|
|
{ |
697 |
|
✗ |
CcDisplayModeDBus *best = NULL; |
698 |
|
|
GList *l; |
699 |
|
|
|
700 |
|
✗ |
for (l = self->modes; l != NULL; l = l->next) |
701 |
|
|
{ |
702 |
|
✗ |
CcDisplayModeDBus *similar = l->data; |
703 |
|
|
|
704 |
|
✗ |
if (similar->width != width || |
705 |
|
✗ |
similar->height != height || |
706 |
|
✗ |
similar->refresh_rate_mode != refresh_rate_mode) |
707 |
|
✗ |
continue; |
708 |
|
|
|
709 |
|
✗ |
if (similar->refresh_rate == refresh_rate && |
710 |
|
✗ |
(similar->flags & MODE_INTERLACED) == (flags & MODE_INTERLACED)) |
711 |
|
|
{ |
712 |
|
✗ |
best = similar; |
713 |
|
✗ |
break; |
714 |
|
|
} |
715 |
|
|
|
716 |
|
|
/* There might be a better heuristic. */ |
717 |
|
✗ |
if (!best || best->refresh_rate < similar->refresh_rate) |
718 |
|
|
{ |
719 |
|
✗ |
best = similar; |
720 |
|
✗ |
continue; |
721 |
|
|
} |
722 |
|
|
} |
723 |
|
|
|
724 |
|
✗ |
return CC_DISPLAY_MODE (best); |
725 |
|
|
} |
726 |
|
|
|
727 |
|
|
static void |
728 |
|
✗ |
cc_display_monitor_dbus_set_mode (CcDisplayMonitor *pself, |
729 |
|
|
CcDisplayMode *mode) |
730 |
|
|
{ |
731 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
732 |
|
✗ |
CcDisplayModeDBus *mode_dbus = CC_DISPLAY_MODE_DBUS (mode); |
733 |
|
|
CcDisplayMode *new_mode; |
734 |
|
|
|
735 |
|
✗ |
g_return_if_fail (mode_dbus != NULL); |
736 |
|
|
|
737 |
|
✗ |
new_mode = cc_display_monitor_dbus_get_closest_mode (self, |
738 |
|
|
mode_dbus->width, |
739 |
|
|
mode_dbus->height, |
740 |
|
|
mode_dbus->refresh_rate, |
741 |
|
|
mode_dbus->refresh_rate_mode, |
742 |
|
|
mode_dbus->flags); |
743 |
|
|
|
744 |
|
✗ |
self->current_mode = new_mode; |
745 |
|
|
|
746 |
|
✗ |
if (!cc_display_mode_dbus_is_supported_scale (new_mode, cc_display_monitor_get_scale (pself))) |
747 |
|
✗ |
cc_display_monitor_set_scale (pself, cc_display_mode_get_preferred_scale (new_mode)); |
748 |
|
|
|
749 |
|
✗ |
g_signal_emit_by_name (self, "mode"); |
750 |
|
|
} |
751 |
|
|
|
752 |
|
|
static void |
753 |
|
✗ |
cc_display_monitor_dbus_set_compatible_clone_mode (CcDisplayMonitor *pself, |
754 |
|
|
CcDisplayMode *clone_mode) |
755 |
|
|
{ |
756 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
757 |
|
|
GList *l; |
758 |
|
✗ |
CcDisplayMode *best_mode = NULL; |
759 |
|
|
int clone_width, clone_height; |
760 |
|
|
|
761 |
|
✗ |
g_return_if_fail (cc_display_mode_is_clone_mode (clone_mode)); |
762 |
|
|
|
763 |
|
✗ |
cc_display_mode_get_resolution (clone_mode, &clone_width, &clone_height); |
764 |
|
|
|
765 |
|
✗ |
for (l = self->modes; l; l = l->next) |
766 |
|
|
{ |
767 |
|
✗ |
CcDisplayMode *mode = l->data; |
768 |
|
|
int width, height; |
769 |
|
|
|
770 |
|
✗ |
cc_display_mode_get_resolution (mode, &width, &height); |
771 |
|
✗ |
if (width != clone_width || height != clone_height) |
772 |
|
✗ |
continue; |
773 |
|
|
|
774 |
|
✗ |
if (!best_mode) |
775 |
|
|
{ |
776 |
|
✗ |
best_mode = mode; |
777 |
|
✗ |
continue; |
778 |
|
|
} |
779 |
|
|
|
780 |
|
✗ |
if (cc_display_mode_get_freq_f (mode) > |
781 |
|
✗ |
cc_display_mode_get_freq_f (best_mode)) |
782 |
|
✗ |
best_mode = mode; |
783 |
|
|
} |
784 |
|
|
|
785 |
|
✗ |
g_return_if_fail (best_mode); |
786 |
|
|
|
787 |
|
✗ |
cc_display_monitor_set_mode (CC_DISPLAY_MONITOR (self), best_mode); |
788 |
|
|
} |
789 |
|
|
|
790 |
|
|
static void |
791 |
|
✗ |
cc_display_monitor_dbus_set_refresh_rate_mode (CcDisplayMonitor *pself, |
792 |
|
|
CcDisplayModeRefreshRateMode refresh_rate_mode) |
793 |
|
|
{ |
794 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
795 |
|
✗ |
CcDisplayModeDBus *mode_dbus = CC_DISPLAY_MODE_DBUS (self->current_mode); |
796 |
|
|
CcDisplayMode *new_mode; |
797 |
|
|
|
798 |
|
✗ |
g_return_if_fail (mode_dbus != NULL); |
799 |
|
|
|
800 |
|
✗ |
new_mode = cc_display_monitor_dbus_get_closest_mode (self, |
801 |
|
|
mode_dbus->width, |
802 |
|
|
mode_dbus->height, |
803 |
|
|
mode_dbus->refresh_rate, |
804 |
|
|
refresh_rate_mode, |
805 |
|
|
mode_dbus->flags); |
806 |
|
|
|
807 |
|
✗ |
g_return_if_fail (new_mode != NULL); |
808 |
|
|
|
809 |
|
✗ |
cc_display_monitor_set_mode (CC_DISPLAY_MONITOR (self), new_mode); |
810 |
|
|
} |
811 |
|
|
|
812 |
|
|
static void |
813 |
|
✗ |
cc_display_monitor_dbus_set_position (CcDisplayMonitor *pself, |
814 |
|
|
int x, int y) |
815 |
|
|
{ |
816 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
817 |
|
|
|
818 |
|
✗ |
if (self->logical_monitor) |
819 |
|
|
{ |
820 |
|
✗ |
gboolean notify = FALSE; |
821 |
|
|
|
822 |
|
✗ |
if (self->logical_monitor->x != x || self->logical_monitor->y != y) |
823 |
|
✗ |
notify = TRUE; |
824 |
|
|
|
825 |
|
✗ |
self->logical_monitor->x = x; |
826 |
|
✗ |
self->logical_monitor->y = y; |
827 |
|
|
|
828 |
|
✗ |
if (notify) |
829 |
|
✗ |
g_signal_emit_by_name (self, "position-changed"); |
830 |
|
|
} |
831 |
|
|
|
832 |
|
✗ |
} |
833 |
|
|
|
834 |
|
|
static double |
835 |
|
✗ |
cc_display_monitor_dbus_get_scale (CcDisplayMonitor *pself) |
836 |
|
|
{ |
837 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
838 |
|
|
|
839 |
|
✗ |
if (self->logical_monitor) |
840 |
|
✗ |
return self->logical_monitor->scale; |
841 |
|
|
|
842 |
|
✗ |
return 1.0; |
843 |
|
|
} |
844 |
|
|
|
845 |
|
|
static void |
846 |
|
✗ |
cc_display_monitor_dbus_set_scale (CcDisplayMonitor *pself, |
847 |
|
|
double scale) |
848 |
|
|
{ |
849 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (pself); |
850 |
|
|
|
851 |
|
✗ |
if (!self->current_mode) |
852 |
|
✗ |
return; |
853 |
|
|
|
854 |
|
✗ |
if (!cc_display_mode_dbus_is_supported_scale (self->current_mode, scale)) |
855 |
|
✗ |
return; |
856 |
|
|
|
857 |
|
✗ |
if (!self->logical_monitor) |
858 |
|
✗ |
return; |
859 |
|
|
|
860 |
|
✗ |
if (!G_APPROX_VALUE (self->logical_monitor->scale, scale, DBL_EPSILON)) |
861 |
|
|
{ |
862 |
|
✗ |
self->logical_monitor->scale = scale; |
863 |
|
|
|
864 |
|
✗ |
g_signal_emit_by_name (self, "scale"); |
865 |
|
|
} |
866 |
|
|
} |
867 |
|
|
|
868 |
|
|
static void |
869 |
|
✗ |
cc_display_monitor_dbus_init (CcDisplayMonitorDBus *self) |
870 |
|
|
{ |
871 |
|
✗ |
self->underscanning = UNDERSCANNING_UNSUPPORTED; |
872 |
|
✗ |
self->max_width = G_MAXINT; |
873 |
|
✗ |
self->max_height = G_MAXINT; |
874 |
|
✗ |
} |
875 |
|
|
|
876 |
|
|
static void |
877 |
|
✗ |
cc_display_monitor_dbus_finalize (GObject *object) |
878 |
|
|
{ |
879 |
|
✗ |
CcDisplayMonitorDBus *self = CC_DISPLAY_MONITOR_DBUS (object); |
880 |
|
|
|
881 |
|
✗ |
g_free (self->connector_name); |
882 |
|
✗ |
g_free (self->vendor_name); |
883 |
|
✗ |
g_free (self->product_name); |
884 |
|
✗ |
g_free (self->product_serial); |
885 |
|
✗ |
g_free (self->display_name); |
886 |
|
|
|
887 |
|
✗ |
g_list_free_full (self->modes, g_object_unref); |
888 |
|
|
|
889 |
|
✗ |
if (self->logical_monitor) |
890 |
|
|
{ |
891 |
|
✗ |
g_hash_table_remove (self->logical_monitor->monitors, self); |
892 |
|
✗ |
g_object_unref (self->logical_monitor); |
893 |
|
|
} |
894 |
|
|
|
895 |
|
✗ |
G_OBJECT_CLASS (cc_display_monitor_dbus_parent_class)->finalize (object); |
896 |
|
✗ |
} |
897 |
|
|
|
898 |
|
|
static void |
899 |
|
✗ |
cc_display_monitor_dbus_class_init (CcDisplayMonitorDBusClass *klass) |
900 |
|
|
{ |
901 |
|
✗ |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
902 |
|
✗ |
CcDisplayMonitorClass *parent_class = CC_DISPLAY_MONITOR_CLASS (klass); |
903 |
|
|
|
904 |
|
✗ |
gobject_class->finalize = cc_display_monitor_dbus_finalize; |
905 |
|
|
|
906 |
|
✗ |
parent_class->get_display_name = cc_display_monitor_dbus_get_display_name; |
907 |
|
✗ |
parent_class->get_connector_name = cc_display_monitor_dbus_get_connector_name; |
908 |
|
✗ |
parent_class->is_builtin = cc_display_monitor_dbus_is_builtin; |
909 |
|
✗ |
parent_class->is_primary = cc_display_monitor_dbus_is_primary; |
910 |
|
✗ |
parent_class->set_primary = cc_display_monitor_dbus_set_primary; |
911 |
|
✗ |
parent_class->is_active = cc_display_monitor_dbus_is_active; |
912 |
|
✗ |
parent_class->set_active = cc_display_monitor_dbus_set_active; |
913 |
|
✗ |
parent_class->get_rotation = cc_display_monitor_dbus_get_rotation; |
914 |
|
✗ |
parent_class->set_rotation = cc_display_monitor_dbus_set_rotation; |
915 |
|
✗ |
parent_class->supports_rotation = cc_display_monitor_dbus_supports_rotation; |
916 |
|
✗ |
parent_class->get_physical_size = cc_display_monitor_dbus_get_physical_size; |
917 |
|
✗ |
parent_class->get_geometry = cc_display_monitor_dbus_get_geometry; |
918 |
|
✗ |
parent_class->get_min_freq = cc_display_monitor_dbus_get_min_freq; |
919 |
|
✗ |
parent_class->get_mode = cc_display_monitor_dbus_get_mode; |
920 |
|
✗ |
parent_class->get_preferred_mode = cc_display_monitor_dbus_get_preferred_mode; |
921 |
|
✗ |
parent_class->get_id = cc_display_monitor_dbus_get_id; |
922 |
|
✗ |
parent_class->get_modes = cc_display_monitor_dbus_get_modes; |
923 |
|
✗ |
parent_class->supports_variable_refresh_rate = cc_display_monitor_dbus_supports_variable_refresh_rate; |
924 |
|
✗ |
parent_class->supports_underscanning = cc_display_monitor_dbus_supports_underscanning; |
925 |
|
✗ |
parent_class->get_underscanning = cc_display_monitor_dbus_get_underscanning; |
926 |
|
✗ |
parent_class->set_underscanning = cc_display_monitor_dbus_set_underscanning; |
927 |
|
✗ |
parent_class->get_privacy = cc_display_monitor_dbus_get_privacy; |
928 |
|
✗ |
parent_class->set_mode = cc_display_monitor_dbus_set_mode; |
929 |
|
✗ |
parent_class->set_compatible_clone_mode = cc_display_monitor_dbus_set_compatible_clone_mode; |
930 |
|
✗ |
parent_class->set_refresh_rate_mode = cc_display_monitor_dbus_set_refresh_rate_mode; |
931 |
|
✗ |
parent_class->set_position = cc_display_monitor_dbus_set_position; |
932 |
|
✗ |
parent_class->get_scale = cc_display_monitor_dbus_get_scale; |
933 |
|
✗ |
parent_class->set_scale = cc_display_monitor_dbus_set_scale; |
934 |
|
✗ |
} |
935 |
|
|
|
936 |
|
|
static void |
937 |
|
✗ |
construct_modes (CcDisplayMonitorDBus *self, |
938 |
|
|
GVariantIter *modes) |
939 |
|
|
{ |
940 |
|
|
CcDisplayModeDBus *mode; |
941 |
|
|
|
942 |
|
|
while (TRUE) |
943 |
|
✗ |
{ |
944 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
945 |
|
|
|
946 |
|
✗ |
if (!g_variant_iter_next (modes, "@"MODE_FORMAT, &variant)) |
947 |
|
✗ |
break; |
948 |
|
|
|
949 |
|
✗ |
mode = cc_display_mode_dbus_new (self, variant); |
950 |
|
✗ |
self->modes = g_list_prepend (self->modes, mode); |
951 |
|
|
|
952 |
|
✗ |
if (mode->flags & MODE_PREFERRED) |
953 |
|
✗ |
self->preferred_mode = CC_DISPLAY_MODE (mode); |
954 |
|
✗ |
if (mode->flags & MODE_CURRENT) |
955 |
|
✗ |
self->current_mode = CC_DISPLAY_MODE (mode); |
956 |
|
|
|
957 |
|
✗ |
if (mode->refresh_rate_mode == MODE_REFRESH_RATE_MODE_VARIABLE) |
958 |
|
✗ |
self->supports_variable_refresh_rate = TRUE; |
959 |
|
|
} |
960 |
|
|
|
961 |
|
✗ |
self->modes = g_list_reverse (self->modes); |
962 |
|
✗ |
} |
963 |
|
|
|
964 |
|
|
static CcDisplayMonitorDBus * |
965 |
|
✗ |
cc_display_monitor_dbus_new (GVariant *variant, |
966 |
|
|
CcDisplayConfigDBus *config) |
967 |
|
|
{ |
968 |
|
✗ |
CcDisplayMonitorDBus *self = g_object_new (CC_TYPE_DISPLAY_MONITOR_DBUS, NULL); |
969 |
|
|
gchar *s1, *s2, *s3, *s4; |
970 |
|
✗ |
g_autoptr(GVariantIter) modes = NULL; |
971 |
|
✗ |
g_autoptr(GVariantIter) props = NULL; |
972 |
|
|
|
973 |
|
✗ |
self->config = config; |
974 |
|
|
|
975 |
|
✗ |
g_variant_get (variant, MONITOR_FORMAT, |
976 |
|
|
&s1, &s2, &s3, &s4, &modes, &props); |
977 |
|
✗ |
self->connector_name = s1; |
978 |
|
✗ |
self->vendor_name = s2; |
979 |
|
✗ |
self->product_name = s3; |
980 |
|
✗ |
self->product_serial = s4; |
981 |
|
|
|
982 |
|
✗ |
construct_modes (self, modes); |
983 |
|
|
|
984 |
|
|
while (TRUE) |
985 |
|
✗ |
{ |
986 |
|
|
const char *s; |
987 |
|
✗ |
g_autoptr(GVariant) v = NULL; |
988 |
|
|
|
989 |
|
✗ |
if (!g_variant_iter_next (props, "{&sv}", &s, &v)) |
990 |
|
✗ |
break; |
991 |
|
|
|
992 |
|
✗ |
if (g_str_equal (s, "width-mm")) |
993 |
|
|
{ |
994 |
|
✗ |
g_variant_get (v, "i", &self->width_mm); |
995 |
|
|
} |
996 |
|
✗ |
else if (g_str_equal (s, "height-mm")) |
997 |
|
|
{ |
998 |
|
✗ |
g_variant_get (v, "i", &self->height_mm); |
999 |
|
|
} |
1000 |
|
✗ |
else if (g_str_equal (s, "is-underscanning")) |
1001 |
|
|
{ |
1002 |
|
✗ |
gboolean underscanning = FALSE; |
1003 |
|
✗ |
g_variant_get (v, "b", &underscanning); |
1004 |
|
✗ |
if (underscanning) |
1005 |
|
✗ |
self->underscanning = UNDERSCANNING_ENABLED; |
1006 |
|
|
else |
1007 |
|
✗ |
self->underscanning = UNDERSCANNING_DISABLED; |
1008 |
|
|
} |
1009 |
|
✗ |
else if (g_str_equal (s, "max-screen-size")) |
1010 |
|
|
{ |
1011 |
|
✗ |
g_variant_get (v, "ii", &self->max_width, &self->max_height); |
1012 |
|
|
} |
1013 |
|
✗ |
else if (g_str_equal (s, "is-builtin")) |
1014 |
|
|
{ |
1015 |
|
✗ |
g_variant_get (v, "b", &self->builtin); |
1016 |
|
|
} |
1017 |
|
✗ |
else if (g_str_equal (s, "display-name")) |
1018 |
|
|
{ |
1019 |
|
✗ |
g_variant_get (v, "s", &self->display_name); |
1020 |
|
|
} |
1021 |
|
✗ |
else if (g_str_equal (s, "privacy-screen-state")) |
1022 |
|
|
{ |
1023 |
|
|
gboolean enabled; |
1024 |
|
|
gboolean locked; |
1025 |
|
✗ |
g_variant_get (v, "(bb)", &enabled, &locked); |
1026 |
|
|
|
1027 |
|
✗ |
if (enabled) |
1028 |
|
✗ |
self->privacy_screen = CC_DISPLAY_MONITOR_PRIVACY_ENABLED; |
1029 |
|
|
else |
1030 |
|
✗ |
self->privacy_screen = CC_DISPLAY_MONITOR_PRIVACY_DISABLED; |
1031 |
|
|
|
1032 |
|
✗ |
if (locked) |
1033 |
|
✗ |
self->privacy_screen |= CC_DISPLAY_MONITOR_PRIVACY_LOCKED; |
1034 |
|
|
} |
1035 |
|
✗ |
else if (g_str_equal (s, "min-refresh-rate")) |
1036 |
|
|
{ |
1037 |
|
✗ |
g_variant_get (v, "i", &self->min_refresh_rate); |
1038 |
|
|
} |
1039 |
|
|
} |
1040 |
|
|
|
1041 |
|
✗ |
return self; |
1042 |
|
|
} |
1043 |
|
|
|
1044 |
|
|
|
1045 |
|
|
typedef enum _CcDisplayLayoutMode |
1046 |
|
|
{ |
1047 |
|
|
CC_DISPLAY_LAYOUT_MODE_LOGICAL = 1, |
1048 |
|
|
CC_DISPLAY_LAYOUT_MODE_PHYSICAL = 2 |
1049 |
|
|
} CcDisplayLayoutMode; |
1050 |
|
|
|
1051 |
|
|
typedef enum _CcDisplayConfigMethod |
1052 |
|
|
{ |
1053 |
|
|
CC_DISPLAY_CONFIG_METHOD_VERIFY = 0, |
1054 |
|
|
CC_DISPLAY_CONFIG_METHOD_TEMPORARY = 1, |
1055 |
|
|
CC_DISPLAY_CONFIG_METHOD_PERSISTENT = 2 |
1056 |
|
|
} CcDisplayConfigMethod; |
1057 |
|
|
|
1058 |
|
|
struct _CcDisplayConfigDBus |
1059 |
|
|
{ |
1060 |
|
|
CcDisplayConfig parent_instance; |
1061 |
|
|
|
1062 |
|
|
GVariant *state; |
1063 |
|
|
GDBusConnection *connection; |
1064 |
|
|
GDBusProxy *proxy; |
1065 |
|
|
|
1066 |
|
|
int min_width; |
1067 |
|
|
int min_height; |
1068 |
|
|
|
1069 |
|
|
guint panel_orientation_managed; |
1070 |
|
|
|
1071 |
|
|
guint32 serial; |
1072 |
|
|
gboolean supports_mirroring; |
1073 |
|
|
gboolean supports_changing_layout_mode; |
1074 |
|
|
gboolean global_scale_required; |
1075 |
|
|
CcDisplayLayoutMode layout_mode; |
1076 |
|
|
|
1077 |
|
|
GList *monitors; |
1078 |
|
|
CcDisplayMonitorDBus *primary; |
1079 |
|
|
|
1080 |
|
|
GHashTable *logical_monitors; |
1081 |
|
|
}; |
1082 |
|
|
|
1083 |
|
✗ |
G_DEFINE_TYPE (CcDisplayConfigDBus, |
1084 |
|
|
cc_display_config_dbus, |
1085 |
|
|
CC_TYPE_DISPLAY_CONFIG) |
1086 |
|
|
|
1087 |
|
|
enum |
1088 |
|
|
{ |
1089 |
|
|
PROP_0, |
1090 |
|
|
PROP_STATE, |
1091 |
|
|
PROP_CONNECTION, |
1092 |
|
|
}; |
1093 |
|
|
|
1094 |
|
|
static GList * |
1095 |
|
✗ |
cc_display_config_dbus_get_monitors (CcDisplayConfig *pself) |
1096 |
|
|
{ |
1097 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1098 |
|
|
|
1099 |
|
✗ |
return self->monitors; |
1100 |
|
|
} |
1101 |
|
|
|
1102 |
|
|
static GVariant * |
1103 |
|
✗ |
build_monitors_variant (GHashTable *monitors) |
1104 |
|
|
{ |
1105 |
|
|
GVariantBuilder builder; |
1106 |
|
|
GHashTableIter iter; |
1107 |
|
|
CcDisplayMonitorDBus *monitor; |
1108 |
|
|
|
1109 |
|
✗ |
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); |
1110 |
|
✗ |
g_hash_table_iter_init (&iter, monitors); |
1111 |
|
|
|
1112 |
|
✗ |
while (g_hash_table_iter_next (&iter, (void **) &monitor, NULL)) |
1113 |
|
|
{ |
1114 |
|
|
GVariantBuilder props_builder; |
1115 |
|
|
CcDisplayModeDBus *mode_dbus; |
1116 |
|
|
|
1117 |
|
✗ |
if (!monitor->current_mode) |
1118 |
|
✗ |
continue; |
1119 |
|
|
|
1120 |
|
✗ |
g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); |
1121 |
|
✗ |
g_variant_builder_add (&props_builder, "{sv}", |
1122 |
|
|
"underscanning", |
1123 |
|
✗ |
g_variant_new_boolean (monitor->underscanning == UNDERSCANNING_ENABLED)); |
1124 |
|
|
|
1125 |
|
✗ |
mode_dbus = CC_DISPLAY_MODE_DBUS (monitor->current_mode); |
1126 |
|
✗ |
g_variant_builder_add (&builder, "(ss@*)", |
1127 |
|
✗ |
monitor->connector_name, |
1128 |
|
|
mode_dbus->id, |
1129 |
|
|
g_variant_builder_end (&props_builder)); |
1130 |
|
|
} |
1131 |
|
|
|
1132 |
|
✗ |
return g_variant_builder_end (&builder); |
1133 |
|
|
} |
1134 |
|
|
|
1135 |
|
|
static GVariant * |
1136 |
|
✗ |
build_logical_monitors_parameter (CcDisplayConfigDBus *self) |
1137 |
|
|
{ |
1138 |
|
|
GVariantBuilder builder; |
1139 |
|
|
GHashTableIter iter; |
1140 |
|
|
CcDisplayLogicalMonitor *logical_monitor; |
1141 |
|
|
|
1142 |
|
✗ |
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(iiduba(ssa{sv}))")); |
1143 |
|
✗ |
g_hash_table_iter_init (&iter, self->logical_monitors); |
1144 |
|
|
|
1145 |
|
✗ |
while (g_hash_table_iter_next (&iter, (void **) &logical_monitor, NULL)) |
1146 |
|
✗ |
g_variant_builder_add (&builder, "(iidub@*)", |
1147 |
|
✗ |
logical_monitor->x, |
1148 |
|
✗ |
logical_monitor->y, |
1149 |
|
✗ |
logical_monitor->scale, |
1150 |
|
✗ |
logical_monitor->rotation, |
1151 |
|
✗ |
logical_monitor->primary, |
1152 |
|
✗ |
build_monitors_variant (logical_monitor->monitors)); |
1153 |
|
|
|
1154 |
|
✗ |
return g_variant_builder_end (&builder); |
1155 |
|
|
} |
1156 |
|
|
|
1157 |
|
|
static GVariant * |
1158 |
|
✗ |
build_apply_parameters (CcDisplayConfigDBus *self, |
1159 |
|
|
CcDisplayConfigMethod method) |
1160 |
|
|
{ |
1161 |
|
|
GVariantBuilder props_builder; |
1162 |
|
✗ |
g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}")); |
1163 |
|
|
|
1164 |
|
✗ |
if (self->supports_changing_layout_mode) |
1165 |
|
✗ |
g_variant_builder_add (&props_builder, "{sv}", |
1166 |
|
✗ |
"layout-mode", g_variant_new_uint32 (self->layout_mode)); |
1167 |
|
|
|
1168 |
|
✗ |
return g_variant_new ("(uu@*@*)", |
1169 |
|
|
self->serial, |
1170 |
|
|
method, |
1171 |
|
|
build_logical_monitors_parameter (self), |
1172 |
|
|
g_variant_builder_end (&props_builder)); |
1173 |
|
|
} |
1174 |
|
|
|
1175 |
|
|
static gboolean |
1176 |
|
✗ |
config_apply (CcDisplayConfigDBus *self, |
1177 |
|
|
CcDisplayConfigMethod method, |
1178 |
|
|
GError **error) |
1179 |
|
|
{ |
1180 |
|
✗ |
g_autoptr(GVariant) retval = NULL; |
1181 |
|
|
|
1182 |
|
✗ |
cc_display_config_dbus_ensure_non_offset_coords (self); |
1183 |
|
|
|
1184 |
|
✗ |
retval = g_dbus_proxy_call_sync (self->proxy, |
1185 |
|
|
"ApplyMonitorsConfig", |
1186 |
|
|
build_apply_parameters (self, method), |
1187 |
|
|
G_DBUS_CALL_FLAGS_NO_AUTO_START, |
1188 |
|
|
-1, |
1189 |
|
|
NULL, |
1190 |
|
|
error); |
1191 |
|
✗ |
return retval != NULL; |
1192 |
|
|
} |
1193 |
|
|
|
1194 |
|
|
static gboolean |
1195 |
|
✗ |
cc_display_config_dbus_is_applicable (CcDisplayConfig *pself) |
1196 |
|
|
{ |
1197 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1198 |
|
✗ |
g_autoptr(GError) error = NULL; |
1199 |
|
|
|
1200 |
|
✗ |
if (!config_apply (self, CC_DISPLAY_CONFIG_METHOD_VERIFY, &error)) |
1201 |
|
|
{ |
1202 |
|
✗ |
g_warning ("Config not applicable: %s", error->message); |
1203 |
|
✗ |
return FALSE; |
1204 |
|
|
} |
1205 |
|
|
else |
1206 |
|
|
{ |
1207 |
|
✗ |
return TRUE; |
1208 |
|
|
} |
1209 |
|
|
} |
1210 |
|
|
|
1211 |
|
|
static CcDisplayMonitorDBus * |
1212 |
|
✗ |
monitor_from_spec (CcDisplayConfigDBus *self, |
1213 |
|
|
const gchar *connector, |
1214 |
|
|
const gchar *vendor, |
1215 |
|
|
const gchar *product, |
1216 |
|
|
const gchar *serial) |
1217 |
|
|
{ |
1218 |
|
|
GList *l; |
1219 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1220 |
|
|
{ |
1221 |
|
✗ |
CcDisplayMonitorDBus *m = l->data; |
1222 |
|
✗ |
if (g_str_equal (m->connector_name, connector) && |
1223 |
|
✗ |
g_str_equal (m->vendor_name, vendor) && |
1224 |
|
✗ |
g_str_equal (m->product_name, product) && |
1225 |
|
✗ |
g_str_equal (m->product_serial, serial)) |
1226 |
|
✗ |
return m; |
1227 |
|
|
} |
1228 |
|
✗ |
return NULL; |
1229 |
|
|
} |
1230 |
|
|
|
1231 |
|
|
static gboolean |
1232 |
|
✗ |
cc_display_config_dbus_equal (CcDisplayConfig *pself, |
1233 |
|
|
CcDisplayConfig *pother) |
1234 |
|
|
{ |
1235 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1236 |
|
✗ |
CcDisplayConfigDBus *other = CC_DISPLAY_CONFIG_DBUS (pother); |
1237 |
|
|
GList *l; |
1238 |
|
|
|
1239 |
|
✗ |
g_return_val_if_fail (pself, FALSE); |
1240 |
|
✗ |
g_return_val_if_fail (pother, FALSE); |
1241 |
|
|
|
1242 |
|
✗ |
cc_display_config_dbus_ensure_non_offset_coords (self); |
1243 |
|
✗ |
cc_display_config_dbus_ensure_non_offset_coords (other); |
1244 |
|
|
|
1245 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1246 |
|
|
{ |
1247 |
|
✗ |
CcDisplayMonitorDBus *m1 = l->data; |
1248 |
|
✗ |
CcDisplayMonitorDBus *m2 = monitor_from_spec (other, |
1249 |
|
✗ |
m1->connector_name, |
1250 |
|
✗ |
m1->vendor_name, |
1251 |
|
✗ |
m1->product_name, |
1252 |
|
✗ |
m1->product_serial); |
1253 |
|
✗ |
if (!m2) |
1254 |
|
✗ |
return FALSE; |
1255 |
|
|
|
1256 |
|
✗ |
if (m1->underscanning != m2->underscanning) |
1257 |
|
✗ |
return FALSE; |
1258 |
|
|
|
1259 |
|
✗ |
if (!cc_display_logical_monitor_equal (m1->logical_monitor, m2->logical_monitor)) |
1260 |
|
✗ |
return FALSE; |
1261 |
|
|
|
1262 |
|
|
/* Modes should not be compared if both monitors have no logical monitor. */ |
1263 |
|
✗ |
if (m1->logical_monitor == NULL && m2->logical_monitor == NULL) |
1264 |
|
✗ |
continue; |
1265 |
|
|
|
1266 |
|
✗ |
if (!cc_display_mode_dbus_equal (CC_DISPLAY_MODE_DBUS (m1->current_mode), |
1267 |
|
✗ |
CC_DISPLAY_MODE_DBUS (m2->current_mode))) |
1268 |
|
✗ |
return FALSE; |
1269 |
|
|
} |
1270 |
|
|
|
1271 |
|
✗ |
return TRUE; |
1272 |
|
|
} |
1273 |
|
|
|
1274 |
|
|
static void |
1275 |
|
✗ |
cc_display_config_dbus_set_primary (CcDisplayConfigDBus *self, |
1276 |
|
|
CcDisplayMonitorDBus *new_primary) |
1277 |
|
|
{ |
1278 |
|
✗ |
if (self->primary == new_primary) |
1279 |
|
✗ |
return; |
1280 |
|
|
|
1281 |
|
✗ |
if (!new_primary->logical_monitor) |
1282 |
|
✗ |
return; |
1283 |
|
|
|
1284 |
|
✗ |
if (self->primary && self->primary->logical_monitor) |
1285 |
|
|
{ |
1286 |
|
✗ |
self->primary->logical_monitor->primary = FALSE; |
1287 |
|
✗ |
g_signal_emit_by_name (self->primary, "primary"); |
1288 |
|
|
} |
1289 |
|
|
|
1290 |
|
✗ |
self->primary = new_primary; |
1291 |
|
✗ |
self->primary->logical_monitor->primary = TRUE; |
1292 |
|
|
|
1293 |
|
✗ |
g_signal_emit_by_name (self->primary, "primary"); |
1294 |
|
✗ |
g_signal_emit_by_name (self, "primary"); |
1295 |
|
|
} |
1296 |
|
|
|
1297 |
|
|
static void |
1298 |
|
✗ |
cc_display_config_dbus_unset_primary (CcDisplayConfigDBus *self, |
1299 |
|
|
CcDisplayMonitorDBus *old_primary) |
1300 |
|
|
{ |
1301 |
|
|
GList *l; |
1302 |
|
|
|
1303 |
|
✗ |
if (self->primary != old_primary) |
1304 |
|
✗ |
return; |
1305 |
|
|
|
1306 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1307 |
|
|
{ |
1308 |
|
✗ |
CcDisplayMonitorDBus *monitor = l->data; |
1309 |
|
✗ |
if (monitor->logical_monitor && |
1310 |
|
|
monitor != old_primary) |
1311 |
|
|
{ |
1312 |
|
✗ |
cc_display_config_dbus_set_primary (self, monitor); |
1313 |
|
✗ |
break; |
1314 |
|
|
} |
1315 |
|
|
} |
1316 |
|
|
|
1317 |
|
✗ |
if (self->primary == old_primary) |
1318 |
|
✗ |
self->primary = NULL; |
1319 |
|
|
} |
1320 |
|
|
|
1321 |
|
|
static gboolean |
1322 |
|
✗ |
cc_display_config_dbus_is_cloning (CcDisplayConfig *pself) |
1323 |
|
|
{ |
1324 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1325 |
|
✗ |
guint n_active_monitors = 0; |
1326 |
|
|
GList *l; |
1327 |
|
|
|
1328 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1329 |
|
✗ |
if (cc_display_monitor_is_active (CC_DISPLAY_MONITOR (l->data))) |
1330 |
|
✗ |
n_active_monitors += 1; |
1331 |
|
|
|
1332 |
|
✗ |
return n_active_monitors > 1 && g_hash_table_size (self->logical_monitors) == 1; |
1333 |
|
|
} |
1334 |
|
|
|
1335 |
|
|
static void |
1336 |
|
✗ |
cc_display_config_dbus_set_cloning (CcDisplayConfig *pself, |
1337 |
|
|
gboolean clone) |
1338 |
|
|
{ |
1339 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1340 |
|
✗ |
gboolean is_cloning = cc_display_config_is_cloning (pself); |
1341 |
|
|
CcDisplayLogicalMonitor *logical_monitor; |
1342 |
|
|
GList *l; |
1343 |
|
|
|
1344 |
|
✗ |
if (clone && !is_cloning) |
1345 |
|
|
{ |
1346 |
|
✗ |
logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL); |
1347 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1348 |
|
|
{ |
1349 |
|
✗ |
if (!cc_display_monitor_is_usable (l->data)) |
1350 |
|
✗ |
continue; |
1351 |
|
✗ |
cc_display_monitor_dbus_set_logical_monitor (CC_DISPLAY_MONITOR_DBUS (l->data), |
1352 |
|
|
logical_monitor); |
1353 |
|
|
} |
1354 |
|
✗ |
register_logical_monitor (self, logical_monitor); |
1355 |
|
|
} |
1356 |
|
✗ |
else if (!clone && is_cloning) |
1357 |
|
|
{ |
1358 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1359 |
|
|
{ |
1360 |
|
✗ |
logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL); |
1361 |
|
✗ |
cc_display_monitor_dbus_set_logical_monitor (CC_DISPLAY_MONITOR_DBUS (l->data), |
1362 |
|
|
logical_monitor); |
1363 |
|
✗ |
register_logical_monitor (self, logical_monitor); |
1364 |
|
|
} |
1365 |
|
✗ |
cc_display_config_dbus_make_linear (self); |
1366 |
|
|
} |
1367 |
|
✗ |
} |
1368 |
|
|
|
1369 |
|
|
static gboolean |
1370 |
|
✗ |
mode_supports_scale (CcDisplayMode *mode, |
1371 |
|
|
double scale) |
1372 |
|
|
{ |
1373 |
|
✗ |
g_autoptr(GArray) scales = NULL; |
1374 |
|
|
int i; |
1375 |
|
|
|
1376 |
|
✗ |
scales = cc_display_mode_get_supported_scales (mode); |
1377 |
|
✗ |
for (i = 0; i < scales->len; i++) |
1378 |
|
|
{ |
1379 |
|
✗ |
if (G_APPROX_VALUE (scale, g_array_index (scales, double, i), |
1380 |
|
|
DBL_EPSILON)) |
1381 |
|
✗ |
return TRUE; |
1382 |
|
|
} |
1383 |
|
|
|
1384 |
|
✗ |
return FALSE; |
1385 |
|
|
} |
1386 |
|
|
|
1387 |
|
|
static void |
1388 |
|
✗ |
remove_unsupported_scales (CcDisplayMode *mode, |
1389 |
|
|
GArray *supported_scales) |
1390 |
|
|
{ |
1391 |
|
✗ |
g_autoptr(GArray) mode_scales = NULL; |
1392 |
|
|
int i; |
1393 |
|
|
|
1394 |
|
✗ |
mode_scales = cc_display_mode_get_supported_scales (mode); |
1395 |
|
✗ |
i = 0; |
1396 |
|
✗ |
while (i < supported_scales->len) |
1397 |
|
|
{ |
1398 |
|
|
double scale; |
1399 |
|
|
|
1400 |
|
✗ |
if (i == supported_scales->len) |
1401 |
|
✗ |
break; |
1402 |
|
|
|
1403 |
|
✗ |
scale = g_array_index (supported_scales, double, i); |
1404 |
|
|
|
1405 |
|
✗ |
if (mode_supports_scale (mode, scale)) |
1406 |
|
|
{ |
1407 |
|
✗ |
i++; |
1408 |
|
✗ |
continue; |
1409 |
|
|
} |
1410 |
|
|
|
1411 |
|
✗ |
g_array_remove_range (supported_scales, i, 1); |
1412 |
|
|
} |
1413 |
|
✗ |
} |
1414 |
|
|
|
1415 |
|
|
static gboolean |
1416 |
|
✗ |
monitor_has_compatible_clone_mode (CcDisplayMonitorDBus *monitor, |
1417 |
|
|
CcDisplayModeDBus *mode, |
1418 |
|
|
GArray *supported_scales) |
1419 |
|
|
{ |
1420 |
|
|
GList *l; |
1421 |
|
|
|
1422 |
|
✗ |
for (l = monitor->modes; l; l = l->next) |
1423 |
|
|
{ |
1424 |
|
✗ |
CcDisplayModeDBus *other_mode = l->data; |
1425 |
|
|
|
1426 |
|
✗ |
if (other_mode->width != mode->width || |
1427 |
|
✗ |
other_mode->height != mode->height) |
1428 |
|
✗ |
continue; |
1429 |
|
|
|
1430 |
|
✗ |
if ((other_mode->flags & MODE_INTERLACED) != |
1431 |
|
✗ |
(mode->flags & MODE_INTERLACED)) |
1432 |
|
✗ |
continue; |
1433 |
|
|
|
1434 |
|
✗ |
remove_unsupported_scales (CC_DISPLAY_MODE (other_mode), supported_scales); |
1435 |
|
|
|
1436 |
|
✗ |
return TRUE; |
1437 |
|
|
} |
1438 |
|
|
|
1439 |
|
✗ |
return FALSE; |
1440 |
|
|
} |
1441 |
|
|
|
1442 |
|
|
static gboolean |
1443 |
|
✗ |
monitors_has_compatible_clone_mode (CcDisplayConfigDBus *self, |
1444 |
|
|
CcDisplayModeDBus *mode, |
1445 |
|
|
GArray *supported_scales) |
1446 |
|
|
{ |
1447 |
|
|
GList *l; |
1448 |
|
|
|
1449 |
|
✗ |
for (l = self->monitors; l; l = l->next) |
1450 |
|
|
{ |
1451 |
|
✗ |
CcDisplayMonitorDBus *monitor = l->data; |
1452 |
|
|
|
1453 |
|
✗ |
if (!monitor_has_compatible_clone_mode (monitor, mode, supported_scales)) |
1454 |
|
✗ |
return FALSE; |
1455 |
|
|
} |
1456 |
|
|
|
1457 |
|
✗ |
return TRUE; |
1458 |
|
|
} |
1459 |
|
|
|
1460 |
|
|
static gboolean |
1461 |
|
✗ |
is_mode_better (CcDisplayModeDBus *mode, |
1462 |
|
|
CcDisplayModeDBus *other_mode) |
1463 |
|
|
{ |
1464 |
|
✗ |
if (mode->width * mode->height > other_mode->width * other_mode->height) |
1465 |
|
✗ |
return TRUE; |
1466 |
|
✗ |
else if (mode->width * mode->height < other_mode->width * other_mode->height) |
1467 |
|
✗ |
return FALSE; |
1468 |
|
|
|
1469 |
|
✗ |
if (!(mode->flags & MODE_INTERLACED) && |
1470 |
|
✗ |
(other_mode->flags & MODE_INTERLACED)) |
1471 |
|
✗ |
return TRUE; |
1472 |
|
|
|
1473 |
|
✗ |
return FALSE; |
1474 |
|
|
} |
1475 |
|
|
|
1476 |
|
|
static GList * |
1477 |
|
✗ |
cc_display_config_dbus_generate_cloning_modes (CcDisplayConfig *pself) |
1478 |
|
|
{ |
1479 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1480 |
|
✗ |
CcDisplayMonitorDBus *base_monitor = NULL; |
1481 |
|
|
GList *l; |
1482 |
|
✗ |
GList *clone_modes = NULL; |
1483 |
|
✗ |
CcDisplayModeDBus *best_mode = NULL; |
1484 |
|
|
|
1485 |
|
✗ |
for (l = self->monitors; l; l = l->next) |
1486 |
|
|
{ |
1487 |
|
✗ |
CcDisplayMonitor *monitor = l->data; |
1488 |
|
|
|
1489 |
|
✗ |
if (cc_display_monitor_is_active (monitor)) |
1490 |
|
|
{ |
1491 |
|
✗ |
base_monitor = CC_DISPLAY_MONITOR_DBUS (monitor); |
1492 |
|
✗ |
break; |
1493 |
|
|
} |
1494 |
|
|
} |
1495 |
|
|
|
1496 |
|
✗ |
if (!base_monitor) |
1497 |
|
✗ |
return NULL; |
1498 |
|
|
|
1499 |
|
✗ |
for (l = base_monitor->modes; l; l = l->next) |
1500 |
|
|
{ |
1501 |
|
✗ |
CcDisplayModeDBus *mode = l->data; |
1502 |
|
|
CcDisplayModeDBus *virtual_mode; |
1503 |
|
✗ |
g_autoptr (GArray) supported_scales = NULL; |
1504 |
|
|
|
1505 |
|
✗ |
supported_scales = |
1506 |
|
✗ |
cc_display_mode_get_supported_scales (CC_DISPLAY_MODE (mode)); |
1507 |
|
|
|
1508 |
|
✗ |
if (!monitors_has_compatible_clone_mode (self, mode, supported_scales)) |
1509 |
|
✗ |
continue; |
1510 |
|
|
|
1511 |
|
✗ |
virtual_mode = cc_display_mode_dbus_new_virtual (mode->width, |
1512 |
|
|
mode->height, |
1513 |
|
|
mode->preferred_scale, |
1514 |
|
|
supported_scales); |
1515 |
|
✗ |
clone_modes = g_list_append (clone_modes, virtual_mode); |
1516 |
|
|
|
1517 |
|
✗ |
if (!best_mode || is_mode_better (virtual_mode, best_mode)) |
1518 |
|
✗ |
best_mode = virtual_mode; |
1519 |
|
|
} |
1520 |
|
|
|
1521 |
|
✗ |
if (best_mode) |
1522 |
|
✗ |
best_mode->flags |= MODE_PREFERRED; |
1523 |
|
|
|
1524 |
|
✗ |
return clone_modes; |
1525 |
|
|
} |
1526 |
|
|
|
1527 |
|
|
static gboolean |
1528 |
|
✗ |
cc_display_config_dbus_apply (CcDisplayConfig *pself, |
1529 |
|
|
GError **error) |
1530 |
|
|
{ |
1531 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1532 |
|
|
|
1533 |
|
✗ |
return config_apply (self, CC_DISPLAY_CONFIG_METHOD_PERSISTENT, error); |
1534 |
|
|
} |
1535 |
|
|
|
1536 |
|
|
static gboolean |
1537 |
|
✗ |
cc_display_config_dbus_is_layout_logical (CcDisplayConfig *pself) |
1538 |
|
|
{ |
1539 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1540 |
|
|
|
1541 |
|
✗ |
return self->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL; |
1542 |
|
|
} |
1543 |
|
|
|
1544 |
|
|
static gboolean |
1545 |
|
|
is_scale_allowed_by_active_monitors (CcDisplayConfigDBus *self, |
1546 |
|
|
CcDisplayMode *mode, |
1547 |
|
|
double scale); |
1548 |
|
|
|
1549 |
|
|
static gboolean |
1550 |
|
✗ |
is_scaled_mode_allowed (CcDisplayConfigDBus *self, |
1551 |
|
|
CcDisplayModeDBus *mode, |
1552 |
|
|
double scale) |
1553 |
|
|
{ |
1554 |
|
|
gint width, height; |
1555 |
|
|
|
1556 |
|
|
/* Do the math as if the monitor is always in landscape mode. */ |
1557 |
|
✗ |
width = round (mode->width / scale); |
1558 |
|
✗ |
height = round (mode->height / scale); |
1559 |
|
|
|
1560 |
|
✗ |
if (MAX (width, height) < self->min_width || |
1561 |
|
✗ |
MIN (width, height) < self->min_height) |
1562 |
|
✗ |
return FALSE; |
1563 |
|
|
|
1564 |
|
✗ |
if (!self->global_scale_required) |
1565 |
|
✗ |
return TRUE; |
1566 |
|
|
|
1567 |
|
✗ |
return is_scale_allowed_by_active_monitors (self, CC_DISPLAY_MODE (mode), scale); |
1568 |
|
|
} |
1569 |
|
|
|
1570 |
|
|
static gboolean |
1571 |
|
✗ |
is_scale_allowed_by_active_monitors (CcDisplayConfigDBus *self, |
1572 |
|
|
CcDisplayMode *mode, |
1573 |
|
|
double scale) |
1574 |
|
|
{ |
1575 |
|
|
GList *l; |
1576 |
|
|
|
1577 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1578 |
|
|
{ |
1579 |
|
✗ |
CcDisplayMonitorDBus *m = CC_DISPLAY_MONITOR_DBUS (l->data); |
1580 |
|
|
|
1581 |
|
✗ |
if (!cc_display_monitor_is_active (CC_DISPLAY_MONITOR (m))) |
1582 |
|
✗ |
continue; |
1583 |
|
|
|
1584 |
|
✗ |
if (!cc_display_mode_dbus_is_supported_scale (mode, scale)) |
1585 |
|
✗ |
return FALSE; |
1586 |
|
|
} |
1587 |
|
|
|
1588 |
|
✗ |
return TRUE; |
1589 |
|
|
} |
1590 |
|
|
|
1591 |
|
|
static GArray * |
1592 |
|
✗ |
cc_display_mode_dbus_get_supported_scales (CcDisplayMode *pself) |
1593 |
|
|
{ |
1594 |
|
✗ |
CcDisplayModeDBus *self = CC_DISPLAY_MODE_DBUS (pself); |
1595 |
|
✗ |
CcDisplayConfig *config = CC_DISPLAY_CONFIG (self->monitor->config); |
1596 |
|
|
|
1597 |
|
✗ |
if (cc_display_config_is_cloning (config)) |
1598 |
|
|
{ |
1599 |
|
✗ |
GArray *scales = g_array_copy (self->supported_scales); |
1600 |
|
|
int i; |
1601 |
|
|
|
1602 |
|
✗ |
for (i = scales->len - 1; i >= 0; i--) |
1603 |
|
|
{ |
1604 |
|
✗ |
double scale = g_array_index (scales, double, i); |
1605 |
|
|
|
1606 |
|
✗ |
if (!is_scale_allowed_by_active_monitors (self->monitor->config, |
1607 |
|
|
pself, scale)) |
1608 |
|
✗ |
g_array_remove_index (scales, i); |
1609 |
|
|
} |
1610 |
|
|
|
1611 |
|
✗ |
return g_steal_pointer (&scales); |
1612 |
|
|
} |
1613 |
|
|
|
1614 |
|
✗ |
return g_array_ref (self->supported_scales); |
1615 |
|
|
} |
1616 |
|
|
|
1617 |
|
|
static void |
1618 |
|
✗ |
filter_out_invalid_scaled_modes (CcDisplayConfigDBus *self) |
1619 |
|
|
{ |
1620 |
|
|
GList *l; |
1621 |
|
|
|
1622 |
|
✗ |
for (l = self->monitors; l; l = l->next) |
1623 |
|
|
{ |
1624 |
|
✗ |
CcDisplayMonitorDBus *monitor = l->data; |
1625 |
|
✗ |
GList *ll = monitor->modes; |
1626 |
|
|
|
1627 |
|
✗ |
while (ll != NULL) |
1628 |
|
|
{ |
1629 |
|
✗ |
CcDisplayModeDBus *mode = ll->data; |
1630 |
|
✗ |
GList *current = ll; |
1631 |
|
✗ |
double current_scale = -1; |
1632 |
|
|
int i; |
1633 |
|
|
|
1634 |
|
✗ |
ll = ll->next; |
1635 |
|
|
|
1636 |
|
✗ |
if (monitor->current_mode != CC_DISPLAY_MODE (mode) && |
1637 |
|
✗ |
monitor->preferred_mode != CC_DISPLAY_MODE (mode) && |
1638 |
|
✗ |
!is_scaled_mode_allowed (self, mode, 1.0)) |
1639 |
|
|
{ |
1640 |
|
✗ |
g_clear_object (&mode); |
1641 |
|
✗ |
monitor->modes = g_list_delete_link (monitor->modes, current); |
1642 |
|
✗ |
continue; |
1643 |
|
|
} |
1644 |
|
|
|
1645 |
|
✗ |
if (monitor->current_mode == CC_DISPLAY_MODE (mode)) |
1646 |
|
✗ |
current_scale = cc_display_monitor_dbus_get_scale (CC_DISPLAY_MONITOR (monitor)); |
1647 |
|
|
|
1648 |
|
✗ |
for (i = mode->supported_scales->len - 1; i >= 0; i--) |
1649 |
|
|
{ |
1650 |
|
✗ |
float scale = g_array_index (mode->supported_scales, double, i); |
1651 |
|
|
|
1652 |
|
✗ |
if (!G_APPROX_VALUE (scale, current_scale, DBL_EPSILON) && |
1653 |
|
✗ |
!G_APPROX_VALUE (scale, mode->preferred_scale, DBL_EPSILON) && |
1654 |
|
✗ |
!is_scaled_mode_allowed (self, mode, scale)) |
1655 |
|
|
{ |
1656 |
|
✗ |
g_array_remove_index (mode->supported_scales, i); |
1657 |
|
|
} |
1658 |
|
|
} |
1659 |
|
|
} |
1660 |
|
|
} |
1661 |
|
✗ |
} |
1662 |
|
|
|
1663 |
|
|
static void |
1664 |
|
✗ |
cc_display_config_dbus_set_minimum_size (CcDisplayConfig *pself, |
1665 |
|
|
int width, |
1666 |
|
|
int height) |
1667 |
|
|
{ |
1668 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1669 |
|
|
|
1670 |
|
✗ |
g_assert (width >= 0 && height >= 0); |
1671 |
|
✗ |
g_assert (((self->min_width == 0 && self->min_height == 0) || |
1672 |
|
|
(self->min_width >= width && self->min_height >= height)) && |
1673 |
|
|
"Minimum size can't be set again to higher values"); |
1674 |
|
|
|
1675 |
|
✗ |
self->min_width = width; |
1676 |
|
✗ |
self->min_height = height; |
1677 |
|
|
|
1678 |
|
✗ |
filter_out_invalid_scaled_modes (self); |
1679 |
|
✗ |
} |
1680 |
|
|
|
1681 |
|
|
static gboolean |
1682 |
|
✗ |
cc_display_config_dbus_is_scaled_mode_valid (CcDisplayConfig *pself, |
1683 |
|
|
CcDisplayMode *mode, |
1684 |
|
|
double scale) |
1685 |
|
|
{ |
1686 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1687 |
|
|
|
1688 |
|
✗ |
if (cc_display_config_is_cloning (pself)) |
1689 |
|
✗ |
return is_scale_allowed_by_active_monitors (self, mode, scale); |
1690 |
|
|
|
1691 |
|
✗ |
return cc_display_mode_dbus_is_supported_scale (mode, scale); |
1692 |
|
|
} |
1693 |
|
|
|
1694 |
|
|
static gboolean |
1695 |
|
✗ |
cc_display_config_dbus_get_panel_orientation_managed (CcDisplayConfig *pself) |
1696 |
|
|
{ |
1697 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (pself); |
1698 |
|
|
|
1699 |
|
✗ |
return self->panel_orientation_managed; |
1700 |
|
|
} |
1701 |
|
|
|
1702 |
|
|
static void |
1703 |
|
✗ |
cc_display_config_dbus_init (CcDisplayConfigDBus *self) |
1704 |
|
|
{ |
1705 |
|
✗ |
self->serial = 0; |
1706 |
|
✗ |
self->supports_mirroring = TRUE; |
1707 |
|
✗ |
self->supports_changing_layout_mode = FALSE; |
1708 |
|
✗ |
self->global_scale_required = FALSE; |
1709 |
|
✗ |
self->layout_mode = CC_DISPLAY_LAYOUT_MODE_LOGICAL; |
1710 |
|
✗ |
self->logical_monitors = g_hash_table_new (NULL, NULL); |
1711 |
|
✗ |
} |
1712 |
|
|
|
1713 |
|
|
static void |
1714 |
|
✗ |
remove_logical_monitor (gpointer data, |
1715 |
|
|
GObject *object) |
1716 |
|
|
{ |
1717 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (data); |
1718 |
|
|
|
1719 |
|
✗ |
g_hash_table_remove (self->logical_monitors, object); |
1720 |
|
✗ |
} |
1721 |
|
|
|
1722 |
|
|
static void |
1723 |
|
✗ |
register_logical_monitor (CcDisplayConfigDBus *self, |
1724 |
|
|
CcDisplayLogicalMonitor *logical_monitor) |
1725 |
|
|
{ |
1726 |
|
✗ |
g_hash_table_add (self->logical_monitors, logical_monitor); |
1727 |
|
✗ |
g_object_weak_ref (G_OBJECT (logical_monitor), remove_logical_monitor, self); |
1728 |
|
✗ |
g_object_unref (logical_monitor); |
1729 |
|
✗ |
} |
1730 |
|
|
|
1731 |
|
|
static void |
1732 |
|
✗ |
apply_global_scale_requirement (CcDisplayConfigDBus *self, |
1733 |
|
|
CcDisplayMonitor *monitor) |
1734 |
|
|
{ |
1735 |
|
|
GList *l; |
1736 |
|
✗ |
double scale = cc_display_monitor_get_scale (monitor); |
1737 |
|
|
|
1738 |
|
✗ |
for (l = self->monitors; l != NULL; l = l->next) |
1739 |
|
|
{ |
1740 |
|
✗ |
CcDisplayMonitor *m = l->data; |
1741 |
|
✗ |
if (m != monitor) |
1742 |
|
✗ |
cc_display_monitor_set_scale (m, scale); |
1743 |
|
|
} |
1744 |
|
✗ |
} |
1745 |
|
|
|
1746 |
|
|
static void |
1747 |
|
✗ |
construct_monitors (CcDisplayConfigDBus *self, |
1748 |
|
|
GVariantIter *monitors, |
1749 |
|
|
GVariantIter *logical_monitors) |
1750 |
|
|
{ |
1751 |
|
|
while (TRUE) |
1752 |
|
✗ |
{ |
1753 |
|
|
CcDisplayMonitorDBus *monitor; |
1754 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
1755 |
|
|
|
1756 |
|
✗ |
if (!g_variant_iter_next (monitors, "@"MONITOR_FORMAT, &variant)) |
1757 |
|
✗ |
break; |
1758 |
|
|
|
1759 |
|
✗ |
monitor = cc_display_monitor_dbus_new (variant, self); |
1760 |
|
✗ |
self->monitors = g_list_prepend (self->monitors, monitor); |
1761 |
|
|
|
1762 |
|
✗ |
if (self->global_scale_required) |
1763 |
|
✗ |
g_signal_connect_object (monitor, "scale", |
1764 |
|
|
G_CALLBACK (apply_global_scale_requirement), |
1765 |
|
|
self, G_CONNECT_SWAPPED); |
1766 |
|
|
} |
1767 |
|
|
|
1768 |
|
✗ |
self->monitors = g_list_reverse (self->monitors); |
1769 |
|
|
|
1770 |
|
|
while (TRUE) |
1771 |
|
✗ |
{ |
1772 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
1773 |
|
|
CcDisplayLogicalMonitor *logical_monitor; |
1774 |
|
✗ |
g_autoptr(GVariantIter) monitor_specs = NULL; |
1775 |
|
|
const gchar *s1, *s2, *s3, *s4; |
1776 |
|
|
gboolean primary; |
1777 |
|
|
|
1778 |
|
✗ |
if (!g_variant_iter_next (logical_monitors, "@"LOGICAL_MONITOR_FORMAT, &variant)) |
1779 |
|
✗ |
break; |
1780 |
|
|
|
1781 |
|
✗ |
logical_monitor = g_object_new (CC_TYPE_DISPLAY_LOGICAL_MONITOR, NULL); |
1782 |
|
✗ |
g_variant_get (variant, LOGICAL_MONITOR_FORMAT, |
1783 |
|
|
&logical_monitor->x, |
1784 |
|
|
&logical_monitor->y, |
1785 |
|
|
&logical_monitor->scale, |
1786 |
|
|
&logical_monitor->rotation, |
1787 |
|
|
&primary, |
1788 |
|
|
&monitor_specs, |
1789 |
|
|
NULL); |
1790 |
|
|
|
1791 |
|
✗ |
while (g_variant_iter_next (monitor_specs, "(&s&s&s&s)", &s1, &s2, &s3, &s4)) |
1792 |
|
|
{ |
1793 |
|
✗ |
CcDisplayMonitorDBus *m = monitor_from_spec (self, s1, s2, s3, s4); |
1794 |
|
✗ |
if (!m) |
1795 |
|
|
{ |
1796 |
|
✗ |
g_warning ("Couldn't find monitor given spec: %s, %s, %s, %s", |
1797 |
|
|
s1, s2, s3, s4); |
1798 |
|
✗ |
continue; |
1799 |
|
|
} |
1800 |
|
|
|
1801 |
|
✗ |
cc_display_monitor_dbus_set_logical_monitor (m, logical_monitor); |
1802 |
|
|
} |
1803 |
|
|
|
1804 |
|
✗ |
if (g_hash_table_size (logical_monitor->monitors) > 0) |
1805 |
|
|
{ |
1806 |
|
✗ |
if (primary) |
1807 |
|
|
{ |
1808 |
|
✗ |
CcDisplayMonitorDBus *m = NULL; |
1809 |
|
|
GHashTableIter iter; |
1810 |
|
✗ |
g_hash_table_iter_init (&iter, logical_monitor->monitors); |
1811 |
|
✗ |
g_hash_table_iter_next (&iter, (void **) &m, NULL); |
1812 |
|
|
|
1813 |
|
✗ |
cc_display_config_dbus_set_primary (self, m); |
1814 |
|
|
} |
1815 |
|
|
} |
1816 |
|
|
else |
1817 |
|
|
{ |
1818 |
|
✗ |
g_warning ("Got an empty logical monitor, ignoring"); |
1819 |
|
|
} |
1820 |
|
|
|
1821 |
|
✗ |
register_logical_monitor (self, logical_monitor); |
1822 |
|
|
} |
1823 |
|
✗ |
} |
1824 |
|
|
|
1825 |
|
|
static void |
1826 |
|
✗ |
update_panel_orientation_managed (CcDisplayConfigDBus *self) |
1827 |
|
|
{ |
1828 |
|
✗ |
g_autoptr(GVariant) v = NULL; |
1829 |
|
✗ |
gboolean panel_orientation_managed = FALSE; |
1830 |
|
|
|
1831 |
|
✗ |
if (self->proxy != NULL) |
1832 |
|
|
{ |
1833 |
|
✗ |
v = g_dbus_proxy_get_cached_property (self->proxy, "PanelOrientationManaged"); |
1834 |
|
✗ |
if (v) |
1835 |
|
|
{ |
1836 |
|
✗ |
panel_orientation_managed = g_variant_get_boolean (v); |
1837 |
|
|
} |
1838 |
|
|
} |
1839 |
|
|
|
1840 |
|
✗ |
if (panel_orientation_managed == self->panel_orientation_managed) |
1841 |
|
✗ |
return; |
1842 |
|
|
|
1843 |
|
✗ |
self->panel_orientation_managed = panel_orientation_managed; |
1844 |
|
✗ |
g_signal_emit_by_name (self, "panel-orientation-managed", self->panel_orientation_managed); |
1845 |
|
|
} |
1846 |
|
|
|
1847 |
|
|
static void |
1848 |
|
✗ |
proxy_properties_changed_cb (CcDisplayConfigDBus *self, |
1849 |
|
|
GVariant *changed_properties, |
1850 |
|
|
GStrv invalidated_properties) |
1851 |
|
|
{ |
1852 |
|
|
GVariantDict dict; |
1853 |
|
|
|
1854 |
|
✗ |
g_variant_dict_init (&dict, changed_properties); |
1855 |
|
|
|
1856 |
|
✗ |
if (g_variant_dict_contains (&dict, "PanelOrientationManaged")) |
1857 |
|
✗ |
update_panel_orientation_managed (self); |
1858 |
|
✗ |
} |
1859 |
|
|
|
1860 |
|
|
static void |
1861 |
|
✗ |
cc_display_config_dbus_constructed (GObject *object) |
1862 |
|
|
{ |
1863 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object); |
1864 |
|
✗ |
g_autoptr(GVariantIter) monitors = NULL; |
1865 |
|
✗ |
g_autoptr(GVariantIter) logical_monitors = NULL; |
1866 |
|
✗ |
g_autoptr(GVariantIter) props = NULL; |
1867 |
|
✗ |
g_autoptr(GError) error = NULL; |
1868 |
|
|
|
1869 |
|
✗ |
g_variant_get (self->state, |
1870 |
|
|
CURRENT_STATE_FORMAT, |
1871 |
|
|
&self->serial, |
1872 |
|
|
&monitors, |
1873 |
|
|
&logical_monitors, |
1874 |
|
|
&props); |
1875 |
|
|
|
1876 |
|
|
while (TRUE) |
1877 |
|
✗ |
{ |
1878 |
|
|
const char *s; |
1879 |
|
✗ |
g_autoptr(GVariant) v = NULL; |
1880 |
|
|
|
1881 |
|
✗ |
if (!g_variant_iter_next (props, "{&sv}", &s, &v)) |
1882 |
|
✗ |
break; |
1883 |
|
|
|
1884 |
|
✗ |
if (g_str_equal (s, "supports-mirroring")) |
1885 |
|
|
{ |
1886 |
|
✗ |
g_variant_get (v, "b", &self->supports_mirroring); |
1887 |
|
|
} |
1888 |
|
✗ |
else if (g_str_equal (s, "supports-changing-layout-mode")) |
1889 |
|
|
{ |
1890 |
|
✗ |
g_variant_get (v, "b", &self->supports_changing_layout_mode); |
1891 |
|
|
} |
1892 |
|
✗ |
else if (g_str_equal (s, "global-scale-required")) |
1893 |
|
|
{ |
1894 |
|
✗ |
g_variant_get (v, "b", &self->global_scale_required); |
1895 |
|
|
} |
1896 |
|
✗ |
else if (g_str_equal (s, "layout-mode")) |
1897 |
|
|
{ |
1898 |
|
✗ |
guint32 u = 0; |
1899 |
|
✗ |
g_variant_get (v, "u", &u); |
1900 |
|
✗ |
if (u >= CC_DISPLAY_LAYOUT_MODE_LOGICAL && |
1901 |
|
✗ |
u <= CC_DISPLAY_LAYOUT_MODE_PHYSICAL) |
1902 |
|
✗ |
self->layout_mode = u; |
1903 |
|
|
} |
1904 |
|
|
} |
1905 |
|
|
|
1906 |
|
✗ |
construct_monitors (self, monitors, logical_monitors); |
1907 |
|
✗ |
filter_out_invalid_scaled_modes (self); |
1908 |
|
|
|
1909 |
|
✗ |
self->proxy = g_dbus_proxy_new_sync (self->connection, |
1910 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
1911 |
|
|
NULL, |
1912 |
|
|
"org.gnome.Mutter.DisplayConfig", |
1913 |
|
|
"/org/gnome/Mutter/DisplayConfig", |
1914 |
|
|
"org.gnome.Mutter.DisplayConfig", |
1915 |
|
|
NULL, |
1916 |
|
|
&error); |
1917 |
|
✗ |
if (error) |
1918 |
|
✗ |
g_warning ("Could not create DisplayConfig proxy: %s", error->message); |
1919 |
|
|
|
1920 |
|
✗ |
g_signal_connect_swapped (self->proxy, "g-properties-changed", |
1921 |
|
|
G_CALLBACK (proxy_properties_changed_cb), self); |
1922 |
|
✗ |
update_panel_orientation_managed (self); |
1923 |
|
|
|
1924 |
|
✗ |
G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->constructed (object); |
1925 |
|
✗ |
} |
1926 |
|
|
|
1927 |
|
|
static void |
1928 |
|
✗ |
cc_display_config_dbus_set_property (GObject *object, |
1929 |
|
|
guint prop_id, |
1930 |
|
|
const GValue *value, |
1931 |
|
|
GParamSpec *pspec) |
1932 |
|
|
{ |
1933 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object); |
1934 |
|
|
|
1935 |
|
✗ |
switch (prop_id) |
1936 |
|
|
{ |
1937 |
|
✗ |
case PROP_STATE: |
1938 |
|
✗ |
self->state = g_value_dup_variant (value); |
1939 |
|
✗ |
break; |
1940 |
|
✗ |
case PROP_CONNECTION: |
1941 |
|
✗ |
self->connection = g_value_dup_object (value); |
1942 |
|
✗ |
break; |
1943 |
|
✗ |
default: |
1944 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1945 |
|
|
} |
1946 |
|
✗ |
} |
1947 |
|
|
|
1948 |
|
|
static void |
1949 |
|
✗ |
cc_display_config_dbus_get_property (GObject *object, |
1950 |
|
|
guint prop_id, |
1951 |
|
|
GValue *value, |
1952 |
|
|
GParamSpec *pspec) |
1953 |
|
|
{ |
1954 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object); |
1955 |
|
|
|
1956 |
|
✗ |
switch (prop_id) |
1957 |
|
|
{ |
1958 |
|
✗ |
case PROP_STATE: |
1959 |
|
✗ |
g_value_set_variant (value, self->state); |
1960 |
|
✗ |
break; |
1961 |
|
✗ |
case PROP_CONNECTION: |
1962 |
|
✗ |
g_value_set_object (value, self->connection); |
1963 |
|
✗ |
break; |
1964 |
|
✗ |
default: |
1965 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1966 |
|
|
} |
1967 |
|
✗ |
} |
1968 |
|
|
|
1969 |
|
|
static void |
1970 |
|
✗ |
cc_display_config_dbus_dispose (GObject *object) |
1971 |
|
|
{ |
1972 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object); |
1973 |
|
|
|
1974 |
|
✗ |
if (self->logical_monitors) |
1975 |
|
|
{ |
1976 |
|
|
GHashTableIter iter; |
1977 |
|
|
gpointer monitor; |
1978 |
|
|
|
1979 |
|
✗ |
g_hash_table_iter_init (&iter, self->logical_monitors); |
1980 |
|
|
|
1981 |
|
✗ |
while (g_hash_table_iter_next (&iter, &monitor, NULL)) |
1982 |
|
✗ |
g_object_weak_unref (G_OBJECT (monitor), remove_logical_monitor, self); |
1983 |
|
|
} |
1984 |
|
|
|
1985 |
|
✗ |
G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->dispose (object); |
1986 |
|
✗ |
} |
1987 |
|
|
|
1988 |
|
|
static void |
1989 |
|
✗ |
cc_display_config_dbus_finalize (GObject *object) |
1990 |
|
|
{ |
1991 |
|
✗ |
CcDisplayConfigDBus *self = CC_DISPLAY_CONFIG_DBUS (object); |
1992 |
|
|
|
1993 |
|
✗ |
g_clear_pointer (&self->state, g_variant_unref); |
1994 |
|
✗ |
g_clear_object (&self->connection); |
1995 |
|
✗ |
g_clear_object (&self->proxy); |
1996 |
|
|
|
1997 |
|
✗ |
g_clear_list (&self->monitors, g_object_unref); |
1998 |
|
✗ |
g_clear_pointer (&self->logical_monitors, g_hash_table_destroy); |
1999 |
|
|
|
2000 |
|
✗ |
G_OBJECT_CLASS (cc_display_config_dbus_parent_class)->finalize (object); |
2001 |
|
✗ |
} |
2002 |
|
|
|
2003 |
|
|
static void |
2004 |
|
✗ |
cc_display_config_dbus_class_init (CcDisplayConfigDBusClass *klass) |
2005 |
|
|
{ |
2006 |
|
✗ |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
2007 |
|
✗ |
CcDisplayConfigClass *parent_class = CC_DISPLAY_CONFIG_CLASS (klass); |
2008 |
|
|
GParamSpec *pspec; |
2009 |
|
|
|
2010 |
|
✗ |
gobject_class->constructed = cc_display_config_dbus_constructed; |
2011 |
|
✗ |
gobject_class->set_property = cc_display_config_dbus_set_property; |
2012 |
|
✗ |
gobject_class->get_property = cc_display_config_dbus_get_property; |
2013 |
|
✗ |
gobject_class->dispose = cc_display_config_dbus_dispose; |
2014 |
|
✗ |
gobject_class->finalize = cc_display_config_dbus_finalize; |
2015 |
|
|
|
2016 |
|
✗ |
parent_class->get_monitors = cc_display_config_dbus_get_monitors; |
2017 |
|
✗ |
parent_class->is_applicable = cc_display_config_dbus_is_applicable; |
2018 |
|
✗ |
parent_class->equal = cc_display_config_dbus_equal; |
2019 |
|
✗ |
parent_class->apply = cc_display_config_dbus_apply; |
2020 |
|
✗ |
parent_class->is_cloning = cc_display_config_dbus_is_cloning; |
2021 |
|
✗ |
parent_class->set_cloning = cc_display_config_dbus_set_cloning; |
2022 |
|
✗ |
parent_class->generate_cloning_modes = cc_display_config_dbus_generate_cloning_modes; |
2023 |
|
✗ |
parent_class->is_layout_logical = cc_display_config_dbus_is_layout_logical; |
2024 |
|
✗ |
parent_class->is_scaled_mode_valid = cc_display_config_dbus_is_scaled_mode_valid; |
2025 |
|
✗ |
parent_class->set_minimum_size = cc_display_config_dbus_set_minimum_size; |
2026 |
|
✗ |
parent_class->get_panel_orientation_managed = |
2027 |
|
|
cc_display_config_dbus_get_panel_orientation_managed; |
2028 |
|
|
|
2029 |
|
✗ |
pspec = g_param_spec_variant ("state", |
2030 |
|
|
"GVariant", |
2031 |
|
|
"GVariant", |
2032 |
|
|
G_VARIANT_TYPE (CURRENT_STATE_FORMAT), |
2033 |
|
|
NULL, |
2034 |
|
|
G_PARAM_READWRITE | |
2035 |
|
|
G_PARAM_STATIC_STRINGS | |
2036 |
|
|
G_PARAM_CONSTRUCT_ONLY); |
2037 |
|
✗ |
g_object_class_install_property (gobject_class, PROP_STATE, pspec); |
2038 |
|
|
|
2039 |
|
✗ |
pspec = g_param_spec_object ("connection", |
2040 |
|
|
"GDBusConnection", |
2041 |
|
|
"GDBusConnection", |
2042 |
|
|
G_TYPE_DBUS_CONNECTION, |
2043 |
|
|
G_PARAM_READWRITE | |
2044 |
|
|
G_PARAM_STATIC_STRINGS | |
2045 |
|
|
G_PARAM_CONSTRUCT_ONLY); |
2046 |
|
✗ |
g_object_class_install_property (gobject_class, PROP_CONNECTION, pspec); |
2047 |
|
✗ |
} |
2048 |
|
|
|
2049 |
|
|
static gint |
2050 |
|
✗ |
sort_x_axis (gconstpointer a, gconstpointer b) |
2051 |
|
|
{ |
2052 |
|
✗ |
const CcDisplayLogicalMonitor *ma = a; |
2053 |
|
✗ |
const CcDisplayLogicalMonitor *mb = b; |
2054 |
|
✗ |
return ma->x - mb->x; |
2055 |
|
|
} |
2056 |
|
|
|
2057 |
|
|
static gint |
2058 |
|
✗ |
sort_y_axis (gconstpointer a, gconstpointer b) |
2059 |
|
|
{ |
2060 |
|
✗ |
const CcDisplayLogicalMonitor *ma = a; |
2061 |
|
✗ |
const CcDisplayLogicalMonitor *mb = b; |
2062 |
|
✗ |
return ma->y - mb->y; |
2063 |
|
|
} |
2064 |
|
|
|
2065 |
|
|
static void |
2066 |
|
✗ |
add_x_delta (gpointer d1, gpointer d2) |
2067 |
|
|
{ |
2068 |
|
✗ |
CcDisplayLogicalMonitor *m = d1; |
2069 |
|
✗ |
int delta = GPOINTER_TO_INT (d2); |
2070 |
|
✗ |
m->x += delta; |
2071 |
|
✗ |
} |
2072 |
|
|
|
2073 |
|
|
static gboolean |
2074 |
|
✗ |
logical_monitor_is_rotated (CcDisplayLogicalMonitor *lm) |
2075 |
|
|
{ |
2076 |
|
✗ |
switch (lm->rotation) |
2077 |
|
|
{ |
2078 |
|
✗ |
case CC_DISPLAY_ROTATION_90: |
2079 |
|
|
case CC_DISPLAY_ROTATION_270: |
2080 |
|
|
case CC_DISPLAY_ROTATION_90_FLIPPED: |
2081 |
|
|
case CC_DISPLAY_ROTATION_270_FLIPPED: |
2082 |
|
✗ |
return TRUE; |
2083 |
|
✗ |
default: |
2084 |
|
✗ |
return FALSE; |
2085 |
|
|
} |
2086 |
|
|
} |
2087 |
|
|
|
2088 |
|
|
static int |
2089 |
|
✗ |
logical_monitor_width (CcDisplayLogicalMonitor *lm) |
2090 |
|
|
{ |
2091 |
|
|
CcDisplayMonitorDBus *monitor; |
2092 |
|
|
CcDisplayModeDBus *mode; |
2093 |
|
|
GHashTableIter iter; |
2094 |
|
|
int width; |
2095 |
|
|
|
2096 |
|
✗ |
g_hash_table_iter_init (&iter, lm->monitors); |
2097 |
|
✗ |
g_hash_table_iter_next (&iter, (void **) &monitor, NULL); |
2098 |
|
✗ |
mode = CC_DISPLAY_MODE_DBUS (monitor->current_mode); |
2099 |
|
✗ |
if (logical_monitor_is_rotated (lm)) |
2100 |
|
✗ |
width = mode ? mode->height : 0; |
2101 |
|
|
else |
2102 |
|
✗ |
width = mode ? mode->width : 0; |
2103 |
|
|
|
2104 |
|
✗ |
if (monitor->config->layout_mode == CC_DISPLAY_LAYOUT_MODE_LOGICAL) |
2105 |
|
✗ |
return round (width / lm->scale); |
2106 |
|
|
else |
2107 |
|
✗ |
return width; |
2108 |
|
|
} |
2109 |
|
|
|
2110 |
|
|
static void |
2111 |
|
✗ |
add_y_delta (gpointer d1, gpointer d2) |
2112 |
|
|
{ |
2113 |
|
✗ |
CcDisplayLogicalMonitor *m = d1; |
2114 |
|
✗ |
int delta = GPOINTER_TO_INT (d2); |
2115 |
|
✗ |
m->y += delta; |
2116 |
|
✗ |
} |
2117 |
|
|
|
2118 |
|
|
static void |
2119 |
|
✗ |
cc_display_config_dbus_ensure_non_offset_coords (CcDisplayConfigDBus *self) |
2120 |
|
|
{ |
2121 |
|
|
GList *x_axis, *y_axis; |
2122 |
|
|
CcDisplayLogicalMonitor *m; |
2123 |
|
|
|
2124 |
|
✗ |
if (g_hash_table_size (self->logical_monitors) == 0) |
2125 |
|
✗ |
return; |
2126 |
|
|
|
2127 |
|
✗ |
x_axis = g_hash_table_get_keys (self->logical_monitors); |
2128 |
|
✗ |
x_axis = g_list_sort (x_axis, sort_x_axis); |
2129 |
|
✗ |
y_axis = g_hash_table_get_keys (self->logical_monitors); |
2130 |
|
✗ |
y_axis = g_list_sort (y_axis, sort_y_axis); |
2131 |
|
|
|
2132 |
|
✗ |
m = x_axis->data; |
2133 |
|
✗ |
if (m->x != 0) |
2134 |
|
✗ |
g_list_foreach (x_axis, add_x_delta, GINT_TO_POINTER (- m->x)); |
2135 |
|
|
|
2136 |
|
✗ |
m = y_axis->data; |
2137 |
|
✗ |
if (m->y != 0) |
2138 |
|
✗ |
g_list_foreach (y_axis, add_y_delta, GINT_TO_POINTER (- m->y)); |
2139 |
|
|
|
2140 |
|
✗ |
g_list_free (x_axis); |
2141 |
|
✗ |
g_list_free (y_axis); |
2142 |
|
|
} |
2143 |
|
|
|
2144 |
|
|
static void |
2145 |
|
✗ |
cc_display_config_dbus_append_right (CcDisplayConfigDBus *self, |
2146 |
|
|
CcDisplayLogicalMonitor *monitor) |
2147 |
|
|
{ |
2148 |
|
|
GList *x_axis; |
2149 |
|
|
CcDisplayLogicalMonitor *last; |
2150 |
|
|
|
2151 |
|
✗ |
if (g_hash_table_size (self->logical_monitors) == 0) |
2152 |
|
|
{ |
2153 |
|
✗ |
monitor->x = 0; |
2154 |
|
✗ |
monitor->y = 0; |
2155 |
|
✗ |
return; |
2156 |
|
|
} |
2157 |
|
|
|
2158 |
|
✗ |
x_axis = g_hash_table_get_keys (self->logical_monitors); |
2159 |
|
✗ |
x_axis = g_list_sort (x_axis, sort_x_axis); |
2160 |
|
✗ |
last = g_list_last (x_axis)->data; |
2161 |
|
✗ |
monitor->x = last->x + logical_monitor_width (last); |
2162 |
|
✗ |
monitor->y = last->y; |
2163 |
|
|
|
2164 |
|
✗ |
g_list_free (x_axis); |
2165 |
|
|
} |
2166 |
|
|
|
2167 |
|
|
static void |
2168 |
|
✗ |
cc_display_config_dbus_make_linear (CcDisplayConfigDBus *self) |
2169 |
|
|
{ |
2170 |
|
|
CcDisplayLogicalMonitor *primary; |
2171 |
|
|
GList *logical_monitors, *l; |
2172 |
|
|
int x; |
2173 |
|
|
|
2174 |
|
✗ |
if (self->primary && self->primary->logical_monitor) |
2175 |
|
|
{ |
2176 |
|
✗ |
primary = self->primary->logical_monitor; |
2177 |
|
✗ |
primary->x = primary->y = 0; |
2178 |
|
✗ |
x = logical_monitor_width (primary); |
2179 |
|
|
} |
2180 |
|
|
else |
2181 |
|
|
{ |
2182 |
|
✗ |
primary = NULL; |
2183 |
|
✗ |
x = 0; |
2184 |
|
|
} |
2185 |
|
|
|
2186 |
|
✗ |
logical_monitors = g_hash_table_get_keys (self->logical_monitors); |
2187 |
|
✗ |
for (l = logical_monitors; l != NULL; l = l->next) |
2188 |
|
|
{ |
2189 |
|
✗ |
CcDisplayLogicalMonitor *m = l->data; |
2190 |
|
|
|
2191 |
|
✗ |
if (m == primary) |
2192 |
|
✗ |
continue; |
2193 |
|
|
|
2194 |
|
✗ |
m->x = x; |
2195 |
|
✗ |
m->y = 0; |
2196 |
|
✗ |
x += logical_monitor_width (m); |
2197 |
|
|
} |
2198 |
|
|
|
2199 |
|
✗ |
g_list_free (logical_monitors); |
2200 |
|
✗ |
} |
2201 |
|
|
|