mirror of
				https://github.com/glfw/glfw.git
				synced 2025-11-03 22:04:15 +00:00 
			
		
		
		
	Fixed dead keys in X11.
The library will now try to create an X input context to handle dead keys properly on international keyboards. This makes it possible to enter for example an e with accent grave on a German keyboard without further efforts. A fallback mechanism is provided in case the client does not support X input method / context creation. In that case, the library will behave as it did before.
This commit is contained in:
		
							parent
							
								
									49579165a7
								
							
						
					
					
						commit
						cec63f3cb5
					
				@ -449,6 +449,9 @@ 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",
 | 
				
			||||||
@ -579,6 +582,43 @@ 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);
 | 
				
			||||||
@ -686,6 +726,8 @@ 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)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -721,6 +763,12 @@ void _glfwPlatformTerminate(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    free(_glfw.x11.clipboardString);
 | 
					    free(_glfw.x11.clipboardString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_glfw.x11.im)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        XCloseIM(_glfw.x11.im);
 | 
				
			||||||
 | 
					        _glfw.x11.im = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _glfwTerminateJoysticks();
 | 
					    _glfwTerminateJoysticks();
 | 
				
			||||||
    _glfwTerminateContextAPI();
 | 
					    _glfwTerminateContextAPI();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -90,6 +90,8 @@ 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -202,6 +204,9 @@ typedef struct _GLFWlibraryX11
 | 
				
			|||||||
        Window      source;
 | 
					        Window      source;
 | 
				
			||||||
    } xdnd;
 | 
					    } xdnd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Input method and context
 | 
				
			||||||
 | 
					    XIM im;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} _GLFWlibraryX11;
 | 
					} _GLFWlibraryX11;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -97,15 +97,54 @@ static int translateKey(int keycode)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Translates an X Window event to Unicode
 | 
					// Translates an X Window event to Unicode
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
static int translateChar(XKeyEvent* event)
 | 
					static wchar_t * translateChar(XEvent * event, _GLFWwindow * window, int * count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    KeySym keysym;
 | 
					    KeySym keysym;
 | 
				
			||||||
 | 
					    static wchar_t buffer[16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Get X11 keysym
 | 
					    // If there is no input method / context available, use the old fallback
 | 
				
			||||||
    XLookupString(event, NULL, 0, &keysym, NULL);
 | 
					    // mechanism
 | 
				
			||||||
 | 
					    if (!window || !window->x11.ic)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        long uc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Convert to Unicode (see x11_unicode.c)
 | 
					        // Get X11 keysym
 | 
				
			||||||
    return (int) _glfwKeySym2Unicode(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
 | 
				
			||||||
@ -201,6 +240,8 @@ static GLboolean createWindow(_GLFWwindow* window,
 | 
				
			|||||||
    unsigned long wamask;
 | 
					    unsigned long wamask;
 | 
				
			||||||
    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
 | 
				
			||||||
@ -436,6 +477,13 @@ 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
 | 
				
			||||||
 | 
					    // 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _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);
 | 
				
			||||||
@ -828,16 +876,20 @@ 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 int character = translateChar(&event->xkey);
 | 
					            const wchar_t * characters = translateChar(event, window, &n_chars);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
 | 
					            _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (character != -1)
 | 
					            for (i = 0; i < n_chars; i++)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
 | 
					                if (characters[i] != -1)
 | 
				
			||||||
                _glfwInputChar(window, character, mods, plain);
 | 
					                {
 | 
				
			||||||
 | 
					                    const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
 | 
				
			||||||
 | 
					                    _glfwInputChar(window, (unsigned int)characters[i], mods, plain);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -1366,6 +1418,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    if (window->monitor)
 | 
					    if (window->monitor)
 | 
				
			||||||
        leaveFullscreenMode(window);
 | 
					        leaveFullscreenMode(window);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (window->x11.ic)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        XDestroyIC(window->x11.ic);
 | 
				
			||||||
 | 
					        window->x11.ic = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _glfwDestroyContext(window);
 | 
					    _glfwDestroyContext(window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user