Get rid of XKBgeom things as geometries are optional, and soon to be removed from Xorg.
authorThibaut Girka <thib@sitedethib.com>
Thu, 21 Jul 2011 15:49:33 +0200
changeset 11 a4087b9e0406
parent 10 dacf8e3f253b
child 12 d83eef518a33
Get rid of XKBgeom things as geometries are optional, and soon to be removed from Xorg.
Makefile
keyboard-geom.h
keyboard.c
keyboard.h
keyboard.svg
main.c
scripts/make_keyboard_geom.py
--- a/Makefile	Thu Jul 21 12:56:11 2011 +0200
+++ b/Makefile	Thu Jul 21 15:49:33 2011 +0200
@@ -7,7 +7,15 @@
 all: touchkbd
 
 
-keyboard.o: keyboard.c keyboard.h
+keyboard-geom.c: keyboard.svg scripts/make_keyboard_geom.py
+	scripts/make_keyboard_geom.py keyboard.svg keyboard-geom.c
+
+
+keyboard-geom.o: keyboard-geom.c keyboard-geom.h
+	$(CC) -c keyboard-geom.c $(CFLAGS)
+
+
+keyboard.o: keyboard.c keyboard.h keyboard-geom.h
 	$(CC) -c keyboard.c $(CFLAGS)
 
 
@@ -19,12 +27,14 @@
 	$(CC) -c main.c $(CFLAGS)
 
 
-touchkbd: main.o keyboard.o ui.o
-	$(CC) -o touchkbd keyboard.o ui.o main.o $(LDFLAGS)
+
+touchkbd: main.o keyboard.o ui.o keyboard-geom.o
+	$(CC) -o touchkbd keyboard.o ui.o main.o keyboard-geom.o $(LDFLAGS)
 
 
 clean:
 	rm -f *.o
+	rm -f keyboard-geom.c
 
 
 mrproper: clean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keyboard-geom.h	Thu Jul 21 15:49:33 2011 +0200
@@ -0,0 +1,13 @@
+typedef struct _TouchkbdKeyGeom {
+    unsigned int    x, y;
+    unsigned int    width, height;
+    char            *keycode_name;
+} TouchkbdKeyGeom;
+
+typedef struct _TouchkbdKeyboardGeom {
+    unsigned int    width, height;
+    unsigned int    nb_keys;
+    TouchkbdKeyGeom *keys;
+} TouchkbdKeyboardGeom;
+
+extern TouchkbdKeyboardGeom keyboard_geom;
--- a/keyboard.c	Thu Jul 21 12:56:11 2011 +0200
+++ b/keyboard.c	Thu Jul 21 15:49:33 2011 +0200
@@ -1,45 +1,20 @@
 #include "keyboard.h"
+#include "keyboard-geom.h"
 #include <string.h>
 
 
-static int is_section_wanted(Display *display, XkbSectionPtr section, char **wanted_sections)
-{
-    int i;
-    char *section_name;
-
-    if (wanted_sections == NULL)
-        return True;
-
-    section_name = XGetAtomName(display, section->name);
-    for (i = 0; wanted_sections[i] != NULL; i++)
-    {
-        if (strcmp(wanted_sections[i], section_name) == 0)
-        {
-            XFree(section_name);
-            return True;
-        }
-    }
-
-    XFree(section_name);
-    return False;
-}
-
-
 /*
  * vkb is an already-allocated VirtualKeyboard with display set.
- * geom_name is the name of the geometry (ex: pc(pc105))
- * sections is a NULL-terminated array of sections names. If NULL is empty, all sections will be loaded.
  */
-VirtualKeyboard *construct_keyboard(VirtualKeyboard *vkb, char *geom_name, char **sections)
+VirtualKeyboard *construct_keyboard(VirtualKeyboard *vkb)
 {
     XkbComponentNamesRec names;
     VirtualKey *vkeys = NULL;
     unsigned int width = 0, height = 0;
-    unsigned int min_x = ~0, min_y = ~0;
     unsigned int nb_keys = 0;
-    int i, j, k, vkey_idx = 0;
+    int i = 0;
 
-    if (geom_name == NULL || vkb == NULL)
+    if (vkb == NULL)
         return NULL;
 
     /* Construct XkbComponentNamesRec */
@@ -48,11 +23,10 @@
     names.types = NULL;
     names.compat = NULL;
     names.symbols = NULL;
-    names.geometry = geom_name;
+    names.geometry = NULL;
 
     /* Get the xkb instance */
     vkb->xkb = XkbGetKeyboardByName (vkb->display, XkbUseCoreKbd, &names, 0,
-                                     XkbGBN_GeometryMask |
                                      XkbGBN_KeyNamesMask |
                                      XkbGBN_OtherNamesMask |
                                      XkbGBN_ClientSymbolsMask |
@@ -62,47 +36,10 @@
         return NULL;
 
 
-    if (vkb->xkb->geom == NULL)
-        return NULL;
-
-
-    for (i=0; i < vkb->xkb->geom->num_sections; i++)
-    {
-        XkbSectionPtr section = vkb->xkb->geom->sections + i;
-
-        /* Check we want this section. */
-        if (!is_section_wanted(vkb->display, section, sections))
-            continue;
-
-
-        if (section->angle != 0)
-        {
-            fprintf(stderr, "Rotated sections not supported! Skipped!\n");
-            continue;
-        }
-
-
-        /* Update global min_x, min_y, width and height characteristics */
-        if (min_x > section->left)
-            min_x = section->left;
-        if (min_y > section->top)
-            min_y = section->top;
-        if (width < section->left + section->width)
-            width = section->left + section->width;
-        if (height < section->top + section->height)
-            height = section->top + section->height;
-
-        /* Now, count keys. */
-        for (j=0; j < section->num_rows; j++)
-        {
-            XkbRowPtr row = section->rows + j;
-            nb_keys += row->num_keys;
-        }
-    }
-
     /* Update total width and height */
-    width -= min_x;
-    height -= min_y;
+    width = keyboard_geom.width;
+    height = keyboard_geom.height;
+    nb_keys = keyboard_geom.nb_keys;
 
     /* Allocate keys */
     vkeys = calloc(nb_keys, sizeof(VirtualKey));
@@ -110,33 +47,17 @@
         return NULL;
 
     /* Construct keyboard */
-    for (i=0; i < vkb->xkb->geom->num_sections; i++)
+    for (i=0; i < nb_keys; i++)
     {
-        XkbSectionPtr section = vkb->xkb->geom->sections + i;
-
-        if (!is_section_wanted(vkb->display, section, sections))
-            continue;
+        vkeys[i].x = keyboard_geom.keys[i].x;
+        vkeys[i].y = keyboard_geom.keys[i].y;
 
-        for (j=0; j < section->num_rows; j++)
-        {
-            XkbRowPtr row = section->rows + j;
-            unsigned int x = section->left + row->left - min_x;
-            for (k=0; k < row->num_keys; k++)
-            {
-                XkbBoundsRec bounds;
-                XkbKeyPtr key = row->keys + k;
+        vkeys[i].width = keyboard_geom.keys[i].width;
+        vkeys[i].height = keyboard_geom.keys[i].height;
 
-                bounds = XkbKeyShape(vkb->xkb->geom, key)->bounds;
-                vkeys[vkey_idx].x = x + bounds.x1;
-                vkeys[vkey_idx].y = section->top + row->top + bounds.y1 - min_y;
-                vkeys[vkey_idx].width = bounds.x2 - bounds.x1;
-                vkeys[vkey_idx].height = bounds.y2 - bounds.y1;
-                vkeys[vkey_idx].keycode = XkbFindKeycodeByName(vkb->xkb, key->name.name, True);
-                vkeys[vkey_idx].state = VirtualKeyReleased;
-                x += key->gap + bounds.x2;
-                vkey_idx++;
-            }
-        }
+        vkeys[i].keycode = XkbFindKeycodeByName(vkb->xkb, keyboard_geom.keys[i].keycode_name, True);
+
+        vkeys[i].state = VirtualKeyReleased;
     }
 
     /* Update keyboard's properties */
--- a/keyboard.h	Thu Jul 21 12:56:11 2011 +0200
+++ b/keyboard.h	Thu Jul 21 15:49:33 2011 +0200
@@ -7,7 +7,6 @@
 #include <X11/Xlib.h>
 #include <X11/XKBlib.h>
 
-#include <X11/extensions/XKBgeom.h>
 #include <X11/extensions/XKBfile.h>
 
 
@@ -44,7 +43,7 @@
 } VirtualKeyboard;
 
 
-VirtualKeyboard *construct_keyboard(VirtualKeyboard *vkb, char *geom_name, char **sections);
+VirtualKeyboard *construct_keyboard(VirtualKeyboard *vkb);
 VirtualKey *keyboard_locate_key(VirtualKeyboard *vkb, int x, int y);
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/keyboard.svg	Thu Jul 21 15:49:33 2011 +0200
@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="749.99994"
+   height="250"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.1 r9760"
+   sodipodi:docname="keyboard.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="206.53793"
+     inkscape:cy="116.55521"
+     inkscape:document-units="px"
+     inkscape:current-layer="svg2"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1280"
+     inkscape:window-height="725"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <rect
+     y="0"
+     x="3.4204101e-07"
+     height="49.999996"
+     width="49.999996"
+     id="TLDE"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AE01"
+     width="49.999996"
+     height="49.999996"
+     x="50"
+     y="0" />
+  <rect
+     y="0"
+     x="100"
+     height="49.999996"
+     width="49.999996"
+     id="AE02"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AE03"
+     width="49.999996"
+     height="49.999996"
+     x="150"
+     y="0" />
+  <rect
+     y="0"
+     x="200"
+     height="49.999996"
+     width="49.999996"
+     id="AE04"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AE06"
+     width="49.999996"
+     height="49.999996"
+     x="300"
+     y="0" />
+  <rect
+     y="0"
+     x="249.99998"
+     height="49.999996"
+     width="49.999996"
+     id="AE05"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AE07"
+     width="49.999996"
+     height="49.999996"
+     x="349.99997"
+     y="0" />
+  <rect
+     y="0"
+     x="399.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AE08"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AE09"
+     width="49.999996"
+     height="49.999996"
+     x="449.99997"
+     y="0" />
+  <rect
+     y="0"
+     x="499.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AE10"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AE11"
+     width="49.999996"
+     height="49.999996"
+     x="549.99994"
+     y="0" />
+  <rect
+     y="0"
+     x="599.99994"
+     height="49.999996"
+     width="49.999996"
+     id="AE12"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="BKSP"
+     width="99.999992"
+     height="49.999996"
+     x="649.99994"
+     y="0" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="TAB"
+     width="74.999992"
+     height="49.999996"
+     x="3.4204101e-07"
+     y="50" />
+  <rect
+     y="50"
+     x="75"
+     height="49.999996"
+     width="49.999996"
+     id="AD01"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AD02"
+     width="49.999996"
+     height="49.999996"
+     x="125"
+     y="50" />
+  <rect
+     y="50"
+     x="175"
+     height="49.999996"
+     width="49.999996"
+     id="AD03"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AD04"
+     width="49.999996"
+     height="49.999996"
+     x="224.99998"
+     y="50" />
+  <rect
+     y="50"
+     x="274.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AD05"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AD06"
+     width="49.999996"
+     height="49.999996"
+     x="324.99997"
+     y="50" />
+  <rect
+     y="50"
+     x="374.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AD07"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AD08"
+     width="49.999996"
+     height="49.999996"
+     x="424.99997"
+     y="50" />
+  <rect
+     y="50"
+     x="474.99994"
+     height="49.999996"
+     width="49.999996"
+     id="AD09"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AD10"
+     width="49.999996"
+     height="49.999996"
+     x="524.99994"
+     y="50" />
+  <rect
+     y="50"
+     x="574.99994"
+     height="49.999996"
+     width="49.999996"
+     id="AD11"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AD12"
+     width="49.999996"
+     height="49.999996"
+     x="624.99994"
+     y="50" />
+  <rect
+     y="50"
+     x="674.99994"
+     height="49.999996"
+     width="74.999992"
+     id="BKSL"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     y="100"
+     x="3.4204101e-07"
+     height="49.999996"
+     width="99.999992"
+     id="CAPS"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AC01"
+     width="49.999996"
+     height="49.999996"
+     x="100"
+     y="100" />
+  <rect
+     y="100"
+     x="150"
+     height="49.999996"
+     width="49.999996"
+     id="AC02"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AC03"
+     width="49.999996"
+     height="49.999996"
+     x="199.99998"
+     y="100" />
+  <rect
+     y="100"
+     x="249.99998"
+     height="49.999996"
+     width="49.999996"
+     id="AC04"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AC05"
+     width="49.999996"
+     height="49.999996"
+     x="299.99997"
+     y="100" />
+  <rect
+     y="100"
+     x="349.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AC06"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AC07"
+     width="49.999996"
+     height="49.999996"
+     x="399.99997"
+     y="100" />
+  <rect
+     y="100"
+     x="449.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AC08"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AC09"
+     width="49.999996"
+     height="49.999996"
+     x="499.99997"
+     y="100" />
+  <rect
+     y="100"
+     x="549.99994"
+     height="49.999996"
+     width="49.999996"
+     id="AC10"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AC11"
+     width="49.999996"
+     height="49.999996"
+     x="599.99994"
+     y="100" />
+  <rect
+     y="100"
+     x="649.99994"
+     height="49.999996"
+     width="99.999992"
+     id="RTRN"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     y="150"
+     x="125"
+     height="49.999996"
+     width="49.999996"
+     id="AB01"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AB02"
+     width="49.999996"
+     height="49.999996"
+     x="175"
+     y="150" />
+  <rect
+     y="150"
+     x="225"
+     height="49.999996"
+     width="49.999996"
+     id="AB03"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AB04"
+     width="49.999996"
+     height="49.999996"
+     x="275"
+     y="150" />
+  <rect
+     y="150"
+     x="324.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AB05"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AB06"
+     width="49.999996"
+     height="49.999996"
+     x="374.99997"
+     y="150" />
+  <rect
+     y="150"
+     x="424.99997"
+     height="49.999996"
+     width="49.999996"
+     id="AB07"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AB08"
+     width="49.999996"
+     height="49.999996"
+     x="474.99997"
+     y="150" />
+  <rect
+     y="150"
+     x="524.99994"
+     height="49.999996"
+     width="49.999996"
+     id="AB09"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="AB10"
+     width="49.999996"
+     height="49.999996"
+     x="574.99994"
+     y="150" />
+  <rect
+     y="150"
+     x="3.4204101e-07"
+     height="49.999996"
+     width="74.999992"
+     id="LFSH"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="RTSH"
+     width="124.99999"
+     height="49.999996"
+     x="624.99994"
+     y="150" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="LCTL"
+     width="74.999992"
+     height="49.999996"
+     x="3.4204101e-07"
+     y="200" />
+  <rect
+     y="200"
+     x="75"
+     height="49.999996"
+     width="74.999992"
+     id="LWIN"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="LALT"
+     width="74.999992"
+     height="49.999996"
+     x="150"
+     y="200" />
+  <rect
+     y="200"
+     x="674.99994"
+     height="49.999996"
+     width="74.999992"
+     id="RCTL"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="MENU"
+     width="74.999992"
+     height="49.999996"
+     x="599.99994"
+     y="200" />
+  <rect
+     y="200"
+     x="524.99994"
+     height="49.999996"
+     width="74.999992"
+     id="RWIN"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="RALT"
+     width="74.999992"
+     height="49.999996"
+     x="449.99997"
+     y="200" />
+  <rect
+     y="200"
+     x="224.99998"
+     height="49.999996"
+     width="224.99998"
+     id="SPCE"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+     id="LSGT"
+     width="49.999996"
+     height="49.999996"
+     x="74.999992"
+     y="150" />
+</svg>
--- a/main.c	Thu Jul 21 12:56:11 2011 +0200
+++ b/main.c	Thu Jul 21 15:49:33 2011 +0200
@@ -36,10 +36,7 @@
 
     vkb->display = dpy;
 
-    //if (construct_keyboard(vkb, "winbook(XP5)", NULL) == NULL)
-    char *section = "Alpha";
-    char *sections[2] = {section, NULL};
-    if (construct_keyboard(vkb, "pc(pc105)", sections) == NULL)
+    if (construct_keyboard(vkb) == NULL)
     {
         fprintf(stderr, "ERROR: failed to construct keyboard\n");
         return 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/make_keyboard_geom.py	Thu Jul 21 15:49:33 2011 +0200
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+"""Usage: make_keyboard_geom source_file out_file
+"""
+
+import sys
+import xml.dom.minidom
+
+
+def main(source_file, out_file):
+    keys = {}
+    width = 0
+    height = 0
+    document = xml.dom.minidom.parse(source_file)
+    for rect in document.documentElement.getElementsByTagName('rect'):
+        rect_id = rect.getAttribute('id')[:4]
+        if not rect_id.isupper():
+            continue
+
+        rect_x = int(round(float(rect.getAttribute('x'))))
+        rect_y = int(round(float(rect.getAttribute('y'))))
+        rect_width = int(round(float(rect.getAttribute('width'))))
+        rect_height = int(round(float(rect.getAttribute('height'))))
+        keys[rect_id] = '{%d, %d, %d, %d, "%s"}' % (rect_x, rect_y, rect_width, rect_height, rect_id)
+
+        width = max(rect_x + rect_width, width)
+        height = max(rect_y + rect_height, height)
+
+    with open(out_file, 'w') as file:
+        file.write('#include "keyboard-geom.h"\n\n')
+        file.write('TouchkbdKeyGeom keys_geom[%d] = {' % len(keys))
+        content = ',\n    '.join(key for key in keys.values())
+        file.write(content)
+        file.write('};\n\n')
+        file.write('TouchkbdKeyboardGeom keyboard_geom = {%d, %d, %d, keys_geom};\n' % (width, height, len(keys)))
+
+
+
+if __name__ == '__main__':
+    main(*sys.argv[1:])