diff options
Diffstat (limited to 'plugins/xrandr/gsd-xrandr-manager.c')
-rw-r--r-- | plugins/xrandr/gsd-xrandr-manager.c | 589 |
1 files changed, 359 insertions, 230 deletions
diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c index a9893527..26a7e02b 100644 --- a/plugins/xrandr/gsd-xrandr-manager.c +++ b/plugins/xrandr/gsd-xrandr-manager.c @@ -38,6 +38,7 @@ #include <gdk/gdk.h> #include <gdk/gdkx.h> #include <gtk/gtk.h> +#include <libupower-glib/upower.h> #define GNOME_DESKTOP_USE_UNSTABLE_API @@ -102,6 +103,9 @@ struct GsdXrandrManagerPrivate GnomeRRScreen *rw_screen; gboolean running; + UpClient *upower_client; + gboolean laptop_lid_is_closed; + GSettings *settings; GDBusNodeInfo *introspection_data; GDBusConnection *connection; @@ -353,10 +357,68 @@ print_configuration (GnomeRRConfig *config, const char *header) print_output (outputs[i]); } -/* This function centralizes the use of gnome_rr_config_apply_from_filename_with_time(). +static gboolean +is_laptop (GnomeRRScreen *screen, GnomeRROutputInfo *output) +{ + GnomeRROutput *rr_output; + + rr_output = gnome_rr_screen_get_output_by_name (screen, gnome_rr_output_info_get_name (output)); + + return gnome_rr_output_is_laptop (rr_output); +} + +static GnomeRROutputInfo * +get_laptop_output_info (GnomeRRScreen *screen, GnomeRRConfig *config) +{ + int i; + GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (config); + + for (i = 0; outputs[i] != NULL; i++) { + if (is_laptop (screen, outputs[i])) + return outputs[i]; + } + + return NULL; +} + +static gboolean +non_laptop_outputs_are_active (GnomeRRConfig *config, GnomeRROutputInfo *laptop_info) +{ + GnomeRROutputInfo **outputs; + int i; + + outputs = gnome_rr_config_get_outputs (config); + for (i = 0; outputs[i] != NULL; i++) { + if (outputs[i] == laptop_info) + continue; + + if (gnome_rr_output_info_is_active (outputs[i])) + return TRUE; + } + + return FALSE; +} + +static void +turn_off_laptop_display_in_configuration (GnomeRRScreen *screen, GnomeRRConfig *config) +{ + GnomeRROutputInfo *laptop_info; + + laptop_info = get_laptop_output_info (screen, config); + if (laptop_info) { + /* Turn off the laptop's screen only if other displays are on. This is to avoid an all-black-screens scenario. */ + if (non_laptop_outputs_are_active (config, laptop_info)) + gnome_rr_output_info_set_active (laptop_info, FALSE); + } + + /* Adjust the offsets of outputs so they start at (0, 0) */ + gnome_rr_config_sanitize (config); +} + +/* This function effectively centralizes the use of gnome_rr_config_apply_from_filename_with_time(). * - * Optionally filters out GNOME_RR_ERROR_NO_MATCHING_CONFIG from - * gnome_rr_config_apply_from_filename_with_time(), since that is not usually an error. + * Optionally filters out GNOME_RR_ERROR_NO_MATCHING_CONFIG from the matching + * process(), since that is not usually an error. */ static gboolean apply_configuration_from_filename (GsdXrandrManager *manager, @@ -366,6 +428,7 @@ apply_configuration_from_filename (GsdXrandrManager *manager, GError **error) { struct GsdXrandrManagerPrivate *priv = manager->priv; + GnomeRRConfig *config; GError *my_error; gboolean success; char *str; @@ -375,24 +438,37 @@ apply_configuration_from_filename (GsdXrandrManager *manager, g_free (str); my_error = NULL; - success = gnome_rr_config_apply_from_filename_with_time (priv->rw_screen, filename, timestamp, &my_error); - if (success) - return TRUE; - if (g_error_matches (my_error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG)) { - if (no_matching_config_is_an_error) - goto fail; + config = g_object_new (GNOME_TYPE_RR_CONFIG, "screen", priv->rw_screen, NULL); + if (!gnome_rr_config_load_filename (config, filename, &my_error)) { + g_object_unref (config); - /* This is not an error; the user probably changed his monitors - * and so they don't match any of the stored configurations. - */ - g_error_free (my_error); - return TRUE; + if (g_error_matches (my_error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG)) { + if (no_matching_config_is_an_error) { + g_propagate_error (error, my_error); + return FALSE; + } else { + /* This is not an error; the user probably changed his monitors + * and so they don't match any of the stored configurations. + */ + g_error_free (my_error); + return TRUE; + } + } else { + g_propagate_error (error, my_error); + return FALSE; + } } -fail: - g_propagate_error (error, my_error); - return FALSE; + if (up_client_get_lid_is_closed (priv->upower_client)) + turn_off_laptop_display_in_configuration (priv->rw_screen, config); + + gnome_rr_config_ensure_primary (config); + success = gnome_rr_config_apply_with_time (config, priv->rw_screen, timestamp, error); + + g_object_unref (config); + + return success; } /* This function centralizes the use of gnome_rr_config_apply_with_time(). @@ -401,7 +477,7 @@ fail: * We just return whether setting the configuration succeeded. */ static gboolean -apply_configuration (GsdXrandrManager *manager, GnomeRRConfig *config, guint32 timestamp, gboolean show_error) +apply_configuration (GsdXrandrManager *manager, GnomeRRConfig *config, guint32 timestamp, gboolean show_error, gboolean save_configuration) { GsdXrandrManagerPrivate *priv = manager->priv; GError *error; @@ -413,7 +489,10 @@ apply_configuration (GsdXrandrManager *manager, GnomeRRConfig *config, guint32 t error = NULL; success = gnome_rr_config_apply_with_time (config, priv->rw_screen, timestamp, &error); - if (!success) { + if (success) { + if (save_configuration) + gnome_rr_config_save (config, NULL); /* NULL-GError - there's not much we can do if this fails */ + } else { log_msg ("Could not switch to the following configuration (timestamp %u): %s\n", timestamp, error->message); log_configuration (config); if (show_error) @@ -716,16 +795,6 @@ gsd_xrandr_manager_2_rotate_to (GsdXrandrManager *manager, } static gboolean -is_laptop (GnomeRRScreen *screen, GnomeRROutputInfo *output) -{ - GnomeRROutput *rr_output; - - rr_output = gnome_rr_screen_get_output_by_name (screen, gnome_rr_output_info_get_name (output)); - - return gnome_rr_output_is_laptop (rr_output); -} - -static gboolean get_clone_size (GnomeRRScreen *screen, int *width, int *height) { GnomeRRMode **modes = gnome_rr_screen_list_clone_modes (screen); @@ -777,8 +846,20 @@ config_is_all_off (GnomeRRConfig *config) return TRUE; } +static gboolean +laptop_lid_is_closed (GsdXrandrManager *manager) +{ + return up_client_get_lid_is_closed (manager->priv->upower_client); +} + +static gboolean +is_laptop_with_closed_lid (GsdXrandrManager *manager, GnomeRRScreen *screen, GnomeRROutputInfo *info) +{ + return is_laptop (screen, info) && laptop_lid_is_closed (manager); +} + static GnomeRRConfig * -make_clone_setup (GnomeRRScreen *screen) +make_clone_setup (GsdXrandrManager *manager, GnomeRRScreen *screen) { GnomeRRConfig *result; GnomeRROutputInfo **outputs; @@ -795,7 +876,7 @@ make_clone_setup (GnomeRRScreen *screen) GnomeRROutputInfo *info = outputs[i]; gnome_rr_output_info_set_active (info, FALSE); - if (gnome_rr_output_info_is_connected (info)) { + if (!is_laptop_with_closed_lid (manager, screen, info) && gnome_rr_output_info_is_connected (info)) { GnomeRROutput *output = gnome_rr_screen_get_output_by_name (screen, gnome_rr_output_info_get_name (info)); GnomeRRMode **modes = gnome_rr_output_list_modes (output); @@ -904,7 +985,7 @@ turn_on (GnomeRRScreen *screen, } static GnomeRRConfig * -make_laptop_setup (GnomeRRScreen *screen) +make_laptop_setup (GsdXrandrManager *manager, GnomeRRScreen *screen) { /* Turn on the laptop, disable everything else */ GnomeRRConfig *result = gnome_rr_config_new_current (screen, NULL); @@ -914,7 +995,7 @@ make_laptop_setup (GnomeRRScreen *screen) for (i = 0; outputs[i] != NULL; ++i) { GnomeRROutputInfo *info = outputs[i]; - if (is_laptop (screen, info)) { + if (is_laptop (screen, info) && !laptop_lid_is_closed (manager)) { if (!turn_on (screen, info, 0, 0)) { g_object_unref (G_OBJECT (result)); result = NULL; @@ -952,8 +1033,88 @@ turn_on_and_get_rightmost_offset (GnomeRRScreen *screen, GnomeRROutputInfo *info return x; } +/* Used from qsort(); compares outputs based on their X position */ +static int +compare_output_positions (const void *a, const void *b) +{ + GnomeRROutputInfo *oa = (GnomeRROutputInfo *) a; + GnomeRROutputInfo *ob = (GnomeRROutputInfo *) b; + int xa, xb; + + gnome_rr_output_info_get_geometry (oa, &xa, NULL, NULL, NULL); + gnome_rr_output_info_get_geometry (ob, &xb, NULL, NULL, NULL); + + return xb - xa; +} + +/* A set of outputs with already-set sizes and positions may not fit in the + * frame buffer that is available. Turn off outputs right-to-left until we find + * a size that fits. Returns whether something applicable was found + * (i.e. something that fits and that does not consist of only-off outputs). + */ +static gboolean +trim_rightmost_outputs_that_dont_fit_in_framebuffer (GnomeRRScreen *rr_screen, GnomeRRConfig *config) +{ + GnomeRROutputInfo **outputs; + GnomeRROutputInfo **sorted_outputs; + int num_on_outputs; + int i, j; + gboolean applicable; + + outputs = gnome_rr_config_get_outputs (config); + + /* How many are on? */ + + num_on_outputs = 0; + for (i = 0; outputs[i] != NULL; i++) { + if (gnome_rr_output_info_is_active (outputs[i])) + num_on_outputs++; + } + + /* Lay them out from left to right */ + + sorted_outputs = g_new (GnomeRROutputInfo *, num_on_outputs); + j = 0; + for (i = 0; outputs[i] != NULL; i++) { + if (gnome_rr_output_info_is_active (outputs[i])) { + sorted_outputs[j] = outputs[i]; + j++; + } + } + + qsort (sorted_outputs, num_on_outputs, sizeof (sorted_outputs[0]), compare_output_positions); + + /* Trim! */ + + applicable = FALSE; + + for (i = num_on_outputs - 1; i >= 0; i--) { + GError *error = NULL; + gboolean is_bounds_error; + + applicable = gnome_rr_config_applicable (config, rr_screen, &error); + if (applicable) + break; + + is_bounds_error = g_error_matches (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR); + g_error_free (error); + + if (!is_bounds_error) + break; + + gnome_rr_output_info_set_active (sorted_outputs[i], FALSE); + } + + if (config_is_all_off (config)) + applicable = FALSE; + + g_free (sorted_outputs); + + return applicable; +} + static GnomeRRConfig * -make_xinerama_setup (GnomeRRScreen *screen) +make_xinerama_setup (GsdXrandrManager *manager, GnomeRRScreen *screen) { /* Turn on everything that has a preferred mode, and * position it from left to right @@ -967,18 +1128,26 @@ make_xinerama_setup (GnomeRRScreen *screen) for (i = 0; outputs[i] != NULL; ++i) { GnomeRROutputInfo *info = outputs[i]; - if (is_laptop (screen, info)) - x = turn_on_and_get_rightmost_offset (screen, info, x); + if (is_laptop (screen, info)) { + if (laptop_lid_is_closed (manager)) + gnome_rr_output_info_set_active (info, FALSE); + else { + gnome_rr_output_info_set_primary (info, TRUE); + x = turn_on_and_get_rightmost_offset (screen, info, x); + } + } } for (i = 0; outputs[i] != NULL; ++i) { GnomeRROutputInfo *info = outputs[i]; - if (gnome_rr_output_info_is_connected (info) && !is_laptop (screen, info)) + if (gnome_rr_output_info_is_connected (info) && !is_laptop (screen, info)) { + gnome_rr_output_info_set_primary (info, FALSE); x = turn_on_and_get_rightmost_offset (screen, info, x); + } } - if (config_is_all_off (result)) { + if (!trim_rightmost_outputs_that_dont_fit_in_framebuffer (screen, result)) { g_object_unref (G_OBJECT (result)); result = NULL; } @@ -1011,7 +1180,7 @@ make_other_setup (GnomeRRScreen *screen) } } - if (config_is_all_off (result)) { + if (!trim_rightmost_outputs_that_dont_fit_in_framebuffer (screen, result)) { g_object_unref (G_OBJECT (result)); result = NULL; } @@ -1129,9 +1298,9 @@ generate_fn_f7_configs (GsdXrandrManager *mgr) } g_ptr_array_add (array, gnome_rr_config_new_current (screen, NULL)); - g_ptr_array_add (array, make_clone_setup (screen)); - g_ptr_array_add (array, make_xinerama_setup (screen)); - g_ptr_array_add (array, make_laptop_setup (screen)); + g_ptr_array_add (array, make_clone_setup (mgr, screen)); + g_ptr_array_add (array, make_xinerama_setup (mgr, screen)); + g_ptr_array_add (array, make_laptop_setup (mgr, screen)); g_ptr_array_add (array, make_other_setup (screen)); array = sanitize (mgr, array); @@ -1245,7 +1414,7 @@ handle_fn_f7 (GsdXrandrManager *mgr, guint32 timestamp) if (timestamp < server_timestamp) timestamp = server_timestamp; - success = apply_configuration (mgr, priv->fn_f7_configs[mgr->priv->current_fn_f7_config], timestamp, TRUE); + success = apply_configuration (mgr, priv->fn_f7_configs[mgr->priv->current_fn_f7_config], timestamp, TRUE, TRUE); if (success) { log_msg ("Successfully switched to configuration (timestamp %u):\n", timestamp); @@ -1261,20 +1430,6 @@ handle_fn_f7 (GsdXrandrManager *mgr, guint32 timestamp) g_debug ("done handling fn-f7"); } -static GnomeRROutputInfo * -get_laptop_output_info (GnomeRRScreen *screen, GnomeRRConfig *config) -{ - int i; - GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (config); - - for (i = 0; outputs[i] != NULL; i++) { - if (is_laptop (screen, outputs[i])) - return outputs[i]; - } - - return NULL; -} - static GnomeRRRotation get_next_rotation (GnomeRRRotation allowed_rotations, GnomeRRRotation current_rotation) { @@ -1458,7 +1613,7 @@ handle_rotate_windows (GsdXrandrManager *mgr, gnome_rr_output_info_set_rotation (rotatable_output_info, next_rotation); - success = apply_configuration (mgr, current, timestamp, show_error); + success = apply_configuration (mgr, current, timestamp, show_error, TRUE); if (success) rotate_touchscreens (mgr, next_rotation); @@ -1471,129 +1626,58 @@ auto_configure_outputs (GsdXrandrManager *manager, guint32 timestamp) { GsdXrandrManagerPrivate *priv = manager->priv; GnomeRRConfig *config; - GnomeRROutputInfo **outputs; - int i; - GList *just_turned_on; - GList *l; - int x; - GError *error; - gboolean applicable; - - config = gnome_rr_config_new_current (priv->rw_screen, NULL); - - /* For outputs that are connected and on (i.e. they have a CRTC assigned - * to them, so they are getting a signal), we leave them as they are - * with their current modes. - * - * For other outputs, we will turn on connected-but-off outputs and turn - * off disconnected-but-on outputs. - * - * FIXME: If an output remained connected+on, it would be nice to ensure - * that the output's CRTCs still has a reasonable mode (think of - * changing one monitor for another with different capabilities). - */ - - just_turned_on = NULL; - outputs = gnome_rr_config_get_outputs (config); - - for (i = 0; outputs[i] != NULL; i++) { - GnomeRROutputInfo *output = outputs[i]; - - if (gnome_rr_output_info_is_connected (output) && !gnome_rr_output_info_is_active (output)) { - gnome_rr_output_info_set_active (output, TRUE); - gnome_rr_output_info_set_rotation (output, GNOME_RR_ROTATION_0); - just_turned_on = g_list_prepend (just_turned_on, GINT_TO_POINTER (i)); - } else if (!gnome_rr_output_info_is_connected (output) && gnome_rr_output_info_is_active (output)) - gnome_rr_output_info_set_active (output, FALSE); - } - - /* Now, lay out the outputs from left to right. Put first the outputs - * which remained on; put last the outputs that were newly turned on. - */ - - x = 0; - - /* First, outputs that remained on */ - - for (i = 0; outputs[i] != NULL; i++) { - GnomeRROutputInfo *output = outputs[i]; - - if (g_list_find (just_turned_on, GINT_TO_POINTER (i))) - continue; - - if (gnome_rr_output_info_is_active (output)) { - int width, height; - g_assert (gnome_rr_output_info_is_connected (output)); - - gnome_rr_output_info_get_geometry (output, NULL, NULL, &width, &height); - gnome_rr_output_info_set_geometry (output, x, 0, width, height); - x += width; - } - } - - /* Second, outputs that were newly-turned on */ - - for (l = just_turned_on; l; l = l->next) { - GnomeRROutputInfo *output; - int width; - i = GPOINTER_TO_INT (l->data); - output = outputs[i]; - - g_assert (gnome_rr_output_info_is_active (output) && gnome_rr_output_info_is_connected (output)); - - /* since the output was off, use its preferred width/height (it doesn't have a real width/height yet) */ - width = gnome_rr_output_info_get_preferred_width (output); - gnome_rr_output_info_set_geometry (output, x, 0, width, gnome_rr_output_info_get_preferred_height (output)); - - x += width; + config = make_xinerama_setup (manager, priv->rw_screen); + if (config) { + print_configuration (config, "auto-configure - xinerama mode"); + apply_configuration (manager, config, timestamp, TRUE, FALSE); + g_object_unref (config); + } else { + g_debug ("No applicable configuration found during auto-configure"); } +} - /* Check if we have a large enough framebuffer size. If not, turn off - * outputs from right to left until we reach a usable size. - */ - - just_turned_on = g_list_reverse (just_turned_on); /* now the outputs here are from right to left */ - - l = just_turned_on; - while (1) { - GnomeRROutputInfo *output; - gboolean is_bounds_error; - - error = NULL; - applicable = gnome_rr_config_applicable (config, priv->rw_screen, &error); +static void +use_stored_configuration_or_auto_configure_outputs (GsdXrandrManager *manager, guint32 timestamp) +{ + GsdXrandrManagerPrivate *priv = manager->priv; + char *intended_filename; + GError *error; + gboolean success; - if (applicable) - break; + intended_filename = gnome_rr_config_get_intended_filename (); - is_bounds_error = g_error_matches (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR); - g_error_free (error); + error = NULL; + success = apply_configuration_from_filename (manager, intended_filename, TRUE, timestamp, &error); + g_free (intended_filename); - if (!is_bounds_error) - break; + if (!success) { + /* We don't bother checking the error type. + * + * Both G_FILE_ERROR_NOENT and + * GNOME_RR_ERROR_NO_MATCHING_CONFIG would mean, "there + * was no configuration to apply, or none that matched + * the current outputs", and in that case we need to run + * our fallback. + * + * Any other error means "we couldn't do the smart thing + * of using a previously- saved configuration, anyway, + * for some other reason. In that case, we also need to + * run our fallback to avoid leaving the user with a + * bogus configuration. + */ - if (l) { - i = GPOINTER_TO_INT (l->data); - l = l->next; + if (error) + g_error_free (error); - output = outputs[i]; - gnome_rr_output_info_set_active (output, FALSE); + if (timestamp != priv->last_config_timestamp || timestamp == GDK_CURRENT_TIME) { + priv->last_config_timestamp = timestamp; + auto_configure_outputs (manager, timestamp); + log_msg (" Automatically configured outputs\n"); } else - break; - } - - /* Apply the configuration! */ - - if (applicable) { - print_configuration (config, "auto configure"); - - apply_configuration (manager, config, timestamp, TRUE); - } else { - g_debug ("Not an applicable config"); - } - - g_list_free (just_turned_on); - g_object_unref (config); + log_msg (" Ignored autoconfiguration as old and new config timestamps are the same\n"); + } else + log_msg ("Applied stored configuration\n"); } static void @@ -1645,45 +1729,8 @@ on_randr_event (GnomeRRScreen *screen, gpointer data) * outputs in a sane way. */ - char *intended_filename; - GError *error; - gboolean success; - show_timestamps_dialog (manager, "need to deal with reconfiguration, as config > change"); - - intended_filename = gnome_rr_config_get_intended_filename (); - - error = NULL; - success = apply_configuration_from_filename (manager, intended_filename, TRUE, config_timestamp, &error); - g_free (intended_filename); - - if (!success) { - /* We don't bother checking the error type. - * - * Both G_FILE_ERROR_NOENT and - * GNOME_RR_ERROR_NO_MATCHING_CONFIG would mean, "there - * was no configuration to apply, or none that matched - * the current outputs", and in that case we need to run - * our fallback. - * - * Any other error means "we couldn't do the smart thing - * of using a previously- saved configuration, anyway, - * for some other reason. In that case, we also need to - * run our fallback to avoid leaving the user with a - * bogus configuration. - */ - - if (error) - g_error_free (error); - - if (config_timestamp != priv->last_config_timestamp) { - priv->last_config_timestamp = config_timestamp; - auto_configure_outputs (manager, config_timestamp); - log_msg (" Automatically configured outputs to deal with event\n"); - } else - log_msg (" Ignored event as old and new config timestamps are the same\n"); - } else - log_msg ("Applied stored configuration to deal with event\n"); + use_stored_configuration_or_auto_configure_outputs (manager, config_timestamp); } log_close (); @@ -1763,7 +1810,7 @@ apply_default_boot_configuration (GsdXrandrManager *mgr, guint32 timestamp) case GSD_XRANDR_BOOT_BEHAVIOUR_DO_NOTHING: return; case GSD_XRANDR_BOOT_BEHAVIOUR_CLONE: - config = make_clone_setup (screen); + config = make_clone_setup (mgr, screen); break; case GSD_XRANDR_BOOT_BEHAVIOUR_DOCK: config = make_other_setup (screen); @@ -1773,7 +1820,10 @@ apply_default_boot_configuration (GsdXrandrManager *mgr, guint32 timestamp) } if (config) { - apply_configuration (mgr, config, timestamp, TRUE); + /* We don't save the configuration (the "false" parameter to the following function) because we don't want to + * install a user-side setting when *here* we are using a system-default setting. + */ + apply_configuration (mgr, config, timestamp, TRUE, FALSE); g_object_unref (config); } } @@ -1852,6 +1902,55 @@ apply_default_configuration_from_file (GsdXrandrManager *manager, guint32 timest return result; } +static void +turn_off_laptop_display (GsdXrandrManager *manager, guint32 timestamp) +{ + GsdXrandrManagerPrivate *priv = manager->priv; + GnomeRRConfig *config; + + config = gnome_rr_config_new_current (priv->rw_screen, NULL); + + turn_off_laptop_display_in_configuration (priv->rw_screen, config); + + /* We don't turn the laptop's display off if it is the only display present. */ + if (!config_is_all_off (config)) { + /* We don't save the configuration (the "false" parameter to the following function) because we + * wouldn't want to restore a configuration with the laptop's display turned off, if at some + * point later the user booted his laptop with the lid open. + */ + apply_configuration (manager, config, timestamp, FALSE, FALSE); + } + + g_object_unref (config); +} + +static void +power_client_changed_cb (UpClient *client, gpointer data) +{ + GsdXrandrManager *manager = data; + GsdXrandrManagerPrivate *priv = manager->priv; + gboolean is_closed; + + is_closed = up_client_get_lid_is_closed (priv->upower_client); + + if (is_closed != priv->laptop_lid_is_closed) { + priv->laptop_lid_is_closed = is_closed; + + /* Refresh the RANDR state. The lid just got opened/closed, so we can afford to + * probe the outputs right now. It will also help the case where we can't detect + * hotplug/unplug, but the fact that the lid's state changed lets us know that the + * user probably did something interesting. + */ + + gnome_rr_screen_refresh (priv->rw_screen, NULL); /* NULL-GError */ + + if (is_closed) + turn_off_laptop_display (manager, GDK_CURRENT_TIME); /* sucks not to have a timestamp for the notification */ + else + use_stored_configuration_or_auto_configure_outputs (manager, GDK_CURRENT_TIME); + } +} + gboolean gsd_xrandr_manager_start (GsdXrandrManager *manager, GError **error) @@ -1862,7 +1961,7 @@ gsd_xrandr_manager_start (GsdXrandrManager *manager, log_open (); log_msg ("------------------------------------------------------------\nSTARTING XRANDR PLUGIN\n"); - manager->priv->rw_screen = gnome_settings_session_get_screen (error); + manager->priv->rw_screen = gnome_rr_screen_new (gdk_screen_get_default (), error); if (manager->priv->rw_screen == NULL) { log_msg ("Could not initialize the RANDR plugin%s%s\n", @@ -1874,6 +1973,11 @@ gsd_xrandr_manager_start (GsdXrandrManager *manager, g_signal_connect (manager->priv->rw_screen, "changed", G_CALLBACK (on_randr_event), manager); + manager->priv->upower_client = up_client_new (); + manager->priv->laptop_lid_is_closed = up_client_get_lid_is_closed (manager->priv->upower_client); + g_signal_connect (manager->priv->upower_client, "changed", + G_CALLBACK (power_client_changed_cb), manager); + log_msg ("State of screen at startup:\n"); log_screen (manager->priv->rw_screen); @@ -1918,6 +2022,11 @@ gsd_xrandr_manager_stop (GsdXrandrManager *manager) manager->priv->rw_screen = NULL; } + if (manager->priv->upower_client != NULL) { + g_object_unref (manager->priv->upower_client); + manager->priv->upower_client = NULL; + } + if (manager->priv->introspection_data) { g_dbus_node_info_unref (manager->priv->introspection_data); manager->priv->introspection_data = NULL; @@ -1983,20 +2092,15 @@ gsd_xrandr_manager_finalize (GObject *object) } static void -handle_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) +handle_method_call_xrandr_2 (GsdXrandrManager *manager, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation) { - GsdXrandrManager *manager = (GsdXrandrManager *) user_data; gint64 timestamp; GError *error = NULL; - g_debug ("Calling method '%s' for XRandR", method_name); + g_debug ("Calling method '%s' for org.gnome.SettingsDaemon.XRANDR_2", method_name); if (g_strcmp0 (method_name, "ApplyConfiguration") == 0) { gint64 parent_window_id; @@ -2024,6 +2128,26 @@ handle_method_call (GDBusConnection *connection, } } +static void +handle_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + GsdXrandrManager *manager = (GsdXrandrManager *) user_data; + + g_debug ("Handling method call %s.%s", interface_name, method_name); + + if (g_strcmp0 (interface_name, "org.gnome.SettingsDaemon.XRANDR_2") == 0) + handle_method_call_xrandr_2 (manager, method_name, parameters, invocation); + else + g_warning ("unknown interface: %s", interface_name); +} + static const GDBusInterfaceVTable interface_vtable = { @@ -2039,6 +2163,8 @@ on_bus_gotten (GObject *source_object, { GDBusConnection *connection; GError *error = NULL; + GDBusInterfaceInfo **infos; + int i; if (manager->priv->bus_cancellable == NULL || g_cancellable_is_cancelled (manager->priv->bus_cancellable)) { @@ -2054,13 +2180,16 @@ on_bus_gotten (GObject *source_object, } manager->priv->connection = connection; - g_dbus_connection_register_object (connection, - GSD_XRANDR_DBUS_PATH, - manager->priv->introspection_data->interfaces[0], - &interface_vtable, - manager, - NULL, - NULL); + infos = manager->priv->introspection_data->interfaces; + for (i = 0; infos[i] != NULL; i++) { + g_dbus_connection_register_object (connection, + GSD_XRANDR_DBUS_PATH, + infos[i], + &interface_vtable, + manager, + NULL, + NULL); + } } static void |