mirror of
https://github.com/glfw/glfw.git
synced 2024-11-12 17:51:48 +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_DONT_CARE` for indicating that any value is acceptable
|
||||||
- Added `GLFW_DOUBLEBUFFER` for controlling whether to use double buffering
|
- Added `GLFW_DOUBLEBUFFER` for controlling whether to use double buffering
|
||||||
- Added `GLFW_INCLUDE_ES31` for including the OpenGL ES 3.1 header
|
- 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
|
- Added *partial and experimental* support for Wayland
|
||||||
- Bugfix: The debug context attribute was set from `GL_ARB_debug_output` even
|
- Bugfix: The debug context attribute was set from `GL_ARB_debug_output` even
|
||||||
when a debug context had not been requested
|
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.
|
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
|
@section news_30 New features in version 3.0
|
||||||
|
|
||||||
@subsection news_30_cmake CMake build system
|
@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.
|
will automatically iconify and restore the previous video mode on focus loss.
|
||||||
This hint is ignored for windowed mode windows.
|
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
|
@subsection window_hints_fb Framebuffer related hints
|
||||||
|
|
||||||
@ -211,6 +216,7 @@ a robustness strategy.
|
|||||||
| `GLFW_VISIBLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
|
| `GLFW_VISIBLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
|
||||||
| `GLFW_DECORATED` | `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_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_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
|
||||||
| `GLFW_GREEN_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` |
|
| `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
|
decorations such as a border, a close widget, etc. This is controlled by the
|
||||||
[window hint](@ref window_hints) with the same name.
|
[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
|
@subsection window_attribs_context Context attributes
|
||||||
|
|
||||||
|
@ -498,6 +498,7 @@ extern "C" {
|
|||||||
#define GLFW_VISIBLE 0x00020004
|
#define GLFW_VISIBLE 0x00020004
|
||||||
#define GLFW_DECORATED 0x00020005
|
#define GLFW_DECORATED 0x00020005
|
||||||
#define GLFW_AUTO_ICONIFY 0x00020006
|
#define GLFW_AUTO_ICONIFY 0x00020006
|
||||||
|
#define GLFW_FLOATING 0x00020007
|
||||||
|
|
||||||
#define GLFW_RED_BITS 0x00021001
|
#define GLFW_RED_BITS 0x00021001
|
||||||
#define GLFW_GREEN_BITS 0x00021002
|
#define GLFW_GREEN_BITS 0x00021002
|
||||||
|
@ -972,6 +972,9 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
#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 setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
||||||
[window->ns.object setContentView:window->ns.view];
|
[window->ns.object setContentView:window->ns.view];
|
||||||
[window->ns.object setDelegate:window->ns.delegate];
|
[window->ns.object setDelegate:window->ns.delegate];
|
||||||
|
@ -153,6 +153,7 @@ struct _GLFWwndconfig
|
|||||||
GLboolean visible;
|
GLboolean visible;
|
||||||
GLboolean decorated;
|
GLboolean decorated;
|
||||||
GLboolean autoIconify;
|
GLboolean autoIconify;
|
||||||
|
GLboolean floating;
|
||||||
_GLFWmonitor* monitor;
|
_GLFWmonitor* monitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -218,6 +219,7 @@ struct _GLFWwindow
|
|||||||
GLboolean resizable;
|
GLboolean resizable;
|
||||||
GLboolean decorated;
|
GLboolean decorated;
|
||||||
GLboolean autoIconify;
|
GLboolean autoIconify;
|
||||||
|
GLboolean floating;
|
||||||
GLboolean visible;
|
GLboolean visible;
|
||||||
GLboolean closed;
|
GLboolean closed;
|
||||||
void* userPointer;
|
void* userPointer;
|
||||||
@ -323,6 +325,7 @@ struct _GLFWlibrary
|
|||||||
int visible;
|
int visible;
|
||||||
int decorated;
|
int decorated;
|
||||||
int autoIconify;
|
int autoIconify;
|
||||||
|
int floating;
|
||||||
int samples;
|
int samples;
|
||||||
int sRGB;
|
int sRGB;
|
||||||
int refreshRate;
|
int refreshRate;
|
||||||
|
@ -951,6 +951,14 @@ static int createWindow(_GLFWwindow* window,
|
|||||||
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
|
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);
|
DragAcceptFiles(window->win32.handle, TRUE);
|
||||||
|
|
||||||
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
|
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.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE;
|
||||||
wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE;
|
wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE;
|
||||||
wndconfig.autoIconify = _glfw.hints.autoIconify ? 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;
|
wndconfig.monitor = (_GLFWmonitor*) monitor;
|
||||||
|
|
||||||
// Set up desired context config
|
// Set up desired context config
|
||||||
@ -205,6 +206,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
window->resizable = wndconfig.resizable;
|
window->resizable = wndconfig.resizable;
|
||||||
window->decorated = wndconfig.decorated;
|
window->decorated = wndconfig.decorated;
|
||||||
window->autoIconify = wndconfig.autoIconify;
|
window->autoIconify = wndconfig.autoIconify;
|
||||||
|
window->floating = wndconfig.floating;
|
||||||
window->cursorMode = GLFW_CURSOR_NORMAL;
|
window->cursorMode = GLFW_CURSOR_NORMAL;
|
||||||
|
|
||||||
// Save the currently current context so it can be restored later
|
// 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:
|
case GLFW_AUTO_ICONIFY:
|
||||||
_glfw.hints.autoIconify = hint;
|
_glfw.hints.autoIconify = hint;
|
||||||
break;
|
break;
|
||||||
|
case GLFW_FLOATING:
|
||||||
|
_glfw.hints.floating = hint;
|
||||||
|
break;
|
||||||
case GLFW_VISIBLE:
|
case GLFW_VISIBLE:
|
||||||
_glfw.hints.visible = hint;
|
_glfw.hints.visible = hint;
|
||||||
break;
|
break;
|
||||||
@ -585,6 +590,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||||||
return window->resizable;
|
return window->resizable;
|
||||||
case GLFW_DECORATED:
|
case GLFW_DECORATED:
|
||||||
return window->decorated;
|
return window->decorated;
|
||||||
|
case GLFW_FLOATING:
|
||||||
|
return window->floating;
|
||||||
case GLFW_VISIBLE:
|
case GLFW_VISIBLE:
|
||||||
return window->visible;
|
return window->visible;
|
||||||
case GLFW_CLIENT_API:
|
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
|
// See which of the atoms we support that are supported by the WM
|
||||||
_glfw.x11.NET_WM_STATE =
|
_glfw.x11.NET_WM_STATE =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_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 =
|
_glfw.x11.NET_WM_STATE_FULLSCREEN =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
|
||||||
_glfw.x11.NET_WM_NAME =
|
_glfw.x11.NET_WM_NAME =
|
||||||
|
@ -122,6 +122,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom NET_WM_PID;
|
Atom NET_WM_PID;
|
||||||
Atom NET_WM_PING;
|
Atom NET_WM_PING;
|
||||||
Atom NET_WM_STATE;
|
Atom NET_WM_STATE;
|
||||||
|
Atom NET_WM_STATE_ABOVE;
|
||||||
Atom NET_WM_STATE_FULLSCREEN;
|
Atom NET_WM_STATE_FULLSCREEN;
|
||||||
Atom NET_WM_BYPASS_COMPOSITOR;
|
Atom NET_WM_BYPASS_COMPOSITOR;
|
||||||
Atom NET_ACTIVE_WINDOW;
|
Atom NET_ACTIVE_WINDOW;
|
||||||
|
@ -108,6 +108,29 @@ static int translateChar(XKeyEvent* event)
|
|||||||
return (int) _glfwKeySym2Unicode(keysym);
|
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
|
// Splits and translates a text/uri-list into separate file paths
|
||||||
//
|
//
|
||||||
static char** parseUriList(char* text, int* count)
|
static char** parseUriList(char* text, int* count)
|
||||||
@ -382,6 +405,16 @@ static GLboolean createWindow(_GLFWwindow* window,
|
|||||||
XIfEvent(_glfw.x11.display, &event, isFrameExtentsEvent, (XPointer) 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);
|
_glfwPlatformSetWindowTitle(window, wndconfig->title);
|
||||||
|
|
||||||
XRRSelectInput(_glfw.x11.display, window->x11.handle,
|
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
|
// Fullscreen windows are undecorated and, when focused, are kept
|
||||||
// on top of all other windows
|
// on top of all other windows
|
||||||
|
|
||||||
XEvent event;
|
changeWindowState(window,
|
||||||
memset(&event, 0, sizeof(event));
|
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
||||||
|
_NET_WM_STATE_ADD);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else if (window->x11.overrideRedirect)
|
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
|
// 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
|
||||||
|
|
||||||
XEvent event;
|
changeWindowState(window,
|
||||||
memset(&event, 0, sizeof(event));
|
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
||||||
|
_NET_WM_STATE_REMOVE);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user