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>
46 #import "embeddedwindow.h"
48 /*****************************************************************************
49 * DeviceCallback: Callback triggered when the video-device variable is changed
50 *****************************************************************************/
51 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
52 vlc_value_t old_val, vlc_value_t new_val, void *param )
55 vout_thread_t *p_vout = (vout_thread_t *)p_this;
57 msg_Dbg( p_vout, "set %d", new_val.i_int );
58 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
59 var_Set( p_vout->p_libvlc, "video-device", new_val );
62 var_Set( p_vout, "intf-change", val );
67 /*****************************************************************************
68 * VLCEmbeddedList implementation
69 *****************************************************************************/
70 @implementation VLCEmbeddedList
75 o_embedded_array = [NSMutableArray array];
83 for( i = 0; i < [o_embedded_array count]; i++ )
85 id o_vout_view = [o_embedded_array objectAtIndex: i];
86 if( ![o_vout_view isUsed] )
88 [o_vout_view setUsed: YES];
95 - (void)releaseEmbeddedVout: (id)o_vout_view
97 if( [o_embedded_array containsObject: o_vout_view] )
99 [o_vout_view setUsed: NO];
103 msg_Warn( VLCIntf, "cannot find Video Output");
107 - (void)addEmbeddedVout: (id)o_vout_view
109 if( ![o_embedded_array containsObject: o_vout_view] )
111 [o_embedded_array addObject: o_vout_view];
115 - (BOOL)windowContainsEmbedded: (id)o_window
117 /* if( ![[o_window className] isEqualToString: @"VLCVoutWindow"] )
119 NSLog( @"We were not given a VLCVoutWindow" );
121 return ([self getViewForWindow: o_window] == nil ? NO : YES );
124 - (id)getViewForWindow: (id)o_window
126 id o_enumerator = [o_embedded_array objectEnumerator];
127 id o_current_embedded;
129 while( (o_current_embedded = [o_enumerator nextObject]) )
131 if( [o_current_embedded getWindow] == o_window )
133 return o_current_embedded;
141 /*****************************************************************************
142 * VLCVoutView implementation
143 *****************************************************************************/
144 @implementation VLCVoutView
146 - (id)initWithFrame: (NSRect)frameRect
148 self = [super initWithFrame: frameRect];
151 s_frame = &frameRect;
158 - (BOOL)setVout: (vout_thread_t *) vout
159 subView: (NSView *) view
160 frame: (NSRect *) frame
163 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
164 NSArray *o_screens = [NSScreen screens];
170 if( [o_screens count] <= 0 )
172 msg_Err( p_vout, "no OSX screens available" );
176 p_real_vout = [VLCVoutView getRealVout: p_vout];
178 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
179 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
181 i_device = var_GetInteger( p_vout, "macosx-vdev" );
185 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
188 /* Setup the menuitem for the multiple displays. */
189 if( var_Type( p_real_vout, "video-device" ) == 0 )
192 vlc_value_t val2, text;
195 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
197 text.psz_string = _("Fullscreen Video Device");
198 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
200 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
203 text.psz_string = _("Default");
204 var_Change( p_real_vout, "video-device",
205 VLC_VAR_ADDCHOICE, &val2, &text );
206 var_Set( p_real_vout, "video-device", val2 );
208 while( (o_screen = [o_enumerator nextObject]) != NULL )
211 NSRect s_rect = [o_screen frame];
213 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
214 "%s %d (%dx%d)", _("Screen"), i,
215 (int)s_rect.size.width, (int)s_rect.size.height );
217 text.psz_string = psz_temp;
218 val2.i_int = (int)[o_screen displayID];
219 var_Change( p_real_vout, "video-device",
220 VLC_VAR_ADDCHOICE, &val2, &text );
221 if( (int)[o_screen displayID] == i_device )
223 var_Set( p_real_vout, "video-device", val2 );
228 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
232 var_Set( p_real_vout, "intf-change", val2 );
235 /* Add the view. It's automatically resized to fit the window */
236 [self addSubview: o_view];
237 [self setAutoresizesSubviews: YES];
243 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
245 [super resizeSubviewsWithOldSize: oldBoundsSize];
246 [o_view setFrameSize: [self frame].size];
249 - (void)drawRect:(NSRect)rect
251 /* When there is no subview we draw a black background */
253 [[NSColor blackColor] set];
260 [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeOut];
262 /* Make sure we don't see a white flash */
263 [[self window] disableScreenUpdatesUntilFlush];
264 [o_view removeFromSuperview];
274 NSString * o_title = nil;
275 NSMutableString * o_mrl = nil;
276 input_thread_t * p_input;
279 if( !p_vout ) return;
281 p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT );
283 if( !p_input ) return;
285 input_item_t * p_item = input_GetItem( p_input );
287 psz_title = input_item_GetNowPlaying ( p_item );
289 psz_title = input_item_GetName( p_item );
292 o_title = [NSString stringWithUTF8String: psz_title];
294 char *psz_uri = input_item_GetURI( p_item );
296 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
306 /* FIXME once psz_access is exported, we could check if we are
307 * reading from a file in a smarter way. */
309 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
310 if( prefix_range.location != NSNotFound )
311 [o_mrl deleteCharactersInRange: prefix_range];
313 if( [o_mrl characterAtIndex:0] == '/' )
315 /* it's a local file */
316 [o_window setRepresentedFilename: o_mrl];
320 /* it's from the network or somewhere else,
321 * we clear the previous path */
322 [o_window setRepresentedFilename: @""];
324 [o_window setTitle: o_title];
328 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
330 vlc_object_release( p_input );
334 - (void)setOnTop:(BOOL)b_on_top
338 [o_window setLevel: NSStatusWindowLevel];
342 [o_window setLevel: NSNormalWindowLevel];
346 - (NSSize)voutSizeForFactor: (float)factor
348 int i_corrected_height, i_corrected_width;
351 if( p_vout->render.i_height * p_vout->render.i_aspect >
352 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
354 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
356 newsize.width = (int) ( i_corrected_width * factor );
357 newsize.height = (int) ( p_vout->render.i_height * factor );
361 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
362 p_vout->render.i_aspect;
363 newsize.width = (int) ( p_vout->render.i_width * factor );
364 newsize.height = (int) ( i_corrected_height * factor );
370 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
372 if ( !p_vout->b_fullscreen )
376 NSPoint topleftscreen;
380 topleftbase.y = [o_window frame].size.height;
381 topleftscreen = [o_window convertBaseToScreen: topleftbase];
383 newsize = [self voutSizeForFactor:factor];
385 /* In fullscreen mode we need to use a view that is different from
386 * ourselves, with the VLCEmbeddedWindow */
387 if([o_window isKindOfClass:[VLCEmbeddedWindow class]])
388 mainView = [o_window mainView];
392 /* Calculate the window's new size */
393 new_frame.size.width = [o_window frame].size.width -
394 [mainView frame].size.width + newsize.width;
395 new_frame.size.height = [o_window frame].size.height -
396 [mainView frame].size.height + newsize.height;
398 new_frame.origin.x = topleftscreen.x;
399 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
401 [o_window setFrame:new_frame display:animate animate:animate];
402 p_vout->i_changes |= VOUT_SIZE_CHANGE;
406 - (void)toggleFloatOnTop
410 if( !p_real_vout ) return;
411 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
419 var_Set( p_real_vout, "video-on-top", val );
422 - (void)toggleFullscreen
425 if( !p_real_vout ) return;
426 var_Get( p_real_vout, "fullscreen", &val );
427 val.b_bool = !val.b_bool;
428 var_Set( p_real_vout, "fullscreen", val );
434 if( !p_real_vout ) return NO;
435 var_Get( p_real_vout, "fullscreen", &val );
436 return( val.b_bool );
441 vout_Control( p_real_vout, VOUT_SNAPSHOT );
446 /* Disable Screensaver, when we're playing something, but allow it on pause */
447 if( !VLCIntf || !VLCIntf->p_sys )
450 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
451 UpdateSystemActivity( UsrActivity );
459 - (void)scrollWheel:(NSEvent *)theEvent
461 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] getControls];
462 [o_controls scrollWheel: theEvent];
465 - (void)keyDown:(NSEvent *)o_event
469 unsigned int i_pressed_modifiers = 0;
472 i_pressed_modifiers = [o_event modifierFlags];
474 if( i_pressed_modifiers & NSShiftKeyMask )
475 val.i_int |= KEY_MODIFIER_SHIFT;
476 if( i_pressed_modifiers & NSControlKeyMask )
477 val.i_int |= KEY_MODIFIER_CTRL;
478 if( i_pressed_modifiers & NSAlternateKeyMask )
479 val.i_int |= KEY_MODIFIER_ALT;
480 if( i_pressed_modifiers & NSCommandKeyMask )
481 val.i_int |= KEY_MODIFIER_COMMAND;
483 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
487 /* Escape should always get you out of fullscreen */
488 if( key == (unichar) 0x1b )
490 if( p_real_vout && [self isFullscreen] )
492 [self toggleFullscreen];
498 val.i_int = config_GetInt( p_vout, "key-play-pause" );
500 val.i_int |= (int)CocoaKeyToVLC( key );
501 var_Set( p_vout->p_libvlc, "key-pressed", val );
503 else NSLog( @"Could not send keyevent to VLC core" );
506 [super keyDown: o_event];
509 - (void)mouseDown:(NSEvent *)o_event
514 if( ( [o_event type] == NSLeftMouseDown ) &&
515 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
517 if( [o_event clickCount] <= 1 )
519 /* single clicking */
520 var_Get( p_vout, "mouse-button-down", &val );
522 var_Set( p_vout, "mouse-button-down", val );
526 /* multiple clicking */
527 [self toggleFullscreen];
530 else if( ( [o_event type] == NSRightMouseDown ) ||
531 ( ( [o_event type] == NSLeftMouseDown ) &&
532 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
534 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
535 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]];
539 [super mouseDown: o_event];
542 - (void)otherMouseDown:(NSEvent *)o_event
546 if( p_vout && [o_event type] == NSOtherMouseDown )
548 var_Get( p_vout, "mouse-button-down", &val );
550 var_Set( p_vout, "mouse-button-down", val );
553 [super mouseDown: o_event];
556 - (void)rightMouseDown:(NSEvent *)o_event
558 if( p_vout && [o_event type] == NSRightMouseDown )
560 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
561 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]];
564 [super mouseDown: o_event];
567 - (void)mouseUp:(NSEvent *)o_event
571 if( p_vout && [o_event type] == NSLeftMouseUp )
575 var_Set( p_vout, "mouse-clicked", b_val );
577 var_Get( p_vout, "mouse-button-down", &val );
579 var_Set( p_vout, "mouse-button-down", val );
582 [super mouseUp: o_event];
585 - (void)otherMouseUp:(NSEvent *)o_event
589 if( p_vout && [o_event type] == NSOtherMouseUp )
591 var_Get( p_vout, "mouse-button-down", &val );
593 var_Set( p_vout, "mouse-button-down", val );
596 [super mouseUp: o_event];
599 - (void)rightMouseUp:(NSEvent *)o_event
601 if( p_vout && [o_event type] == NSRightMouseUp )
603 /* FIXME: this isn't the appropriate place, but we can't receive
604 * NSRightMouseDown some how */
605 msg_Dbg( p_vout, "received NSRightMouseUp" );
606 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]];
609 [super mouseUp: o_event];
612 - (void)mouseDragged:(NSEvent *)o_event
614 [self mouseMoved: o_event];
617 - (void)otherMouseDragged:(NSEvent *)o_event
619 [self mouseMoved: o_event];
622 - (void)rightMouseDragged:(NSEvent *)o_event
624 [self mouseMoved: o_event];
627 - (void)mouseMoved:(NSEvent *)o_event
635 s_rect = [o_view bounds];
636 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
637 b_inside = [o_view mouse: ml inRect: s_rect];
642 unsigned int i_width, i_height, i_x, i_y;
644 vout_PlacePicture( p_vout, (unsigned int)s_rect.size.width,
645 (unsigned int)s_rect.size.height,
646 &i_x, &i_y, &i_width, &i_height );
648 val.i_int = ( ((int)ml.x) - i_x ) *
649 p_vout->render.i_width / i_width;
650 var_Set( p_vout, "mouse-x", val );
652 if( [[o_view className] isEqualToString: @"VLCGLView"] )
654 val.i_int = ( ((int)(s_rect.size.height - ml.y)) - i_y ) *
655 p_vout->render.i_height / i_height;
659 val.i_int = ( ((int)ml.y) - i_y ) *
660 p_vout->render.i_height / i_height;
662 var_Set( p_vout, "mouse-y", val );
665 var_Set( p_vout, "mouse-moved", val );
667 if( [self isFullscreen] )
668 [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeIn];
671 [super mouseMoved: o_event];
674 - (BOOL)acceptsFirstResponder
679 - (BOOL)becomeFirstResponder
684 - (BOOL)resignFirstResponder
686 /* We need to stay the first responder or we'll miss some
691 /* Class methods used by the different vout modules */
693 + (vout_thread_t *)getRealVout: (vout_thread_t *)p_vout
695 /* p_real_vout: the vout we have to use to check for video-on-top
696 and a few other things. If we are the QuickTime output, it's us.
697 It we are the OpenGL provider, it is our parent.
698 Since we can't be the QuickTime output anymore, we need to be
700 FIXME: check with the caca and x11 vouts! */
701 return (vout_thread_t *) p_vout->p_parent;
704 + (id)getVoutView: (vout_thread_t *)p_vout subView: (NSView *)view
705 frame: (NSRect *)s_frame
707 vlc_value_t value_drawable;
711 var_Get( p_vout->p_libvlc, "drawable", &value_drawable );
713 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
714 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
715 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
716 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
717 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
718 var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
720 /* We only wait for NSApp to initialise if we're not embedded (as in the
721 * case of the Mozilla plugin). We can tell whether we're embedded or not
722 * by examining the "drawable" value: if it's zero, we're running in the
723 * main Mac intf; if it's non-zero, we're embedded. */
724 if( value_drawable.i_int == 0 )
726 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
727 for( i_timeout = 20 ; i_timeout-- ; )
731 msleep( INTF_IDLE_SLEEP );
737 /* No MacOS X intf, unable to communicate with MT */
738 msg_Err( p_vout, "no MacOS X interface present" );
743 if ( VLCIntf && !(p_vout->b_fullscreen) &&
744 !(var_GetBool( p_vout, "macosx-background" )) &&
745 var_GetBool( p_vout, "embedded-video") )
747 o_return = [[[VLCMain sharedInstance] getEmbeddedList]
753 /* No embedded vout is available */
754 if( o_return == nil )
757 bzero( &null_rect, sizeof( NSRect ) );
758 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
760 [o_return setVout: p_vout subView: view frame: s_frame];
764 - (void)enterFullscreen
766 /* Save the settings for next playing item */
767 playlist_t * p_playlist = pl_Hold( p_real_vout );
768 var_SetBool( p_playlist, "fullscreen", true );
769 pl_Release( p_real_vout );
772 - (void)leaveFullscreen
774 /* Save the settings for next playing item */
775 playlist_t * p_playlist = pl_Hold( p_real_vout );
776 var_SetBool( p_playlist, "fullscreen", false );
777 pl_Release( p_real_vout );
782 /*****************************************************************************
783 * VLCDetachedVoutView implementation
784 *****************************************************************************/
785 @implementation VLCDetachedVoutView
787 - (id)initWithFrame: (NSRect)frameRect
789 [super initWithFrame: frameRect];
790 i_time_mouse_last_moved = 0;
794 - (BOOL)mouseDownCanMoveWindow
799 - (bool)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
800 frame: (NSRect *) s_arg_frame
802 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
803 i_time_mouse_last_moved = mdate();
804 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
808 if([self isFullscreen])
809 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
811 [view setFrame: [self frame]];
818 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
819 i_time_mouse_last_moved = 0;
823 - (void)mouseMoved:(NSEvent *)o_event
825 i_time_mouse_last_moved = mdate();
826 [super mouseMoved: o_event];
829 - (void)hideMouse:(BOOL)b_hide
833 NSView *o_contents = [o_window contentView];
835 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
836 ml = [o_contents convertPoint:ml fromView:nil];
837 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
839 if( b_hide && b_inside )
841 [NSCursor setHiddenUntilMouseMoves: YES];
845 [NSCursor setHiddenUntilMouseMoves: NO];
851 /* Dooh, why do we spend processor time doing this kind of stuff? */
853 unsigned int i_mouse_hide_timeout =
854 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
856 if( i_mouse_hide_timeout < 100000 )
857 i_mouse_hide_timeout = 100000;
858 if( p_vout->b_fullscreen )
860 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
862 i_time_mouse_last_moved = mdate();
863 [self hideMouse: YES];
868 [self hideMouse: NO];
873 - (void)enterFullscreen
875 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
876 [super enterFullscreen];
880 - (void)leaveFullscreen
882 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
883 [super leaveFullscreen];
887 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
889 if( p_vout->b_fullscreen )
891 [o_window setMovableByWindowBackground: NO];
892 [super scaleWindowWithFactor: factor animate: animate];
893 [o_window setMovableByWindowBackground: YES];
897 /*****************************************************************************
898 * VLCEmbeddedVoutView implementation
899 *****************************************************************************/
901 @implementation VLCEmbeddedVoutView
905 o_embeddedwindow = [self window];
908 - (BOOL)mouseDownCanMoveWindow
913 - (id)initWithFrame: (NSRect)frameRect
915 if(self = [super initWithFrame: frameRect])
918 [[[VLCMain sharedInstance] getEmbeddedList] addEmbeddedVout: self];
919 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
924 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
925 frame: (NSRect *)s_arg_frame
929 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
931 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
934 o_window = [self window];
936 [o_window setAcceptsMouseMovedEvents: TRUE];
938 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
940 [o_window setLevel: NSStatusWindowLevel];
943 [view setFrameSize: [self frame].size];
946 /* o_window needs to point to our o_embeddedwindow, super might have set it
947 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
948 o_window = o_embeddedwindow;
952 [o_window lockFullscreenAnimation];
954 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
958 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
960 /* Make the window the front and key window before animating */
961 if ([o_window isVisible] && (![o_window isFullscreen]))
962 [o_window makeKeyAndOrderFront: self];
964 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
966 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
968 /* Make sure our window is visible, if we are not in fullscreen */
969 if (![o_window isFullscreen])
970 [o_window makeKeyAndOrderFront: self];
971 [o_window unlockFullscreenAnimation];
978 - (void)setUsed: (BOOL)b_new_used
992 /* Don't close the window yet, wait a bit to see if a new input is poping up */
993 /* FIXME: Probably fade the window In and Out */
994 /* FIXME: fix core */
995 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
997 [[[VLCMain sharedInstance] getEmbeddedList] releaseEmbeddedVout: self];
1000 - (void)enterFullscreen
1003 [super enterFullscreen];
1005 /* We are in a VLCEmbeddedWindow */
1006 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1009 - (void)leaveFullscreen
1012 [super leaveFullscreen];
1014 /* We are in a VLCEmbeddedWindow */
1015 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1019 /*****************************************************************************
1020 * VLCVoutWindow implementation
1021 *****************************************************************************/
1022 @implementation VLCVoutWindow
1024 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1025 frame: (NSRect *) frame
1031 [self performSelectorOnMainThread: @selector(initMainThread:)
1032 withObject: NULL waitUntilDone: YES];
1034 return b_init_ok ? self : nil;
1037 - (id)initMainThread: (id) sender
1040 rect.size.height = p_vout->i_window_height;
1041 rect.size.width = p_vout->i_window_width;
1042 rect.origin.x = rect.origin.y = 70.;
1044 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1046 [self setBackgroundColor:[NSColor blackColor]];
1047 [self setHasShadow:YES];
1048 [self setMovableByWindowBackground: YES];
1050 [self makeKeyAndOrderFront: self];
1051 [self setReleasedWhenClosed: YES];
1052 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1053 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1055 /* We'll catch mouse events */
1056 [self makeFirstResponder: o_view];
1057 [self setCanBecomeKeyWindow: YES];
1058 [self setAcceptsMouseMovedEvents: YES];
1059 [self setIgnoresMouseEvents: NO];
1061 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1063 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1065 /* Find out on which screen to open the window */
1066 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1067 if( !screen ) screen = [NSScreen mainScreen];
1069 NSRect screen_rect = [screen frame];
1070 screen_rect.origin.x = screen_rect.origin.y = 0;
1072 /* Creates a window with size: screen_rect on o_screen */
1073 [self setFrame: screen_rect display: NO];
1075 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1076 [self setMovableByWindowBackground: NO];
1078 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1080 [self setLevel: NSStatusWindowLevel];
1083 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1085 /* Add the view. It's automatically resized to fit the window */
1086 [self setContentView: o_view];
1093 - (void)enterFullscreen
1095 if( fullscreen ) return;
1101 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1102 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1104 /* Find out on which screen to open the window */
1105 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1106 if( !screen ) screen = [self screen];
1109 [screen blackoutOtherScreens];
1111 [self setMovableByWindowBackground: NO];
1113 if( [screen isMainScreen] )
1114 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1116 initialFrame = [self frame];
1117 [self setFrame:[screen frame] display:YES animate:YES];
1118 [self setLevel:NSNormalWindowLevel];
1120 /* tell the fspanel to move itself to front next time it's triggered */
1121 [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: i_device];
1122 [[[[VLCMain sharedInstance] getControls] getFSPanel] setActive: nil];
1127 - (void)leaveFullscreen
1129 if( !fullscreen ) return;
1132 [NSScreen unblackoutScreens];
1134 [[[[VLCMain sharedInstance] getControls] getFSPanel] setNonActive: nil];
1135 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1136 [self setFrame:initialFrame display:YES animate:YES];
1137 [self setMovableByWindowBackground: YES];
1138 if( var_GetBool( p_vout, "video-on-top" ) )
1139 [self setLevel: NSStatusWindowLevel];
1142 - (id)getVoutView // FIXME Naming scheme!