X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fembeddedwindow.m;h=6b892367a6e74e0eccacc3fb2b5980dcf3f2bb6c;hb=e17d5ecd8918a78c8ecbff36110292c1caaafd26;hp=b4d2c5cdda1db40d57d95afc503e4853a04f32b5;hpb=e0f5ea8f11cc5c0cba795a01a9d0ce310c8fa271;p=vlc diff --git a/modules/gui/macosx/embeddedwindow.m b/modules/gui/macosx/embeddedwindow.m index b4d2c5cdda..6b892367a6 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 @@ -25,9 +26,26 @@ * Preamble *****************************************************************************/ -#include "intf.h" -#include "vout.h" -#include "embeddedwindow.h" +#import "intf.h" +#import "controls.h" +#import "vout.h" +#import "embeddedwindow.h" +#import "fspanel.h" +#import "playlist.h" + +/* SetSystemUIMode, ... */ +#import + +/***************************************************************************** + * extension to NSWindow's interface to fix compilation warnings + * and let us access this functions properly + * this uses a private Apple-API, but works fine on all current OSX releases + * keep checking for compatiblity with future releases though + *****************************************************************************/ + +@interface NSWindow (UndocumentedWindowProperties) +- (void)setBottomCornerRounded: (BOOL)value; +@end /***************************************************************************** * VLCEmbeddedWindow Implementation @@ -38,25 +56,86 @@ - (void)awakeFromNib { [self setDelegate: self]; + [self setBottomCornerRounded:NO]; + /* button strings */ [o_btn_backward setToolTip: _NS("Rewind")]; [o_btn_forward setToolTip: _NS("Fast Forward")]; [o_btn_fullscreen setToolTip: _NS("Fullscreen")]; [o_btn_play setToolTip: _NS("Play")]; - [o_slider setToolTip: _NS("Position")]; + [o_timeslider setToolTip: _NS("Position")]; + [o_btn_prev setToolTip: _NS("Previous")]; + [o_btn_stop setToolTip: _NS("Stop")]; + [o_btn_next setToolTip: _NS("Next")]; + [o_volumeslider setToolTip: _NS("Volume")]; + [o_btn_playlist setToolTip: _NS("Playlist")]; + [self setTitle: _NS("VLC media player")]; + + o_img_play = [NSImage imageNamed: @"play_big"]; + o_img_pause = [NSImage imageNamed: @"pause_big"]; + + [self controlTintChanged]; + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector( controlTintChanged ) + name: NSControlTintDidChangeNotification + object: nil]; + + /* Set color of sidebar to Leopard's "Sidebar Blue" */ + [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820 + green:0.843 + blue:0.886 + alpha:1.0]]; + + [self setMinSize:NSMakeSize([o_sidebar_list convertRect:[o_sidebar_list bounds] + toView: nil].size.width + 551., 114.)]; - 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"]; + /* Useful to save o_view frame in fullscreen mode */ + o_temp_view = [[NSView alloc] init]; + [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable]; + + o_fullscreen_window = nil; + o_makekey_anim = o_fullscreen_anim1 = o_fullscreen_anim2 = nil; + + /* Not fullscreen when we wake up */ + [o_btn_fullscreen setState: NO]; + b_fullscreen = NO; + + /* 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; + + o_img_play_pressed = [NSImage imageNamed: @"play_big_down"]; + o_img_pause_pressed = [NSImage imageNamed: @"pause_big_down"]; + + if( b_playing ) + [o_btn_play setAlternateImage: o_img_play_pressed]; + else + [o_btn_play setAlternateImage: o_img_pause_pressed]; +} - o_saved_frame = NSMakeRect( 0.0f, 0.0f, 0.0f, 0.0f ); +- (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 { [o_time setStringValue: o_arg_time]; - [o_slider setFloatValue: f_position]; + [o_timeslider setFloatValue: f_position]; } - (void)playStatusUpdated:(int)i_status @@ -79,41 +158,801 @@ { [o_btn_forward setEnabled: b_seekable]; [o_btn_backward setEnabled: b_seekable]; - [o_slider setEnabled: b_seekable]; + [o_timeslider setEnabled: b_seekable]; +} + +- (void)setScrollString:(NSString *)o_string +{ + [o_scrollfield setStringValue: o_string]; +} + +- (id)getPgbar +{ + if( o_main_pgbar ) + return o_main_pgbar; + + return nil; +} + +- (void)setStop:(BOOL)b_input +{ + [o_btn_stop setEnabled: b_input]; +} + +- (void)setNext:(BOOL)b_input +{ + [o_btn_next setEnabled: b_input]; +} + +- (void)setPrev:(BOOL)b_input +{ + [o_btn_prev setEnabled: b_input]; +} + +- (void)setVolumeEnabled:(BOOL)b_input +{ + [o_volumeslider setEnabled: b_input]; +} + +- (void)setVolumeSlider:(float)f_level +{ + [o_volumeslider setFloatValue: f_level]; +} + +- (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame +{ + [self setFrame: newFrame display: YES animate: YES]; + return NO; +} + +- (BOOL)windowShouldClose:(id)sender +{ + playlist_t * p_playlist = pl_Get( VLCIntf ); + + /* Only want to stop playback if video is playing */ + if( videoRatio.height != 0. && videoRatio.width != 0. ) + playlist_Stop( p_playlist ); + return YES; +} + +- (NSView *)mainView +{ + if (o_fullscreen_window) + return o_temp_view; + else + return o_view; +} + +- (void)setVideoRatio:(NSSize)ratio +{ + videoRatio = ratio; +} + +- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize +{ + NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1]; + NSRect newList = [playlist_area frame]; + if( newList.size.height < 50 && newList.size.height > 0 ) { + [self togglePlaylist:self]; + } + + /* With no video open or with the playlist open the behavior is odd */ + if( newList.size.height > 50 ) + return 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; +} + +- (void)becomeMainWindow +{ + [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820 + green:0.843 + blue:0.886 + alpha:1.0]]; + [o_status becomeMainWindow]; + [super becomeMainWindow]; +} + +- (void)resignMainWindow +{ + [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedWhite:0.91 alpha:1.0]]; + [o_status resignMainWindow]; + [super resignMainWindow]; +} + +- (CGFloat)splitView:(NSSplitView *) splitView constrainSplitPosition:(CGFloat) proposedPosition ofSubviewAt:(NSInteger) index +{ + if([splitView isVertical]) + return proposedPosition; + else if ( splitView == o_vertical_split ) + return proposedPosition ; + else { + float bottom = [splitView frame].size.height - [splitView dividerThickness]; + if(proposedPosition > bottom - 50) { + [o_btn_playlist setState: NSOffState]; + [o_searchfield setHidden:YES]; + [o_playlist_view setHidden:YES]; + return bottom; + } + else { + [o_btn_playlist setState: NSOnState]; + [o_searchfield setHidden:NO]; + [o_playlist_view setHidden:NO]; + [o_playlist swapPlaylists: o_playlist_table]; + [o_vlc_main togglePlaylist:self]; + return proposedPosition; + } + } +} + +- (void)splitViewWillResizeSubviews:(NSNotification *) notification +{ + +} + +- (CGFloat)splitView:(NSSplitView *) splitView constrainMinCoordinate:(CGFloat) proposedMin ofSubviewAt:(NSInteger) offset +{ + if([splitView isVertical]) + return 125.; + else + return 0.; +} + +- (CGFloat)splitView:(NSSplitView *) splitView constrainMaxCoordinate:(CGFloat) proposedMax ofSubviewAt:(NSInteger) offset +{ + if([splitView isVertical]) + return MIN([self frame].size.width - 551, 300); + else + return [splitView frame].size.height; +} + +- (BOOL)splitView:(NSSplitView *) splitView canCollapseSubview:(NSView *) subview +{ + if([splitView isVertical]) + return NO; + else + return NO; +} + +- (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect + ofDividerAtIndex:(NSInteger)dividerIndex +{ + if([splitView isVertical]) { + drawnRect.origin.x -= 3; + drawnRect.size.width += 5; + return drawnRect; + } + else + return drawnRect; +} + +- (IBAction)togglePlaylist:(id)sender +{ + NSView *playback_area = [[o_vertical_split subviews] objectAtIndex:0]; + NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1]; + NSRect newVid = [playback_area frame]; + NSRect newList = [playlist_area frame]; + if(newList.size.height < 50 && sender != self && sender != o_vlc_main) { + newList.size.height = newVid.size.height/2; + newVid.size.height = newVid.size.height/2; + newVid.origin.y = newVid.origin.y + newList.size.height; + [o_btn_playlist setState: NSOnState]; + [o_searchfield setHidden:NO]; + [o_playlist_view setHidden:NO]; + [o_playlist swapPlaylists: o_playlist_table]; + [o_vlc_main togglePlaylist:self]; + } + else { + newVid.size.height = newVid.size.height + newList.size.height; + newList.size.height = 0; + newVid.origin.y = 0; + [o_btn_playlist setState: NSOffState]; + [o_searchfield setHidden:YES]; + [o_playlist_view setHidden:YES]; + } + [playback_area setFrame: newVid]; + [playlist_area setFrame: newList]; +} + +/***************************************************************************** + * Fullscreen support + */ + +- (BOOL)isFullscreen +{ + return b_fullscreen; +} + +- (void)lockFullscreenAnimation +{ + [o_animation_lock lock]; +} + +- (void)unlockFullscreenAnimation +{ + [o_animation_lock unlock]; +} + +- (void)enterFullscreen +{ + NSMutableDictionary *dict1, *dict2; + NSScreen *screen; + NSRect screen_rect; + NSRect rect; + vout_thread_t *p_vout = getVout(); + BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" ); + + 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]; + + [o_btn_fullscreen setState: YES]; + + [NSCursor setHiddenUntilMouseMoves: YES]; + + 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) + { + /* We can't change the styleMask of an already created NSWindow, so we create an other window, and do eye catching stuff */ + + rect = [[o_view superview] convertRect: [o_view frame] toView: nil]; /* Convert to Window base coord */ + rect.origin.x += [self frame].origin.x; + rect.origin.y += [self frame].origin.y; + o_fullscreen_window = [[VLCWindow alloc] initWithContentRect:rect styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; + [o_fullscreen_window setBackgroundColor: [NSColor blackColor]]; + [o_fullscreen_window setCanBecomeKeyWindow: YES]; + + if (![self isVisible] || [self alphaValue] == 0.0) + { + /* We don't animate if we are not visible, instead we + * simply fade the display */ + CGDisplayFadeReservationToken token; + + CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); + CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES ); + + if ([screen isMainScreen]) + SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); + + [[o_view superview] 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]; + [o_fullscreen_window orderFront:self animate:YES]; + + [o_fullscreen_window setFrame:screen_rect display:YES]; + + CGDisplayFade( token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO ); + CGReleaseDisplayFadeReservation( token); + + /* Will release the lock */ + [self hasBecomeFullscreen]; + + return; + } + + /* Make sure we don't see the o_view disappearing of the screen during this operation */ + NSDisableScreenUpdates(); + [[o_view superview] 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]; + NSEnableScreenUpdates(); + } + + /* We are in fullscreen (and no animation is running) */ + if (b_fullscreen) + { + /* Make sure we are hidden */ + [super orderOut: self]; + [self unlockFullscreenAnimation]; + return; + } + + if (o_fullscreen_anim1) + { + [o_fullscreen_anim1 stopAnimation]; + [o_fullscreen_anim1 release]; + } + if (o_fullscreen_anim2) + { + [o_fullscreen_anim2 stopAnimation]; + [o_fullscreen_anim2 release]; + } + + if ([screen isMainScreen]) + SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); + + dict1 = [[NSMutableDictionary alloc] initWithCapacity:2]; + dict2 = [[NSMutableDictionary alloc] initWithCapacity:3]; + + [dict1 setObject:self forKey:NSViewAnimationTargetKey]; + [dict1 setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey]; + + [dict2 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey]; + [dict2 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey]; + [dict2 setObject:[NSValue valueWithRect:screen_rect] forKey:NSViewAnimationEndFrameKey]; + + /* Strategy with NSAnimation allocation: + - Keep at most 2 animation at a time + - leaveFullscreen/enterFullscreen are the only responsible for releasing and alloc-ing + */ + o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]]; + o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]]; + + [dict1 release]; + [dict2 release]; + + [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking]; + [o_fullscreen_anim1 setDuration: 0.3]; + [o_fullscreen_anim1 setFrameRate: 30]; + [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking]; + [o_fullscreen_anim2 setDuration: 0.2]; + [o_fullscreen_anim2 setFrameRate: 30]; + + [o_fullscreen_anim2 setDelegate: self]; + [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0]; + + [o_fullscreen_anim1 startAnimation]; + /* fullscreenAnimation will be unlocked when animation ends */ } -- (void)setFullscreen:(BOOL)b_fullscreen +- (void)hasBecomeFullscreen { - [o_btn_fullscreen setState: b_fullscreen]; + [o_fullscreen_window makeFirstResponder: [[[VLCMain sharedInstance] controls] voutView]]; + + [o_fullscreen_window makeKeyWindow]; + [o_fullscreen_window setAcceptsMouseMovedEvents: TRUE]; + + /* tell the fspanel to move itself to front next time it's triggered */ + [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]]; + + if([self isVisible]) + [super orderOut: self]; + + [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil]; + + b_fullscreen = YES; + [self unlockFullscreenAnimation]; +} + +- (void)leaveFullscreen +{ + [self leaveFullscreenAndFadeOut: NO]; +} + +- (void)leaveFullscreenAndFadeOut: (BOOL)fadeout +{ + NSMutableDictionary *dict1, *dict2; + NSRect frame; + + [self lockFullscreenAnimation]; + + b_fullscreen = NO; + [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) + { + [self unlockFullscreenAnimation]; + return; + } + + if (fadeout) + { + /* We don't animate if we are not visible, instead we + * simply fade the display */ + CGDisplayFadeReservationToken token; + + CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); + CGDisplayFade( token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES ); + + [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil]; + SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar); + + /* 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; + } + + [self setAlphaValue: 0.0]; + [self orderFront: self]; + + [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil]; + SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar); + + if (o_fullscreen_anim1) + { + [o_fullscreen_anim1 stopAnimation]; + [o_fullscreen_anim1 release]; + } + if (o_fullscreen_anim2) + { + [o_fullscreen_anim2 stopAnimation]; + [o_fullscreen_anim2 release]; + } + + 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; + + dict2 = [[NSMutableDictionary alloc] initWithCapacity:2]; + [dict2 setObject:self forKey:NSViewAnimationTargetKey]; + [dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey]; + + o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]]; + [dict2 release]; + + [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking]; + [o_fullscreen_anim2 setDuration: 0.3]; + [o_fullscreen_anim2 setFrameRate: 30]; + + [o_fullscreen_anim2 setDelegate: self]; + + dict1 = [[NSMutableDictionary alloc] initWithCapacity:3]; + + [dict1 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey]; + [dict1 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey]; + [dict1 setObject:[NSValue valueWithRect:frame] forKey:NSViewAnimationEndFrameKey]; + + o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict1, nil]]; + [dict1 release]; + + [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking]; + [o_fullscreen_anim1 setDuration: 0.2]; + [o_fullscreen_anim1 setFrameRate: 30]; + [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0]; + + /* Make sure o_fullscreen_window is the frontmost window */ + [o_fullscreen_window orderFront: self]; + + [o_fullscreen_anim1 startAnimation]; + /* fullscreenAnimation will be unlocked when animation ends */ +} + +- (void)hasEndedFullscreen +{ + /* This function is private and should be only triggered at the end of the fullscreen change animation */ + /* Make sure we don't see the o_view disappearing of the screen during this operation */ + NSDisableScreenUpdates(); + [o_view retain]; + [o_view removeFromSuperviewWithoutNeedingDisplay]; + [[o_temp_view superview] replaceSubview:o_temp_view with:o_view]; + [o_view release]; + [o_view setFrame:[o_temp_view frame]]; + [self makeFirstResponder: o_view]; + if ([self isVisible]) + [super makeKeyAndOrderFront:self]; /* our version contains a workaround */ + [o_fullscreen_window orderOut: self]; + NSEnableScreenUpdates(); + + [o_fullscreen_window release]; + o_fullscreen_window = nil; + [self setLevel:originalLevel]; + + [self unlockFullscreenAnimation]; } -- (void)zoom:(id)sender +- (void)animationDidEnd:(NSAnimation*)animation { - if( ![self isZoomed] ) + NSArray *viewAnimations; + if( o_makekey_anim == animation ) { - NSRect zoomRect = [[self screen] frame]; - o_saved_frame = [self frame]; - /* we don't have to take care of the eventual menu bar and dock - as zoomRect will be cropped automatically by setFrame:display: - to the right rectangle */ - [self setFrame: zoomRect display: YES animate: YES]; + [o_makekey_anim release]; + return; + } + if ([animation currentValue] < 1.0) + return; + + /* Fullscreen ended or started (we are a delegate only for leaveFullscreen's/enterFullscren's anim2) */ + viewAnimations = [o_fullscreen_anim2 viewAnimations]; + if ([viewAnimations count] >=1 && + [[[viewAnimations objectAtIndex: 0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect]) + { + /* Fullscreen ended */ + [self hasEndedFullscreen]; } else { - /* unzoom to the saved_frame if the o_saved_frame coords look sound - (just in case) */ - if( o_saved_frame.size.width > 0 && o_saved_frame.size.height > 0 ) - [self setFrame: o_saved_frame display: YES animate: YES]; + /* Fullscreen started */ + [self hasBecomeFullscreen]; } } -- (BOOL)windowShouldClose:(id)sender +- (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]; + [dict setObject:self forKey:NSViewAnimationTargetKey]; + [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey]; + + o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]]; + [dict release]; + + [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking]; + [o_makekey_anim setDuration: 0.1]; + [o_makekey_anim setFrameRate: 30]; + [o_makekey_anim setDelegate: self]; + + [o_makekey_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 { - playlist_t * p_playlist = pl_Yield( VLCIntf ); + struct { NSRect frame; BOOL display; BOOL animate;} args; + NSData *packedargs; + + args.frame = frame; + args.display = display; + args.animate = animate; + + packedargs = [NSData dataWithBytes:&args length:sizeof(args)]; - playlist_Stop( p_playlist ); - vlc_object_release( p_playlist ); + [self performSelectorOnMainThread:@selector(setFrameOnMainThread:) + withObject: packedargs waitUntilDone: YES]; +} + +- (void)setFrameOnMainThread:(NSData*)packedargs +{ + struct args { NSRect frame; BOOL display; BOOL animate; } * args = (struct args*)[packedargs bytes]; + + 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 arrayWithObject:dict]]; + [dict release]; + + [anim setAnimationBlockingMode: NSAnimationNonblocking]; + [anim setDuration: 0.4]; + [anim setFrameRate: 30]; + [anim startAnimation]; + } + else { + [super setFrame:args->frame display:args->display animate:args->animate]; + } + +} +@end + +/***************************************************************************** + * embeddedbackground + *****************************************************************************/ + + +@implementation embeddedbackground + +- (void)dealloc +{ + [self unregisterDraggedTypes]; + [super dealloc]; +} + +- (void)awakeFromNib +{ + [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, + NSFilenamesPboardType, nil]]; + [self addSubview: o_timeslider]; + [self addSubview: o_scrollfield]; + [self addSubview: o_time]; + [self addSubview: o_main_pgbar]; + [self addSubview: o_btn_backward]; + [self addSubview: o_btn_forward]; + [self addSubview: o_btn_fullscreen]; + [self addSubview: o_btn_equalizer]; + [self addSubview: o_btn_playlist]; + [self addSubview: o_btn_play]; + [self addSubview: o_btn_prev]; + [self addSubview: o_btn_stop]; + [self addSubview: o_btn_next]; + [self addSubview: o_btn_volume_down]; + [self addSubview: o_volumeslider]; + [self addSubview: o_btn_volume_up]; + [self addSubview: o_searchfield]; +} + +- (NSDragOperation)draggingEntered:(id )sender +{ + if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) + == NSDragOperationGeneric) + { + return NSDragOperationGeneric; + } + else + { + return NSDragOperationNone; + } +} + +- (BOOL)prepareForDragOperation:(id )sender +{ return YES; } +- (BOOL)performDragOperation:(id )sender +{ + NSPasteboard *o_paste = [sender draggingPasteboard]; + NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil]; + NSString *o_desired_type = [o_paste availableTypeFromArray:o_types]; + NSData *o_carried_data = [o_paste dataForType:o_desired_type]; + BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" ); + + if( o_carried_data ) + { + if ([o_desired_type isEqualToString:NSFilenamesPboardType]) + { + int i; + NSArray *o_array = [NSArray array]; + NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] + sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + + for( i = 0; i < (int)[o_values count]; i++) + { + NSDictionary *o_dic; + o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"]; + o_array = [o_array arrayByAddingObject: o_dic]; + } + if( b_autoplay ) + [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO]; + else + [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES]; + return YES; + } + } + [self setNeedsDisplay:YES]; + return YES; +} + +- (void)concludeDragOperation:(id )sender +{ + [self setNeedsDisplay:YES]; +} + +- (void)drawRect:(NSRect)rect +{ + NSImage *leftImage = [NSImage imageNamed:@"display_left"]; + NSImage *middleImage = [NSImage imageNamed:@"display_middle"]; + NSImage *rightImage = [NSImage imageNamed:@"display_right"]; + [middleImage setSize:NSMakeSize(NSWidth( [self bounds] ) - 134 - [leftImage size].width - [rightImage size].width, [middleImage size].height)]; + [middleImage setScalesWhenResized:YES]; + [leftImage compositeToPoint:NSMakePoint( 122., 40. ) operation:NSCompositeSourceOver]; + [middleImage compositeToPoint:NSMakePoint( 122. + [leftImage size].width, 40. ) operation:NSCompositeSourceOver]; + [rightImage compositeToPoint:NSMakePoint( NSWidth( [self bounds] ) - 12 - [rightImage size].width, 40. ) operation:NSCompositeSourceOver]; +} + +- (void)mouseDown:(NSEvent *)event +{ + dragStart = [self convertPoint:[event locationInWindow] fromView:nil]; +} + +- (void)mouseDragged:(NSEvent *)event +{ + NSPoint dragLocation = [self convertPoint:[event locationInWindow] fromView:nil]; + NSPoint winOrigin = [o_window frame].origin; + + NSPoint newOrigin = NSMakePoint(winOrigin.x + (dragLocation.x - dragStart.x), + winOrigin.y + (dragLocation.y - dragStart.y)); + [o_window setFrameOrigin: newOrigin]; +} + +@end + +/***************************************************************************** + * statusbar + *****************************************************************************/ + + +@implementation statusbar +- (void)awakeFromNib +{ + [self addSubview: o_text]; + mainwindow = YES; +} + +- (void)resignMainWindow +{ + mainwindow = NO; + [self needsDisplay]; +} + +- (void)becomeMainWindow +{ + mainwindow = YES; + [self needsDisplay]; +} + +- (void)drawRect:(NSRect)rect +{ + if(mainwindow) + [[NSColor colorWithCalibratedRed:0.820 + green:0.843 + blue:0.886 + alpha:1.0] set]; + else + [[NSColor colorWithCalibratedWhite:0.91 alpha:1.0] set]; + NSRectFill(rect); + /*NSRect divider = rect; + divider.origin.y += divider.size.height - 1; + divider.size.height = 1; + [[NSColor colorWithCalibratedWhite:0.65 alpha:1.] set]; + NSRectFill(divider);*/ +} @end