Commit dd86d6d4 authored by David Fuhrmann's avatar David Fuhrmann
Browse files

macosx: adapt and fix fullscreen handling after latest changes

Now, every video window is responsible for the fullscreen handling for its own.
Furthermore, fullscreen now acts entirely in response to vout events, and not over the
playlist fullscreen variable callback anymore.
Native fullscreen mode should also work correctly, but of course only
for embedded video in mainwindow.
parent 6c1febea
......@@ -561,6 +561,8 @@ static VLCCoreInteraction *_o_sharedInstance = nil;
if (p_vout) {
var_SetBool(p_vout, "fullscreen", b_fs);
vlc_object_release(p_vout);
} else { // e.g. lion fullscreen toggle
[[VLCMain sharedInstance] setFullscreen:b_fs forWindow:nil];
}
}
......
......@@ -89,27 +89,20 @@
BOOL b_nonembedded;
BOOL b_podcastView_displayed;
VLCWindow * o_fullscreen_window;
NSViewAnimation * o_fullscreen_anim1;
NSViewAnimation * o_fullscreen_anim2;
NSViewAnimation * o_makekey_anim;
NSView * o_temp_view;
/* set to yes if we are fullscreen and all animations are over */
BOOL b_fullscreen;
BOOL b_window_is_invisible;
NSRecursiveLock * o_animation_lock;
NSTimer *t_hide_mouse_timer;
VLCColorView * o_color_backdrop;
NSInteger i_originalLevel;
id o_current_video_window;
NSRect frameBeforePlayback;
}
+ (VLCMainWindow *)sharedInstance;
@property (readonly) BOOL fullscreen;
@property (readwrite) BOOL fullscreen;
@property (readonly) BOOL nativeFullscreenMode;
@property (readonly) VLCFSPanel* fsPanel;
- (VLCMainWindowControlsBar *)controlsBar;
......@@ -135,22 +128,14 @@
- (void)setPlay;
- (void)updateVolumeSlider;
- (void)showFullscreenController;
- (VLCVoutView *)setupVout:(vout_window_t *)p_wnd;
- (void)setVideoplayEnabled;
- (void)hideMouseCursor:(NSTimer *)timer;
- (void)recreateHideMouseTimer;
/* fullscreen handling */
- (void)showFullscreenController;
- (void)lockFullscreenAnimation;
- (void)unlockFullscreenAnimation;
- (void)enterFullscreen;
- (void)leaveFullscreen;
- (void)leaveFullscreenAndFadeOut: (BOOL)fadeout;
- (void)hasEndedFullscreen;
- (void)hasBecomeFullscreen;
/* lion's native fullscreen handling */
- (void)windowWillEnterFullScreen:(NSNotification *)notification;
- (void)windowDidEnterFullScreen:(NSNotification *)notification;
......
......@@ -57,6 +57,10 @@
@implementation VLCMainWindow
@synthesize fullscreen=b_fullscreen;
@synthesize nativeFullscreenMode=b_nativeFullscreenMode;
@synthesize fsPanel=o_fspanel;
static VLCMainWindow *_o_sharedInstance = nil;
+ (VLCMainWindow *)sharedInstance
......@@ -193,8 +197,6 @@ static VLCMainWindow *_o_sharedInstance = nil;
[self setTitle: _NS("VLC media player")];
b_dropzone_active = YES;
o_temp_view = [[NSView alloc] init];
[o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
[o_dropzone_view setFrame: [o_playlist_table frame]];
[o_left_split_view setFrame: [o_sidebar_view frame]];
......@@ -810,11 +812,8 @@ static VLCMainWindow *_o_sharedInstance = nil;
if (b_videoPlayback) {
frameBeforePlayback = [self frame];
// look for 'start at fullscreen'
[[VLCMain sharedInstance] fullscreenChanged];
} else {
if (!b_nonembedded)
if (!b_nonembedded && !b_fullscreen)
[[self animator] setFrame:frameBeforePlayback display:YES];
[self makeFirstResponder: nil];
......@@ -836,14 +835,8 @@ static VLCMainWindow *_o_sharedInstance = nil;
if (!b_videoPlayback)
[o_fspanel setNonActive: nil];
}
if (!b_videoPlayback && b_fullscreen) {
if (!b_nativeFullscreenMode)
[[VLCCoreInteraction sharedInstance] toggleFullscreen];
}
}
// Called automatically if window's acceptsMouseMovedEvents property is true
- (void)mouseMoved:(NSEvent *)theEvent
{
......@@ -882,362 +875,6 @@ static VLCMainWindow *_o_sharedInstance = nil;
[o_fspanel fadeIn];
}
- (BOOL)fullscreen
{
return b_fullscreen;
}
- (void)lockFullscreenAnimation
{
[o_animation_lock lock];
}
- (void)unlockFullscreenAnimation
{
[o_animation_lock unlock];
}
- (void)enterFullscreen
{
NSMutableDictionary *dict1, *dict2;
NSScreen *screen;
NSRect screen_rect;
NSRect rect;
BOOL blackout_other_displays = var_InheritBool(VLCIntf, "macosx-black");
o_current_video_window = [o_video_view window];
screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_InheritInteger(VLCIntf, "macosx-vdev")];
[self lockFullscreenAnimation];
if (!screen) {
msg_Dbg(VLCIntf, "chosen screen isn't present, using current screen for fullscreen mode");
screen = [o_current_video_window screen];
}
if (!screen) {
msg_Dbg(VLCIntf, "Using deepest screen");
screen = [NSScreen deepestScreen];
}
screen_rect = [screen frame];
[o_controls_bar setFullscreenState:YES];
//if (o_detached_video_window)
// [[o_detached_video_window controlsBar] setFullscreenState:YES];
[self recreateHideMouseTimer];
if (blackout_other_displays)
[screen blackoutOtherScreens];
/* Make sure we don't see the window flashes in float-on-top mode */
i_originalLevel = [o_current_video_window level];
[o_current_video_window setLevel:NSNormalWindowLevel];
/* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */
if (!o_fullscreen_window) {
/* We can't change the styleMask of an already created NSWindow, so we create another window, and do eye catching stuff */
rect = [[o_video_view superview] convertRect: [o_video_view frame] toView: nil]; /* Convert to Window base coord */
rect.origin.x += [o_current_video_window frame].origin.x;
rect.origin.y += [o_current_video_window frame].origin.y;
o_fullscreen_window = [[VLCWindow alloc] initWithContentRect:rect styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
[o_fullscreen_window setBackgroundColor: [NSColor blackColor]];
[o_fullscreen_window setCanBecomeKeyWindow: YES];
[o_fullscreen_window setCanBecomeMainWindow: YES];
if (![o_current_video_window isVisible] || [o_current_video_window alphaValue] == 0.0) {
/* We don't animate if we are not visible, instead we
* simply fade the display */
CGDisplayFadeReservationToken token;
if (blackout_other_displays) {
CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
CGDisplayFade(token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES);
}
if ([screen mainScreen])
[NSApp setPresentationOptions:(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
[[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 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) {
CGDisplayFade(token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO);
CGReleaseDisplayFadeReservation(token);
}
/* Will release the lock */
[self hasBecomeFullscreen];
return;
}
/* Make sure we don't see the o_video_view disappearing of the screen during this operation */
NSDisableScreenUpdates();
[[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 makeKeyAndOrderFront:self];
NSEnableScreenUpdates();
}
/* We are in fullscreen (and no animation is running) */
if (b_fullscreen) {
/* Make sure we are hidden */
[o_current_video_window orderOut: self];
[self unlockFullscreenAnimation];
return;
}
if (o_fullscreen_anim1) {
[o_fullscreen_anim1 stopAnimation];
[o_fullscreen_anim1 release];
}
if (o_fullscreen_anim2) {
[o_fullscreen_anim2 stopAnimation];
[o_fullscreen_anim2 release];
}
if ([screen mainScreen])
[NSApp setPresentationOptions:(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
dict1 = [[NSMutableDictionary alloc] initWithCapacity:2];
dict2 = [[NSMutableDictionary alloc] initWithCapacity:3];
[dict1 setObject:o_current_video_window forKey:NSViewAnimationTargetKey];
[dict1 setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
[dict2 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
[dict2 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
[dict2 setObject:[NSValue valueWithRect:screen_rect] forKey:NSViewAnimationEndFrameKey];
/* Strategy with NSAnimation allocation:
- Keep at most 2 animation at a time
- leaveFullscreen/enterFullscreen are the only responsible for releasing and alloc-ing
*/
o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]];
o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]];
[dict1 release];
[dict2 release];
[o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
[o_fullscreen_anim1 setDuration: 0.3];
[o_fullscreen_anim1 setFrameRate: 30];
[o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
[o_fullscreen_anim2 setDuration: 0.2];
[o_fullscreen_anim2 setFrameRate: 30];
[o_fullscreen_anim2 setDelegate: self];
[o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
[o_fullscreen_anim1 startAnimation];
/* fullscreenAnimation will be unlocked when animation ends */
}
- (void)hasBecomeFullscreen
{
if ([[o_video_view subviews] count] > 0)
[o_fullscreen_window makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
[o_fullscreen_window makeKeyWindow];
[o_fullscreen_window setAcceptsMouseMovedEvents: YES];
/* tell the fspanel to move itself to front next time it's triggered */
[o_fspanel setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]];
[o_fspanel setActive: nil];
if ([o_current_video_window isVisible])
[o_current_video_window orderOut: self];
b_fullscreen = YES;
[self unlockFullscreenAnimation];
}
- (void)leaveFullscreen
{
[self leaveFullscreenAndFadeOut: NO];
}
- (void)leaveFullscreenAndFadeOut: (BOOL)fadeout
{
NSMutableDictionary *dict1, *dict2;
NSRect frame;
BOOL blackout_other_displays = var_InheritBool(VLCIntf, "macosx-black");
if (!o_current_video_window)
return;
[self lockFullscreenAnimation];
[o_controls_bar setFullscreenState:NO];
//if (o_detached_video_window)
// [[o_detached_video_window controlsBar] setFullscreenState:NO];
/* We always try to do so */
[NSScreen unblackoutScreens];
vout_thread_t *p_vout = getVout();
if (p_vout) {
if (var_GetBool(p_vout, "video-on-top"))
[[o_video_view window] setLevel: NSStatusWindowLevel];
else
[[o_video_view window] setLevel: NSNormalWindowLevel];
vlc_object_release(p_vout);
}
[[o_video_view window] makeKeyAndOrderFront: nil];
/* Don't do anything if o_fullscreen_window is already closed */
if (!o_fullscreen_window) {
[self unlockFullscreenAnimation];
return;
}
if (fadeout) {
/* We don't animate if we are not visible, instead we
* simply fade the display */
CGDisplayFadeReservationToken token;
if (blackout_other_displays) {
CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
CGDisplayFade(token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES);
}
[o_fspanel setNonActive: nil];
[NSApp setPresentationOptions: NSApplicationPresentationDefault];
/* 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;
}
[o_current_video_window setAlphaValue: 0.0];
[o_current_video_window orderFront: self];
[[o_video_view window] orderFront: self];
[o_fspanel setNonActive: nil];
[NSApp setPresentationOptions:(NSApplicationPresentationDefault)];
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 += [o_current_video_window frame].origin.x;
frame.origin.y += [o_current_video_window frame].origin.y;
dict2 = [[NSMutableDictionary alloc] initWithCapacity:2];
[dict2 setObject:o_current_video_window forKey:NSViewAnimationTargetKey];
[dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]];
[dict2 release];
[o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
[o_fullscreen_anim2 setDuration: 0.3];
[o_fullscreen_anim2 setFrameRate: 30];
[o_fullscreen_anim2 setDelegate: self];
dict1 = [[NSMutableDictionary alloc] initWithCapacity:3];
[dict1 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
[dict1 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
[dict1 setObject:[NSValue valueWithRect:frame] forKey:NSViewAnimationEndFrameKey];
o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict1, nil]];
[dict1 release];
[o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
[o_fullscreen_anim1 setDuration: 0.2];
[o_fullscreen_anim1 setFrameRate: 30];
[o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
/* Make sure o_fullscreen_window is the frontmost window */
[o_fullscreen_window orderFront: self];
[o_fullscreen_anim1 startAnimation];
/* fullscreenAnimation will be unlocked when animation ends */
}
- (void)hasEndedFullscreen
{
b_fullscreen = NO;
/* This function is private and should be only triggered at the end of the fullscreen change animation */
/* 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 removeFromSuperviewWithoutNeedingDisplay];
[[o_temp_view superview] replaceSubview:o_temp_view with:o_video_view];
[o_video_view release];
[o_video_view setFrame:[o_temp_view frame]];
if ([[o_video_view subviews] count] > 0)
[[o_video_view window] makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
if (!b_nonembedded)
[super makeKeyAndOrderFront:self]; /* our version contains a workaround */
else
[[o_video_view window] makeKeyAndOrderFront: self];
[o_fullscreen_window orderOut: self];
NSEnableScreenUpdates();
[o_fullscreen_window release];
o_fullscreen_window = nil;
[[o_video_view window] setLevel:i_originalLevel];
[[o_video_view window] 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] && b_nonembedded)
[o_current_video_window orderOut: self];
o_current_video_window = nil;
[self unlockFullscreenAnimation];
}
- (void)animationDidEnd:(NSAnimation*)animation
{
NSArray *viewAnimations;
if (o_makekey_anim == animation) {
[o_makekey_anim release];
return;
}
if ([animation currentValue] < 1.0)
return;
/* Fullscreen ended or started (we are a delegate only for leaveFullscreen's/enterFullscren's anim2) */
viewAnimations = [o_fullscreen_anim2 viewAnimations];
if ([viewAnimations count] >=1 &&
[[[viewAnimations objectAtIndex: 0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect]) {
/* Fullscreen ended */
[self hasEndedFullscreen];
} else
/* Fullscreen started */
[self hasBecomeFullscreen];
}
- (void)makeKeyAndOrderFront: (id)sender
{
/* Hack
......
......@@ -175,13 +175,14 @@
[[self window] performZoom: sender];
else if (sender == o_fullscreen_btn) {
// set fs directly to true, as the vars can be already true in some configs
var_SetBool(pl_Get(VLCIntf), "fullscreen", true);
vout_thread_t *p_vout = getVout();
if (p_vout) {
var_SetBool(p_vout, "fullscreen", true);
vlc_object_release(p_vout);
} else { // e.g. lion fullscreen toggle
[[VLCMain sharedInstance] setFullscreen:true forWindow:nil];
}
} else
msg_Err(VLCIntf, "unknown button action sender");
......
......@@ -40,6 +40,8 @@
- (void)updateWindowsControlsBarWithSelector:(SEL)aSel;
- (void)updateWindowsUsingBlock:(void (^)(VLCVideoWindowCommon *o_window))windowUpdater;
- (void)updateWindow:(vout_window_t *)p_wnd withSelector:(SEL)aSel;
- (void)setNativeVideoSize:(NSSize)size forWindow:(vout_window_t *)p_wnd;
@end
......@@ -54,10 +54,13 @@
return;
}
if ([[VLCMainWindow sharedInstance] fullscreen] && ![[VLCMainWindow sharedInstance] nativeFullscreenMode])
[o_window leaveFullscreen];
if (![NSStringFromClass([o_window class]) isEqualToString:@"VLCMainWindow"]) {
[o_window orderOut:self];
}
[o_vout_dict removeObjectForKey:o_key];
}
......@@ -70,6 +73,17 @@
}];
}
- (void)updateWindow:(vout_window_t *)p_wnd withSelector:(SEL)aSel;
{
VLCVideoWindowCommon *o_window = [o_vout_dict objectForKey:[NSValue valueWithPointer:p_wnd]];
if(!o_window) {
msg_Err(VLCIntf, "Cannot call selector for nonexisting window");
return;
}
[o_window performSelector:aSel];
}
- (void)updateWindowsUsingBlock:(void (^)(VLCVideoWindowCommon *o_window))windowUpdater
{
[o_vout_dict enumerateKeysAndObjectsUsingBlock:^(id key, VLCVideoWindowCommon *o_window, BOOL *stop) {
......
......@@ -69,7 +69,7 @@ static const float f_min_video_height = 70.0;
* Common code for main window, detached window and extra video window
*****************************************************************************/
@interface VLCVideoWindowCommon : VLCWindow <NSWindowDelegate>
@interface VLCVideoWindowCommon : VLCWindow <NSWindowDelegate, NSAnimationDelegate>
{
NSRect previousSavedFrame;
BOOL b_dark_interface;
......@@ -80,6 +80,20 @@ static const float f_min_video_height = 70.0;
IBOutlet VLCControlsBarCommon *o_controls_bar;
NSSize nativeVideoSize;
// variables for fullscreen handling
VLCVideoWindowCommon *o_current_video_window;
VLCWindow * o_fullscreen_window;
NSViewAnimation * o_fullscreen_anim1;
NSViewAnimation * o_fullscreen_anim2;
NSViewAnimation * o_makekey_anim;
NSView * o_temp_view;
BOOL b_window_is_invisible;
NSRecursiveLock * o_animation_lock;
NSInteger i_originalLevel;
}
@property (nonatomic, assign) VLCVoutView* videoView;
......@@ -90,4 +104,8 @@ static const float f_min_video_height = 70.0;
- (void)setTitle:(NSString *)title;
/* fullscreen handling */
- (void)enterFullscreen;
- (void)leaveFullscreen;
@end
\ No newline at end of file
......@@ -25,6 +25,8 @@
#import "Windows.h"
#import "intf.h"
#import "CoreInteraction.h"
#import "ControlsBar.h"
#import "VideoView.h"
/*****************************************************************************
* VLCWindow
......@@ -245,9 +247,18 @@
[self setMovableByWindowBackground: YES];
[self setCanBecomeKeyWindow:YES];
o_temp_view = [[NSView alloc] init];
[o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
return self;
}
- (void)dealloc
{