/*****************************************************************************
* Windows.m: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2012 VLC authors and VideoLAN
+ * Copyright (C) 2012-2013 VLC authors and VideoLAN
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
return;
}
- invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(close)]];
+ // TODO this callback stuff does not work and is not needed
+ invoc = [[[NSInvocation alloc] init] autorelease];
+ [invoc setSelector:@selector(close)];
[invoc setTarget: self];
if (![self isVisible] || [self alphaValue] == 0.0) {
- (void)orderOut: (id)sender animate: (BOOL)animate
{
- NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(orderOut:)]];
+ NSInvocation *invoc = [[[NSInvocation alloc] init] autorelease];
+ [invoc setSelector:@selector(orderOut:)];
[invoc setTarget: self];
- [invoc setArgument: sender atIndex: 0];
+ [invoc setArgument: sender atIndex: 2];
[self orderOut: sender animate: animate callback: invoc];
}
[dict setObject:self forKey:NSViewAnimationTargetKey];
[dict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
- anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
+ anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
[dict release];
[anim setAnimationBlockingMode:NSAnimationNonblocking];
[anim setDuration:0.9];
[anim setFrameRate:30];
- [anim setUserInfo: callback];
+ [anim setUserInfo:callback];
+ [anim setDelegate:self];
@synchronized(self) {
current_anim = self->o_current_animation;
[dict setObject:self forKey:NSViewAnimationTargetKey];
[dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
- anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
+ anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
[dict release];
[anim setAnimationBlockingMode:NSAnimationNonblocking];
[anim setDuration:0.5];
[anim setFrameRate:30];
+ [anim setDelegate:self];
@synchronized(self) {
current_anim = self->o_current_animation;
NSInvocation * invoc;
[super orderOut: nil];
[self setAlphaValue: 1.0];
- if ((invoc = [anim userInfo]))
+ if ((invoc = [anim userInfo])) {
[invoc invoke];
+ }
}
}
@synthesize videoView=o_video_view;
@synthesize controlsBar=o_controls_bar;
+@synthesize enteringFullscreenTransition=b_entering_fullscreen_transition;
#pragma mark -
#pragma mark Init
if (!([self styleMask] & NSTitledWindowMask)) {
[[NSNotificationCenter defaultCenter] postNotificationName:NSWindowWillCloseNotification object:self];
- [self orderOut: sender];
+ [self close];
} else
[super performClose: sender];
}
if (var_InheritBool(VLCIntf, "video-wallpaper") || [self level] < NSNormalWindowLevel)
return;
- [self setLevel: i_state];
-
+ if (!b_fullscreen && !b_entering_fullscreen_transition)
+ [self setLevel: i_state];
+ else {
+ // only save it for restore
+ i_originalLevel = i_state;
+ }
}
- (NSRect)getWindowRectForProposedVideoViewSize:(NSSize)size
return proposedFrameSize;
// needed when entering lion fullscreen mode
- if ([self fullscreen])
+ if (b_entering_fullscreen_transition || [self fullscreen])
return proposedFrameSize;
if ([[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]) {
}
+#pragma mark -
+#pragma mark Mouse cursor handling
+
+// NSTimer selectors require this function signature as per Apple's docs
+- (void)hideMouseCursor:(NSTimer *)timer
+{
+ [NSCursor setHiddenUntilMouseMoves: YES];
+}
+
+- (void)recreateHideMouseTimer
+{
+ if (t_hide_mouse_timer != nil) {
+ [t_hide_mouse_timer invalidate];
+ [t_hide_mouse_timer release];
+ }
+
+ t_hide_mouse_timer = [NSTimer scheduledTimerWithTimeInterval:2
+ target:self
+ selector:@selector(hideMouseCursor:)
+ userInfo:nil
+ repeats:NO];
+ [t_hide_mouse_timer retain];
+}
+
+// Called automatically if window's acceptsMouseMovedEvents property is true
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ if (b_fullscreen)
+ [self recreateHideMouseTimer];
+
+ [super mouseMoved: theEvent];
+}
+
#pragma mark -
#pragma mark Lion native fullscreen handling
[[[VLCMainWindow sharedInstance] fsPanel] setNonActive:nil];
}
+- (void)resignKeyWindow
+{
+ [super resignKeyWindow];
+
+ [[[VLCMainWindow sharedInstance] fsPanel] setNonActive:nil];
+}
+
- (void)windowWillEnterFullScreen:(NSNotification *)notification
{
// workaround, see #6668
[NSApp setPresentationOptions:(NSApplicationPresentationFullScreen | NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
- [self setFullscreen: YES];
+ i_originalLevel = [self level];
+ // b_fullscreen and b_entering_fullscreen_transition must not be true yet
+ [[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: NSNormalWindowLevel];
+ [self setLevel:NSNormalWindowLevel];
+
+ b_entering_fullscreen_transition = YES;
var_SetBool(pl_Get(VLCIntf), "fullscreen", true);
}
}
- [o_video_view setFrame: [[self contentView] frame]];
-
- [[VLCMainWindow sharedInstance] recreateHideMouseTimer];
- i_originalLevel = [self level];
- [[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: NSNormalWindowLevel];
- [self setLevel:NSNormalWindowLevel];
+ if ([self hasActiveVideo])
+ [[VLCMainWindow sharedInstance] recreateHideMouseTimer];
if (b_dark_interface) {
[o_titlebar_view removeFromSuperviewWithoutNeedingDisplay];
[self setFrame: winrect display:NO animate:NO];
}
- // TODO fix bottom bar status when vout just not visible, but there
- if (![o_video_view isHidden])
+ [o_video_view setFrame: [[self contentView] frame]];
+ if (![o_video_view isHidden]) {
[[o_controls_bar bottomBarView] setHidden: YES];
+ }
+
[self setMovableByWindowBackground: NO];
}
// But this creates some problems when leaving fs over remote intfs, so activate app here.
[NSApp activateIgnoringOtherApps:YES];
+ [self setFullscreen: YES];
+ b_entering_fullscreen_transition = NO;
+
if ([self hasActiveVideo]) {
[[[VLCMainWindow sharedInstance] fsPanel] setVoutWasUpdated: self];
- [[[VLCMainWindow sharedInstance] fsPanel] setActive: nil];
+ if (![o_video_view isHidden])
+ [[[VLCMainWindow sharedInstance] fsPanel] setActive: nil];
}
NSArray *subviews = [[self videoView] subviews];
[NSCursor setHiddenUntilMouseMoves: NO];
[[[VLCMainWindow sharedInstance] fsPanel] setNonActive: nil];
-
- [[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: i_originalLevel];
- [self setLevel:i_originalLevel];
+
if (b_dark_interface) {
NSRect winrect;
CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;
- winrect = [self frame];
+ winrect = [o_video_view frame];
+ winrect.size.height -= f_titleBarHeight;
+ [o_video_view setFrame: winrect];
+
+ winrect = [self frame];
[o_titlebar_view setFrame: NSMakeRect(0, winrect.size.height - f_titleBarHeight,
winrect.size.width, f_titleBarHeight)];
[[self contentView] addSubview: o_titlebar_view];
winrect.size.height = winrect.size.height + f_titleBarHeight;
[self setFrame: winrect display:NO animate:NO];
- winrect = [o_video_view frame];
- winrect.size.height -= f_titleBarHeight;
- [o_video_view setFrame: winrect];
}
NSRect videoViewFrame = [o_video_view frame];
- videoViewFrame.origin.y = [[o_controls_bar bottomBarView] frame].size.height;
- videoViewFrame.size.height -= [[o_controls_bar bottomBarView] frame].size.height;
+ videoViewFrame.origin.y += [o_controls_bar height];
+ videoViewFrame.size.height -= [o_controls_bar height];
[o_video_view setFrame: videoViewFrame];
- [[o_controls_bar bottomBarView] setHidden: NO];
-
- [self setMovableByWindowBackground: YES];
-}
-#pragma mark -
-#pragma mark Fullscreen Logic
+ if (![o_video_view isHidden]) {
+ [[o_controls_bar bottomBarView] setHidden: NO];
+ }
-- (void)lockFullscreenAnimation
-{
- [o_animation_lock lock];
+ [self setMovableByWindowBackground: YES];
}
-- (void)unlockFullscreenAnimation
+- (void)windowDidExitFullScreen:(NSNotification *)notification
{
- [o_animation_lock unlock];
+ [[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: i_originalLevel];
+ [self setLevel:i_originalLevel];
}
+#pragma mark -
+#pragma mark Fullscreen Logic
+
- (void)enterFullscreen
{
NSMutableDictionary *dict1, *dict2;
BOOL blackout_other_displays = var_InheritBool(VLCIntf, "macosx-black");
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");
/* Make sure we don't see the window flashes in float-on-top mode */
i_originalLevel = [self level];
+ // b_fullscreen must not be true yet
[[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: NSNormalWindowLevel];
[self 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 */
CGDisplayFade(token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES);
}
- NSApplicationPresentationOptions presentationOpts = [NSApp presentationOptions];
- if ([screen hasMenuBar])
- presentationOpts |= NSApplicationPresentationAutoHideMenuBar;
- if ([screen hasMenuBar] || [screen hasDock])
- presentationOpts |= NSApplicationPresentationAutoHideDock;
- [NSApp setPresentationOptions:presentationOpts];
+ [screen setFullscreenPresentationOptions];
+ [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_video_view release];
[o_fullscreen_window makeKeyAndOrderFront:self];
[o_fullscreen_window orderFront:self animate:YES];
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_video_view release];
[o_fullscreen_window makeKeyAndOrderFront:self];
NSEnableScreenUpdates();
}
/* Make sure we are hidden */
[self orderOut: self];
- [self unlockFullscreenAnimation];
return;
}
[o_fullscreen_anim2 release];
}
- NSApplicationPresentationOptions presentationOpts = [NSApp presentationOptions];
- if ([screen hasMenuBar])
- presentationOpts |= NSApplicationPresentationAutoHideMenuBar;
- if ([screen hasMenuBar] || [screen hasDock])
- presentationOpts |= NSApplicationPresentationAutoHideDock;
- [NSApp setPresentationOptions:presentationOpts];
+ [screen setFullscreenPresentationOptions];
dict1 = [[NSMutableDictionary alloc] initWithCapacity:2];
dict2 = [[NSMutableDictionary alloc] initWithCapacity:3];
[o_fullscreen_anim1 startAnimation];
/* fullscreenAnimation will be unlocked when animation ends */
+
+ b_entering_fullscreen_transition = YES;
}
- (void)hasBecomeFullscreen
if ([self isVisible])
[self orderOut: self];
+ b_entering_fullscreen_transition = NO;
[self setFullscreen:YES];
- [self unlockFullscreenAnimation];
}
- (void)leaveFullscreen
NSRect frame;
BOOL blackout_other_displays = var_InheritBool(VLCIntf, "macosx-black");
- [self lockFullscreenAnimation];
-
if (o_controls_bar)
[o_controls_bar setFullscreenState:NO];
[[[VLCMainWindow sharedInstance] controlsBar] setFullscreenState:NO];
/* Don't do anything if o_fullscreen_window is already closed */
if (!o_fullscreen_window) {
- [self unlockFullscreenAnimation];
return;
}
}
[[[VLCMainWindow sharedInstance] fsPanel] setNonActive: nil];
- [NSApp setPresentationOptions: NSApplicationPresentationDefault];
+ [[o_fullscreen_window screen] setNonFullscreenPresentationOptions];
/* Will release the lock */
[self hasEndedFullscreen];
[[o_video_view window] orderFront: self];
[[[VLCMainWindow sharedInstance] fsPanel] setNonActive: nil];
- [NSApp setPresentationOptions:(NSApplicationPresentationDefault)];
+ [[o_fullscreen_window screen] setNonFullscreenPresentationOptions];
if (o_fullscreen_anim1) {
[o_fullscreen_anim1 stopAnimation];
[dict2 setObject:self forKey:NSViewAnimationTargetKey];
[dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
- o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]];
+ o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]];
[dict2 release];
[o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
[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]];
+ o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]];
[dict1 release];
[o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
if ([[o_video_view subviews] count] > 0)
[self makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
+ [o_video_view setHidden: b_video_view_was_hidden];
+
[super makeKeyAndOrderFront:self]; /* our version (in main window) contains a workaround */
[o_fullscreen_window orderOut: self];
[o_fullscreen_window release];
o_fullscreen_window = nil;
-
+
[[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: i_originalLevel];
[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];
-
- [self unlockFullscreenAnimation];
}
- (void)animationDidEnd:(NSAnimation*)animation
/* 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]) {
+ [[[viewAnimations objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect]) {
/* Fullscreen ended */
[self hasEndedFullscreen];
} else
[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
static NSMutableArray *attributes = nil;
if (attributes == nil) {
attributes = [[super accessibilityAttributeNames] mutableCopy];
- NSArray *appendAttributes = [NSArray arrayWithObjects: NSAccessibilitySubroleAttribute,
+ NSArray *appendAttributes = [NSArray arrayWithObjects:NSAccessibilitySubroleAttribute,
NSAccessibilityCloseButtonAttribute,
NSAccessibilityMinimizeButtonAttribute,
- NSAccessibilityZoomButtonAttribute,
- nil];
+ NSAccessibilityZoomButtonAttribute, nil];
for(NSString *attribute in appendAttributes) {
if (![attributes containsObject:attribute])