]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/Windows.m
macosx: implement native fullscreen behaviour for yosemite titlebar
[vlc] / modules / gui / macosx / Windows.m
index 062b0eab5a8bdd8f2c1adc39f89dbfff56d9ef82..48b1d82f6ebe73a4c76b231cd8ee8ceb07a75b11 100644 (file)
 
 - (VLCVoutView *)videoView
 {
-    if ([[self contentView] class] == [VLCVoutView class])
-        return (VLCVoutView *)[self contentView];
+    NSArray *o_subViews = [[self contentView] subviews];
+    if ([o_subViews count] > 0) {
+        id o_vout_view = [o_subViews objectAtIndex:0];
+
+        if ([o_vout_view class] == [VLCVoutView class])
+            return (VLCVoutView *)o_vout_view;
+    }
 
     return nil;
 }
 
     BOOL b_inFullscreen = [self fullscreen] || ([self respondsToSelector:@selector(inFullscreenTransition)] && [(VLCVideoWindowCommon *)self inFullscreenTransition]);
 
-    if(OSX_MAVERICKS && b_inFullscreen && constrainedRect.size.width == screenRect.size.width
+    if((OSX_MAVERICKS || OSX_YOSEMITE) && b_inFullscreen && constrainedRect.size.width == screenRect.size.width
           && constrainedRect.size.height != screenRect.size.height
           && abs(screenRect.size.height - constrainedRect.size.height) <= 25.) {
 
 @interface VLCVideoWindowCommon (Internal)
 - (void)customZoom:(id)sender;
 - (void)hasBecomeFullscreen;
-- (void)leaveFullscreenAndFadeOut:(BOOL)fadeout;
 - (void)hasEndedFullscreen;
 @end
 
 @synthesize videoView=o_video_view;
 @synthesize controlsBar=o_controls_bar;
 @synthesize inFullscreenTransition=b_in_fullscreen_transition;
+@synthesize windowShouldExitFullscreenWhenFinished=b_windowShouldExitFullscreenWhenFinished;
 
 #pragma mark -
 #pragma mark Init
 
     if (b_nativeFullscreenMode) {
         [self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
-    } else {
-        [o_titlebar_view setFullscreenButtonHidden: YES];
     }
 
+
     [super awakeFromNib];
 }
 
 - (NSRect) customConstrainFrameRect: (NSRect)frameRect toScreen: (NSScreen*)screen
 {
     NSRect screenRect = [screen visibleFrame];
-    float difference;
+    CGFloat difference;
 
     /* Move top edge of the window inside the screen */
     difference = NSMaxY (frameRect) - NSMaxY (screenRect);
      the window */
     difference = NSMaxY (screenRect) - NSMaxY (frameRect);
     if (_styleMask & NSResizableWindowMask) {
-        float difference2;
+        CGFloat difference2;
 
         difference2 = screenRect.origin.y - frameRect.origin.y;
         difference2 -= difference;
     NSPoint topleftbase = NSMakePoint(0, [self frame].size.height);
     NSPoint topleftscreen = [self convertBaseToScreen: topleftbase];
 
-    unsigned int i_width = size.width;
-    unsigned int i_height = size.height;
-    if (i_width < windowMinSize.width)
-        i_width = windowMinSize.width;
-    if (i_height < f_min_video_height)
-        i_height = f_min_video_height;
+    CGFloat f_width = size.width;
+    CGFloat f_height = size.height;
+    if (f_width < windowMinSize.width)
+        f_width = windowMinSize.width;
+    if (f_height < f_min_video_height)
+        f_height = f_min_video_height;
 
     /* Calculate the window's new size */
     NSRect new_frame;
-    new_frame.size.width = [self frame].size.width - [o_video_view frame].size.width + i_width;
-    new_frame.size.height = [self frame].size.height - [o_video_view frame].size.height + i_height;
+    new_frame.size.width = [self frame].size.width - [o_video_view frame].size.width + f_width;
+    new_frame.size.height = [self frame].size.height - [o_video_view frame].size.height + f_height;
     new_frame.origin.x = topleftscreen.x;
     new_frame.origin.y = topleftscreen.y - new_frame.size.height;
 
         NSRect videoWindowFrame = [self frame];
         NSRect viewRect = [o_video_view convertRect:[o_video_view bounds] toView: nil];
         NSRect contentRect = [self contentRectForFrameRect:videoWindowFrame];
-        float marginy = viewRect.origin.y + videoWindowFrame.size.height - contentRect.size.height;
-        float marginx = contentRect.size.width - viewRect.size.width;
+        CGFloat marginy = viewRect.origin.y + videoWindowFrame.size.height - contentRect.size.height;
+        CGFloat marginx = contentRect.size.width - viewRect.size.width;
         if (o_titlebar_view && b_dark_interface)
             marginy += [o_titlebar_view frame].size.height;
 
     [super mouseMoved: theEvent];
 }
 
+#pragma mark -
+#pragma mark Key events
+
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+    BOOL b_alt_pressed = ([theEvent modifierFlags] & NSAlternateKeyMask) != 0;
+    [o_titlebar_view informModifierPressed: b_alt_pressed];
+
+    [super flagsChanged:theEvent];
+}
+
 #pragma mark -
 #pragma mark Lion native fullscreen handling
 
     [[[VLCMainWindow sharedInstance] fsPanel] setNonActive:nil];
 }
 
-#ifdef MAC_OS_X_VERSION_10_7
 -(NSArray*)customWindowsToEnterFullScreenForWindow:(NSWindow *)window
 {
     if (window == self) {
         [[window animator] setFrame:frameBeforeLionFullscreen display:YES animate:YES];
     } completionHandler:nil];
 }
-#endif
 
 - (void)windowWillEnterFullScreen:(NSNotification *)notification
 {
-    // workaround, see #6668
-    [NSApp setPresentationOptions:(NSApplicationPresentationFullScreen | NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
-
     i_originalLevel = [self level];
+    b_windowShouldExitFullscreenWhenFinished = [[VLCMain sharedInstance] activeVideoPlayback];
+
     // b_fullscreen and b_in_fullscreen_transition must not be true yet
     [[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: NSNormalWindowLevel];
     [self setLevel:NSNormalWindowLevel];
         if ([[subviews objectAtIndex:x] respondsToSelector:@selector(reshape)])
             [[subviews objectAtIndex:x] reshape];
     }
-
 }
 
 - (void)windowWillExitFullScreen:(NSNotification *)notification
     b_in_fullscreen_transition = YES;
     [self setFullscreen: NO];
 
-    var_SetBool(pl_Get(VLCIntf), "fullscreen", false);
-
     if ([self hasActiveVideo]) {
+        var_SetBool(pl_Get(VLCIntf), "fullscreen", false);
+
         vout_thread_t *p_vout = getVoutForActiveWindow();
         if (p_vout) {
             var_SetBool(p_vout, "fullscreen", false);
 #pragma mark -
 #pragma mark Fullscreen Logic
 
-- (void)enterFullscreen
+- (void)enterFullscreenWithAnimation:(BOOL)b_animation
 {
     NSMutableDictionary *dict1, *dict2;
     NSScreen *screen;
         [o_fullscreen_window setHasActiveVideo: YES];
         [o_fullscreen_window setFullscreen: YES];
 
-        if (![self isVisible] || [self alphaValue] == 0.0) {
+        /* Make sure video view gets visible in case the playlist was visible before */
+        b_video_view_was_hidden = [o_video_view isHidden];
+        [o_video_view setHidden: NO];
+
+        if (!b_animation) {
             /* We don't animate if we are not visible, instead we
              * simply fade the display */
             CGDisplayFadeReservationToken token;
                 CGDisplayFade(token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES);
             }
 
-            [screen setFullscreenPresentationOptions];
-
+            NSDisableScreenUpdates();
             [o_video_view retain];
             [[o_video_view superview] replaceSubview:o_video_view with:o_temp_view];
             [o_temp_view setFrame:[o_video_view frame]];
-            [o_fullscreen_window setContentView:o_video_view];
+            [[o_fullscreen_window contentView] addSubview:o_video_view];
+            [o_video_view setFrame: [[o_fullscreen_window contentView] frame]];
             [o_video_view release];
+            NSEnableScreenUpdates();
+
+            [screen setFullscreenPresentationOptions];
+
+            [o_fullscreen_window setFrame:screen_rect display:YES animate:NO];
 
-            [o_fullscreen_window makeKeyAndOrderFront:self];
             [o_fullscreen_window orderFront:self animate:YES];
 
-            [o_fullscreen_window setFrame:screen_rect display:YES animate:YES];
             [o_fullscreen_window setLevel:NSNormalWindowLevel];
 
             if (blackout_other_displays) {
             return;
         }
 
-        /* Make sure video view gets visible in case the playlist was visible before */
-        b_video_view_was_hidden = [o_video_view isHidden];
-        [o_video_view setHidden: NO];
-
         /* Make sure we don't see the o_video_view disappearing of the screen during this operation */
         NSDisableScreenUpdates();
         [o_video_view retain];
         [[o_video_view superview] replaceSubview:o_video_view with:o_temp_view];
         [o_temp_view setFrame:[o_video_view frame]];
-        [o_fullscreen_window setContentView:o_video_view];
+        [[o_fullscreen_window contentView] addSubview:o_video_view];
+        [o_video_view setFrame: [[o_fullscreen_window contentView] frame]];
         [o_video_view release];
         [o_fullscreen_window makeKeyAndOrderFront:self];
         NSEnableScreenUpdates();
     [self setFullscreen:YES];
 }
 
-- (void)leaveFullscreen
-{
-    [self leaveFullscreenAndFadeOut: NO];
-}
-
-- (void)leaveFullscreenAndFadeOut: (BOOL)fadeout
+- (void)leaveFullscreenWithAnimation:(BOOL)b_animation
 {
     NSMutableDictionary *dict1, *dict2;
     NSRect frame;
         return;
     }
 
-    if (fadeout) {
+    [[[VLCMainWindow sharedInstance] fsPanel] setNonActive: nil];
+    [[o_fullscreen_window screen] setNonFullscreenPresentationOptions];
+
+    if (o_fullscreen_anim1) {
+        [o_fullscreen_anim1 stopAnimation];
+        [o_fullscreen_anim1 release];
+        o_fullscreen_anim1 = nil;
+    }
+    if (o_fullscreen_anim2) {
+        [o_fullscreen_anim2 stopAnimation];
+        [o_fullscreen_anim2 release];
+        o_fullscreen_anim2 = nil;
+    }
+
+    b_in_fullscreen_transition = YES;
+    [self setFullscreen:NO];
+
+    if (!b_animation) {
         /* We don't animate if we are not visible, instead we
          * simply fade the display */
         CGDisplayFadeReservationToken token;
             CGDisplayFade(token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES);
         }
 
-        [[[VLCMainWindow sharedInstance] fsPanel] setNonActive: nil];
-        [[o_fullscreen_window screen] setNonFullscreenPresentationOptions];
+        [self setAlphaValue:1.0];
+        [self orderFront: self];
 
         /* Will release the lock */
         [self hasEndedFullscreen];
 
-        /* Our window is hidden, and might be faded. We need to workaround that, so note it
-         * here */
-        b_window_is_invisible = YES;
-
         if (blackout_other_displays) {
             CGDisplayFade(token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO);
             CGReleaseDisplayFadeReservation(token);
         return;
     }
 
-    b_in_fullscreen_transition = YES;
-
     [self setAlphaValue: 0.0];
     [self orderFront: self];
     [[o_video_view window] orderFront: self];
 
-    [[[VLCMainWindow sharedInstance] fsPanel] setNonActive: nil];
-    [[o_fullscreen_window screen] setNonFullscreenPresentationOptions];
-
-    if (o_fullscreen_anim1) {
-        [o_fullscreen_anim1 stopAnimation];
-        [o_fullscreen_anim1 release];
-    }
-    if (o_fullscreen_anim2) {
-        [o_fullscreen_anim2 stopAnimation];
-        [o_fullscreen_anim2 release];
-    }
-
     frame = [[o_temp_view superview] convertRect: [o_temp_view frame] toView: nil]; /* Convert to Window base coord */
     frame.origin.x += [self frame].origin.x;
     frame.origin.y += [self frame].origin.y;
 
 - (void)hasEndedFullscreen
 {
-    [self setFullscreen:NO];
     b_in_fullscreen_transition = NO;
 
     /* This function is private and should be only triggered at the end of the fullscreen change animation */
 
     [o_video_view setHidden: b_video_view_was_hidden];
 
-    [super makeKeyAndOrderFront:self]; /* our version (in main window) contains a workaround */
+    [self makeKeyAndOrderFront:self];
 
     [o_fullscreen_window orderOut: self];
     NSEnableScreenUpdates();
     [self setLevel:i_originalLevel];
 
     [self setAlphaValue: config_GetFloat(VLCIntf, "macosx-opaqueness")];
-
-    // if we quit fullscreen because there is no video anymore, make sure non-embedded window is not visible
-    if (![[VLCMain sharedInstance] activeVideoPlayback] && [self class] != [VLCMainWindow class])
-        [self orderOut: self];
 }
 
 - (void)animationDidEnd:(NSAnimation*)animation
 {
     NSArray *viewAnimations;
-    if (o_makekey_anim == animation) {
-        [o_makekey_anim release];
-        return;
-    }
     if ([animation currentValue] < 1.0)
         return;
 
         [self hasBecomeFullscreen];
 }
 
-- (void)orderOut:(id)sender
-{
-    [super orderOut:sender];
-
-    /*
-     * TODO reimplement leaveFullscreenAndFadeOut:YES, or remove code
-     * and the hack below
-    
-    if (![NSStringFromClass([self class]) isEqualToString:@"VLCMainWindow"]) {
-        [self leaveFullscreenAndFadeOut:YES];
-    }
-     */
-}
-
-- (void)makeKeyAndOrderFront: (id)sender
-{
-    /* Hack
-     * when we exit fullscreen and fade out, we may endup in
-     * having a window that is faded. We can't have it fade in unless we
-     * animate again. */
-
-    if (!b_window_is_invisible) {
-        /* Make sure we don't do it too much */
-        [super makeKeyAndOrderFront: sender];
-        return;
-    }
-
-    [super setAlphaValue:0.0f];
-    [super makeKeyAndOrderFront: sender];
-
-    NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:2];
-    [dict setObject:self forKey:NSViewAnimationTargetKey];
-    [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
-
-    o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
-    [dict release];
-
-    [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking];
-    [o_makekey_anim setDuration: 0.1];
-    [o_makekey_anim setFrameRate: 30];
-    [o_makekey_anim setDelegate: self];
-
-    [o_makekey_anim startAnimation];
-    b_window_is_invisible = NO;
-
-    /* fullscreenAnimation will be unlocked when animation ends */
-}
-
-
 #pragma mark -
 #pragma mark Accessibility stuff