diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 198513724..edd3d0647 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -1653,6 +1653,7 @@ - (void)performMiniaturize:(id)sender - (BOOL)canBecomeKeyWindow { if (glfw_window && glfw_window->ns.layer_shell.is_active) { + if (glfw_window->ns.layer_shell.config.type == GLFW_LAYER_SHELL_BACKGROUND) return NO; switch(glfw_window->ns.layer_shell.config.focus_policy) { case GLFW_FOCUS_NOT_ALLOWED: return NO; case GLFW_FOCUS_EXCLUSIVE: return YES; @@ -1665,7 +1666,7 @@ - (BOOL)canBecomeKeyWindow - (BOOL)canBecomeMainWindow { - return YES; + return !glfw_window->ns.layer_shell.is_active || glfw_window->ns.layer_shell.config.type != GLFW_LAYER_SHELL_BACKGROUND; } static void @@ -1928,42 +1929,63 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) bool _glfwPlatformSetLayerShellConfig(_GLFWwindow* window, const GLFWLayerShellConfig *value) { #define config window->ns.layer_shell.config +#define nswindow window->ns.object window->resizable = false; if (value) config = *value; - const bool is_transparent = ![window->ns.object isOpaque]; + const bool is_transparent = ![nswindow isOpaque]; int background_blur = config.related.background_blur; if (!is_transparent || config.related.background_opacity >= 1.f) { background_blur = 0; } - [window->ns.object setBackgroundColor:nil]; + [nswindow setBackgroundColor:nil]; _glfwPlatformSetWindowBlur(window, background_blur); window->ns.titlebar_hidden = true; window->decorated = false; - [window->ns.object setTitlebarAppearsTransparent:false]; - [window->ns.object setHasShadow:false]; - [window->ns.object setTitleVisibility:NSWindowTitleHidden]; + [nswindow setTitlebarAppearsTransparent:false]; + [nswindow setHasShadow:false]; + [nswindow setTitleVisibility:NSWindowTitleHidden]; NSColorSpace *cs = nil; switch (config.related.color_space) { case SRGB_COLORSPACE: cs = [NSColorSpace sRGBColorSpace]; break; case DISPLAY_P3_COLORSPACE: cs = [NSColorSpace displayP3ColorSpace]; break; case DEFAULT_COLORSPACE: cs = nil; break; // using deviceRGBColorSpace causes a hang when transitioning to fullscreen } - [window->ns.object setColorSpace:cs]; - [[window->ns.object standardWindowButton: NSWindowCloseButton] setHidden:true]; - [[window->ns.object standardWindowButton: NSWindowMiniaturizeButton] setHidden:true]; - [[window->ns.object standardWindowButton: NSWindowZoomButton] setHidden:true]; - [window->ns.object setStyleMask:NSWindowStyleMaskBorderless]; + [nswindow setColorSpace:cs]; + [[nswindow standardWindowButton: NSWindowCloseButton] setHidden:true]; + [[nswindow standardWindowButton: NSWindowMiniaturizeButton] setHidden:true]; + [[nswindow standardWindowButton: NSWindowZoomButton] setHidden:true]; + [nswindow setStyleMask:NSWindowStyleMaskBorderless]; // HACK: Changing the style mask can cause the first responder to be cleared - [window->ns.object makeFirstResponder:window->ns.view]; - uint32_t width = 0, height = 0; + [nswindow makeFirstResponder:window->ns.view]; NSScreen *screen = screen_for_window_center(window); - // CGFloat monitor_width = NSWidth(screen.frame), monitor_height = NSHeight(screen.frame); unsigned cell_width, cell_height; double left_edge_spacing, top_edge_spacing, right_edge_spacing, bottom_edge_spacing; float xscale = (float)config.expected.xscale, yscale = (float)config.expected.yscale; _glfwPlatformGetWindowContentScale(window, &xscale, &yscale); config.size_callback((GLFWwindow*)window, xscale, yscale, &cell_width, &cell_height, &left_edge_spacing, &top_edge_spacing, &right_edge_spacing, &bottom_edge_spacing); - CGFloat x = NSMinX(screen.visibleFrame), y = NSMinY(screen.visibleFrame); - [window->ns.object setFrame:NSMakeRect(x, y, (CGFloat)width, (CGFloat)height) display:YES]; + CGFloat x = NSMinX(screen.visibleFrame), y = NSMinY(screen.visibleFrame) + 1, width = NSWidth(screen.visibleFrame), height = NSHeight(screen.visibleFrame); + CGFloat dock_height = NSMinY(screen.visibleFrame) - NSMinY(screen.frame); + CGFloat menubar_height = NSHeight(screen.frame) - NSHeight(screen.visibleFrame) - dock_height; + // Screen co-ordinate system is with origin in lower left and y increasing upwards and x increasing rightwards + // NSLog(@"frame: %@ visibleFrame: %@\n", NSStringFromRect(screen.frame), NSStringFromRect(screen.visibleFrame)); + NSWindowLevel level = NSScreenSaverWindowLevel - 1; + NSWindowAnimationBehavior animation_behavior = NSWindowAnimationBehaviorUtilityWindow; + if (config.type == GLFW_LAYER_SHELL_BACKGROUND) { + x = NSMinX(screen.frame); height = NSHeight(screen.frame) - menubar_height + 1; y = NSMinY(screen.frame); width = NSWidth(screen.frame); + animation_behavior = NSWindowAnimationBehaviorNone; + // See: https://stackoverflow.com/questions/4982584/how-do-i-draw-the-desktop-on-mac-os-x/4982619#4982619 + level = kCGDesktopWindowLevel; + } + + x += config.requested_left_margin; width -= config.requested_left_margin + config.requested_right_margin; + y += config.requested_bottom_margin; height -= config.requested_top_margin + config.requested_bottom_margin; + + [nswindow setAnimationBehavior:animation_behavior]; + [nswindow setLevel:level]; + [nswindow setCollectionBehavior: (NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorIgnoresCycle)]; + [nswindow setFrame:NSMakeRect(x, y, width, height) display:YES animate:config.type != GLFW_LAYER_SHELL_BACKGROUND]; + if (config.type == GLFW_LAYER_SHELL_BACKGROUND) [nswindow orderBack:nil]; + else [nswindow orderFrontRegardless]; return true; #undef config +#undef nswindow } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) @@ -2135,7 +2157,9 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window) void _glfwPlatformShowWindow(_GLFWwindow* window) { - [window->ns.object orderFront:nil]; + if (window->ns.layer_shell.is_active && window->ns.layer_shell.config.type == GLFW_LAYER_SHELL_BACKGROUND) { + [window->ns.object orderBack:nil]; + } else [window->ns.object orderFront:nil]; } void _glfwPlatformHideWindow(_GLFWwindow* window)