Updating branch refs/heads/bluesabre/display-settings to 4eaeaf0726dd89d9e3fd66fff37e7aaa117260c2 (commit) from 8beeb1f9177a1fc454aa37ba251e2d5ff484963f (commit)
commit 4eaeaf0726dd89d9e3fd66fff37e7aaa117260c2 Author: Lionel Le Folgoc <lio...@lefolgoc.net> Date: Wed Nov 7 19:29:42 2012 +0100 Enable/Disable internal output on lid changed events Signed-off-by: Simon Steinbeiss <simon.steinbe...@elfenbeinturm.at> xfsettingsd/displays.c | 269 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 233 insertions(+), 36 deletions(-) diff --git a/xfsettingsd/displays.c b/xfsettingsd/displays.c index 597e0d9..7238f2c 100644 --- a/xfsettingsd/displays.c +++ b/xfsettingsd/displays.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2008 Nick Schermer <n...@xfce.org> - * Copyright (C) 2010 Lionel Le Folgoc <lio...@lefolgoc.net> + * Copyright (C) 2010-2012 Lionel Le Folgoc <lio...@lefolgoc.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,9 @@ #include "debug.h" #include "displays.h" +#ifdef HAVE_UPOWERGLIB +#include "displays-upower.h" +#endif /* check for randr 1.3 or better */ #if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3) @@ -69,6 +72,8 @@ static XfceRRCrtc *xfce_displays_helper_find_crtc_by_id (Xfc 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_get_topleftmost_pos (XfceRRCrtc *crtc, + XfceDisplaysHelper *helper); static void xfce_displays_helper_normalize_crtc (XfceRRCrtc *crtc, XfceDisplaysHelper *helper); static Status xfce_displays_helper_disable_crtc (XfceDisplaysHelper *helper, @@ -79,12 +84,18 @@ static void xfce_displays_helper_apply_crtc (Xfc XfceDisplaysHelper *helper); static void xfce_displays_helper_set_outputs (XfceRRCrtc *crtc, RROutput output); +static void xfce_displays_helper_apply_all (XfceDisplaysHelper *helper); 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); +#ifdef HAVE_UPOWERGLIB +static void xfce_displays_helper_toggle_internal (XfceDisplaysUPower *power, + gboolean lid_is_closed, + XfceDisplaysHelper *helper); +#endif @@ -106,6 +117,11 @@ struct _XfceDisplaysHelper gint primary; #endif +#ifdef HAVE_UPOWERGLIB + XfceDisplaysUPower *power; + gint phandler; +#endif + GdkDisplay *display; GdkWindow *root_window; Display *xdisplay; @@ -166,6 +182,10 @@ xfce_displays_helper_init (XfceDisplaysHelper *helper) gint major = 0, minor = 0; gint error_base, err; +#ifdef HAVE_UPOWERGLIB + helper->power = NULL; + helper->phandler = 0; +#endif helper->resources = NULL; helper->crtcs = NULL; helper->handler = 0; @@ -209,6 +229,14 @@ xfce_displays_helper_init (XfceDisplaysHelper *helper) xfce_displays_helper_screen_on_event, helper); +#ifdef HAVE_UPOWERGLIB + helper->power = g_object_new (XFCE_TYPE_DISPLAYS_UPOWER, NULL); + helper->phandler = g_signal_connect (G_OBJECT (helper->power), + "lid-changed", + G_CALLBACK (xfce_displays_helper_toggle_internal), + helper); +#endif + /* open the channel */ helper->channel = xfconf_channel_get ("displays"); @@ -255,6 +283,16 @@ xfce_displays_helper_dispose (GObject *object) helper->handler = 0; } +#ifdef HAVE_UPOWERGLIB + if (helper->phandler > 0) + { + g_signal_handler_disconnect (G_OBJECT (helper->power), + helper->phandler); + g_object_unref (helper->power); + helper->phandler = 0; + } +#endif + gdk_window_remove_filter (helper->root_window, xfce_displays_helper_screen_on_event, helper); @@ -352,7 +390,6 @@ xfce_displays_helper_screen_on_event (GdkXEvent *xevent, /*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 :/) */ } /* Pass the event on to GTK+ */ @@ -637,10 +674,6 @@ xfce_displays_helper_load_from_xfconf (XfceDisplaysHelper *helper, 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: @@ -778,6 +811,19 @@ xfce_displays_helper_find_usable_crtc (XfceDisplaysHelper *helper, static void +xfce_displays_helper_get_topleftmost_pos (XfceRRCrtc *crtc, + XfceDisplaysHelper *helper) +{ + g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && crtc); + + /* used to normalize positions later */ + helper->min_x = MIN (helper->min_x, crtc->x); + helper->min_y = MIN (helper->min_y, crtc->y); +} + + + +static void xfce_displays_helper_normalize_crtc (XfceRRCrtc *crtc, XfceDisplaysHelper *helper) { @@ -922,6 +968,43 @@ xfce_displays_helper_set_outputs (XfceRRCrtc *crtc, static void +xfce_displays_helper_apply_all (XfceDisplaysHelper *helper) +{ + g_assert (XFCE_IS_DISPLAYS_HELPER (helper) && helper->crtcs); + + /* normalization and screen size calculation */ + g_ptr_array_foreach (helper->crtcs, (GFunc) xfce_displays_helper_get_topleftmost_pos, helper); + g_ptr_array_foreach (helper->crtcs, (GFunc) xfce_displays_helper_normalize_crtc, helper); + + gdk_error_trap_push (); + + /* 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 */ + 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 */ + xfce_displays_helper_set_screen_size (helper); + + /* final loop, apply crtc changes */ + 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 (helper->xdisplay, GDK_WINDOW_XID (helper->root_window), + helper->primary); +#endif + + /* release the grab, changes are done */ + gdk_x11_display_ungrab (helper->display); + gdk_flush (); + gdk_error_trap_pop (); +} + + + +static void xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper, const gchar *scheme) { @@ -962,36 +1045,8 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper, goto err_cleanup; } - /* second loop, normalization and screen size calculation */ - g_ptr_array_foreach (helper->crtcs, (GFunc) xfce_displays_helper_normalize_crtc, helper); - - gdk_error_trap_push (); - - /* 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 */ - 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 */ - xfce_displays_helper_set_screen_size (helper); - - /* final loop, apply crtc changes */ - 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 (helper->xdisplay, GDK_WINDOW_XID (helper->root_window), - helper->primary); -#endif - - /* release the grab, changes are done */ - gdk_x11_display_ungrab (helper->display); - gdk_flush (); - gdk_error_trap_pop (); - - /* refresh the cache (better safe than sorry) */ - xfce_displays_helper_reload (helper); + /* apply settings */ + xfce_displays_helper_apply_all (helper); err_cleanup: /* Free the xfconf properties */ @@ -1016,3 +1071,145 @@ xfce_displays_helper_channel_property_changed (XfconfChannel *channel, xfconf_channel_reset_property (channel, "/Schemes/Apply", FALSE); } } + + + +#ifdef HAVE_UPOWERGLIB +static void +xfce_displays_helper_toggle_internal (XfceDisplaysUPower *power, + gboolean lid_is_closed, + XfceDisplaysHelper *helper) +{ + GHashTable *saved_outputs; + XfceRRCrtc *crtc = NULL; + XRROutputInfo *info; + RROutput lvds = None; + gboolean active = FALSE; + RRMode best_mode; + gint best_dist, dist, n, m; + + xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "Lid is %s, toggling internal output.", + XFSD_LID_STR (lid_is_closed)); + + for (n = 0; n < helper->resources->noutput; ++n) + { + gdk_error_trap_push (); + info = XRRGetOutputInfo (helper->xdisplay, helper->resources, + helper->resources->outputs[n]); + + /* Try to find the internal display */ + if (info && (info->connection == RR_Connected) + && (g_str_has_prefix (info->name, "LVDS") + || strcmp (info->name, "PANEL") == 0)) + { + lvds = helper->resources->outputs[n]; + break; + } + + XRRFreeOutputInfo (info); + gdk_flush (); + gdk_error_trap_pop (); + } + + if (lvds == None) + return; + + /* Get the associated CRTC */ + if (info->crtc != None) + crtc = xfce_displays_helper_find_crtc_by_id (helper, info->crtc); + + /* Is LVDS active? */ + active = crtc && crtc->mode != None; + helper->mm_width = helper->mm_height = helper->width = helper->height = 0; + helper->min_x = helper->min_y = 32768; + + if (active && lid_is_closed) + { + /* if active and the lid is closed, deactivate it */ + xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "%s will be disabled (lid closed event).", info->name); + crtc->mode = None; + crtc->noutput = 0; + crtc->changed = TRUE; + + } + else if (!active && !lid_is_closed) + { + /* re-activate it because the user opened the lid */ + saved_outputs = xfconf_channel_get_properties (helper->channel, "/Default"); + if (saved_outputs) + { + /* try to load user saved settings */ + active = xfce_displays_helper_load_from_xfconf (helper, "Default", + saved_outputs, lvds); + g_hash_table_destroy (saved_outputs); + if (!active) + { + /* inactive, because of invalid or inexistent settings, + * so set up a mode manually */ + if (info->crtc == None) + crtc = xfce_displays_helper_find_usable_crtc (helper, lvds); + + if (!crtc) + { + g_warning ("No available CRTC for %s (lid opened event).", info->name); + goto lid_abort; + } + xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "CRTC %lu assigned to %s (lid opened event).", + crtc->id, info->name); + + /* find the preferred mode */ + best_mode = None; + best_dist = 0; + 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; + + if (n < info->npreferred) + dist = 0; + else if (info->mm_height != 0) + dist = (1000 * gdk_screen_height () / gdk_screen_height_mm () - + 1000 * helper->resources->modes[m].height / info->mm_height); + else + dist = gdk_screen_height () - helper->resources->modes[m].height; + + dist = ABS (dist); + + if (best_mode == None || dist < best_dist) + { + best_mode = helper->resources->modes[m].id; + best_dist = dist; + } + } + } + /* bad luck */ + if (best_mode == None) + { + g_warning ("No available mode for %s (lid opened event).", info->name); + goto lid_abort; + } + /* set the mode found */ + crtc->mode = best_mode; + xfce_displays_helper_set_outputs (crtc, lvds); + crtc->changed = TRUE; + } + xfsettings_dbg (XFSD_DEBUG_DISPLAYS, "%s will be re-enabled (lid opened event).", info->name); + } + } + else + goto lid_abort; + + /* apply settings */ + xfce_displays_helper_apply_all (helper); + +lid_abort: + /* wasn't freed because of the break */ + XRRFreeOutputInfo (info); + gdk_flush (); + gdk_error_trap_pop (); +} +#endif _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits