[mutter/wip/wayland-display] MonitorConfig: handle changes in the laptop lid
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-display] MonitorConfig: handle changes in the laptop lid
- Date: Fri, 26 Jul 2013 16:40:22 +0000 (UTC)
commit 84f9a0a5d6369053e3e22b416f0c3fc87182decb
Author: Giovanni Campagna <gcampagn redhat com>
Date: Fri Jul 26 18:22:59 2013 +0200
MonitorConfig: handle changes in the laptop lid
This way we don't need to track the current and previous
configuration in gnome-settings-daemon, when we already do so
in mutter.
configure.ac | 1 +
src/core/monitor-config.c | 186 +++++++++++++++++++++++++++++++++++++++++++-
src/core/monitor-private.h | 3 +
3 files changed, 186 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 06e3bb0..b7ac179 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,7 @@ MUTTER_PC_MODULES="
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.14.3
cogl-1.0 >= 1.13.3
+ upower-glib > 0.9.11
"
GLIB_GSETTINGS
diff --git a/src/core/monitor-config.c b/src/core/monitor-config.c
index cc4ae36..7a3257a 100644
--- a/src/core/monitor-config.c
+++ b/src/core/monitor-config.c
@@ -38,6 +38,7 @@
#include <string.h>
#include <clutter/clutter.h>
+#include <libupower-glib/upower.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
@@ -88,9 +89,13 @@ struct _MetaMonitorConfig {
GHashTable *configs;
MetaConfiguration *current;
gboolean current_is_stored;
+ MetaConfiguration *previous;
GFile *file;
GCancellable *save_cancellable;
+
+ UpClient *up_client;
+ gboolean lid_is_closed;
};
struct _MetaMonitorConfigClass {
@@ -104,6 +109,9 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
GPtrArray *crtcs,
GPtrArray *outputs);
+static void power_client_changed_cb (UpClient *client,
+ gpointer user_data);
+
static void
free_output_key (MetaOutputKey *key)
{
@@ -199,6 +207,12 @@ meta_monitor_config_init (MetaMonitorConfig *self)
path = g_build_filename (g_get_user_config_dir (), filename, NULL);
self->file = g_file_new_for_path (path);
g_free (path);
+
+ self->up_client = up_client_new ();
+ self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
+
+ g_signal_connect_object (self->up_client, "changed",
+ G_CALLBACK (power_client_changed_cb), self, 0);
}
static void
@@ -808,6 +822,8 @@ apply_configuration (MetaMonitorConfig *self,
{
g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs);
+ if (!stored)
+ config_free (config);
return FALSE;
}
@@ -816,16 +832,108 @@ apply_configuration (MetaMonitorConfig *self,
(MetaCRTCInfo**)crtcs->pdata, crtcs->len,
(MetaOutputInfo**)outputs->pdata, outputs->len);
- if (self->current && !self->current_is_stored)
- config_free (self->current);
+ /* Stored (persistent) configurations override the previous one always.
+ Also, we clear the previous configuration if the current one (which is
+ about to become previous) is stored.
+ */
+ if (stored ||
+ (self->current && self->current_is_stored))
+ {
+ if (self->previous)
+ config_free (self->previous);
+ self->previous = NULL;
+ }
+ else
+ {
+ self->previous = self->current;
+ }
+
self->current = config;
self->current_is_stored = stored;
+ if (self->current == self->previous)
+ self->previous = NULL;
+
g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs);
return TRUE;
}
+static gboolean
+key_is_laptop (MetaOutputKey *key)
+{
+ /* FIXME: extend with better heuristics */
+ return g_str_has_prefix (key->connector, "LVDS") ||
+ g_str_has_prefix (key->connector, "eDP");
+}
+
+static gboolean
+laptop_display_is_on (MetaConfiguration *config)
+{
+ unsigned int i;
+
+ for (i = 0; i < config->n_outputs; i++)
+ {
+ MetaOutputKey *key = &config->keys[i];
+ MetaOutputConfig *output = &config->outputs[i];
+
+ if (key_is_laptop (key) && output->enabled)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static MetaConfiguration *
+make_laptop_lid_config (MetaConfiguration *reference)
+{
+ MetaConfiguration *new;
+ unsigned int i;
+ gboolean has_primary;
+
+ g_assert (reference->n_outputs > 1);
+
+ new = g_slice_new0 (MetaConfiguration);
+ new->n_outputs = reference->n_outputs;
+ new->keys = g_new0 (MetaOutputKey, reference->n_outputs);
+ new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs);
+
+ for (i = 0; i < new->n_outputs; i++)
+ {
+ MetaOutputKey *current_key = &reference->keys[i];
+ MetaOutputConfig *current_output = &reference->outputs[i];
+
+ new->keys[i].connector = g_strdup (current_key->connector);
+ new->keys[i].vendor = g_strdup (current_key->vendor);
+ new->keys[i].product = g_strdup (current_key->product);
+ new->keys[i].serial = g_strdup (current_key->serial);
+
+ if (g_str_has_prefix (current_key->connector, "LVDS") ||
+ g_str_has_prefix (current_key->connector, "eDP"))
+ new->outputs[i].enabled = FALSE;
+ else
+ /* This can potentially leave a "hole" in the screen,
+ but this is actually a good thing, as it means windows
+ don't move around.
+ */
+ new->outputs[i] = *current_output;
+ }
+
+ has_primary = FALSE;
+ for (i = 0; i < new->n_outputs; i++)
+ {
+ if (new->outputs[i].is_primary)
+ {
+ has_primary = TRUE;
+ break;
+ }
+ }
+ if (!has_primary)
+ new->outputs[0].is_primary = TRUE;
+
+ return new;
+}
+
gboolean
meta_monitor_config_apply_stored (MetaMonitorConfig *self,
MetaMonitorManager *manager)
@@ -839,7 +947,13 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
if (stored)
{
- return apply_configuration (self, stored, manager, TRUE);
+ if (self->lid_is_closed &&
+ stored->n_outputs > 1 &&
+ laptop_display_is_on (stored))
+ return apply_configuration (self, make_laptop_lid_config (stored),
+ manager, FALSE);
+ else
+ return apply_configuration (self, stored, manager, TRUE);
}
else
return FALSE;
@@ -1077,7 +1191,18 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
if (default_config != NULL)
- ok = apply_configuration (self, default_config, manager, FALSE);
+ {
+ if (self->lid_is_closed &&
+ default_config->n_outputs > 1 &&
+ laptop_display_is_on (default_config))
+ {
+ ok = apply_configuration (self, make_laptop_lid_config (default_config),
+ manager, FALSE);
+ config_free (default_config);
+ }
+ else
+ ok = apply_configuration (self, default_config, manager, FALSE);
+ }
else
ok = FALSE;
@@ -1133,6 +1258,55 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
self->current = current;
}
+void
+meta_monitor_config_restore_previous (MetaMonitorConfig *self,
+ MetaMonitorManager *manager)
+{
+ if (self->previous)
+ {
+ apply_configuration (self, self->previous, manager, FALSE);
+ }
+ else
+ {
+ if (!meta_monitor_config_apply_stored (self, manager))
+ meta_monitor_config_make_default (self, manager);
+ }
+}
+
+static void
+turn_off_laptop_display (MetaMonitorConfig *self,
+ MetaMonitorManager *manager)
+{
+ MetaConfiguration *new;
+
+ if (self->current->n_outputs == 1)
+ return;
+
+ new = make_laptop_lid_config (self->current);
+ apply_configuration (self, new, manager, FALSE);
+}
+
+static void
+power_client_changed_cb (UpClient *client,
+ gpointer user_data)
+{
+ MetaMonitorManager *manager = meta_monitor_manager_get ();
+ MetaMonitorConfig *self = user_data;
+ gboolean is_closed;
+
+ is_closed = up_client_get_lid_is_closed (self->up_client);
+
+ if (is_closed != self->lid_is_closed)
+ {
+ self->lid_is_closed = is_closed;
+
+ if (is_closed)
+ turn_off_laptop_display (self, manager);
+ else
+ meta_monitor_config_restore_previous (self, manager);
+ }
+}
+
typedef struct {
MetaMonitorConfig *config;
GString *buffer;
@@ -1272,6 +1446,10 @@ meta_monitor_config_make_persistent (MetaMonitorConfig *self)
self->current_is_stored = TRUE;
g_hash_table_replace (self->configs, self->current, self->current);
+ if (self->previous)
+ config_free (self->previous);
+ self->previous = NULL;
+
meta_monitor_config_save (self);
}
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index 5365a6f..7ca2bb8 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -269,6 +269,9 @@ void meta_monitor_config_update_current (MetaMonitorConfig *confi
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
+void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
+ MetaMonitorManager *manager);
+
void meta_crtc_info_free (MetaCRTCInfo *info);
void meta_output_info_free (MetaOutputInfo *info);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]