1 /*****************************************************************************
2 * vout.m: MacOS X video output module
3 *****************************************************************************
4 * Copyright (C) 2001-2009 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 /* prevent system sleep */
38 #import <CoreServices/CoreServices.h>
41 #import <CoreServices/../Frameworks/OSServices.framework/Headers/Power.h>
45 #import <Carbon/Carbon.h>
53 #import "embeddedwindow.h"
55 /*****************************************************************************
56 * DeviceCallback: Callback triggered when the video-device variable is changed
57 *****************************************************************************/
58 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
59 vlc_value_t old_val, vlc_value_t new_val, void *param )
62 vout_thread_t *p_vout = (vout_thread_t *)p_this;
64 msg_Dbg( p_vout, "set %d", new_val.i_int );
65 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
66 var_Set( p_vout->p_libvlc, "video-device", new_val );
69 var_Set( p_vout, "intf-change", val );
74 /*****************************************************************************
75 * VLCEmbeddedList implementation
76 *****************************************************************************/
77 @implementation VLCEmbeddedList
82 o_embedded_array = [NSMutableArray array];
90 for( i = 0; i < [o_embedded_array count]; i++ )
92 id o_vout_view = [o_embedded_array objectAtIndex: i];
93 if( ![o_vout_view isUsed] )
95 [o_vout_view setUsed: YES];
102 - (void)releaseEmbeddedVout: (id)o_vout_view
104 if( [o_embedded_array containsObject: o_vout_view] )
106 [o_vout_view setUsed: NO];
110 msg_Warn( VLCIntf, "cannot find Video Output");
114 - (void)addEmbeddedVout: (id)o_vout_view
116 if( ![o_embedded_array containsObject: o_vout_view] )
118 [o_embedded_array addObject: o_vout_view];
122 - (BOOL)windowContainsEmbedded: (id)o_window
124 /* if( ![[o_window className] isEqualToString: @"VLCVoutWindow"] )
126 NSLog( @"We were not given a VLCVoutWindow" );
128 return ([self viewForWindow: o_window] == nil ? NO : YES );
131 - (id)viewForWindow: (id)o_window
133 if( o_embedded_array != nil )
135 id o_enumerator = [o_embedded_array objectEnumerator];
136 id o_current_embedded;
137 if( o_window != nil )
139 while( (o_current_embedded = [o_enumerator nextObject]) )
141 if( [o_current_embedded voutWindow] == o_window )
143 return o_current_embedded;
153 /*****************************************************************************
154 * VLCVoutView implementation
155 *****************************************************************************/
156 @implementation VLCVoutView
158 - (id)initWithFrame: (NSRect)frameRect
160 self = [super initWithFrame: frameRect];
163 s_frame = &frameRect;
170 - (BOOL)setVout: (vout_thread_t *) vout
171 subView: (NSView *) view
172 frame: (NSRect *) frame
175 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
176 NSArray *o_screens = [NSScreen screens];
182 if( [o_screens count] <= 0 )
184 msg_Err( p_vout, "no OSX screens available" );
188 p_real_vout = [VLCVoutView realVout: p_vout];
190 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
191 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
193 i_device = var_GetInteger( p_vout, "macosx-vdev" );
197 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
200 /* Setup the menuitem for the multiple displays. */
201 if( var_Type( p_real_vout, "video-device" ) == 0 )
204 vlc_value_t val2, text;
207 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
209 text.psz_string = _("Fullscreen Video Device");
210 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
212 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
215 text.psz_string = _("Default");
216 var_Change( p_real_vout, "video-device",
217 VLC_VAR_ADDCHOICE, &val2, &text );
218 var_Set( p_real_vout, "video-device", val2 );
220 while( (o_screen = [o_enumerator nextObject]) != NULL )
223 NSRect s_rect = [o_screen frame];
225 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
226 "%s %d (%dx%d)", _("Screen"), i,
227 (int)s_rect.size.width, (int)s_rect.size.height );
229 text.psz_string = psz_temp;
230 val2.i_int = (int)[o_screen displayID];
231 var_Change( p_real_vout, "video-device",
232 VLC_VAR_ADDCHOICE, &val2, &text );
233 if( (int)[o_screen displayID] == i_device )
235 var_Set( p_real_vout, "video-device", val2 );
240 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
244 var_Set( p_real_vout, "intf-change", val2 );
247 /* Add the view. It's automatically resized to fit the window */
248 [self addSubview: o_view];
249 [self setAutoresizesSubviews: YES];
255 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
257 [super resizeSubviewsWithOldSize: oldBoundsSize];
258 [o_view setFrameSize: [self frame].size];
261 - (void)drawRect:(NSRect)rect
263 /* When there is no subview we draw a black background */
265 [[NSColor blackColor] set];
272 [[[[VLCMain sharedInstance] controls] fspanel] fadeOut];
274 /* Make sure we don't see a white flash */
275 [[self voutWindow] disableScreenUpdatesUntilFlush];
276 [o_view removeFromSuperview];
286 NSString * o_title = nil;
287 NSMutableString * o_mrl = nil;
288 input_thread_t * p_input;
291 if( !p_vout ) return;
293 p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT );
295 if( !p_input ) return;
297 input_item_t * p_item = input_GetItem( p_input );
299 psz_title = input_item_GetNowPlaying ( p_item );
301 psz_title = input_item_GetName( p_item );
304 o_title = [NSString stringWithUTF8String: psz_title];
306 char *psz_uri = input_item_GetURI( p_item );
308 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
318 /* FIXME once psz_access is exported, we could check if we are
319 * reading from a file in a smarter way. */
321 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
322 if( prefix_range.location != NSNotFound )
323 [o_mrl deleteCharactersInRange: prefix_range];
325 if( [o_mrl characterAtIndex:0] == '/' )
327 /* it's a local file */
328 [o_window setRepresentedFilename: o_mrl];
332 /* it's from the network or somewhere else,
333 * we clear the previous path */
334 [o_window setRepresentedFilename: @""];
336 [o_window setTitle: o_title];
340 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
342 vlc_object_release( p_input );
345 - (void)setOnTop:(BOOL)b_on_top
349 [o_window setLevel: NSStatusWindowLevel];
353 [o_window setLevel: NSNormalWindowLevel];
357 - (NSSize)voutSizeForFactor: (float)factor
359 int i_corrected_height, i_corrected_width;
362 if( p_vout->render.i_height * p_vout->render.i_aspect >
363 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
365 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
367 newsize.width = (int) ( i_corrected_width * factor );
368 newsize.height = (int) ( p_vout->render.i_height * factor );
372 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
373 p_vout->render.i_aspect;
374 newsize.width = (int) ( p_vout->render.i_width * factor );
375 newsize.height = (int) ( i_corrected_height * factor );
381 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
383 if ( !p_vout->b_fullscreen )
387 NSPoint topleftscreen;
391 topleftbase.y = [o_window frame].size.height;
392 topleftscreen = [o_window convertBaseToScreen: topleftbase];
394 newsize = [self voutSizeForFactor:factor];
396 /* In fullscreen mode we need to use a view that is different from
397 * ourselves, with the VLCEmbeddedWindow */
398 if([o_window isKindOfClass:[VLCEmbeddedWindow class]])
399 mainView = [o_window mainView];
403 /* Calculate the window's new size */
404 new_frame.size.width = [o_window frame].size.width -
405 [mainView frame].size.width + newsize.width;
406 new_frame.size.height = [o_window frame].size.height -
407 [mainView frame].size.height + newsize.height;
409 new_frame.origin.x = topleftscreen.x;
410 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
412 [o_window setFrame:new_frame display:animate animate:animate];
413 p_vout->i_changes |= VOUT_SIZE_CHANGE;
417 - (void)toggleFloatOnTop
421 if( !p_real_vout ) return;
422 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
430 var_Set( p_real_vout, "video-on-top", val );
433 - (void)toggleFullscreen
436 if( !p_real_vout ) return;
437 var_Get( p_real_vout, "fullscreen", &val );
438 val.b_bool = !val.b_bool;
439 var_Set( p_real_vout, "fullscreen", val );
445 if( !p_real_vout ) return NO;
446 var_Get( p_real_vout, "fullscreen", &val );
447 return( val.b_bool );
452 var_TriggerCallback( p_real_vout, "video-snapshot" );
457 /* Disable Screensaver, when we're playing something, but allow it on pause */
458 if( !VLCIntf || !VLCIntf->p_sys )
461 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
462 UpdateSystemActivity( UsrActivity );
470 - (void)scrollWheel:(NSEvent *)theEvent
472 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] controls];
473 [o_controls scrollWheel: theEvent];
476 - (void)keyDown:(NSEvent *)o_event
480 unsigned int i_pressed_modifiers = 0;
483 i_pressed_modifiers = [o_event modifierFlags];
485 if( i_pressed_modifiers & NSShiftKeyMask )
486 val.i_int |= KEY_MODIFIER_SHIFT;
487 if( i_pressed_modifiers & NSControlKeyMask )
488 val.i_int |= KEY_MODIFIER_CTRL;
489 if( i_pressed_modifiers & NSAlternateKeyMask )
490 val.i_int |= KEY_MODIFIER_ALT;
491 if( i_pressed_modifiers & NSCommandKeyMask )
492 val.i_int |= KEY_MODIFIER_COMMAND;
494 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
498 /* Escape should always get you out of fullscreen */
499 if( key == (unichar) 0x1b )
501 if( p_real_vout && [self isFullscreen] )
503 [self toggleFullscreen];
509 val.i_int = config_GetInt( p_vout, "key-play-pause" );
511 val.i_int |= (int)CocoaKeyToVLC( key );
512 var_Set( p_vout->p_libvlc, "key-pressed", val );
514 else NSLog( @"Could not send keyevent to VLC core" );
517 [super keyDown: o_event];
520 - (void)mouseDown:(NSEvent *)o_event
525 if( ( [o_event type] == NSLeftMouseDown ) &&
526 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
528 if( [o_event clickCount] <= 1 )
530 /* single clicking */
531 var_Get( p_vout, "mouse-button-down", &val );
533 var_Set( p_vout, "mouse-button-down", val );
537 /* multiple clicking */
538 [self toggleFullscreen];
541 else if( ( [o_event type] == NSRightMouseDown ) ||
542 ( ( [o_event type] == NSLeftMouseDown ) &&
543 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
545 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
546 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
550 [super mouseDown: o_event];
553 - (void)otherMouseDown:(NSEvent *)o_event
557 if( p_vout && [o_event type] == NSOtherMouseDown )
559 var_Get( p_vout, "mouse-button-down", &val );
561 var_Set( p_vout, "mouse-button-down", val );
564 [super mouseDown: o_event];
567 - (void)rightMouseDown:(NSEvent *)o_event
569 if( p_vout && [o_event type] == NSRightMouseDown )
571 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
572 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
575 [super mouseDown: o_event];
578 - (void)mouseUp:(NSEvent *)o_event
582 if( p_vout && [o_event type] == NSLeftMouseUp )
584 var_SetBool( p_vout, "mouse-clicked", true );
586 var_Get( p_vout, "mouse-button-down", &val );
588 var_Set( p_vout, "mouse-button-down", val );
591 [super mouseUp: o_event];
594 - (void)otherMouseUp:(NSEvent *)o_event
598 if( p_vout && [o_event type] == NSOtherMouseUp )
600 var_Get( p_vout, "mouse-button-down", &val );
602 var_Set( p_vout, "mouse-button-down", val );
605 [super mouseUp: o_event];
608 - (void)rightMouseUp:(NSEvent *)o_event
610 if( p_vout && [o_event type] == NSRightMouseUp )
612 /* FIXME: this isn't the appropriate place, but we can't receive
613 * NSRightMouseDown some how */
614 msg_Dbg( p_vout, "received NSRightMouseUp" );
615 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
618 [super mouseUp: o_event];
621 - (void)mouseDragged:(NSEvent *)o_event
623 [self mouseMoved: o_event];
626 - (void)otherMouseDragged:(NSEvent *)o_event
628 [self mouseMoved: o_event];
631 - (void)rightMouseDragged:(NSEvent *)o_event
633 [self mouseMoved: o_event];
636 - (void)mouseMoved:(NSEvent *)o_event
644 s_rect = [o_view bounds];
645 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
646 b_inside = [o_view mouse: ml inRect: s_rect];
651 unsigned int i_width, i_height, i_x, i_y;
653 vout_PlacePicture( p_vout, (unsigned int)s_rect.size.width,
654 (unsigned int)s_rect.size.height,
655 &i_x, &i_y, &i_width, &i_height );
657 val.i_int = ( ((int)ml.x) - i_x ) *
658 p_vout->render.i_width / i_width;
659 var_Set( p_vout, "mouse-x", val );
661 if( [[o_view className] isEqualToString: @"VLCGLView"] )
663 val.i_int = ( ((int)(s_rect.size.height - ml.y)) - i_y ) *
664 p_vout->render.i_height / i_height;
668 val.i_int = ( ((int)ml.y) - i_y ) *
669 p_vout->render.i_height / i_height;
671 var_Set( p_vout, "mouse-y", val );
674 var_Set( p_vout, "mouse-moved", val );
676 if( [self isFullscreen] )
677 [[[[VLCMain sharedInstance] controls] fspanel] fadeIn];
680 [super mouseMoved: o_event];
683 - (BOOL)acceptsFirstResponder
688 - (BOOL)becomeFirstResponder
693 - (BOOL)resignFirstResponder
695 /* We need to stay the first responder or we'll miss some
700 /* Class methods used by the different vout modules */
702 + (vout_thread_t *)realVout: (vout_thread_t *)p_vout
704 /* p_real_vout: the vout we have to use to check for video-on-top
705 and a few other things. If we are the QuickTime output, it's us.
706 It we are the OpenGL provider, it is our parent.
707 Since we can't be the QuickTime output anymore, we need to be
709 FIXME: check with the caca and x11 vouts! */
710 return (vout_thread_t *) p_vout->p_parent;
713 + (id)voutView: (vout_thread_t *)p_vout subView: (NSView *)view
714 frame: (NSRect *)s_frame
720 i_drawable_gl = var_GetInteger( p_vout->p_libvlc, "drawable-gl" );
722 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
723 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
724 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
725 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
726 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
727 var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
729 /* We only wait for NSApp to initialise if we're not embedded (as in the
730 * case of the Mozilla plugin). We can tell whether we're embedded or not
731 * by examining the "drawable-gl" value: if it's zero, we're running in the
732 * main Mac intf; if it's non-zero, we're embedded. */
733 if( i_drawable_gl == 0 )
735 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
736 for( i_timeout = 20 ; i_timeout-- ; )
740 msleep( INTF_IDLE_SLEEP );
746 /* No MacOS X intf, unable to communicate with MT */
747 msg_Err( p_vout, "no MacOS X interface present" );
752 if ( VLCIntf && !(p_vout->b_fullscreen) &&
753 !(var_GetBool( p_vout, "macosx-background" )) &&
754 var_GetBool( p_vout, "embedded-video") )
756 o_return = [[[VLCMain sharedInstance] embeddedList] embeddedVout];
761 /* No embedded vout is available */
762 if( o_return == nil )
765 bzero( &null_rect, sizeof( NSRect ) );
766 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
768 [o_return setVout: p_vout subView: view frame: s_frame];
772 - (void)enterFullscreen
774 /* Save the settings for next playing item */
775 playlist_t * p_playlist = pl_Hold( p_real_vout );
776 var_SetBool( p_playlist, "fullscreen", true );
777 pl_Release( p_real_vout );
780 - (void)leaveFullscreen
782 /* Save the settings for next playing item */
783 playlist_t * p_playlist = pl_Hold( p_real_vout );
784 var_SetBool( p_playlist, "fullscreen", false );
785 pl_Release( p_real_vout );
790 /*****************************************************************************
791 * VLCDetachedVoutView implementation
792 *****************************************************************************/
793 @implementation VLCDetachedVoutView
795 - (id)initWithFrame: (NSRect)frameRect
797 [super initWithFrame: frameRect];
798 i_time_mouse_last_moved = 0;
802 - (BOOL)mouseDownCanMoveWindow
807 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
808 frame: (NSRect *) s_arg_frame
810 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
811 i_time_mouse_last_moved = mdate();
812 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
816 if([self isFullscreen])
817 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
819 [view setFrame: [self frame]];
826 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
827 i_time_mouse_last_moved = 0;
831 - (void)mouseMoved:(NSEvent *)o_event
833 i_time_mouse_last_moved = mdate();
834 [super mouseMoved: o_event];
837 - (void)hideMouse:(BOOL)b_hide
841 NSView *o_contents = [o_window contentView];
843 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
844 ml = [o_contents convertPoint:ml fromView:nil];
845 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
847 if( b_hide && b_inside )
849 [NSCursor setHiddenUntilMouseMoves: YES];
853 [NSCursor setHiddenUntilMouseMoves: NO];
859 /* Dooh, why do we spend processor time doing this kind of stuff? */
861 unsigned int i_mouse_hide_timeout =
862 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
864 if( i_mouse_hide_timeout < 100000 )
865 i_mouse_hide_timeout = 100000;
866 if( p_vout->b_fullscreen )
868 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
870 i_time_mouse_last_moved = mdate();
871 [self hideMouse: YES];
876 [self hideMouse: NO];
881 - (void)enterFullscreen
883 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
884 [super enterFullscreen];
888 - (void)leaveFullscreen
890 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
891 [super leaveFullscreen];
895 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
897 if( p_vout->b_fullscreen )
899 [o_window setMovableByWindowBackground: NO];
900 [super scaleWindowWithFactor: factor animate: animate];
901 [o_window setMovableByWindowBackground: YES];
905 /*****************************************************************************
906 * VLCEmbeddedVoutView implementation
907 *****************************************************************************/
909 @implementation VLCEmbeddedVoutView
913 o_embeddedwindow = [self window];
916 - (BOOL)mouseDownCanMoveWindow
921 - (id)initWithFrame: (NSRect)frameRect
923 if(self = [super initWithFrame: frameRect])
926 [[[VLCMain sharedInstance] embeddedList] addEmbeddedVout: self];
927 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
932 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
933 frame: (NSRect *)s_arg_frame
937 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
939 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
942 o_window = [self window];
944 [o_window setAcceptsMouseMovedEvents: TRUE];
946 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
948 [o_window setLevel: NSStatusWindowLevel];
951 [view setFrameSize: [self frame].size];
954 /* o_window needs to point to our o_embeddedwindow, super might have set it
955 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
956 o_window = o_embeddedwindow;
960 [o_window lockFullscreenAnimation];
962 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
966 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
968 /* Make the window the front and key window before animating */
969 if ([o_window isVisible] && (![o_window isFullscreen]))
970 [o_window makeKeyAndOrderFront: self];
972 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
974 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
976 /* Make sure our window is visible, if we are not in fullscreen */
977 if (![o_window isFullscreen])
978 [o_window makeKeyAndOrderFront: self];
979 [o_window unlockFullscreenAnimation];
986 - (void)setUsed: (BOOL)b_new_used
1000 /* Don't close the window yet, wait a bit to see if a new input is poping up */
1001 /* FIXME: Probably fade the window In and Out */
1002 /* FIXME: fix core */
1003 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
1005 [[[VLCMain sharedInstance] embeddedList] releaseEmbeddedVout: self];
1008 - (void)enterFullscreen
1011 [super enterFullscreen];
1013 /* We are in a VLCEmbeddedWindow */
1014 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1017 - (void)leaveFullscreen
1020 [super leaveFullscreen];
1022 /* We are in a VLCEmbeddedWindow */
1023 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1027 /*****************************************************************************
1028 * VLCVoutWindow implementation
1029 *****************************************************************************/
1030 @implementation VLCVoutWindow
1032 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1033 frame: (NSRect *) frame
1039 [self performSelectorOnMainThread: @selector(initMainThread:)
1040 withObject: NULL waitUntilDone: YES];
1042 return b_init_ok ? self : nil;
1045 - (id)initMainThread: (id) sender
1048 rect.size.height = p_vout->i_window_height;
1049 rect.size.width = p_vout->i_window_width;
1050 rect.origin.x = rect.origin.y = 70.;
1052 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1054 [self setBackgroundColor:[NSColor blackColor]];
1055 [self setHasShadow:YES];
1056 [self setMovableByWindowBackground: YES];
1058 [self makeKeyAndOrderFront: self];
1059 [self setReleasedWhenClosed: YES];
1060 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1061 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1063 /* We'll catch mouse events */
1064 [self makeFirstResponder: o_view];
1065 [self setCanBecomeKeyWindow: YES];
1066 [self setAcceptsMouseMovedEvents: YES];
1067 [self setIgnoresMouseEvents: NO];
1069 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1071 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1073 /* Find out on which screen to open the window */
1074 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1075 if( !screen ) screen = [NSScreen mainScreen];
1077 NSRect screen_rect = [screen frame];
1078 screen_rect.origin.x = screen_rect.origin.y = 0;
1080 /* Creates a window with size: screen_rect on o_screen */
1081 [self setFrame: screen_rect display: NO];
1083 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1084 [self setMovableByWindowBackground: NO];
1086 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1088 [self setLevel: NSStatusWindowLevel];
1091 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1093 /* Add the view. It's automatically resized to fit the window */
1094 [self setContentView: o_view];
1101 - (void)enterFullscreen
1103 if( fullscreen ) return;
1109 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1110 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1112 /* Find out on which screen to open the window */
1113 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1114 if( !screen ) screen = [self screen];
1117 [screen blackoutOtherScreens];
1119 [self setMovableByWindowBackground: NO];
1121 if( [screen isMainScreen] )
1122 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1124 initialFrame = [self frame];
1125 [self setFrame:[screen frame] display:YES animate:YES];
1126 [self setLevel:NSNormalWindowLevel];
1128 /* tell the fspanel to move itself to front next time it's triggered */
1129 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: i_device];
1130 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
1135 - (void)leaveFullscreen
1137 if( !fullscreen ) return;
1140 [NSScreen unblackoutScreens];
1142 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
1143 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1145 [self setFrame:initialFrame display:YES animate:YES];
1146 [self setMovableByWindowBackground: YES];
1147 if( var_GetBool( p_vout, "video-on-top" ) )
1148 [self setLevel: NSStatusWindowLevel];