Merge lp:~tombeckmann/switchboard-plug-display/mutter-dbus into lp:~elementary-apps/switchboard-plug-display/trunk

Proposed by Tom Beckmann
Status: Work in progress
Proposed branch: lp:~tombeckmann/switchboard-plug-display/mutter-dbus
Merge into: lp:~elementary-apps/switchboard-plug-display/trunk
Diff against target: 969 lines (+886/-7)
6 files modified
src/CMakeLists.txt (+7/-2)
src/Configuration.vala (+14/-5)
src/MutterDisplayConfig.vala (+103/-0)
src/crtc-assignment.c (+677/-0)
src/crtc-assignment.h (+45/-0)
vapi/crtc-assignment.vapi (+40/-0)
To merge this branch: bzr merge lp:~tombeckmann/switchboard-plug-display/mutter-dbus
Reviewer Review Type Date Requested Status
elementary Apps team Pending
Review via email: mp+245371@code.launchpad.net

Description of the change

This branch aims to fix the issue with multimonitors resetting after a gala restart by calling mutter's dbus directly instead of using xrandr via gnome-desktop. This fix won't be necessary once we get a more recent version of libgnome-desktop, however backports aren't planned for this lib for Freya, so this branch would be a requirement for Freya.

To post a comment you must log in.

Unmerged revisions

79. By Tom Beckmann

various fixes, may work now

78. By Tom Beckmann

clean up gnome-desktop file to prevent conflicts, add actual integration

77. By Tom Beckmann

prepare call to mutter dbus for applying

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2014-07-30 00:58:06 +0000
3+++ src/CMakeLists.txt 2014-12-25 21:32:50 +0000
4@@ -18,6 +18,7 @@
5 DisplayPlug.vala
6 DisplayPopover.vala
7 Monitor.vala
8+ MutterDisplayConfig.vala
9 OutputList.vala
10 SettingsDaemon.vala
11 Utils.vala
12@@ -29,13 +30,17 @@
13 clutter-1.0
14 gnome-desktop-3.0
15 gdk-x11-3.0
16+ crtc-assignment
17 OPTIONS
18 --thread
19 --vapidir=${CMAKE_SOURCE_DIR}/vapi
20 )
21
22-add_library (${CMAKE_PROJECT_NAME} MODULE ${VALA_C})
23+include_directories (${CMAKE_SOURCE_DIR}/src)
24+add_definitions (-w -g)
25+
26+add_library (${CMAKE_PROJECT_NAME} MODULE ${VALA_C} crtc-assignment.c)
27 target_link_libraries (${CMAKE_PROJECT_NAME} ${DEPS_LIBRARIES})
28
29 # Installation
30-install (TARGETS ${CMAKE_PROJECT_NAME} DESTINATION ${PKGDATADIR})
31\ No newline at end of file
32+install (TARGETS ${CMAKE_PROJECT_NAME} DESTINATION ${PKGDATADIR})
33
34=== modified file 'src/Configuration.vala'
35--- src/Configuration.vala 2014-07-29 17:45:48 +0000
36+++ src/Configuration.vala 2014-12-25 21:32:50 +0000
37@@ -15,6 +15,8 @@
38 public Gnome.RRScreen screen { get; private set; }
39 public Gnome.RRConfig current_config { get; private set; }
40
41+ MutterWMHelper mutter_wm_helper;
42+
43 SettingsDaemon? settings_daemon = null;
44 private Configuration () {
45 try {
46@@ -24,6 +26,8 @@
47 report_error (e.message);
48 }
49
50+ mutter_wm_helper = new MutterWMHelper ();
51+
52 try {
53 settings_daemon = get_settings_daemon ();
54 } catch (Error e) {
55@@ -68,13 +72,18 @@
56 apply_state_changed (false);
57 current_config.sanitize ();
58 current_config.ensure_primary ();
59+ print ("BLAH BLAH\n");
60
61 #if !HAS_GNOME312
62 try {
63- var other_screen = new Gnome.RRScreen (Gdk.Screen.get_default ());
64- var other_config = new Gnome.RRConfig.current (other_screen);
65- other_config.ensure_primary ();
66- other_config.save ();
67+ if (mutter_wm_helper.supported) {
68+ mutter_wm_helper.apply_config (current_config, screen);
69+ } else {
70+ var other_screen = new Gnome.RRScreen (Gdk.Screen.get_default ());
71+ var other_config = new Gnome.RRConfig.current (other_screen);
72+ other_config.ensure_primary ();
73+ other_config.save ();
74+ }
75 } catch (Error e) {}
76 #endif
77
78@@ -183,4 +192,4 @@
79
80 update_outputs (current_config);
81 }
82-}
83\ No newline at end of file
84+}
85
86=== added file 'src/MutterDisplayConfig.vala'
87--- src/MutterDisplayConfig.vala 1970-01-01 00:00:00 +0000
88+++ src/MutterDisplayConfig.vala 2014-12-25 21:32:50 +0000
89@@ -0,0 +1,103 @@
90+
91+public struct CrtcConfig
92+{
93+ uint id;
94+ int new_mode;
95+ int x;
96+ int y;
97+ uint transform;
98+ uint[] outputs;
99+ HashTable<string, Variant> properties;
100+}
101+
102+public struct OutputConfig
103+{
104+ uint id;
105+ HashTable<string, Variant> properties;
106+}
107+
108+[DBus (name = "org.gnome.Mutter.DisplayConfig")]
109+public interface MutterDisplayConfig : Object
110+{
111+ [DBus (signature = "ua(uxiiiiiuaua{sv})a(uxiausauaua{sv})a(uxuud)ii")]
112+ public abstract Variant get_resources () throws Error;
113+ public abstract void apply_configuration (uint serial, bool persistent, CrtcConfig[] crtcs, OutputConfig[] outputs) throws Error;
114+}
115+
116+public class MutterWMHelper : Object
117+{
118+ public bool supported { get; private set; default = false; }
119+
120+ MutterDisplayConfig mutter_proxy;
121+
122+ public MutterWMHelper ()
123+ {
124+ try {
125+ mutter_proxy = Bus.get_proxy_sync (BusType.SESSION,
126+ "org.pantheon.gala", "/org/gnome/Mutter/DisplayConfig");
127+ } catch (Error e) {
128+ return;
129+ }
130+
131+ supported = mutter_proxy != null;
132+ }
133+
134+ public void apply_config (Gnome.RRConfig config, Gnome.RRScreen screen)
135+ {
136+ CrtcAssignment assignment;
137+ Gnome.RRCrtc crtc;
138+ CrtcInfo info;
139+ CrtcConfig[] crtcs = {};
140+ OutputConfig[] outputs = {};
141+
142+ var mutter_info = mutter_proxy.get_resources ();
143+ var serial = mutter_info.get_uint32 ();
144+
145+ try {
146+ get_crtc_assignment (config, screen, out assignment);
147+ } catch (Error e) {
148+ warning (e.message);
149+ return;
150+ }
151+
152+ if (assignment == null) {
153+ return;
154+ }
155+
156+ var iter = HashTableIter<Gnome.RRCrtc,CrtcInfo?> (assignment.info);
157+ while (iter.next (out crtc, out info)) {
158+ uint[] output_list = {};
159+
160+ for (var i = 0; i < info.outputs.len; i++) {
161+ output_list += ((Gnome.RROutput) info.outputs.index (i)).get_id ();
162+ }
163+
164+ crtcs += CrtcConfig () {
165+ id = crtc.get_id (),
166+ new_mode = info.mode != null ? (int) info.mode.get_id () : -1,
167+ x = info.x,
168+ y = info.y,
169+ transform = rotation_to_transform (info.rotation),
170+ outputs = output_list,
171+ properties = null
172+ };
173+ }
174+
175+ for (var i = 0; assignment.outputs[i] != null; i++) {
176+ var output = assignment.outputs[i];
177+ var rr_output = screen.get_output_by_name (output.get_name ());
178+ var properties = new HashTable<string,Variant> (direct_hash, direct_equal);
179+
180+ properties.@set ("primary", output.get_primary ());
181+ properties.@set ("presentation", false);
182+
183+ outputs += OutputConfig () {
184+ id = rr_output.get_id (),
185+ properties = properties
186+ };
187+ }
188+
189+ mutter_proxy.apply_configuration (serial, true, crtcs, outputs);
190+ }
191+}
192+
193
194=== added file 'src/crtc-assignment.c'
195--- src/crtc-assignment.c 1970-01-01 00:00:00 +0000
196+++ src/crtc-assignment.c 2014-12-25 21:32:50 +0000
197@@ -0,0 +1,677 @@
198+/* gnome-rr-config.c
199+ * -*- c-basic-offset: 4 -*-
200+ *
201+ * Copyright 2007, 2008, 2013 Red Hat, Inc.
202+ * Copyright 2010 Giovanni Campagna <scampa.giovanni@gmail.com>
203+ *
204+ * This file is part of the Gnome Library.
205+ *
206+ * The Gnome Library is free software; you can redistribute it and/or
207+ * modify it under the terms of the GNU Library General Public License as
208+ * published by the Free Software Foundation; either version 2 of the
209+ * License, or (at your option) any later version.
210+ *
211+ * The Gnome Library is distributed in the hope that it will be useful,
212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
213+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
214+ * Library General Public License for more details.
215+ *
216+ * You should have received a copy of the GNU Library General Public
217+ * License along with the Gnome Library; see the file COPYING.LIB. If not,
218+ * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
219+ * Boston, MA 02110-1301, USA.
220+ *
221+ * Author: Soren Sandmann <sandmann@redhat.com>
222+ */
223+
224+#define GNOME_DESKTOP_USE_UNSTABLE_API
225+
226+#include <glib/gi18n-lib.h>
227+#include <stdlib.h>
228+#include <string.h>
229+#include <glib.h>
230+#include <glib/gstdio.h>
231+
232+#include <X11/Xlib.h>
233+#include <gdk/gdkx.h>
234+
235+#include "crtc-assignment.h"
236+
237+//#include "edid.h"
238+
239+#define CONFIG_INTENDED_BASENAME "monitors.xml"
240+#define CONFIG_BACKUP_BASENAME "monitors.xml.backup"
241+
242+/* Look for DPI_FALLBACK in:
243+ * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
244+ * for the reasoning */
245+#define DPI_FALLBACK 96.0
246+
247+/* In version 0 of the config file format, we had several <configuration>
248+ * toplevel elements and no explicit version number. So, the filed looked
249+ * like
250+ *
251+ * <configuration>
252+ * ...
253+ * </configuration>
254+ * <configuration>
255+ * ...
256+ * </configuration>
257+ *
258+ * Since version 1 of the config file, the file has a toplevel <monitors>
259+ * element to group all the configurations. That element has a "version"
260+ * attribute which is an integer. So, the file looks like this:
261+ *
262+ * <monitors version="1">
263+ * <configuration>
264+ * ...
265+ * </configuration>
266+ * <configuration>
267+ * ...
268+ * </configuration>
269+ * </monitors>
270+ */
271+
272+/**
273+ * some things copied from gnome-rr-private.h
274+ *
275+ * copying the entire file didn't seem very useful as it included
276+ * a bunch of things that we don't need
277+ */
278+struct _GnomeRRConfigPrivate
279+{
280+ gboolean clone;
281+ GnomeRRScreen *screen;
282+ GnomeRROutputInfo **outputs;
283+};
284+struct _GnomeRROutputInfoPrivate
285+{
286+ char * name;
287+
288+ gboolean on;
289+ int width;
290+ int height;
291+ int rate;
292+ int x;
293+ int y;
294+ GnomeRRRotation rotation;
295+ GnomeRRRotation available_rotations;
296+
297+ gboolean connected;
298+ char * vendor;
299+ char * product;
300+ char * serial;
301+ double aspect;
302+ int pref_width;
303+ int pref_height;
304+ char * display_name;
305+ gboolean primary;
306+};
307+
308+static gboolean crtc_assignment_apply (CrtcAssignment *assign,
309+ gboolean persistent,
310+ GError **error);
311+static CrtcAssignment *crtc_assignment_new (GnomeRRScreen *screen,
312+ GnomeRROutputInfo **outputs,
313+ GError **error);
314+
315+static GnomeRROutputInfo **
316+make_outputs (GnomeRRConfig *config)
317+{
318+ GPtrArray *outputs;
319+ GnomeRROutputInfo *first_on;
320+ int i;
321+
322+ outputs = g_ptr_array_new ();
323+
324+ first_on = NULL;
325+
326+ for (i = 0; config->priv->outputs[i] != NULL; ++i)
327+ {
328+ GnomeRROutputInfo *old = config->priv->outputs[i];
329+ GnomeRROutputInfo *new = g_object_new (GNOME_TYPE_RR_OUTPUT_INFO, NULL);
330+ *(new->priv) = *(old->priv);
331+ if (old->priv->name)
332+ new->priv->name = g_strdup (old->priv->name);
333+ if (old->priv->display_name)
334+ new->priv->display_name = g_strdup (old->priv->display_name);
335+
336+ if (old->priv->on && !first_on)
337+ first_on = old;
338+
339+ if (config->priv->clone && new->priv->on)
340+ {
341+ g_assert (first_on);
342+
343+ new->priv->width = first_on->priv->width;
344+ new->priv->height = first_on->priv->height;
345+ new->priv->rotation = first_on->priv->rotation;
346+ new->priv->x = 0;
347+ new->priv->y = 0;
348+ }
349+
350+ g_ptr_array_add (outputs, new);
351+ }
352+
353+ g_ptr_array_add (outputs, NULL);
354+
355+ return (GnomeRROutputInfo **)g_ptr_array_free (outputs, FALSE);
356+}
357+
358+gboolean
359+get_crtc_assignment (GnomeRRConfig *config,
360+ GnomeRRScreen *screen,
361+ CrtcAssignment *assignment,
362+ GError **error)
363+{
364+ GnomeRROutputInfo **outputs;
365+ gboolean result = FALSE;
366+ int i;
367+
368+ g_return_val_if_fail (GNOME_IS_RR_CONFIG (config), FALSE);
369+ g_return_val_if_fail (GNOME_IS_RR_SCREEN (screen), FALSE);
370+
371+ outputs = make_outputs (config);
372+
373+ assignment = crtc_assignment_new (screen, outputs, error);
374+
375+ if (assignment)
376+ {
377+ return TRUE;
378+ }
379+
380+ for (i = 0; outputs[i] != NULL; i++)
381+ g_object_unref (outputs[i]);
382+ g_free (outputs);
383+
384+ return FALSE;
385+}
386+
387+
388+/*
389+ * CRTC assignment
390+ */
391+
392+static gboolean
393+can_clone (CrtcInfo *info,
394+ GnomeRROutput *output)
395+{
396+ int i;
397+
398+ for (i = 0; i < info->outputs->len; ++i)
399+ {
400+ GnomeRROutput *clone = info->outputs->pdata[i];
401+
402+ if (!gnome_rr_output_can_clone (clone, output))
403+ return FALSE;
404+ }
405+
406+ return TRUE;
407+}
408+
409+static gboolean
410+crtc_assignment_assign (CrtcAssignment *assign,
411+ GnomeRRCrtc *crtc,
412+ GnomeRRMode *mode,
413+ int x,
414+ int y,
415+ GnomeRRRotation rotation,
416+ gboolean primary,
417+ GnomeRROutput *output,
418+ GError **error)
419+{
420+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
421+ guint32 crtc_id;
422+ const char *output_name;
423+
424+ crtc_id = gnome_rr_crtc_get_id (crtc);
425+ output_name = gnome_rr_output_get_name (output);
426+
427+ if (!gnome_rr_crtc_can_drive_output (crtc, output))
428+ {
429+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
430+ _("CRTC %d cannot drive output %s"), crtc_id, output_name);
431+ return FALSE;
432+ }
433+
434+ if (!gnome_rr_output_supports_mode (output, mode))
435+ {
436+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
437+ _("output %s does not support mode %dx%d@%dHz"),
438+ output_name,
439+ gnome_rr_mode_get_width (mode),
440+ gnome_rr_mode_get_height (mode),
441+ gnome_rr_mode_get_freq (mode));
442+ return FALSE;
443+ }
444+
445+ if (!gnome_rr_crtc_supports_rotation (crtc, rotation))
446+ {
447+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
448+ _("CRTC %d does not support rotation=%d"),
449+ crtc_id, rotation);
450+ return FALSE;
451+ }
452+
453+ if (info)
454+ {
455+ if (!(info->mode == mode &&
456+ info->x == x &&
457+ info->y == y &&
458+ info->rotation == rotation))
459+ {
460+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
461+ _("output %s does not have the same parameters as another cloned output:\n"
462+ "existing mode = %d, new mode = %d\n"
463+ "existing coordinates = (%d, %d), new coordinates = (%d, %d)\n"
464+ "existing rotation = %d, new rotation = %d"),
465+ output_name,
466+ gnome_rr_mode_get_id (info->mode), gnome_rr_mode_get_id (mode),
467+ info->x, info->y,
468+ x, y,
469+ info->rotation, rotation);
470+ return FALSE;
471+ }
472+
473+ if (!can_clone (info, output))
474+ {
475+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
476+ _("cannot clone to output %s"),
477+ output_name);
478+ return FALSE;
479+ }
480+
481+ g_ptr_array_add (info->outputs, output);
482+
483+ if (primary && !assign->primary)
484+ {
485+ assign->primary = output;
486+ }
487+
488+ return TRUE;
489+ }
490+ else
491+ {
492+ CrtcInfo *info = g_new0 (CrtcInfo, 1);
493+
494+ info->mode = mode;
495+ info->x = x;
496+ info->y = y;
497+ info->rotation = rotation;
498+ info->outputs = g_ptr_array_new ();
499+
500+ g_ptr_array_add (info->outputs, output);
501+
502+ g_hash_table_insert (assign->info, crtc, info);
503+
504+ if (primary && !assign->primary)
505+ {
506+ assign->primary = output;
507+ }
508+
509+ return TRUE;
510+ }
511+}
512+
513+static void
514+crtc_assignment_unassign (CrtcAssignment *assign,
515+ GnomeRRCrtc *crtc,
516+ GnomeRROutput *output)
517+{
518+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
519+
520+ if (info)
521+ {
522+ g_ptr_array_remove (info->outputs, output);
523+
524+ if (assign->primary == output)
525+ {
526+ assign->primary = NULL;
527+ }
528+
529+ if (info->outputs->len == 0)
530+ g_hash_table_remove (assign->info, crtc);
531+ }
532+}
533+
534+void
535+crtc_assignment_free (CrtcAssignment *assign)
536+{
537+ if (!assign)
538+ return;
539+
540+ if (assign->info)
541+ g_hash_table_destroy (assign->info);
542+
543+ g_free (assign);
544+}
545+
546+static gboolean
547+mode_is_rotated (CrtcInfo *info)
548+{
549+ if ((info->rotation & GNOME_RR_ROTATION_270) ||
550+ (info->rotation & GNOME_RR_ROTATION_90))
551+ {
552+ return TRUE;
553+ }
554+ return FALSE;
555+}
556+
557+static void
558+accumulate_error (GString *accumulated_error, GError *error)
559+{
560+ g_string_append_printf (accumulated_error, " %s\n", error->message);
561+ g_error_free (error);
562+}
563+
564+/* Check whether the given set of settings can be used
565+ * at the same time -- ie. whether there is an assignment
566+ * of CRTC's to outputs.
567+ *
568+ * Brute force - the number of objects involved is small
569+ * enough that it doesn't matter.
570+ */
571+static gboolean
572+real_assign_crtcs (GnomeRRScreen *screen,
573+ GnomeRROutputInfo **outputs,
574+ CrtcAssignment *assignment,
575+ GError **error)
576+{
577+ GnomeRRCrtc **crtcs = gnome_rr_screen_list_crtcs (screen);
578+ GnomeRROutputInfo *output;
579+ int i;
580+ gboolean tried_mode;
581+ GError *my_error;
582+ GString *accumulated_error;
583+ gboolean success;
584+
585+ output = *outputs;
586+ if (!output)
587+ return TRUE;
588+
589+ /* It is always allowed for an output to be turned off */
590+ if (!output->priv->on)
591+ {
592+ return real_assign_crtcs (screen, outputs + 1, assignment, error);
593+ }
594+
595+ success = FALSE;
596+ tried_mode = FALSE;
597+ accumulated_error = g_string_new (NULL);
598+
599+ for (i = 0; crtcs[i] != NULL; ++i)
600+ {
601+ GnomeRRCrtc *crtc = crtcs[i];
602+ int crtc_id = gnome_rr_crtc_get_id (crtc);
603+ int pass;
604+
605+ g_string_append_printf (accumulated_error,
606+ _("Trying modes for CRTC %d\n"),
607+ crtc_id);
608+
609+ /* Make two passes, one where frequencies must match, then
610+ * one where they don't have to
611+ */
612+ for (pass = 0; pass < 2; ++pass)
613+ {
614+ GnomeRROutput *gnome_rr_output = gnome_rr_screen_get_output_by_name (screen, output->priv->name);
615+ GnomeRRMode **modes = gnome_rr_output_list_modes (gnome_rr_output);
616+ int j;
617+
618+ for (j = 0; modes[j] != NULL; ++j)
619+ {
620+ GnomeRRMode *mode = modes[j];
621+ int mode_width;
622+ int mode_height;
623+ int mode_freq;
624+
625+ mode_width = gnome_rr_mode_get_width (mode);
626+ mode_height = gnome_rr_mode_get_height (mode);
627+ mode_freq = gnome_rr_mode_get_freq (mode);
628+
629+ g_string_append_printf (accumulated_error,
630+ _("CRTC %d: trying mode %dx%d@%dHz with output at %dx%d@%dHz (pass %d)\n"),
631+ crtc_id,
632+ mode_width, mode_height, mode_freq,
633+ output->priv->width, output->priv->height, output->priv->rate,
634+ pass);
635+
636+ if (mode_width == output->priv->width &&
637+ mode_height == output->priv->height &&
638+ (pass == 1 || mode_freq == output->priv->rate))
639+ {
640+ tried_mode = TRUE;
641+
642+ my_error = NULL;
643+ if (crtc_assignment_assign (
644+ assignment, crtc, modes[j],
645+ output->priv->x, output->priv->y,
646+ output->priv->rotation,
647+ output->priv->primary,
648+ gnome_rr_output,
649+ &my_error))
650+ {
651+ my_error = NULL;
652+ if (real_assign_crtcs (screen, outputs + 1, assignment, &my_error)) {
653+ success = TRUE;
654+ goto out;
655+ } else
656+ accumulate_error (accumulated_error, my_error);
657+
658+ crtc_assignment_unassign (assignment, crtc, gnome_rr_output);
659+ } else
660+ accumulate_error (accumulated_error, my_error);
661+ }
662+ }
663+ }
664+ }
665+
666+out:
667+
668+ if (success)
669+ g_string_free (accumulated_error, TRUE);
670+ else {
671+ char *str;
672+
673+ str = g_string_free (accumulated_error, FALSE);
674+
675+ if (tried_mode)
676+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
677+ _("could not assign CRTCs to outputs:\n%s"),
678+ str);
679+ else
680+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_CRTC_ASSIGNMENT,
681+ _("none of the selected modes were compatible with the possible modes:\n%s"),
682+ str);
683+
684+ g_free (str);
685+ }
686+
687+ return success;
688+}
689+
690+void
691+crtc_info_free (CrtcInfo *info)
692+{
693+ g_ptr_array_free (info->outputs, TRUE);
694+ g_free (info);
695+}
696+
697+static void
698+get_required_virtual_size (CrtcAssignment *assign, int *width, int *height)
699+{
700+ GList *active_crtcs = g_hash_table_get_keys (assign->info);
701+ GList *list;
702+ int d;
703+
704+ if (!width)
705+ width = &d;
706+ if (!height)
707+ height = &d;
708+
709+ /* Compute size of the screen */
710+ *width = *height = 1;
711+ for (list = active_crtcs; list != NULL; list = list->next)
712+ {
713+ GnomeRRCrtc *crtc = list->data;
714+ CrtcInfo *info = g_hash_table_lookup (assign->info, crtc);
715+ int w, h;
716+
717+ w = gnome_rr_mode_get_width (info->mode);
718+ h = gnome_rr_mode_get_height (info->mode);
719+
720+ if (mode_is_rotated (info))
721+ {
722+ int tmp = h;
723+ h = w;
724+ w = tmp;
725+ }
726+
727+ *width = MAX (*width, info->x + w);
728+ *height = MAX (*height, info->y + h);
729+ }
730+
731+ g_list_free (active_crtcs);
732+}
733+
734+static CrtcAssignment *
735+crtc_assignment_new (GnomeRRScreen *screen,
736+ GnomeRROutputInfo **outputs,
737+ GError **error)
738+{
739+ CrtcAssignment *assignment = g_new0 (CrtcAssignment, 1);
740+
741+ assignment->outputs = outputs;
742+ assignment->info = g_hash_table_new_full (
743+ g_direct_hash, g_direct_equal, NULL, (GFreeFunc)crtc_info_free);
744+
745+ if (real_assign_crtcs (screen, outputs, assignment, error))
746+ {
747+ int width, height;
748+ int min_width, max_width, min_height, max_height;
749+
750+ get_required_virtual_size (assignment, &width, &height);
751+
752+ gnome_rr_screen_get_ranges (
753+ screen, &min_width, &max_width, &min_height, &max_height);
754+
755+ if (width < min_width || width > max_width ||
756+ height < min_height || height > max_height)
757+ {
758+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
759+ /* Translators: the "requested", "minimum", and
760+ * "maximum" words here are not keywords; please
761+ * translate them as usual. */
762+ _("required virtual size does not fit available size: "
763+ "requested=(%d, %d), minimum=(%d, %d), maximum=(%d, %d)"),
764+ width, height,
765+ min_width, min_height,
766+ max_width, max_height);
767+ goto fail;
768+ }
769+
770+ assignment->screen = screen;
771+
772+ return assignment;
773+ }
774+
775+fail:
776+ crtc_assignment_free (assignment);
777+
778+ return NULL;
779+}
780+
781+#define ROTATION_MASK 0x7F
782+
783+wl_output_transform
784+rotation_to_transform (GnomeRRRotation rotation)
785+{
786+ static const wl_output_transform y_reflected_map[] = {
787+ WL_OUTPUT_TRANSFORM_FLIPPED_180,
788+ WL_OUTPUT_TRANSFORM_FLIPPED_90,
789+ WL_OUTPUT_TRANSFORM_FLIPPED,
790+ WL_OUTPUT_TRANSFORM_FLIPPED_270
791+ };
792+ wl_output_transform ret;
793+
794+ switch (rotation & ROTATION_MASK)
795+ {
796+ default:
797+ case GNOME_RR_ROTATION_0:
798+ ret = WL_OUTPUT_TRANSFORM_NORMAL;
799+ break;
800+ case GNOME_RR_ROTATION_90:
801+ ret = WL_OUTPUT_TRANSFORM_90;
802+ break;
803+ case GNOME_RR_ROTATION_180:
804+ ret = WL_OUTPUT_TRANSFORM_180;
805+ break;
806+ case GNOME_RR_ROTATION_270:
807+ ret = WL_OUTPUT_TRANSFORM_270;
808+ break;
809+ }
810+
811+ if (rotation & GNOME_RR_REFLECT_X)
812+ return ret + 4;
813+ else if (rotation & GNOME_RR_REFLECT_Y)
814+ return y_reflected_map[ret];
815+ else
816+ return ret;
817+}
818+
819+/*
820+static gboolean
821+crtc_assignment_apply (CrtcAssignment *assign, gboolean persistent, GError **error)
822+{
823+ GVariantBuilder crtc_builder, output_builder, nested_outputs;
824+ GHashTableIter iter;
825+ GnomeRRCrtc *crtc;
826+ CrtcInfo *info;
827+ unsigned i;
828+
829+ g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uiiiuaua{sv})"));
830+ g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(ua{sv})"));
831+
832+ g_hash_table_iter_init (&iter, assign->info);
833+ while (g_hash_table_iter_next (&iter, (void*) &crtc, (void*) &info))
834+ {
835+ g_variant_builder_init (&nested_outputs, G_VARIANT_TYPE ("au"));
836+ for (i = 0; i < info->outputs->len; i++)
837+ {
838+ GnomeRROutput *output = g_ptr_array_index (info->outputs, i);
839+
840+ g_variant_builder_add (&nested_outputs, "u",
841+ gnome_rr_output_get_id (output));
842+ }
843+
844+ g_variant_builder_add (&crtc_builder, "(uiiiuaua{sv})",
845+ gnome_rr_crtc_get_id (crtc),
846+ info->mode ?
847+ gnome_rr_mode_get_id (info->mode) : -1,
848+ info->x,
849+ info->y,
850+ rotation_to_transform (info->rotation),
851+ &nested_outputs,
852+ NULL);
853+ }
854+
855+ for (i = 0; assign->outputs[i]; i++)
856+ {
857+ GnomeRROutputInfo *output = assign->outputs[i];
858+ GnomeRROutput *gnome_rr_output = gnome_rr_screen_get_output_by_name (assign->screen,
859+ output->priv->name);
860+
861+ g_variant_builder_add (&output_builder, "(u@a{sv})",
862+ gnome_rr_output_get_id (gnome_rr_output),
863+ g_variant_new_parsed ("{ 'primary': <%b>,"
864+ " 'presentation': <%b> }",
865+ output->priv->primary,
866+ FALSE));
867+ }
868+
869+ return _gnome_rr_screen_apply_configuration (assign->screen,
870+ persistent,
871+ g_variant_builder_end (&crtc_builder),
872+ g_variant_builder_end (&output_builder),
873+ error);
874+}*/
875
876=== added file 'src/crtc-assignment.h'
877--- src/crtc-assignment.h 1970-01-01 00:00:00 +0000
878+++ src/crtc-assignment.h 2014-12-25 21:32:50 +0000
879@@ -0,0 +1,45 @@
880+#include <gnome-desktop-3.0/libgnome-desktop/gnome-rr.h>
881+#include <gnome-desktop-3.0/libgnome-desktop/gnome-rr-config.h>
882+
883+typedef struct CrtcAssignment CrtcAssignment;
884+
885+struct CrtcAssignment
886+{
887+ GnomeRROutputInfo **outputs;
888+ GnomeRRScreen *screen;
889+ GHashTable *info;
890+ GnomeRROutput *primary;
891+};
892+
893+typedef struct CrtcInfo CrtcInfo;
894+
895+struct CrtcInfo
896+{
897+ GnomeRRMode *mode;
898+ int x;
899+ int y;
900+ GnomeRRRotation rotation;
901+ GPtrArray *outputs;
902+};
903+
904+#ifdef GDK_WINDOWING_WAYLAND
905+#include <gdk/gdkwayland.h>
906+#else
907+enum wl_output_transform {
908+ WL_OUTPUT_TRANSFORM_NORMAL,
909+ WL_OUTPUT_TRANSFORM_90,
910+ WL_OUTPUT_TRANSFORM_180,
911+ WL_OUTPUT_TRANSFORM_270,
912+ WL_OUTPUT_TRANSFORM_FLIPPED,
913+ WL_OUTPUT_TRANSFORM_FLIPPED_90,
914+ WL_OUTPUT_TRANSFORM_FLIPPED_180,
915+ WL_OUTPUT_TRANSFORM_FLIPPED_270
916+};
917+#endif
918+
919+typedef enum wl_output_transform wl_output_transform;
920+
921+void crtc_assignment_free (CrtcAssignment *assign);
922+void crtc_info_free (CrtcInfo *info);
923+
924+gboolean get_crtc_assignment (GnomeRRConfig *config, GnomeRRScreen *screen, CrtcAssignment *assignment, GError **error);
925
926=== added file 'vapi/crtc-assignment.vapi'
927--- vapi/crtc-assignment.vapi 1970-01-01 00:00:00 +0000
928+++ vapi/crtc-assignment.vapi 2014-12-25 21:32:50 +0000
929@@ -0,0 +1,40 @@
930+
931+[CCode (cheader_filename = "crtc-assignment.h")]
932+public class CrtcAssignment
933+{
934+ [CCode (array_null_terminated = true)]
935+ public Gnome.RROutputInfo[] outputs;
936+ public Gnome.RRScreen screen;
937+ public GLib.HashTable<Gnome.RRCrtc,CrtcInfo?> info;
938+ public Gnome.RROutput primary;
939+}
940+
941+[CCode (cheader_filename = "crtc-assignment.h", has_destroy_function = "false")]
942+public struct CrtcInfo
943+{
944+ Gnome.RRMode mode;
945+ int x;
946+ int y;
947+ Gnome.RRRotation rotation;
948+ GLib.PtrArray outputs;
949+}
950+
951+[CCode (cheader_filename = "crtc-assignment.h")]
952+public enum wl_output_transform {
953+ WL_OUTPUT_TRANSFORM_NORMAL,
954+ WL_OUTPUT_TRANSFORM_90,
955+ WL_OUTPUT_TRANSFORM_180,
956+ WL_OUTPUT_TRANSFORM_270,
957+ WL_OUTPUT_TRANSFORM_FLIPPED,
958+ WL_OUTPUT_TRANSFORM_FLIPPED_90,
959+ WL_OUTPUT_TRANSFORM_FLIPPED_180,
960+ WL_OUTPUT_TRANSFORM_FLIPPED_270
961+}
962+
963+[CCode (cheader_filename = "crtc-assignment.h")]
964+public bool get_crtc_assignment (Gnome.RRConfig config,
965+ Gnome.RRScreen screen, out CrtcAssignment assignment) throws GLib.Error;
966+
967+[CCode (cheader_filename = "crtc-assignment.h")]
968+public wl_output_transform rotation_to_transform (Gnome.RRRotation rotation);
969+

Subscribers

People subscribed via source and target branches

to all changes: