Added GLFW_FLOATING.

Fixes #23.
This commit is contained in:
Camilla Berglund 2014-05-23 14:01:02 +02:00
parent c9808586b3
commit 3ce7bfef07
11 changed files with 81 additions and 34 deletions

View File

@ -63,6 +63,7 @@ GLFW bundles a number of dependencies in the `deps/` directory.
- Added `GLFW_DONT_CARE` for indicating that any value is acceptable
- Added `GLFW_DOUBLEBUFFER` for controlling whether to use double buffering
- Added `GLFW_INCLUDE_ES31` for including the OpenGL ES 3.1 header
- Added `GLFW_FLOATING` for creating always-on-top windowed mode windows
- Added *partial and experimental* support for Wayland
- Bugfix: The debug context attribute was set from `GL_ARB_debug_output` even
when a debug context had not been requested

View File

@ -41,6 +41,12 @@ building multi-monitor installations, where you need windows to stay in full
screen despite losing focus.
@subsection news_31_floating Floating windows
GLFW not supports floating windows, also called topmost or always on top, for
easier debugging, with the `GLFW_FLOATING` window hint.
@section news_30 New features in version 3.0
@subsection news_30_cmake CMake build system

View File

@ -122,6 +122,11 @@ The `GLFW_AUTO_ICONIFY` hint specifies whether the (full screen) window
will automatically iconify and restore the previous video mode on focus loss.
This hint is ignored for windowed mode windows.
The `GLFW_FLOATING` hint specifies whether the window will be floating above
other regular windows, also called topmost or always-on-top. This is intended
primarily for debugging purposes and cannot be used to implement proper full
screen windows. This hint is ignored for full screen windows.
@subsection window_hints_fb Framebuffer related hints
@ -211,6 +216,7 @@ a robustness strategy.
| `GLFW_VISIBLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_DECORATED` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_AUTO_ICONIFY` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_FLOATING` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
@ -445,6 +451,10 @@ The `GLFW_DECORATED` attribute indicates whether the specified window has
decorations such as a border, a close widget, etc. This is controlled by the
[window hint](@ref window_hints) with the same name.
The `GLFW_FLOATING` attribute indicates whether the specified window is
floating, also called topmost or always-on-top. This is controlled by the
[window hint](@ref window_hints) with the same name.
@subsection window_attribs_context Context attributes

View File

@ -498,6 +498,7 @@ extern "C" {
#define GLFW_VISIBLE 0x00020004
#define GLFW_DECORATED 0x00020005
#define GLFW_AUTO_ICONIFY 0x00020006
#define GLFW_FLOATING 0x00020007
#define GLFW_RED_BITS 0x00021001
#define GLFW_GREEN_BITS 0x00021002

View File

@ -972,6 +972,9 @@ static GLboolean createWindow(_GLFWwindow* window,
}
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
if (wndconfig->floating)
[window->ns.object setLevel:NSFloatingWindowLevel];
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
[window->ns.object setContentView:window->ns.view];
[window->ns.object setDelegate:window->ns.delegate];

View File

@ -153,6 +153,7 @@ struct _GLFWwndconfig
GLboolean visible;
GLboolean decorated;
GLboolean autoIconify;
GLboolean floating;
_GLFWmonitor* monitor;
};
@ -218,6 +219,7 @@ struct _GLFWwindow
GLboolean resizable;
GLboolean decorated;
GLboolean autoIconify;
GLboolean floating;
GLboolean visible;
GLboolean closed;
void* userPointer;
@ -323,6 +325,7 @@ struct _GLFWlibrary
int visible;
int decorated;
int autoIconify;
int floating;
int samples;
int sRGB;
int refreshRate;

View File

@ -951,6 +951,14 @@ static int createWindow(_GLFWwindow* window,
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
}
if (wndconfig->floating && !wndconfig->monitor)
{
SetWindowPos(window->win32.handle,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
DragAcceptFiles(window->win32.handle, TRUE);
if (!_glfwCreateContext(window, ctxconfig, fbconfig))

View File

@ -167,6 +167,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE;
wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE;
wndconfig.autoIconify = _glfw.hints.autoIconify ? GL_TRUE : GL_FALSE;
wndconfig.floating = _glfw.hints.floating ? GL_TRUE : GL_FALSE;
wndconfig.monitor = (_GLFWmonitor*) monitor;
// Set up desired context config
@ -205,6 +206,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->resizable = wndconfig.resizable;
window->decorated = wndconfig.decorated;
window->autoIconify = wndconfig.autoIconify;
window->floating = wndconfig.floating;
window->cursorMode = GLFW_CURSOR_NORMAL;
// Save the currently current context so it can be restored later
@ -335,6 +337,9 @@ GLFWAPI void glfwWindowHint(int target, int hint)
case GLFW_AUTO_ICONIFY:
_glfw.hints.autoIconify = hint;
break;
case GLFW_FLOATING:
_glfw.hints.floating = hint;
break;
case GLFW_VISIBLE:
_glfw.hints.visible = hint;
break;
@ -585,6 +590,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->resizable;
case GLFW_DECORATED:
return window->decorated;
case GLFW_FLOATING:
return window->floating;
case GLFW_VISIBLE:
return window->visible;
case GLFW_CLIENT_API:

View File

@ -419,6 +419,8 @@ static void detectEWMH(void)
// See which of the atoms we support that are supported by the WM
_glfw.x11.NET_WM_STATE =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
_glfw.x11.NET_WM_STATE_ABOVE =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
_glfw.x11.NET_WM_STATE_FULLSCREEN =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
_glfw.x11.NET_WM_NAME =

View File

@ -122,6 +122,7 @@ typedef struct _GLFWlibraryX11
Atom NET_WM_PID;
Atom NET_WM_PING;
Atom NET_WM_STATE;
Atom NET_WM_STATE_ABOVE;
Atom NET_WM_STATE_FULLSCREEN;
Atom NET_WM_BYPASS_COMPOSITOR;
Atom NET_ACTIVE_WINDOW;

View File

@ -108,6 +108,29 @@ static int translateChar(XKeyEvent* event)
return (int) _glfwKeySym2Unicode(keysym);
}
// Adds or removes an EWMH state to a window
//
static void changeWindowState(_GLFWwindow* window, Atom state, int action)
{
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_WM_STATE;
event.xclient.data.l[0] = action;
event.xclient.data.l[1] = state;
event.xclient.data.l[2] = 0; // No secondary property
event.xclient.data.l[3] = 1; // Sender is a normal application
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
}
// Splits and translates a text/uri-list into separate file paths
//
static char** parseUriList(char* text, int* count)
@ -382,6 +405,16 @@ static GLboolean createWindow(_GLFWwindow* window,
XIfEvent(_glfw.x11.display, &event, isFrameExtentsEvent, (XPointer) window);
}
if (wndconfig->floating && !wndconfig->monitor)
{
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
changeWindowState(window,
_glfw.x11.NET_WM_STATE_ABOVE,
_NET_WM_STATE_ADD);
}
}
_glfwPlatformSetWindowTitle(window, wndconfig->title);
XRRSelectInput(_glfw.x11.display, window->x11.handle,
@ -490,23 +523,9 @@ static void enterFullscreenMode(_GLFWwindow* window)
// Fullscreen windows are undecorated and, when focused, are kept
// on top of all other windows
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_WM_STATE;
event.xclient.data.l[0] = _NET_WM_STATE_ADD;
event.xclient.data.l[1] = _glfw.x11.NET_WM_STATE_FULLSCREEN;
event.xclient.data.l[2] = 0; // No secondary property
event.xclient.data.l[3] = 1; // Sender is a normal application
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
changeWindowState(window,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_ADD);
}
else if (window->x11.overrideRedirect)
{
@ -557,23 +576,9 @@ static void leaveFullscreenMode(_GLFWwindow* window)
// Ask the window manager to make the GLFW window a normal window
// Normal windows usually have frames and other decorations
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_WM_STATE;
event.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
event.xclient.data.l[1] = _glfw.x11.NET_WM_STATE_FULLSCREEN;
event.xclient.data.l[2] = 0; // No secondary property
event.xclient.data.l[3] = 1; // Sender is a normal application
XSendEvent(_glfw.x11.display,
_glfw.x11.root,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
&event);
changeWindowState(window,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_REMOVE);
}
}