From 0abcdfbc7963fff7ebe4ba267ee6a07ac9281413 Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@novell.com>
Date: Tue, 27 Jan 2009 19:52:50 -0600
Subject: [PATCH 1/6] Add a GConf key to rotate tablets when the monitor rotates

Signed-off-by: Federico Mena Quintero <federico@novell.com>
---
 data/apps_gnome_settings_daemon_xrandr.schemas.in |   25 +++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

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>
-- 
1.6.0.2


From 7e914e4b2812a96be4c7e6a1afd0ac15cc324ab7 Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@novell.com>
Date: Wed, 28 Jan 2009 11:38:37 -0600
Subject: [PATCH 2/6] Change a define for a GConf key name

Signed-off-by: Federico Mena Quintero <federico@novell.com>
---
 plugins/xrandr/gsd-xrandr-manager.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index 50d55ce..d85f5f7 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -63,7 +63,7 @@
 #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 VIDEO_KEYSYM    "XF86Display"
 #define ROTATE_KEYSYM   "XF86RotateWindows"
@@ -1940,7 +1940,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 {
@@ -1954,7 +1954,8 @@ 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);
 }
 
 static void
-- 
1.6.0.2


From 3adbb2125beec207e062b0d9618d05163140efa5 Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@novell.com>
Date: Thu, 29 Jan 2009 18:37:53 -0600
Subject: [PATCH 3/6] Framework to handle the new GConf key to rotate the tablet

Signed-off-by: Federico Mena Quintero <federico@novell.com>
---
 plugins/xrandr/gsd-xrandr-manager.c |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index d85f5f7..144bfd8 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 (CONF_DIR "/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"
 #define ROTATE_KEYSYM   "XF86RotateWindows"
@@ -166,6 +167,12 @@ show_timestamps_dialog (GsdXrandrManager *manager, const char *msg)
 #endif
 }
 
+static void
+handle_tablet_rotation (GsdXrandrManager *manager)
+{
+        /* FMQ: implement */
+}
+
 /* This function centralizes the use of gnome_rr_config_apply_from_filename_with_time().
  *
  * Optionally filters out GNOME_RR_ERROR_NO_MATCHING_CONFIG from
@@ -1956,6 +1963,8 @@ on_config_changed (GConfClient          *client,
 {
         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
-- 
1.6.0.2


From 19e9c480c665f694edb95ff76ac6296dd5bfa650 Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@novell.com>
Date: Thu, 29 Jan 2009 18:42:40 -0600
Subject: [PATCH 4/6] Handle rotation of the tablet every time we apply a RANDR configuration

Signed-off-by: Federico Mena Quintero <federico@novell.com>
---
 plugins/xrandr/gsd-xrandr-manager.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index 144bfd8..b3c0077 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -196,8 +196,10 @@ apply_configuration_from_filename (GsdXrandrManager *manager,
 
         my_error = NULL;
         success = gnome_rr_config_apply_from_filename_with_time (priv->rw_screen, filename, timestamp, &my_error);
-        if (success)
+        if (success) {
+                handle_tablet_rotation (manager);
                 return TRUE;
+        }
 
         if (g_error_matches (my_error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_MATCHING_CONFIG)) {
                 if (no_matching_config_is_an_error)
@@ -234,6 +236,8 @@ apply_configuration_and_display_error (GsdXrandrManager *manager, GnomeRRConfig
                 g_error_free (error);
         }
 
+        handle_tablet_rotation (manager);
+
         return success;
 }
 
-- 
1.6.0.2


From 460b016b82edf567d9110f6200255468a2c8d8ba Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@novell.com>
Date: Mon, 30 Nov 2009 14:41:22 -0600
Subject: [PATCH 5/6] Find the rotation to use for the tablet

Signed-off-by: Federico Mena Quintero <federico@novell.com>
---
 plugins/xrandr/gsd-xrandr-manager.c |   49 ++++++++++++++++++++++++++++++++++-
 1 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index b3c0077..91e269d 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -167,10 +167,57 @@ show_timestamps_dialog (GsdXrandrManager *manager, const char *msg)
 #endif
 }
 
+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
 handle_tablet_rotation (GsdXrandrManager *manager)
 {
-        /* FMQ: implement */
+        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);
 }
 
 /* This function centralizes the use of gnome_rr_config_apply_from_filename_with_time().
-- 
1.6.0.2


From 3a4af57c91f76f1703545236b408a673880075b7 Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@novell.com>
Date: Fri, 30 Jan 2009 13:46:57 -0600
Subject: [PATCH 6/6] Call xsetwacom(1) to rotate the stylus

Signed-off-by: Federico Mena Quintero <federico@novell.com>
---
 plugins/xrandr/gsd-xrandr-manager.c |   74 +++++++++++++++++++++++++++++++++++
 1 files changed, 74 insertions(+), 0 deletions(-)

diff --git a/plugins/xrandr/gsd-xrandr-manager.c b/plugins/xrandr/gsd-xrandr-manager.c
index 91e269d..5bc3d88 100644
--- a/plugins/xrandr/gsd-xrandr-manager.c
+++ b/plugins/xrandr/gsd-xrandr-manager.c
@@ -197,6 +197,80 @@ find_rotation_for_tablet (GnomeRRConfig *configuration)
 }
 
 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;
-- 
1.6.0.2

