- Merged patch from Nico (code style, :popup, release vimView)
[MacVim/jjgod.git] / MMFullscreenWindow.m
blobed0dab9085cc0634950418ba405eaf02ab27e7ab
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 #import "MMFullscreenWindow.h"
12 #import <PSMTabBarControl.h>
13 #import "MMVimView.h"
14 #import "MMTextView.h"
15 #import "MMWindowController.h"
16 #import <Carbon/Carbon.h>
20 @implementation MMFullscreenWindow
22 - (MMFullscreenWindow *)initWithWindow:(NSWindow *)t view:(MMVimView *)v
24     NSScreen* screen = [t screen];
26     // XXX: what if screen == nil?
28     // you can't change the style of an existing window in cocoa. create a new
29     // window and move the MMTextView into it.
30     // (another way would be to make the existing window large enough that the
31     // title bar is off screen. but that doesn't work with multiple screens).  
32     self = [super initWithContentRect:[screen frame]
33                             styleMask:NSBorderlessWindowMask
34                               backing:NSBackingStoreBuffered
35                                 defer:YES
36                                screen:screen];
37       
38     if (self == nil)
39         return nil;
41     [self setHasShadow:NO];
42     [self setShowsResizeIndicator:NO];
43     [self setBackgroundColor:[NSColor blackColor]];
44     [self setReleasedWhenClosed:NO];
46     target = t;  [target retain];
47     view = v;  [view retain];
49     return self;
52 - (void)dealloc
54     [target release];
55     [view release];
57     [super dealloc];
60 - (void)centerView
62     NSRect outer = [self frame], inner = [view frame];
63     //NSLog(@"%s %@%@", _cmd, NSStringFromRect(outer), NSStringFromRect(inner));
65     NSPoint origin = NSMakePoint((outer.size.width - inner.size.width)/2,
66                                  (outer.size.height - inner.size.height)/2);
67     [view setFrameOrigin:origin];
70 - (void)enterFullscreen
72     // hide menu and dock, both appear on demand
73     SetSystemUIMode(kUIModeAllSuppressed, 0); //requires 10.3
75     // fade to black
76     Boolean didBlend = NO;
77     CGDisplayFadeReservationToken token;
78     if (CGAcquireDisplayFadeReservation(.5, &token) == kCGErrorSuccess) {
79         CGDisplayFade(token, .25, kCGDisplayBlendNormal,
80             kCGDisplayBlendSolidColor, .0, .0, .0, true);
81         didBlend = YES;
82     }
83     
84     // fool delegate
85     id delegate = [target delegate];
86     [target setDelegate:nil];
87     
88     // make target's window controller believe that it's now controlling us
89     [target retain];  // NSWindowController will release target once in the
90                       // in the next line
91     [[target windowController] setWindow:self];
94     oldTabBarStyle = [[view tabBarControl] styleName];
95     [[view tabBarControl] setStyleNamed:@"Unified"];
97     // add text view
98     oldPosition = [view frame].origin;
100     [[self contentView] addSubview:view];
101     [self setInitialFirstResponder:[view textView]];
102     
103     [self setTitle:[target title]];
104     [self setOpaque:[target isOpaque]];
106     // make us visible and target invisible
107     [target orderOut:self];
108     [self makeKeyAndOrderFront:self];
110     // don't set this sooner, so we don't get an additional
111     // focus gained message  
112     [self setDelegate:delegate];
114     // update bottom right corner scrollbar (no resize handle in fu mode)
115     [[self windowController] placeViews];
116     
117     // the call above moves the text view in the lower left corner, fix that
118     // XXX: still required?
119     [self centerView];
120     [self display];
122     // fade back in
123     if (didBlend) {
124         CGDisplayFade(token, .25, kCGDisplayBlendSolidColor,
125             kCGDisplayBlendNormal, .0, .0, .0, false);
126         CGReleaseDisplayFadeReservation(token);
127     }
130 - (void)leaveFullscreen
132     // fade to black
133     Boolean didBlend = NO;
134     CGDisplayFadeReservationToken token;
135     if (CGAcquireDisplayFadeReservation(.5, &token) == kCGErrorSuccess) {
136         CGDisplayFade(token, .25, kCGDisplayBlendNormal,
137             kCGDisplayBlendSolidColor, .0, .0, .0, true);
138         didBlend = YES;
139     }
141     // fix up target controller
142     [self retain];  // NSWindowController releases us once
143     [[self windowController] setWindow:target];
146     [[view tabBarControl] setStyleNamed:oldTabBarStyle];
148     // fix delegate
149     id delegate = [self delegate];
150     [self setDelegate:nil];
151     
152     // move text view back to original window, hide fullscreen window,
153     // show original window
154     // do this _after_ resetting delegate and window controller, so the
155     // window controller doesn't get a focus lost message from the fullscreen
156     // window.
157     [[target contentView] addSubview:view];
158     [view setFrameOrigin:oldPosition];
159     [self close];
160     [target makeKeyAndOrderFront:self];
162     // ...but we don't want a focus gained message either, so don't set this
163     // sooner
164     [target setDelegate:delegate];
167     // update bottom right corner scrollbar (resize handle reappears)
168     // XXX: Doesn't work?
169     [[self windowController] placeViews];
170     [view placeScrollbars];
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 // the window controller will send us messages that are meant for the original,
201 // non-fullscreen window. forward those, and interpret the messages that are
202 // interesting for us
204 - (void)setTitle:(NSString *)title
206     [target setTitle:title];
207     [super setTitle:title];
210 // HACK: if the T flag in guioptions is changed in fu mode, the toolbar needs
211 // to be changed when nofu is set. MMWindowController gets the toolbar object,
212 // so we need to return a toolbar from this method, even if none is visible for
213 // the fullscreen window. Seems to work, though.
214 - (NSToolbar *)toolbar
216     return [target toolbar];
219 - (void)setFrame:(NSRect)frame display:(BOOL)display
221     // HACK: if the target window would resize, we have to call our own
222     // windowDidResize method so that placeViews in MMWindowController is called
223     if (!NSEqualRects(frame, [target frame]))
224     {
225         [target setFrame:frame display:NO];
227         // XXX: send this directly to MMVimView
228         if ([[self delegate] respondsToSelector:@selector(windowDidResize:)])
229           [[self delegate] windowDidResize:nil];
231         [self centerView];
232         [self display];
233     }
236 /*- (NSRect)frame
238     return [target frame];  // really? needed by MMWindowController placeViews.
239                             //  but mucks up display
242 - (NSRect)contentRectForFrameRect:(NSRect)rect
244     //return [target contentRectForFrameRect:rect];
245     
246     // EVIL HACK: this is always called with [[self window] frame] as argument
247     // from MMWindowController. We can't let frame return the frame of target,
248     // so "fix" this here.
249     return [target contentRectForFrameRect:[target frame]];
252 - (NSRect)frameRectForContentRect:(NSRect)contentRect
254     return [target frameRectForContentRect:contentRect];
257 - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen
259     return [target constrainFrameRect:frameRect toScreen:screen];
262 - (void)setContentResizeIncrements:(NSSize)size
264     [target setContentResizeIncrements:size];
267 - (void)setOpaque:(BOOL)isOpaque
269     // XXX: Do we want transparency even in fullscreen mode?
270     [super setOpaque:isOpaque];
271     [target setOpaque:isOpaque];
274 @end