1 /*****************************************************************************
2 * vout.m: MacOS X video output module
3 *****************************************************************************
4 * Copyright (C) 2001-2011 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 <stdlib.h> /* free() */
36 /* prevent system sleep */
37 #import <CoreServices/CoreServices.h>
40 #import <CoreServices/../Frameworks/OSServices.framework/Headers/Power.h>
44 #import <Carbon/Carbon.h>
51 #import "embeddedwindow.h"
53 #include <vlc_common.h>
54 #include <vlc_vout_window.h>
55 #include <vlc_vout_display.h>
61 /*****************************************************************************
62 * DeviceCallback: Callback triggered when the video-device variable is changed
63 *****************************************************************************/
64 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
65 vlc_value_t old_val, vlc_value_t new_val, void *param )
68 vout_thread_t *p_vout = (vout_thread_t *)p_this;
70 msg_Dbg( p_vout, "set %"PRId64, new_val.i_int );
71 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
72 var_Set( p_vout->p_libvlc, "video-device", new_val );
75 var_Set( p_vout, "intf-change", val );
80 /*****************************************************************************
81 * VLCEmbeddedList implementation
82 *****************************************************************************/
83 @implementation VLCEmbeddedList
88 o_embedded_array = [NSMutableArray array];
96 for( i = 0; i < [o_embedded_array count]; i++ )
98 id o_vout_view = [o_embedded_array objectAtIndex: i];
99 if( ![o_vout_view isUsed] )
101 [o_vout_view setUsed: YES];
108 - (void)releaseEmbeddedVout: (id)o_vout_view
110 if( [o_embedded_array containsObject: o_vout_view] )
112 [o_vout_view setUsed: NO];
116 msg_Warn( VLCIntf, "cannot find Video Output");
120 - (void)addEmbeddedVout: (id)o_vout_view
122 if( ![o_embedded_array containsObject: o_vout_view] )
124 [o_embedded_array addObject: o_vout_view];
128 - (BOOL)windowContainsEmbedded: (id)o_window
130 return ([self viewForWindow: o_window] == nil ? NO : YES );
133 - (id)viewForWindow: (id)o_window
135 if( o_embedded_array != nil )
137 id o_enumerator = [o_embedded_array objectEnumerator];
138 id o_current_embedded;
139 if( o_window != nil )
141 while( (o_current_embedded = [o_enumerator nextObject]) )
143 if( [o_current_embedded voutWindow] == o_window )
145 return o_current_embedded;
155 /*****************************************************************************
156 * VLCVoutView implementation
157 *****************************************************************************/
158 @implementation VLCVoutView
160 - (id)initWithFrame: (NSRect)frameRect
162 self = [super initWithFrame: frameRect];
165 s_frame = &frameRect;
172 - (BOOL)setVout: (vout_thread_t *) vout
173 subView: (NSView *) view
174 frame: (NSRect *) frame
177 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
178 NSArray *o_screens = [NSScreen screens];
184 if( [o_screens count] <= 0 )
186 msg_Err( VLCIntf, "no OSX screens available" );
190 p_real_vout = [VLCVoutView realVout: p_vout];
192 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
193 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
195 i_device = var_GetInteger( p_vout, "macosx-vdev" );
199 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
202 /* Setup the menuitem for the multiple displays. */
203 if( var_Type( p_real_vout, "video-device" ) == 0 )
206 vlc_value_t val2, text;
209 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
211 text.psz_string = _("Fullscreen Video Device");
212 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
214 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
217 text.psz_string = _("Default");
218 var_Change( p_real_vout, "video-device",
219 VLC_VAR_ADDCHOICE, &val2, &text );
220 var_Set( p_real_vout, "video-device", val2 );
222 while( (o_screen = [o_enumerator nextObject]) != NULL )
225 NSRect s_rect = [o_screen frame];
227 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
228 "%s %d (%dx%d)", _("Screen"), i,
229 (int)s_rect.size.width, (int)s_rect.size.height );
231 text.psz_string = psz_temp;
232 val2.i_int = (int)[o_screen displayID];
233 var_Change( p_real_vout, "video-device",
234 VLC_VAR_ADDCHOICE, &val2, &text );
235 if( (int)[o_screen displayID] == i_device )
237 var_Set( p_real_vout, "video-device", val2 );
242 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
246 var_Set( p_real_vout, "intf-change", val2 );
249 /* Add the view. It's automatically resized to fit the window */
250 [self addSubview: o_view];
251 [self setAutoresizesSubviews: YES];
257 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
259 [super resizeSubviewsWithOldSize: oldBoundsSize];
260 [o_view setFrameSize: [self frame].size];
263 - (void)drawRect:(NSRect)rect
265 /* When there is no subview we draw a black background */
267 [[NSColor blackColor] set];
274 [[[[VLCMain sharedInstance] controls] fspanel] fadeOut];
276 /* Make sure we don't see a white flash */
277 [[self voutWindow] disableScreenUpdatesUntilFlush];
278 [o_view removeFromSuperview];
288 NSString * o_title = nil;
289 NSMutableString * o_mrl = nil;
290 input_thread_t * p_input;
293 if( !p_vout ) return;
295 p_input = getInput();
297 if( !p_input ) return;
299 input_item_t * p_item = input_GetItem( p_input );
301 psz_title = input_item_GetNowPlaying ( p_item );
303 psz_title = input_item_GetName( p_item );
306 o_title = [NSString stringWithUTF8String: psz_title];
308 char *psz_uri = decode_URI( input_item_GetURI( p_item ) );
310 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
320 /* FIXME once psz_access is exported, we could check if we are
321 * reading from a file in a smarter way. */
323 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
324 if( prefix_range.location != NSNotFound )
325 [o_mrl deleteCharactersInRange: prefix_range];
327 if( [o_mrl characterAtIndex:0] == '/' )
329 /* it's a local file */
330 [o_window setRepresentedFilename: o_mrl];
334 /* it's from the network or somewhere else,
335 * we clear the previous path */
336 [o_window setRepresentedFilename: @""];
338 [o_window setTitle: o_title];
342 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
344 vlc_object_release( p_input );
347 - (void)setOnTop:(BOOL)b_on_top
351 [o_window setLevel: NSStatusWindowLevel];
355 [o_window setLevel: NSNormalWindowLevel];
359 - (NSSize)voutSizeForFactor: (float)factor
361 int i_corrected_height, i_corrected_width;
364 if( p_vout->render.i_height * p_vout->render.i_aspect >
365 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
367 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
369 newsize.width = (int) ( i_corrected_width * factor );
370 newsize.height = (int) ( p_vout->render.i_height * factor );
374 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
375 p_vout->render.i_aspect;
376 newsize.width = (int) ( p_vout->render.i_width * factor );
377 newsize.height = (int) ( i_corrected_height * factor );
383 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
385 if ( !p_vout->b_fullscreen )
389 NSPoint topleftscreen;
393 topleftbase.y = [o_window frame].size.height;
394 topleftscreen = [o_window convertBaseToScreen: topleftbase];
396 newsize = [self voutSizeForFactor:factor];
398 /* In fullscreen mode we need to use a view that is different from
399 * ourselves, with the VLCEmbeddedWindow */
400 if([o_window isKindOfClass:[VLCEmbeddedWindow class]])
401 mainView = [o_window mainView];
405 /* Calculate the window's new size */
406 new_frame.size.width = [o_window frame].size.width -
407 [mainView frame].size.width + newsize.width;
408 new_frame.size.height = [o_window frame].size.height -
409 [mainView frame].size.height + newsize.height;
411 new_frame.origin.x = topleftscreen.x;
412 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
414 [o_window setFrame:new_frame display:animate animate:animate];
415 p_vout->i_changes |= VOUT_SIZE_CHANGE;
419 - (void)toggleFloatOnTop
423 if( !p_real_vout ) return;
424 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
432 var_Set( p_real_vout, "video-on-top", val );
435 - (void)toggleFullscreen
438 if( !p_real_vout ) return;
439 var_ToggleBool( p_real_vout, "fullscreen" );
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 msg_Dbg( VLCIntf, "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 )
586 var_GetCoords( p_vout, "mouse-moved", &x, &y );
587 var_SetCoords( p_vout, "mouse-clicked", x, y );
589 var_Get( p_vout, "mouse-button-down", &val );
591 var_Set( p_vout, "mouse-button-down", val );
594 [super mouseUp: o_event];
597 - (void)otherMouseUp:(NSEvent *)o_event
601 if( p_vout && [o_event type] == NSOtherMouseUp )
603 var_Get( p_vout, "mouse-button-down", &val );
605 var_Set( p_vout, "mouse-button-down", val );
608 [super mouseUp: o_event];
611 - (void)rightMouseUp:(NSEvent *)o_event
613 if( p_vout && [o_event type] == NSRightMouseUp )
615 /* FIXME: this isn't the appropriate place, but we can't receive
616 * NSRightMouseDown some how */
617 msg_Dbg( p_vout, "received NSRightMouseUp" );
618 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
621 [super mouseUp: o_event];
624 - (void)mouseDragged:(NSEvent *)o_event
626 [self mouseMoved: o_event];
629 - (void)otherMouseDragged:(NSEvent *)o_event
631 [self mouseMoved: o_event];
634 - (void)rightMouseDragged:(NSEvent *)o_event
636 [self mouseMoved: o_event];
639 - (void)mouseMoved:(NSEvent *)o_event
647 s_rect = [o_view bounds];
648 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
649 b_inside = [o_view mouse: ml inRect: s_rect];
654 unsigned int i_width, i_height, i_x, i_y;
656 vout_PlacePicture( p_vout, (unsigned int)s_rect.size.width,
657 (unsigned int)s_rect.size.height,
658 &i_x, &i_y, &i_width, &i_height );
660 x = (((int)ml.x) - i_x) * p_vout->render.i_width / i_width;
661 if( [[o_view className] isEqualToString: @"VLCGLView"] )
663 y = (((int)(s_rect.size.height - ml.y)) - i_y) *
664 p_vout->render.i_height / i_height;
668 y = (((int)ml.y) - i_y) * p_vout->render.i_height / i_height;
670 var_SetCoords( p_vout, "mouse-moved", x, y );
672 if( self && [self isFullscreen] )
673 [[[[VLCMain sharedInstance] controls] fspanel] fadeIn];
676 [super mouseMoved: o_event];
679 - (BOOL)acceptsFirstResponder
684 - (BOOL)becomeFirstResponder
689 - (BOOL)resignFirstResponder
691 /* We need to stay the first responder or we'll miss some
696 /* Class methods used by the different vout modules */
698 + (vout_thread_t *)realVout: (vout_thread_t *)p_vout
700 /* p_real_vout: the vout we have to use to check for video-on-top
701 and a few other things. If we are the QuickTime output, it's us.
702 It we are the OpenGL provider, it is our parent.
703 Since we can't be the QuickTime output anymore, we need to be
705 FIXME: check with the caca and x11 vouts! */
706 return (vout_thread_t *) p_vout->p_parent;
709 + (id)voutView: (vout_thread_t *)p_vout subView: (NSView *)view
710 frame: (NSRect *)s_frame
716 i_drawable_gl = var_GetInteger( p_vout->p_libvlc, "drawable-gl" );
718 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
719 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
720 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
721 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
722 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
723 var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
725 /* We only wait for NSApp to initialise if we're not embedded (as in the
726 * case of the Mozilla plugin). We can tell whether we're embedded or not
727 * by examining the "drawable-gl" value: if it's zero, we're running in the
728 * main Mac intf; if it's non-zero, we're embedded. */
729 if( i_drawable_gl == 0 )
731 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
732 for( i_timeout = 20 ; i_timeout-- ; )
736 msleep( INTF_IDLE_SLEEP );
742 /* No MacOS X intf, unable to communicate with MT */
743 msg_Err( p_vout, "no MacOS X interface present" );
748 if ( VLCIntf && !(p_vout->b_fullscreen) &&
749 !(var_GetBool( p_vout, "macosx-background" )) &&
750 var_GetBool( p_vout, "embedded-video") )
752 o_return = [[[VLCMain sharedInstance] embeddedList] embeddedVout];
757 /* No embedded vout is available */
758 if( o_return == nil )
761 memset( &null_rect, 0, sizeof( NSRect ) );
762 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
764 [o_return setVout: p_vout subView: view frame: s_frame];
768 - (void)enterFullscreen
770 /* Save the settings for next playing item */
771 playlist_t * p_playlist = pl_Get( p_real_vout );
772 var_SetBool( p_playlist, "fullscreen", true );
775 - (void)leaveFullscreen
777 /* Save the settings for next playing item */
778 playlist_t * p_playlist = pl_Get( p_real_vout );
779 var_SetBool( p_playlist, "fullscreen", false );
784 /*****************************************************************************
785 * VLCDetachedVoutView implementation
786 *****************************************************************************/
787 @implementation VLCDetachedVoutView
789 - (id)initWithFrame: (NSRect)frameRect
791 [super initWithFrame: frameRect];
792 i_time_mouse_last_moved = 0;
796 - (BOOL)mouseDownCanMoveWindow
801 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
802 frame: (NSRect *) s_arg_frame
804 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
805 i_time_mouse_last_moved = mdate();
806 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
810 if([self isFullscreen])
811 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
813 [view setFrame: [self frame]];
820 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
821 i_time_mouse_last_moved = 0;
825 - (void)mouseMoved:(NSEvent *)o_event
827 i_time_mouse_last_moved = mdate();
828 [super mouseMoved: o_event];
831 - (void)hideMouse:(BOOL)b_hide
835 NSView *o_contents = [o_window contentView];
837 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
838 ml = [o_contents convertPoint:ml fromView:nil];
839 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
841 if( b_hide && b_inside )
843 [NSCursor setHiddenUntilMouseMoves: YES];
847 [NSCursor setHiddenUntilMouseMoves: NO];
853 /* Dooh, why do we spend processor time doing this kind of stuff? */
855 unsigned int i_mouse_hide_timeout =
856 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
858 if( i_mouse_hide_timeout < 100000 )
859 i_mouse_hide_timeout = 100000;
860 if( p_vout->b_fullscreen )
862 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
864 i_time_mouse_last_moved = mdate();
865 [self hideMouse: YES];
870 [self hideMouse: NO];
875 - (void)enterFullscreen
877 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
878 [super enterFullscreen];
882 - (void)leaveFullscreen
884 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
885 [super leaveFullscreen];
889 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
891 if( p_vout->b_fullscreen )
893 [o_window setMovableByWindowBackground: NO];
894 [super scaleWindowWithFactor: factor animate: animate];
895 [o_window setMovableByWindowBackground: YES];
899 /*****************************************************************************
900 * VLCEmbeddedVoutView implementation
901 *****************************************************************************/
903 @implementation VLCEmbeddedVoutView
907 o_embeddedwindow = [self window];
910 - (BOOL)mouseDownCanMoveWindow
915 - (id)initWithFrame: (NSRect)frameRect
917 if(self = [super initWithFrame: frameRect])
920 [[[VLCMain sharedInstance] embeddedList] addEmbeddedVout: self];
921 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
926 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
927 frame: (NSRect *)s_arg_frame
931 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
933 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
936 o_window = [self window];
938 [o_window setAcceptsMouseMovedEvents: TRUE];
940 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
942 [o_window setLevel: NSStatusWindowLevel];
945 [view setFrameSize: [self frame].size];
948 /* o_window needs to point to our o_embeddedwindow, super might have set it
949 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
950 o_window = o_embeddedwindow;
954 [o_window lockFullscreenAnimation];
956 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
960 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
962 /* Make the window the front and key window before animating */
963 if ([o_window isVisible] && (![o_window isFullscreen]))
964 [o_window makeKeyAndOrderFront: self];
966 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
968 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
970 /* Make sure our window is visible, if we are not in fullscreen */
971 if (![o_window isFullscreen])
972 [o_window makeKeyAndOrderFront: self];
973 [o_window unlockFullscreenAnimation];
980 - (void)setUsed: (BOOL)b_new_used
994 /* Don't close the window yet, wait a bit to see if a new input is poping up */
995 /* FIXME: Probably fade the window In and Out */
996 /* FIXME: fix core */
997 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
999 [[[VLCMain sharedInstance] embeddedList] releaseEmbeddedVout: self];
1002 - (void)enterFullscreen
1005 [super enterFullscreen];
1007 /* We are in a VLCEmbeddedWindow */
1008 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1011 - (void)leaveFullscreen
1014 [super leaveFullscreen];
1016 /* We are in a VLCEmbeddedWindow */
1017 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1021 /*****************************************************************************
1022 * VLCVoutWindow implementation
1023 *****************************************************************************/
1024 @implementation VLCVoutWindow
1026 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1027 frame: (NSRect *) frame
1033 [self performSelectorOnMainThread: @selector(initMainThread:)
1034 withObject: NULL waitUntilDone: YES];
1036 return b_init_ok ? self : nil;
1039 - (id)initMainThread: (id) sender
1042 rect.size.height = p_vout->i_window_height;
1043 rect.size.width = p_vout->i_window_width;
1044 rect.origin.x = rect.origin.y = 70.;
1046 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1048 [self setBackgroundColor:[NSColor blackColor]];
1049 [self setHasShadow:YES];
1050 [self setMovableByWindowBackground: YES];
1052 [self makeKeyAndOrderFront: self];
1053 [self setReleasedWhenClosed: YES];
1054 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1055 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1057 /* We'll catch mouse events */
1058 [self makeFirstResponder: o_view];
1059 [self setCanBecomeKeyWindow: YES];
1060 [self setAcceptsMouseMovedEvents: YES];
1061 [self setIgnoresMouseEvents: NO];
1063 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1065 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1067 /* Find out on which screen to open the window */
1068 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1069 if( !screen ) screen = [NSScreen mainScreen];
1071 NSRect screen_rect = [screen frame];
1072 screen_rect.origin.x = screen_rect.origin.y = 0;
1074 /* Creates a window with size: screen_rect on o_screen */
1075 [self setFrame: screen_rect display: NO];
1077 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1078 [self setMovableByWindowBackground: NO];
1080 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1082 [self setLevel: NSStatusWindowLevel];
1085 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1087 /* Add the view. It's automatically resized to fit the window */
1088 [self setContentView: o_view];
1095 - (void)enterFullscreen
1097 if( fullscreen ) return;
1103 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1104 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1106 /* Find out on which screen to open the window */
1107 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1108 if( !screen ) screen = [self screen];
1111 [screen blackoutOtherScreens];
1113 [self setMovableByWindowBackground: NO];
1115 if( [screen isMainScreen] )
1116 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1118 initialFrame = [self frame];
1119 [self setFrame:[screen frame] display:YES animate:YES];
1120 [self setLevel:NSNormalWindowLevel];
1122 /* tell the fspanel to move itself to front next time it's triggered */
1123 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: i_device];
1124 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
1129 - (void)leaveFullscreen
1131 if( !fullscreen ) return;
1134 [NSScreen unblackoutScreens];
1136 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
1137 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1139 [self setFrame:initialFrame display:YES animate:YES];
1140 [self setMovableByWindowBackground: YES];
1141 if( var_GetBool( p_vout, "video-on-top" ) )
1142 [self setLevel: NSStatusWindowLevel];