Add init/window hints/attributes to set Cocoa windows' tabbing mode

Closes #1250
This commit is contained in:
ws909 2022-12-30 16:29:20 +01:00
parent 57cbded076
commit 85d3c6f1ec
21 changed files with 165 additions and 9 deletions

View File

@ -98,6 +98,7 @@ video tutorials.
- IntellectualKitty
- Aaron Jacobs
- JannikGM
- Andreas O. Jansen
- Erik S. V. Jansson
- jjYBdx4IL
- Toni Jovanoski

View File

@ -121,6 +121,8 @@ information on what to include when reporting a bug.
## Changelog
- Added `GLFW_COCOA_TABBING_MODE` window hint for specifying a window's tabbing mode (#1250)
- Added `GLFW_COCOA_ALLOW_AUTO_TABBING` init hint for enabling and disabling application-wide window tabbing (#1250)
- Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958)
- Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`,
`GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to

View File

@ -320,6 +320,30 @@ extern "C" {
*/
#define GLFW_FALSE 0
/*! @brief Zero.
*
* This is only semantic sugar for the number 0.
*
* @ingroup init
*/
#define GLFW_NEVER 0
/*! @brief One.
*
* This is only semantic sugar for the number 1.
*
* @ingroup init
*/
#define GLFW_AUTO 1
/*! @brief Two.
*
* This is only semantic sugar for the number 2.
*
* @ingroup init
*/
#define GLFW_ALWAYS 2
/*! @name Key and button actions
* @{ */
/*! @brief The key or mouse button was released.
@ -1108,6 +1132,11 @@ extern "C" {
* [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint).
*/
#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
/*! @brief macOS specific
* [window hint](@ref GLFW_COCOA_TABBING_MODE_hint).
* [attribute](@ref GLFW_COCOA_TABBING_MODE_attrib).
*/
#define GLFW_COCOA_TABBING_MODE 0x00023004
/*! @brief X11 specific
* [window hint](@ref GLFW_X11_CLASS_NAME_hint).
*/
@ -1302,6 +1331,11 @@ extern "C" {
* macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
*/
#define GLFW_COCOA_MENUBAR 0x00051002
/*! @brief macOS specific init hint.
*
* macOS specific [init hint](@ref GLFW_COCOA_ALLOW_AUTO_TABBING_hint).
*/
#define GLFW_COCOA_ALLOW_AUTO_TABBING 0x00051003
/*! @brief X11 specific init hint.
*
* X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint).
@ -4015,9 +4049,10 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
* [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
* [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
* [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib)
* [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib),
* [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib),
* [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib) and
* [GLFW_COCOA_TABBING_MODE](@ref GLFW_COCOA_TABBING_MODE_attrib).
*
* Some of these attributes are ignored for full screen windows. The new
* value will take effect if the window is later made windowed.
@ -4027,7 +4062,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
*
* @param[in] window The window to set the attribute for.
* @param[in] attrib A supported window attribute.
* @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
* @param[in] value `GLFW_TRUE`, `GLFW_FALSE` `GLFW_NEVER`, `GLFW_ALWAYS` or `GLFW_AUTO`.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref

View File

@ -551,12 +551,14 @@ GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform)
_glfwWindowMaximizedCocoa,
_glfwWindowHoveredCocoa,
_glfwFramebufferTransparentCocoa,
_glfwWindowTabbingModeCocoa,
_glfwGetWindowOpacityCocoa,
_glfwSetWindowResizableCocoa,
_glfwSetWindowDecoratedCocoa,
_glfwSetWindowFloatingCocoa,
_glfwSetWindowOpacityCocoa,
_glfwSetWindowMousePassthroughCocoa,
_glfwSetWindowTabbingModeCocoa,
_glfwPollEventsCocoa,
_glfwWaitEventsCocoa,
_glfwWaitEventsTimeoutCocoa,
@ -639,6 +641,9 @@ int _glfwInitCocoa(void)
// In case we are unbundled, make us a proper UI application
if (_glfw.hints.init.ns.menubar)
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
if (!_glfw.hints.init.ns.autoTabbing)
[NSWindow setAllowsAutomaticWindowTabbing:NO];
return GLFW_TRUE;

View File

@ -241,12 +241,14 @@ GLFWbool _glfwWindowVisibleCocoa(_GLFWwindow* window);
GLFWbool _glfwWindowMaximizedCocoa(_GLFWwindow* window);
GLFWbool _glfwWindowHoveredCocoa(_GLFWwindow* window);
GLFWbool _glfwFramebufferTransparentCocoa(_GLFWwindow* window);
char _glfwWindowTabbingModeCocoa(_GLFWwindow* window);
void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingCocoa(_GLFWwindow* window, GLFWbool enabled);
float _glfwGetWindowOpacityCocoa(_GLFWwindow* window);
void _glfwSetWindowOpacityCocoa(_GLFWwindow* window, float opacity);
void _glfwSetWindowMousePassthroughCocoa(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowTabbingModeCocoa(_GLFWwindow* window, char value);
void _glfwSetRawMouseMotionCocoa(_GLFWwindow *window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedCocoa(void);

View File

@ -885,10 +885,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setRestorable:NO];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if ([window->ns.object respondsToSelector:@selector(setTabbingMode:)])
[window->ns.object setTabbingMode:NSWindowTabbingModeDisallowed];
#endif
_glfwSetWindowTabbingModeCocoa(window, wndconfig->ns.tabbingMode);
_glfwGetWindowSizeCocoa(window, &window->ns.width, &window->ns.height);
_glfwGetFramebufferSizeCocoa(window, &window->ns.fbWidth, &window->ns.fbHeight);
@ -1876,6 +1873,46 @@ const char* _glfwGetClipboardStringCocoa(void)
} // autoreleasepool
}
void _glfwSetWindowTabbingModeCocoa(_GLFWwindow* window, const char mode)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if ([window->ns.object respondsToSelector:@selector(setTabbingMode:)]) {
NSWindowTabbingMode tabbingMode;
switch (mode) {
case GLFW_NEVER:
tabbingMode = NSWindowTabbingModeDisallowed;
break;
case GLFW_AUTO:
tabbingMode = NSWindowTabbingModeAutomatic;
break;
case GLFW_ALWAYS:
tabbingMode = NSWindowTabbingModePreferred;
break;
}
[window->ns.object setTabbingMode:tabbingMode];
}
#endif
}
char _glfwWindowTabbingModeCocoa(_GLFWwindow* window)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if ([window->ns.object respondsToSelector:@selector(tabbingMode:)]) {
switch ([window->ns.object tabbingMode]) {
case NSWindowTabbingModeDisallowed:
return GLFW_NEVER;
case NSWindowTabbingModeAutomatic:
return GLFW_AUTO;
case NSWindowTabbingModePreferred:
return GLFW_ALWAYS;
}
}
#endif
return 0;
}
EGLenum _glfwGetEGLPlatformCocoa(EGLint** attribs)
{
if (_glfw.egl.ANGLE_platform_angle)

View File

@ -57,7 +57,8 @@ static _GLFWinitconfig _glfwInitHints =
NULL, // vkGetInstanceProcAddr function
{
GLFW_TRUE, // macOS menu bar
GLFW_TRUE // macOS bundle chdir
GLFW_TRUE, // macOS bundle chdir
GLFW_FALSE // macOS NSWindow auto tabbing
},
{
GLFW_TRUE, // X11 XCB Vulkan surface
@ -476,6 +477,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
case GLFW_COCOA_MENUBAR:
_glfwInitHints.ns.menubar = value;
return;
case GLFW_COCOA_ALLOW_AUTO_TABBING:
_glfwInitHints.ns.autoTabbing = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_X11_XCB_VULKAN_SURFACE:
_glfwInitHints.x11.xcbVulkanSurface = value;
return;

View File

@ -375,6 +375,7 @@ struct _GLFWinitconfig
struct {
GLFWbool menubar;
GLFWbool chdir;
GLFWbool autoTabbing;
} ns;
struct {
GLFWbool xcbVulkanSurface;
@ -407,6 +408,7 @@ struct _GLFWwndconfig
GLFWbool scaleToMonitor;
struct {
GLFWbool retina;
char tabbingMode;
char frameName[256];
} ns;
struct {
@ -729,12 +731,14 @@ struct _GLFWplatform
GLFWbool (*windowMaximized)(_GLFWwindow*);
GLFWbool (*windowHovered)(_GLFWwindow*);
GLFWbool (*framebufferTransparent)(_GLFWwindow*);
char (*windowTabbingMode)(_GLFWwindow*);
float (*getWindowOpacity)(_GLFWwindow*);
void (*setWindowResizable)(_GLFWwindow*,GLFWbool);
void (*setWindowDecorated)(_GLFWwindow*,GLFWbool);
void (*setWindowFloating)(_GLFWwindow*,GLFWbool);
void (*setWindowOpacity)(_GLFWwindow*,float);
void (*setWindowMousePassthrough)(_GLFWwindow*,GLFWbool);
void (*setWindowTabbingMode)(_GLFWwindow*,char);
void (*pollEvents)(void);
void (*waitEvents)(void);
void (*waitEventsTimeout)(double);

View File

@ -96,12 +96,14 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform)
_glfwWindowMaximizedNull,
_glfwWindowHoveredNull,
_glfwFramebufferTransparentNull,
_glfwWindowTabbingModeNull,
_glfwGetWindowOpacityNull,
_glfwSetWindowResizableNull,
_glfwSetWindowDecoratedNull,
_glfwSetWindowFloatingNull,
_glfwSetWindowOpacityNull,
_glfwSetWindowMousePassthroughNull,
_glfwSetWindowTabbingModeNull,
_glfwPollEventsNull,
_glfwWaitEventsNull,
_glfwWaitEventsTimeoutNull,

View File

@ -105,10 +105,12 @@ void _glfwMaximizeWindowNull(_GLFWwindow* window);
GLFWbool _glfwWindowMaximizedNull(_GLFWwindow* window);
GLFWbool _glfwWindowHoveredNull(_GLFWwindow* window);
GLFWbool _glfwFramebufferTransparentNull(_GLFWwindow* window);
char _glfwWindowTabbingModeNull(_GLFWwindow* window);
void _glfwSetWindowResizableNull(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedNull(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowMousePassthroughNull(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowTabbingModeNull(_GLFWwindow* window, char value);
float _glfwGetWindowOpacityNull(_GLFWwindow* window);
void _glfwSetWindowOpacityNull(_GLFWwindow* window, float opacity);
void _glfwSetRawMouseMotionNull(_GLFWwindow *window, GLFWbool enabled);

View File

@ -551,6 +551,15 @@ const char* _glfwGetClipboardStringNull(void)
return _glfw.null.clipboardString;
}
void _glfwSetWindowTabbingModeNull(_GLFWwindow* window, char value)
{
}
char _glfwWindowTabbingModeNull(_GLFWwindow* window)
{
return GLFW_NEVER;
}
EGLenum _glfwGetEGLPlatformNull(EGLint** attribs)
{
return 0;

View File

@ -661,12 +661,14 @@ GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform)
_glfwWindowMaximizedWin32,
_glfwWindowHoveredWin32,
_glfwFramebufferTransparentWin32,
_glfwWindowTabbingModeWin32,
_glfwGetWindowOpacityWin32,
_glfwSetWindowResizableWin32,
_glfwSetWindowDecoratedWin32,
_glfwSetWindowFloatingWin32,
_glfwSetWindowOpacityWin32,
_glfwSetWindowMousePassthroughWin32,
_glfwSetWindowTabbingModeWin32,
_glfwPollEventsWin32,
_glfwWaitEventsWin32,
_glfwWaitEventsTimeoutWin32,

View File

@ -566,12 +566,14 @@ GLFWbool _glfwWindowVisibleWin32(_GLFWwindow* window);
GLFWbool _glfwWindowMaximizedWin32(_GLFWwindow* window);
GLFWbool _glfwWindowHoveredWin32(_GLFWwindow* window);
GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window);
char _glfwWindowTabbingModeWin32(_GLFWwindow* window);
void _glfwSetWindowResizableWin32(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedWin32(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingWin32(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowMousePassthroughWin32(_GLFWwindow* window, GLFWbool enabled);
float _glfwGetWindowOpacityWin32(_GLFWwindow* window);
void _glfwSetWindowOpacityWin32(_GLFWwindow* window, float opacity);
void _glfwSetWindowTabbingModeWin32(_GLFWwindow* window, char value);
void _glfwSetRawMouseMotionWin32(_GLFWwindow *window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedWin32(void);

View File

@ -2373,6 +2373,16 @@ const char* _glfwGetClipboardStringWin32(void)
return _glfw.win32.clipboardString;
}
void _glfwSetWindowTabbingModeWin32(_GLFWwindow* window, char value)
{
// Silently ignore
}
char _glfwWindowTabbingModeWin32(_GLFWwindow* window)
{
return GLFW_NEVER;
}
EGLenum _glfwGetEGLPlatformWin32(EGLint** attribs)
{
if (_glfw.egl.ANGLE_platform_angle)

View File

@ -293,6 +293,8 @@ void glfwDefaultWindowHints(void)
// The default is to use full Retina resolution framebuffers
_glfw.hints.window.ns.retina = GLFW_TRUE;
_glfw.hints.window.ns.tabbingMode = 0;
}
GLFWAPI void glfwWindowHint(int hint, int value)
@ -385,6 +387,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_COCOA_TABBING_MODE:
_glfw.hints.window.ns.tabbingMode = value;
return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return;
@ -902,6 +907,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->context.release;
case GLFW_CONTEXT_NO_ERROR:
return window->context.noerror;
case GLFW_COCOA_TABBING_MODE:
return _glfw.platform.windowTabbingMode(window);
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
@ -949,6 +956,10 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
window->mousePassthrough = value;
_glfw.platform.setWindowMousePassthrough(window, value);
return;
case GLFW_COCOA_TABBING_MODE:
_glfw.platform.setWindowTabbingMode(window, value);
return;
}
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);

View File

@ -442,12 +442,14 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform)
_glfwWindowMaximizedWayland,
_glfwWindowHoveredWayland,
_glfwFramebufferTransparentWayland,
_glfwWindowTabbingModeWayland,
_glfwGetWindowOpacityWayland,
_glfwSetWindowResizableWayland,
_glfwSetWindowDecoratedWayland,
_glfwSetWindowFloatingWayland,
_glfwSetWindowOpacityWayland,
_glfwSetWindowMousePassthroughWayland,
_glfwSetWindowTabbingModeWayland,
_glfwPollEventsWayland,
_glfwWaitEventsWayland,
_glfwWaitEventsTimeoutWayland,

View File

@ -469,12 +469,14 @@ GLFWbool _glfwWindowVisibleWayland(_GLFWwindow* window);
GLFWbool _glfwWindowMaximizedWayland(_GLFWwindow* window);
GLFWbool _glfwWindowHoveredWayland(_GLFWwindow* window);
GLFWbool _glfwFramebufferTransparentWayland(_GLFWwindow* window);
char _glfwWindowTabbingModeWayland(_GLFWwindow* window);
void _glfwSetWindowResizableWayland(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedWayland(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingWayland(_GLFWwindow* window, GLFWbool enabled);
float _glfwGetWindowOpacityWayland(_GLFWwindow* window);
void _glfwSetWindowOpacityWayland(_GLFWwindow* window, float opacity);
void _glfwSetWindowMousePassthroughWayland(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowTabbingModeWayland(_GLFWwindow* window, char value);
void _glfwSetRawMouseMotionWayland(_GLFWwindow* window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedWayland(void);

View File

@ -2775,6 +2775,16 @@ const char* _glfwGetClipboardStringWayland(void)
return _glfw.wl.clipboardString;
}
void _glfwSetWindowTabbingModeWayland(_GLFWwindow* window, const char mode)
{
// Silently ignore
}
char _glfwWindowTabbingModeWayland(_GLFWwindow* window)
{
return GLFW_NEVER;
}
EGLenum _glfwGetEGLPlatformWayland(EGLint** attribs)
{
if (_glfw.egl.EXT_platform_base && _glfw.egl.EXT_platform_wayland)

View File

@ -1232,12 +1232,14 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform)
_glfwWindowMaximizedX11,
_glfwWindowHoveredX11,
_glfwFramebufferTransparentX11,
_glfwWindowTabbingModeX11,
_glfwGetWindowOpacityX11,
_glfwSetWindowResizableX11,
_glfwSetWindowDecoratedX11,
_glfwSetWindowFloatingX11,
_glfwSetWindowOpacityX11,
_glfwSetWindowMousePassthroughX11,
_glfwSetWindowTabbingModeX11,
_glfwPollEventsX11,
_glfwWaitEventsX11,
_glfwWaitEventsTimeoutX11,

View File

@ -928,12 +928,14 @@ GLFWbool _glfwWindowVisibleX11(_GLFWwindow* window);
GLFWbool _glfwWindowMaximizedX11(_GLFWwindow* window);
GLFWbool _glfwWindowHoveredX11(_GLFWwindow* window);
GLFWbool _glfwFramebufferTransparentX11(_GLFWwindow* window);
char _glfwWindowTabbingModeX11(_GLFWwindow* window);
void _glfwSetWindowResizableX11(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedX11(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled);
float _glfwGetWindowOpacityX11(_GLFWwindow* window);
void _glfwSetWindowOpacityX11(_GLFWwindow* window, float opacity);
void _glfwSetWindowMousePassthroughX11(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowTabbingModeX11(_GLFWwindow* window, char value);
void _glfwSetRawMouseMotionX11(_GLFWwindow *window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedX11(void);

View File

@ -3082,6 +3082,16 @@ const char* _glfwGetClipboardStringX11(void)
return getSelectionString(_glfw.x11.CLIPBOARD);
}
void _glfwSetWindowTabbingModeX11(_GLFWwindow* window, const char mode)
{
// Silently ignore
}
char _glfwWindowTabbingModeX11(_GLFWwindow* window)
{
return GLFW_NEVER;
}
EGLenum _glfwGetEGLPlatformX11(EGLint** attribs)
{
if (_glfw.egl.ANGLE_platform_angle)