X11: Fix BadMatch on XSetInputFocus

Input focus was in some cases set before the window was visible (ICCCM
section 4.2.2).

Related to #798.
Fixes #789.
This commit is contained in:
Camilla Berglund 2016-08-10 16:22:03 +02:00
parent ad9233e620
commit f1c536fe13
2 changed files with 32 additions and 2 deletions

View File

@ -114,6 +114,8 @@ information on what to include when reporting a bug.
removed (#817,#826) removed (#817,#826)
- [X11] Bugfix: Window size limits were ignored if the minimum or maximum size - [X11] Bugfix: Window size limits were ignored if the minimum or maximum size
was set to `GLFW_DONT_CARE` (#805) was set to `GLFW_DONT_CARE` (#805)
- [X11] Bugfix: Input focus was set before window was visible, causing
`BadMatch` on some non-reparenting WMs (#789,#798)
- [WGL] Added reporting of errors from `WGL_ARB_create_context` extension - [WGL] Added reporting of errors from `WGL_ARB_create_context` extension
- [GLX] Bugfix: Dynamically loaded entry points were not verified - [GLX] Bugfix: Dynamically loaded entry points were not verified
- [EGL] Added `lib` prefix matching between EGL and OpenGL ES library binaries - [EGL] Added `lib` prefix matching between EGL and OpenGL ES library binaries
@ -180,6 +182,7 @@ skills.
- Warren Hu - Warren Hu
- IntellectualKitty - IntellectualKitty
- Aaron Jacobs - Aaron Jacobs
- Erik S. V. Jansson
- Toni Jovanoski - Toni Jovanoski
- Arseny Kapoulkine - Arseny Kapoulkine
- Osman Keskin - Osman Keskin

View File

@ -92,6 +92,26 @@ static GLFWbool waitForEvent(double* timeout)
} }
} }
// Waits until a VisibilityNotify event arrives for the specified window or the
// timeout period elapses (ICCCM section 4.2.2)
//
static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
{
XEvent dummy;
double timeout = 0.1;
while (!XCheckTypedWindowEvent(_glfw.x11.display,
window->x11.handle,
VisibilityNotify,
&dummy))
{
if (!waitForEvent(&timeout))
return GLFW_FALSE;
}
return GLFW_TRUE;
}
// Returns whether the window is iconified // Returns whether the window is iconified
// //
static int getWindowState(_GLFWwindow* window) static int getWindowState(_GLFWwindow* window)
@ -1878,7 +1898,10 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
} }
if (_glfwPlatformWindowIconified(window)) if (_glfwPlatformWindowIconified(window))
{
XMapWindow(_glfw.x11.display, window->x11.handle); XMapWindow(_glfw.x11.display, window->x11.handle);
waitForVisibilityNotify(window);
}
else if (_glfwPlatformWindowVisible(window)) else if (_glfwPlatformWindowVisible(window))
{ {
if (_glfw.x11.NET_WM_STATE && if (_glfw.x11.NET_WM_STATE &&
@ -1915,8 +1938,11 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window)
{ {
if (_glfwPlatformWindowVisible(window))
return;
XMapWindow(_glfw.x11.display, window->x11.handle); XMapWindow(_glfw.x11.display, window->x11.handle);
XFlush(_glfw.x11.display); waitForVisibilityNotify(window);
} }
void _glfwPlatformHideWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window)
@ -1971,7 +1997,8 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (window->monitor) if (window->monitor)
{ {
XMapRaised(_glfw.x11.display, window->x11.handle); XMapRaised(_glfw.x11.display, window->x11.handle);
acquireMonitor(window); if (waitForVisibilityNotify(window))
acquireMonitor(window);
} }
else else
{ {