<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEMHRno9cCp7ImA9WhBbEEw.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647</id><updated>2013-05-08T21:27:17.468+10:00</updated><category term="workflow" /><category term="synaptics" /><category term="xds" /><category term="mpx" /><category term="tutorial" /><category term="freedesktop.org" /><category term="fedora" /><category term="xkb" /><category term="wacom" /><category term="hal" /><category term="evtest" /><category term="xi2" /><category term="gnome" /><category term="x" /><category term="xorg" /><category term="xts" /><category term="tig" /><category term="configuration" /><category term="git" /><category term="outdoors" /><category term="xorg.conf" /><category term="input device properties" /><category term="compiz" /><category term="gnome-device-setup" /><category term="evdev" /><category term="multitouch" /><category term="xlib" /><title>Who-T</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://who-t.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>129</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Who-t" /><feedburner:info uri="who-t" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DkABQHk4eip7ImA9WhBVEUU.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-7084474253717217623</id><published>2013-04-17T17:45:00.000+10:00</published><updated>2013-04-17T17:45:51.732+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-04-17T17:45:51.732+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>CVE-2013-1940: VT-switched servers receive input from hot-plugged devices</title><content type="html">&lt;p&gt;Rather by accident, Dave Airlie and I found a minor security issue in the X server last week (&lt;a href="https://plus.google.com/104877287288155269055/posts/YqUmH95LTkh"&gt;read the story here&lt;/a&gt;) This issue has been assigned CVE-2013-1940 and is now publicly available. The corresponding bug reports are here: &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=63353"&gt;https://bugs.freedesktop.org/63353&lt;/a&gt; and &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=950438"&gt;https://bugzilla.redhat.com/950438&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;X servers receive notifications from HAL/udev about new input devices, even when you vt-switched to the tty or another server. Input devices added while the server is not the owner of the vt  will be added but not &lt;i&gt;enabled&lt;/i&gt;, so events from such devices are ignored. On vt-switch back, the device is enabled and the fd is added to the select set used by the server. Future events will trigger a SIGIO and will be processed as expected&lt;/p&gt;

&lt;p&gt;
evdev holds the fd open between PreInit and enabling the device. If the device is hot-plugged while the server is vt-switched away events accumulate on the fd. evdev calls xf86FlushInput() to discard these events but a bug in that function made it essentially a noop for evdev devices. Thus, once the server is the VT owner again, events from that device are still on the fd and are  processed whenever the next event comes along on that device.
&lt;/p&gt;

&lt;p&gt;
Reproducer is fairly simple: open a text editor, vt-switch, hotplug a keyboard, type something on that keyboard, vt-switch back and the events will be replayed on the existing server.
&lt;/p&gt;

&lt;p&gt;
This issue is now &lt;a href="http://cgit.freedesktop.org/xorg/xserver/commit/?id=6ca03b9161d33b1d2b55a3a1a913cf88deb2343f"&gt;fixed upstream&lt;/a&gt; and I have released &lt;a href="http://lists.x.org/archives/xorg-announce/2013-April/002199.html"&gt;xserver 1.13.4&lt;/a&gt; and &lt;a href="http://lists.x.org/archives/xorg-announce/2013-April/002200.html"&gt;xserver 1.14.1&lt;/a&gt;. It is of relatively low impact but the fix is easy so I recommend to patch your X servers. 
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/ZfhoROxgPqc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/7084474253717217623/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=7084474253717217623" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7084474253717217623?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7084474253717217623?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/ZfhoROxgPqc/cve-2013-1940-vt-switched-servers.html" title="CVE-2013-1940: VT-switched servers receive input from hot-plugged devices" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2013/04/cve-2013-1940-vt-switched-servers.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UNRXo5cCp7ImA9WhBRE0o.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-5855801169632435026</id><published>2013-03-04T14:28:00.000+10:00</published><updated>2013-03-04T14:28:14.428+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-04T14:28:14.428+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>git branch-tools: some helpers for managing git branches</title><content type="html">&lt;p&gt;I'm using a lot of branches. Almost one per feature or bug, and they add up quickly. Why I'm doing this doesn't matter for this post, but I found it to be a good workflow. The problem with that is of course that after a while I forget which branch was for what, or what branch I worked on three weeks ago. So I started hacking up some git helpers.&lt;/p&gt;

&lt;p&gt;I pushed them to &lt;a href=" https://github.com/whot/git-branch-tools"&gt;https://github.com/whot/git-branch-tools&lt;/a&gt; today, feel free to use them or improve on them.&lt;/p&gt;

&lt;h2&gt;Archiving branches&lt;/h2&gt;
&lt;p&gt;
Some branches are not actively developed anymore but should still be preserved for posterity. These branches are clogging up the branch view.

&lt;pre&gt;git archive-branch mybranch&lt;/pre&gt;

moves &lt;i&gt;mybranch&lt;/i&gt; to &lt;i&gt;archive/2013/mybranch&lt;/i&gt; and tags the current top commit with a message about the branch history. An example &lt;i&gt;git branch&lt;/i&gt; output would look like this now:

&lt;pre&gt;
  ...
  archive/2013/touch-test-libtool-linker-issues
  archive/2013/two-screen-coordinates
  archive/2013/wrong-signal-logging-merge
  archive/2013/xi2-protocol-tests
  archive/2013/xi21-confine-to
  archive/2013/xorg-conf-init-cleanup
  attic
  bugfix/xts-segfault
  devel
  fedora-17-branch
  fedora-rawhide-branch
  for-keith
  high-keycodes
  master
  memleak
* next
  ...
&lt;/pre&gt;

&lt;/p&gt;

&lt;h2&gt;Showing recent branches&lt;/h2&gt;
&lt;p&gt;
Working on many branches can mean you forget which branch you worked on last week, or the week before.

&lt;pre&gt;git recent-branches&lt;/pre&gt;

lists the various branches checked out over the history, including the date and last commit date on that branch.

Example:
&lt;pre&gt;
next                                 4 hours ago    last commit 6 days ago
server-1.13-branch                   4 hours ago    last commit 2 weeks ago
touch-grab-race-condition-56578-v2   3 days ago     last commit 3 days ago
touch-grab-race-condition-56578      4 days ago     last commit 6 days ago      †
bug/xts-segfaults                    6 days ago     last commit 6 days ago      †
master                               6 days ago     last commit 3 weeks ago
for-keith                            10 days ago    last commit 2 weeks ago
memleak                              13 days ago    last commit 2 weeks ago
&lt;/pre&gt;
The output above shows the branch name, last time that branch was checked out, last commit time and a marker that shows up if this branch doesn't exist anymore. There are a few more flags you can pass in too, including git log flags, so play around with it.
&lt;/p&gt;
&lt;h2&gt;Better branch descriptions&lt;/h2&gt;
&lt;p&gt;
Can't remember what branch "fix-race-condition" was? Me neither. That's what

&lt;pre&gt;git branch-description [branchname] [upstream]&lt;/pre&gt;

will tell you. If upstream is given, it'll also show you what has been merged into upstream already (by patch, not by commit). Example again:
&lt;pre&gt;
:: whot@yabbi:~/xorg/xserver (next)&gt; git-branch-description touch-grab-race-condition-56578-v2
Branch       touch-grab-race-condition-56578-v2
Branched:    Thu Feb 14 11:05:48 2013 -0800
Last commit: Fri Mar 1 16:37:49 2013 +1000

Fixes for https://bugs.freedesktop.org/show_bug.cgi?id=56578, second attempt

============================ Unmerged commits =============================
Commits on touch-grab-race-condition-56578-v2 not in next:
68b937046f278d53de14b586dbf7fd5aa7367f59 Xi: return !Success from DeliverTouchEmulatedEvent if we didn't deliver
f8baab8ac32e5abb31bcd1bb4f74e82d40208221 Xi: use a temp variable for the new listener
9cbb956765c7b4f1572ab2100f46504bf6313330 dix: don't set non-exisiting flags on touch events
2a5b3f2f2293f4a428142fffdb1b6e8ffbbb5db0 dix: fix a comment
76e8756545951d7f13ca84a4bd24fe5f367c5de2 Xi: compress two if statements with the same body
61b06226a43839ed75126f9c54d47bc440285e21 dix: update coords for touch events in PlayReleasedEvents
bd1a5423bbb02a349991a52f4997e830a0dc1992 Xi: add a comment to make a condition a bit clearer
78b26498085a7589e1f4d9ac3c21b69dc3227f87 Xi: not having an ownership mask does not mean automatic acceptance
c7271c7e05cdbeb35a3558223f9c2d6544504c4c dix: don't prepend an activated passive grab to the listeners
71ee72c97e459ef76984e6da64e5dab0ce6e4465 Xi: if we delivered a TouchEnd to a passive grab, end it
9b6966187fd0e6fb7ad3c2c1073456d96e3adab0 Xi: if a pointer grabbing listener gets the touch end, the touch is over
5afef18196ce70faec3e94379c3e6d3767660c4a FIXME: Xi: fix lookup in ActivateEarlyAccept
3784283be1f482a0f039f2eb790c0c8c2cc4bedb Xi: update the core listener state if we delivered the event
3570ef1244c87aef92db97df6e2b921529ffb75a Xi: if a passive async grab is activated from an emulated touch, accept
9bef901d8e28d48f43da3167219b02ad1dba27d8 Xi: save state for early acceptance
7d51022becd5af124896817030a10eedf7f1783a Xi: when punting to a new owner, always create TouchEnd events
4775cdb0d9a2513edcf27a9c4c1916e8213c397b Xi: use public.processInputProc to replay the touch history
431b128b9138af7a208b63d4eb5b917d94c08129 Xi: Don't emit a TouchEnd event to a frozen device
4126d64f6a40d5568b2d1412d519325c02786c9a dix: AllowSome is equivalent to TouchAccept
33421e91a52be91d7121c7c2146ff7bb53bea638 dix: move EmitTouchEnd to touch.c
54f8884aef275b15f2c42e3350e2b4968124af01 dix: XAllowEvents() on a touch event means accepting it

Commits on touch-grab-race-condition-56578-v2 already merged to next:

================================= Activity =================================
e7b4b83 HEAD@{5 hours ago}: checkout: moving from touch-grab-race-condition-56578-v2 to server-1.13-branch
9cbb956 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 9cbb956
d58ddeb HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to d58ddeb
7c3968b HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 7c3968b
a354dd8 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to a354dd8
fdf4869 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to fdf4869
82be6b2 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 82be6b2
82be6b2 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 82be6b2
68b9370 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 68b9370
151eff1 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 151eff1
57fa0b9 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 57fa0b9
b43e866 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to b43e866
ef6a120 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to ef6a120
9064294 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 90642948cc78834d95f7a3bddaac7ff77b68ed7e
9064294 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 90642948cc78834d95f7a3bddaac7ff77b68ed7e
6513e0e HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 6513e0e
0d60ba6 HEAD@{3 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba6
dd23302 HEAD@{4 days ago}: checkout: moving from f21354da571dcd39ae1423388298d5c61d3e736d to touch-grab-race-condition-56578-v2
f21354d HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to f21354da571dcd39ae1423388298d5c61d3e736d
0d60ba6 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba6
ae2cac9 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to ae2cac99a75917d6c4d34b8aa4aeaec0b5d32da7
c2b3d37 HEAD@{4 days ago}: checkout: moving from d75925b9fb8b24c8134b5082294e82abf83294af to touch-grab-race-condition-56578-v2
0d60ba6 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba683e7e95049c01ac5dba48a2f5fd80d9b9
c2b3d37 HEAD@{4 days ago}: checkout: moving from 0d60ba683e7e95049c01ac5dba48a2f5fd80d9b9 to touch-grab-race-condition-56578-v2
0d60ba6 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 0d60ba683e7e95049c01ac5dba48a2f5fd80d9b9
0d60ba6 HEAD@{4 days ago}: checkout: moving from 90642948cc78834d95f7a3bddaac7ff77b68ed7e to touch-grab-race-condition-56578-v2
9064294 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 90642948cc78834d95f7a3bddaac7ff77b68ed7e
8e5adb4 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578-v2 to 8e5adb4ef8bafa2a3188e69409e2908f80288311
033b932 HEAD@{4 days ago}: checkout: moving from touch-grab-race-condition-56578 to touch-grab-race-condition-56578-v2

&lt;/pre&gt;
And install the &lt;b&gt;git-post-checkout-nagging-hook&lt;/b&gt; as your &lt;i&gt;.git/hooks/post-checkout&lt;/i&gt; to make sure you get reminded to set the branch description.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/fcIF7bqIWbY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/5855801169632435026/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=5855801169632435026" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/5855801169632435026?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/5855801169632435026?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/fcIF7bqIWbY/git-branch-tools-some-helpers-for.html" title="git branch-tools: some helpers for managing git branches" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://who-t.blogspot.com/2013/03/git-branch-tools-some-helpers-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAMRnc_fip7ImA9WhNaEE8.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-2578923774678781560</id><published>2013-01-24T20:53:00.000+10:00</published><updated>2013-01-24T20:53:07.946+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-24T20:53:07.946+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>How to move a cursor</title><content type="html">&lt;p&gt;So you thought moving a pointer/cursor on-screen is simple? Well... no.&lt;/p&gt;

&lt;p&gt;Having recently spent a day fixing up &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=31636"&gt;freedesktop Bug 31636&lt;/a&gt;, I figured maybe I should take you on a journey that starts with naïveté and ends in insanity. Just like Twilight.&lt;/p&gt;

&lt;p&gt;
What is actually needed to move a pointer on the screen?
Move your mouse. The driver submits two relative coordinates to the server and expects the pointer to move. So we take the coordinates, add it to the last known coordinates and we're done.
&lt;/p&gt;

&lt;p&gt;
A 1:1 movement of course only works for slow mouse movements. For larger deltas, we need to accelerate the pointer movement so we can easily cover larger distances on the screen. So we look at the timestamps of the events, their delta movements and use that to calculate some factor. This factor is applied to the latest deltas and then decides the actual movement.&lt;br/&gt;
&lt;/p&gt;

&lt;p&gt;
Now we've pretty much covered traditional mice. Many devices however are absolute input devices. They don't use delta coordinates, they just give us the absolute position of the pointer. However, that position is not in pixels but some device coordinate system. So we need to remember the axis ranges and scale from the device coordinate system into the screen coordinate system.
&lt;/p&gt;

&lt;p&gt;
Many users have more than one screen. Two or more screens, when not in mirrored mode, create a desktop that is larger than each single screen. For absolute devices, we map the device to the desktop coordinates so that each edge of the device maps to the corresponding edge on the desktop. Absolute events from such a device must be first mapped to desktop coordinates. From those coordinates we can gather the screen the pointer is to be on and clip the coordinates back to the per-screen coordinates to draw the visible cursor. For relative devices the process is somewhat similar, we add movement to the desktop coordinates, then clip back to per-screen for updates.
&lt;/p&gt;

&lt;p&gt;
All of the above is pretty standard and doesn't require any X specifics. Let's get into what the X11 protocol requires.
&lt;/p&gt;

&lt;p&gt;
evdev has a calibration feature that allows a device to be adjusted for differences in the actual vs. announced coordinates. This is needed when a device real axis ranges are actually different to what the device announces. For example, a device may claim that the axis starts at 0, but really the first value you get out of it is e.g. 50.
For historical reasons we cannot change the device axes once they are set up though. So evdev's calibration scales from the calibrated device range (e.g. 50-950) into the actual announced device range (0-1000). That scaled coordinate is then posted to the server. The wacom driver has a similar feature (called Area).
&lt;/p&gt;

&lt;p&gt;
The X Input Extensions (XI) provides so-called "valuators" (== axes) to the clients as part of the various input events. Valuators 0 and 1 are x and y. XI requires valuator data to be in absolute device coordinates, but those are per protocol screen. In old-style multi-monitor setups with two Section Device entries in the xorg.conf, you have more than one protocol screen. The device itself however is still mapped to the whole desktop. So we convert device coordinates to desktop coordinates, then to screen coordinates on the current screen, and then that position is converted back into device coordinates. Bonus points for considering what happens in a setup with three monitors but only two protocol screens
&lt;/p&gt;

&lt;p&gt;
If you kept counting, you should be up to 5 coordinate systems now:
&lt;ol&gt;
&lt;li&gt;device coordinate system&lt;/li&gt;
&lt;li&gt;adjusted device coordinate system after calibration is applied&lt;/li&gt;
&lt;li&gt;desktop-wide coordinate system&lt;/li&gt;
&lt;li&gt;per-screen coordinate system&lt;/li&gt;
&lt;li&gt;per-screen device coordinate system&lt;/li&gt;
&lt;/ol&gt;
Yep, that's right. A coordinate from an absolute input device passes through all 5 before the pointer position is defined and the data can be appended to the event. And that happens on every single pointer event. Compare this to a relative event, which has four steps:
&lt;ol&gt;
&lt;li&gt;relative coordinates&lt;/li&gt;
&lt;li&gt;device-specific acceleration&lt;/li&gt;
&lt;li&gt;desktop-wide coordinate system&lt;/li&gt;
&lt;li&gt;per-screen coordinate system&lt;/li&gt;
&lt;/ol&gt;
The bug that triggered this blog post was an actual use-case. If an absolute device is used in relative mode, the coordinates were still applied according to the device coordinate range. Thus, relative motion on the device was dependent on the desktop dimensions and attaching a second monitor would increase movement in one axes but not the other. To avoid this, we have an extra layer of scaling, where we pre-scale the coordinates first. That scaling is then undone by the second conversion into desktop coordinates. Whoopee.
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/H3nJQGu1Aig" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/2578923774678781560/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=2578923774678781560" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2578923774678781560?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2578923774678781560?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/H3nJQGu1Aig/how-to-move-cursor.html" title="How to move a cursor" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://who-t.blogspot.com/2013/01/how-to-move-cursor.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEDQnk4fCp7ImA9WhBRFkw.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-4983428319961846535</id><published>2013-01-24T13:45:00.001+10:00</published><updated>2013-03-07T10:54:33.734+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-07T10:54:33.734+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xi2" /><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>Proposed XI2.3 addition: XIGetSupportedVersion</title><content type="html">&lt;p&gt;&lt;b&gt;Update March 7 2013: This addition was not merged into XI 2.3, largely because there is no real need for it. XI 1.x' XGetExtensionVersion() returns the server version without locking in a client version and at this point there was no perceived need for getting the already-requested client version back.&lt;/b&gt;
I'll leave this here for archival purposes but again, this request was &lt;b&gt;not&lt;/b&gt; merged into XI 2.3
&lt;/p&gt;

&lt;h2&gt;Original post below&lt;/h2&gt;

&lt;p&gt;Posting this here too to get a bit more exposure.&lt;/p&gt;

&lt;p&gt;XIQueryVersion(3) is the first XI2 request clients should send to the server. The client announces its supported version and in return receives the server version (which is always less or equal to the client, never higher).&lt;/p&gt;

&lt;p&gt;
As XI 2.1 - 2.3 progressed, we started using this information in the server. Clients are treated slightly differently depending on their announced version. The current differences are:
&lt;ul&gt;
&lt;li&gt;XIQueryPointer will not set the button 1 mask for pointer-emulated events if the  client supports XI 2.2 or newer.&lt;/li&gt;
&lt;li&gt;XIAllowEvents will allow XIRejectTouch and XIAcceptTouch for clients supporting XI 2.2 or newer.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://who-t.blogspot.com.au/2011/09/whats-new-in-xi-21-raw-events.html"&gt;Raw event delivery&lt;/a&gt; changes if a client supports XI 2.1 or newer.&lt;/li&gt;
&lt;/ul&gt;
The client can issue multiple XIQueryVersion requests, but they need to have the same version numbers to provide for consistent server behaviour.
&lt;/p&gt;

&lt;p&gt;
So far, so good.  This works fine as long as the client supports one specific version. However, as toolkits like GTK have come to support XI2, the requirements changed a bit. An application and its toolkit usually look like a single client to the server. However, the client may support XI 2.0, but the toolkit may support XI 2.3. And neither knows of the other's version support. If the client requests XIQueryVersion before the toolkit, the toolkit is locked into the client version. But if the toolkit first requests XIQueryVersion, the client is locked into the version supported by the toolkit. Worst case the client may get a BadValue and quit because it may not be built for this case.
&lt;/p&gt;

&lt;p&gt;
Jasper St. Pierre and Owen Taylor brought this up on #xorg-devel today, and I've send a &lt;a href="http://lists.x.org/archives/xorg-devel/2013-January/035232.html"&gt;proposed solution&lt;/a&gt; to the mailing list.
&lt;/p&gt;
&lt;p&gt;
A new XIGetSupportedVersion request simply returns the server's major/minor version number. Uncapped, so really what the server supports. And the same request also returns the client version previously announced with XIQueryVersion. Or zero, if the client hasn't called it yet.
&lt;/p&gt;
&lt;p&gt;
This request enables toolkits to query what the client has already set, and of course what the server supports without modifying the client state. The request is currently an RFC, but I do hope we may get this into XI 2.3. 
&lt;/p&gt;

&lt;p&gt;
If you're working on XI2-aware clients or toolkits and you have a use-case that requires this or would break by this addition, please speak up now.
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/guXs_I7-eig" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/4983428319961846535/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=4983428319961846535" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/4983428319961846535?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/4983428319961846535?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/guXs_I7-eig/proposed-xi23-addition.html" title="Proposed XI2.3 addition: XIGetSupportedVersion" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2013/01/proposed-xi23-addition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UGQ3Y_fSp7ImA9WhNUEUU.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-1804914165336029900</id><published>2013-01-02T13:21:00.000+10:00</published><updated>2013-01-03T15:00:22.845+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-03T15:00:22.845+10:00</app:edited><title>Getting rid of the GNOME "Oh No! Something has gone wrong." dialog</title><content type="html">&lt;p&gt;In some error cases, GNOME will display a full-screen window with only a single button. The window claims that "Oh no!  Something has gone wrong." and "A problem has occurred and the system can't recover. Please log out and try again." The button merely allows a user to log-out and thus quit the current session. Killing that window with xkill also quits the session.
&lt;/p&gt;&lt;p&gt;
Most of the crashes I get is from experimental code crashing gnome-settings-daemon. Certainly not something fatal, certainly not something that should prevent me from continuing to work in my current session. After all, the menu key still works, the hot corner works, everything works, but closing the dialog will throw me out of my session. And because that pesky dialog is always on-top, I'm down to one monitor. Luckily, the dialog can be disabled.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update Jan 3: As Jasper points out in the comments, Alt+F4 will close the window. Though I tried Ctrl+W and Ctrl+Q, I haven't used Alt+F4 in ages. Sometimes the right solution is so much simpler :)&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;
The dialog is displayed by &lt;a href="http://git.gnome.org/browse/gnome-session/"&gt;gnome-session&lt;/a&gt; and it's named the &lt;a href="http://www.nytimes.com/2009/02/15/magazine/15wwln_consumed-t.html"&gt;fail whale&lt;/a&gt; (&lt;a href="http://git.gnome.org/browse/gnome-session/tree/gnome-session/gsm-fail-whale-dialog.c"&gt;code&lt;/a&gt;). It's &lt;a href="http://git.gnome.org/browse/gnome-session/tree/gnome-session/gsm-manager.c#n291"&gt;triggered only for required apps&lt;/a&gt; and those can be configured.

&lt;pre&gt;
$ cat /usr/share/gnome-session/sessions/gnome.session | grep Required
RequiredComponents=gnome-shell;gnome-settings-daemon;
&lt;/pre&gt;

Drop g-s-d from the required components, restart the session, and you won't see the error anymore. Try it by sending SIGABRT to g-s-d. 

&lt;pre&gt;
$ kill -ABRT `pidof gnome-settings-daemon`
&lt;/pre&gt;

Doing so twice (g-s-d restarts once) will trigger the error unless g-s-d is dropped from the required components.
&lt;/p&gt;&lt;p&gt;
It should go without saying, but the above will only display the &lt;b&gt;error message&lt;/b&gt;, it won't fix the actual error that causes the message to be displayed. 
&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/vP980AIGL0Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/1804914165336029900/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=1804914165336029900" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/1804914165336029900?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/1804914165336029900?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/vP980AIGL0Q/getting-rid-of-gnome-oh-no-something.html" title="Getting rid of the GNOME &quot;Oh No! Something has gone wrong.&quot; dialog" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://who-t.blogspot.com/2013/01/getting-rid-of-gnome-oh-no-something.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAMQH09cCp7ImA9WhBRFkw.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-8564951734910620801</id><published>2012-12-10T12:55:00.000+10:00</published><updated>2013-03-07T10:56:21.368+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-03-07T10:56:21.368+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xi2" /><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>What's new in XI 2.3 - Pointer Barrier events and barrier releases</title><content type="html">&lt;small&gt;Update 7 March 2013: XI 2.3 is released, amend accordingly&lt;/small&gt;

&lt;p&gt;The main feature making up XI 2.3 is Pointer Barrier events. This feature was initiated by 
&lt;a href="https://launchpad.net/~raof"&gt;Chris Halse-Rogers&lt;/a&gt; and then taken up by &lt;a href="http://blog.mecheye.net/author/jstpierre/"&gt;Jasper St. Pierre&lt;/a&gt; and me, until it became part of XI 2.3.&lt;/p&gt;

&lt;p&gt;The usual conditions apply: a client must announce XI2.3 support with the XIQueryVersion() request to utilise any of the below.&lt;/p&gt;

&lt;h2&gt;Pointer barriers&lt;/h2&gt;
&lt;p&gt;Pointer Barriers are an &lt;a href="http://cgit.freedesktop.org/xorg/proto/fixesproto/plain/fixesproto.txt"&gt;XFixes v5.0&lt;/a&gt; additions to restrict pointer movement. They were first available in server 1.11 (released Aug 2011). A pointer barrier is created by a client along a specific horizontal or vertical line of pixels. Relative input devices such as mice or touchpads will be constrained by this barrier, preventing the cursor from moving across the barrier.
&lt;/p&gt;
&lt;p&gt;
For example, GNOME3 creates a vertical barrier on the top-left screen edge. In a multi-monitor screen, flicking the pointer up to the Activities menu will constrain the pointer there even if there is a screen to the left of the menu. This makes the menu much easier to hit.&lt;/p&gt;
&lt;p&gt;
The client can choose for the barrier to be transparent in specific directions. GNOME3's pointer barrier is permissive in the direction of positive X (i.e. left-to-right). Thus, moving from the left screen to the right is unrestricted, even though the pointer is constrained when moving in the other direction.
&lt;/p&gt;

&lt;p&gt;
A simple client that creates a vertical pointer barrier looks like this:
&lt;pre&gt;
Display *dpy = XOpenDisplay(NULL);
int fixes_opcode, fixes_event_base, fixes_error_base;
PointerBarrier barrier;

if (!XQueryExtension(dpy, "XFIXES",
                     &amp;fixes_opcode,
                     &amp;fixes_event_base,
                     &amp;fixes_error_base))
    return EXIT_FAILURE;

/* vertical barrier from 20/20 to 20/100 */
barrier = XFixesCreatePointerBarrier(dpy, DefaultRootWindow(dpy),
                                     20, 20,
                                     20, 100,
                                     0, /* block in all directions */
                                     0, NULL); /* no per-device barriers */

mainloop();

&lt;/pre&gt;
The above code will set up a barrier for all devices, blocking in all
directions.
&lt;/p&gt;

&lt;h2&gt;Pointer barrier events&lt;/h2&gt;
&lt;p&gt;
As of XI 2.3, pointer barrier events are sent to clients when pointer movement is constrained by a barrier, provided that client created pointer barriers, the clients have the matching event mask set. Two new event types were added, &lt;b&gt;XI_BarrierHit&lt;/b&gt; and &lt;b&gt;XI_BarrierLeave&lt;/b&gt;. Both events are only sent to clients owning a barrier and are only sent to the window used to create the barrier (the root window in the example above). 
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
unsigned char m[XIMaskLen(XI_BarrierLeave)] = {0};
XIEventMask mask;
mask.deviceid = XIAllMasterDevices;
mask.mask_len = XIMaskLen(XI_BarrierLeave);
mask.mask = m;

XISetMask(mask.mask, XI_BarrierHit);
XISetMask(mask.mask, XI_BarrierLeave);
XISelectEvents(dpy, DefaultRootWindow(dpy), &amp;mask, 1);
XSync(dpy, False);

while (1) {
    XEvent ev;
    XNextEvent(dpy, &amp;ev);
    if (ev.type != GenericEvent || ev.xcookie.extension != xi2_opcode)
       continue;

    XGetEventData(dpy, &amp;ev.xcookie);
    XIBarrierEvent *b = ev.xcookie.data;
    if (b-&gt;evtype == XI_BarrierHit)
       printf("Pointer hit the barrier\n");
    else if (b-&gt;evtype == XI_BarrierLeave)
       printf("Pointer left the barrier\n");
    
    XFreeEventData(dpy, &amp;ev.xcookie);
}

&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;An XI_BarrierHit event is first sent when the pointer movement is first
constrained by a barrier. It includes some information such as the device,
the barrier and the window. It also includes coordinate data.&lt;/p&gt;
&lt;p&gt;XI_BarrierHit events are sent for each movement of the pointer against this barrier, or along it, until the pointer finally moves away from the barrier again. "Moving away" means a move to different position that is not blocked by the barrier.
&lt;ul&gt;
&lt;li&gt;if the barrier is vertical, the pointer moves to a different X axis value, or&lt;/li&gt;
&lt;li&gt;if the barrier is horizontal, the pointer moves to a different Y axis value, or&lt;/li&gt;
&lt;li&gt;the pointer moves &lt;i&gt;past&lt;/i&gt; the barrier's end point&lt;/li&gt;
&lt;/ul&gt;
Once the pointer does move away, a XI_BarrierLeave event is sent.
A pointer that moves against a barrier, pushes against it for 3
more events and then pulls back will thus generate 4 XI_BarrierHit events and
one XI_BarrierLeave event.&lt;/p&gt;
&lt;p&gt;
Who gets events? Always the client that created the barrier, and only if the
window has the event mask set. If the client has a grab on the device with
the grab_window being the barrier window, the barrier events follow the
usual grab event mask behaviour:
&lt;ul&gt;
&lt;li&gt;if the grab event mask has XI_BarrierHit set, the event is delivered&lt;/li&gt;
&lt;li&gt;if the grab event mask does not have XI_BarrierHit set but the window
mask does &lt;i&gt;and&lt;/i&gt; owner_events is True, the event is delivered&lt;/li&gt;
&lt;li&gt;if owner_events is False and the grab mask does not have
XI_BarrierHit set, no event is sent&lt;/li&gt;
&lt;/ul&gt;
The above applies to XI_BarrierLeave events as well.
&lt;/p&gt;
&lt;p&gt;
If the client's grab has a grab_window different to the barrier window, or
the device is grabbed by another client, event delivery is as usual. In all
cases, if the device is grabbed, the XIBarrierDeviceIsGrabbed flag is set.
Clients should use this flag to determine what to do. For example, the
barrier that is used to trigger the GNOME overlay should probably not
trigger if another client has a grab as it may interfere with drag-and-drop.
&lt;/p&gt;

&lt;h3&gt;Coordinates and time in pointer barrier events&lt;/h3&gt;
&lt;p&gt;
Barrier events contain two sets of x/y coordinates. First, the root
coordinates which represent the position of the pointer after being confined
by barrier (and screen extents, where applicable). This coordinate is the
same you would get from a subsequent XIQueryPointer request.
&lt;/p&gt;
&lt;p&gt;
The second set are the delta coordinates (dx/dy), in screen coordinates, from the last pointer position, &lt;i&gt;had the barrier not constrained it&lt;/i&gt;. So you can calculate how much the pointer would have moved and thus derive speed. The dtime field in the event helps you to calculate speed, it provides the time in milliseconds since the last pointer event. The deltas are calculated after taking pointer acceleration into account.
&lt;pre&gt;
    XIBarrierEvent *b = ev.xcookie.data;
    double dx, dy;
    double speed;
    unsigned int millis;

    dx = b-&gt;dx;
    dy = b-&gt;dy;
    millis = b-&gt;dtime;

    speed = sqrt(dx * dx + dy * dy) / millis * 1000;

    printf("Barrier was hit at %.2f/%.2f at %.2f pixels/sec\n",
           b-&gt;root_x, b-&gt;root_y,  speed);
&lt;/pre&gt;
&lt;/p&gt;
&lt;h2&gt;Releasing a pointer from barrier constraints&lt;/h2&gt;
&lt;p&gt;
By default, a pointer barrier blocks all movement of relative input devices
across a barrier. However, a client can opt to temporarily release the
pointer from the barrier constraints with the XIBarrierReleasePointer request.
&lt;/p&gt;
&lt;p&gt;
To do so, the client needs the event ID of the barrier event. Since a pointer may bump against the same barrier multiple times before the client reacts (X is asynchronous, after all), the event ID serves to identify a set of movements against or along the pointer barrier.&lt;/p&gt;
&lt;p&gt;An event ID is assigned to the first XI_BarrierHit event, and then it remains
the same until the XI_BarrierLeave event. This event is the
last event with the current event ID, any future barrier events will have a
new event ID.
This approach may be familiar to you from dealing with touch
events, that use a similar approach (touch IDs start at TouchBegin and are
tracked through to the TouchEnd).
&lt;/p&gt;
&lt;p&gt;
To release a pointer and let it pass through the barrier, call XIBarrierReleasePointer().
&lt;pre&gt;
    XIBarrierEvent *b = ev.xcookie.data;
    ...
    if (speed &gt; 200) {
        printf("Movement exceeds speed limit, allowing pointer to go through\n")
        XIBarrierReleasePointer(dpy, b-&gt;deviceid, b-&gt;barrier, b-&gt;eventid);
        XFlush(dpy);
    }
&lt;/pre&gt;
If, when the request arrives at the server, the pointer is still trapped by the barrier, the barrier is now transparent and the pointer can move through it &lt;i&gt;with the next movement&lt;/i&gt;. If the pointer moves away from the barrier after releasing it and later moves against this barrier again, it will be constrained once more (albeit with a different eventid). Likewise, if the pointer has already moved away and against the barrier again before the client reacted, the release request has no effect.
&lt;/p&gt;
&lt;p&gt;If the release does succeed and the pointer moves through the barrier, the client gets a XI_BarrierLeave event with the XIBarrierPointerReleased flag.&lt;/p&gt;

&lt;h2&gt;The pointer barrier hit-box&lt;/h2&gt;
&lt;p&gt;
As mentioned above, a XI_BarrierLeave event is sent when the pointer moves away from the barrier. This would usually require a 1 pixel movement (let's ignore subpixel-movement, our hand's aren't that precise). However, during testing we found that 1 px pointer-movement can still happen even when a user tries hart to move along the barrier, or even when pushing against the barrier. Thus, we implemented a hit-box of 2 pixels. Thus, a 1 px movement along the barrier still counts as hitting the barrier, and the pointer is not treated as having left the barrier until it leaves the hit-box.
&lt;/p&gt;
&lt;h2&gt;Testing the current state&lt;/h2&gt;
&lt;p&gt;
The current code is available in the &lt;i&gt;barriers&lt;/i&gt; branch of the following repositories:
&lt;pre&gt;
git://people.freedesktop.org/~whot/inputproto.git 
git://people.freedesktop.org/~whot/libXi.git 
git://people.freedesktop.org/~whot/xserver.git 
&lt;/pre&gt;
An example program to test the feature is available &lt;a href="http://people.freedesktop.org/~whot/xi2-recipes/pointer-barriers-interactive.c"&gt;here&lt;/a&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/a5W-C4vA7UU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/8564951734910620801/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=8564951734910620801" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8564951734910620801?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8564951734910620801?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/a5W-C4vA7UU/whats-new-in-xi-23-pointer-barrier.html" title="What's new in XI 2.3 - Pointer Barrier events and barrier releases" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/12/whats-new-in-xi-23-pointer-barrier.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIBSXo4eCp7ImA9WhNXFk0.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-6468396000089593389</id><published>2012-12-04T16:29:00.000+10:00</published><updated>2012-12-04T16:29:18.430+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-12-04T16:29:18.430+10:00</app:edited><title>Two magic words - "I think"</title><content type="html">&lt;p&gt;We live in a world of absolutes. Water is wet, taxes are annoying, death is certain, it's always beer o'clock somewhere and the world is going to end somewhen later this year (which makes this post doubly futile, but what the hell). Hard to dispute any of those.&lt;/p&gt;

&lt;p&gt;We also live in a world of non-absolutes. You may be freezing when someone right next to you is hot. You may be enjoying a movie when the person you dragged into the theatre is wishing for stronger teeth to gnaw through that wrist. Saying "it's cold" or "this movie is awesome" is going to be met with disagreement&lt;/p&gt;

&lt;p&gt;What does that have to do with software development? We tend to be so convinced of ourselves that we take our personal opinion or experience as absolutes. It's acceptable to say "it's broken" when the application crashes once you start typing. But to say "it's broken" because it doesn't work as &lt;i&gt;you&lt;/i&gt; expected is bad.
&lt;/p&gt;

&lt;p&gt;
Such a statement kills the climate of any conversation. If you tell me that something "is broken", "is completely borked", "is idiotic", or any of those you're achieving one thing: You're putting me on the defence, and quite offensively so. After all, how could I have possibly written, approved, applied something that's so clearly wrong? That makes me uncomfortable. So I'll likely attack back because all &lt;i&gt;I&lt;/i&gt; need to do now is find &lt;b&gt;one&lt;/b&gt; example that proves you wrong. And that's usually quite easy. But at that point it's unlikely a decent conversation will ensue.&lt;/p&gt;

&lt;p&gt;
Worse, if you keep doing that at some point I'll stop listening because someone who makes false statements all the time should be in politics or advertising, but not involved with FOSS.
&lt;/p&gt;

&lt;p&gt;
So now let's try the same again with those magic words: "I think this is completely broken". Well, now you've changed it from an absolute statement to an expression of your opinion. So my task is now to convince you to reconsider your opinion. I'm not on the defence, and the result is that in the worst case we'll agree to disagree - without that awkward absolute statement in the room.
&lt;/p&gt;

&lt;p&gt;A few examples:
&lt;ul&gt;
&lt;li&gt;"Nobody needs this" vs. "I don't think anybody needs this"&lt;/li&gt;
&lt;li&gt;"The application must not do this" vs "I think the application must not do this"&lt;/li&gt;
&lt;li&gt;"Wearing underpants is wrong" vs "I think wearing underpants is wrong"&lt;/li&gt;
&lt;li&gt;"Bananas must be peeled from the bottom" vs "I think bananas must be peeled from the bottom"&lt;/li&gt;
&lt;/ul&gt;
Did you notice any differences? Any of the "I think" can be quite simply countered with "I don't think so" (especially the third one, please) and all you'd have is a discussion of two people with differing viewpoints. Even re-reading these examples my reaction to the first is automatically "WTF?", but the reaction to the "I think" alternatives is a conversational "nah, mate".
&lt;/p&gt;

&lt;p&gt;
So next time you're not happy about something: just prefix your criticism with "I think". You may be surprised what difference it makes to the conversation.
&lt;/p&gt;

&lt;p&gt;
Oh, two other magic words: "for me". Compare "This workflow is completely broken" vs "This workflow is completely broken for me". Amazing what difference those two words make...
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/JBdsd-12oOo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/6468396000089593389/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=6468396000089593389" title="10 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/6468396000089593389?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/6468396000089593389?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/JBdsd-12oOo/two-magic-words-i-think.html" title="Two magic words - &quot;I think&quot;" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>10</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/12/two-magic-words-i-think.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AERXkyfyp7ImA9WhNXEUs.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-9077780113158781309</id><published>2012-11-29T16:15:00.000+10:00</published><updated>2012-11-29T16:15:04.797+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-11-29T16:15:04.797+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>X.Org integration test suite - part 2, the registry</title><content type="html">&lt;p&gt;Back in August, I wrote about the &lt;a href="http://who-t.blogspot.com.au/2012/08/xorg-integration-test-suite.html"&gt;X.Org Integration Test suite&lt;/a&gt;, in short XIT. Since then I've been quite busy adding tests to it, expanding it and fixing the odd bug. &lt;a href="http://blog.mecheye.net/author/jstpierre/"&gt;Jasper St. Pierre&lt;/a&gt; has been writing tests against it for the new pointer barrier features, making that feature probably the first to get full, repeatable testing before merging.
&lt;/p&gt;&lt;p&gt;
Aside from general cleanup so that tests are even easier to write, one of the features I've pushed today is a bug registry. One of the issues with the test suite (especially one that is not integrated with the repository directly) is that tests don't just fail or succeed, they can also be known to fail, or known to succeed.
&lt;/p&gt;&lt;p&gt;
For example, a test may succeed on git master, but fail on the 1.13 branch - either because the fix has not yet been backported, or because the fix will not be backported anyway.
&lt;/p&gt;&lt;p&gt;
Keeping track of those failures is quite a task, especially when you have multiple server versions to worry about.
&lt;/p&gt;&lt;p&gt;
This is what the bug-registry is supposed to address. It's in its early stages, but has already been quite helpful. At it's very base is the commandline client &lt;i&gt;xit-bug-registry&lt;/i&gt;, and the matching data file (xml) that keeps track of the various test cases.
&lt;/p&gt;&lt;p&gt;
This is a simple introduction on how to use it.
&lt;/p&gt;&lt;p&gt;
To get started, run the tests, then create a new registry from the test output
&lt;/p&gt;
&lt;pre&gt;
$&gt; sudo ./tests/server/server --gtest_output="xml:server-results.xml"
$&gt; xit-bug-registry create server-results.xml &gt; registry.xml
&lt;/pre&gt;

Information about the tests can now be queried:
&lt;pre&gt;
$&gt; xit-bug-registry -f registry.xml list

TestSuite                     TestCase                               Success
---------                     --------                               -------
BarrierConflictingDirections  InvalidConflictingDirectionsBarrier/0     True
BarrierConflictingDirections  InvalidConflictingDirectionsBarrier/1     True
EventQueueTest                mieqOverflow                              True
MiscServerTest                DoubleSegfault                            True
PointerGrabTest               GrabDisabledDevices                       True
PointerGrabTest               ImplicitGrabRawEvents                     False
ScreenSaverTest               ScreenSaverActivateDeactivate             False
...
&lt;/pre&gt;

The above shows a bunch of tests that are expected to succeed, and two that
are expected to fail. Ideally, these tests will be annotated, so that looking
up info will look like this:
&lt;pre&gt;
$&gt; xit-bug-registry -f registry.xml info XTest DisabledDevicesProperty
XTest DisabledDevicesProperty:  Expected result: Success
Known bugs: 
0: https://bugs.freedesktop.org/show_bug.cgi?id=56380
Known fixes: 
0: aad65415bff12c6860c19beac42e4165e598a40f
&lt;/pre&gt;

To get there, some manual interaction is required:
&lt;pre&gt;
$&gt; xit-bug-registry -f registry.xml edit \
 XTest DisabledDevicesProperty \
 add-bug http://bugs.freedesktop.org/56380
$&gt; xit-bug-registry -f registry.xml edit \
 XTest DisabledDevicesProperty \
add-commit aad65415bff12c6860c19beac42e4165e598a40f
&lt;/pre&gt;

&lt;p&gt;
There are other bits one can add, but bugs and commits are likely the
interesting bits. Right now, that's all it does, but in the future I hope to
expand the script to query the bug database for the bug status, and query
repositories to check if the fix is on the branch yet.
&lt;/p&gt;&lt;p&gt;
That's all nice, but the real important bit is to verify that after fixing a
bug, one hasn't broken anything.
&lt;/p&gt;

&lt;pre&gt;
$&gt; sudo ./tests/server/server --gtest_output="xml:server-results.xml"
$&gt; xit-bug-registry -f registry.xml verify server-results.xml
Code TestSuite                    TestCase                                Result  Expected
---- ---------                    --------                                ------  --------
++   BarrierConflictingDirections InvalidConflictingDirectionsBarrier/0   true      true
++   BarrierConflictingDirections InvalidConflictingDirectionsBarrier/1   true      true
++   BarrierConflictingDirections InvalidConflictingDirectionsBarrier/2   true      true
++   BarrierConflictingDirections InvalidConflictingDirectionsBarrier/3   true      true
++   BarrierConflictingDirections InvalidConflictingDirectionsBarrier/4   true      true
++   BarrierConflictingDirections InvalidConflictingDirectionsBarrier/5   true      true
--   PointerGrabTest              ImplicitGrabRawEvents                  false     false
XX   ScreenSaverTest              ScreenSaverActivateDeactivate           true     false
++   TouchDeviceChangeTest        DeviceChangedEventPointerToTouchSwitch  true      true
++   TouchDeviceChangeTest        DeviceChangedEventTouchToPointerSwitch  true      true
XX   TouchDeviceChangeTest        NoCursorJumpsOnTouchToPointerSwitch     true     false
++   TouchDeviceTest              DisableDeviceEndTouches                 true      true
--   TouchEventHistoryTest        EventHistoryReplay/0                   false     false
--   TouchEventHistoryTest        EventHistoryReplay/1                   false     false
--   TouchEventHistoryTest        EventHistoryReplay/10                  false     false
...
&lt;/pre&gt;

&lt;p&gt;
This simply shows us which tests had which result. Cases with code ++ succeeded
when they were expected to, -- failed when they were expected to. XX is what
you need to look for, it indicates that the test outcome differs to the status in the registry.
In this case, two tests now succeed when before they didn't - usually a good outcome.
&lt;/p&gt;&lt;p&gt;
Once a fix is merged, you can update the status of the bug:
&lt;pre&gt;
$&gt; xit-bug-registry -f registry.xml edit \
 XTest DisabledDevicesProperty \
 set-status success
&lt;/pre&gt;
If this test fails in the future, you'll now be able to spot it.
&lt;/p&gt;
&lt;p&gt;
The information is all in the registry file and though I admit the interface
is still clumsy, it's quite simple to keep a set of registries (e.g. upstream,
Fedora, RHEL, etc.) and thus a known set of test outcomes for each. 
&lt;/p&gt;
&lt;p&gt;
Finally, as test cases are being added, it's important to update the registry.
This is as simple as:
&lt;pre&gt;
$&gt; xit-bug-registry create results-with-new-testcases.xml &gt; new-registry.xml
$&gt; xit-bug-registry merge registry.xml new-registry.xml
&lt;/pre&gt;
This command will merge any new test cases into our original registry, but
won't update the status on any existing ones.
&lt;/p&gt;

&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/xgAQKSyLjBU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/9077780113158781309/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=9077780113158781309" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/9077780113158781309?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/9077780113158781309?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/xgAQKSyLjBU/xorg-integration-test-suite-part-2.html" title="X.Org integration test suite - part 2, the registry" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/11/xorg-integration-test-suite-part-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UBQ3kyeCp7ImA9WhNTFkQ.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-7610139345865190762</id><published>2012-10-19T15:39:00.001+10:00</published><updated>2012-10-20T10:00:52.790+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-20T10:00:52.790+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="wacom" /><title>Lenovo x220t Tablet and the broken Wacom 0xE6 tablet</title><content type="html">I noticed that my tablet didn't work anymore. In fact, the tablet itself didn't even show up in /proc/bus/input/devices. At first I suspected a kernel bug and rebooted into a variety of different Fedora kernels, but to no avail.&lt;br /&gt;
&lt;br /&gt;
Looking at various logs, I discovered: &lt;br /&gt;
&lt;pre&gt;
:: whot@yabbi:~&gt; dmesg | grep 56a
[    2.291841] usb 2-1.5: New USB device found, idVendor=056a, idProduct=0094
&lt;/pre&gt;
Wacom's vendor ID is 056a, but the tablet in the x220 is a 0xE6, not a 0x94 (the latter of which doesn't exist). With that info, googling for a solution was a bit easier. As suggested in the &lt;a href="http://old.nabble.com/X220t-Tablet-no-longer-working-td34233718.html#a34285921" target="_blank"&gt;thread on linuxwacom-devel&lt;/a&gt; a power off did indeed fix the issue for me.&lt;br /&gt;
&lt;pre&gt;
:: whot@yabbi:~&gt; dmesg | grep 56a
[    2.291841] usb 2-1.5: New USB device found, idVendor=056a, idProduct=00e6
&lt;/pre&gt;

It turns out this is an issue with kernel 3.5.3 and 3.5.4, but it is fixed in 3.5.5. &lt;a href=" https://bugzilla.kernel.org/show_bug.cgi?id=46821"&gt;kernel bug&lt;/a&gt;. As Ping &lt;a href="http://old.nabble.com/X220t-Tablet-no-longer-working-td34233718.html#a34285921"&gt;states&lt;/a&gt;:&lt;br/&gt;
&lt;blockquote&gt;
The root cause is somewhere in the kernel tablet is set to a wrong
mode. Once it is in that mode, a reboot won't reset it to normal. We
have to power it off and wait a few seconds for all bits to reset.
That's why I tell people to even unplug the power cable since bits may
stay as long as they get power.
&lt;/blockquote&gt;
&lt;br/&gt;

&lt;small&gt;update 20/10/12: list kernel versions affected, add Ping's quote&lt;/small&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/RJFKi7nZsgQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/7610139345865190762/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=7610139345865190762" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7610139345865190762?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7610139345865190762?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/RJFKi7nZsgQ/lenovo-x220t-tablet-and-broken-wacom.html" title="Lenovo x220t Tablet and the broken Wacom 0xE6 tablet" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/10/lenovo-x220t-tablet-and-broken-wacom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YDRXo7eyp7ImA9WhNTFk8.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-8064510597870923921</id><published>2012-10-19T14:36:00.001+10:00</published><updated>2012-10-19T15:39:34.403+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-19T15:39:34.403+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>The X.Org joystick driver (xf86-input-joystick)</title><content type="html">At &lt;a href="http://www.x.org/wiki/Events/XDC2012" target="_blank"&gt;XDC2012&lt;/a&gt;, &lt;a href="http://www.saschahlusiak.de/" target="_blank"&gt;Sascha Hlusiak&lt;/a&gt;, maintainer of the &lt;a href="http://cgit.freedesktop.org/xorg/driver/xf86-input-joystick" target="_blank"&gt;xf86-input-joystick&lt;/a&gt; module, gave a &lt;a href="http://www.x.org/wiki/Events/XDC2012/XDC2012AbstractSaschaHlusiak" target="_blank"&gt;talk&lt;/a&gt; (&lt;a href="http://www.x.org/wiki/Events/XDC2012/XDC2012AbstractSaschaHlusiak?action=AttachFile&amp;amp;do=view&amp;amp;target=xf86-input-joystick.pdf" target="_blank"&gt;slides&lt;/a&gt;) outlining the joystick driver's current state and future directions. There were quite a few tidbits of information in there that I want to repeat here, a slightly more public place.&lt;br /&gt;
&lt;br /&gt;
The most important bit about the xf86-input-joystick module is what it is not: it is &lt;b&gt;not a joystick driver&lt;/b&gt;. If you want to use your joystick in a game under X, you don't need that driver. The xf86-input-joystick module is designed to &lt;b&gt;control the pointer with a joystick device&lt;/b&gt;. Sascha gave the example of using an XBox controller to control a Linux-driven media-center. The controller can serve as a cheap remote control (especially if you already have the controller but you'd need to buy a remote ;)&lt;br /&gt;
&lt;br /&gt;
So why is the joystick module not a joystick driver? The evdev driver handles most input devices with arbitrary axes and games can use those devices through evdev. But this is a game-specific application, and the game likely knows what features of the joystick it wants.&lt;br /&gt;
&lt;br /&gt;
For pointer control, it's not quite as obvious. Your average joystick has a couple of axes, four or more buttons and possibly even force feedback. The joystick module's configuration must determine which axis controls the pointer motion (and must be mapped from absolute to relative) and which button generates button (or key) events. Because no two joysticks are the same, there cannot be a sane default for the joystick driver configuration. The default install is thus almost certainly useless and may even interfere with your normal X install.&lt;br /&gt;
&lt;br /&gt;
For example, a joystick sending absolute input events that does not have the mapping configured correctly will force the mouse pointer onto a specific position.That may make it impossible to move the pointer with the mouse.&lt;br /&gt;
&lt;br /&gt;
For this reason, any distribution that ships the joystick module should add Option "Floating" "on" into the default configuration. This way the joystick is detected and enabled in X, but it won't actually control the cursor. This means the joystick may look like it's not working initially to the users who want it, but it's not breaking anything for those that install the module unintentionally. The joystick module should not be part of a default install, it's use-case is too narrow.&lt;br /&gt;
&lt;br /&gt;
Once you're happy using the joystick module for it's intended purpose, there are vast configuration options to suit all tastes:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Option "MapButton1" "button=3"&lt;/b&gt; maps the first joystick button into a right-click (X logical button 3)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Option "MapButton2" "axis=+5x"&lt;/b&gt; maps the second joystick button to a x movement by 5 units&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Option "MapButton3" "keycode=50,40"&lt;/b&gt; maps to Shift +d, though you may want to &lt;a href="http://who-t.blogspot.com.au/2008/09/rmlvo-keyboard-configuration.html" target="_blank"&gt;read about keycodes vs keysyms&lt;/a&gt; first&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Option&amp;nbsp; "MapAxis2"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "mode=relative&amp;nbsp;&amp;nbsp;&amp;nbsp; keylow=111&amp;nbsp; keyhigh=116"&lt;/b&gt; will map the second axis to key events up/down&lt;/li&gt;
&lt;/ul&gt;
I recommend reading the &lt;a href="http://www.x.org/releases/X11R7.7/doc/man/man4/joystick.4.xhtml" target="_blank"&gt;joystick(4) man page&lt;/a&gt; for further examples on configuration options. Note, the linked man page isn't the latest one, but it's at least rendered in html, not plain &lt;a href="http://cgit.freedesktop.org/xorg/driver/xf86-input-joystick/tree/man/joystick.man" target="_blank"&gt;roff&lt;/a&gt;.&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/nRpx_F-f754" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/8064510597870923921/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=8064510597870923921" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8064510597870923921?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8064510597870923921?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/nRpx_F-f754/the-xorg-joystick-driver-xf86-input.html" title="The X.Org joystick driver (xf86-input-joystick)" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/10/the-xorg-joystick-driver-xf86-input.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMHR3w6fCp7ImA9WhJbGE0.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-2560716586063656944</id><published>2012-09-28T13:20:00.001+10:00</published><updated>2012-09-28T13:20:36.214+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-28T13:20:36.214+10:00</app:edited><title>Never use a "Questions?" slide in your presentation</title><content type="html">Most presenters do this. Give a presentation, finishing with a "questions?" slide. Except, that's a really bad idea.&lt;br/&gt;&lt;br/&gt;

You give a talk at a conference? You have 20, maybe 45 minutes to get your topic into the mind of the audience? Then don't let your audience stare at "Questions?" for 10, 20 minutes (however long the question time takes). Even if there are no questions, it usually takes a few minutes for applause, saying thanks and until you leave the podium. And the whole time your audience is staring at a meaningless word.
&lt;br/&gt;&lt;br/&gt;
So, skip the useless "Questions?" slide. You can invite your audience to ask questions without it too. The whole point of being a speaker is that you're allowed to also say things that are not on the slides.&lt;br/&gt;&lt;/br&gt;

Finish with a slide that reminds your audience what you just talked about. A summary of the talk, the one point you really wanted to drive home. Maybe even a joke, if you have one that gets the point across.
&lt;br/&gt;&lt;br/&gt;
And your contact details. It gives those without questions enough time to write it down.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/mXaDt7NRM3c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/2560716586063656944/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=2560716586063656944" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2560716586063656944?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2560716586063656944?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/mXaDt7NRM3c/never-use-questions-slide-in-your.html" title="Never use a &quot;Questions?&quot; slide in your presentation" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/09/never-use-questions-slide-in-your.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEFRH08eSp7ImA9WhJVEUg.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-2659684644517722886</id><published>2012-08-28T20:43:00.001+10:00</published><updated>2012-08-28T20:43:35.371+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-28T20:43:35.371+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>X.Org integration test suite</title><content type="html">&lt;p&gt;One of the problems we face in X is that testing can be incredibly painful. Somebugs only happen with a specific server state, a specific device and a specific application. Sometimes we don't spot regressions for several releases, and in some cases that means we can't easily go back and fix it either - users may have gotten used to the new behaviour already.&lt;/p&gt;

&lt;p&gt;A few months ago, Chase Douglas &lt;a href="http://voices.canonical.com/chase.douglas/2012/04/30/integration-testing-for-x-org/"&gt;announced&lt;/a&gt; the &lt;a href="http://cgit.freedesktop.org/xorg/test/xorg-gtest/"&gt;xorg-gtest&lt;/a&gt; framework. I started extending xorg-gtest and writing tests against it. Olivier Fourdan soon joined in with his own tests. The result of that are the xorg integration tests (XIT) found here:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://cgit.freedesktop.org/~whot/xorg-integration-tests/"&gt;http://cgit.freedesktop.org/~whot/xorg-integration-tests/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post is an outline of what the XIT do and what we could potentially make it do.
We currently have over 50 tests in the XIT repository. Most of the tests are still quite simple, but I've already added some that test for a specific bug and that certainly helped testing. In one case, a failing test reminded me that I forgot to send a pull request :)&lt;/p&gt;

&lt;h2&gt;googletest and xorg-gtest&lt;/h2&gt;
&lt;p&gt;xorg-gtest is based on the &lt;a href="http://http://code.google.com/p/googletest/"&gt;googletest&lt;/a&gt; C++ framework. It provides a bunch of classes with virtual functions that are called set up or tear down a test. For the tests, it provides a set of assertion macros. xorg-gtest provides a set of classes on top of googletest that make starting an X server simpler. The XServer class provided hooks up config and log files, waits for the server to accept connections and terminates the server gracefully. It also includes a class for starting &lt;a href="http://people.freedesktop.org/~whot/evemu/"&gt;evemu&lt;/a&gt; devices and re-playing input event sequences. There are a few additional helper classes in the XIT, for example one that makes writing configurations easier. They may move to xorg-gtest at some point in the future.&lt;/p&gt;

&lt;h2&gt;Example tests&lt;/h2&gt;

&lt;p&gt;Your average test now essentially consists of three steps: write out a specific config, start the server and then query that server for information or test it for behaviour.&lt;/p&gt;

&lt;p&gt;A straightforward test is the &lt;a href="http://cgit.freedesktop.org/~whot/xorg-integration-tests/tree/tests/input/legacy-drivers.cpp#n88"&gt;acecad driver test&lt;/a&gt; below.&lt;/p&gt;

&lt;pre&gt;
TEST(AcecadInputDriver, WithOptionDevice)
{
    XOrgConfig config;
    xorg::testing::XServer server;

    config.AddInputSection("acecad", "--device--",
                           "Option \"CorePointer\" \"on\"\n"
                           "Option \"Device\" \"/dev/input/event0\"\n");
    config.AddDefaultScreenWithDriver();
    StartServer("acecad-type-stylus", server, config);

    ::Display *dpy = XOpenDisplay(server.GetDisplayString().c_str());

    int ndevices;
    XIDeviceInfo *info;
    info = XIQueryDevice(dpy, XIAllDevices, &amp;ndevices);
    XIFreeDeviceInfo(info);

    ASSERT_EQ(ndevices, 7);

    config.RemoveConfig();
    server.Terminate(3000);
    server.RemoveLogFile();
}
&lt;/pre&gt;

&lt;p&gt;A slightly more involved test that makes use of the googletest class hierarchy would be the &lt;a href="http://cgit.freedesktop.org/~whot/xorg-integration-tests/tree/tests/input/legacy-drivers.cpp#n64"&gt;void driver test&lt;/a&gt; below. It makes use of a InputDriverTest class that starts the server for us and tears it down afterwards. So all we need is a couple of lines for the class definition and then the test itself.&lt;/p&gt;

&lt;pre&gt;
class VoidInputDriverTest : public InputDriverTest {
public:
    /**
     * Initialize an xorg.conf with a single CorePointer void device.
     */
    virtual void SetUp() {
        InputDriverTest::SetUp("void");
    }
};

TEST_F(VoidInputDriverTest, VoidDriver)
{
    ASSERT_EQ(FindInputDeviceByName(Display(), "--device--"), 1);
}
&lt;/pre&gt;

&lt;p&gt;These two are just examples as used in the integration test suite. I recommend reading the &lt;a href="http://code.google.com/p/googletest/wiki/Documentation"&gt;googletest documentation&lt;/a&gt; for a bit more info on test fixtures and assertions. xorg-gtest also is well-documented though I recommend building the doxygen sources.&lt;/p&gt;

&lt;h2&gt;Emulating input devices&lt;/h2&gt;
&lt;p&gt;xorg-gtest provides a Device class that, based on evemu recordings, can simulate input devices. So with the current implementation, this as simple as:&lt;/p&gt;

&lt;pre&gt;
  SetDevice("keyboards/AT-Translated-Set-2-Keyboard.desc");
  dev-&gt;Play("keyboards/qwerty.events");
  ...
  dev-&gt;PlayOne(EV_KEY, KEY_Q, 1, true); // press
  dev-&gt;PlayOne(EV_KEY, KEY_Q, 0, true); // release
&lt;/pre&gt;
&lt;p&gt;If you now check for the keysym received, you can easily write a few simple XKB layout tests.&lt;/p&gt;

&lt;h2&gt;Fighting the build system&lt;/h2&gt;
&lt;p&gt;As convenient as tests are to write, googletest is not the easiest thing to deal with. The piles of macros subclass your classes and the &lt;a href="http://en.wikipedia.org/wiki/One_Definition_Rule"&gt;C++ ODR&lt;/a&gt; essentially &lt;a href="http://http://code.google.com/p/googletest/wiki/FAQ#Why_is_it_not_recommended_to_install_a_pre-compiled_copy_of_Goog"&gt;prevents&lt;/a&gt; googletest from being built into a library. Autotools on the other hand make it difficult to compile an external project into your own file. That is the main reason for one big collection of tests instead of a per-driver test suite. Copying Makefile.am's around is painful enough, but at least manageable when only one project does it.&lt;/p&gt;

&lt;p&gt;The current need for three different repositories (googletest, xorg-gtest and XIT) doesn't make things easier. I'm somewhat tempted to merge XIT into xorg-gtest, be it as git submodule or some other means.&lt;/p&gt;
&lt;p&gt;Having said that, since starting to write the tests I'm also really tempted to merge the drivers into the server, it would make things a lot easier&lt;/p&gt;

&lt;h2&gt;ifdefs maze&lt;/h2&gt;
&lt;p&gt;To make the tests useful, they should be able to run on most systems. Right now, I've got some simple defines to test for RHEL6 and also XI 2.2. But I don't think this will scale too well. Every system may have different defaults, and short of having platform-specific tests (which may only be different in one single line) I don't know what the good answer is. I do want it answered soon, before it gets out of hand.&lt;/p&gt;

&lt;h2&gt;Scalability&lt;/h2&gt;
&lt;p&gt;Running all tests takes a while. In the current test design, every single test starts a new server and thus it takes a couple of seconds for even the quickest test to succeed. This works with 50 test cases, but it won't work with 500 and even less with 5000. So we need some solution for that. Not re-starting the server is the obvious one and there will be tests that won't require that.&lt;/p&gt;

&lt;h2&gt;Output testing&lt;/h2&gt;
&lt;p&gt;Most of the test runs I do either on my laptop or on a virtual machine. For input tests, this is easy since we only need to set up the dummy driver and the rest can be emulated. For output tests, not so much so a good approach of only running tests applicable for the hardware would be useful. I haven't thought too much about this yet.&lt;/p&gt;

&lt;h2&gt;Testing XIT&lt;/h2&gt;
&lt;p&gt;Right now, it sits in my personal home directory but I hope that after XDC this year, we can decide what the future of this test suite can be and where to host it proper. &lt;/p&gt;
&lt;p&gt;In the meantime, grab it from here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cgit.freedesktop.org/~whot/xorg-integration-tests/"&gt;http://cgit.freedesktop.org/~whot/xorg-integration-tests/&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/Ftvj6UjkXsw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/2659684644517722886/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=2659684644517722886" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2659684644517722886?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2659684644517722886?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/Ftvj6UjkXsw/xorg-integration-test-suite.html" title="X.Org integration test suite" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/08/xorg-integration-test-suite.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAGQn44eyp7ImA9WhJWFE4.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-7388416912715063999</id><published>2012-08-20T13:52:00.000+10:00</published><updated>2012-08-20T13:52:03.033+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-08-20T13:52:03.033+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>screen configuration for automatic session names</title><content type="html">screen is an immensely useful program, but once you start running multiple sessions at the same time, it gets tricky to find the right one again.&amp;nbsp; For example, which one was offlineimap again?&lt;br /&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;br /&gt;
&amp;nbsp;:: whot@salty:~&amp;gt; screen -ls&lt;br /&gt;There are screens on:&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;5238.pts-3.salty&amp;nbsp;&amp;nbsp; &amp;nbsp;(Detached)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;5229.pts-3.salty&amp;nbsp;&amp;nbsp; &amp;nbsp;(Detached)&lt;br /&gt;
&lt;br /&gt;
The -S argument allows to specify a session name but I couldn't find a configuration to set this automatically. So I've added this little script:&lt;br /&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;br /&gt;
$&amp;gt; cat $HOME/scripts/screen&lt;br /&gt;
#!/bin/bash&lt;br /&gt;/usr/bin/screen $([[ ($1 != -*) &amp;amp;&amp;amp; ($# &amp;gt; 0) ]] &amp;amp;&amp;amp; echo "-S $1") "$@"&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;Explanation: if called with 1 or more parameters and the first parameter does not start with a dash, replace a call in the form of &lt;span style="font-family: monospaced;"&gt;screen command ...&lt;/span&gt; with &lt;span style="font-family: monospaced;"&gt;screen -S command command ...&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This results in screen sessions having useful names, allowing for more effective reattaching. And the obligatory, ahem, screenshots:&amp;nbsp; &lt;br /&gt;
&lt;pre&gt;
:: whot@yabbi:~&amp;gt; screen foo
[detached from 17755.foo]
:: whot@yabbi:~&amp;gt; screen bar
[detached from 17766.bar]
:: whot@yabbi:~&amp;gt; screen -ls
There are screens on:
&amp;nbsp;&amp;nbsp;&amp;nbsp; 17766.bar&amp;nbsp;&amp;nbsp;&amp;nbsp; (Detached)
&amp;nbsp;&amp;nbsp;&amp;nbsp; 17755.foo&amp;nbsp;&amp;nbsp;&amp;nbsp; (Detached)
2 Sockets in /var/run/screen/S-whot.&lt;br /&gt;
&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/XEqVLESEQYw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/7388416912715063999/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=7388416912715063999" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7388416912715063999?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7388416912715063999?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/XEqVLESEQYw/screen-configuration-for-automatic.html" title="screen configuration for automatic session names" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/08/screen-configuration-for-automatic.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MEQX84eip7ImA9WhJSGUs.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-8652141031456301027</id><published>2012-07-11T11:16:00.000+10:00</published><updated>2012-07-11T11:16:40.132+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-11T11:16:40.132+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>Daily tmp directory</title><content type="html">My $HOME/tmp directory got a bit messy, especially with building test rpms or testing tarballs. My solution was to just change the directory to automatically change daily. Scripts below:

&lt;pre&gt;
:: whot@yabbi:~&gt; cat scripts/tmp-today 
#!/bin/bash
date=`date +%Y-%m-%d-%a`

tmpdir=$HOME/tmp/$date
tmplink=$HOME/tmp/today

if [ -e "$tmpdir" ]; then
    exit 0
fi

mkdir $tmpdir
ln -sf $tmpdir $tmplink
&lt;/pre&gt;

And the crontab entries to run this script:
&lt;pre&gt;
0 2 * * * /home/whot/scripts/tmp-today
@reboot /home/whot/scripts/tmp-today
&lt;/pre&gt;
So run the thing at 2.00 am and on every reboot in case the box was shut off overnight.

I had it on midnight first, but I think 2 am is better. If I'm still up at 2 and working, then mentally I'm still in on the day before and I don't want files to end up in different directories just because midnight clocked over.

And because the laptop may be suspended overnight, we run the script on resume as well:
&lt;pre&gt;
:: whot@yabbi:~&gt; cat /etc/pm/sleep.d/00-tmp-dir 
#!/bin/bash

case "$1" in
 thaw|resume)
  su -c - whot /home/whot/scripts/tmp-today
  ;;
 *)
  ;;
esac
&lt;/pre&gt;

This obviously works for other directories as well, e.g. your daily download directory.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/u1n5Zv5DGkc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/8652141031456301027/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=8652141031456301027" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8652141031456301027?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8652141031456301027?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/u1n5Zv5DGkc/daily-tmp-directory.html" title="Daily tmp directory" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/07/daily-tmp-directory.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cMQXg7fSp7ImA9WhBSFEU.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-1534766703184649299</id><published>2012-07-06T10:14:00.000+10:00</published><updated>2013-02-22T08:18:00.605+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-22T08:18:00.605+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="configuration" /><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>elographics touchscreen setup</title><content type="html">This is a tutorial of sorts on how to set up an elographics serial touchscreen. I don't actually have such a device but the question pops up every couple of months. Together with Tom Munro Glass and Tias Guns, we got one working properly.&lt;br/&gt;&lt;br/&gt;

A bit of history first: not too long ago, the X server was talking to serial devices directly and thus had several drivers for specific input devices. The &lt;a href="http://cgit.freedesktop.org/xorg/driver/xf86-input-elographics/"&gt;elographics X drivers&lt;/a&gt; is one of them. Unfortunately, due to lack of hardware we, the upstream maintainers, can only perform cursory testing of that driver. The Linux kernel however supports a large amount of serial devices too, so for this tutorial I'll explain how to use the linux kernel to talk to the device.  I'll show how to set up udev rules to use inputattach and then the X.Org evdev driver, thus making the device utilise a well-tested driver that has some client-stack support not found for the X.Org elographics driver [1].
&lt;br/&gt;&lt;br/&gt;
&lt;h2&gt;Kernel setup&lt;/h2&gt;
USB devices are automagically detected by the kernel and it will load the right drivers. Serial devices on the other hand require some manual configuration.
Elographics devices have serial kernel drivers and &lt;a href="http://man.he.net/man1/inputattach"&gt;inputattach&lt;/a&gt; can be used to hook serial devices up with those kernel drivers. First we need to load the kernel module, then call inputattach with the right options for our device:
&lt;pre&gt;
root@localhost:~&gt; modprobe elo
root@localhost:~&gt; inputattach -elo /dev/ttyS0 --daemon
&lt;/pre&gt;
The path to the device may need to be changed on your box. Do look up the &lt;a href="http://man.he.net/man1/inputattach"&gt;inputattach man page&lt;/a&gt;, depending on your device you may need a different flag.
&lt;br/&gt;&lt;br/&gt;
Once inputattach is running, the device should be visible in /proc/bus/input/devices. You can run &lt;a href="http://www.freedesktop.org/wiki/Evtest"&gt;evtest&lt;/a&gt; against it and see the event stream. 

&lt;br/&gt;&lt;br/&gt;
&lt;h2&gt;udev setup&lt;/h2&gt;
Since we don't want to run inputattach manually each time, we'll now set up udev to run this command for us. According to Tom, the elographics device does not have a &lt;a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463195.aspx"&gt;pnpid&lt;/a&gt;, so he configured it with a fixed device path on ttyS4:

&lt;pre&gt;
$&gt; cat /lib/udev/rules.d/99-elographics.rules
ACTION=="add|change", SUBSYSTEM=="tty|pnp", KERNEL=="ttyS4", \
        RUN+="/sbin/modprobe elo", \
        RUN+="/sbin/inputattach -elo /dev/%k --daemon"
&lt;/pre&gt;

If a device has a pnpid, the rule can be more flexible in what ttyS* the device needs to appear on. For example,  a Wacom serial tablet may have the id WACf004 so we can use the match rule below.
&lt;pre&gt;
$&gt; cat /lib/udev/rules.d/99-wacom-w8001.rules
ACTION=="add|change", SUBSYSTEM=="tty|pnp", KERNEL=="ttyS[0-9]*", \
        ATTRS{id}=="WACf*", \ 
        RUN+="/sbin/modprobe wacom_w8001", \
        RUN+="/sbin/inputattach -w8001 /dev/%k --daemon"
&lt;/pre&gt;

Once this rule is in place, inputattach will be started for us at boot time (of course the device needs to be connected at boot time too). The next step is to configure X to see the device.
&lt;br/&gt;
&lt;br/&gt;

&lt;h2&gt;X.Org configuration&lt;/h2&gt;

X requires the udev properties ID_INPUT and one of ID_INPUT_MOUSE, ID_INPUT_TABLET, etc. to to recognise an input device. Each of those triggers the respective MatchIsPointer, MatchIsTablet, etc. directive in the xorg.conf.d snippets. On modern systems, the udev properties should be assigned automatically [2]. If that doesn't happen on your box, you can modify the above udev rules to add it manually:

&lt;pre&gt;
$&gt; cat /lib/udev/rules.d/99-elographics.rules
ACTION=="add|change", SUBSYSTEM=="tty|pnp", KERNEL=="ttyS4", \
        RUN+="/sbin/modprobe elo", \
        RUN+="/sbin/inputattach -elo /dev/%k --daemon", \
        ENV{ID_INPUT}="1", ENV{ID_INPUT_TOUCHSCREEN}="1"
&lt;/pre&gt;

Once this is done, the X server will pick up the device, and the default configuration [3] will assign the evdev driver to it. Restart X, and you're done. &lt;br/&gt;&lt;br/&gt; If you require additional options, set up an xorg.conf.d snippet. There you can add any options found in &lt;a href="http://www.x.org/releases/X11R7.6/doc/man/man4/evdev.4.xhtml"&gt;evdev(4)&lt;/a&gt;:
&lt;pre&gt;
$&gt; cat /etc/X11/xorg.conf.d/99-elographics.conf
Section "InputClass"
  Identifier "elographics config"
  MatchProduct "Elo Serial TouchScreen"
  Option "EmulateThirdButton" "on"
EndSection
&lt;/pre&gt;

This snippet will match any device with the product name containing "Elo Serial Touchscreen" and enable the right button emulation feature in the evdev driver. If you are unsure about the name of your device, check /proc/bus/input/devices once inputattach is running.
&lt;br/&gt;
&lt;br/&gt;
&lt;h2&gt;X.Org configuration on Red Hat Enterprise Linux (RHEL) 6.x&lt;/h2&gt;
This section applies to derivatives as well, e.g. CentOS 6.
On RHEL 6.x, we use HAL as a configuration backend. So you will need an fdi snippet to match the device up with the driver. The snippet below is the one Tom ended up using, and it also shows the Calibration option being merged.

&lt;pre&gt;
$&gt; cat /etc/hal/fdi/policy/10-elographics.fdi
&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;
&amp;lt;deviceinfo version="0.2"&amp;gt;
  &amp;lt;device&amp;gt;
    &amp;lt;match key="info.category" contains="input"&amp;gt;
      &amp;lt;match key="info.product" contains="Elo Serial TouchScreen"&amp;gt;
        &amp;lt;merge key="input.x11_driver" type="string"&amp;gt;evdev&amp;lt;/merge&amp;gt;
        &amp;lt;!-- next line is equivalent to an xorg.conf.d statement of
                Option "Calibration "40 4000 40 4000" --&amp;gt;
        &amp;lt;merge key="input.x11_options.calibration" type="string"&amp;gt;40 4000
40 4000&amp;lt;/merge&amp;gt;
      &amp;lt;/match&amp;gt;
    &amp;lt;/match&amp;gt;
  &amp;lt;/device&amp;gt;
&amp;lt;/deviceinfo&amp;gt;
&lt;/pre&gt;

Note the "match key" statement. Apparently, this particular device does not set "input.touchscreen", so we match on just "input" instead. Not too big a deal, since we then also match on the product name.
&lt;br/&gt;&lt;br/&gt;
Once this file is in place, restart haldaemon and check with lshal that the right options are assigned. Then restart X and the device should work.

&lt;br/&gt;&lt;br/&gt;
Good luck!
&lt;br/&gt;&lt;br/&gt;
Many thanks to Tias and Tom for proof-reading this article multiple times.


&lt;br/&gt;&lt;br/&gt;
[1] for example, evdev supports dynamic recalibration with the &lt;a href="http://www.freedesktop.org/wiki/Software/xinput_calibrator"&gt;xinput_calibrator&lt;/a&gt; tool&lt;br/&gt;
[2] check the output of &lt;i&gt;udevadm info --export-db&lt;/i&gt;&lt;br/&gt;
[3] your distribution should ship  /usr/share/X11/xorg.conf.d/10-evdev.conf which assigns evdev to MatchIsTablet.&lt;br/&gt;

&lt;br/&gt;
&lt;small&gt;[edit 22 Feb 13: fix typo in MatchProduct name]&lt;/small&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/kPve0mNNA94" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/1534766703184649299/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=1534766703184649299" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/1534766703184649299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/1534766703184649299?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/kPve0mNNA94/elographics-touchscreen-setup.html" title="elographics touchscreen setup" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/07/elographics-touchscreen-setup.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAFR3k-eyp7ImA9WhJTEkg.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-8587414820552615702</id><published>2012-06-21T16:05:00.001+10:00</published><updated>2012-06-21T16:05:16.753+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-21T16:05:16.753+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xkb" /><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><title>XKB SlowKeys</title><content type="html">XKB has an accessibility feature called SlowKeys. Once enabled, a key must be pressed longer than a certain timeout (default: 300ms) to register as key event. Why? From &lt;a href="http://www.x.org/archive/X11R7.5/doc/man/man3/XkbGetSlowKeysDelay.3.html" target="_blank"&gt;XkbGetSlowKeysDelay(3)&lt;/a&gt;:&lt;br /&gt;
&lt;blockquote&gt;
Some users may
accidentally bump keys while moving a hand or typing stick toward  the
key they want. Usually, the keys that are accidentally bumped are just hit
 for a very short period of time. The SlowKeys control helps filter these
 accidental bumps by telling the server to wait a specified period, called
the  &lt;i&gt;SlowKeys&lt;/i&gt; acceptance delay,  before delivering key events. If the key
is released before this period elapses,  no key events are generated.&lt;/blockquote&gt;
This is a useful feature for those that need it, but quite disturbing when it gets enabled without the user noticing. And that can &lt;a href="https://bugzilla.redhat.com/816764" target="_blank"&gt;happen&lt;/a&gt; and it then appears as if the keyboard drivers are broken (after all, a restart of the X server reverts it). So here's a what you have to do to avoid this issue:&lt;br /&gt;
&lt;br /&gt;
The server has a built-in key sequence that if either shift key is held for 8 seconds, SlowKeys are enabled. Likewise, another 8s press of either shift key disables them again. This may accidentally happen when playing games or scrolling through long documents.&lt;br /&gt;
&lt;br /&gt;
The server keeps two bitflags around. One for "accessibility features enabled" and one for "slow keys enabled". If the former is set, the key sequence above will activate slow keys (and thus toggle the second bit).&lt;br /&gt;
&lt;br /&gt;
In GNOME3, you can find these options in the Universal Access panel of your System Settings: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-k-uX72jOl9Y/T-Et7TWyZFI/AAAAAAAAA78/vX0FF-zn_Gc/s1600/slowkeys.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="294" src="http://3.bp.blogspot.com/-k-uX72jOl9Y/T-Et7TWyZFI/AAAAAAAAA78/vX0FF-zn_Gc/s320/slowkeys.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
If "Turn on accessibility features from the keyboard" is checked, holding shift will enable/disable SlowKeys. If the SlowKeys toggle is on, SlowKeys are always on.&lt;br /&gt;
&lt;br /&gt;
The equivalent gsettings command (to uncheck the checkbox) is:&lt;br /&gt;
&lt;pre&gt;gsettings set org.gnome.desktop.a11y.keyboard enable false&lt;/pre&gt;
&amp;nbsp;I recommend that if you do not need this feature, uncheck the checkbox to avoid nasty surprises. I've also added &lt;a href="http://cgit.freedesktop.org/xorg/xserver/commit/?id=ff41753b1bee414b16c0f1e8d183776e87c94065" target="_blank"&gt;a patch&lt;/a&gt; to the X server to put a warning in the log if SlowKeys is enabled via the shift key. This should make future triaging a bit easier. If you see the message &lt;br /&gt;
&lt;pre&gt;(II) XKB SlowKeys are now enabled. Hold shift to disable.&lt;/pre&gt;
in your log, you're likely better off disabling the checkbox. This patch will be in server 1.13 and server 1.12.3.&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
GNOME3 should also warn about SlowKeys being enabled but due to &lt;a href="https://bugzilla.gnome.org/show_bug.cgi?id=668213" target="_blank"&gt;Bug 668213&lt;/a&gt; it stopped doing so in January. Affected is GNOME 3.2+ but we're working on a fix to this.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/x_6nFP05cNI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/8587414820552615702/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=8587414820552615702" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8587414820552615702?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/8587414820552615702?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/x_6nFP05cNI/xkb-slowkeys.html" title="XKB SlowKeys" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-k-uX72jOl9Y/T-Et7TWyZFI/AAAAAAAAA78/vX0FF-zn_Gc/s72-c/slowkeys.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/06/xkb-slowkeys.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMBSX8-eSp7ImA9WhJTEkg.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-5962709440777583493</id><published>2012-06-21T16:00:00.001+10:00</published><updated>2012-06-21T16:00:58.151+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-21T16:00:58.151+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xkb" /><title>_XkbErrCode2 macro explanation</title><content type="html">While debugging some keyboard layout issues, I got this error:
&lt;br /&gt;
&lt;pre&gt;X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  145 (XKEYBOARD)
  Minor opcode of failed request:  9 (XkbSetMap)
  Value in failed request:  0x163f0005
  Serial number of failed request:  116
  Current serial number in output stream:  122
&lt;/pre&gt;
X Errors are supposed to be useful to the client, usually denoting some
error code (e.g. BadValue) and, if possible, the value that triggered it.

After reading the code, I found the _XkbErrCode2 family of macros that
expand to fill in the error code.
&lt;br /&gt;
&lt;pre&gt;#define _XkbErrCode2(a,b) \
   ((XID)((((unsigned int)(a))&amp;lt;&amp;lt;24)|((b)&amp;amp;0xffffff)))
#define _XkbErrCode3(a,b,c) \
   _XkbErrCode2(a,(((unsigned int)(b))&amp;lt;&amp;lt;16)|(c))
#define _XkbErrCode4(a,b,c,d) \
   _XkbErrCode3(a,b,((((unsigned int)(c))&amp;lt;&amp;lt;8)|(d)))
&lt;/pre&gt;
Easy enough to decompose on the client though there's no indication of which
decomposed representation is the correct one. 
&lt;br /&gt;
&lt;pre&gt;xkb/xkb.c:1742 _XkbErrCode3(0x16, i + req-&amp;gt;firstKeySym, wire-&amp;gt;width);
xkb/xkb.c:1749 _XkbErrCode4(0x16, i + req-&amp;gt;firstKeySym, wire-&amp;gt;nSyms, w);
&lt;/pre&gt;
That's when I started wondering what the 0x16 could mean - could it possibly
be _XkbErrBadValue (from xkbfile.h) Bit generic, but possible. But why isn't
it using the define? Looking at other _XkbErrCode calls, some were somewhat
close but others were miles out.  XkbBell returning _XkbErrMissingVMods?
That didn't make sense.&lt;br /&gt;
&lt;br /&gt;
And that's when it struck me: they didn't have any meaning. 0x16 is
literally 0x16, the 22nd error code statement in this function. And, in this
case also the 23rd since it is used twice.
Of course, if one ever de-duplicate some of the XKB code the numbering is
out. And I couldn't find a place where this is documented, so who knows how
much damage we did to that approach without noticing.&lt;br /&gt;
&lt;br /&gt;
Anyway, if you ever have to google for _XkbErrCode2, I'm hoping this post
now comes up and explains the despair you're about to encounter.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/ZYCxlyDLKxI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/5962709440777583493/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=5962709440777583493" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/5962709440777583493?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/5962709440777583493?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/ZYCxlyDLKxI/xkberrcode2-macro-explanation.html" title="_XkbErrCode2 macro explanation" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/06/xkberrcode2-macro-explanation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMDSHs9cSp7ImA9WhVaFEs.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-371826442412207193</id><published>2012-06-12T11:11:00.000+10:00</published><updated>2012-06-12T11:11:19.569+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-12T11:11:19.569+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xi2" /><title>XI 2.1 protocol design issues</title><content type="html">When &lt;a href="http://who-t.blogspot.com.au/2011/09/whats-new-in-xi-21-smooth-scrolling.html"&gt;XI 2.1 smooth scrolling&lt;/a&gt; was released, we were glad to finally have a way for fluid scrolling events. Unfortunately, two design issues have since been discovered that make it harder for applications than necessary. Mea culpa, I apologise, these are things that we should have caught in the review process.

&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Scrolling may overflow the axis range&lt;/h2&gt;
Scrolling events are now posted through axes marked as scrolling axes. This means they're limited to the 32.32 fixed point value range that valuators can take. That range matters because despite scrolling being relative, coordinates in XIDeviceEvents must always be absolute values. Scrolling down is more common than scrolling up, so the axis will slowly accumulate until it reaches the maximum range.

We have to reset them to 0 once we reach INT_MAX to avoid overflow so at some point you may see a scrolling event that jumps from something that's close to 2&lt;sup&gt;32&lt;/sup&gt; to 0. You can at this point assume that this was not a valid scroll event.

This is a rather theoretical case, overflowing this range requires &lt;i&gt;a lot&lt;/i&gt; of scrolling, even on touchpads with a higher scroll increment.

&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
The first scroll event has no usable scroll information&lt;/h2&gt;
This is a more significant issue. The smooth scrolling information is part of the valuator data, but axis data is only sent in some events, and then only to some clients. Once a pointer leaves the window, the original client loses track of what happens to the valuators. Once the pointer re-enters the client's window it will receive the new axis value once more scrolling happens. That value is an absolute value but clients need the delta between it and the previous scroll event. That information is only available once the second event is sent to the client.&lt;br /&gt;
&lt;br /&gt;
For example, the axis data may be 3000 when the pointer leaves the window. Then the pointer re-enters the window and the first scroll event sends has a value of 5500. Since we don't know how much the axis increased elsewhere, we cannot act on this scroll event, we have to wait for the next one to calculate a delta.&lt;br /&gt;
&lt;br /&gt;
I confirmed with &lt;a href="http://blogs.gnome.org/carlosg/" target="_blank"&gt;Carlos&lt;/a&gt; that this is indeed what GTK does: &lt;a href="http://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkdevicemanager-xi2.c#n1551" target="_blank"&gt;reset the scroll valuators&lt;/a&gt; on enter and then &lt;a href="http://git.gnome.org/browse/gtk+/tree/gdk/x11/gdkdevicemanager-xi2.c#n1059" target="_blank"&gt;track the valuators&lt;/a&gt; for future events.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/frMwXqJMr-8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/371826442412207193/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=371826442412207193" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/371826442412207193?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/371826442412207193?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/frMwXqJMr-8/xi-21-protocol-design-issues.html" title="XI 2.1 protocol design issues" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/06/xi-21-protocol-design-issues.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcHQXc-eSp7ImA9WhVbGEg.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-1843464465522159726</id><published>2012-06-05T11:00:00.000+10:00</published><updated>2012-06-05T11:00:30.951+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-05T11:00:30.951+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>git branch-info</title><content type="html">I have too many branches. And sometimes I forgot which one is which. So yesterday I sat down and wrote a git alias to tell me:

&lt;small&gt;
&lt;pre&gt;
branch-info = "!sh -c 'git branch --list --no-color | \
    sed -e \"s/*/ /\" | \
    while read branch; do \
    git log -1 --format=format:\"%Cred$branch:%Cblue %s %Cgreen%h%Creset (%ar)\" $branch; \
    done'"
&lt;/pre&gt;
&lt;/small&gt;

Gives me a nice output like this:

&lt;small&gt;
&lt;pre&gt;
:: whot@yabbi:~/xorg/xserver (for-keith)&gt; git branch-info
&lt;span style="color:#ff0000"&gt;dtrace-input-abi:&lt;/span&gt; &lt;span style="color:#0000ff"&gt; dix: add dtrace probes to input API&lt;/span&gt; &lt;span style="color:#00aa00"&gt; c0b0a9b&lt;/span&gt; (3 months ago)
&lt;span style="color:#ff0000"&gt;extmod-changes:&lt;/span&gt; &lt;span style="color:#0000ff"&gt; DRI2: Remove prototype for DRI2DestroyDrawable&lt;/span&gt; &lt;span style="color:#00aa00"&gt; 8ba2980&lt;/span&gt; (11 months ago)
&lt;span style="color:#ff0000"&gt;fedora-17-branch:&lt;/span&gt; &lt;span style="color:#0000ff"&gt; os: make timers signal-safe&lt;/span&gt; &lt;span style="color:#00aa00"&gt;7089841&lt;/span&gt; (6 weeks ago)
&lt;span style="color:#ff0000"&gt;master:&lt;/span&gt; &lt;span style="color:#0000ff"&gt; Xext: include dix-config.h&lt;/span&gt; &lt;span style="color:#00aa00"&gt;594b4a4&lt;/span&gt;(12 days ago)
&lt;span style="color:#ff0000"&gt;mt-devel:&lt;/span&gt; &lt;span style="color:#0000ff"&gt;Switch to new listener handling for touch events&lt;/span&gt; &lt;span style="color:#00aa00"&gt;3ee84fc&lt;/span&gt; (6 months ago)
&lt;span style="color:#ff0000"&gt;mt-devel2:&lt;/span&gt; &lt;span style="color:#0000ff"&gt;dix: conditionally update the cursor sprite&lt;/span&gt; &lt;span style="color:#00aa00"&gt;9edb3fd&lt;/span&gt;(6 months ago)
&lt;span style="color:#ff0000"&gt;multitouch:&lt;/span&gt; &lt;span style="color:#0000ff"&gt;blah&lt;/span&gt; &lt;span style="color:#00aa00"&gt;8ecec2e&lt;/span&gt;(4 months ago)
...
&lt;/pre&gt;
&lt;/small&gt;

Or, the same thing aligned in columns, though without colours (column doesn't parse the escape sequences for colors so the columns are misaligned).

&lt;small&gt;
&lt;pre&gt;
branch-info = "!sh -c 'git branch --list --no-color | \
    sed -e \"s/*/ /\" | \
    while read branch; do \
    git log -1 --format=format:\"$branch:|%s|%h|%ar\n\" $branch; done | \
    column -t -s\"|\"'"
&lt;/pre&gt;
&lt;/small&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/PYxfjjMFoUc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/1843464465522159726/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=1843464465522159726" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/1843464465522159726?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/1843464465522159726?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/PYxfjjMFoUc/git-branch-info.html" title="git branch-info" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/06/git-branch-info.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcCRX08fyp7ImA9WhVaEEk.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-622547121609456355</id><published>2012-06-05T09:54:00.000+10:00</published><updated>2012-06-07T14:24:24.377+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-06-07T14:24:24.377+10:00</app:edited><title>pkg-config and empty CFLAGS</title><content type="html">I ran into this a few days ago and it took me a while to find. One of the gnome modules failed to build with an error of "cannot find &amp;lt;gtk/gtk.h&amp;gt;". At first I thought it was a Makefile.am/configure.ac error but it appears the issue sits deeper. Cause of the problem was a stale gtk installation, but finding that was tricky.

The configure.ac file contains essentially
&lt;pre&gt;
PKG_CHECK_MODULES(GTK, gtk+-2.0)
AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS)
&lt;/pre&gt;

Turns out that PKG_CHECK_MODULES in configure.ac gets translated to 
&lt;pre&gt;
pkg-config --exists --print-errors gtk+-2.0
&lt;/pre&gt;

This returns 0 (success) on my machine - the gtk+-2.0.pc file is there. However, to get the CFLAGS, configure runs a different command and that returned an error:

&lt;pre&gt;
$&gt; pkg-config --cflags gtk+-2.0
Package libpng12 was not found in the pkg-config search path.
Perhaps you should add the directory containing `libpng12.pc'
to the PKG_CONFIG_PATH environment variable
Package 'libpng12', required by 'GdkPixbuf', not found
&lt;/pre&gt;

Alas, this error isn't shown anywhere and it doesn't end up in the log either. What &lt;i&gt;does&lt;/i&gt; happen though is that GTK_CFLAGS gets replaced with an empty string, causing the build error above. Once I installed the required libpng everything works fine. But if you ever run into issues where the CFLAGS aren't quite what they should be, check the pkg-config commands for success.

&lt;br/&gt;&lt;br/&gt;
&lt;small&gt;
[Update Jun 07 2012]&lt;br/&gt;
&lt;/small&gt;
As pointed out in the comments, looks like we're looking at &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=4738"&gt;https://bugs.freedesktop.org/show_bug.cgi?id=4738&lt;/a&gt; and  
&lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=43149"&gt;https://bugs.freedesktop.org/show_bug.cgi?id=43149&lt;/a&gt; here.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/xX5WUACEfAQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/622547121609456355/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=622547121609456355" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/622547121609456355?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/622547121609456355?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/xX5WUACEfAQ/pkg-config-and-empty-cflags.html" title="pkg-config and empty CFLAGS" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/06/pkg-config-and-empty-cflags.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQAQ3kyeyp7ImA9WhVUE08.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-2840097443696556710</id><published>2012-05-18T17:32:00.000+10:00</published><updated>2012-05-18T17:32:22.793+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-18T17:32:22.793+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="outdoors" /><title>Home-made 4WD rooftop awning</title><content type="html">This article describes how to build your own rooftop awning. I recommend that if you do want an awning, purchase one from a store. They have come down in price considerably since I built mine.

If you do go ahead, make sure to check with your local transportation authority and check whether such a device is legal in your country/state.&lt;br /&gt;
&lt;br /&gt;
Anyway, let's start. A while ago I wanted a rooftop awning but I didn't want to pay that much money. In Australia, these awnings go for several hundred dollars, and the small ones are indeed quite small. So I built my own, instructions are below. This is how it looks like:&lt;br /&gt;&lt;br/&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-dITbSuSNpWE/T7OFbmPbjKI/AAAAAAAAA6w/08OPoXfvk0k/s1600/beach.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="192" width="320" src="http://3.bp.blogspot.com/-dITbSuSNpWE/T7OFbmPbjKI/AAAAAAAAA6w/08OPoXfvk0k/s320/beach.jpg" /&gt;&lt;/a&gt;&lt;br/&gt;
Sometimes it's a tough life...
&lt;/div&gt;


&lt;br /&gt;
The ingredients are:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;tarp with metal eyelets. IIRC mine is 2.4 x 3.0m &lt;a href="http://www.bunnings.com.au/products_product_tarpaulin-medium-duty-160gm2_7789.aspx?search=tarpaulin&amp;amp;searchType=any&amp;amp;searchSubType=products"&gt;(similar one)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;3m 25x25mm aluminium square tube (or width of tarp otherwise)&lt;/li&gt;
&lt;li&gt;Two plastic caps for the square tube&lt;/li&gt;
&lt;li&gt;Four 1.5 inch 3/8 bolts + nuts + washers&lt;/li&gt;
&lt;li&gt;Four 2 inch 3/8 bolts + nuts + washers&lt;/li&gt;
&lt;li&gt;Four poles, one crossbar, ropes, pegs&lt;/li&gt;
&lt;li&gt;Wide (~5cm) velcro, 1 m is sufficient (makes 3 strips)&lt;/li&gt;
&lt;/ul&gt;
&lt;br/&gt;
Most of the stuff I got from Bunnings, the poles from the camping store and the velcro from a textile store next to the BCF at Cannon Hill.&lt;br/&gt;
&lt;br /&gt;
The basic design is simple. The tarp is held onto the square tube by a bunch of vertical bolts - one per tarp eyelet. The crossbar, which is too long for my tray, is held in place by two horizontal bolts, on the inside (towards the car). The tarp is folded in half, then rolled up and held in place by three strips of velcro.
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-FxGwHb9tZ0s/T7XyPsWYCiI/AAAAAAAAA7Y/D2Y5KrgFC6U/s1600/tarp-rolled-up.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="214" width="320" src="http://2.bp.blogspot.com/-FxGwHb9tZ0s/T7XyPsWYCiI/AAAAAAAAA7Y/D2Y5KrgFC6U/s320/tarp-rolled-up.jpg" /&gt;&lt;/a&gt;&lt;br/&gt;Tarp when rolled up for transport.&lt;/div&gt;
&lt;br /&gt;
I have Rhino Rack Aero bars and the bolts I got had a head exactly the size of the groove. So I don't need mountings, I simply push the screw into the groove, then sit the awning on it and tighten the nut up the top. And, second time lucky, the eyelets are the distance of my roof racks, so I don't have to do anything there either.
&lt;br /&gt;

&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-5XsWnRsrkdk/T7OHqxaEUbI/AAAAAAAAA7I/EgXkUV-Wtvg/s1600/rack-fitting.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="213" src="http://1.bp.blogspot.com/-5XsWnRsrkdk/T7OHqxaEUbI/AAAAAAAAA7I/EgXkUV-Wtvg/s320/rack-fitting.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;
The bolt fits exactly into the groove - lucky me :) &lt;br/&gt;Obscured by the rolled-up tarp is the top end of the bolt - simply a washer and a nut.
&lt;/div&gt;

&lt;br/&gt;

&lt;h2&gt;Assembly instructions&lt;/h2&gt;
&lt;br /&gt;
Drill a hole a few cm in from one ond of the square tube. Now take a bolt and nut, screw the tarp's corner to the tube. Stretch it to the other end, drill another hole, bolt, nut, done. The tarp should be tightly stretched. Now mark each eyelets in the middle for more holes. Take the tarp off, drill the remaining holes, then saw the excess square tube off.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-1RIS2VE9xQ0/T7XzubMBQHI/AAAAAAAAA7k/uTNa91DlRuU/s1600/bolt.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="213" src="http://2.bp.blogspot.com/-1RIS2VE9xQ0/T7XzubMBQHI/AAAAAAAAA7k/uTNa91DlRuU/s320/bolt.jpg" /&gt;&lt;/a&gt;&lt;br/&gt;Bolt shown from the side&lt;/div&gt;

&lt;br /&gt;
As said above, my roof racks are exactly the distance of the eyelets, so I don't need extra mountings. The professional awnings have an L-shaped attachment that goes into the roof racks and the awning then hangs off the side. &lt;a href="http://blkmav.com/prado/awning2.jpg"&gt;This photo&lt;/a&gt; shows the attachment, the same should be possible on this home-made model.&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
The final bit are two horizontal drillings through the tube. They are for mounting the crossbar next to the tube. I transport the four poles, the ropes and the pegs in the tray.&lt;br /&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-HFFaoOLODs4/T7X1Tk1YyxI/AAAAAAAAA7w/DQslh9qOEsw/s1600/crossbar-mount.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="213" src="http://2.bp.blogspot.com/-HFFaoOLODs4/T7X1Tk1YyxI/AAAAAAAAA7w/DQslh9qOEsw/s320/crossbar-mount.jpg" /&gt;&lt;/a&gt;&lt;br/&gt;
Crossbar mount. The bolt is horizontal when mounted.
&lt;/div&gt;



&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-4pytYiBa97s/T7OHJDI9ayI/AAAAAAAAA68/XtZskqRbpJ0/s1600/side.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="213" width="320" src="http://3.bp.blogspot.com/-4pytYiBa97s/T7OHJDI9ayI/AAAAAAAAA68/XtZskqRbpJ0/s320/side.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;
The front bit of the rolled-up awning, taken from the other side of the car, showing the crossbar mount.
&lt;/div&gt;

&lt;br /&gt;
Setting it up is simple enough, though it does require 2 people. It takes a few minutes to set up, a few minutes to pack up again. If the tarp gives up, I can (hopefully) buy another one and replace it.&lt;br /&gt;
&lt;br /&gt;
Costs for me was just over AUD 100, including the crossbar and the poles. If you already have those, you're obviously able to build it for much less.

&lt;br/&gt; &lt;br /&gt;
&lt;h2&gt;Side notes&lt;/h2&gt;
As I have the handyman's knowledge of a five-year-old, I did a few things wrong. First,
Bunnings sells bolts in imperial and metric. Had I known that, I'd have bought metric screws. I ended up just getting the first set that matched the size I needed. The metric section was a few metres further down the aisle. &lt;br /&gt; &lt;br /&gt;
The first set of (round capped) nuts wasn't galvanised and started rusting (you can see it in the photos). Haven't been able to find galvanised ones for the imperial bolts, so I've since replaced them with galvanised normal nuts.&lt;br /&gt;&lt;br /&gt;
&lt;h2&gt;Pros and Cons&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It's freaking awesome! Having a shady spot next to the car wherever you roll up is great!&lt;/li&gt;
&lt;li&gt;The awning is big. Not much of an issue once it's mounted but it's pretty unwieldy in the garage.&lt;/li&gt;
&lt;li&gt;The surface area covered is perfect for two people and a table, so no issues there.&lt;/li&gt;
&lt;li&gt;The awning is not free-standing. I believe the commercial models are, but this one needs to be pegged down. Which means that moving the car once it's set up is a no-go, you have to tear it down.&lt;/li&gt;
&lt;li&gt;The way I roll it results in rain collecting in the rolled-up tarp. I could roll it the other way, but that's a bit awkward. No big issue though, except after a good rain when you break at the first set of lights, a few litres of water will run down your windscreen :) &lt;/li&gt;
&lt;li&gt;I can't yet claim how it will hold up in a typical Queensland wind or thunderstorm. I think it will be alright, but so far I've only had it up during light winds and light rain.&lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/aF9qESGPjJ4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/2840097443696556710/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=2840097443696556710" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2840097443696556710?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/2840097443696556710?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/aF9qESGPjJ4/home-made-4wd-rooftop-awning.html" title="Home-made 4WD rooftop awning" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-dITbSuSNpWE/T7OFbmPbjKI/AAAAAAAAA6w/08OPoXfvk0k/s72-c/beach.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/05/home-made-4wd-rooftop-awning.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUMRX0-eip7ImA9WhVVFkQ.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-7440622670581948654</id><published>2012-05-10T09:15:00.000+10:00</published><updated>2012-05-11T08:51:24.352+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-11T08:51:24.352+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>Testing X servers from git</title><content type="html">Every so-often I get asked the question of how to test the X server (or drivers) from git. The setup I have is quite simple: I have a full tree in /opt/xorg, next to the system-installed binaries in /usr. A symlink and some environment variables allow me to switch between git versions of the server and clients and the system-installed ones.
&lt;br/&gt;&lt;br/&gt;
&lt;h2&gt;Installing the tree&lt;/h2&gt;
Getting that setup is quite easy these days:

&lt;small&gt;
&lt;/small&gt;&lt;br /&gt;
&lt;pre&gt;&lt;small&gt;mkdir -p xorg/util
git clone git://anongit.freedesktop.org/git/xorg/util/modular xorg/util/modular
cd xorg
./util/modular/build.sh --clone --autoresume built.modules /opt/xorg
&lt;/small&gt;&lt;/pre&gt;
&lt;small&gt;
&lt;/small&gt;

That takes a while but if any component fails to build (usually due to missing dependencies) just re-run the last command. The built.modules file contains all successfully built modules and the script will simply continue from the last component. Despite the name, build.sh will also &lt;i&gt;install&lt;/i&gt; each component into the specified prefix.&lt;br /&gt;
&lt;br /&gt;
You get &lt;i&gt;everything&lt;/i&gt; here, including a shiny new copy of xeyes. Yes, what you always wanted, I know &lt;br /&gt;
&lt;br /&gt;
Note that build.sh is just a &lt;a href="http://cgit.freedesktop.org/xorg/util/modular/tree/build.sh"&gt;shell script&lt;/a&gt;, so you can make changes to it. Disable the parts you don't want (fonts, for example) by commenting them out. Or alternatively, generate a list of all modules, remove the ones you don't want or need and build with that set only:
&lt;pre&gt;
&lt;small&gt;
./util/modular/build.sh -L &gt; module_list
vim module_list # you can skip fonts, apps (except xkbcomp) and exotic drivers
./util/modular/build.sh --clone --autoresume built.modules --modfile module_list /opt/xorg
&lt;/small&gt;
&lt;/pre&gt;

Either way, you end up with /opt/xorg/bin/Xorg, the X server binary. I just move my system-installed and then symlink the new one.&lt;br/&gt;
&lt;br /&gt;

&lt;pre&gt;&lt;small&gt;sudo mv /usr/bin/Xorg /usr/bin/Xorg_old
sudo ln -s /opt/xorg/bin/Xorg /usr/bin/Xorg
&lt;/small&gt;&lt;/pre&gt;

Next time when gdm starts the server, it'll start the one from git. You can now update modules from git one-by-one as you need to and just run make install in all of them. Alternatively, running the build.sh script again without the --clone parameter will simply git pull in each module.
&lt;br/&gt;&lt;br/&gt;
&lt;h2&gt;Setting up the environment&lt;/h2&gt;
What I then define is a few environment variables. In my .zshrc I have
&lt;pre&gt;&lt;small&gt;alias mpx=". $HOME/.exportrc.xorg"
&lt;/small&gt;&lt;/pre&gt;
and that file contains
&lt;pre&gt;&lt;small&gt;export PKG_CONFIG_PATH=/opt/xorg/lib/pkgconfig:/opt/xorg/share/pkgconfig
export LD_LIBRARY_PATH=/opt/xorg/lib/
export PATH=/opt/xorg/bin:$PATH
export ACLOCAL="aclocal -I /opt/xorg/share/aclocal"
export MANPATH=/opt/xorg/share/man/
&lt;/small&gt;&lt;/pre&gt;
So running "mpx" will start git versions of the clients, link clients against git versions of the libraries, or build against git versions of the protocol.
&lt;br/&gt;&lt;br/&gt;
&lt;h2&gt;Why this setup?&lt;/h2&gt;

The biggest advantage of this setup is simple: the system install doesn't get touched at all and if the git X server breaks changing the symlink back to /usr/bin/Xorg_old gives me a working X again. And it's equally quick to test Fedora rpms, just flick the symlink back and restart the server. I have similar trees for gnome, wayland, and a few other large projects.&lt;br /&gt;
&lt;br /&gt;
It also makes it simple to test if a specific bug is a distribution bug or an upstream bug. Install the matching X server branch instead of master and with a bit of symlink flicking you can check if the bug reproduces in both. For example, only a few weeks ago I noticed that xinput got BadAtom errors when run from /usr/bin but not when run from /opt/xorg/bin. Turns out it was a thing fixed in the upstream libXi but not backported to Fedora yet.&lt;br /&gt;&lt;br /&gt;

The drawback of this setup is that whenever the xorg-x11-server-Xorg module is updated, I need to move and symlink again. That could be automated with a script but so far I've just been too lazy to do it.&lt;br/&gt;&lt;br/&gt;

&lt;small&gt;
[Update 11.05.12: typo and minor fixes, explain build.sh -L]
&lt;/small&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/qfsoV_yMXvk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/7440622670581948654/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=7440622670581948654" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7440622670581948654?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7440622670581948654?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/qfsoV_yMXvk/testing-x-servers-from-git.html" title="Testing X servers from git" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/05/testing-x-servers-from-git.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEINSXcycSp7ImA9WhVVFUw.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-632444455653174450</id><published>2012-05-09T08:36:00.000+10:00</published><updated>2012-05-09T08:36:38.999+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-09T08:36:38.999+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>vimdir for project-specific vim settings</title><content type="html">Sometimes it feels that each project I work on has different indentation settings. Not quite true but still annoying. I don't know of a way to tell vim to auto-detect the indentation settings based on the current file (which, for X.Org projects wouldn't work anyway) but what has been incredibly useful is the &lt;a href="http://www.vim.org/scripts/script.php?script_id=1860"&gt;vimdir&lt;/a&gt; script.

It simply scans the directory tree upwards to find a .vimdir file and loads the settings from there. So I keep files like this around:
&lt;pre&gt;
setlocal noexpandtab shiftwidth=8 tabstop=8
&lt;/pre&gt;

The alternative is to add a snippet to the file itself but not every maintainer is happy with that.

&lt;pre&gt;
/* vim: set noexpandtab tabstop=8 shiftwidth=8: */
&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/00q9sYvlvKY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/632444455653174450/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=632444455653174450" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/632444455653174450?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/632444455653174450?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/00q9sYvlvKY/vimdir-for-project-specific-vim.html" title="vimdir for project-specific vim settings" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/05/vimdir-for-project-specific-vim.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QEQ3w5cCp7ImA9WhVVEU0.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-3733470202065921083</id><published>2012-05-04T14:21:00.003+10:00</published><updated>2012-05-04T14:21:42.228+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-04T14:21:42.228+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="workflow" /><title>Copy/paste of code is not ok</title><content type="html">Much too often, I see patches that add code copied from other sections of the same repository. The usual excuse is that, well, we know that block of code works, it's easy to copy and we immediately get the result we need.&lt;br /&gt;
&lt;br /&gt;
This is rather short-sighted. Whenever code is copied, the two instances will go and live separate lives. Code is never static, over time that copy becomes a partial reimplementation of the original.&lt;br /&gt;
&lt;br /&gt;
There are a few conditions when copy-paste is acceptable:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;You can guarantee that the original code does not have any bugs and thus the copy does not have any bugs, now or in the future. Otehr&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;You can guarantee that &lt;i&gt;anyone&lt;/i&gt; making changes to this code in the future is aware of the copy and the original and their respective contexts.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;You can guarantee that the context of the original and the copy never changes in a different manner.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;You are happy to reimburse testers and developers for the time wasted tracking down bugs caused by ignoring any of the three above.&lt;/li&gt;
&lt;/ul&gt;
If the above are true, copying code is ok. And you probably get some price for having found an impossible piece of code. In all other cases, write a helper function and share the code. If the helper function is to unwieldy, maybe it's time to think about the design and refactor some things.&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/mzCNYP9Rkro" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/3733470202065921083/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=3733470202065921083" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/3733470202065921083?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/3733470202065921083?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/mzCNYP9Rkro/copypaste-of-code-is-not-ok.html" title="Copy/paste of code is not ok" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/05/copypaste-of-code-is-not-ok.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cNQ3s7fSp7ImA9WhVVEU0.&quot;"><id>tag:blogger.com,1999:blog-6112936277054198647.post-7701694931843662424</id><published>2012-05-03T10:36:00.000+10:00</published><updated>2012-05-04T14:18:12.505+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-04T14:18:12.505+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xorg" /><category scheme="http://www.blogger.com/atom/ns#" term="synaptics" /><title>What's new in Synaptics 1.6.0</title><content type="html">&lt;a href="http://lists.freedesktop.org/archives/xorg-announce/2012-May/001944.html"&gt;xf86-input-synaptics 1.6.0&lt;/a&gt; was released today and it packs a bunch of changes. This post outlines some of these changes and future directions for the drive.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;

Clickpad support&lt;/h2&gt;
Clickpads are touchpads without physical buttons. Instead, the user has to press the whole pad down to trigger a click. These pads are becoming increasingly common in laptops but need a bunch of software workarounds to make them useful with traditional interaction methods. I've got a post dedicated to &lt;a href="http://who-t.blogspot.com.au/2012/04/clickpad-support-in-synaptics-driver.html"&gt;Clickpad support in the synaptics driver&lt;/a&gt;, so best to read that for more details.&lt;br /&gt;
&lt;br /&gt;
The important bit about clickpad support is that it's only available on multi-touch capable X servers. If you're running an older server, you won't see clickpad-y goodness. Sorry. &lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;

Smooth scrolling&lt;/h2&gt;
&lt;a href="http://who-t.blogspot.com.au/2011/09/whats-new-in-xi-21-smooth-scrolling.html"&gt;Smooth scrolling&lt;/a&gt; is now supported by the driver as well. On XI 2.1-compatible servers (read: server 1.12 &lt;span style="font-size: x-small;"&gt;[1]&lt;/span&gt;), the driver will submit scrolling valuators instead of scroll events. This makes for a smoother scrolling experience on clients that support it.&lt;br /&gt;
&lt;br /&gt;
We're in a transition period where clients start to enable smooth scrolling but many other clients don't support it yet. For now, we left coasting enabled by default in the driver to provide a consistent experience. This will likely be disabled once smooth scrolling support and client-side coasting becomes more prevalent.&lt;br /&gt;
&lt;br /&gt;
Meanwhile, clients can disable it by setting the "&lt;i&gt;Synaptics Coasting Speed&lt;/i&gt;" property to 0, 0.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;

Bugs, bugs, bugs&lt;/h2&gt;
Luckily I was able to spend quite some time on synaptics over the last weeks to fix various bugs and I think this is the most solid release of synaptics in quite a while. A few bugs that you may have seen that have now been fixed are:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;touchpad unresponsive after suspend&amp;nbsp; &lt;a href="https://bugs.freedesktop.org/show_bug.cgi?id=49161" target="_blank"&gt;#49161&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;weird cursor jumps while dragging&amp;nbsp;&lt;a href="http://bugs.freedesktop.org/show_bug.cgi?id=48777" target="_blank"&gt;#48777&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;broken double-tap &lt;a href="http://bugs.freedesktop.org/show_bug.cgi?id=31854" target="_blank"&gt;#31854&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;slow or too fast scrolling on pre-1.12 servers &lt;a href="http://bugs.freedesktop.org/show_bug.cgi?id=46617" target="_blank"&gt;#46617&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
and a few more.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;

Future of synaptics&lt;/h2&gt;
What becomes more and more obvious is that the driver is on the edge of being unmaintainable. Pushing new features into the driver always always means that some other feature is broken and sometimes we don't notice for months. Having around 75 options in the driver doesn't help here, testing all combinations is impossible.&lt;br /&gt;
&lt;br /&gt;
I can't claim that I have big plans because I tend to get pre-empted by misc things all the time but the rough plan is to keep a 1.6.x series while re-doing some of the internals of the driver for the 1.7 release. Expect the git master branch to see a few big changes though.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: x-small;"&gt;[1] Ubuntu 12.04 ships a 1.11 with the 1.12 input stack, so the above applies to that server too.&lt;/span&gt;&lt;img src="http://feeds.feedburner.com/~r/Who-t/~4/H3-lhPfNtzM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://who-t.blogspot.com/feeds/7701694931843662424/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6112936277054198647&amp;postID=7701694931843662424" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7701694931843662424?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6112936277054198647/posts/default/7701694931843662424?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Who-t/~3/H3-lhPfNtzM/whats-new-in-synaptics-160.html" title="What's new in Synaptics 1.6.0" /><author><name>Peter Hutterer</name><uri>http://www.blogger.com/profile/17204066043271384535</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://who-t.blogspot.com/2012/05/whats-new-in-synaptics-160.html</feedburner:origLink></entry></feed>
