Subject: Bug#719: Clone screens for touch-enabled devices

From: Stefan Baur <[email-masked]>
Date: Tue, 06 Jan 2015 15:08:33 +0100

package: x2gothinclient
version: 1.1.0.2
priority: wishlist
Control: tag -1 patch

Hi,

when using a touch-enabled device (like a tablet computer) as a
thinclient, the cursor isn't properly aligned when you try to run a
second display (non-touch-enabled) alongside with it.

What happens is that both displays get attached to form one large
virtual screen, however, your touch-enabled surface obviously still
only covers the primary display.

The X server doesn't understand this, and tries to map your movements
on the primary display to the entire virtual screen surface, so the
further to the side and to the bottom you get, the more off your mouse
pointer will be from the actual position where you touch your primary
display.

  PRI     SEC                 VIRT
+-----+ +-----+            +----------+
|X    | |     |            |O         |
|     | |     |            |          |
|     | |     |            |          |
|     | |     |            |          |
+-----+ +-----+            +----------+

+-----+ +-----+            +----------+
|     | |     |            |          |
|     | |     |            |          |
|   \ | |   / |            |       O  |
|     | |     |            |          |
+-----+ +-----+            +----------+

\ = where you touch
/ = where X draws the cursor in reality
X = overlapping \ and /
O = where X believes the cursor is, on the virtual screen

There's no sensible way to use a touch-enabled device with a second
screen and no additional, external pointing device, so I've added this
patch/workaround that switches to clone mode instead.

Of course, if you give up on using the touchscreen and plug in a USB
mouse or other external pointing device, you could use two screens.
This patch doesn't cover that situation.

Maybe someone else has an idea on what a sensible solution could look
like that covers this as well?  Like, scan for USB HID pointing
devices ("find /dev/input -name "mouse*" | wc -l") and, if present in
addition to a touchscreen, don't clone, but do side-by-side s if no
touch device was detected at all?
Tht might have some additional caveats, though, like the detection
mis-firing if the touch component of a tablet device "cloaks" as mouse
or offers some sort of mouse emulation support.
Also, in that case, it would probably be smart to disable the touch
interface completely so as to not confuse users why their touches
don't align with the cursor.  Does anybody know of a generic way to do
this?

Again, input/suggestions welcome.

- -Stefan

- -- 
BAUR-ITCS UG (haftungsbeschränkt)
Geschäftsführer: Stefan Baur
Eichenäckerweg 10, 89081 Ulm | Registergericht Ulm, HRB 724364
Fon/Fax 0731 40 34 66-36/-35 | USt-IdNr.: DE268653243
--- /usr/sbin/x2gothinclientd.orig      2015-01-06 14:22:52.416278048 +0000
+++ /usr/sbin/x2gothinclientd   2015-01-06 14:38:58.600131472 +0000
@@ -111,16 +111,29 @@
                        # wait for X-Server to come up
                        sleep(3);

-                       # align displays next to each other in order of appearance in xrandr
+                       # Align displays next to each other in order of appearance in xrandr, unless touch
+                       # devices are detected - in that case, clone displays so that touchable area and display
+                       # stay aligned.  This fix has been introduced for a certain make of wacom touch-sensitive
+                       # displays.  If you have a touch-sensitive device that isn't affected by this, or that
+                       # is negatively affected by this fix, please let us know so we can add a better detection.
                        my $this_display;
                        my $next_display;
+                       my $touchdevicescount=`DISPLAY=:0 xsetwacom -d localhost:0.0 --list devices | wc -l`;
+
                        foreach (`DISPLAY=:0 LANG=C xrandr 2>/dev/null | grep ' connected ' | cut -d ' ' -f1`)
                        {
                                $next_display = $_;
                                $next_display =~ s/\n//;
                                if (defined($this_display))
                                {
-                                       `DISPLAY=:0 /usr/bin/xrandr --output $next_display --left-of $this_display`;
+                                       if ($touchdevicescount > 0)
+                                       {
+                                               `DISPLAY=:0 /usr/bin/xrandr --output $next_display --same-as $this_display`;
+                                       }
+                                       else
+                                       {
+                                               `DISPLAY=:0 /usr/bin/xrandr --output $next_display --left-of $this_display`;
+                                       }
                                }
                                $this_display = $next_display;
                        }