1 /*****************************************************************************
2 * vout.m: MacOS X video output module
3 *****************************************************************************
4 * Copyright (C) 2001-2008 the VideoLAN team
7 * Authors: Colin Delacroix <colin@zoy.org>
8 * Florian G. Pflug <fgp@phlo.org>
9 * Jon Lech Johansen <jon-vl@nanocrew.net>
10 * Derk-Jan Hartman <hartman at videolan dot org>
11 * Eric Petit <titer@m0k.org>
12 * Benjamin Pracht <bigben at videolan dot org>
13 * Felix Paul Kühne <fkuehne at videolan dot org>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
28 *****************************************************************************/
30 /*****************************************************************************
32 *****************************************************************************/
33 #include <errno.h> /* ENOMEM */
34 #include <stdlib.h> /* free() */
37 /* BeginFullScreen, EndFullScreen */
38 #include <QuickTime/QuickTime.h>
40 /* prevent system sleep */
41 #import <CoreServices/CoreServices.h>
49 #import "embeddedwindow.h"
51 /*****************************************************************************
52 * DeviceCallback: Callback triggered when the video-device variable is changed
53 *****************************************************************************/
54 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
55 vlc_value_t old_val, vlc_value_t new_val, void *param )
58 vout_thread_t *p_vout = (vout_thread_t *)p_this;
60 msg_Dbg( p_vout, "set %d", new_val.i_int );
61 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
62 var_Set( p_vout->p_libvlc, "video-device", new_val );
65 var_Set( p_vout, "intf-change", val );
70 /*****************************************************************************
71 * VLCEmbeddedList implementation
72 *****************************************************************************/
73 @implementation VLCEmbeddedList
78 o_embedded_array = [NSMutableArray array];
86 for( i = 0; i < [o_embedded_array count]; i++ )
88 id o_vout_view = [o_embedded_array objectAtIndex: i];
89 if( ![o_vout_view isUsed] )
91 [o_vout_view setUsed: YES];
98 - (void)releaseEmbeddedVout: (id)o_vout_view
100 if( [o_embedded_array containsObject: o_vout_view] )
102 [o_vout_view setUsed: NO];
106 msg_Warn( VLCIntf, "cannot find Video Output");
110 - (void)addEmbeddedVout: (id)o_vout_view
112 if( ![o_embedded_array containsObject: o_vout_view] )
114 [o_embedded_array addObject: o_vout_view];
118 - (BOOL)windowContainsEmbedded: (id)o_window
120 /* if( ![[o_window className] isEqualToString: @"VLCVoutWindow"] )
122 NSLog( @"We were not given a VLCVoutWindow" );
124 return ([self getViewForWindow: o_window] == nil ? NO : YES );
127 - (id)getViewForWindow: (id)o_window
129 if( o_embedded_array != nil )
131 id o_enumerator = [o_embedded_array objectEnumerator];
132 id o_current_embedded;
133 if( o_window != nil )
135 while( (o_current_embedded = [o_enumerator nextObject]) )
137 if( [o_current_embedded getWindow] == o_window )
139 return o_current_embedded;
149 /*****************************************************************************
150 * VLCVoutView implementation
151 *****************************************************************************/
152 @implementation VLCVoutView
154 - (id)initWithFrame: (NSRect)frameRect
156 self = [super initWithFrame: frameRect];
159 s_frame = &frameRect;
166 - (BOOL)setVout: (vout_thread_t *) vout
167 subView: (NSView *) view
168 frame: (NSRect *) frame
171 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
172 NSArray *o_screens = [NSScreen screens];
178 if( [o_screens count] <= 0 )
180 msg_Err( p_vout, "no OSX screens available" );
184 p_real_vout = [VLCVoutView getRealVout: p_vout];
186 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
187 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
189 i_device = var_GetInteger( p_vout, "macosx-vdev" );
193 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
196 /* Setup the menuitem for the multiple displays. */
197 if( var_Type( p_real_vout, "video-device" ) == 0 )
200 vlc_value_t val2, text;
203 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
205 text.psz_string = _("Fullscreen Video Device");
206 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
208 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
211 text.psz_string = _("Default");
212 var_Change( p_real_vout, "video-device",
213 VLC_VAR_ADDCHOICE, &val2, &text );
214 var_Set( p_real_vout, "video-device", val2 );
216 while( (o_screen = [o_enumerator nextObject]) != NULL )
219 NSRect s_rect = [o_screen frame];
221 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
222 "%s %d (%dx%d)", _("Screen"), i,
223 (int)s_rect.size.width, (int)s_rect.size.height );
225 text.psz_string = psz_temp;
226 val2.i_int = (int)[o_screen displayID];
227 var_Change( p_real_vout, "video-device",
228 VLC_VAR_ADDCHOICE, &val2, &text );
229 if( (int)[o_screen displayID] == i_device )
231 var_Set( p_real_vout, "video-device", val2 );
236 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
240 var_Set( p_real_vout, "intf-change", val2 );
243 /* Add the view. It's automatically resized to fit the window */
244 [self addSubview: o_view];
245 [self setAutoresizesSubviews: YES];
251 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
253 [super resizeSubviewsWithOldSize: oldBoundsSize];
254 [o_view setFrameSize: [self frame].size];
257 - (void)drawRect:(NSRect)rect
259 /* When there is no subview we draw a black background */
261 [[NSColor blackColor] set];
268 [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeOut];
270 /* Make sure we don't see a white flash */
271 [[self window] disableScreenUpdatesUntilFlush];
272 [o_view removeFromSuperview];
282 NSString * o_title = nil;
283 NSMutableString * o_mrl = nil;
284 input_thread_t * p_input;
287 if( !p_vout ) return;
289 p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT );
291 if( !p_input ) return;
293 input_item_t * p_item = input_GetItem( p_input );
295 psz_title = input_item_GetNowPlaying ( p_item );
297 psz_title = input_item_GetName( p_item );
300 o_title = [NSString stringWithUTF8String: psz_title];
302 char *psz_uri = input_item_GetURI( p_item );
304 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
314 /* FIXME once psz_access is exported, we could check if we are
315 * reading from a file in a smarter way. */
317 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
318 if( prefix_range.location != NSNotFound )
319 [o_mrl deleteCharactersInRange: prefix_range];
321 if( [o_mrl characterAtIndex:0] == '/' )
323 /* it's a local file */
324 [o_window setRepresentedFilename: o_mrl];
328 /* it's from the network or somewhere else,
329 * we clear the previous path */
330 [o_window setRepresentedFilename: @""];
332 [o_window setTitle: o_title];
336 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
338 vlc_object_release( p_input );
342 - (void)setOnTop:(BOOL)b_on_top
346 [o_window setLevel: NSStatusWindowLevel];
350 [o_window setLevel: NSNormalWindowLevel];
354 - (NSSize)voutSizeForFactor: (float)factor
356 int i_corrected_height, i_corrected_width;
359 if( p_vout->render.i_height * p_vout->render.i_aspect >
360 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
362 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
364 newsize.width = (int) ( i_corrected_width * factor );
365 newsize.height = (int) ( p_vout->render.i_height * factor );
369 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
370 p_vout->render.i_aspect;
371 newsize.width = (int) ( p_vout->render.i_width * factor );
372 newsize.height = (int) ( i_corrected_height * factor );
378 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
380 if ( !p_vout->b_fullscreen )
384 NSPoint topleftscreen;
388 topleftbase.y = [o_window frame].size.height;
389 topleftscreen = [o_window convertBaseToScreen: topleftbase];
391 newsize = [self voutSizeForFactor:factor];
393 /* In fullscreen mode we need to use a view that is different from
394 * ourselves, with the VLCEmbeddedWindow */
395 if([o_window isKindOfClass:[VLCEmbeddedWindow class]])
396 mainView = [o_window mainView];
400 /* Calculate the window's new size */
401 new_frame.size.width = [o_window frame].size.width -
402 [mainView frame].size.width + newsize.width;
403 new_frame.size.height = [o_window frame].size.height -
404 [mainView frame].size.height + newsize.height;
406 new_frame.origin.x = topleftscreen.x;
407 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
409 [o_window setFrame:new_frame display:animate animate:animate];
410 p_vout->i_changes |= VOUT_SIZE_CHANGE;
414 - (void)toggleFloatOnTop
418 if( !p_real_vout ) return;
419 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
427 var_Set( p_real_vout, "video-on-top", val );
430 - (void)toggleFullscreen
433 if( !p_real_vout ) return;
434 var_Get( p_real_vout, "fullscreen", &val );
435 val.b_bool = !val.b_bool;
436 var_Set( p_real_vout, "fullscreen", val );
442 if( !p_real_vout ) return NO;
443 var_Get( p_real_vout, "fullscreen", &val );
444 return( val.b_bool );
449 var_TriggerCallback( p_real_vout, "video-snapshot" );
454 /* Disable Screensaver, when we're playing something, but allow it on pause */
455 if( !VLCIntf || !VLCIntf->p_sys )
459 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
460 UpdateSystemActivity( UsrActivity );
468 - (void)scrollWheel:(NSEvent *)theEvent
470 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] getControls];
471 [o_controls scrollWheel: theEvent];
474 - (void)keyDown:(NSEvent *)o_event
478 unsigned int i_pressed_modifiers = 0;
481 i_pressed_modifiers = [o_event modifierFlags];
483 if( i_pressed_modifiers & NSShiftKeyMask )
484 val.i_int |= KEY_MODIFIER_SHIFT;
485 if( i_pressed_modifiers & NSControlKeyMask )
486 val.i_int |= KEY_MODIFIER_CTRL;
487 if( i_pressed_modifiers & NSAlternateKeyMask )
488 val.i_int |= KEY_MODIFIER_ALT;
489 if( i_pressed_modifiers & NSCommandKeyMask )
490 val.i_int |= KEY_MODIFIER_COMMAND;
492 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
496 /* Escape should always get you out of fullscreen */
497 if( key == (unichar) 0x1b )
499 if( p_real_vout && [self isFullscreen] )
501 [self toggleFullscreen];
507 val.i_int = config_GetInt( p_vout, "key-play-pause" );
509 val.i_int |= (int)CocoaKeyToVLC( key );
510 var_Set( p_vout->p_libvlc, "key-pressed", val );
512 else NSLog( @"Could not send keyevent to VLC core" );
515 [super keyDown: o_event];
518 - (void)mouseDown:(NSEvent *)o_event
523 if( ( [o_event type] == NSLeftMouseDown ) &&
524 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
526 if( [o_event clickCount] <= 1 )
528 /* single clicking */
529 var_Get( p_vout, "mouse-button-down", &val );
531 var_Set( p_vout, "mouse-button-down", val );
535 /* multiple clicking */
536 [self toggleFullscreen];
539 else if( ( [o_event type] == NSRightMouseDown ) ||
540 ( ( [o_event type] == NSLeftMouseDown ) &&
541 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
543 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
544 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] voutView]];
548 [super mouseDown: o_event];
551 - (void)otherMouseDown:(NSEvent *)o_event
555 if( p_vout && [o_event type] == NSOtherMouseDown )
557 var_Get( p_vout, "mouse-button-down", &val );
559 var_Set( p_vout, "mouse-button-down", val );
562 [super mouseDown: o_event];
565 - (void)rightMouseDown:(NSEvent *)o_event
567 if( p_vout && [o_event type] == NSRightMouseDown )
569 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
570 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] voutView]];
573 [super mouseDown: o_event];
576 - (void)mouseUp:(NSEvent *)o_event
580 if( p_vout && [o_event type] == NSLeftMouseUp )
582 var_SetBool( p_vout, "mouse-clicked", true );
584 var_Get( p_vout, "mouse-button-down", &val );
586 var_Set( p_vout, "mouse-button-down", val );
589 [super mouseUp: o_event];
592 - (void)otherMouseUp:(NSEvent *)o_event
596 if( p_vout && [o_event type] == NSOtherMouseUp )
598 var_Get( p_vout, "mouse-button-down", &val );
600 var_Set( p_vout, "mouse-button-down", val );
603 [super mouseUp: o_event];
606 - (void)rightMouseUp:(NSEvent *)o_event
608 if( p_vout && [o_event type] == NSRightMouseUp )
610 /* FIXME: this isn't the appropriate place, but we can't receive
611 * NSRightMouseDown some how */
612 msg_Dbg( p_vout, "received NSRightMouseUp" );
613 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] voutView]];
616 [super mouseUp: o_event];
619 - (void)mouseDragged:(NSEvent *)o_event
621 [self mouseMoved: o_event];
624 - (void)otherMouseDragged:(NSEvent *)o_event
626 [self mouseMoved: o_event];
629 - (void)rightMouseDragged:(NSEvent *)o_event
631 [self mouseMoved: o_event];
634 - (void)mouseMoved:(NSEvent *)o_event
642 s_rect = [o_view bounds];
643 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
644 b_inside = [o_view mouse: ml inRect: s_rect];
649 unsigned int i_width, i_height, i_x, i_y;
651 vout_PlacePicture( p_vout, (unsigned int)s_rect.size.width,
652 (unsigned int)s_rect.size.height,
653 &i_x, &i_y, &i_width, &i_height );
655 val.i_int = ( ((int)ml.x) - i_x ) *
656 p_vout->render.i_width / i_width;
657 var_Set( p_vout, "mouse-x", val );
659 if( [[o_view className] isEqualToString: @"VLCGLView"] )
661 val.i_int = ( ((int)(s_rect.size.height - ml.y)) - i_y ) *
662 p_vout->render.i_height / i_height;
666 val.i_int = ( ((int)ml.y) - i_y ) *
667 p_vout->render.i_height / i_height;
669 var_Set( p_vout, "mouse-y", val );
672 var_Set( p_vout, "mouse-moved", val );
674 if( [self isFullscreen] )
675 [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeIn];
678 [super mouseMoved: o_event];
681 - (BOOL)acceptsFirstResponder
686 - (BOOL)becomeFirstResponder
691 - (BOOL)resignFirstResponder
693 /* We need to stay the first responder or we'll miss some
698 /* Class methods used by the different vout modules */
700 + (vout_thread_t *)getRealVout: (vout_thread_t *)p_vout
702 /* p_real_vout: the vout we have to use to check for video-on-top
703 and a few other things. If we are the QuickTime output, it's us.
704 It we are the OpenGL provider, it is our parent.
705 Since we can't be the QuickTime output anymore, we need to be
707 FIXME: check with the caca and x11 vouts! */
708 return (vout_thread_t *) p_vout->p_parent;
711 + (id)voutView: (vout_thread_t *)p_vout subView: (NSView *)view
712 frame: (NSRect *)s_frame
714 vlc_value_t value_drawable;
718 var_Get( p_vout->p_libvlc, "drawable", &value_drawable );
720 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
721 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
722 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
723 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
724 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
725 var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
727 /* We only wait for NSApp to initialise if we're not embedded (as in the
728 * case of the Mozilla plugin). We can tell whether we're embedded or not
729 * by examining the "drawable" value: if it's zero, we're running in the
730 * main Mac intf; if it's non-zero, we're embedded. */
731 if( value_drawable.i_int == 0 )
733 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
734 for( i_timeout = 20 ; i_timeout-- ; )
738 msleep( INTF_IDLE_SLEEP );
744 /* No MacOS X intf, unable to communicate with MT */
745 msg_Err( p_vout, "no MacOS X interface present" );
750 if ( VLCIntf && !(p_vout->b_fullscreen) &&
751 !(var_GetBool( p_vout, "macosx-background" )) &&
752 var_GetBool( p_vout, "embedded-video") )
754 o_return = [[[VLCMain sharedInstance] getEmbeddedList]
760 /* No embedded vout is available */
761 if( o_return == nil )
764 bzero( &null_rect, sizeof( NSRect ) );
765 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
767 [o_return setVout: p_vout subView: view frame: s_frame];
771 - (void)enterFullscreen
773 /* Save the settings for next playing item */
774 playlist_t * p_playlist = pl_Hold( p_real_vout );
775 var_SetBool( p_playlist, "fullscreen", true );
776 pl_Release( p_real_vout );
779 - (void)leaveFullscreen
781 /* Save the settings for next playing item */
782 playlist_t * p_playlist = pl_Hold( p_real_vout );
783 var_SetBool( p_playlist, "fullscreen", false );
784 pl_Release( p_real_vout );
789 /*****************************************************************************
790 * VLCDetachedVoutView implementation
791 *****************************************************************************/
792 @implementation VLCDetachedVoutView
794 - (id)initWithFrame: (NSRect)frameRect
796 [super initWithFrame: frameRect];
797 i_time_mouse_last_moved = 0;
801 - (BOOL)mouseDownCanMoveWindow
806 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
807 frame: (NSRect *) s_arg_frame
809 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
810 i_time_mouse_last_moved = mdate();
811 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
815 if([self isFullscreen])
816 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
818 [view setFrame: [self frame]];
825 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
826 i_time_mouse_last_moved = 0;
830 - (void)mouseMoved:(NSEvent *)o_event
832 i_time_mouse_last_moved = mdate();
833 [super mouseMoved: o_event];
836 - (void)hideMouse:(BOOL)b_hide
840 NSView *o_contents = [o_window contentView];
842 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
843 ml = [o_contents convertPoint:ml fromView:nil];
844 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
846 if( b_hide && b_inside )
848 [NSCursor setHiddenUntilMouseMoves: YES];
852 [NSCursor setHiddenUntilMouseMoves: NO];
858 /* Dooh, why do we spend processor time doing this kind of stuff? */
860 unsigned int i_mouse_hide_timeout =
861 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
863 if( i_mouse_hide_timeout < 100000 )
864 i_mouse_hide_timeout = 100000;
865 if( p_vout->b_fullscreen )
867 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
869 i_time_mouse_last_moved = mdate();
870 [self hideMouse: YES];
875 [self hideMouse: NO];
880 - (void)enterFullscreen
882 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
883 [super enterFullscreen];
887 - (void)leaveFullscreen
889 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
890 [super leaveFullscreen];
894 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
896 if( p_vout->b_fullscreen )
898 [o_window setMovableByWindowBackground: NO];
899 [super scaleWindowWithFactor: factor animate: animate];
900 [o_window setMovableByWindowBackground: YES];
904 /*****************************************************************************
905 * VLCEmbeddedVoutView implementation
906 *****************************************************************************/
908 @implementation VLCEmbeddedVoutView
912 o_embeddedwindow = [self window];
915 - (BOOL)mouseDownCanMoveWindow
920 - (id)initWithFrame: (NSRect)frameRect
922 if(self = [super initWithFrame: frameRect])
925 [[[VLCMain sharedInstance] getEmbeddedList] addEmbeddedVout: self];
926 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
931 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
932 frame: (NSRect *)s_arg_frame
936 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
938 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
941 o_window = [self window];
943 [o_window setAcceptsMouseMovedEvents: TRUE];
945 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
947 [o_window setLevel: NSStatusWindowLevel];
950 [view setFrameSize: [self frame].size];
953 /* o_window needs to point to our o_embeddedwindow, super might have set it
954 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
955 o_window = o_embeddedwindow;
959 [o_window lockFullscreenAnimation];
961 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
965 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
967 /* Make the window the front and key window before animating */
968 if ([o_window isVisible] && (![o_window isFullscreen]))
969 [o_window makeKeyAndOrderFront: self];
971 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
973 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
975 /* Make sure our window is visible, if we are not in fullscreen */
976 if (![o_window isFullscreen])
977 [o_window makeKeyAndOrderFront: self];
978 [o_window unlockFullscreenAnimation];
985 - (void)setUsed: (BOOL)b_new_used
999 /* Don't close the window yet, wait a bit to see if a new input is poping up */
1000 /* FIXME: Probably fade the window In and Out */
1001 /* FIXME: fix core */
1002 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
1004 [[[VLCMain sharedInstance] getEmbeddedList] releaseEmbeddedVout: self];
1007 - (void)enterFullscreen
1010 [super enterFullscreen];
1012 /* We are in a VLCEmbeddedWindow */
1013 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1016 - (void)leaveFullscreen
1019 [super leaveFullscreen];
1021 /* We are in a VLCEmbeddedWindow */
1022 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1026 /*****************************************************************************
1027 * VLCVoutWindow implementation
1028 *****************************************************************************/
1029 @implementation VLCVoutWindow
1031 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1032 frame: (NSRect *) frame
1038 [self performSelectorOnMainThread: @selector(initMainThread:)
1039 withObject: NULL waitUntilDone: YES];
1041 return b_init_ok ? self : nil;
1044 - (id)initMainThread: (id) sender
1047 rect.size.height = p_vout->i_window_height;
1048 rect.size.width = p_vout->i_window_width;
1049 rect.origin.x = rect.origin.y = 70.;
1051 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1053 [self setBackgroundColor:[NSColor blackColor]];
1054 [self setHasShadow:YES];
1055 [self setMovableByWindowBackground: YES];
1057 [self makeKeyAndOrderFront: self];
1058 [self setReleasedWhenClosed: YES];
1059 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1060 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1062 /* We'll catch mouse events */
1063 [self makeFirstResponder: o_view];
1064 [self setCanBecomeKeyWindow: YES];
1065 [self setAcceptsMouseMovedEvents: YES];
1066 [self setIgnoresMouseEvents: NO];
1068 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1070 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1072 /* Find out on which screen to open the window */
1073 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1074 if( !screen ) screen = [NSScreen mainScreen];
1076 NSRect screen_rect = [screen frame];
1077 screen_rect.origin.x = screen_rect.origin.y = 0;
1079 /* Creates a window with size: screen_rect on o_screen */
1080 [self setFrame: screen_rect display: NO];
1082 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1083 [self setMovableByWindowBackground: NO];
1085 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1087 [self setLevel: NSStatusWindowLevel];
1090 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1092 /* Add the view. It's automatically resized to fit the window */
1093 [self setContentView: o_view];
1100 - (void)enterFullscreen
1102 if( fullscreen ) return;
1108 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1109 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1111 /* Find out on which screen to open the window */
1112 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1113 if( !screen ) screen = [self screen];
1116 [screen blackoutOtherScreens];
1118 [self setMovableByWindowBackground: NO];
1120 if( [screen isMainScreen] )
1121 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1123 initialFrame = [self frame];
1124 [self setFrame:[screen frame] display:YES animate:YES];
1125 [self setLevel:NSNormalWindowLevel];
1127 /* tell the fspanel to move itself to front next time it's triggered */
1128 [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: i_device];
1129 [[[[VLCMain sharedInstance] getControls] getFSPanel] setActive: nil];
1134 - (void)leaveFullscreen
1136 if( !fullscreen ) return;
1139 [NSScreen unblackoutScreens];
1141 [[[[VLCMain sharedInstance] getControls] getFSPanel] setNonActive: nil];
1142 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1143 [self setFrame:initialFrame display:YES animate:YES];
1144 [self setMovableByWindowBackground: YES];
1145 if( var_GetBool( p_vout, "video-on-top" ) )
1146 [self setLevel: NSStatusWindowLevel];