[Xfce4-commits] <xfce4-settings:master> Refactor XfceDisplaysHelper to listen to screen changes
Simon Steinbeiss
noreply at xfce.org
Wed Nov 7 19:50:02 CET 2012
Updating branch refs/heads/master
to 7ef545b96688fd5797a3d422e50fa7be7c676af5 (commit)
from cb8ab60dc89ab61ef62fd85b4f11c11026e79794 (commit)
commit 7ef545b96688fd5797a3d422e50fa7be7c676af5
Author: Lionel Le Folgoc <lionel at lefolgoc.net>
Date: Tue Nov 6 22:58:51 2012 +0100
Refactor XfceDisplaysHelper to listen to screen changes
This will enable it to take some actions depending on the context, e.g.
re-enable LVDS1 when VGA1 is disconnected, etc (to do for later).
Signed-off-by: Simon Steinbeiss <simon.steinbeiss at elfenbeinturm.at>
xfsettingsd/displays.c | 1190 +++++++++++++++++++++++++++---------------------
1 files changed, 675 insertions(+), 515 deletions(-)
diff --git a/xfsettingsd/displays.c b/xfsettingsd/displays.c
index af6e6cd..597e0d9 100644
--- a/xfsettingsd/displays.c
+++ b/xfsettingsd/displays.c
@@ -47,12 +47,44 @@
-static void xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
- const gchar *scheme);
-static void xfce_displays_helper_channel_property_changed (XfconfChannel *channel,
- const gchar *property_name,
- const GValue *value,
- XfceDisplaysHelper *helper);
+/* wrappers to avoid querying too often */
+typedef struct _XfceRRCrtc XfceRRCrtc;
+
+
+
+static void xfce_displays_helper_dispose (GObject *object);
+static void xfce_displays_helper_finalize (GObject *object);
+static void xfce_displays_helper_reload (XfceDisplaysHelper *helper);
+static GdkFilterReturn xfce_displays_helper_screen_on_event (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data);
+static void xfce_displays_helper_set_screen_size (XfceDisplaysHelper *helper);
+static gboolean xfce_displays_helper_load_from_xfconf (XfceDisplaysHelper *helper,
+ const gchar *scheme,
+ GHashTable *saved_outputs,
+ RROutput output);
+static GPtrArray *xfce_displays_helper_list_crtcs (XfceDisplaysHelper *helper);
+static XfceRRCrtc *xfce_displays_helper_find_crtc_by_id (XfceDisplaysHelper *helper,
+ RRCrtc id);
+static void xfce_displays_helper_free_crtc (XfceRRCrtc *crtc);
+static XfceRRCrtc *xfce_displays_helper_find_usable_crtc (XfceDisplaysHelper *helper,
+ RROutput output);
+static void xfce_displays_helper_normalize_crtc (XfceRRCrtc *crtc,
+ XfceDisplaysHelper *helper);
+static Status xfce_displays_helper_disable_crtc (XfceDisplaysHelper *helper,
+ RRCrtc crtc);
+static void xfce_displays_helper_workaround_crtc_size (XfceRRCrtc *crtc,
+ XfceDisplaysHelper *helper);
+static void xfce_displays_helper_apply_crtc (XfceRRCrtc *crtc,
+ XfceDisplaysHelper *helper);
+static void xfce_displays_helper_set_outputs (XfceRRCrtc *crtc,
+ RROutput output);
+static void xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
+ const gchar *scheme);
+static void xfce_displays_helper_channel_property_changed (XfconfChannel *channel,
+ const gchar *property_name,
+ const GValue *value,
+ XfceDisplaysHelper *helper);
@@ -66,16 +98,33 @@ struct _XfceDisplaysHelper
GObject __parent__;
/* xfconf channel */
- XfconfChannel *channel;
+ XfconfChannel *channel;
+ guint handler;
#ifdef HAS_RANDR_ONE_POINT_THREE
- gint has_1_3;
+ gint has_1_3;
+ gint primary;
#endif
-};
-/* wrappers to avoid querying too often */
-typedef struct _XfceRRCrtc XfceRRCrtc;
-typedef struct _XfceRROutput XfceRROutput;
+ GdkDisplay *display;
+ GdkWindow *root_window;
+ Display *xdisplay;
+ gint event_base;
+
+ /* RandR cache */
+ XRRScreenResources *resources;
+ GPtrArray *crtcs;
+
+ /* screen size */
+ gint width;
+ gint height;
+ gint mm_width;
+ gint mm_height;
+
+ /* used to normalize positions */
+ gint min_x;
+ gint min_y;
+};
struct _XfceRRCrtc
{
@@ -94,12 +143,6 @@ struct _XfceRRCrtc
gint changed;
};
-struct _XfceRROutput
-{
- RROutput id;
- XRROutputInfo *info;
-};
-
G_DEFINE_TYPE (XfceDisplaysHelper, xfce_displays_helper, G_TYPE_OBJECT);
@@ -109,7 +152,10 @@ G_DEFINE_TYPE (XfceDisplaysHelper, xfce_displays_helper, G_TYPE_OBJECT);
static void
xfce_displays_helper_class_init (XfceDisplaysHelperClass *klass)
{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->dispose = xfce_displays_helper_dispose;
+ gobject_class->finalize = xfce_displays_helper_finalize;
}
@@ -118,15 +164,51 @@ static void
xfce_displays_helper_init (XfceDisplaysHelper *helper)
{
gint major = 0, minor = 0;
- gint event_base, error_base;
+ gint error_base, err;
+
+ helper->resources = NULL;
+ helper->crtcs = NULL;
+ helper->handler = 0;
+
+ /* get the default display */
+ helper->display = gdk_display_get_default ();
+ helper->xdisplay = gdk_x11_display_get_xdisplay (helper->display);
+ helper->root_window = gdk_get_default_root_window ();
/* check if the randr extension is running */
- if (XRRQueryExtension (GDK_DISPLAY (), &event_base, &error_base))
+ if (XRRQueryExtension (helper->xdisplay, &helper->event_base, &error_base))
{
/* query the version */
- if (XRRQueryVersion (GDK_DISPLAY (), &major, &minor)
+ if (XRRQueryVersion (helper->xdisplay, &major, &minor)
&& (major > 1 || (major == 1 && minor >= 2)))
{
+ gdk_error_trap_push ();
+ /* get the screen resource */
+ helper->resources = XRRGetScreenResources (helper->xdisplay,
+ GDK_WINDOW_XID (helper->root_window));
+ gdk_flush ();
+ err = gdk_error_trap_pop ();
+ if (err)
+ {
+ g_critical ("XRRGetScreenResources failed (err: %d). "
+ "Display settings won't be applied.", err);
+ return;
+ }
+
+ /* get all existing CRTCs */
+ helper->crtcs = xfce_displays_helper_list_crtcs (helper);
+
+ /* Set up RandR notifications */
+ XRRSelectInput (helper->xdisplay,
+ GDK_WINDOW_XID (helper->root_window),
+ RRScreenChangeNotifyMask);
+ gdk_x11_register_standard_event_type (helper->display,
+ helper->event_base,
+ RRNotify + 1);
+ gdk_window_add_filter (helper->root_window,
+ xfce_displays_helper_screen_on_event,
+ helper);
+
/* open the channel */
helper->channel = xfconf_channel_get ("displays");
@@ -134,8 +216,10 @@ xfce_displays_helper_init (XfceDisplaysHelper *helper)
xfconf_channel_reset_property (helper->channel, "/Schemes/Apply", FALSE);
/* monitor channel changes */
- g_signal_connect (G_OBJECT (helper->channel), "property-changed",
- G_CALLBACK (xfce_displays_helper_channel_property_changed), helper);
+ helper->handler = g_signal_connect (G_OBJECT (helper->channel),
+ "property-changed",
+ G_CALLBACK (xfce_displays_helper_channel_property_changed),
+ helper);
#ifdef HAS_RANDR_ONE_POINT_THREE
helper->has_1_3 = (major > 1 || (major == 1 && minor >= 3));
@@ -153,209 +237,537 @@ xfce_displays_helper_init (XfceDisplaysHelper *helper)
else
{
g_critical ("No RANDR extension found in display %s. Display settings won't be applied.",
- gdk_display_get_name (gdk_display_get_default ()));
+ gdk_display_get_name (helper->display));
}
}
static void
-xfce_displays_helper_process_screen_size (gint mode_width,
- gint mode_height,
- gint crtc_pos_x,
- gint crtc_pos_y,
- gint *width,
- gint *height,
- gint *mm_width,
- gint *mm_height)
+xfce_displays_helper_dispose (GObject *object)
{
- g_assert (width && height && mm_width && mm_height);
+ XfceDisplaysHelper *helper = XFCE_DISPLAYS_HELPER (object);
- *width = MAX (*width, crtc_pos_x + mode_width);
- *height = MAX (*height, crtc_pos_y + mode_height);
+ if (helper->handler > 0)
+ {
+ g_signal_handler_disconnect (G_OBJECT (helper->channel),
+ helper->handler);
+ helper->handler = 0;
+ }
- /* The 'physical size' of an X screen is meaningless if that screen
- * can consist of many monitors. So just pick a size that make the
- * dpi 96.
- *
- * Firefox and Evince apparently believe what X tells them.
- */
- *mm_width = (*width / 96.0) * 25.4 + 0.5;
- *mm_height = (*height / 96.0) * 25.4 + 0.5;
+ gdk_window_remove_filter (helper->root_window,
+ xfce_displays_helper_screen_on_event,
+ helper);
+
+ (*G_OBJECT_CLASS (xfce_displays_helper_parent_class)->dispose) (object);
}
-static XfceRRCrtc *
-xfce_displays_helper_list_crtcs (Display *xdisplay,
- XRRScreenResources *resources)
+static void
+xfce_displays_helper_finalize (GObject *object)
{
- XfceRRCrtc *crtcs;
- XRRCrtcInfo *crtc_info;
- gint n;
+ XfceDisplaysHelper *helper = XFCE_DISPLAYS_HELPER (object);
- g_assert (xdisplay && resources);
+ /* Free the CRTC cache */
+ if (helper->crtcs)
+ {
+ g_ptr_array_free (helper->crtcs, TRUE);
+ helper->crtcs = NULL;
+ }
- /* get all existing CRTCs */
- crtcs = g_new0 (XfceRRCrtc, resources->ncrtc);
- for (n = 0; n < resources->ncrtc; ++n)
- {
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Detected CRTC %lu.", resources->crtcs[n]);
-
- crtcs[n].id = resources->crtcs[n];
- crtc_info = XRRGetCrtcInfo (xdisplay, resources, resources->crtcs[n]);
- crtcs[n].mode = crtc_info->mode;
- crtcs[n].rotation = crtc_info->rotation;
- crtcs[n].rotations = crtc_info->rotations;
- crtcs[n].width = crtc_info->width;
- crtcs[n].height = crtc_info->height;
- crtcs[n].x = crtc_info->x;
- crtcs[n].y = crtc_info->y;
-
- crtcs[n].noutput = crtc_info->noutput;
- crtcs[n].outputs = NULL;
- if (crtc_info->noutput > 0)
- crtcs[n].outputs = g_memdup (crtc_info->outputs,
- crtc_info->noutput * sizeof (RROutput));
+ /* Free the screen resources */
+ if (helper->resources)
+ {
+ gdk_error_trap_push ();
+ XRRFreeScreenResources (helper->resources);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+ helper->resources = NULL;
+ }
- crtcs[n].npossible = crtc_info->npossible;
- crtcs[n].possible = NULL;
- if (crtc_info->npossible > 0)
- crtcs[n].possible = g_memdup (crtc_info->possible,
- crtc_info->npossible * sizeof (RROutput));
+ (*G_OBJECT_CLASS (xfce_displays_helper_parent_class)->finalize) (object);
+}
- crtcs[n].changed = FALSE;
- XRRFreeCrtcInfo (crtc_info);
- }
- return crtcs;
+
+static void
+xfce_displays_helper_reload (XfceDisplaysHelper *helper)
+{
+ gint err;
+
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Refreshing RandR cache.");
+
+ /* Free the CRTC cache */
+ g_ptr_array_free (helper->crtcs, TRUE);
+
+ gdk_error_trap_push ();
+
+ /* Free the screen resources */
+ XRRFreeScreenResources (helper->resources);
+
+ /* get the screen resource */
+#ifdef HAS_RANDR_ONE_POINT_THREE
+ /* xfce_displays_helper_reload () is usually called after a xrandr notification,
+ which means that X is aware of the new hardware already. So, if possible,
+ do not reprobe the hardware again. */
+ if (helper->has_1_3)
+ helper->resources = XRRGetScreenResourcesCurrent (helper->xdisplay,
+ GDK_WINDOW_XID (helper->root_window));
+ else
+#endif
+ helper->resources = XRRGetScreenResources (helper->xdisplay,
+ GDK_WINDOW_XID (helper->root_window));
+
+ gdk_flush ();
+ err = gdk_error_trap_pop ();
+ if (err)
+ g_critical ("Failed to reload the RandR cache (err: %d).", err);
+
+ /* get all existing CRTCs */
+ helper->crtcs = xfce_displays_helper_list_crtcs (helper);
}
-static XfceRRCrtc *
-xfce_displays_helper_find_crtc_by_id (XRRScreenResources *resources,
- XfceRRCrtc *crtcs,
- RRCrtc id)
+static GdkFilterReturn
+xfce_displays_helper_screen_on_event (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
{
- gint n;
+ XfceDisplaysHelper *helper = XFCE_DISPLAYS_HELPER (data);
+ XEvent *e = xevent;
+ gint event_num;
+
+ if (!e)
+ return GDK_FILTER_CONTINUE;
- g_assert (resources && crtcs);
+ event_num = e->type - helper->event_base;
- for (n = 0; n < resources->ncrtc; ++n)
+ if (event_num == RRScreenChangeNotify)
{
- if (crtcs[n].id == id)
- return &crtcs[n];
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "RRScreenChangeNotify event received.");
+
+ xfce_displays_helper_reload (helper);
+
+ /*TODO: check that there is still one output enabled */
+ /*TODO: e.g. reenable LVDS1 when VGA1 is diconnected. */
+ /*TODO: also, disable LVDS1 when the lid is closed (needs upower though :/) */
}
- return NULL;
+ /* Pass the event on to GTK+ */
+ return GDK_FILTER_CONTINUE;
}
static void
-xfce_displays_helper_cleanup_crtc (XfceRRCrtc *crtc)
+xfce_displays_helper_set_screen_size (XfceDisplaysHelper *helper)
{
- if (crtc == NULL)
+ gint min_width, min_height, max_width, max_height;
+
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->xdisplay && helper->resources);
+
+ /* get the screen size extremums */
+ if (!XRRGetScreenSizeRange (helper->xdisplay, GDK_WINDOW_XID (helper->root_window),
+ &min_width, &min_height, &max_width, &max_height))
+ {
+ g_warning ("Unable to get the range of screen sizes. "
+ "Display settings may fail to apply.");
return;
+ }
- if (crtc->outputs != NULL)
- g_free (crtc->outputs);
- if (crtc->possible != NULL)
- g_free (crtc->possible);
+ /* set the screen size only if it's really needed and valid */
+ if (helper->width >= min_width && helper->width <= max_width
+ && helper->height >= min_height && helper->height <= max_height
+ && (helper->width != gdk_screen_width ()
+ || helper->height != gdk_screen_height ()
+ || helper->mm_width != gdk_screen_width_mm ()
+ || helper->mm_height != gdk_screen_height_mm ()))
+ {
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Applying desktop dimensions: %dx%d (px), %dx%d (mm).",
+ helper->width, helper->height, helper->mm_width, helper->mm_height);
+ XRRSetScreenSize (helper->xdisplay, GDK_WINDOW_XID (helper->root_window),
+ helper->width, helper->height, helper->mm_width, helper->mm_height);
+ }
}
-static void
-xfce_displays_helper_free_output (XfceRROutput *output)
+static gboolean
+xfce_displays_helper_load_from_xfconf (XfceDisplaysHelper *helper,
+ const gchar *scheme,
+ GHashTable *saved_outputs,
+ RROutput output)
{
- if (output == NULL)
- return;
+ XfceRRCrtc *crtc = NULL;
+ XRROutputInfo *info;
+ GValue *value;
+ const gchar *str_value;
+ gchar property[512];
+ gdouble output_rate, rate;
+ RRMode valid_mode;
+ Rotation rot;
+ gint x, y, n, m, int_value, err;
+ gboolean active = FALSE;
- XRRFreeOutputInfo (output->info);
- g_free (output);
+ gdk_error_trap_push ();
+ info = XRRGetOutputInfo (helper->xdisplay, helper->resources, output);
+ gdk_flush ();
+ err = gdk_error_trap_pop ();
+ if (err || !info)
+ {
+ g_warning ("Failed to load info for output %lu (err: %d). Skipping.",
+ output, err);
+ return FALSE;
+ }
+
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Detected output %lu %s.", output,
+ info->name);
+
+ /* ignore disconnected outputs */
+ if (info->connection != RR_Connected)
+ goto next_output;
+
+ /* Get the associated CRTC */
+ if (info->crtc != None)
+ crtc = xfce_displays_helper_find_crtc_by_id (helper, info->crtc);
+
+ /* track active outputs */
+ if (crtc && crtc->mode != None)
+ {
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "%s is active.", info->name);
+ active = TRUE;
+ }
+
+ /* does this output exist in xfconf? */
+ g_snprintf (property, sizeof (property), "/%s/%s", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+
+ if (value == NULL || !G_VALUE_HOLDS_STRING (value))
+ goto next_output;
+
+#ifdef HAS_RANDR_ONE_POINT_THREE
+ if (helper->has_1_3)
+ {
+ /* is it the primary output? */
+ g_snprintf (property, sizeof (property), "/%s/%s/Primary", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (G_VALUE_HOLDS_BOOLEAN (value) && g_value_get_boolean (value))
+ helper->primary = output;
+ }
+#endif
+
+ /* status */
+ g_snprintf (property, sizeof (property), "/%s/%s/Active", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+
+ if (value == NULL || !G_VALUE_HOLDS_BOOLEAN (value))
+ goto next_output;
+
+ /* No existing CRTC, try to find a free one */
+ if (info->crtc == None)
+ crtc = xfce_displays_helper_find_usable_crtc (helper, output);
+
+ if (!crtc)
+ {
+ g_warning ("No available CRTC for %s, aborting.", info->name);
+ goto next_output;
+ }
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "CRTC %lu assigned to %s.", crtc->id, info->name);
+
+ /* disable inactive outputs */
+ if (!g_value_get_boolean (value))
+ {
+ if (crtc->mode != None)
+ {
+ active = FALSE;
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "%s will be disabled by configuration.", info->name);
+
+ crtc->mode = None;
+ crtc->noutput = 0;
+ crtc->changed = TRUE;
+ }
+
+ goto next_output;
+ }
+
+ /* rotation */
+ g_snprintf (property, sizeof (property), "/%s/%s/Rotation", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (G_VALUE_HOLDS_INT (value))
+ int_value = g_value_get_int (value);
+ else
+ int_value = 0;
+
+ /* convert to a Rotation */
+ switch (int_value)
+ {
+ case 90: rot = RR_Rotate_90; break;
+ case 180: rot = RR_Rotate_180; break;
+ case 270: rot = RR_Rotate_270; break;
+ default: rot = RR_Rotate_0; break;
+ }
+
+ /* reflection */
+ g_snprintf (property, sizeof (property), "/%s/%s/Reflection", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (G_VALUE_HOLDS_STRING (value))
+ str_value = g_value_get_string (value);
+ else
+ str_value = "0";
+
+ /* convert to a Rotation */
+ if (g_strcmp0 (str_value, "X") == 0)
+ rot |= RR_Reflect_X;
+ else if (g_strcmp0 (str_value, "Y") == 0)
+ rot |= RR_Reflect_Y;
+ else if (g_strcmp0 (str_value, "XY") == 0)
+ rot |= (RR_Reflect_X|RR_Reflect_Y);
+
+ /* check rotation support */
+ if ((crtc->rotations & rot) == 0)
+ {
+ g_warning ("Unsupported rotation for %s. Fallback to RR_Rotate_0.", info->name);
+ rot = RR_Rotate_0;
+ }
+
+ /* update CRTC rotation */
+ if (crtc->rotation != rot)
+ {
+ crtc->rotation = rot;
+ crtc->changed = TRUE;
+ }
+
+ /* resolution */
+ g_snprintf (property, sizeof (property), "/%s/%s/Resolution", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (value == NULL || !G_VALUE_HOLDS_STRING (value))
+ str_value = "";
+ else
+ str_value = g_value_get_string (value);
+
+ /* refresh rate */
+ g_snprintf (property, sizeof (property), "/%s/%s/RefreshRate", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (G_VALUE_HOLDS_DOUBLE (value))
+ output_rate = g_value_get_double (value);
+ else
+ output_rate = 0.0;
+
+ /* check mode validity */
+ valid_mode = None;
+ for (n = 0; n < info->nmode; ++n)
+ {
+ /* walk all modes */
+ for (m = 0; m < helper->resources->nmode; ++m)
+ {
+ /* does the mode info match the mode we seek? */
+ if (helper->resources->modes[m].id != info->modes[n])
+ continue;
+
+ /* calculate the refresh rate */
+ rate = (gdouble) helper->resources->modes[m].dotClock /
+ ((gdouble) helper->resources->modes[m].hTotal * (gdouble) helper->resources->modes[m].vTotal);
+
+ /* find the mode corresponding to the saved values */
+ if (rint (rate) == rint (output_rate)
+ && (g_strcmp0 (helper->resources->modes[m].name, str_value) == 0))
+ {
+ valid_mode = helper->resources->modes[m].id;
+ break;
+ }
+ }
+ /* found it */
+ if (valid_mode != None)
+ break;
+ }
+
+ if (valid_mode == None)
+ {
+ /* unsupported mode, abort for this output */
+ g_warning ("Unknown mode '%s @ %.1f' for output %s, aborting.",
+ str_value, output_rate, info->name);
+ goto next_output;
+ }
+ else if (crtc->mode != valid_mode)
+ {
+ if (crtc->mode == None)
+ active = TRUE;
+
+ /* update CRTC mode */
+ crtc->mode = valid_mode;
+ crtc->changed = TRUE;
+ }
+
+ /* recompute dimensions according to the selected rotation */
+ if ((crtc->rotation & (RR_Rotate_90|RR_Rotate_270)) != 0)
+ {
+ crtc->width = helper->resources->modes[m].height;
+ crtc->height = helper->resources->modes[m].width;
+ }
+ else
+ {
+ crtc->width = helper->resources->modes[m].width;
+ crtc->height = helper->resources->modes[m].height;
+ }
+
+ /* position, x */
+ g_snprintf (property, sizeof (property), "/%s/%s/Position/X", scheme, info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (G_VALUE_HOLDS_INT (value))
+ x = g_value_get_int (value);
+ else
+ x = 0;
+
+ /* position, y */
+ g_snprintf (property, sizeof (property), "/%s/%s/Position/Y", scheme,
+ info->name);
+ value = g_hash_table_lookup (saved_outputs, property);
+ if (G_VALUE_HOLDS_INT (value))
+ y = g_value_get_int (value);
+ else
+ y = 0;
+
+ /* update CRTC position */
+ if (crtc->x != x || crtc->y != y)
+ {
+ crtc->x = x;
+ crtc->y = y;
+ crtc->changed = TRUE;
+ }
+
+ /* used to normalize positions later */
+ helper->min_x = MIN (helper->min_x, crtc->x);
+ helper->min_y = MIN (helper->min_y, crtc->y);
+
+ xfce_displays_helper_set_outputs (crtc, output);
+
+next_output:
+ XRRFreeOutputInfo (info);
+ return active;
}
static GPtrArray *
-xfce_displays_helper_list_outputs (Display *xdisplay,
- XRRScreenResources *resources,
- XfceRRCrtc *crtcs,
- gint *nactive)
+xfce_displays_helper_list_crtcs (XfceDisplaysHelper *helper)
{
- GPtrArray *outputs;
- XRROutputInfo *info;
- XfceRROutput *output;
- XfceRRCrtc *crtc;
- gint n;
-
- g_assert (xdisplay && resources && nactive);
+ GPtrArray *crtcs;
+ XRRCrtcInfo *crtc_info;
+ XfceRRCrtc *crtc;
+ gint n, err;
- outputs = g_ptr_array_new ();
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->xdisplay && helper->resources);
- /* get all connected outputs */
- *nactive = 0;
- for (n = 0; n < resources->noutput; ++n)
+ /* get all existing CRTCs */
+ crtcs = g_ptr_array_new_with_free_func ((GDestroyNotify) xfce_displays_helper_free_crtc);
+ for (n = 0; n < helper->resources->ncrtc; ++n)
{
- info = XRRGetOutputInfo (xdisplay, resources, resources->outputs[n]);
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Detected CRTC %lu.", helper->resources->crtcs[n]);
- if (info->connection != RR_Connected)
+ gdk_error_trap_push ();
+ crtc_info = XRRGetCrtcInfo (helper->xdisplay, helper->resources, helper->resources->crtcs[n]);
+ gdk_flush ();
+ err = gdk_error_trap_pop ();
+ if (err || !crtc_info)
{
- XRRFreeOutputInfo (info);
+ g_warning ("Failed to load info for CRTC %lu (err: %d). Skipping.",
+ helper->resources->crtcs[n], err);
continue;
}
- output = g_new0 (XfceRROutput, 1);
- output->id = resources->outputs[n];
- output->info = info;
+ crtc = g_new0 (XfceRRCrtc, 1);
+ crtc->id = helper->resources->crtcs[n];
+ crtc->mode = crtc_info->mode;
+ crtc->rotation = crtc_info->rotation;
+ crtc->rotations = crtc_info->rotations;
+ crtc->width = crtc_info->width;
+ crtc->height = crtc_info->height;
+ crtc->x = crtc_info->x;
+ crtc->y = crtc_info->y;
+
+ crtc->noutput = crtc_info->noutput;
+ crtc->outputs = NULL;
+ if (crtc_info->noutput > 0)
+ crtc->outputs = g_memdup (crtc_info->outputs,
+ crtc_info->noutput * sizeof (RROutput));
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Detected output %lu %s.", output->id,
- output->info->name);
+ crtc->npossible = crtc_info->npossible;
+ crtc->possible = NULL;
+ if (crtc_info->npossible > 0)
+ crtc->possible = g_memdup (crtc_info->possible,
+ crtc_info->npossible * sizeof (RROutput));
- /* track active outputs */
- crtc = xfce_displays_helper_find_crtc_by_id (resources, crtcs,
- output->info->crtc);
- if (crtc && crtc->mode != None)
- {
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "%s is active.", output->info->name);
- ++(*nactive);
- }
+ crtc->changed = FALSE;
+ XRRFreeCrtcInfo (crtc_info);
/* cache it */
- g_ptr_array_add (outputs, output);
+ g_ptr_array_add (crtcs, crtc);
}
- return outputs;
+ return crtcs;
}
static XfceRRCrtc *
-xfce_displays_helper_find_usable_crtc (XRRScreenResources *resources,
- XfceRRCrtc *crtcs,
- XfceRROutput *output)
+xfce_displays_helper_find_crtc_by_id (XfceDisplaysHelper *helper,
+ RRCrtc id)
+{
+ XfceRRCrtc *crtc;
+ guint n;
+
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->crtcs);
+
+ for (n = 0; n < helper->crtcs->len; ++n)
+ {
+ crtc = g_ptr_array_index (helper->crtcs, n);
+ if (crtc->id == id)
+ return crtc;
+ }
+
+ return NULL;
+}
+
+
+
+static void
+xfce_displays_helper_free_crtc (XfceRRCrtc *crtc)
{
- gint m, n;
+ if (crtc == NULL)
+ return;
+
+ if (crtc->outputs != NULL)
+ g_free (crtc->outputs);
+ if (crtc->possible != NULL)
+ g_free (crtc->possible);
+ g_free (crtc);
+}
- g_assert (resources && crtcs && output);
- /* if there is one already assigned, return it */
- if (output->info->crtc != None)
- return xfce_displays_helper_find_crtc_by_id (resources, crtcs,
- output->info->crtc);
+
+static XfceRRCrtc *
+xfce_displays_helper_find_usable_crtc (XfceDisplaysHelper *helper,
+ RROutput output)
+{
+ XfceRRCrtc *crtc;
+ guint n;
+ gint m;
+
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->crtcs);
/* try to find one that is not already used by another output */
- for (n = 0; n < resources->ncrtc; ++n)
+ for (n = 0; n < helper->crtcs->len; ++n)
{
- if (crtcs[n].noutput > 0 || crtcs[n].changed)
+ crtc = g_ptr_array_index (helper->crtcs, n);
+ if (crtc->noutput > 0 || crtc->changed)
continue;
- for (m = 0; m < crtcs[n].npossible; ++m)
+ for (m = 0; m < crtc->npossible; ++m)
{
- if (crtcs[n].possible[m] == output->id)
- return &crtcs[n];
+ if (crtc->possible[m] == output)
+ return crtc;
}
}
@@ -365,43 +777,110 @@ xfce_displays_helper_find_usable_crtc (XRRScreenResources *resources,
+static void
+xfce_displays_helper_normalize_crtc (XfceRRCrtc *crtc,
+ XfceDisplaysHelper *helper)
+{
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && crtc);
+
+ /* ignore disabled outputs for size computations */
+ if (crtc->mode == None)
+ return;
+
+ /* normalize positions to ensure the upper left corner is at (0,0) */
+ if (helper->min_x || helper->min_y)
+ {
+ crtc->x -= helper->min_x;
+ crtc->y -= helper->min_y;
+ crtc->changed = TRUE;
+ }
+
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Normalized CRTC %lu: size=%dx%d, pos=%dx%d.",
+ crtc->id, crtc->width, crtc->height, crtc->x, crtc->y);
+
+ /* calculate the total screen size */
+ helper->width = MAX (helper->width, crtc->x + crtc->width);
+ helper->height = MAX (helper->height, crtc->y + crtc->height);
+
+ /* The 'physical size' of an X screen is meaningless if that screen
+ * can consist of many monitors. So just pick a size that make the
+ * dpi 96.
+ *
+ * Firefox and Evince apparently believe what X tells them.
+ */
+ helper->mm_width = (helper->width / 96.0) * 25.4 + 0.5;
+ helper->mm_height = (helper->height / 96.0) * 25.4 + 0.5;
+}
+
+
+
static Status
-xfce_displays_helper_disable_crtc (Display *xdisplay,
- XRRScreenResources *resources,
+xfce_displays_helper_disable_crtc (XfceDisplaysHelper *helper,
RRCrtc crtc)
{
- g_assert (xdisplay && resources);
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->xdisplay && helper->resources);
xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Disabling CRTC %lu.", crtc);
- return XRRSetCrtcConfig (xdisplay, resources, crtc, CurrentTime,
- 0, 0, None, RR_Rotate_0, NULL, 0);
+ return XRRSetCrtcConfig (helper->xdisplay, helper->resources, crtc,
+ CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0);
}
-static Status
-xfce_displays_helper_apply_crtc (Display *xdisplay,
- XRRScreenResources *resources,
- XfceRRCrtc *crtc)
+static void
+xfce_displays_helper_workaround_crtc_size (XfceRRCrtc *crtc,
+ XfceDisplaysHelper *helper)
+{
+ XRRCrtcInfo *crtc_info;
+
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->xdisplay && helper->resources && crtc);
+
+ /* The CRTC needs to be disabled if its previous mode won't fit in the new screen.
+ It will be reenabled with its new mode (known to fit) after the screen size is
+ changed, unless the user disabled it (no need to reenable it then). */
+ crtc_info = XRRGetCrtcInfo (helper->xdisplay, helper->resources, crtc->id);
+ if ((crtc_info->x + crtc_info->width > (guint) helper->width) ||
+ (crtc_info->y + crtc_info->height > (guint) helper->height))
+ {
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "CRTC %lu must be temporarily disabled.", crtc->id);
+ if (xfce_displays_helper_disable_crtc (helper, crtc->id) == RRSetConfigSuccess)
+ crtc->changed = (crtc->mode != None);
+ else
+ g_warning ("Failed to temporarily disable CRTC %lu.", crtc->id);
+ }
+ XRRFreeCrtcInfo (crtc_info);
+}
+
+
+
+static void
+xfce_displays_helper_apply_crtc (XfceRRCrtc *crtc,
+ XfceDisplaysHelper *helper)
{
Status ret;
- g_assert (xdisplay && resources && crtc);
+ g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->xdisplay && helper->resources && crtc);
xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Configuring CRTC %lu.", crtc->id);
- if (crtc->mode == None)
- ret = xfce_displays_helper_disable_crtc (xdisplay, resources, crtc->id);
- else
- ret = XRRSetCrtcConfig (xdisplay, resources, crtc->id, CurrentTime,
- crtc->x, crtc->y, crtc->mode, crtc->rotation,
- crtc->outputs, crtc->noutput);
+ /* check if we really need to do something */
+ if (crtc->changed)
+ {
+ xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Applying changes to CRTC %lu.", crtc->id);
- if (ret == RRSetConfigSuccess)
- crtc->changed = FALSE;
+ if (crtc->mode == None)
+ ret = xfce_displays_helper_disable_crtc (helper, crtc->id);
+ else
+ ret = XRRSetCrtcConfig (helper->xdisplay, helper->resources, crtc->id,
+ CurrentTime, crtc->x, crtc->y, crtc->mode,
+ crtc->rotation, crtc->outputs, crtc->noutput);
- return ret;
+ if (ret == RRSetConfigSuccess)
+ crtc->changed = FALSE;
+ else
+ g_warning ("Failed to configure CRTC %lu.", crtc->id);
+ }
}
@@ -446,58 +925,16 @@ static void
xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
const gchar *scheme)
{
- GdkDisplay *display;
- Display *xdisplay;
- GdkWindow *root_window;
- XRRScreenResources *resources;
- XRRCrtcInfo *crtc_info;
- XfceRRCrtc *crtcs, *crtc;
- gchar property[512];
- gint min_width, min_height, max_width, max_height;
- gint mm_width, mm_height, width, height;
- gint x, y, min_x, min_y;
- gint l, m, int_value, nactive;
- guint n;
- GValue *value;
- const gchar *str_value;
- gdouble output_rate, rate;
- RRMode valid_mode;
- Rotation rot;
- GPtrArray *connected_outputs;
- GHashTable *saved_outputs;
- XfceRROutput *output;
-#ifdef HAS_RANDR_ONE_POINT_THREE
- RROutput primary = None;
-#endif
-
- gdk_error_trap_push ();
+ gchar property[512];
+ gint n, nactive;
+ GHashTable *saved_outputs;
saved_outputs = NULL;
-
- /* get the default display */
- display = gdk_display_get_default ();
- xdisplay = gdk_x11_display_get_xdisplay (display);
- root_window = gdk_get_default_root_window ();
-
- /* get the screen resource */
- resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XID (root_window));
-
- /* get the range of screen sizes */
- mm_width = mm_height = width = height = 0;
- min_x = min_y = 32768;
- if (!XRRGetScreenSizeRange (xdisplay, GDK_WINDOW_XID (root_window),
- &min_width, &min_height, &max_width, &max_height))
- {
- g_critical ("Unable to get the range of screen sizes, aborting.");
- goto err_abort;
- }
-
- /* get all existing CRTCs */
- crtcs = xfce_displays_helper_list_crtcs (xdisplay, resources);
-
- /* then all connected outputs */
- connected_outputs = xfce_displays_helper_list_outputs (xdisplay, resources,
- crtcs, &nactive);
+ helper->mm_width = helper->mm_height = helper->width = helper->height = 0;
+ helper->min_x = helper->min_y = 32768;
+#ifdef HAS_RANDR_ONE_POINT_THREE
+ helper->primary = None;
+#endif
/* finally the list of saved outputs from xfconf */
g_snprintf (property, sizeof (property), "/%s", scheme);
@@ -508,221 +945,12 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
goto err_cleanup;
/* first loop, loads all the outputs, and gets the number of active ones */
- for (n = 0; n < connected_outputs->len; ++n)
+ nactive = 0;
+ for (n = 0; n < helper->resources->noutput; ++n)
{
- output = g_ptr_array_index (connected_outputs, n);
-
- /* does this output exist in xfconf? */
- g_snprintf (property, sizeof (property), "/%s/%s", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
-
- if (value == NULL || !G_VALUE_HOLDS_STRING (value))
- continue;
-
-#ifdef HAS_RANDR_ONE_POINT_THREE
- if (helper->has_1_3)
- {
- /* is it the primary output? */
- g_snprintf (property, sizeof (property), "/%s/%s/Primary", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (G_VALUE_HOLDS_BOOLEAN (value) && g_value_get_boolean (value))
- primary = output->id;
- }
-#endif
-
- /* status */
- g_snprintf (property, sizeof (property), "/%s/%s/Active", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
-
- if (value == NULL || !G_VALUE_HOLDS_BOOLEAN (value))
- continue;
-
- /* Pick a CRTC for this output */
- crtc = xfce_displays_helper_find_usable_crtc (resources, crtcs, output);
- if (!crtc)
- {
- g_warning ("No available CRTC for %s, aborting.", output->info->name);
- continue;
- }
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "CRTC %lu assigned to %s.", crtc->id,
- output->info->name);
-
- /* disable inactive outputs */
- if (!g_value_get_boolean (value))
- {
- if (crtc->mode != None)
- {
- --nactive;
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "%s will be disabled by configuration.",
- output->info->name);
-
- crtc->mode = None;
- crtc->noutput = 0;
- crtc->changed = TRUE;
- }
-
- continue;
- }
-
- /* rotation */
- g_snprintf (property, sizeof (property), "/%s/%s/Rotation", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (G_VALUE_HOLDS_INT (value))
- int_value = g_value_get_int (value);
- else
- int_value = 0;
-
- /* convert to a Rotation */
- switch (int_value)
- {
- case 90: rot = RR_Rotate_90; break;
- case 180: rot = RR_Rotate_180; break;
- case 270: rot = RR_Rotate_270; break;
- default: rot = RR_Rotate_0; break;
- }
-
- /* reflection */
- g_snprintf (property, sizeof (property), "/%s/%s/Reflection", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (G_VALUE_HOLDS_STRING (value))
- str_value = g_value_get_string (value);
- else
- str_value = "0";
-
- /* convert to a Rotation */
- if (g_strcmp0 (str_value, "X") == 0)
- rot |= RR_Reflect_X;
- else if (g_strcmp0 (str_value, "Y") == 0)
- rot |= RR_Reflect_Y;
- else if (g_strcmp0 (str_value, "XY") == 0)
- rot |= (RR_Reflect_X|RR_Reflect_Y);
-
- /* check rotation support */
- if ((crtc->rotations & rot) == 0)
- {
- g_warning ("Unsupported rotation for %s. Fallback to RR_Rotate_0.",
- output->info->name);
- rot = RR_Rotate_0;
- }
-
- /* update CRTC rotation */
- if (crtc->rotation != rot)
- {
- crtc->rotation = rot;
- crtc->changed = TRUE;
- }
-
- /* resolution */
- g_snprintf (property, sizeof (property), "/%s/%s/Resolution",
- scheme, output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (value == NULL || !G_VALUE_HOLDS_STRING (value))
- str_value = "";
- else
- str_value = g_value_get_string (value);
-
- /* refresh rate */
- g_snprintf (property, sizeof (property), "/%s/%s/RefreshRate", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (G_VALUE_HOLDS_DOUBLE (value))
- output_rate = g_value_get_double (value);
- else
- output_rate = 0.0;
-
- /* check mode validity */
- valid_mode = None;
- for (m = 0; m < output->info->nmode; ++m)
- {
- /* walk all modes */
- for (l = 0; l < resources->nmode; ++l)
- {
- /* does the mode info match the mode we seek? */
- if (resources->modes[l].id != output->info->modes[m])
- continue;
-
- /* calculate the refresh rate */
- rate = (gdouble) resources->modes[l].dotClock /
- ((gdouble) resources->modes[l].hTotal * (gdouble) resources->modes[l].vTotal);
-
- /* find the mode corresponding to the saved values */
- if (rint (rate) == rint (output_rate)
- && (g_strcmp0 (resources->modes[l].name, str_value) == 0))
- {
- valid_mode = resources->modes[l].id;
- break;
- }
- }
- /* found it */
- if (valid_mode != None)
- break;
- }
-
- if (valid_mode == None)
- {
- /* unsupported mode, abort for this output */
- g_warning ("Unknown mode '%s @ %.1f' for output %s, aborting.",
- str_value, output_rate, output->info->name);
- continue;
- }
- else if (crtc->mode != valid_mode)
- {
- if (crtc->mode == None)
- ++nactive;
-
- /* update CRTC mode */
- crtc->mode = valid_mode;
- crtc->changed = TRUE;
- }
-
- /* recompute dimensions according to the selected rotation */
- if ((crtc->rotation & (RR_Rotate_90|RR_Rotate_270)) != 0)
- {
- crtc->width = resources->modes[l].height;
- crtc->height = resources->modes[l].width;
- }
- else
- {
- crtc->width = resources->modes[l].width;
- crtc->height = resources->modes[l].height;
- }
-
- /* position, x */
- g_snprintf (property, sizeof (property), "/%s/%s/Position/X", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (G_VALUE_HOLDS_INT (value))
- x = g_value_get_int (value);
- else
- x = 0;
-
- /* position, y */
- g_snprintf (property, sizeof (property), "/%s/%s/Position/Y", scheme,
- output->info->name);
- value = g_hash_table_lookup (saved_outputs, property);
- if (G_VALUE_HOLDS_INT (value))
- y = g_value_get_int (value);
- else
- y = 0;
-
- /* update CRTC position */
- if (crtc->x != x || crtc->y != y)
- {
- crtc->x = x;
- crtc->y = y;
- crtc->changed = TRUE;
- }
-
- /* used to normalize positions later */
- min_x = MIN (min_x, crtc->x);
- min_y = MIN (min_y, crtc->y);
-
- xfce_displays_helper_set_outputs (crtc, output->id);
+ if (xfce_displays_helper_load_from_xfconf (helper, scheme, saved_outputs,
+ helper->resources->outputs[n]))
+ ++nactive;
}
xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Total %d active output(s).", nactive);
@@ -734,109 +962,41 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
goto err_cleanup;
}
- /* grab server to prevent clients from thinking no output is enabled */
- gdk_x11_display_grab (display);
-
/* second loop, normalization and screen size calculation */
- for (m = 0; m < resources->ncrtc; ++m)
- {
- /* ignore disabled outputs for size computations */
- if (crtcs[m].mode == None)
- continue;
+ g_ptr_array_foreach (helper->crtcs, (GFunc) xfce_displays_helper_normalize_crtc, helper);
- /* normalize positions to ensure the upper left corner is at (0,0) */
- if (min_x || min_y)
- {
- crtcs[m].x -= min_x;
- crtcs[m].y -= min_y;
- crtcs[m].changed = TRUE;
- }
-
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Normalized CRTC %lu: size=%dx%d, pos=%dx%d.",
- crtcs[m].id, crtcs[m].width, crtcs[m].height, crtcs[m].x, crtcs[m].y);
+ gdk_error_trap_push ();
- /* calculate the total screen size */
- xfce_displays_helper_process_screen_size (crtcs[m].width, crtcs[m].height,
- crtcs[m].x, crtcs[m].y, &width,
- &height, &mm_width, &mm_height);
- }
+ /* grab server to prevent clients from thinking no output is enabled */
+ gdk_x11_display_grab (helper->display);
/* disable CRTCs that won't fit in the new screen */
- for (m = 0; m < resources->ncrtc; ++m)
- {
- /* The CRTC needs to be disabled if its previous mode won't fit in the new screen.
- It will be reenabled with its new mode (known to fit) after the screen size is
- changed, unless the user disabled it (no need to reenable it then). */
- crtc_info = XRRGetCrtcInfo (xdisplay, resources, crtcs[m].id);
- if ((crtc_info->x + crtc_info->width > (guint) width) ||
- (crtc_info->y + crtc_info->height > (guint) height))
- {
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "CRTC %lu must be temporarily disabled.", crtcs[m].id);
- if (xfce_displays_helper_disable_crtc (xdisplay, resources, crtcs[m].id) == RRSetConfigSuccess)
- crtcs[m].changed = (crtcs[m].mode != None);
- else
- g_warning ("Failed to temporarily disable CRTC %lu.", crtc->id);
- }
- XRRFreeCrtcInfo (crtc_info);
- }
+ g_ptr_array_foreach (helper->crtcs, (GFunc) xfce_displays_helper_workaround_crtc_size, helper);
/* set the screen size only if it's really needed and valid */
- if (width >= min_width && width <= max_width
- && height >= min_height && height <= max_height
- && (width != gdk_screen_width ()
- || height != gdk_screen_height ()
- || mm_width != gdk_screen_width_mm ()
- || mm_height != gdk_screen_height_mm ()))
- {
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Applying desktop dimensions: %dx%d (px), %dx%d (mm).",
- width, height, mm_width, mm_height);
- XRRSetScreenSize (xdisplay, GDK_WINDOW_XID (root_window),
- width, height, mm_width, mm_height);
- }
+ xfce_displays_helper_set_screen_size (helper);
/* final loop, apply crtc changes */
- for (m = 0; m < resources->ncrtc; ++m)
- {
- /* check if we really need to do something */
- if (crtcs[m].changed)
- {
- xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Applying changes to CRTC %lu.", crtcs[m].id);
-
- if (xfce_displays_helper_apply_crtc (xdisplay, resources, &crtcs[m]) != RRSetConfigSuccess)
- g_warning ("Failed to configure CRTC %lu.", crtcs[m].id);
- }
- }
+ g_ptr_array_foreach (helper->crtcs, (GFunc) xfce_displays_helper_apply_crtc, helper);
#ifdef HAS_RANDR_ONE_POINT_THREE
if (helper->has_1_3)
- XRRSetOutputPrimary (xdisplay, GDK_WINDOW_XID (root_window), primary);
+ XRRSetOutputPrimary (helper->xdisplay, GDK_WINDOW_XID (helper->root_window),
+ helper->primary);
#endif
/* release the grab, changes are done */
- gdk_x11_display_ungrab (display);
+ gdk_x11_display_ungrab (helper->display);
+ gdk_flush ();
+ gdk_error_trap_pop ();
+
+ /* refresh the cache (better safe than sorry) */
+ xfce_displays_helper_reload (helper);
err_cleanup:
/* Free the xfconf properties */
if (saved_outputs)
g_hash_table_destroy (saved_outputs);
-
- /* Free our output cache */
- g_ptr_array_foreach (connected_outputs, (GFunc) xfce_displays_helper_free_output, NULL);
- g_ptr_array_free (connected_outputs, TRUE);
-
- /* cleanup our CRTC cache */
- for (m = 0; m < resources->ncrtc; ++m)
- {
- xfce_displays_helper_cleanup_crtc (&crtcs[m]);
- }
- g_free (crtcs);
-
-err_abort:
- /* free the screen resources */
- XRRFreeScreenResources (resources);
-
- gdk_flush ();
- gdk_error_trap_pop ();
}
More information about the Xfce4-commits
mailing list