|
@@ -95,58 +95,6 @@ static int translateKey(int keycode)
|
|
|
return _glfw.x11.keyCodeLUT[keycode];
|
|
|
}
|
|
|
|
|
|
-// Translates an X Window event to Unicode
|
|
|
-//
|
|
|
-static wchar_t * translateChar(XEvent * event, _GLFWwindow * window, int * count)
|
|
|
-{
|
|
|
- KeySym keysym;
|
|
|
- static wchar_t buffer[16];
|
|
|
-
|
|
|
- // If there is no input method / context available, use the old fallback
|
|
|
- // mechanism
|
|
|
- if (!window || !window->x11.ic)
|
|
|
- {
|
|
|
- long uc;
|
|
|
-
|
|
|
- // Get X11 keysym
|
|
|
- XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
|
|
|
-
|
|
|
- // Convert to Unicode (see x11_unicode.c)
|
|
|
- uc = _glfwKeySym2Unicode(keysym);
|
|
|
- if (uc < 0 || uc > 0xFFFF)
|
|
|
- {
|
|
|
- *count = 0;
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- buffer[0] = (unsigned int)uc;
|
|
|
- *count = 1;
|
|
|
- }
|
|
|
- // Else lookup the wide char string with respect to dead characters
|
|
|
- else
|
|
|
- {
|
|
|
- Status dummy;
|
|
|
-
|
|
|
- // Check if the given event is a dead char. In that case, it does not
|
|
|
- // produce a unicode char.
|
|
|
- if (XFilterEvent(event, None))
|
|
|
- {
|
|
|
- *count = 0;
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- // Retrieve unicode string
|
|
|
- *count = XwcLookupString(window->x11.ic, &event->xkey, buffer, 16 * sizeof(wchar_t), 0, &dummy);
|
|
|
- if (*count < 0)
|
|
|
- {
|
|
|
- *count = 0;
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return buffer;
|
|
|
-}
|
|
|
-
|
|
|
// Return the GLFW window corresponding to the specified X11 window
|
|
|
//
|
|
|
static _GLFWwindow* findWindowByHandle(Window handle)
|
|
@@ -240,8 +188,6 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|
|
unsigned long wamask;
|
|
|
XSetWindowAttributes wa;
|
|
|
XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL;
|
|
|
-
|
|
|
- window->x11.ic = NULL;
|
|
|
|
|
|
// Every window needs a colormap
|
|
|
// Create one based on the visual used by the current context
|
|
@@ -477,13 +423,18 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|
|
|
|
|
XRRSelectInput(_glfw.x11.display, window->x11.handle,
|
|
|
RRScreenChangeNotifyMask);
|
|
|
-
|
|
|
- // Try to create an input context. If this function returns NULL, ic is
|
|
|
- // set to NULL and we know we have to use fallback mechanisms to parse
|
|
|
- // char events.
|
|
|
- window->x11.ic = XCreateIC(_glfw.x11.im, XNInputStyle,
|
|
|
- XIMPreeditNothing | XIMStatusNothing, XNClientWindow,
|
|
|
- window->x11.handle, XNFocusWindow, window->x11.handle, NULL);
|
|
|
+
|
|
|
+ if (_glfw.x11.im)
|
|
|
+ {
|
|
|
+ window->x11.ic = XCreateIC(_glfw.x11.im,
|
|
|
+ XNInputStyle,
|
|
|
+ XIMPreeditNothing | XIMStatusNothing,
|
|
|
+ XNClientWindow,
|
|
|
+ window->x11.handle,
|
|
|
+ XNFocusWindow,
|
|
|
+ window->x11.handle,
|
|
|
+ NULL);
|
|
|
+ }
|
|
|
|
|
|
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
|
|
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
|
|
@@ -876,20 +827,45 @@ static void processEvent(XEvent *event)
|
|
|
{
|
|
|
case KeyPress:
|
|
|
{
|
|
|
- int i, n_chars;
|
|
|
const int key = translateKey(event->xkey.keycode);
|
|
|
const int mods = translateState(event->xkey.state);
|
|
|
- const wchar_t * characters = translateChar(event, window, &n_chars);
|
|
|
+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
|
|
|
|
|
- _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
|
|
|
+ if (event->xkey.keycode)
|
|
|
+ _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
|
|
|
|
|
|
- for (i = 0; i < n_chars; i++)
|
|
|
+ if (window->x11.ic)
|
|
|
{
|
|
|
- if (characters[i] != -1)
|
|
|
+ // Translate keys to characters with XIM input context
|
|
|
+
|
|
|
+ int i;
|
|
|
+ Status status;
|
|
|
+ wchar_t buffer[16];
|
|
|
+
|
|
|
+ if (XFilterEvent(event, None))
|
|
|
{
|
|
|
- const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
|
|
- _glfwInputChar(window, (unsigned int)characters[i], mods, plain);
|
|
|
+ // Discard intermediary (dead key) events for character input
|
|
|
+ break;
|
|
|
}
|
|
|
+
|
|
|
+ const int count = XwcLookupString(window->x11.ic,
|
|
|
+ &event->xkey,
|
|
|
+ buffer, sizeof(buffer),
|
|
|
+ NULL, &status);
|
|
|
+
|
|
|
+ for (i = 0; i < count; i++)
|
|
|
+ _glfwInputChar(window, buffer[i], mods, plain);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Translate keys to characters with fallback lookup table
|
|
|
+
|
|
|
+ KeySym keysym;
|
|
|
+ XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
|
|
|
+
|
|
|
+ const long character = _glfwKeySym2Unicode(keysym);
|
|
|
+ if (character != -1)
|
|
|
+ _glfwInputChar(window, character, mods, plain);
|
|
|
}
|
|
|
|
|
|
break;
|
|
@@ -1418,7 +1394,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|
|
{
|
|
|
if (window->monitor)
|
|
|
leaveFullscreenMode(window);
|
|
|
-
|
|
|
+
|
|
|
if (window->x11.ic)
|
|
|
{
|
|
|
XDestroyIC(window->x11.ic);
|