X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fembeddedwindow.m;h=03b2aa0e0751719bd448b4efb10c33446363aa02;hb=8a5d95d032dd1d3773858ece1d5efe2f970d6bab;hp=b5d4a02d065ce5a2c4a58ed316718106c9ebb6a5;hpb=6ee1e193fd896ab9a4729fde14f009d9ce629815;p=vlc diff --git a/modules/gui/macosx/embeddedwindow.m b/modules/gui/macosx/embeddedwindow.m index b5d4a02d06..03b2aa0e07 100644 --- a/modules/gui/macosx/embeddedwindow.m +++ b/modules/gui/macosx/embeddedwindow.m @@ -1,10 +1,11 @@ /***************************************************************************** * embeddedwindow.m: MacOS X interface module ***************************************************************************** - * Copyright (C) 2005-2006 the VideoLAN team + * Copyright (C) 2005-2008 the VideoLAN team * $Id$ * * Authors: Benjamin Pracht + * Felix Paul Kühne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,9 +52,12 @@ [o_slider setToolTip: _NS("Position")]; o_img_play = [NSImage imageNamed: @"play_embedded"]; - o_img_play_pressed = [NSImage imageNamed: @"play_embedded_blue"]; o_img_pause = [NSImage imageNamed: @"pause_embedded"]; - o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_blue"]; + [self controlTintChanged]; + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector( controlTintChanged ) + name: NSControlTintDidChangeNotification + object: nil]; /* Useful to save o_view frame in fullscreen mode */ o_temp_view = [[NSView alloc] init]; @@ -65,11 +69,55 @@ /* Not fullscreen when we wake up */ [o_btn_fullscreen setState: NO]; b_fullscreen = NO; - /* Use a recursive lock to be able to trigger enter/leavefullscreen - * in middle of an animation, providing that the enter/leave functions - * are called from the same thread */ - o_animation_lock = [[NSRecursiveLock alloc] init]; - b_animation_lock_alreadylocked = NO; + + [self setMovableByWindowBackground:YES]; + + [self setDelegate:self]; + + /* Make sure setVisible: returns NO */ + [self orderOut:self]; + b_window_is_invisible = YES; + videoRatio = NSMakeSize( 0., 0. ); +} + +- (void)controlTintChanged +{ + BOOL b_playing = NO; + if( [o_btn_play alternateImage] == o_img_play_pressed ) + b_playing = YES; + + if( [NSColor currentControlTint] == NSGraphiteControlTint ) + { + o_img_play_pressed = [NSImage imageNamed: @"play_embedded_graphite"]; + o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_graphite"]; + [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_graphite"]]; + [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_graphite"]]; + [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]]; + } + else + { + o_img_play_pressed = [NSImage imageNamed: @"play_embedded_blue"]; + o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_blue"]; + [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_blue"]]; + [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_blue"]]; + [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]]; + } + + if( b_playing ) + [o_btn_play setAlternateImage: o_img_play_pressed]; + else + [o_btn_play setAlternateImage: o_img_pause_pressed]; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver: self]; + [o_img_play release]; + [o_img_play_pressed release]; + [o_img_pause release]; + [o_img_pause_pressed release]; + + [super dealloc]; } - (void)setTime:(NSString *)o_arg_time position:(float)f_position @@ -124,6 +172,25 @@ return o_view; } +- (void)setVideoRatio:(NSSize)ratio +{ + videoRatio = ratio; +} + +- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize +{ + if( videoRatio.height == 0. || videoRatio.width == 0. ) + return proposedFrameSize; + + NSRect viewRect = [o_view convertRect:[o_view bounds] toView: nil]; + NSRect contentRect = [self contentRectForFrameRect:[self frame]]; + float marginy = viewRect.origin.y + [self frame].size.height - contentRect.size.height; + float marginx = contentRect.size.width - viewRect.size.width; + proposedFrameSize.height = (proposedFrameSize.width - marginx) * videoRatio.height / videoRatio.width + marginy; + + return proposedFrameSize; +} + /***************************************************************************** * Fullscreen support */ @@ -150,16 +217,24 @@ NSRect screen_rect; NSRect rect; vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT, FIND_ANYWHERE ); - BOOL blackout_other_displays = var_GetBool( p_vout, "macosx-black" ); + BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" ); - screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )]; - - vlc_object_release( p_vout ); + screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )]; [self lockFullscreenAnimation]; if (!screen) + { + msg_Dbg( p_vout, "chosen screen isn't present, using current screen for fullscreen mode" ); screen = [self screen]; + } + if (!screen) + { + msg_Dbg( p_vout, "Using deepest screen" ); + screen = [NSScreen deepestScreen]; + } + + vlc_object_release( p_vout ); screen_rect = [screen frame]; @@ -167,8 +242,12 @@ [NSCursor setHiddenUntilMouseMoves: YES]; - if (blackout_other_displays) - [screen blackoutOtherScreens]; /* We should do something like [screen blackoutOtherScreens]; */ + if( blackout_other_displays ) + [screen blackoutOtherScreens]; + + /* Make sure we don't see the window flashes in float-on-top mode */ + originalLevel = [self level]; + [self setLevel:NSNormalWindowLevel]; /* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */ if (!o_fullscreen_window) @@ -189,10 +268,8 @@ * simply fade the display */ CGDisplayFadeReservationToken token; - [o_fullscreen_window setFrame:screen_rect display:NO]; - CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); - CGDisplayFade( token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES ); + CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES ); if ([screen isMainScreen]) SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); @@ -200,10 +277,15 @@ [[self contentView] replaceSubview:o_view with:o_temp_view]; [o_temp_view setFrame:[o_view frame]]; [o_fullscreen_window setContentView:o_view]; + + [o_fullscreen_window makeKeyAndOrderFront:self]; + [o_fullscreen_window makeKeyAndOrderFront:self]; - [self orderOut: self]; + [o_fullscreen_window orderFront:self animate:YES]; - CGDisplayFade( token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO ); + [o_fullscreen_window setFrame:screen_rect display:YES]; + + CGDisplayFade( token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO ); CGReleaseDisplayFadeReservation( token); /* Will release the lock */ @@ -225,7 +307,6 @@ { /* We were already fullscreen nothing to do when NSAnimation * is not supported */ - b_animation_lock_alreadylocked = NO; [self unlockFullscreenAnimation]; return; } @@ -235,7 +316,6 @@ { /* Make sure we are hidden */ [super orderOut: self]; - b_animation_lock_alreadylocked = NO; [self unlockFullscreenAnimation]; return; } @@ -251,13 +331,6 @@ [o_fullscreen_anim2 release]; } - /* This is a recursive lock. If we are already in the middle of an animation we - * unlock it. We don't add an extra locking here, because enter/leavefullscreen - * are executed always in the same thread */ - if (b_animation_lock_alreadylocked) - [self unlockFullscreenAnimation]; - b_animation_lock_alreadylocked = YES; - if ([screen isMainScreen]) SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); @@ -304,10 +377,12 @@ /* tell the fspanel to move itself to front next time it's triggered */ [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]]; - - [super orderOut: self]; + + if([self isVisible]) + [super orderOut: self]; [[[[VLCMain sharedInstance] getControls] getFSPanel] setActive: nil]; + b_fullscreen = YES; [self unlockFullscreenAnimation]; } @@ -333,7 +408,6 @@ /* Don't do anything if o_fullscreen_window is already closed */ if (!o_fullscreen_window) { - b_animation_lock_alreadylocked = NO; [self unlockFullscreenAnimation]; return; } @@ -354,6 +428,10 @@ /* 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; + CGDisplayFade( token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO ); CGReleaseDisplayFadeReservation( token); return; @@ -376,13 +454,6 @@ [o_fullscreen_anim2 release]; } - /* This is a recursive lock. If we are already in the middle of an animation we - * unlock it. We don't add an extra locking here, because enter/leavefullscreen - * are executed always in the same thread */ - if (b_animation_lock_alreadylocked) - [self unlockFullscreenAnimation]; - b_animation_lock_alreadylocked = YES; - 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; @@ -433,13 +504,14 @@ [o_view setFrame:[o_temp_view frame]]; [self makeFirstResponder: o_view]; if ([self isVisible]) - [self makeKeyAndOrderFront:self]; + [super makeKeyAndOrderFront:self]; /* our version contains a workaround */ [o_fullscreen_window orderOut: self]; EnableScreenUpdates(); [o_fullscreen_window release]; o_fullscreen_window = nil; - b_animation_lock_alreadylocked = NO; + [self setLevel:originalLevel]; + [self unlockFullscreenAnimation]; } @@ -468,10 +540,46 @@ - (void)orderOut: (id)sender { [super orderOut: sender]; + /* Make sure we leave fullscreen */ [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] autorelease]; + [dict setObject:self forKey:NSViewAnimationTargetKey]; + [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey]; + + NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]]; + + [anim setAnimationBlockingMode: NSAnimationNonblocking]; + [anim setDuration: 0.1]; + [anim setFrameRate: 30]; + + [anim startAnimation]; + b_window_is_invisible = NO; + + /* fullscreenAnimation will be unlocked when animation ends */ +} + + + /* Make sure setFrame gets executed on main thread especially if we are animating. * (Thus we won't block the video output thread) */ - (void)setFrame:(NSRect)frame display:(BOOL)display animate:(BOOL)animate @@ -493,6 +601,24 @@ { struct args { NSRect frame; BOOL display; BOOL animate; } * args = (struct args*)[packedargs bytes]; - [super setFrame: args->frame display: args->display animate:args->animate]; + if( args->animate ) + { + /* Make sure we don't block too long and set up a non blocking animation */ + NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys: + self, NSViewAnimationTargetKey, + [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey, + [NSValue valueWithRect:args->frame], NSViewAnimationEndFrameKey, nil]; + + NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; + + [anim setAnimationBlockingMode: NSAnimationNonblocking]; + [anim setDuration: 0.4]; + [anim setFrameRate: 30]; + [anim startAnimation]; + } + else { + [super setFrame:args->frame display:args->display animate:args->animate]; + } + } @end