Simplified sending events to WM.

This commit is contained in:
Camilla Berglund 2015-06-02 17:05:00 +02:00
parent f0212f3f15
commit 41af5aaae2
1 changed files with 36 additions and 65 deletions

View File

@ -176,9 +176,10 @@ static _GLFWwindow* findWindowByHandle(Window handle)
return window; return window;
} }
// Adds or removes an EWMH state to a window // Sends an EWMH or ICCCM event to the window manager
// //
static void changeWindowState(_GLFWwindow* window, Atom state, int action) static void sendEventToWM(_GLFWwindow* window, Atom type,
long a, long b, long c, long d, long e)
{ {
XEvent event; XEvent event;
memset(&event, 0, sizeof(event)); memset(&event, 0, sizeof(event));
@ -186,11 +187,12 @@ static void changeWindowState(_GLFWwindow* window, Atom state, int action)
event.type = ClientMessage; event.type = ClientMessage;
event.xclient.window = window->x11.handle; event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NET_WM_STATE; event.xclient.message_type = type;
event.xclient.data.l[0] = action; event.xclient.data.l[0] = a;
event.xclient.data.l[1] = state; event.xclient.data.l[1] = b;
event.xclient.data.l[2] = 0; // No secondary property event.xclient.data.l[2] = c;
event.xclient.data.l[3] = 1; // Sender is a normal application event.xclient.data.l[3] = d;
event.xclient.data.l[4] = e;
XSendEvent(_glfw.x11.display, XSendEvent(_glfw.x11.display,
_glfw.x11.root, _glfw.x11.root,
@ -459,9 +461,11 @@ static GLboolean createWindow(_GLFWwindow* window,
{ {
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE) if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{ {
changeWindowState(window, sendEventToWM(window,
_glfw.x11.NET_WM_STATE_ABOVE, _glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD); _NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_ABOVE,
0, 1, 0);
} }
} }
@ -765,23 +769,13 @@ static void enterFullscreenMode(_GLFWwindow* window)
if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS) if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
{ {
XEvent event; sendEventToWM(window,
memset(&event, 0, sizeof(event)); _glfw.x11.NET_WM_FULLSCREEN_MONITORS,
window->monitor->x11.index,
event.type = ClientMessage; window->monitor->x11.index,
event.xclient.window = window->x11.handle; window->monitor->x11.index,
event.xclient.format = 32; // Data is 32-bit longs window->monitor->x11.index,
event.xclient.message_type = _glfw.x11.NET_WM_FULLSCREEN_MONITORS; 0);
event.xclient.data.l[0] = window->monitor->x11.index;
event.xclient.data.l[1] = window->monitor->x11.index;
event.xclient.data.l[2] = window->monitor->x11.index;
event.xclient.data.l[3] = window->monitor->x11.index;
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
} }
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN) if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
@ -795,31 +789,17 @@ static void enterFullscreenMode(_GLFWwindow* window)
// Ask the window manager to raise and focus the GLFW window // Ask the window manager to raise and focus the GLFW window
// Only focused windows with the _NET_WM_STATE_FULLSCREEN state end // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end
// up on top of all other windows ("Stacking order" in EWMH spec) // up on top of all other windows ("Stacking order" in EWMH spec)
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
XEvent event;
memset(&event, 0, sizeof(event));
event.type = ClientMessage;
event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NET_ACTIVE_WINDOW;
event.xclient.data.l[0] = 1; // Sender is a normal application
event.xclient.data.l[1] = 0; // We don't really know the timestamp
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
} }
// Ask the window manager to make the GLFW window a full screen window // Ask the window manager to make the GLFW window a full screen window
// Full screen windows are undecorated and, when focused, are kept // Full screen windows are undecorated and, when focused, are kept
// on top of all other windows // on top of all other windows
sendEventToWM(window,
changeWindowState(window, _glfw.x11.NET_WM_STATE,
_glfw.x11.NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_ADD,
_NET_WM_STATE_ADD); _glfw.x11.NET_WM_STATE_FULLSCREEN,
0, 1, 0);
} }
else if (window->x11.overrideRedirect) else if (window->x11.overrideRedirect)
{ {
@ -871,10 +851,11 @@ static void leaveFullscreenMode(_GLFWwindow* window)
{ {
// Ask the window manager to make the GLFW window a normal window // Ask the window manager to make the GLFW window a normal window
// Normal windows usually have frames and other decorations // Normal windows usually have frames and other decorations
sendEventToWM(window,
changeWindowState(window, _glfw.x11.NET_WM_STATE,
_glfw.x11.NET_WM_STATE_FULLSCREEN, _NET_WM_STATE_REMOVE,
_NET_WM_STATE_REMOVE); _glfw.x11.NET_WM_STATE_FULLSCREEN,
0, 1, 0);
} }
} }
@ -1607,23 +1588,13 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
if (!_glfwPlatformWindowVisible(window) && if (!_glfwPlatformWindowVisible(window) &&
_glfw.x11.NET_REQUEST_FRAME_EXTENTS) _glfw.x11.NET_REQUEST_FRAME_EXTENTS)
{ {
// Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
// function before the window is mapped
double base; double base;
XEvent event; XEvent event;
memset(&event, 0, sizeof(event));
event.type = ClientMessage; // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
event.xclient.window = window->x11.handle; // function before the window is mapped
event.xclient.format = 32; // Data is 32-bit longs sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
event.xclient.message_type = _glfw.x11.NET_REQUEST_FRAME_EXTENTS; 0, 0, 0, 0, 0);
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
// HACK: Poll with timeout for the required response instead of blocking // HACK: Poll with timeout for the required response instead of blocking
// This is done because some window managers (at least Unity, // This is done because some window managers (at least Unity,