1
0
Fork 0
mirror of https://github.com/gwm17/glfw.git synced 2024-11-26 20:28:49 -05:00

Cleanup of basic XIM support.

Shortened and simplified the code.  Removed reporting of XIM sentinel
key press event.  Added credit.  Updated changelog.

Closes #151.
This commit is contained in:
Camilla Berglund 2014-09-21 02:13:41 +02:00
parent cec63f3cb5
commit c769061a8a
4 changed files with 89 additions and 116 deletions

View File

@ -118,6 +118,7 @@ GLFW bundles a number of dependencies in the `deps/` directory.
- [X11] Bugfix: Workaround for legacy Compiz caused flickering during resize - [X11] Bugfix: Workaround for legacy Compiz caused flickering during resize
- [X11] Bugfix: The name pointer of joysticks were not cleared on disconnection - [X11] Bugfix: The name pointer of joysticks were not cleared on disconnection
- [X11] Bugfix: Video mode dimensions were not rotated to match the CRTC - [X11] Bugfix: Video mode dimensions were not rotated to match the CRTC
- [X11] Bugfix: Unicode character input ignored dead keys
## Contact ## Contact
@ -174,6 +175,7 @@ skills.
- Sylvain Hellegouarch - Sylvain Hellegouarch
- Matthew Henry - Matthew Henry
- heromyth - heromyth
- Lucas Hinderberger
- Paul Holden - Paul Holden
- Toni Jovanoski - Toni Jovanoski
- Arseny Kapoulkine - Arseny Kapoulkine

View File

@ -329,6 +329,30 @@ static void updateKeyCodeLUT(void)
} }
} }
// Check whether the IM has a usable style
//
static GLboolean hasUsableInputMethodStyle(void)
{
unsigned int i;
GLboolean found = GL_FALSE;
XIMStyles* styles = NULL;
if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL)
return GL_FALSE;
for (i = 0; i < styles->count_styles; i++)
{
if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing))
{
found = GL_TRUE;
break;
}
}
XFree(styles);
return found;
}
// Check whether the specified atom is supported // Check whether the specified atom is supported
// //
static Atom getSupportedAtom(Atom* supportedAtoms, static Atom getSupportedAtom(Atom* supportedAtoms,
@ -449,9 +473,6 @@ static void detectEWMH(void)
// //
static GLboolean initExtensions(void) static GLboolean initExtensions(void)
{ {
unsigned int u;
XIMStyles * styles = NULL;
// Find or create window manager atoms // Find or create window manager atoms
_glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display,
"WM_PROTOCOLS", "WM_PROTOCOLS",
@ -582,43 +603,6 @@ static GLboolean initExtensions(void)
_glfw.x11.SAVE_TARGETS = _glfw.x11.SAVE_TARGETS =
XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False);
// ------------------------------------------------------------------------
// Optional extensions (function returns always true from here!)
// Open input method
if (!XSupportsLocale())
return GL_TRUE;
XSetLocaleModifiers("");
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, 0, 0);
if (!_glfw.x11.im)
return GL_TRUE;
// Get available input styles
if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) || !styles)
{
XCloseIM(_glfw.x11.im);
_glfw.x11.im = NULL;
return GL_TRUE;
}
// Search for needed input style
for (u = 0; u < styles->count_styles; u++)
{
if (styles->supported_styles[u] == (XIMPreeditNothing | XIMStatusNothing))
break;
}
if (u >= styles->count_styles)
{
XFree(styles);
XCloseIM(_glfw.x11.im);
_glfw.x11.im = NULL;
return GL_TRUE;
}
XFree(styles);
// Find Xdnd (drag and drop) atoms, if available // Find Xdnd (drag and drop) atoms, if available
_glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True); _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True);
_glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True); _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True);
@ -726,8 +710,6 @@ int _glfwPlatformInit(void)
{ {
XInitThreads(); XInitThreads();
_glfw.x11.im = NULL;
_glfw.x11.display = XOpenDisplay(NULL); _glfw.x11.display = XOpenDisplay(NULL);
if (!_glfw.x11.display) if (!_glfw.x11.display)
{ {
@ -744,6 +726,21 @@ int _glfwPlatformInit(void)
_glfw.x11.cursor = createNULLCursor(); _glfw.x11.cursor = createNULLCursor();
if (XSupportsLocale())
{
XSetLocaleModifiers("");
_glfw.x11.im = XOpenIM(_glfw.x11.display, 0, 0, 0);
if (_glfw.x11.im)
{
if (!hasUsableInputMethodStyle())
{
XCloseIM(_glfw.x11.im);
_glfw.x11.im = NULL;
}
}
}
if (!_glfwInitContextAPI()) if (!_glfwInitContextAPI())
return GL_FALSE; return GL_FALSE;

View File

@ -78,6 +78,7 @@ typedef struct _GLFWwindowX11
{ {
Colormap colormap; Colormap colormap;
Window handle; Window handle;
XIC ic;
GLboolean overrideRedirect; GLboolean overrideRedirect;
@ -90,8 +91,6 @@ typedef struct _GLFWwindowX11
// The last position the cursor was warped to by GLFW // The last position the cursor was warped to by GLFW
int warpPosX, warpPosY; int warpPosX, warpPosY;
// The window's input context
XIC ic;
} _GLFWwindowX11; } _GLFWwindowX11;
@ -107,6 +106,8 @@ typedef struct _GLFWlibraryX11
Cursor cursor; Cursor cursor;
// Context for mapping window XIDs to _GLFWwindow pointers // Context for mapping window XIDs to _GLFWwindow pointers
XContext context; XContext context;
// XIM input method
XIM im;
// True if window manager supports EWMH // True if window manager supports EWMH
GLboolean hasEWMH; GLboolean hasEWMH;
// Most recent error code received by X error handler // Most recent error code received by X error handler
@ -204,9 +205,6 @@ typedef struct _GLFWlibraryX11
Window source; Window source;
} xdnd; } xdnd;
// Input method and context
XIM im;
} _GLFWlibraryX11; } _GLFWlibraryX11;

View File

@ -95,58 +95,6 @@ static int translateKey(int keycode)
return _glfw.x11.keyCodeLUT[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 // Return the GLFW window corresponding to the specified X11 window
// //
static _GLFWwindow* findWindowByHandle(Window handle) static _GLFWwindow* findWindowByHandle(Window handle)
@ -241,8 +189,6 @@ static GLboolean createWindow(_GLFWwindow* window,
XSetWindowAttributes wa; XSetWindowAttributes wa;
XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL; XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL;
window->x11.ic = NULL;
// Every window needs a colormap // Every window needs a colormap
// Create one based on the visual used by the current context // Create one based on the visual used by the current context
// TODO: Decouple this from context creation // TODO: Decouple this from context creation
@ -478,12 +424,17 @@ static GLboolean createWindow(_GLFWwindow* window,
XRRSelectInput(_glfw.x11.display, window->x11.handle, XRRSelectInput(_glfw.x11.display, window->x11.handle,
RRScreenChangeNotifyMask); RRScreenChangeNotifyMask);
// Try to create an input context. If this function returns NULL, ic is if (_glfw.x11.im)
// set to NULL and we know we have to use fallback mechanisms to parse {
// char events. window->x11.ic = XCreateIC(_glfw.x11.im,
window->x11.ic = XCreateIC(_glfw.x11.im, XNInputStyle, XNInputStyle,
XIMPreeditNothing | XIMStatusNothing, XNClientWindow, XIMPreeditNothing | XIMStatusNothing,
window->x11.handle, XNFocusWindow, window->x11.handle, NULL); XNClientWindow,
window->x11.handle,
XNFocusWindow,
window->x11.handle,
NULL);
}
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos); _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height); _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
@ -876,20 +827,45 @@ static void processEvent(XEvent *event)
{ {
case KeyPress: case KeyPress:
{ {
int i, n_chars;
const int key = translateKey(event->xkey.keycode); const int key = translateKey(event->xkey.keycode);
const int mods = translateState(event->xkey.state); 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)); // Discard intermediary (dead key) events for character input
_glfwInputChar(window, (unsigned int)characters[i], mods, plain); 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; break;