# HG changeset patch
# User Mads Kiilerich <[email protected]>
# Date 1301337958 -7200
# Node ID baa78bb6c387807ccc1906c3a734f9363925fafa
# Parent  6a33087569558a7ff6e2d92f0b6c9dc9f7b1594d
libfreerdpkbd: use libxkbfile directly instead of invoking xprop and setxkbmap


Hi

I would like to commit this. Do you see any fundamental issues with this 
approach?


Calling directly is faster and removes some dependencies and is less fragile as
it avoids parsing the output.

This removes the secret indirect dependency to xkb and makes it explicit and 
optional.
Most users should now make sure they have xkbfile development headers installed
so they get the full functionality.

Note that display now has to be initialized before we can call xf_kb_init, so
the keyboard initialization is shuffled around a bit.

/Mads

diff --git a/X11/xf_keyboard.c b/X11/xf_keyboard.c
--- a/X11/xf_keyboard.c
+++ b/X11/xf_keyboard.c
@@ -33,9 +33,9 @@
 static RD_BOOL pressed_keys[256] = { False };
 
 void
-xf_kb_init(unsigned int keyboard_layout_id)
+xf_kb_init(Display *dpy, unsigned int keyboard_layout_id)
 {
-       xf_kb_keyboard_layout = freerdp_kbd_init(keyboard_layout_id);
+       xf_kb_keyboard_layout = freerdp_kbd_init(dpy, keyboard_layout_id);
        DEBUG_KBD("freerdp_kbd_init: %X\n", xf_kb_keyboard_layout);
 }
 
diff --git a/X11/xf_keyboard.h b/X11/xf_keyboard.h
--- a/X11/xf_keyboard.h
+++ b/X11/xf_keyboard.h
@@ -20,11 +20,13 @@
 #ifndef __XF_KEYBOARD_H
 #define __XF_KEYBOARD_H
 
+#include <X11/Xlib.h>
+
 #include <freerdp/freerdp.h>
 #include "xf_types.h"
 
 void
-xf_kb_init(unsigned int keyboard_layout_id);
+xf_kb_init(Display *dpy, unsigned int keyboard_layout_id);
 void
 xf_kb_inst_init(xfInfo * xfi);
 void
diff --git a/X11/xf_win.c b/X11/xf_win.c
--- a/X11/xf_win.c
+++ b/X11/xf_win.c
@@ -1078,7 +1078,6 @@
        xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_num);
        xfi->depth = DefaultDepthOfScreen(xfi->screen);
        xfi->xserver_be = (ImageByteOrder(xfi->display) == MSBFirst);
-       xf_kb_inst_init(xfi);
 
        if (xfi->percentscreen > 0)
        {
diff --git a/X11/xfreerdp.c b/X11/xfreerdp.c
--- a/X11/xfreerdp.c
+++ b/X11/xfreerdp.c
@@ -584,6 +584,8 @@
                printf("run_xfreerdp: freerdp_chanman_pre_connect failed\n");
                return XF_EXIT_CONN_FAILED;
        }
+       xf_kb_init(xfi->display, xfi->keyboard_layout_id);
+       xf_kb_inst_init(xfi);
        printf("keyboard_layout: 0x%X\n", inst->settings->keyboard_layout);
        /* call connect */
        if (inst->rdp_connect(inst) != 0)
@@ -776,7 +778,6 @@
                        break;
                }
 
-               xf_kb_init(xfi->keyboard_layout_id);
                DEBUG("starting thread %d to %s:%d\n", g_thread_count,
                        xfi->settings->server, xfi->settings->tcp_port_rdp);
                if (pthread_create(&thread, 0, thread_func, xfi) == 0)
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -18,6 +18,7 @@
 AH_TEMPLATE(IPv6, [IPv6])
 AH_TEMPLATE(NEED_ALIGN, [Alignment])
 AH_TEMPLATE(DISABLE_TLS, [Disable TLS encryption])
+AH_TEMPLATE(WITH_XKBFILE, [Use xkbfile for keyboard handling])
 AH_TEMPLATE(WITH_SCARD, [Define if smartcard is enabled])
 AH_TEMPLATE(WITH_DEBUG, [Turn on debugging messages])
 AH_TEMPLATE(WITH_DEBUG_NLA, [Turn on debugging messages])
@@ -938,6 +939,25 @@
 fi
 
 #
+# xkbfile
+#
+AC_ARG_WITH([xkbfile],
+       [AS_HELP_STRING([--with-xkbfile], [use xkbfile for keyboard 
detection])])
+xkbfile=no
+AS_IF([test "x$with_xkbfile" != xno], [
+       PKG_CHECK_MODULES(XKBFILE, [xkbfile], [
+               xkbfile=yes
+               AC_DEFINE(WITH_XKBFILE,1)
+               AC_SUBST(XKBFILE_CFLAGS)
+               AC_SUBST(XKBFILE_LIBS)
+       ], [
+               if test "x$with_xkbfile" == xyes; then
+                       AC_MSG_ERROR([xkbfile development headers not found])
+               fi
+       ])
+])
+
+#
 # DirectFB (optionally built when --with-dfb specified)
 #
 dfb="no"
@@ -1005,4 +1025,5 @@
 echo "Printer      : $printer"
 echo "CUnit        : $cunit"
 echo "X11          : $x11"
+echo "xkbfile      : $xkbfile"
 echo "DirectFB     : $dfb"
diff --git a/include/freerdp/kbd.h b/include/freerdp/kbd.h
--- a/include/freerdp/kbd.h
+++ b/include/freerdp/kbd.h
@@ -35,7 +35,7 @@
 rdpKeyboardLayout *
 freerdp_kbd_get_layouts(int types);
 unsigned int
-freerdp_kbd_init(unsigned int keyboard_layout_id);
+freerdp_kbd_init(void *dpy, unsigned int keyboard_layout_id);
 uint8
 freerdp_kbd_get_scancode_by_keycode(uint8 keycode, RD_BOOL * extended);
 uint8
diff --git a/libfreerdpkbd/Makefile.am b/libfreerdpkbd/Makefile.am
--- a/libfreerdpkbd/Makefile.am
+++ b/libfreerdpkbd/Makefile.am
@@ -13,7 +13,7 @@
 libfreerdpkbd_la_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
        -DKEYMAP_PATH=\"$(KEYMAP_PATH)\"
 
-libfreerdpkbd_la_LDFLAGS =
+libfreerdpkbd_la_LDFLAGS = @XKBFILE_LIBS@
 
 # extra
 EXTRA_DIST =
diff --git a/libfreerdpkbd/libfreerdpkbd.c b/libfreerdpkbd/libfreerdpkbd.c
--- a/libfreerdpkbd/libfreerdpkbd.c
+++ b/libfreerdpkbd/libfreerdpkbd.c
@@ -17,9 +17,17 @@
    limitations under the License.
 */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#ifdef WITH_XKBFILE
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#include <X11/extensions/XKBfile.h>
+#include <X11/extensions/XKBrules.h>
+#endif
 
 #include <freerdp/freerdp.h>
 #include <freerdp/kbd.h>
@@ -103,126 +111,70 @@
        return layouts;
 }
 
+#ifdef WITH_XKBFILE
+
+/* return substring starting after nth comma, ending at following comma */
+static char *
+comma_substring(char *s, int n)
+{
+       char *p;
+       while (n--) {
+               if (!(p = strchr(s, ',')))
+                       break;
+               s = p + 1;
+       }
+       if ((p = strchr(s, ',')) != NULL)
+               *p = 0;
+       return s;
+}
+
 static unsigned int
-detect_keyboard_layout_from_xkb()
+detect_keyboard_layout_from_xkb(void *dpy)
 {
-       FILE* xprop;
+       char *layout, *variant;
+       unsigned int keyboard_layout = 0;
+       XkbRF_VarDefsRec rules_names;
 
-       char* pch;
-       char* beg;
-       char* end;
+       DEBUG_KBD(" display: %p\n", dpy);
+       if (dpy && XkbRF_GetNamesProp(dpy, NULL, &rules_names))
+       {
+               DEBUG_KBD(" layouts: %s\n", rules_names.layout);
+               DEBUG_KBD(" variants: %s\n", rules_names.variant);
 
-       char* layout = NULL;
-       char* variant = NULL;
+               layout = comma_substring(rules_names.layout, 0);
+               variant = comma_substring(rules_names.variant, 0);
 
-       char buffer[1024];
-       unsigned int keyboard_layout = 0;
+               DEBUG_KBD(" layout: %s\n", layout);
+               DEBUG_KBD(" variant: %s\n", variant);
 
-       xprop = popen("xprop -root _XKB_RULES_NAMES", "r");
-       /* _XKB_RULES_NAMES(STRING) = "evdev", "pc105", "gb", "", 
"lv3:ralt_switch" */
-       /* _XKB_RULES_NAMES(STRING) = "evdev", "evdev", "us,dk,gb", ",,", 
"grp:shift_caps_toggle" */
+               keyboard_layout = find_keyboard_layout_in_xorg_rules(layout, 
variant);
 
-       while(fgets(buffer, sizeof(buffer), xprop) != NULL)
-       {
-               if((pch = strstr(buffer, "_XKB_RULES_NAMES(STRING) = ")) != 
NULL)
-               {
-                       /* Skip "rules" */
-                       pch = strchr(&buffer[27], ',');
-                       if (pch == NULL)
-                               continue;
+               free(rules_names.model);
+               free(rules_names.layout);
+               free(rules_names.variant);
+               free(rules_names.options);
+       }
 
-                       /* Skip "type" */
-                       pch = strchr(pch + 1, ',');
-                       if (pch == NULL)
-                               continue;
-
-                       /* Parse "layout" */
-                       beg = strchr(pch + 1, '"');
-                       if (beg == NULL)
-                               continue;
-                       end = strchr(beg + 1, '"');
-                       if (end == NULL)
-                               continue;
-                       *end = '\0';
-                       layout = beg + 1;
-
-                       /* Truncate after first of multiple layouts */
-                       pch = strchr(layout, ',');
-                       if (pch != NULL)
-                               *pch = '\0';
-
-                       /* Parse "variant" */
-                       beg = strchr(end + 1, '"');
-                       if (beg == NULL)
-                               continue;
-                       end = strchr(beg + 1, '"');
-                       if (end == NULL)
-                               continue;
-                       *end = '\0';
-                       variant = beg + 1;
-
-                       /* Truncate after first of multiple variants */
-                       pch = strchr(variant, ',');
-                       if (pch != NULL)
-                               *pch = '\0';
-               }
-       }
-       pclose(xprop);
-
-       keyboard_layout = find_keyboard_layout_in_xorg_rules(layout, variant);
        return keyboard_layout;
 }
 
 static unsigned int
-detect_keyboard_type_from_xkb(char* xkbfile, int length)
+detect_keyboard_type_from_xkb(Display *dpy, char* xkbfile, int length)
 {
-       char* pch;
-       char* beg;
-       char* end;
-       char buffer[1024];
-       unsigned int rv = 0;
+       XkbDescPtr xkb;
 
-       FILE* setxkbmap;
-
-       // This tells us about the current XKB configuration, if XKB is 
available
-       setxkbmap = popen("setxkbmap -print", "r");
-
-       while(fgets(buffer, sizeof(buffer), setxkbmap) != NULL)
+       if (dpy && (xkb = XkbGetMap(dpy, 0, XkbUseCoreKbd)))
        {
-               // The line with xkb_keycodes is what interests us
-               pch = strstr(buffer, "xkb_keycodes");
-
-               if(pch != NULL)
-               {
-                       pch = strstr(pch, "include");
-                       if(pch != NULL)
-                       {
-                               // Check " " delimiter presence
-                               if((beg = strchr(pch, '"')) == NULL)
-                                       break;
-                               else
-                                       beg++;
-
-                               if((pch = strchr(beg + 1, '"')) == NULL)
-                                       break;
-
-                               end = strcspn(beg + 1, "\"") + beg + 1;
-                               *end = '\0';
-
-                               strncpy(xkbfile, beg, length);
-
-                               rv = 1;
-                               break;
-                       }
-               }
+               if (XkbGetNames(dpy, XkbKeyTypesMask, xkb) == Success)
+                       strncpy(xkbfile, XkbAtomText(dpy, xkb->names->keycodes, 
XkbMessage), length);
+               XkbFreeKeyboard(xkb, 0, 1);
        }
 
-       if (xkbfile[0] == '\0')
-               strcpy(xkbfile, "base");
+       DEBUG_KBD("XkbGetNames keycodes: %s\n", xkbfile);
+       return 1;
+}
 
-       pclose(setxkbmap);
-       return rv;
-}
+#endif
 
 static unsigned int
 detect_keyboard_layout_from_locale()
@@ -569,7 +521,7 @@
 }
 
 static unsigned int
-detect_keyboard(unsigned int keyboardLayoutID, char *xkbfile, size_t 
xkbfilelength)
+detect_keyboard(void *dpy, unsigned int keyboardLayoutID, char *xkbfile, 
size_t xkbfilelength)
 {
        xkbfile[0] = '\0';
 
@@ -584,11 +536,13 @@
        }
 #endif
 
+#ifdef WITH_XKBFILE
        if(keyboardLayoutID == 0)
        {
-               keyboardLayoutID = detect_keyboard_layout_from_xkb();
+               keyboardLayoutID = detect_keyboard_layout_from_xkb(dpy);
                DEBUG_KBD("detect_keyboard_layout_from_xkb: %X\n", 
keyboardLayoutID);
        }
+#endif
 
        if(keyboardLayoutID == 0)
        {
@@ -604,7 +558,10 @@
 
        if (xkbfile[0] == '\0')
        {
-               detect_keyboard_type_from_xkb(xkbfile, xkbfilelength);
+               strncpy(xkbfile, "base", xkbfilelength);
+#ifdef WITH_XKBFILE
+               detect_keyboard_type_from_xkb(dpy, xkbfile, xkbfilelength);
+#endif
                DEBUG_KBD("detect_keyboard_type_from_xkb: %s\n", xkbfile);
        }
 
@@ -670,11 +627,19 @@
        }
 }
 
+/* Initialize global keyboard mapping and return the suggested server side 
layout.
+   dpy must be a X Display* or NULL. */
 unsigned int
-freerdp_kbd_init(unsigned int keyboard_layout_id)
+freerdp_kbd_init(void *dpy, unsigned int keyboard_layout_id)
 {
        char xkbfile[256];
-       keyboard_layout_id = detect_keyboard(keyboard_layout_id, xkbfile, 
sizeof(xkbfile));
+
+#ifdef WITH_XKBFILE
+       if (!XkbQueryExtension(dpy, NULL, NULL, NULL, NULL, NULL))
+               return 0;
+#endif
+
+       keyboard_layout_id = detect_keyboard(dpy, keyboard_layout_id, xkbfile, 
sizeof(xkbfile));
 
        printf("Using keyboard layout 0x%X with xkb name %s and xkbfile %s\n",
                        keyboard_layout_id, 
get_layout_name(keyboard_layout_id), xkbfile);

------------------------------------------------------------------------------
Create and publish websites with WebMatrix
Use the most popular FREE web apps or write code yourself; 
WebMatrix provides all the features you need to develop and publish 
your website. http://p.sf.net/sfu/ms-webmatrix-sf
_______________________________________________
Freerdp-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freerdp-devel

Reply via email to