Support other displays fade out. Change video-device to point to the unique screen ID.
authorPierre d'Herbemont <pdherbemont@videolan.org>
Fri, 2 Mar 2007 18:21:44 +0000 (18:21 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Fri, 2 Mar 2007 18:21:44 +0000 (18:21 +0000)
modules/gui/macosx/embeddedwindow.m
modules/gui/macosx/misc.h
modules/gui/macosx/misc.m
modules/gui/macosx/vout.m

index 29cdb1d..c466a93 100644 (file)
     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];
     [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)
     [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];
 }
     
     [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;
index a6d9f65..9cb548e 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
+#import <ApplicationServices/ApplicationServices.h>
+
+/*****************************************************************************
+ * 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
  *
 {
     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
 
 
index ad531fa..b60ec2e 100644 (file)
 #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
  *
 
     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
 
 /*****************************************************************************
index 77bbf13..c9671c1 100644 (file)
@@ -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);