Skip to content

Commit 0d59902

Browse files
committed
Cocoa: Fix clearing of unrelated window style bits
Whenever GLFW changed the window style mask, a new mask was created from scratch based on the attributes set on the GLFW window object. This caused us to potentially clear unrelated window style bits. This was always wrong but became a critical issue when Cocoa began throwing an exception if an application cleared the NSWindowStyleMaskFullScreen while the window is in macOS fullscreen. This commit reworks all style mask editing so it only changes the relevant bits, preserving all others. This is only a narrow bug fix to prevent crashes, intended for the stable branch. Our interaction with macOS fullscreen is still very poor. The next step after this is a set of patches that improve the interaction between the current API and macOS fullscreen. Fixes glfw#1886 Fixes glfw#2110
1 parent 6f8ec40 commit 0d59902

File tree

3 files changed

+60
-26
lines changed

3 files changed

+60
-26
lines changed

Diff for: CONTRIBUTORS.md

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ video tutorials.
8484
- heromyth
8585
- Lucas Hinderberger
8686
- Paul Holden
87+
- Hajime Hoshi
8788
- Warren Hu
8889
- Charles Huber
8990
- Brent Huisman
@@ -149,6 +150,7 @@ video tutorials.
149150
- James Murphy
150151
- Julian Møller
151152
- ndogxj
153+
- F. Nedelec
152154
- n3rdopolis
153155
- Kristian Nielsen
154156
- Kamil Nowakowski

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ information on what to include when reporting a bug.
255255
- [Cocoa] Bugfix: A connected Apple AirPlay would emit a useless error (#1791)
256256
- [Cocoa] Bugfix: The EGL and OSMesa libraries were not unloaded on termination
257257
- [Cocoa] Bugfix: `GLFW_MAXIMIZED` was always true when `GLFW_RESIZABLE` was false
258+
- [Cocoa] Bugfix: Changing `GLFW_DECORATED` in macOS fullscreen would abort
259+
application (#1886)
260+
- [Cocoa] Bugfix: Setting a monitor from macOS fullscreen would abort
261+
application (#2110)
258262
- [X11] Bugfix: The CMake files did not check for the XInput headers (#1480)
259263
- [X11] Bugfix: Key names were not updated when the keyboard layout changed
260264
(#1462,#1528)

Diff for: src/cocoa_window.m

+54-26
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,6 @@
3131
#include <float.h>
3232
#include <string.h>
3333

34-
// Returns the style mask corresponding to the window settings
35-
//
36-
static NSUInteger getStyleMask(_GLFWwindow* window)
37-
{
38-
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
39-
40-
if (window->monitor || !window->decorated)
41-
styleMask |= NSWindowStyleMaskBorderless;
42-
else
43-
{
44-
styleMask |= NSWindowStyleMaskTitled |
45-
NSWindowStyleMaskClosable;
46-
47-
if (window->resizable)
48-
styleMask |= NSWindowStyleMaskResizable;
49-
}
50-
51-
return styleMask;
52-
}
53-
5434
// Returns whether the cursor is in the content area of the specified window
5535
//
5636
static GLFWbool cursorInContentArea(_GLFWwindow* window)
@@ -809,9 +789,21 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
809789
else
810790
contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
811791

792+
NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
793+
794+
if (window->monitor || !window->decorated)
795+
styleMask |= NSWindowStyleMaskBorderless;
796+
else
797+
{
798+
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
799+
800+
if (window->resizable)
801+
styleMask |= NSWindowStyleMaskResizable;
802+
}
803+
812804
window->ns.object = [[GLFWWindow alloc]
813805
initWithContentRect:contentRect
814-
styleMask:getStyleMask(window)
806+
styleMask:styleMask
815807
backing:NSBackingStoreBuffered
816808
defer:NO];
817809

@@ -1241,9 +1233,10 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
12411233
{
12421234
const NSRect contentRect =
12431235
NSMakeRect(xpos, _glfwTransformYCocoa(ypos + height - 1), width, height);
1236+
const NSUInteger styleMask = [window->ns.object styleMask];
12441237
const NSRect frameRect =
12451238
[window->ns.object frameRectForContentRect:contentRect
1246-
styleMask:getStyleMask(window)];
1239+
styleMask:styleMask];
12471240

12481241
[window->ns.object setFrame:frameRect display:YES];
12491242
}
@@ -1260,7 +1253,27 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
12601253
// TODO: Solve this in a less terrible way
12611254
_glfwPollEventsCocoa();
12621255

1263-
const NSUInteger styleMask = getStyleMask(window);
1256+
NSUInteger styleMask = [window->ns.object styleMask];
1257+
1258+
if (window->monitor)
1259+
{
1260+
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
1261+
styleMask |= NSWindowStyleMaskBorderless;
1262+
}
1263+
else
1264+
{
1265+
if (window->decorated)
1266+
{
1267+
styleMask &= ~NSWindowStyleMaskBorderless;
1268+
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
1269+
}
1270+
1271+
if (window->resizable)
1272+
styleMask |= NSWindowStyleMaskResizable;
1273+
else
1274+
styleMask &= ~NSWindowStyleMaskResizable;
1275+
}
1276+
12641277
[window->ns.object setStyleMask:styleMask];
12651278
// HACK: Changing the style mask can cause the first responder to be cleared
12661279
[window->ns.object makeFirstResponder:window->ns.view];
@@ -1391,17 +1404,18 @@ void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled)
13911404
{
13921405
@autoreleasepool {
13931406

1394-
[window->ns.object setStyleMask:getStyleMask(window)];
1395-
1407+
const NSUInteger styleMask = [window->ns.object styleMask];
13961408
if (enabled)
13971409
{
1410+
[window->ns.object setStyleMask:(styleMask | NSWindowStyleMaskResizable)];
13981411
const NSWindowCollectionBehavior behavior =
13991412
NSWindowCollectionBehaviorFullScreenPrimary |
14001413
NSWindowCollectionBehaviorManaged;
14011414
[window->ns.object setCollectionBehavior:behavior];
14021415
}
14031416
else
14041417
{
1418+
[window->ns.object setStyleMask:(styleMask & ~NSWindowStyleMaskResizable)];
14051419
const NSWindowCollectionBehavior behavior =
14061420
NSWindowCollectionBehaviorFullScreenNone;
14071421
[window->ns.object setCollectionBehavior:behavior];
@@ -1413,8 +1427,22 @@ void _glfwSetWindowResizableCocoa(_GLFWwindow* window, GLFWbool enabled)
14131427
void _glfwSetWindowDecoratedCocoa(_GLFWwindow* window, GLFWbool enabled)
14141428
{
14151429
@autoreleasepool {
1416-
[window->ns.object setStyleMask:getStyleMask(window)];
1430+
1431+
NSUInteger styleMask = [window->ns.object styleMask];
1432+
if (enabled)
1433+
{
1434+
styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
1435+
styleMask &= ~NSWindowStyleMaskBorderless;
1436+
}
1437+
else
1438+
{
1439+
styleMask |= NSWindowStyleMaskBorderless;
1440+
styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
1441+
}
1442+
1443+
[window->ns.object setStyleMask:styleMask];
14171444
[window->ns.object makeFirstResponder:window->ns.view];
1445+
14181446
} // autoreleasepool
14191447
}
14201448

0 commit comments

Comments
 (0)