From da461ea191f6f5d8e65e2e75277300417a09cdec Mon Sep 17 00:00:00 2001 From: Pierre d'Herbemont Date: Fri, 2 Mar 2007 18:21:44 +0000 Subject: [PATCH] Support other displays fade out. Change video-device to point to the unique screen ID. --- modules/gui/macosx/embeddedwindow.m | 13 +- modules/gui/macosx/misc.h | 38 ++++ modules/gui/macosx/misc.m | 262 ++++++++++++++++++++++++++++ modules/gui/macosx/vout.m | 61 ++----- 4 files changed, 319 insertions(+), 55 deletions(-) diff --git a/modules/gui/macosx/embeddedwindow.m b/modules/gui/macosx/embeddedwindow.m index 29cdb1de33..c466a9364e 100644 --- a/modules/gui/macosx/embeddedwindow.m +++ b/modules/gui/macosx/embeddedwindow.m @@ -138,11 +138,13 @@ vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT, FIND_ANYWHERE ); BOOL blackout_other_displays = var_GetBool( p_vout, "macosx-black" ); - /* We should get the screen pointed by var_GetInteger( p_vout, "video-device" ) */ - screen = [self screen]; + screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )]; vlc_object_release( p_vout ); + if (!screen) + screen = [self screen]; + screen_rect = [screen frame]; [o_btn_fullscreen setState: YES]; @@ -150,7 +152,7 @@ [NSCursor setHiddenUntilMouseMoves: YES]; if (blackout_other_displays) - ; /* We should do something like [screen blackoutOtherScreens]; */ + [screen blackoutOtherScreens]; /* We should do something like [screen blackoutOtherScreens]; */ /* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */ if (!o_fullscreen_window) @@ -262,7 +264,7 @@ [o_fullscreen_window setAcceptsMouseMovedEvents: TRUE]; /* tell the fspanel to move itself to front next time it's triggered */ - [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: 0 /* Get this right */]; + [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]]; [[[[VLCMain sharedInstance] getControls] getFSPanel] setActive: nil]; } @@ -274,6 +276,9 @@ [o_btn_fullscreen setState: NO]; + /* We always try to do so */ + [NSScreen unblackoutScreens]; + /* Don't do anything if o_fullscreen_window is already closed */ if (!o_fullscreen_window) return; diff --git a/modules/gui/macosx/misc.h b/modules/gui/macosx/misc.h index a6d9f651f9..9cb548e109 100644 --- a/modules/gui/macosx/misc.h +++ b/modules/gui/macosx/misc.h @@ -21,6 +21,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ +#import + +/***************************************************************************** + * NSAnimation (VLCAddition) + *****************************************************************************/ + +@interface NSAnimation (VLCAdditions) +- (void)setUserInfo: (void *)userInfo; +- (void *)userInfo; +@end + +/***************************************************************************** + * NSScreen (VLCAdditions) + * + * Missing extension to NSScreen + *****************************************************************************/ + +@interface NSScreen (VLCAdditions) + ++ (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID; +- (CGDirectDisplayID)displayID; +- (void)blackoutOtherScreens; ++ (void)unblackoutScreens; +@end + /***************************************************************************** * VLCWindow * @@ -31,9 +56,22 @@ { BOOL b_canBecomeKeyWindow; BOOL b_isset_canBecomeKeyWindow; + NSViewAnimation *animation; } - (void)setCanBecomeKeyWindow: (BOOL)canBecomeKey; + +/* animate mode is only supported in >=10.4 */ +- (void)orderFront: (id)sender animate: (BOOL)animate; + +/* animate mode is only supported in >=10.4 */ +- (void)orderOut: (id)sender animate: (BOOL)animate; + +/* animate mode is only supported in >=10.4 */ +- (void)orderOut: (id)sender animate: (BOOL)animate callback:(NSInvocation *)callback; + +/* animate mode is only supported in >=10.4 */ +- (void)closeAndAnimate: (BOOL)animate; @end diff --git a/modules/gui/macosx/misc.m b/modules/gui/macosx/misc.m index ad531fa044..b60ec2e564 100644 --- a/modules/gui/macosx/misc.m +++ b/modules/gui/macosx/misc.m @@ -28,6 +28,116 @@ #include "playlist.h" #include "controls.h" +/***************************************************************************** + * NSAnimation (VLCAdditions) + * + * Missing extension to NSAnimation + *****************************************************************************/ + +@implementation NSAnimation (VLCAdditions) +/* fake class attributes */ +static NSMapTable *VLCAdditions_userInfo = NULL; + ++ (void)load +{ + /* init our fake object attribute */ + VLCAdditions_userInfo = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 16); +} + +- (void)dealloc +{ + NSMapRemove(VLCAdditions_userInfo, self); + [super dealloc]; +} + +- (void)setUserInfo: (void *)userInfo +{ + NSMapInsert(VLCAdditions_userInfo, self, (void*)userInfo); +} + +- (void *)userInfo +{ + return NSMapGet(VLCAdditions_userInfo, self); +} +@end + +/***************************************************************************** + * NSScreen (VLCAdditions) + * + * Missing extension to NSScreen + *****************************************************************************/ + +@implementation NSScreen (VLCAdditions) + +static NSMutableArray *blackoutWindows = NULL; + ++ (void)load +{ + /* init our fake object attribute */ + blackoutWindows = [[NSMutableArray alloc] initWithCapacity:1]; +} + ++ (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID +{ + int i; + + for( i = 0; i < [[NSScreen screens] count]; i++ ) + { + NSScreen *screen = [[NSScreen screens] objectAtIndex: i]; + if([screen displayID] == displayID) + return screen; + } + return nil; +} + +- (CGDirectDisplayID)displayID +{ + return (CGDirectDisplayID)_screenNumber; +} + +- (void)blackoutOtherScreens +{ + unsigned int i; + + /* Free our previous blackout window (follow blackoutWindow alloc strategy) */ + [blackoutWindows makeObjectsPerformSelector:@selector(close)]; + [blackoutWindows removeAllObjects]; + + + for(i = 0; i < [[NSScreen screens] count]; i++) + { + VLCWindow *blackoutWindow; + NSScreen *screen = [[NSScreen screens] objectAtIndex: i]; + if(self == screen) + continue; + /* blackoutWindow alloc strategy + - The NSMutableArray blackoutWindows has the blackoutWindow references + - blackoutOtherDisplays is responsible for alloc/releasing its Windows + */ + blackoutWindow = [[VLCWindow alloc] initWithContentRect: [screen frame] styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + [blackoutWindow setBackgroundColor:[NSColor blackColor]]; + [blackoutWindow setLevel: NSFloatingWindowLevel]; /* Disappear when Expose is triggered */ + + [blackoutWindow orderFront: self animate: YES]; + + [blackoutWindows addObject: blackoutWindow]; + [blackoutWindow release]; + } +} + ++ (void)unblackoutScreens +{ + unsigned int i; + + for(i = 0; i < [blackoutWindows count]; i++) + { + VLCWindow *blackoutWindow = [blackoutWindows objectAtIndex: i]; + [blackoutWindow closeAndAnimate: YES]; + } +} + +@end + /***************************************************************************** * VLCWindow * @@ -56,6 +166,158 @@ return [super canBecomeKeyWindow]; } + +- (void)closeAndAnimate: (BOOL)animate +{ + NSInvocation *invoc; + + if (!animate || MACOS_VERSION < 10.4f) + { + [super close]; + return; + } + + invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(close)]]; + [invoc setTarget: (id)super]; + + if (![self isVisible] || [self alphaValue] == 0.0) + { + [super close]; + return; + } + + [self orderOut: self animate: YES callback: invoc]; +} + +- (void)orderOut: (id)sender animate: (BOOL)animate +{ + NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(orderOut:)]]; + [invoc setTarget: (id)super]; + [invoc setArgument: sender atIndex: 0]; + [self orderOut: sender animate: animate callback: invoc]; +} + +- (void)orderOut: (id)sender animate: (BOOL)animate callback:(NSInvocation *)callback +{ + NSViewAnimation *anim; + NSViewAnimation *current_anim; + NSMutableDictionary *dict; + + if (!animate || MACOS_VERSION < 10.4f) + { + [self orderOut: sender]; + return; + } + + dict = [[NSMutableDictionary alloc] initWithCapacity:2]; + + [dict setObject:self forKey:NSViewAnimationTargetKey]; + + [dict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey]; + anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; + [dict release]; + + [anim setAnimationBlockingMode:NSAnimationNonblocking]; + [anim setDuration:0.9]; + [anim setFrameRate:30]; + [anim setUserInfo: callback]; + + @synchronized(self) { + current_anim = self->animation; + + if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeOutEffect && [current_anim isAnimating]) + { + [anim release]; + } + else + { + if (current_anim) + { + [current_anim stopAnimation]; + [anim setCurrentProgress:1.0-[current_anim currentProgress]]; + [current_anim release]; + } + else + [anim setCurrentProgress:1.0 - [self alphaValue]]; + self->animation = anim; + [self setDelegate: self]; + [anim startAnimation]; + } + } +} + +- (void)orderFront: (id)sender animate: (BOOL)animate +{ + NSViewAnimation *anim; + NSViewAnimation *current_anim; + NSMutableDictionary *dict; + + if (!animate || MACOS_VERSION < 10.4f) + { + [super orderFront: sender]; + [self setAlphaValue: 1.0]; + return; + } + + if (![self isVisible]) + { + [self setAlphaValue: 0.0]; + [super orderFront: sender]; + } + else if ([self alphaValue] == 1.0) + { + [super orderFront: self]; + return; + } + + dict = [[NSMutableDictionary alloc] initWithCapacity:2]; + + [dict setObject:self forKey:NSViewAnimationTargetKey]; + + [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey]; + anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; + [dict release]; + + [anim setAnimationBlockingMode:NSAnimationNonblocking]; + [anim setDuration:0.5]; + [anim setFrameRate:30]; + + @synchronized(self) { + current_anim = self->animation; + + if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeInEffect && [current_anim isAnimating]) + { + [anim release]; + } + else + { + if (current_anim) + { + [current_anim stopAnimation]; + [anim setCurrentProgress:1.0 - [current_anim currentProgress]]; + [current_anim release]; + } + else + [anim setCurrentProgress:[self alphaValue]]; + self->animation = anim; + [self setDelegate: self]; + [self orderFront: sender]; + [anim startAnimation]; + } + } +} + +- (void)animationDidEnd:(NSAnimation*)anim +{ + if ([self alphaValue] <= 0.0) + { + NSInvocation * invoc; + [super orderOut: nil]; + [self setAlphaValue: 1.0]; + if ((invoc = [anim userInfo])) + [invoc invoke]; + } +} @end /***************************************************************************** diff --git a/modules/gui/macosx/vout.m b/modules/gui/macosx/vout.m index 77bbf130c1..c9671c119d 100644 --- a/modules/gui/macosx/vout.m +++ b/modules/gui/macosx/vout.m @@ -214,10 +214,10 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, (int)s_rect.size.width, (int)s_rect.size.height ); text.psz_string = psz_temp; - val2.i_int = i; + val2.i_int = (int)[o_screen displayID]; var_Change( p_real_vout, "video-device", VLC_VAR_ADDCHOICE, &val2, &text ); - if( i == i_device ) + if( (int)[o_screen displayID] == i_device ) { var_Set( p_real_vout, "video-device", val2 ); } @@ -962,20 +962,13 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, b_embedded = var_GetBool( p_vout, "macosx-embedded" ); /* Find out on which screen to open the window */ - if( i_device <= 0 || i_device > (int)[o_screens count] ) - { - /* No preference specified. Use the main screen */ + o_screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device]; + + if( !o_screen ) o_screen = [NSScreen mainScreen]; - i_device = [o_screens indexOfObject: o_screen]; - if( o_screen == [o_screens objectAtIndex: 0] ) - b_menubar_screen = VLC_TRUE; - } - else - { - i_device--; - o_screen = [o_screens objectAtIndex: i_device]; - b_menubar_screen = ( i_device == 0 ); - } + + if( o_screen == [NSScreen mainScreen] ) + b_menubar_screen = VLC_TRUE; if( p_vout->b_fullscreen ) { @@ -998,42 +991,8 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, defer: YES screen: o_screen]; if( b_black == VLC_TRUE ) - { - CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); - CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, true ); - CGReleaseDisplayFadeReservation( token ); - unsigned int i; - for( i = 0 ; i < [o_screens count]; i++) - { - struct - { - CGDirectDisplayID displayID; - CGGammaValue redMin, redMax, redGamma, - greenMin, greenMax, greenGamma, - blueMin, blueMax, blueGamma; - } dispSettings; - CGDisplayCount dspyCnt; - CGPoint gPoint; - - if( i == (unsigned int)i_device ) continue; - - screen_rect = [[o_screens objectAtIndex: i] frame]; - - gPoint.x = screen_rect.origin.x; - gPoint.y = screen_rect.origin.y; - CGGetDisplaysWithPoint( gPoint, 1, &(dispSettings.displayID), &dspyCnt); - CGGetDisplayTransferByFormula( - dispSettings.displayID, - &dispSettings.redMin, &dispSettings.redMax, &dispSettings.redGamma, - &dispSettings.greenMin, &dispSettings.greenMax, &dispSettings.greenGamma, - &dispSettings.blueMin, &dispSettings.blueMax, &dispSettings.blueGamma ); - CGSetDisplayTransferByFormula( - dispSettings.displayID, - dispSettings.redMin, 0, dispSettings.redGamma, - dispSettings.greenMin, 0, dispSettings.greenGamma, - dispSettings.blueMin, 0, dispSettings.blueGamma ); - } - } + [o_screen blackoutOtherScreens]; + if( b_menubar_screen ) { SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); -- 2.39.2