File gnome-settings-daemon-bnc461755-randr-rotate-wacom.diff of Package gnome-settings-daemon
diff --git a/ChangeLog b/ChangeLog
index ec6af64..fd47f34 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2009-01-28 Federico Mena Quintero <federico@novell.com>
+
+ https://bugzilla.novell.com/show_bug.cgi?id=461755 - For tablets,
+ call xsetwacom to rotate the stylus when the monitor is rotated.
+
+ This is not really the right way to do things --- the X server
+ should take care of this. In the meantime, we'll offer this
+ option here and in gnome-display-properties from
+ gnome-control-center.
+
+ * data/apps_gnome_settings_daemon_xrandr.schemas.in: New key
+ /apps/gnome_settings_daemon/xrandr/rotate_tablet_with_monitor to
+ select whether the stylus will be rotated when the monitor is
+ rotated. See the key's description for information about why this
+ needs to be an option (it depends on built-in vs. external
+ tablets).
+
+ Sanitize GConf key:
+
+ * plugins/xrandr/gsd-xrandr-manager.c
+ (CONF_KEY_SHOW_NOTIFICATION_ICON): renamed from CONF_KEY.
+ (on_config_changed): Only frob the tray icon if its corresponding
+ GConf key changes.
+
2009-01-27 Federico Mena Quintero <federico@novell.com>
http://bugzilla.gnome.org/show_bug.cgi?id=545115 - Ask for
diff --git a/data/apps_gnome_settings_daemon_xrandr.schemas.in b/data/apps_gnome_settings_daemon_xrandr.schemas.in
index c9f59fd..80324ca 100644
--- a/data/apps_gnome_settings_daemon_xrandr.schemas.in
+++ b/data/apps_gnome_settings_daemon_xrandr.schemas.in
@@ -14,5 +14,30 @@
</long>
</locale>
</schema>
+
+ <schema>
+ <key>/schemas/apps/gnome_settings_daemon/xrandr/rotate_tablet_with_monitor</key>
+ <applyto>/apps/gnome_settings_daemon/xrandr/rotate_tablet_with_monitor</applyto>
+ <owner>gnome</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Rotate pressure-sensitive tablet along with the
+ monitor</short>
+ <long>For internal pressure-sensitive
+ tablets which are part of the display (such as the
+ ones in tablet PCs), you want the tablet's cursor to
+ rotate when the monitor is rotated, so that the
+ orientation of the stylus will match the orientation
+ of the monitor; use "true" in this case. But for
+ external tablets, you may prefer to keep the tablet in
+ the same orientation even if you rotate the monitor;
+ use "false" in this case.
+
+ This option will only be used if the xsetwacom binary
+ is in your PATH.
+ </long>
+ </locale>
+ </schema>
</schemalist>
</gconfschemafile>
diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index d2eba18..911eb1b 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -63,7 +63,8 @@
#define GSD_XRANDR_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_XRANDR_MANAGER, GsdXrandrManagerPrivate))
#define CONF_DIR "/apps/gnome_settings_daemon/xrandr"
-#define CONF_KEY "show_notification_icon"
+#define CONF_KEY_SHOW_NOTIFICATION_ICON (CONF_DIR "/show_notification_icon")
+#define CONF_KEY_ROTATE_TABLET_WITH_MONITOR (CONF_DIR "/rotate_tablet_with_monitor")
#define VIDEO_KEYSYM "XF86Display"
@@ -109,6 +110,147 @@ G_DEFINE_TYPE (GsdXrandrManager, gsd_xrandr_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
+static GnomeRRRotation
+find_rotation_for_tablet (GnomeRRConfig *configuration)
+{
+ int i;
+
+ /* The stupid heuristic is to find the first rotated output, and use its rotation.
+ * The rationale is:
+ *
+ * - If you have a built-in tablet (like a tablet PC), then you want the
+ * stylus to match the built-in monitor's orientation. Your external
+ * monitor has no relationship to your stylus.
+ *
+ * - If you have a single swivel monitor, that's the one which corresponds to
+ * your external tablet.
+ *
+ * - If you have two swivel monitors, well, I want your setup at my home, too.
+ */
+
+ for (i = 0; configuration->outputs[i] != NULL; i++) {
+ GnomeOutputInfo *output;
+
+ output = configuration->outputs[i];
+ if (output->on && output->connected && output->rotation != GNOME_RR_ROTATION_0)
+ return output->rotation;
+ }
+
+ return GNOME_RR_ROTATION_0;
+}
+
+static void
+rotate_tablet (GsdXrandrManager *manager, GnomeRRRotation rotation)
+{
+ char *stdout_str;
+ int status;
+ char *p;
+ char *newline;
+ const char *arg;
+
+ /* We really don't do error checking. If xsetwacom(1) doesn't exist,
+ * well, too bad. Maybe that means that the user doesn't have a tablet.
+ */
+
+ stdout_str = NULL;
+ if (!g_spawn_command_line_sync ("xsetwacom list",
+ &stdout_str,
+ NULL,
+ &status,
+ NULL))
+ goto out;
+
+ if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0 && stdout_str != NULL))
+ goto out;
+
+ switch (rotation) {
+ case GNOME_RR_ROTATION_90:
+ arg = "CW";
+ break;
+
+ case GNOME_RR_ROTATION_180:
+ arg = "HALF";
+ break;
+
+ case GNOME_RR_ROTATION_270:
+ arg = "CCW";
+ break;
+
+ default: /* this also catches GNOME_RR_ROTATION_0 */
+ arg = "NONE";
+ break;
+ }
+
+ for (p = stdout_str; *p != '\0'; p = newline + 1) {
+ char *end;
+ char *device_name;
+ char *command;
+
+ newline = strchr (p, '\n');
+ if (!newline)
+ break;
+
+ *newline = '\0';
+
+ if (!strstr (p, "stylus"))
+ continue;
+
+ device_name = p;
+ for (end = device_name; *end != '\0' && !g_ascii_isspace (*end); end++);
+
+ *end = '\0';
+
+ if (strlen (device_name) == 0)
+ continue;
+
+ command = g_strconcat ("xsetwacom set ", device_name, " Rotate ", arg, NULL);
+ g_spawn_command_line_sync (command, NULL, NULL, NULL, NULL);
+ g_free (command);
+ }
+
+out:
+
+ g_free (stdout_str);
+}
+
+static void
+handle_tablet_rotation (GsdXrandrManager *manager)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ GnomeRRConfig *configuration;
+ GnomeRRRotation rotation;
+
+ if (!gconf_client_get_bool (priv->client, CONF_KEY_ROTATE_TABLET_WITH_MONITOR, NULL)) {
+ rotate_tablet (manager, GNOME_RR_ROTATION_0); /* un-rotate the tablet when the GConf key is turned off */
+ return;
+ }
+
+ /* Re-creating the current configuration is probably not the most
+ * efficient thing, but it should give us an accurate view of the world.
+ */
+ configuration = gnome_rr_config_new_current (priv->rw_screen);
+
+ rotation = find_rotation_for_tablet (configuration);
+
+ gnome_rr_config_free (configuration);
+
+ rotate_tablet (manager, rotation);
+}
+
+static gboolean
+apply_stored_configuration_and_rotate_tablet (GsdXrandrManager *manager, const char *filename, GError **error)
+{
+ struct GsdXrandrManagerPrivate *priv = manager->priv;
+ gboolean success;
+
+ success = gnome_rr_config_apply_from_filename (priv->rw_screen, filename, error);
+
+ if (success)
+ handle_tablet_rotation (manager);
+
+ return success;
+}
+
static void
restore_backup_configuration_without_messages (const char *backup_filename, const char *intended_filename)
{
@@ -119,7 +261,6 @@ restore_backup_configuration_without_messages (const char *backup_filename, cons
static void
restore_backup_configuration (GsdXrandrManager *manager, const char *backup_filename, const char *intended_filename)
{
- struct GsdXrandrManagerPrivate *priv = manager->priv;
int saved_errno;
char *msg;
@@ -127,7 +268,7 @@ restore_backup_configuration (GsdXrandrManager *manager, const char *backup_file
GError *error;
error = NULL;
- if (!gnome_rr_config_apply_from_filename (priv->rw_screen, intended_filename, &error)) {
+ if (!apply_stored_configuration_and_rotate_tablet (manager, intended_filename, &error)) {
error_message (manager, _("Could not restore the display's configuration"), error, NULL);
if (error)
@@ -241,7 +382,6 @@ user_says_things_are_ok (GsdXrandrManager *manager)
static gboolean
try_to_apply_intended_configuration (GsdXrandrManager *manager, GError **error)
{
- struct GsdXrandrManagerPrivate *priv = manager->priv;
char *backup_filename;
char *intended_filename;
gboolean result;
@@ -251,7 +391,7 @@ try_to_apply_intended_configuration (GsdXrandrManager *manager, GError **error)
backup_filename = gnome_rr_config_get_backup_filename ();
intended_filename = gnome_rr_config_get_intended_filename ();
- result = gnome_rr_config_apply_from_filename (priv->rw_screen, intended_filename, error);
+ result = apply_stored_configuration_and_rotate_tablet (manager, intended_filename, error);
if (!result) {
error_message (manager, _("The selected configuration for displays could not be applied"), error ? *error : NULL, NULL);
restore_backup_configuration_without_messages (backup_filename, intended_filename);
@@ -1268,7 +1408,7 @@ status_icon_stop (GsdXrandrManager *manager)
static void
start_or_stop_icon (GsdXrandrManager *manager)
{
- if (gconf_client_get_bool (manager->priv->client, CONF_DIR "/" CONF_KEY, NULL)) {
+ if (gconf_client_get_bool (manager->priv->client, CONF_KEY_SHOW_NOTIFICATION_ICON, NULL)) {
status_icon_start (manager);
}
else {
@@ -1282,7 +1422,10 @@ on_config_changed (GConfClient *client,
GConfEntry *entry,
GsdXrandrManager *manager)
{
- start_or_stop_icon (manager);
+ if (strcmp (entry->key, CONF_KEY_SHOW_NOTIFICATION_ICON) == 0)
+ start_or_stop_icon (manager);
+ else if (strcmp (entry->key, CONF_KEY_ROTATE_TABLET_WITH_MONITOR) == 0)
+ handle_tablet_rotation (manager);
}
static void
@@ -1291,7 +1434,7 @@ apply_intended_configuration (GsdXrandrManager *manager, const char *intended_fi
GError *my_error;
my_error = NULL;
- if (!gnome_rr_config_apply_from_filename (manager->priv->rw_screen, intended_filename, &my_error)) {
+ if (!apply_stored_configuration_and_rotate_tablet (manager, intended_filename, &my_error)) {
if (my_error) {
if (g_error_matches (my_error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG)) {
/* This is not an error; the user probably
@@ -1325,7 +1468,7 @@ apply_stored_configuration_at_startup (GsdXrandrManager *manager)
my_error = NULL;
- success = gnome_rr_config_apply_from_filename (manager->priv->rw_screen, backup_filename, &my_error);
+ success = apply_stored_configuration_and_rotate_tablet (manager, backup_filename, &my_error);
if (success) {
/* The backup configuration existed, and could be applied
* successfully, so we must restore it on top of the