mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
parent
c9808586b3
commit
3ce7bfef07
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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:
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user