Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
OOMacSnowLeopardFullScreenController.m
Go to the documentation of this file.
1/*
2
3OOMacSnowLeopardFullScreenController.m
4
5
6Oolite
7Copyright (C) 2004-2013 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
27
28#if OOLITE_MAC_OS_X && OOLITE_64_BIT
29
30
31#import <Carbon/Carbon.h> // For SetSystemUIMode()
32#import "MyOpenGLView.h"
33#import "OOLogging.h"
36
37
38#define SUPPRESS_BLANKING_WINDOWS ( 1 && OO_DEBUG)
39
40
41@interface OOMacSnowLeopardFullScreenController ()
42
43@property (nonatomic, retain) NSWindow *fullScreenWindow; // Window on main gameplay screen which contains our OpenGL view in full screen mode.
44@property (nonatomic, retain) NSArray *blankingWindows; // Plain black windows covering other screens if relevant.
45@property (nonatomic, retain) NSWindow *standardWindow; // The main game window, stashed away for use when existing full screen mode.
46
47@property (nonatomic, retain) NSScreen *gameScreen;
48
49- (void) beginFullScreenMode;
50- (void) endFullScreenMode;
51
52- (void) screenParametersChanged:(NSNotification *)notification;
53
54- (void) setUpBlankingWindowsForScreensOtherThan:(NSScreen *)gameScreen;
55- (void) removeBlankingWindows;
56
57@end
58
59
60@implementation OOMacSnowLeopardFullScreenController
61
62@synthesize fullScreenMode = _fullScreenMode; // Future note: needs to be explicit because property declaration is inherited.
63@synthesize fullScreenWindow = _fullScreenWindow;
64@synthesize blankingWindows = _blankingWindows;
65@synthesize standardWindow = _standardWindow;
66@synthesize gameScreen = _gameScreen;
67
68
69- (void) dealloc
70{
71 self.fullScreenMode = NO;
72
73 DESTROY(_fullScreenWindow);
74 DESTROY(_blankingWindows);
75 DESTROY(_standardWindow);
76 DESTROY(_gameScreen);
77
78 [super dealloc];
79}
80
81
82- (void) setFullScreenMode:(BOOL)value
83{
84 if (!value && self.fullScreenMode)
85 {
86 [self endFullScreenMode];
87 }
88 else if (value && !self.fullScreenMode)
89 {
90 [self beginFullScreenMode];
91 }
92}
93
94
95- (NSArray *) displayModes
96{
97 NSSize size = self.fullScreenWindow.frame.size;
98 NSDictionary *fakeMode = [NSDictionary dictionaryWithObjectsAndKeys:
99 [NSNumber numberWithUnsignedInt:size.width], kOODisplayWidth,
100 [NSNumber numberWithUnsignedInt:size.height], kOODisplayHeight,
101 nil];
102 return [NSArray arrayWithObject:fakeMode];
103}
104
105
106- (NSUInteger) indexOfCurrentDisplayMode
107{
108 return 0;
109}
110
111
112- (BOOL) setDisplayWidth:(NSUInteger)width height:(NSUInteger)height refreshRate:(NSUInteger)refresh
113{
114 return NO;
115}
116
117
118- (NSDictionary *) findDisplayModeForWidth:(NSUInteger)width height:(NSUInteger)height refreshRate:(NSUInteger)refresh
119{
120 NSDictionary *fakeMode = [self.displayModes objectAtIndex:0];
121 if (width == [fakeMode oo_unsignedIntegerForKey:kOODisplayWidth] &&
122 height == [fakeMode oo_unsignedIntegerForKey:kOODisplayHeight])
123 {
124 return fakeMode;
125 }
126 return nil;
127}
128
129
130- (void) noteMouseInteractionModeChangedFrom:(OOMouseInteractionMode)oldMode to:(OOMouseInteractionMode)newMode
131{
132 NSAssert(self.fullScreenMode, @"%s called in wrong state.", __FUNCTION__);
133
134 [self.gameView noteMouseInteractionModeChangedFrom:oldMode to:newMode];
135}
136
137
138#pragma mark - Actual full screen mode handling
139
140- (void) beginFullScreenMode
141{
142 NSAssert(!self.fullScreenMode, @"%s called in wrong state.", __FUNCTION__);
143
144 // Stash the windowed-mode window so we can restore to it later.
145 self.standardWindow = self.gameView.window;
146
147 /*
148 Set up a full-screen window. Based on OpenGL Programming Guide for Mac
149 [developer.apple.com], dated 2012-07-23, "Drawing to the Full Screen".
150 */
151 self.gameScreen = self.gameView.window.screen;
152 NSRect frame = self.gameScreen.frame;
153 OOFullScreenWindow *window = [[OOFullScreenWindow alloc] initWithContentRect:frame
154 styleMask:NSBorderlessWindowMask
155 backing:NSBackingStoreBuffered
156 defer:NO];
157 if (window == nil) return;
158
159 self.fullScreenWindow = [window autorelease];
160
161 [window setOpaque:YES];
162 [window setMovable:YES];
163 window.canBecomeKeyWindow = YES;
164 window.canBecomeMainWindow = YES;
165 window.acceptsMouseMovedEvents = YES;
166#if !OO_DEBUG
167 /*
168 Leaving a full-screen window visible in the background is anti-social,
169 but convenient in debug builds.
170 */
171 window.hidesOnDeactivate = YES;
172#endif
173
174 // TODO: handle screen reconfiguration.
175
176 [self.standardWindow orderOut:nil];
177 window.contentView = self.gameView;
178
179 SetSystemUIMode(kUIModeAllSuppressed, kUIOptionDisableMenuBarTransparency);
180 [self setUpBlankingWindowsForScreensOtherThan:self.gameScreen];
181
182 [window makeKeyAndOrderFront:self];
183
184 _fullScreenMode = YES;
185
186 // Subscribe to reconfiguration notifications.
187 [[NSNotificationCenter defaultCenter] addObserver:self
188 selector:@selector(screenParametersChanged:)
189 name:NSApplicationDidChangeScreenParametersNotification
190 object:NSApp];
191}
192
193
194- (void) endFullScreenMode
195{
196 NSAssert(self.fullScreenMode, @"%s called in wrong state.", __FUNCTION__);
197
198 [self.fullScreenWindow orderOut:nil];
199
200 [self removeBlankingWindows];
201 SetSystemUIMode(kUIModeNormal, 0);
202
203 self.standardWindow.contentView = self.gameView;
204 [self.standardWindow makeKeyAndOrderFront:nil];
205
206 self.standardWindow = nil;
207 self.fullScreenWindow = nil;
208 self.gameScreen = nil;
209
210 _fullScreenMode = NO;
211
212 // Unsubscribe from notifications.
213 [[NSNotificationCenter defaultCenter] removeObserver:self
214 name:NSApplicationDidChangeScreenParametersNotification
215 object:NSApp];
216}
217
218
219- (void) screenParametersChanged:(NSNotification *)notification
220{
221 NSAssert(self.fullScreenMode, @"%s called in wrong state.", __FUNCTION__);
222
223 [self.fullScreenWindow setFrame:self.gameScreen.frame display:YES];
224 [self setUpBlankingWindowsForScreensOtherThan:self.gameScreen];
225}
226
227
228- (void) setUpBlankingWindowsForScreensOtherThan:(NSScreen *)gameScreen
229{
230#if SUPPRESS_BLANKING_WINDOWS
231 // Skip blanking windows while debugging.
232 return;
233#endif
234
235 /*
236 On muliple-screen systems, fill all screens except the game screen
237 with an all-black window. This behaviour has its critics, but it is
238 consistent with both traditional Oolite behaviour and Mac OS X 10.7
239 and later standard behaviour.
240 */
241
242 // Remove any existing blanking windows.
243 [self removeBlankingWindows];
244
245 NSArray *screens = [NSScreen screens];
246 if (screens.count <= 1)
247 {
248 // No blanking windows needed on single-screen systems.
249 return;
250 }
251
252 NSMutableArray *windows = [NSMutableArray arrayWithCapacity:screens.count - 1];
253 for (NSScreen *screen in screens)
254 {
255 if ([screen isEqual:gameScreen]) continue;
256
257 NSRect frame = screen.frame;
258 OOFullScreenWindow *window = [[OOFullScreenWindow alloc] initWithContentRect:frame
259 styleMask:NSBorderlessWindowMask
260 backing:NSBackingStoreBuffered
261 defer:NO];
262
263 [window setOpaque:YES];
264 [window setMovable:YES];
265 window.collectionBehavior = NSWindowCollectionBehaviorTransient | NSWindowCollectionBehaviorIgnoresCycle;
266 window.canBecomeKeyWindow = NO;
267 window.canBecomeMainWindow = NO;
268 window.hidesOnDeactivate = YES;
269 window.backgroundColor = [NSColor blackColor];
270
271 [windows addObject:window];
272 [window orderFront:nil];
273 [window release];
274 }
275
276 self.blankingWindows = windows;
277}
278
279
280- (void) removeBlankingWindows
281{
282 for (NSWindow *window in self.blankingWindows)
283 {
284 [window orderOut:nil];
285 }
286 self.blankingWindows = nil;
287}
288
289
290- (void) checkWindowVisible:(NSTimer *)timer
291{
292 NSWindow *window = timer.userInfo;
293 OOLog(@"temp.fullScreen", @"Window %@ is %@ on screen %@", window, window.isVisible ? @"visible" : @"INVISIBLE", window.screen);
294}
295
296@end
297
298#endif
#define DESTROY(x)
Definition OOCocoa.h:77
#define kOODisplayHeight
#define kOODisplayWidth
#define OOLog(class, format,...)
Definition OOLogging.h:88
OOMouseInteractionMode
return nil
voidpf void uLong size
Definition ioapi.h:134