summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--generic/tkCmds.c2
-rw-r--r--generic/tkInt.h1
-rw-r--r--unix/tkUnixEvent.c34
-rw-r--r--unix/tkUnixKey.c33
5 files changed, 60 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 165f388..b0a4fdf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-04-01 Don Porter <dgp@users.sourceforge.net>
+
+ * generic/tkInt.h: [Bug 3607830] Runtime checks that Xkb is
+ * unix/tkUnixEvent.c: available in the X server before trying to
+ * unix/tkUnixKey.c: use. Adapted from patch from Brian Griffin.
+
2013-03-27 Jan Nijtmans <nijtmans@users.sf.net>
* library/button.tcl: [Bug 3608074]: Add <<Invoke>> bindings to
diff --git a/generic/tkCmds.c b/generic/tkCmds.c
index a86ef84..e9c6401 100644
--- a/generic/tkCmds.c
+++ b/generic/tkCmds.c
@@ -421,7 +421,7 @@ TkFreeBindingTags(
* have to be freed.
*/
- ckfree(p);
+ ckfree((char *)p);
}
}
ckfree((char *) winPtr->tagPtr);
diff --git a/generic/tkInt.h b/generic/tkInt.h
index 9a36e1e..74fd351 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -570,6 +570,7 @@ typedef struct TkDisplay {
#define TK_DISPLAY_USE_IM (1 << 1)
#define TK_DISPLAY_WM_TRACING (1 << 3)
#define TK_DISPLAY_IN_WARP (1 << 4)
+#define TK_DISPLAY_USE_XKB (1 << 5)
/*
* One of the following structures exists for each error handler created by a
diff --git a/unix/tkUnixEvent.c b/unix/tkUnixEvent.c
index 59fba29..53e01ed 100644
--- a/unix/tkUnixEvent.c
+++ b/unix/tkUnixEvent.c
@@ -12,6 +12,14 @@
#include "tkUnixInt.h"
#include <signal.h>
+#ifdef HAVE_XKBKEYCODETOKEYSYM
+# include <X11/XKBlib.h>
+/* Work around stupid un-const-ified Xkb headers. Grrrrr.... */
+# define XkbOpenDisplay(D,V,E,M,m,R) \
+ (XkbOpenDisplay)((char *)(D),(V),(E),(M),(m),(R))
+#else
+# define XkbOpenDisplay(D,V,E,M,m,R) (V),(E),(M),(m),(R),(NULL)
+#endif
/*
* The following static indicates whether this module has been initialized in
@@ -116,7 +124,30 @@ TkpOpenDisplay(
CONST char *displayNameStr)
{
TkDisplay *dispPtr;
- Display *display = XOpenDisplay(displayNameStr);
+ Display *display;
+ int event = 0;
+ int error = 0;
+ int major = 1;
+ int minor = 0;
+ int reason = 0;
+ unsigned int use_xkb = 0;
+
+ /*
+ ** Bug [3607830]: Before using Xkb, it must be initialized and confirmed
+ ** that the serve supports it. The XkbOpenDisplay call
+ ** will perform this check and return NULL if the extension
+ ** is not supported.
+ */
+ display = XkbOpenDisplay(displayNameStr, &event, &error, &major, &minor, &reason);
+
+ if (display == NULL) {
+ /*fprintf(stderr,"event=%d error=%d major=%d minor=%d reason=%d\nDisabling xkb\n",
+ event, error, major, minor, reason);*/
+ display = XOpenDisplay(displayNameStr);
+ } else {
+ use_xkb = TK_DISPLAY_USE_XKB;
+ /*fprintf(stderr, "Using xkb %d.%d\n", major, minor);*/
+ }
if (display == NULL) {
return NULL;
@@ -124,6 +155,7 @@ TkpOpenDisplay(
dispPtr = (TkDisplay *) ckalloc(sizeof(TkDisplay));
memset(dispPtr, 0, sizeof(TkDisplay));
dispPtr->display = display;
+ dispPtr->flags |= use_xkb;
#ifdef TK_USE_INPUT_METHODS
OpenIM(dispPtr);
#endif
diff --git a/unix/tkUnixKey.c b/unix/tkUnixKey.c
index a730001..40cc779 100644
--- a/unix/tkUnixKey.c
+++ b/unix/tkUnixKey.c
@@ -12,11 +12,20 @@
#include "tkInt.h"
+/*
+** Bug [3607830]: Before using Xkb, it must be initialized. TkpOpenDisplay
+** does this and sets the USE_XKB flag if xkb is supported.
+** (should this be function ptr?)
+*/
#ifdef HAVE_XKBKEYCODETOKEYSYM
# include <X11/XKBlib.h>
#else
# define XkbKeycodeToKeysym(D,K,G,L) XKeycodeToKeysym(D,K,L)
#endif
+#define TkKeycodeToKeysym(D,K,G,L) \
+ ((D)->flags & TK_DISPLAY_USE_XKB) ? \
+ XkbKeycodeToKeysym((D)->display,K,G,L) : \
+ XKeycodeToKeysym((D)->display,K,L)
/*
* Prototypes for local functions defined in this file:
@@ -217,7 +226,7 @@ TkpGetString(
/*
* When mapping from a keysym to a keycode, need information about the
- * modifier state to be used so that when they call XkbKeycodeToKeysym taking
+ * modifier state to be used so that when they call TkKeycodeToKeysym taking
* into account the xkey.state, they will get back the original keysym.
*/
@@ -227,27 +236,23 @@ TkpSetKeycodeAndState(
KeySym keySym,
XEvent *eventPtr)
{
- Display *display;
+ TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
int state;
KeyCode keycode;
- display = Tk_Display(tkwin);
-
if (keySym == NoSymbol) {
keycode = 0;
} else {
- keycode = XKeysymToKeycode(display, keySym);
+ keycode = XKeysymToKeycode(dispPtr->display, keySym);
}
+ eventPtr->xkey.keycode = keycode;
if (keycode != 0) {
for (state = 0; state < 4; state++) {
- if (XkbKeycodeToKeysym(display, keycode, 0, state) == keySym) {
+ if (XLookupKeysym(&eventPtr->xkey, state) == keySym) {
if (state & 1) {
eventPtr->xkey.state |= ShiftMask;
}
if (state & 2) {
- TkDisplay *dispPtr;
-
- dispPtr = ((TkWindow *) tkwin)->dispPtr;
eventPtr->xkey.state |= dispPtr->modeModMask;
}
break;
@@ -332,7 +337,7 @@ TkpGetKeySym(
&& (eventPtr->xkey.state & LockMask))) {
index += 1;
}
- sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, 0,
+ sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode, 0,
index);
/*
@@ -347,7 +352,7 @@ TkpGetKeySym(
|| ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
|| ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
index &= ~1;
- sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode,
0, index);
}
}
@@ -358,7 +363,7 @@ TkpGetKeySym(
*/
if ((index & 1) && (sym == NoSymbol)) {
- sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ sym = TkKeycodeToKeysym(dispPtr, eventPtr->xkey.keycode,
0, index & ~1);
}
return sym;
@@ -408,7 +413,7 @@ TkpInitKeymapInfo(
if (*codePtr == 0) {
continue;
}
- keysym = XkbKeycodeToKeysym(dispPtr->display, *codePtr, 0, 0);
+ keysym = TkKeycodeToKeysym(dispPtr, *codePtr, 0, 0);
if (keysym == XK_Shift_Lock) {
dispPtr->lockUsage = LU_SHIFT;
break;
@@ -434,7 +439,7 @@ TkpInitKeymapInfo(
if (*codePtr == 0) {
continue;
}
- keysym = XkbKeycodeToKeysym(dispPtr->display, *codePtr, 0, 0);
+ keysym = TkKeycodeToKeysym(dispPtr, *codePtr, 0, 0);
if (keysym == XK_Mode_switch) {
dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
}