<?xml version="1.0"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
	<channel>
		<title>Alex Baines - Updates</title>
		<link>http://abaines.me.uk</link>
		<description>This page lists infrequent updates about new things that I've been working on.
</description>
		<language>en-gb</language>
		<lastBuildDate>Sun, 11 Nov 2018 17:08:15 +0000</lastBuildDate>
		<copyright>2018 Alex Baines</copyright>
		
		<item>
			<title>Layout independent keys with Linux & X11</title>
			<link>http://abaines.me.uk/updates/linux-x11-keys</link>
			<description>&lt;p&gt;With all the talk of new display managers like Mir and Wayland rising, this is
perhaps an outdated topic to discuss, but with overall documentation about
X11 and Xkb keyboard handling being pretty sparse, I thought I’d note my
findings down anyway.&lt;/p&gt;

&lt;p&gt;Getting a layout independent ID for a key - the same concept as a scancode - is
especially useful for games where you want to bind keys for specific finger
positions like WASD without worrying if the player is using an AZERTY keyboard,
or an alternate layout like dvorak or colemak.&lt;/p&gt;

&lt;p&gt;Doing this on Linux and X11 turns out to actually be pretty easy, although not
well documented.&lt;/p&gt;

&lt;p&gt;To give some context, X11 has two indentifiers related to keys: KeySyms and
KeyCodes. KeySyms are 32-bit ints which represent any symbol that might appear
on a key. Each key can have multiple KeySyms, for example the Q key on a QWERTY 
keyboard has (at least) two: q and Q (with alt-gr on a UK keyboard I get @ too).&lt;/p&gt;

&lt;p&gt;KeyCodes are 8-bit numbers ranging from 8 to 255 which each represent a
physical key. That same Q key only has one KeyCode no matter if you hold shift
or not. The mapping of KeyCodes to physical keys is implementation defined
though - depending on the keyboard driver in use, the Q key could have two
differing KeyCodes between two computers.&lt;/p&gt;

&lt;p&gt;However, in modern Linux distributions the keyboard driver is almost invariably
going to be evdev - so these KeyCodes can actually be used just fine as a layout
independent key identifier!&lt;/p&gt;

&lt;p&gt;Wait so you’re saying we’ve solved this already? Yup, so if that’s all you 
wanted to know you can just look up the KeyCode in xev and stop reading.
But let’s suppose that evdev was not ubiquitous, could we still get a layout
independent ID for each key? If you use a small bit of Xkb arcane magic, then
the answer, as I understand it, is yes.&lt;/p&gt;

&lt;p&gt;It turns out XKb knew this was what we wanted all along, and as part of its
&lt;a href=&quot;https://www.x.org/wiki/guide/hutterer-kbd/#index1h3&quot;&gt;RMLVO&lt;/a&gt; system has names
for every key on a standard US keyboard that are independent of what is actually
printed on the keys.
If you take a look at the files in /usr/share/X11/xkb/keycode/ you’ll see keys 
labelled with names such as “AD01”. This corresponds to the key 4 rows up
(the D) and 1 across - on QWERTY it’d be that Q key again.&lt;/p&gt;

&lt;figure&gt;
	&lt;a href=&quot;/img/xkb.png&quot;&gt;
	&lt;img src=&quot;/img/xkb.png&quot; alt=&quot;XKB Names&quot; title=&quot;XKB's generic key names.&quot; /&gt;
	&lt;/a&gt;
	&lt;figcaption&gt;XKB's generic key names.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;That’s all well and good, but how can we map this to a KeyCode or KeySym at
runtime? Handily, XKB stores an array of these “AD01” style names with the
array’s index corresponding to the X11 KeyCode. So it’s just a matter of
iterating through this array, finding the strange name of the key you’re
interested in, and noting down what the index was. An example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span class=&quot;c&quot;&gt;#if 0
    gcc -std=c99 $0 -o xkb-key-id -lX11 &amp;amp;&amp;amp; ./xkb-key-id &amp;amp;&amp;amp; exit
#endif
&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#include &amp;lt;X11/XKBlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#define countof(x) (sizeof(x)/sizeof(*x))
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Define which keys we want to look up
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_KEY_UP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_KEY_DOWN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_KEY_LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_KEY_RIGHT&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KeyInfo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keycode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MY_KEY_UP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;AD02&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 'w' on qwerty
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MY_KEY_DOWN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;AC02&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 's' on qwerty
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MY_KEY_LEFT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;AC01&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 'a' on qwerty
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MY_KEY_RIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;AC03&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 'd' on qwerty
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Open a handle to the X11 display server + initialize XKB
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbMajorVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;min&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbMinorVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dpy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbOpenDisplay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Find the keycodes for the keys we're interested in.
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;XkbDescPtr&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xkb&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbGetKeyboard&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbAllComponentsMask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbUseCoreKbd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xkb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max_key_code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strncmp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xkb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;XkbKeyNameLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keycode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Get the state + group for XkbLookupKeySym as (sort of) described by
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// XKBProto.pdf section 2.2.2. (With probably broken wrapping?)
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// I recommend just using the xkey.state field when you get a KeyPress
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// or KeyRelease, but this example doesn't do any event handling.
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;XkbStateRec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xkb_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;XkbGetState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XkbUseCoreKbd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xkb_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xkb_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Print out the keycodes / keysyms we got
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;countof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;KeySym&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sym&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NoSymbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;XkbLookupKeySym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keycode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Key %d: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, keycode: %d, keysym: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
               &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keycode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;XKeysymToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The KeyCodes printed out should match the codes listed in the KeyCode files, and
also the KeyCodes from xev. I haven’t thouroughly tested it, but I expect it 
should work regardless of the keyboard driver in use.&lt;/p&gt;

&lt;p&gt;To make use of these KeyCodes you’d compare them against the xkey.key_code field
of KeyPress and KeyRelease events from X11 - if they match you know which key
was pressed/released.&lt;/p&gt;

&lt;p&gt;If you want to get KeySyms from this, then you should be a bit careful -
XKeycodeToKeysym will only give you the KeySym from “group 1” of the keys. This
means that if a user has multiple keyboard layouts configured which they switch
between, then only the KeySym from the first layout will be returned, even if
they’re currently using the second.&lt;/p&gt;

&lt;p&gt;That’s probably why the function was deprecated - you should use XLookupKeysym
instead which uses the struct you get from KeyPress / KeyRelease events
(i.e. &amp;amp;event.xkey), and takes the currently active group into account.
Likewise for XkbKeycodeToKeysym which takes the state field of the same event 
that has the group encoded in its upper bits (You could calculate it manually
if you’re careful).&lt;/p&gt;

&lt;p&gt;If you want text input as well then use Xutf8LookupString which gives you the
correct KeySym as well as correct unicode text, accounting for dead keys,
compose keys and other complexities. I wrote a small example some time ago
for that &lt;a href=&quot;https://gist.github.com/baines/5a49f1334281b2685af5dcae81a6fa8a&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/baines/5a49f1334281b2685af5dcae81a6fa8a.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Hopefully that sheds some light on Linux + X11’s keyboard situation. TL;DR:
KeyCodes are good enough for layout independence, but there’s other fun stuff
lurking in the dusty X11 headers.&lt;/p&gt;

&lt;p&gt;Thanks for reading, If you have any comments, corrections or questions, drop me 
an email: alex @ this domain.&lt;/p&gt;
</description>

			<pubDate>Sat, 03 Sep 2016 00:00:00 +0000</pubDate>
			<guid>/updates/linux-x11-keys</guid>
		</item>
		
		<item>
			<title>Dares, Bots, and Ports, oh my!</title>
			<link>http://abaines.me.uk/updates/dares-bots-port-oh-my</link>
			<description>&lt;h3 id=&quot;ludum-dare&quot;&gt;Ludum Dare&lt;/h3&gt;

&lt;p&gt;Last week I took part in Ludum Dare 35, and created a game in 48 hours using C
and SDL2. I called it “VampShift: The Bloodening”, and following from the
competition’s theme of “shape-shift”, you play as a vampire that has to progress
through rooms via shape-shifting into a bat.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;a href=&quot;/ld35/&quot;&gt;&lt;img src=&quot;/img/vstb.png&quot; alt=&quot;VampShift: The Bloodening&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;a href=&quot;/ld35/&quot;&gt;play the web version here&lt;/a&gt;, or see its
&lt;a href=&quot;http://ludumdare.com/compo/ludum-dare-35/?action=preview&amp;amp;uid=64951&quot;&gt;Ludum Dare entry page here&lt;/a&gt;,
which includes links to the downloadable version for Linux &amp;amp; Windows.&lt;/p&gt;

&lt;p&gt;I also live-streamed the development of the game on Twitch. The VoDs are
available at &lt;a href=&quot;https://twitch.tv/insofaras/profile/highlights&quot;&gt;https://twitch.tv/insofaras/profile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You might be curious about the “insofaras” user name there. I originally picked
that (rather pretentious :/) name on twitch intending it to just be a random
anonymous account, but lately I’ve been doing some projects under that name
that I think are worth de-anonymizing it for.&lt;/p&gt;

&lt;p&gt;The first of which is:&lt;/p&gt;

&lt;h3 id=&quot;insobot&quot;&gt;Insobot&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/insofaras/insobot&quot;&gt;Insobot&lt;/a&gt; is an IRC bot written in C99 
with a modular structure; it can load and reload modules in the form of shared 
libraries (.so) at runtime without disconnecting from the server.
Various modules exist for it including, at the time of writing, modules for 
storing quotes, expanding URLs, showing twitch uptime / new followers, and 
giving the schedule for Handmade Hero.&lt;/p&gt;

&lt;p&gt;The reason that last module exists is because Insobot basically spawned out of
my involvement with the community around Handmade Hero (known as Handmade Dev or
Handmade Network), and my interest in creating a project that uses a more 
limited subset of C++ than I was used to.&lt;/p&gt;

&lt;p&gt;The community seems to appreciate insobot, and have used my insobot code as the
basis for their hmd_bot, which is designed to replace their previous hmh_bot
that was written in python. Perhaps the main reason insobot is “appreciated”
though is due to one of its modules that I haven’t mentioned yet - 
the Markov chain module.&lt;/p&gt;

&lt;p&gt;It’s a pretty standard &lt;a href=&quot;https://en.wikipedia.org/wiki/Markov_chain&quot;&gt;Markov chain&lt;/a&gt;
implementation that gets words — and connections between words — from the IRC
chat. When mentioned, or on a random chance, it will form a sentence of its own
and send that back for all to see.&lt;/p&gt;

&lt;p&gt;For something that doesn’t really amount to much more than a lot of rand(), it
has had some amusing results, several of which have been shared on twitter:&lt;/p&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://twitter.com/AllenWebster4th/status/708833510530883584&quot;&gt;
	&lt;img src=&quot;/img/ibq1.jpg&quot; alt=&quot;Insobot Quote&quot; title=&quot;Showing some understanding?&quot; /&gt;
	&lt;/a&gt;
	&lt;figcaption&gt;Showing some understanding?&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://twitter.com/JamesWidman/status/708840547453157376&quot;&gt;
	&lt;img src=&quot;/img/ibq2.jpg&quot; alt=&quot;Insobot Quote&quot; title=&quot;Strangely appropriate&quot; /&gt;
	&lt;/a&gt;
	&lt;figcaption&gt;Strangely appropriate&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://twitter.com/cmuratori/status/710311130401341441&quot;&gt;
	&lt;img src=&quot;/img/ibq3.png&quot; alt=&quot;Insobot Quote&quot; title=&quot;Not a fan of new programming languages&quot; /&gt;
	&lt;/a&gt;
	&lt;figcaption&gt;Not a fan of new programming languages&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure&gt;
	&lt;a href=&quot;https://twitter.com/d7samurai/status/716369247031730177&quot;&gt;
	&lt;img src=&quot;/img/ibq4.jpg&quot; alt=&quot;Insobot Quote&quot; title=&quot;Insulting my people&quot; /&gt;
	&lt;/a&gt;
	&lt;figcaption&gt;Insulting my people&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The source code of Insobot is avialable at &lt;a href=&quot;https://github.com/insofaras/insobot&quot;&gt;github.com/insofaras/insobot&lt;/a&gt;.
I’ll probably be moving it to my main github account at some point.&lt;/p&gt;

&lt;h3 id=&quot;4coder&quot;&gt;4coder&lt;/h3&gt;

&lt;p&gt;The second major project that I took on under the name Insofaras is helping
to port the &lt;a href=&quot;http://4coder.net&quot;&gt;4coder&lt;/a&gt; code editor to Linux.&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;a href=&quot;http://4coder.net&quot;&gt;&lt;img src=&quot;/img/4coder.png&quot; alt=&quot;4coder&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://4coder.net&quot;&gt;4coder&lt;/a&gt; is a project by Allen Webster to create an improved
editor for C and C++ programmers. He’s already implemented the standard text 
editor side of things, and is planning to add more advanced features that take
advantage of the editor itself having an understanding of the programming
languages in use.&lt;/p&gt;

&lt;p&gt;One of its defining features is the customisation layer, implemented through
loading a user-created DLL / shared-library. In contrast to the scripting
languages often found in other editors, this approach allows extension of
the editor with native compiled code, appropriate for its target audience of
C programmers.&lt;/p&gt;

&lt;p&gt;Mr Handmade Hero himself — Casey Muratori — has already found the current alpha
build good enough to replace Emacs; he recently switched to using 4coder
on his Twitch streams. That is, in the words of Allen Webster, awesome.&lt;/p&gt;

&lt;p&gt;My involvement with 4coder has been mainly implementing the stubbed-out functions
that were present in the Linux platform layer. This boils down to looking at
how the windows side is doing things, and translating that into a POSIX and
Linux approach.&lt;/p&gt;

&lt;p&gt;I’ve enjoyed doing this Linux porting work, if you have a project that you would
like a Linux version of, contact me: alex @ this site.&lt;/p&gt;

</description>

			<pubDate>Fri, 22 Apr 2016 00:00:00 +0000</pubDate>
			<guid>/updates/dares-bots-port-oh-my</guid>
		</item>
		
		<item>
			<title>Ramblings about C++ and Linux's perf.</title>
			<link>http://abaines.me.uk/updates/cpp-perf-ramblings</link>
			<description>&lt;p&gt;I’ve been watching some &lt;a href=&quot;https://handmadehero.org/&quot;&gt;Handmade Hero&lt;/a&gt; as of late, a series in which Casey
Muratori creates a game from about as scratch as you can get - not even using
the standard C runtime library.&lt;/p&gt;

&lt;p&gt;I can’t say I fully agree with his reluctance to use certain C++ features like
templates, but the series has shown some benefits to writing your own base code 
instead of relying on the standard library.&lt;/p&gt;

&lt;p&gt;Taking that to heart, I have started a
&lt;a href=&quot;https://github.com/baines/altlib&quot;&gt;small standard library of my own&lt;/a&gt;, with
some additions and replacements for some parts of C++’s STL. I don’t plan to
stop using std:: things in my code, but writing my own versions of certain bits
is, if nothing else, educational.&lt;/p&gt;

&lt;figure&gt;
	&lt;img src=&quot;/img/wheel.png&quot; alt=&quot;A wheel&quot; title=&quot;I'm not reinventing it, honest!&quot; /&gt;
	&lt;figcaption&gt;I'm not reinventing it, honest!&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;After I found &lt;code class=&quot;highlighter-rouge&quot;&gt;std::experimental::string_view&lt;/code&gt; from the draft of the next C++
version I started using it anywhere I didn’t need the mutability of std::string,
but being experimental it isn’t yet fully supported across compilers. Its
interoperability with &lt;code class=&quot;highlighter-rouge&quot;&gt;std::string&lt;/code&gt; isn’t that great either, which prompted me to
start my alternate standard library - &lt;a href=&quot;https://github.com/baines/altlib&quot;&gt;altlib&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;with two classes to replace them both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These two classes, &lt;code class=&quot;highlighter-rouge&quot;&gt;alt::StrMut&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;alt::StrRef&lt;/code&gt;, aren’t really all that 
interesting. They perform a little bit better than the std equivalents but its
nothing to write home about. The more interesting thing is a Linux tool I
discovered while debugging their performance, suitably named perf.&lt;/p&gt;

&lt;p&gt;A lot of people say the debugging tools on Linux suck compared to other OS’s.
While I agree that gdb’s interface is pretty user-unfriendly, I’ve always
considered valgrind a great counterexample to that argument. Maybe I’m just
tool-ignorant but I think perf is yet more proof that Linux has its fair share
of awesome debugging tools.&lt;/p&gt;

&lt;p&gt;The problem that I faced was determining why&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;n&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrMut&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;some random string literal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;was considerably slower than doing the same thing for std::string.
So, in my search for a tool to help me I found perf, compiled a small test case,
and ran &lt;code class=&quot;highlighter-rouge&quot;&gt;perf record&lt;/code&gt; on it to collect some performance data.&lt;/p&gt;

&lt;p&gt;The perf tool dumps out a perf.data file, which can then be analyzed with &lt;code class=&quot;highlighter-rouge&quot;&gt;perf
report&lt;/code&gt;. This was when my mind was slightly blown, as perf gives an amazing 
annotated view of the assembly. As well as having neat arrows to trace the flow
of jmp instructions, it lists the hot parts of the code that are bottlenecking
the program’s performance. If you compile with debugging symbols, it intermixes
the assembly with the source code too.&lt;/p&gt;

&lt;p&gt;I was quickly able to see the following code was the main bottleneck, in a
simple strlen equivalent function:&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;img src=&quot;/img/perf.png&quot; alt=&quot;Linux's perf utility in action&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But that seemed very odd to me, I had created the &lt;code class=&quot;highlighter-rouge&quot;&gt;StrMut&lt;/code&gt; class so that its
append method took a &lt;code class=&quot;highlighter-rouge&quot;&gt;const StrRef&amp;amp;&lt;/code&gt;, which the string literal could be implicitly
converted to with some constructors like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-cpp&quot; data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;StrRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* [...] */&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;StrRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrLen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* [...] */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I had assumed that a string literal would bind to the first one, which gets the
literal’s length at compile time with no need for a &lt;code class=&quot;highlighter-rouge&quot;&gt;StrLen&lt;/code&gt; call, but it was the
second constructor that was actually getting called.&lt;/p&gt;

&lt;p&gt;After some searching, I found a &lt;a href=&quot;https://stackoverflow.com/a/26725089&quot;&gt;stackoverflow answer&lt;/a&gt;
that seems to suggest that a string literal binds more easily to the latter 
style due to the former being a template call. I’m not sure if it should really
work that way, but apparently it does. I changed the second constructor to take
a plain &lt;code class=&quot;highlighter-rouge&quot;&gt;char*&lt;/code&gt; without the const to stop literals from binding to it, there’s
probably a better fix but that’ll do for the time being.&lt;/p&gt;

&lt;p&gt;So I suppose I should thank the Handmade Hero series, for inspiring me to write 
code which happened to have a bug that - in turn - introduced me to perf. It
will be a cool new tool in my Linux C++ debugging adventures!&lt;/p&gt;

</description>

			<pubDate>Fri, 28 Aug 2015 00:00:00 +0000</pubDate>
			<guid>/updates/cpp-perf-ramblings</guid>
		</item>
		
		<item>
			<title>New Game: Lawn-Mowing Robot</title>
			<link>http://abaines.me.uk/updates/puzzlescript-game</link>
			<description>&lt;p&gt;I felt unusually inspired recently after seeing lots of awesome puzzle games
being made with &lt;a href=&quot;http://www.puzzlescript.net/&quot;&gt;Puzzlescript&lt;/a&gt;.
Specifically, &lt;a href=&quot;http://www.draknek.org/games/puzzlescript/&quot;&gt;Train Braining and Mirror Isles by Draknek&lt;/a&gt;
which you should totally check out if you haven’t already.&lt;/p&gt;

&lt;p&gt;I’m no puzzle-game master like he is, but I had a go at making my own. I also 
don’t claim to be good at naming things - that’s why it’s called 
“Lawn-Mowing Robot”…&lt;/p&gt;

&lt;p class=&quot;center&quot;&gt;&lt;a href=&quot;/games/lawn-mowing-robot&quot;&gt;&lt;img src=&quot;/img/lmr.png&quot; alt=&quot;Screenshot of Lawn-Mowing Robot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The game plays a bit weirdly, but it’s only 8 levels and runs in a browser, so
I’d love for you to give it a try from the link below.&lt;/p&gt;

&lt;p&gt;It’s my first proper puzzle game so if you have any comments or feedback drop me
an email. Thanks!&lt;/p&gt;
</description>

			<pubDate>Sat, 28 Mar 2015 00:00:00 +0000</pubDate>
			<guid>/updates/puzzlescript-game</guid>
		</item>
		
		<item>
			<title>Website Updated</title>
			<link>http://abaines.me.uk/updates/website-updated</link>
			<description>&lt;p&gt;I’ve spent some time updating the website to have a better front page and a
new updates section, the most recent of which appear on it.&lt;/p&gt;

&lt;p&gt;The new section will just be for informative but infrequent updates about the 
site (like this one!) or stuff I’m doing and wanted to share.&lt;/p&gt;

&lt;p&gt;I also switched the site to HTTPS using a cloudflare free account. It seems to
be working well so far - I’m surprised they offer such a service for free
with seemingly no strings attached.&lt;/p&gt;
</description>

			<pubDate>Fri, 27 Mar 2015 00:00:00 +0000</pubDate>
			<guid>/updates/website-updated</guid>
		</item>
		
		<item>
			<title>Game engine ported to JS with Emscripten</title>
			<link>http://abaines.me.uk/updates/emscripen-engine</link>
			<description>&lt;p&gt;I’ve been messing with Emscripten and managed to port my OpenGL/SDL2 game
engine to Javascript &amp;amp; WebGL with it.&lt;/p&gt;

&lt;p&gt;The Engine itself is still pretty crap and you probably shouldn’t use it, 
but you could theoretically make web-games with it now, so that’s something.&lt;/p&gt;
</description>

			<pubDate>Fri, 13 Mar 2015 00:00:00 +0000</pubDate>
			<guid>/updates/emscripen-engine</guid>
		</item>
		
	</channel>
</rss>
	
