/*****************************************************************************
- * MainWindow.h: MacOS X interface module
+ * MainWindow.m: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2002-2011 VideoLAN
+ * Copyright (C) 2002-2011 VLC authors and VideoLAN
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
#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>
- (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];
[self setMovableByWindowBackground: YES];
/* we don't want this window to be restored on relaunch */
- if ([self respondsToSelector:@selector(setRestorable:)])
+ if (OSX_LION)
[self setRestorable:NO];
return self;
- (void)dealloc
{
+ [[NSNotificationCenter defaultCenter] removeObserver: self];
config_PutInt( VLCIntf->p_libvlc, "volume", i_lastShownVolume );
+ [self saveFrameUsingName: [self frameAutosaveName]];
[o_sidebaritems release];
[super dealloc];
}
- (void)awakeFromNib
{
/* setup the styled interface */
- b_dark_interface = config_GetInt( VLCIntf, "macosx-interfacestyle" );
b_nativeFullscreenMode = config_GetInt( VLCIntf, "macosx-nativefullscreenmode" );
i_lastShownVolume = -1;
}
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"]];
/* 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]];
[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"];
{
[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"]];
}
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"]];
}
[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 -
[[[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
[self setTitle: _NS("VLC media player")];
[self setRepresentedURL: nil];
}
+
[o_pool release];
}
b_plmul = playlist_CurrentSize( p_playlist ) > 1;
PL_UNLOCK;
- [o_sidebar_view reloadData];
-
input_thread_t * p_input = playlist_CurrentInput( p_playlist );
bool b_buffering = NO;
/* 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 );
}
- (void)drawFancyGradientEffectForTimeSlider
{
NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
- float f_value = ([o_time_sld_middle_view frame].size.width -5) * ([o_time_sld intValue] / [o_time_sld maxValue]);
+ float f_value = [o_time_sld_middle_view frame].size.width * ([o_time_sld intValue] / [o_time_sld maxValue]);
if (f_value > 5.0)
{
if (f_value != [o_time_sld_fancygradient_view frame].size.width)
- (void)setVideoplayEnabled
{
+ BOOL b_videoPlayback = [[VLCMain sharedInstance] activeVideoPlayback];
+
if (!b_nonembedded)
- [o_playlist_btn setEnabled: [[VLCMain sharedInstance] activeVideoPlayback]];
+ [o_playlist_btn setEnabled: b_videoPlayback];
else
{
[o_playlist_btn setEnabled: NO];
- if (![[VLCMain sharedInstance] activeVideoPlayback])
+ if (!b_videoPlayback)
[o_nonembedded_window orderOut: nil];
}
+ if( OSX_LION && b_nativeFullscreenMode )
+ {
+ if( [NSApp presentationOptions] == NSApplicationPresentationFullScreen )
+ [o_bottombar_view setHidden: b_videoPlayback];
+ else
+ [o_bottombar_view setHidden: NO];
+ if (!b_videoPlayback)
+ [o_fspanel setNonActive: nil];
+ }
}
- (void)resizeWindow
{
- if ( !b_fullscreen && !(OSX_LION && [NSApp currentSystemPresentationOptions] == NSApplicationPresentationFullScreen && b_nativeFullscreenMode) )
+ if ( !b_fullscreen && !(OSX_LION && [NSApp presentationOptions] == NSApplicationPresentationFullScreen && b_nativeFullscreenMode) )
{
NSPoint topleftbase;
NSPoint topleftscreen;
/* 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;
#pragma mark Fullscreen support
- (void)showFullscreenController
{
- if (b_fullscreen)
+ if (b_fullscreen && [[VLCMain sharedInstance] activeVideoPlayback] )
[o_fspanel fadeIn];
}
[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)
{
- (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
[NSValue valueWithRect:args->frame], NSViewAnimationEndFrameKey, nil];
NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
- [dict release];
[anim setAnimationBlockingMode: NSAnimationNonblocking];
[anim setDuration: 0.4];
[anim setFrameRate: 30];
[anim startAnimation];
+
+ [anim release];
}
else {
[super setFrame:args->frame display:args->display animate:args->animate];
}
}
+#pragma mark -
+#pragma mark Lion's native fullscreen handling
+- (void)windowWillEnterFullScreen:(NSNotification *)notification
+{
+ [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 -
#pragma mark Side Bar Data handling
/* taken under BSD-new from the PXSourceList sample project, adapted for VLC */