mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-16 06:45:59 +00:00
cocoa: Add a hint to control menu visibility in fullscreen spaces windows
Adds SDL_HINT_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY to control whether or not the menu can be accessed when the cursor is moved to the top of the screen when a window is in fullscreen spaces mode. The three values are true, false, and 'auto' (default), with auto resulting in a hidden menu if fullscreen was toggled programmatically, and the menu being accessible if fullscreen was toggled via the button on the window title bar, so the user has an easy way back out of fullscreen if the client app/game doesn't have a readily available option to toggle it.
This commit is contained in:
@@ -218,6 +218,7 @@ static bool Cocoa_VideoInit(SDL_VideoDevice *_this)
|
||||
|
||||
data.allow_spaces = SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, true);
|
||||
data.trackpad_is_touch_only = SDL_GetHintBoolean(SDL_HINT_TRACKPAD_IS_TOUCH_ONLY, false);
|
||||
SDL_AddHintCallback(SDL_HINT_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY, Cocoa_MenuVisibilityCallback, NULL);
|
||||
|
||||
data.swaplock = SDL_CreateMutex();
|
||||
if (!data.swaplock) {
|
||||
|
@@ -142,6 +142,7 @@ typedef enum
|
||||
@property(nonatomic) NSView *sdlContentView;
|
||||
@property(nonatomic) NSMutableArray *nscontexts;
|
||||
@property(nonatomic) BOOL in_blocking_transition;
|
||||
@property(nonatomic) BOOL fullscreen_space_requested;
|
||||
@property(nonatomic) BOOL was_zoomed;
|
||||
@property(nonatomic) NSInteger window_number;
|
||||
@property(nonatomic) NSInteger flash_request;
|
||||
@@ -192,4 +193,6 @@ extern bool Cocoa_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, boo
|
||||
extern bool Cocoa_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent);
|
||||
extern bool Cocoa_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
extern void Cocoa_MenuVisibilityCallback(void *userdata, const char *name, const char *oldValue, const char *newValue);
|
||||
|
||||
#endif // SDL_cocoawindow_h_
|
||||
|
@@ -404,6 +404,61 @@ static NSScreen *ScreenForPoint(const NSPoint *point)
|
||||
return screen;
|
||||
}
|
||||
|
||||
bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
|
||||
|
||||
if ([data.listener isInFullscreenSpace]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum CocoaMenuVisibility
|
||||
{
|
||||
COCOA_MENU_VISIBILITY_AUTO = 0,
|
||||
COCOA_MENU_VISIBILITY_NEVER,
|
||||
COCOA_MENU_VISIBILITY_ALWAYS
|
||||
} CocoaMenuVisibility;
|
||||
|
||||
static CocoaMenuVisibility menu_visibility_hint = COCOA_MENU_VISIBILITY_AUTO;
|
||||
|
||||
static void Cocoa_ToggleFullscreenSpaceMenuVisibility(SDL_Window *window)
|
||||
{
|
||||
if (window && Cocoa_IsWindowInFullscreenSpace(window)) {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
|
||||
|
||||
// 'Auto' sets the menu to visible if fullscreen wasn't explicitly entered via SDL_SetWindowFullscreen().
|
||||
if ((menu_visibility_hint == COCOA_MENU_VISIBILITY_AUTO && !data.fullscreen_space_requested) ||
|
||||
menu_visibility_hint == COCOA_MENU_VISIBILITY_ALWAYS) {
|
||||
[NSMenu setMenuBarVisible:YES];
|
||||
} else {
|
||||
[NSMenu setMenuBarVisible:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_MenuVisibilityCallback(void *userdata, const char *name, const char *oldValue, const char *newValue)
|
||||
{
|
||||
if (newValue) {
|
||||
if (*newValue == '0' || SDL_strcasecmp(newValue, "false") == 0) {
|
||||
menu_visibility_hint = COCOA_MENU_VISIBILITY_NEVER;
|
||||
} else if (*newValue == '1' || SDL_strcasecmp(newValue, "true") == 0) {
|
||||
menu_visibility_hint = COCOA_MENU_VISIBILITY_ALWAYS;
|
||||
} else {
|
||||
menu_visibility_hint = COCOA_MENU_VISIBILITY_AUTO;
|
||||
}
|
||||
} else {
|
||||
menu_visibility_hint = COCOA_MENU_VISIBILITY_AUTO;
|
||||
}
|
||||
|
||||
// Update the current menu visibility.
|
||||
Cocoa_ToggleFullscreenSpaceMenuVisibility(SDL_GetKeyboardFocus());
|
||||
}
|
||||
|
||||
static NSScreen *ScreenForRect(const NSRect *rect)
|
||||
{
|
||||
NSPoint center = NSMakePoint(NSMidX(*rect), NSMidY(*rect));
|
||||
@@ -1195,7 +1250,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
||||
Cocoa_CheckClipboardUpdate(_data.videodata);
|
||||
|
||||
if (isFullscreenSpace && !window->fullscreen_exclusive) {
|
||||
[NSMenu setMenuBarVisible:NO];
|
||||
Cocoa_ToggleFullscreenSpaceMenuVisibility(window);
|
||||
}
|
||||
{
|
||||
const unsigned int newflags = [NSEvent modifierFlags] & NSEventModifierFlagCapsLock;
|
||||
@@ -1307,9 +1362,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
||||
if ([self windowOperationIsPending:PENDING_OPERATION_LEAVE_FULLSCREEN]) {
|
||||
[self setFullscreenSpace:NO];
|
||||
} else {
|
||||
if (window->fullscreen_exclusive) {
|
||||
[NSMenu setMenuBarVisible:NO];
|
||||
}
|
||||
Cocoa_ToggleFullscreenSpaceMenuVisibility(window);
|
||||
|
||||
/* Don't recurse back into UpdateFullscreenMode() if this was hit in
|
||||
* a blocking transition, as the caller is already waiting in
|
||||
@@ -1380,6 +1433,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
|
||||
NSWindow *nswindow = _data.nswindow;
|
||||
|
||||
inFullscreenTransition = NO;
|
||||
_data.fullscreen_space_requested = NO;
|
||||
|
||||
/* As of macOS 10.15, the window decorations can go missing sometimes after
|
||||
certain fullscreen-desktop->exlusive-fullscreen->windowed mode flows
|
||||
@@ -3030,25 +3084,15 @@ void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
}
|
||||
}
|
||||
|
||||
bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window)
|
||||
{
|
||||
@autoreleasepool {
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
|
||||
|
||||
if ([data.listener isInFullscreenSpace]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, bool state, bool blocking)
|
||||
{
|
||||
@autoreleasepool {
|
||||
bool succeeded = false;
|
||||
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
|
||||
|
||||
if (state) {
|
||||
data.fullscreen_space_requested = YES;
|
||||
}
|
||||
data.in_blocking_transition = blocking;
|
||||
if ([data.listener setFullscreenSpace:(state ? YES : NO)]) {
|
||||
if (blocking) {
|
||||
|
Reference in New Issue
Block a user