Fix a wide character bug
[MacVim.git] / src / MacVim / MMFullscreenWindow.m
blobfe781677b14ecfec94ee72919db4363f32b8f20d
1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
2  *
3  * VIM - Vi IMproved            by Bram Moolenaar
4  *                              MacVim GUI port by Bjorn Winckler
5  *
6  * Do ":help uganda"  in Vim to read copying and usage conditions.
7  * Do ":help credits" in Vim to see a list of people who contributed.
8  * See README.txt for an overview of the Vim source code.
9  */
11  * MMFullscreen
12  *
13  * Support for full-screen editing.
14  *
15  * Author: Nico Weber
16  */
18 #import "MMFullscreenWindow.h"
19 #import <PSMTabBarControl.h>
20 #import "MMVimView.h"
21 #import "MMTextView.h"
22 #import "MMWindowController.h"
23 #import <Carbon/Carbon.h>
27 @implementation MMFullscreenWindow
29 - (MMFullscreenWindow *)initWithWindow:(NSWindow *)t view:(MMVimView *)v
31     NSScreen* screen = [t screen];
33     // XXX: what if screen == nil?
35     // you can't change the style of an existing window in cocoa. create a new
36     // window and move the MMTextView into it.
37     // (another way would be to make the existing window large enough that the
38     // title bar is off screen. but that doesn't work with multiple screens).  
39     self = [super initWithContentRect:[screen frame]
40                             styleMask:NSBorderlessWindowMask
41                               backing:NSBackingStoreBuffered
42                                 defer:YES
43                                screen:screen];
44       
45     if (self == nil)
46         return nil;
48     [self setHasShadow:NO];
49     [self setShowsResizeIndicator:NO];
50     [self setBackgroundColor:[NSColor blackColor]];
51     [self setReleasedWhenClosed:NO];
53     target = t;  [target retain];
54     view = v;  [view retain];
56     return self;
59 - (void)dealloc
61     [target release];
62     [view release];
64     [super dealloc];
67 - (void)centerView
69     NSRect outer = [self frame], inner = [view frame];
70     //NSLog(@"%s %@%@", _cmd, NSStringFromRect(outer), NSStringFromRect(inner));
72     NSPoint origin = NSMakePoint((outer.size.width - inner.size.width)/2,
73                                  (outer.size.height - inner.size.height)/2);
74     [view setFrameOrigin:origin];
77 - (void)enterFullscreen
79     // hide menu and dock, both appear on demand
80     SetSystemUIMode(kUIModeAllSuppressed, 0); //requires 10.3
82     // fade to black
83     Boolean didBlend = NO;
84     CGDisplayFadeReservationToken token;
85     if (CGAcquireDisplayFadeReservation(.5, &token) == kCGErrorSuccess) {
86         CGDisplayFade(token, .25, kCGDisplayBlendNormal,
87             kCGDisplayBlendSolidColor, .0, .0, .0, true);
88         didBlend = YES;
89     }
90     
91     // fool delegate
92     id delegate = [target delegate];
93     [target setDelegate:nil];
94     
95     // make target's window controller believe that it's now controlling us
96     [target retain];  // NSWindowController will release target once in the
97                       // in the next line
98     [[target windowController] setWindow:self];
101     oldTabBarStyle = [[view tabBarControl] styleName];
102     [[view tabBarControl] setStyleNamed:@"Unified"];
104     // add text view
105     oldPosition = [view frame].origin;
107     [[self contentView] addSubview:view];
108     [self setInitialFirstResponder:[view textView]];
109     
110     [self setTitle:[target title]];
111     [self setOpaque:[target isOpaque]];
113     // don't set this sooner, so we don't get an additional
114     // focus gained message  
115     [self setDelegate:delegate];
117     // update bottom right corner scrollbar (no resize handle in fu mode)
118     [view placeViews];
120     // move vim view to the window's center
121     [self centerView];
123     // make us visible and target invisible
124     [target orderOut:self];
125     [self makeKeyAndOrderFront:self];
127     // fade back in
128     if (didBlend) {
129         CGDisplayFade(token, .25, kCGDisplayBlendSolidColor,
130             kCGDisplayBlendNormal, .0, .0, .0, false);
131         CGReleaseDisplayFadeReservation(token);
132     }
135 - (void)leaveFullscreen
137     // fade to black
138     Boolean didBlend = NO;
139     CGDisplayFadeReservationToken token;
140     if (CGAcquireDisplayFadeReservation(.5, &token) == kCGErrorSuccess) {
141         CGDisplayFade(token, .25, kCGDisplayBlendNormal,
142             kCGDisplayBlendSolidColor, .0, .0, .0, true);
143         didBlend = YES;
144     }
146     // fix up target controller
147     [self retain];  // NSWindowController releases us once
148     [[self windowController] setWindow:target];
150     [[view tabBarControl] setStyleNamed:oldTabBarStyle];
152     // fix delegate
153     id delegate = [self delegate];
154     [self setDelegate:nil];
155     
156     // move text view back to original window, hide fullscreen window,
157     // show original window
158     // do this _after_ resetting delegate and window controller, so the
159     // window controller doesn't get a focus lost message from the fullscreen
160     // window.
161     [[target contentView] addSubview:view];
162     [view setFrameOrigin:oldPosition];
163     [self close];
164     [target makeKeyAndOrderFront:self];
166     // ...but we don't want a focus gained message either, so don't set this
167     // sooner
168     [target setDelegate:delegate];
170     // update bottom right corner scrollbar (resize handle reappears)
171     [view placeViews];
173     // fade back in  
174     if (didBlend) {
175         CGDisplayFade(token, .25, kCGDisplayBlendSolidColor,
176             kCGDisplayBlendNormal, .0, .0, .0, false);
177         CGReleaseDisplayFadeReservation(token);
178     }
179     
180     // order menu and dock back in
181     SetSystemUIMode(kUIModeNormal, 0);
184 // Title-less windows normally don't receive key presses, override this
185 - (BOOL)canBecomeKeyWindow
187     return YES;
190 // Title-less windows normally can't become main which means that another
191 // non-fullscreen window will have the "active" titlebar in expose. Bad, fix it.
192 - (BOOL)canBecomeMainWindow
194     return YES;
198 #pragma mark Proxy/Decorator/whatever stuff
200 - (void)scrollWheel:(NSEvent *)theEvent
202     [[view textView] scrollWheel:theEvent];
205 // the window controller will send us messages that are meant for the original,
206 // non-fullscreen window. forward those, and interpret the messages that are
207 // interesting for us
209 - (void)setTitle:(NSString *)title
211     [target setTitle:title];
212     [super setTitle:title];
215 // HACK: if the T flag in guioptions is changed in fu mode, the toolbar needs
216 // to be changed when nofu is set. MMWindowController gets the toolbar object,
217 // so we need to return a toolbar from this method, even if none is visible for
218 // the fullscreen window. Seems to work, though.
219 - (NSToolbar *)toolbar
221     return [target toolbar];
224 - (void)setFrame:(NSRect)frame display:(BOOL)display
226     // HACK: if the target window would resize, we have to call our own
227     // windowDidResize method so that placeViews in MMWindowController is called
228     if (!NSEqualRects(frame, [target frame]))
229     {
230         [target setFrame:frame display:NO];
232         // XXX: send this directly to MMVimView
233         if ([[self delegate] respondsToSelector:@selector(windowDidResize:)])
234           [[self delegate] windowDidResize:nil];
236         [self centerView];
237         [self display];
238     }
241 /*- (NSRect)frame
243     return [target frame];  // really? needed by MMWindowController placeViews.
244                             //  but mucks up display
247 - (NSRect)contentRectForFrameRect:(NSRect)rect
249     //return [target contentRectForFrameRect:rect];
250     
251     // EVIL HACK: if this is always called with [[self window] frame] as
252     // argument from MMWindowController, we can't let frame return the frame
253     // of target so "fix" this here.
254     if (NSEqualRects([self frame], rect)) {
255         return [target contentRectForFrameRect:[target frame]];
256     } else {
257         return [target contentRectForFrameRect:rect];
258     }
261 - (NSRect)frameRectForContentRect:(NSRect)contentRect
263     return [target frameRectForContentRect:contentRect];
266 - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen
268     return [target constrainFrameRect:frameRect toScreen:screen];
271 - (void)setContentResizeIncrements:(NSSize)size
273     [target setContentResizeIncrements:size];
276 - (void)setOpaque:(BOOL)isOpaque
278     // XXX: Do we want transparency even in fullscreen mode?
279     [super setOpaque:isOpaque];
280     [target setOpaque:isOpaque];
283 @end