]> git.sesse.net Git - vlc/blobdiff - modules/gui/macosx/MainWindow.m
macosx: resolve conflict between sidebar icons and other UI artwork (refs #5742)
[vlc] / modules / gui / macosx / MainWindow.m
index 6a8fde13f916ee295812bee2e3cb5abc839ed2f4..baaf6940c325f98f6841f7942f5d37e091f1c7e1 100644 (file)
@@ -33,6 +33,7 @@
 #import "open.h"
 #import "controls.h" // TODO: remove me
 #import "SideBarItem.h"
+#import "MainWindowTitle.h"
 #import <vlc_playlist.h>
 #import <vlc_aout_intf.h>
 #import <vlc_url.h>
@@ -69,9 +70,19 @@ static VLCMainWindow *_o_sharedInstance = nil;
 - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
                   backing:(NSBackingStoreType)backingType defer:(BOOL)flag
 {
-//     styleMask ^= NSTexturedBackgroundWindowMask;
+    b_dark_interface = config_GetInt( VLCIntf, "macosx-interfacestyle" );
+
+    if (b_dark_interface)
+    {
+#ifdef MAC_OS_X_VERSION_10_7
+        styleMask = NSBorderlessWindowMask | NSResizableWindowMask;
+        [o_resize_view removeFromSuperviewWithoutNeedingDisplay];
+#else
+        styleMask = NSBorderlessWindowMask;
+#endif
+    }
 
-    self = [super initWithContentRect:contentRect styleMask:styleMask //& ~NSTitledWindowMask
+    self = [super initWithContentRect:contentRect styleMask:styleMask
                               backing:backingType defer:flag];
 
     [[VLCMain sharedInstance] updateTogglePlaylistState];
@@ -98,7 +109,9 @@ static VLCMainWindow *_o_sharedInstance = nil;
 
 - (void)dealloc
 {
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
     config_PutInt( VLCIntf->p_libvlc, "volume", i_lastShownVolume );
+    [self saveFrameUsingName: [self frameAutosaveName]];
     [o_sidebaritems release];
     [super dealloc];
 }
@@ -106,7 +119,6 @@ static VLCMainWindow *_o_sharedInstance = nil;
 - (void)awakeFromNib
 {
     /* setup the styled interface */
-    b_dark_interface = config_GetInt( VLCIntf, "macosx-interfacestyle" );
     b_nativeFullscreenMode = config_GetInt( VLCIntf, "macosx-nativefullscreenmode" );
     i_lastShownVolume = -1;
 
@@ -173,7 +185,6 @@ static VLCMainWindow *_o_sharedInstance = nil;
     }
     else
     {
-        /* TODO: we also need to change the window style here... */
         [o_bottombar_view setImage: [NSImage imageNamed:@"bottom-background_dark"]];
         [o_bwd_btn setImage: [NSImage imageNamed:@"back_dark"]];
         [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed_dark"]];
@@ -228,11 +239,14 @@ static VLCMainWindow *_o_sharedInstance = nil;
     /* interface builder action */
     [self setDelegate: self];
     [self setExcludedFromWindowsMenu: YES];
+    [self setAcceptsMouseMovedEvents: YES];
     // Set that here as IB seems to be buggy
-    [self setContentMinSize:NSMakeSize(500., 288.)];
+    if (b_dark_interface)
+        [self setContentMinSize:NSMakeSize(500., (288. + [o_titlebar_view frame].size.height))];
+    else
+        [self setContentMinSize:NSMakeSize(500., 288.)];
     [self setTitle: _NS("VLC media player")];
     [o_playlist_btn setEnabled:NO];
-    [o_video_view setFrame: [o_split_view frame]];
     o_temp_view = [[NSView alloc] init];
     [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
     [o_dropzone_view setFrame: [o_playlist_table frame]];
@@ -270,12 +284,24 @@ static VLCMainWindow *_o_sharedInstance = nil;
 
         [o_fullscreen_btn removeFromSuperviewWithoutNeedingDisplay];
     }
+    else
+        [o_titlebar_view setFullscreenButtonHidden: YES];
+
+    if (OSX_LION)
+    {
+        /* the default small size of the search field is slightly different on Lion, let's work-around that */
+        NSRect frame;
+        frame = [o_search_fld frame];
+        frame.origin.y = frame.origin.y + 2.0;
+        frame.size.height = frame.size.height - 1.0;
+        [o_search_fld setFrame: frame];
+    }
 
     /* create the sidebar */
     o_sidebaritems = [[NSMutableArray alloc] init];
     SideBarItem *libraryItem = [SideBarItem itemWithTitle:_NS("LIBRARY") identifier:@"library"];
     SideBarItem *playlistItem = [SideBarItem itemWithTitle:_NS("Playlist") identifier:@"playlist"];
-    [playlistItem setIcon: [NSImage imageNamed:@"document-music-playlist"]];
+    [playlistItem setIcon: [NSImage imageNamed:@"sidebar-playlist"]];
     SideBarItem *mycompItem = [SideBarItem itemWithTitle:_NS("MY COMPUTER") identifier:@"mycomputer"];
     SideBarItem *devicesItem = [SideBarItem itemWithTitle:_NS("DEVICES") identifier:@"devices"];
     SideBarItem *lanItem = [SideBarItem itemWithTitle:_NS("LOCAL NETWORK") identifier:@"localnetwork"];
@@ -303,7 +329,7 @@ static VLCMainWindow *_o_sharedInstance = nil;
                 {
                     [internetItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
                     if (!strncmp( *ppsz_name, "podcast", 7 ))
-                        [[internetItems lastObject] setIcon: [NSImage imageNamed:@"film-cast"]];
+                        [[internetItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-podcast"]];
                     else
                         [[internetItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
                 }
@@ -317,18 +343,18 @@ static VLCMainWindow *_o_sharedInstance = nil;
             case SD_CAT_LAN:
                 {
                     [lanItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
-                    [[lanItems lastObject] setIcon: [NSImage imageNamed:@"network-cloud"]];
+                    [[lanItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-local"]];
                 }
                 break;
             case SD_CAT_MYCOMPUTER:
                 {
                     [mycompItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
                     if (!strncmp( *ppsz_name, "video_dir", 9 ))
-                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"film"]];
+                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-movie"]];
                     else if (!strncmp( *ppsz_name, "audio_dir", 9 ))
-                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"music-beam"]];
+                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-music"]];
                     else if (!strncmp( *ppsz_name, "picture_dir", 11 ))
-                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"picture"]];
+                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-pictures"]];
                     else
                         [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
                 }
@@ -366,6 +392,32 @@ static VLCMainWindow *_o_sharedInstance = nil;
 
     [o_sidebar_view reloadData];
     [o_sidebar_view selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:YES];
+
+    if( b_dark_interface )
+    {
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidResizeNotification object: nil];
+        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidMoveNotification object: nil];
+
+        NSRect winrect;
+        CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;
+        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_split_view frame];
+        winrect.size.height = winrect.size.height - f_titleBarHeight;
+        [o_split_view setFrame: winrect];
+        [o_video_view setFrame: winrect];
+        previousSavedFrame = winrect;
+
+        [self display];
+    }
+    else
+        [o_video_view setFrame: [o_split_view frame]];
 }
 
 #pragma mark -
@@ -620,6 +672,140 @@ static VLCMainWindow *_o_sharedInstance = nil;
     [[[VLCMain sharedInstance] open] openFileGeneric];
 }
 
+#pragma mark -
+#pragma mark overwritten default functionality
+- (BOOL)canBecomeKeyWindow
+{
+    return YES;
+}
+
+- (void)setTitle:(NSString *)title
+{
+    if (b_dark_interface)
+        [o_titlebar_view setWindowTitle: title];
+    [super setTitle: title];
+}
+
+- (void)performZoom:(id)sender
+{
+    if (b_dark_interface)
+        [self customZoom: sender];
+    else
+        [super performZoom: sender];
+}
+
+- (void)zoom:(id)sender
+{
+    if (b_dark_interface)
+        [self customZoom: sender];
+    else
+        [super zoom: sender];
+}
+
+/**
+ * Given a proposed frame rectangle, return a modified version
+ * which will fit inside the screen.
+ *
+ * This method is based upon NSWindow.m, part of the GNUstep GUI Library, licensed under LGPLv2+.
+ *    Authors:  Scott Christley <scottc@net-community.com>, Venkat Ajjanagadde <venkat@ocbi.com>,   
+ *              Felipe A. Rodriguez <far@ix.netcom.com>, Richard Frith-Macdonald <richard@brainstorm.co.uk>
+ *    Copyright (C) 1996 Free Software Foundation, Inc.
+ */
+- (NSRect) customConstrainFrameRect: (NSRect)frameRect toScreen: (NSScreen*)screen
+{
+    NSRect screenRect = [screen visibleFrame];
+    float difference;
+
+    /* Move top edge of the window inside the screen */
+    difference = NSMaxY (frameRect) - NSMaxY (screenRect);
+    if (difference > 0)
+    {
+        frameRect.origin.y -= difference;
+    }
+
+    /* If the window is resizable, resize it (if needed) so that the
+     bottom edge is on the screen or can be on the screen when the user moves
+     the window */
+    difference = NSMaxY (screenRect) - NSMaxY (frameRect);
+    if (_styleMask & NSResizableWindowMask)
+    {
+        float difference2;
+
+        difference2 = screenRect.origin.y - frameRect.origin.y;
+        difference2 -= difference;
+        // Take in account the space between the top of window and the top of the 
+        // screen which can be used to move the bottom of the window on the screen
+        if (difference2 > 0)
+        {
+            frameRect.size.height -= difference2;
+            frameRect.origin.y += difference2;
+        }
+
+        /* Ensure that resizing doesn't makewindow smaller than minimum */
+        difference2 = [self minSize].height - frameRect.size.height;
+        if (difference2 > 0)
+        {
+            frameRect.size.height += difference2;
+            frameRect.origin.y -= difference2;
+        }
+    }
+
+    return frameRect;
+}
+
+#define DIST 3
+
+/**
+ Zooms the receiver.   This method calls the delegate method
+ windowShouldZoom:toFrame: to determine if the window should
+ be allowed to zoom to full screen.
+ *
+ * This method is based upon NSWindow.m, part of the GNUstep GUI Library, licensed under LGPLv2+.
+ *    Authors:  Scott Christley <scottc@net-community.com>, Venkat Ajjanagadde <venkat@ocbi.com>,   
+ *              Felipe A. Rodriguez <far@ix.netcom.com>, Richard Frith-Macdonald <richard@brainstorm.co.uk>
+ *    Copyright (C) 1996 Free Software Foundation, Inc.
+ */
+- (void) customZoom: (id)sender
+{
+    NSRect maxRect = [[self screen] visibleFrame];
+    NSRect currentFrame = [self frame];
+
+    if ([[self delegate] respondsToSelector: @selector(windowWillUseStandardFrame:defaultFrame:)])
+    {
+        maxRect = [[self delegate] windowWillUseStandardFrame: self defaultFrame: maxRect];
+    }
+
+    maxRect = [self customConstrainFrameRect: maxRect toScreen: [self screen]];
+
+    // Compare the new frame with the current one
+    if ((abs(NSMaxX(maxRect) - NSMaxX(currentFrame)) < DIST)
+        && (abs(NSMaxY(maxRect) - NSMaxY(currentFrame)) < DIST)
+        && (abs(NSMinX(maxRect) - NSMinX(currentFrame)) < DIST)
+        && (abs(NSMinY(maxRect) - NSMinY(currentFrame)) < DIST))
+    {
+        // Already in zoomed mode, reset user frame, if stored
+        if ([self frameAutosaveName] != nil)
+        {
+            [self setFrame: previousSavedFrame display: YES animate: YES];
+            [self saveFrameUsingName: [self frameAutosaveName]];
+        }
+        return;
+    }
+
+    if ([self frameAutosaveName] != nil)
+    {
+        [self saveFrameUsingName: [self frameAutosaveName]];
+        previousSavedFrame = [self frame];
+    }
+
+    [self setFrame: maxRect display: YES animate: YES];
+}
+
+- (void)windowResizedOrMoved:(NSNotification *)notification
+{
+    [self saveFrameUsingName: [self frameAutosaveName]];
+}
+
 #pragma mark -
 #pragma mark Update interface and respond to foreign events
 - (void)showDropZone
@@ -778,6 +964,9 @@ static VLCMainWindow *_o_sharedInstance = nil;
 
         /* chapters & titles */
         //FIXME! b_chapters = p_input->stream.i_area_nb > 1;
+
+        if (cachedInputState == PLAYING_S || b_buffering == YES)
+            [self makeKeyAndOrderFront: nil];
         vlc_object_release( p_input );
     }
 
@@ -912,10 +1101,8 @@ static VLCMainWindow *_o_sharedInstance = nil;
             [o_bottombar_view setHidden: b_videoPlayback];
         else
             [o_bottombar_view setHidden: NO];
-    }
-    else
-    {
-        [o_fullscreen_btn setEnabled: b_videoPlayback];
+        if (!b_videoPlayback)
+            [o_fspanel setNonActive: nil];
     }
 }
 
@@ -932,7 +1119,10 @@ static VLCMainWindow *_o_sharedInstance = nil;
 
         /* Calculate the window's new size */
         new_frame.size.width = [self frame].size.width - [o_video_view frame].size.width + nativeVideoSize.width;
-        new_frame.size.height = [self frame].size.height - [o_video_view frame].size.height + nativeVideoSize.height;
+        if (b_dark_interface)
+            new_frame.size.height = [self frame].size.height - [o_video_view frame].size.height + nativeVideoSize.height + [o_titlebar_view frame].size.height;
+        else
+            new_frame.size.height = [self frame].size.height - [o_video_view frame].size.height + nativeVideoSize.height;
 
         new_frame.origin.x = topleftscreen.x;
         new_frame.origin.y = topleftscreen.y - new_frame.size.height;
@@ -954,7 +1144,7 @@ static VLCMainWindow *_o_sharedInstance = nil;
 #pragma mark Fullscreen support
 - (void)showFullscreenController
 {
-    if (b_fullscreen)
+     if (b_fullscreen && [[VLCMain sharedInstance] activeVideoPlayback] )
         [o_fspanel fadeIn];
 }
 
@@ -1176,7 +1366,8 @@ static VLCMainWindow *_o_sharedInstance = nil;
     [o_fullscreen_btn setState: NO];
 
     /* We always try to do so */
-    [NSScreen unblackoutScreens];
+    if (!(OSX_LION && b_nativeFullscreenMode))
+        [NSScreen unblackoutScreens];
     vout_thread_t *p_vout = getVout();
     if (p_vout)
     {
@@ -1339,10 +1530,11 @@ static VLCMainWindow *_o_sharedInstance = nil;
 
 - (void)orderOut: (id)sender
 {
-    [super orderOut: sender];
-
     /* Make sure we leave fullscreen */
-    [self leaveFullscreenAndFadeOut: YES];
+    if (!(OSX_LION && b_nativeFullscreenMode))
+        [self leaveFullscreenAndFadeOut: YES];
+
+    [super orderOut: sender];
 }
 
 - (void)makeKeyAndOrderFront: (id)sender
@@ -1429,12 +1621,67 @@ static VLCMainWindow *_o_sharedInstance = nil;
 {
     [o_video_view setFrame: [[self contentView] frame]];
     [NSCursor setHiddenUntilMouseMoves: YES];
+    b_fullscreen = YES;
+    [o_fspanel setVoutWasUpdated: (int)[[self screen] displayID]];
+
+    if (b_dark_interface)
+    {
+        [o_titlebar_view removeFromSuperviewWithoutNeedingDisplay];
+
+        NSRect winrect;
+        CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;
+        winrect = [self frame];
+
+        winrect.size.height = winrect.size.height - f_titleBarHeight;
+        [self setFrame: winrect display:NO animate:NO];
+        winrect = [o_split_view frame];
+        winrect.size.height = winrect.size.height + f_titleBarHeight;
+        [o_split_view setFrame: winrect];
+    }
 }
 
 - (void)windowWillExitFullScreen:(NSNotification *)notification
 {
     [o_video_view setFrame: [o_split_view frame]];
     [NSCursor setHiddenUntilMouseMoves: NO];
+    [o_fspanel setNonActive: nil];
+    b_fullscreen = NO;
+
+    if (b_dark_interface)
+    {
+        NSRect winrect;
+        CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;
+        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_split_view frame];
+        winrect.size.height = winrect.size.height - f_titleBarHeight;
+        [o_split_view setFrame: winrect];
+        [o_video_view setFrame: winrect];
+    }
+}
+
+#pragma mark -
+#pragma mark split view delegate
+- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex
+{
+    if (dividerIndex == 0)
+        return 200.0;
+    else
+        return proposedMin;
+}
+
+- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex
+{
+    if (dividerIndex == 0)
+        return ([self frame].size.width - 300.0);
+    else
+        return proposedMax;
 }
 
 #pragma mark -