From f8b3fb9776dd78219edaaf9ec18b50813e1c12ae Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sun, 18 Dec 2011 19:22:06 +0100 Subject: [PATCH] Add up_client_tablet_display_is_rotated/present() These functions allow hooking to the status of the rotatable display available in tablet laptops. It is implemented in the linux backend by reading from the input device providing SW_TABLET_MODE. --- libupower-glib/up-client.c | 101 ++++++++++++++++++++++++++++++++++++++++ libupower-glib/up-client.h | 2 + src/linux/up-backend.c | 8 ++- src/linux/up-input.c | 53 ++++++++++++++------- src/linux/up-input.h | 8 +++- src/org.freedesktop.UPower.xml | 20 ++++++++ src/up-daemon.c | 54 +++++++++++++++++++++ src/up-daemon.h | 4 ++ tools/up-tool.c | 22 ++++++--- 9 files changed, 244 insertions(+), 28 deletions(-) diff --git a/libupower-glib/up-client.c b/libupower-glib/up-client.c index 8dccbde..745c463 100644 --- a/libupower-glib/up-client.c +++ b/libupower-glib/up-client.c @@ -66,6 +66,8 @@ struct _UpClientPrivate gboolean lid_is_present; gboolean lid_force_sleep; gboolean is_docked; + gboolean tablet_display_is_present; + gboolean tablet_display_is_rotated; gboolean done_enumerate; }; @@ -90,6 +92,8 @@ enum { PROP_LID_IS_PRESENT, PROP_LID_FORCE_SLEEP, PROP_IS_DOCKED, + PROP_TABLET_DISPLAY_IS_PRESENT, + PROP_TABLET_DISPLAY_IS_ROTATED, PROP_LAST }; @@ -440,6 +444,27 @@ up_client_get_properties_sync (UpClient *client, GCancellable *cancellable, GErr g_object_notify (G_OBJECT(client), "lid-force-sleep"); } + value = g_hash_table_lookup (props, "TabletDisplayIsPresent"); + if (value == NULL) { + g_warning ("No 'TabletDisplayIsPresent' property"); + goto out; + } + ret = g_value_get_boolean (value); + if (ret != client->priv->tablet_display_is_present) { + client->priv->tablet_display_is_present = ret; + g_object_notify (G_OBJECT(client), "tablet-display-is-present"); + } + value = g_hash_table_lookup (props, "TabletDisplayIsRotated"); + if (value == NULL) { + g_warning ("No 'TabletDisplayIsRotated' property"); + goto out; + } + ret = g_value_get_boolean (value); + if (ret != client->priv->tablet_display_is_rotated) { + client->priv->tablet_display_is_rotated = ret; + g_object_notify (G_OBJECT(client), "tablet-display-is-rotated"); + } + /* cached */ client->priv->have_properties = TRUE; @@ -611,6 +636,46 @@ up_client_get_on_low_battery (UpClient *client) return client->priv->on_low_battery; } +/** + * up_client_get_tablet_display_is_present: + * @client: a #UpClient instance + * + * Get whether the system has a tablet laptop rotatable + * display. + * + * Return value: TRUE if the system has a rotatable display + * available. + * + * Since: 0.9.16 + **/ +gboolean +up_client_get_tablet_display_is_present (UpClient *client) +{ + g_return_val_if_fail (UP_IS_CLIENT (client), FALSE); + up_client_get_properties_sync (client, NULL, NULL); + return client->priv->tablet_display_is_present; +} + +/** + * up_client_get_tablet_display_is_rotated: + * @client: a #UpClient instance. + * + * Get whether the system has a tablet laptop display, and + * it is fully rotated and locked. + * + * Return value: TRUE if the screen is rotated, FALSE + * other wise. + * + * Since: 0.9.16 + **/ +gboolean +up_client_get_tablet_display_is_rotated (UpClient *client) +{ + g_return_val_if_fail (UP_IS_CLIENT (client), FALSE); + up_client_get_properties_sync (client, NULL, NULL); + return client->priv->tablet_display_is_rotated; +} + /* * up_client_add: */ @@ -746,6 +811,12 @@ up_client_get_property (GObject *object, case PROP_IS_DOCKED: g_value_set_boolean (value, client->priv->is_docked); break; + case PROP_TABLET_DISPLAY_IS_PRESENT: + g_value_set_boolean (value, client->priv->tablet_display_is_present); + break; + case PROP_TABLET_DISPLAY_IS_ROTATED: + g_value_set_boolean (value, client->priv->tablet_display_is_rotated); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -892,6 +963,36 @@ up_client_class_init (UpClientClass *klass) NULL, FALSE, G_PARAM_READABLE)); + /** + * UpClient:tablet-display-is-present: + * + * If there is a tablet laptop rotatable display + * + * Since: 0.9.16 + */ + g_object_class_install_property (object_class, + PROP_TABLET_DISPLAY_IS_PRESENT, + g_param_spec_boolean ("tablet-display-is-present", + "If there is a tablet " + "laptop rotatable display", + NULL, + FALSE, + G_PARAM_READABLE)); + /** + * UpClient:tablet-display-is-rotated: + * + * If the tablet laptop display is fully rotated and locked + * + * Since: 0.9.16 + */ + g_object_class_install_property (object_class, + PROP_TABLET_DISPLAY_IS_ROTATED, + g_param_spec_boolean ("tablet-display-is-rotated", + "If a tablet laptop display " + "is fully rotated and locked", + NULL, + FALSE, + G_PARAM_READABLE)); /** * UpClient::device-added: diff --git a/libupower-glib/up-client.h b/libupower-glib/up-client.h index 482cd90..0a00916 100644 --- a/libupower-glib/up-client.h +++ b/libupower-glib/up-client.h @@ -109,6 +109,8 @@ gboolean up_client_get_is_docked (UpClient *client); gboolean up_client_get_can_suspend (UpClient *client); gboolean up_client_get_on_battery (UpClient *client); gboolean up_client_get_on_low_battery (UpClient *client); +gboolean up_client_get_tablet_display_is_present (UpClient *client); +gboolean up_client_get_tablet_display_is_rotated (UpClient *client); G_END_DECLS diff --git a/src/linux/up-backend.c b/src/linux/up-backend.c index d126b5b..a891282 100644 --- a/src/linux/up-backend.c +++ b/src/linux/up-backend.c @@ -158,8 +158,12 @@ up_backend_device_new (UpBackend *backend, GUdevDevice *native) goto out; } - /* we now have a lid */ - up_daemon_set_lid_is_present (backend->priv->daemon, TRUE); + if (ret & UP_INPUT_CAPABILITY_LID) { + /* we now have a lid */ + up_daemon_set_lid_is_present (backend->priv->daemon, TRUE); + } else if (ret & UP_INPUT_CAPABILITY_TABLET_MODE) { + up_daemon_set_tablet_display_is_present (backend->priv->daemon, TRUE); + } /* not a power device */ up_device_list_insert (backend->priv->managed_devices, G_OBJECT (native), G_OBJECT (input)); diff --git a/src/linux/up-input.c b/src/linux/up-input.c index a2b887d..685315c 100644 --- a/src/linux/up-input.c +++ b/src/linux/up-input.c @@ -137,8 +137,9 @@ up_input_event_io (GIOChannel *channel, GIOCondition condition, gpointer data) } /* is not lid */ - if (input->priv->event.code != SW_LID) { - g_debug ("not a lid"); + if (input->priv->event.code != SW_LID && + input->priv->event.code != SW_TABLET_MODE) { + g_debug ("not a lid/tablet-mode event"); continue; } @@ -150,7 +151,12 @@ up_input_event_io (GIOChannel *channel, GIOCondition condition, gpointer data) /* are we set */ ret = test_bit (input->priv->event.code, bitmask); - up_daemon_set_lid_is_closed (input->priv->daemon, ret); + + if (input->priv->event.code == SW_LID) { + up_daemon_set_lid_is_closed (input->priv->daemon, ret); + } else if (input->priv->event.code == SW_TABLET_MODE) { + up_daemon_set_tablet_display_is_rotated (input->priv->daemon, ret); + } } out: return TRUE; @@ -159,9 +165,10 @@ out: /** * up_input_coldplug: **/ -gboolean +UpInputCapabilities up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d) { + UpInputCapabilities capabilities = UP_INPUT_CAPABILITY_NONE; gboolean ret = FALSE; gchar *path; gchar *contents = NULL; @@ -199,14 +206,19 @@ up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d) num_bits = up_input_str_to_bitmask (contents, bitmask, sizeof (bitmask)); if ((num_bits == 0) || (num_bits >= SW_CNT)) { g_debug ("invalid bitmask entry for %s", native_path); - ret = FALSE; goto out; } - /* is this a lid? */ - if (!test_bit (SW_LID, bitmask)) { - g_debug ("not a lid: %s", native_path); - ret = FALSE; + if (test_bit (SW_LID, bitmask)) { + capabilities |= UP_INPUT_CAPABILITY_LID; + } + + if (test_bit (SW_TABLET_MODE, bitmask)) { + capabilities |= UP_INPUT_CAPABILITY_TABLET_MODE; + } + + if (capabilities == UP_INPUT_CAPABILITY_NONE) { + g_debug ("not a lid/tablet-mode: %s", native_path); goto out; } @@ -214,7 +226,7 @@ up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d) device_file = g_udev_device_get_device_file (d); if (device_file == NULL || device_file[0] == '\0') { g_debug ("no device file: %s", native_path); - ret = FALSE; + capabilities = UP_INPUT_CAPABILITY_NONE; goto out; } @@ -222,14 +234,14 @@ up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d) input->priv->eventfp = open (device_file, O_RDONLY | O_NONBLOCK); if (input->priv->eventfp <= 0) { g_warning ("cannot open '%s': %s", device_file, strerror (errno)); - ret = FALSE; + capabilities = UP_INPUT_CAPABILITY_NONE; goto out; } /* get initial state */ if (ioctl (input->priv->eventfp, EVIOCGSW(sizeof (bitmask)), bitmask) < 0) { g_warning ("ioctl EVIOCGSW on %s failed", native_path); - ret = FALSE; + capabilities = UP_INPUT_CAPABILITY_NONE; goto out; } @@ -242,7 +254,7 @@ up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d) if (status != G_IO_STATUS_NORMAL) { g_warning ("failed to set encoding: %s", error->message); g_error_free (error); - ret = FALSE; + capabilities = UP_INPUT_CAPABILITY_NONE; goto out; } @@ -252,13 +264,20 @@ up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d) /* watch this */ g_io_add_watch (input->priv->channel, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, up_input_event_io, input); - /* set if we are closed */ - g_debug ("using %s for lid event", native_path); - up_daemon_set_lid_is_closed (input->priv->daemon, test_bit (SW_LID, bitmask)); + if (capabilities & UP_INPUT_CAPABILITY_LID) { + g_debug ("using %s for lid event", native_path); + up_daemon_set_lid_is_closed (input->priv->daemon, + test_bit (SW_LID, bitmask)); + } else if (capabilities & UP_INPUT_CAPABILITY_TABLET_MODE) { + g_debug ("using %s for tablet mode", native_path); + up_daemon_set_tablet_display_is_rotated (input->priv->daemon, + test_bit (SW_TABLET_MODE, bitmask)); + } + out: g_free (path); g_free (contents); - return ret; + return capabilities; } /** diff --git a/src/linux/up-input.h b/src/linux/up-input.h index c42808b..2bd79c7 100644 --- a/src/linux/up-input.h +++ b/src/linux/up-input.h @@ -47,9 +47,15 @@ typedef struct GObjectClass parent_class; } UpInputClass; +typedef enum { + UP_INPUT_CAPABILITY_NONE = 0, + UP_INPUT_CAPABILITY_LID = 1 << 0, + UP_INPUT_CAPABILITY_TABLET_MODE = 1 << 1 +} UpInputCapabilities; + GType up_input_get_type (void); UpInput *up_input_new (void); -gboolean up_input_coldplug (UpInput *input, +UpInputCapabilities up_input_coldplug (UpInput *input, UpDaemon *daemon, GUdevDevice *d); diff --git a/src/org.freedesktop.UPower.xml b/src/org.freedesktop.UPower.xml index a3f0004..ef05791 100644 --- a/src/org.freedesktop.UPower.xml +++ b/src/org.freedesktop.UPower.xml @@ -390,6 +390,26 @@ method return sender=:1.386 -> dest=:1.451 reply_serial=2 + + + + + If there is a tablet laptop rotatable display present. + + + + + + + + + + If the tablet laptop display is fully rotated and locked. + + + + + diff --git a/src/up-daemon.c b/src/up-daemon.c index db02eae..db352c8 100644 --- a/src/up-daemon.c +++ b/src/up-daemon.c @@ -54,6 +54,8 @@ enum PROP_LID_IS_PRESENT, PROP_LID_FORCE_SLEEP, PROP_IS_DOCKED, + PROP_TABLET_DISPLAY_IS_PRESENT, + PROP_TABLET_DISPLAY_IS_ROTATED, PROP_LAST }; @@ -91,6 +93,8 @@ struct UpDaemonPrivate gboolean hibernate_has_encrypted_swap; gboolean during_coldplug; gboolean sent_sleeping_signal; + gboolean tablet_display_is_present; + gboolean tablet_display_is_rotated; guint battery_poll_id; guint battery_poll_count; GTimer *about_to_sleep_timer; @@ -869,6 +873,30 @@ up_daemon_set_on_low_battery (UpDaemon *daemon, gboolean on_low_battery) } /** + * up_daemon_set_tablet_display_is_present: + **/ +void +up_daemon_set_tablet_display_is_present (UpDaemon *daemon, gboolean tablet_display_is_present) +{ + UpDaemonPrivate *priv = daemon->priv; + g_debug ("tablet_display_is_present = %s", tablet_display_is_present ? "yes" : "no"); + priv->tablet_display_is_present = tablet_display_is_present; + g_object_notify (G_OBJECT (daemon), "tablet-display-is-present"); +} + +/** + * up_daemon_set_tablet_display_is_rotated: + **/ +void +up_daemon_set_tablet_display_is_rotated (UpDaemon *daemon, gboolean tablet_display_is_rotated) +{ + UpDaemonPrivate *priv = daemon->priv; + g_debug ("tablet_display_is_rotated = %s", tablet_display_is_rotated ? "yes" : "no"); + priv->tablet_display_is_rotated = tablet_display_is_rotated; + g_object_notify (G_OBJECT (daemon), "tablet-display-is-rotated"); +} + +/** * up_daemon_refresh_battery_devices_cb: **/ static gboolean @@ -1131,6 +1159,10 @@ up_daemon_init (UpDaemon *daemon) G_CALLBACK (up_daemon_properties_changed_cb), daemon); g_signal_connect (daemon, "notify::on-low-battery", G_CALLBACK (up_daemon_properties_changed_cb), daemon); + g_signal_connect (daemon, "notify::tablet-display-is-present", + G_CALLBACK (up_daemon_properties_changed_cb), daemon); + g_signal_connect (daemon, "notify::tablet-display-is-rotated", + G_CALLBACK (up_daemon_properties_changed_cb), daemon); /* check if we have support */ daemon->priv->kernel_can_suspend = up_backend_kernel_can_suspend (daemon->priv->backend); @@ -1215,6 +1247,12 @@ up_daemon_get_property (GObject *object, guint prop_id, GValue *value, GParamSpe case PROP_IS_DOCKED: g_value_set_boolean (value, priv->is_docked); break; + case PROP_TABLET_DISPLAY_IS_PRESENT: + g_value_set_boolean (value, priv->tablet_display_is_present); + break; + case PROP_TABLET_DISPLAY_IS_ROTATED: + g_value_set_boolean (value, priv->tablet_display_is_rotated); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1382,6 +1420,22 @@ up_daemon_class_init (UpDaemonClass *klass) "If the laptop lid is closed", FALSE, G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_TABLET_DISPLAY_IS_PRESENT, + g_param_spec_boolean ("tablet-display-is-present", + "Tablet display is present", + "If there is a tablet " + "laptop rotatable display", + FALSE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_TABLET_DISPLAY_IS_ROTATED, + g_param_spec_boolean ("tablet-display-is-rotated", + "Tablet display is rotated", + "If a tablet laptop display " + "is fully rotated and locked", + FALSE, + G_PARAM_READABLE)); dbus_g_object_type_install_info (UP_TYPE_DAEMON, &dbus_glib_up_daemon_object_info); diff --git a/src/up-daemon.h b/src/up-daemon.h index 6feff2f..a06be09 100644 --- a/src/up-daemon.h +++ b/src/up-daemon.h @@ -87,6 +87,10 @@ void up_daemon_set_on_battery (UpDaemon *daemon, gboolean on_battery); void up_daemon_set_on_low_battery (UpDaemon *daemon, gboolean on_low_battery); +void up_daemon_set_tablet_display_is_present (UpDaemon *daemon, + gboolean tablet_display_is_present); +void up_daemon_set_tablet_display_is_rotated (UpDaemon *daemon, + gboolean tablet_display_is_rotated); /* exported */ gboolean up_daemon_enumerate_devices (UpDaemon *daemon, diff --git a/tools/up-tool.c b/tools/up-tool.c index 9156010..25acd54 100644 --- a/tools/up-tool.c +++ b/tools/up-tool.c @@ -125,6 +125,8 @@ up_client_print (UpClient *client) gboolean lid_is_closed; gboolean lid_is_present; gboolean is_docked; + gboolean tablet_display_is_present; + gboolean tablet_display_is_rotated; g_object_get (client, "daemon-version", &daemon_version, @@ -135,16 +137,20 @@ up_client_print (UpClient *client) "lid-is-closed", &lid_is_closed, "lid-is-present", &lid_is_present, "is-docked", &is_docked, + "tablet-display-is-present", &tablet_display_is_present, + "tablet-display-is-rotated", &tablet_display_is_rotated, NULL); - g_print (" daemon-version: %s\n", daemon_version); - g_print (" can-suspend: %s\n", can_suspend ? "yes" : "no"); - g_print (" can-hibernate %s\n", can_hibernate ? "yes" : "no"); - g_print (" on-battery: %s\n", on_battery ? "yes" : "no"); - g_print (" on-low-battery: %s\n", on_low_battery ? "yes" : "no"); - g_print (" lid-is-closed: %s\n", lid_is_closed ? "yes" : "no"); - g_print (" lid-is-present: %s\n", lid_is_present ? "yes" : "no"); - g_print (" is-docked: %s\n", is_docked ? "yes" : "no"); + g_print (" daemon-version: %s\n", daemon_version); + g_print (" can-suspend: %s\n", can_suspend ? "yes" : "no"); + g_print (" can-hibernate %s\n", can_hibernate ? "yes" : "no"); + g_print (" on-battery: %s\n", on_battery ? "yes" : "no"); + g_print (" on-low-battery: %s\n", on_low_battery ? "yes" : "no"); + g_print (" lid-is-closed: %s\n", lid_is_closed ? "yes" : "no"); + g_print (" lid-is-present: %s\n", lid_is_present ? "yes" : "no"); + g_print (" is-docked: %s\n", is_docked ? "yes" : "no"); + g_print (" tablet-display-is-present: %s\n", tablet_display_is_present ? "yes" : "no"); + g_print (" tablet-display-is-rotated: %s\n", tablet_display_is_rotated ? "yes" : "no"); g_free (daemon_version); } -- 1.7.7.4