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 <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>
56 /*****************************************************************************
57 * DeviceCallback: Callback triggered when the video-device variable is changed
58 *****************************************************************************/
59 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
60 vlc_value_t old_val, vlc_value_t new_val, void *param )
63 vout_thread_t *p_vout = (vout_thread_t *)p_this;
65 msg_Dbg( p_vout, "set %d", new_val.i_int );
66 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
67 var_Set( p_vout->p_libvlc, "video-device", new_val );
70 var_Set( p_vout, "intf-change", val );
75 /*****************************************************************************
76 * VLCEmbeddedList implementation
77 *****************************************************************************/
78 @implementation VLCEmbeddedList
83 o_embedded_array = [NSMutableArray array];
91 for( i = 0; i < [o_embedded_array count]; i++ )
93 id o_vout_view = [o_embedded_array objectAtIndex: i];
94 if( ![o_vout_view isUsed] )
96 [o_vout_view setUsed: YES];
103 - (void)releaseEmbeddedVout: (id)o_vout_view
105 if( [o_embedded_array containsObject: o_vout_view] )
107 [o_vout_view setUsed: NO];
111 msg_Warn( VLCIntf, "cannot find Video Output");
115 - (void)addEmbeddedVout: (id)o_vout_view
117 if( ![o_embedded_array containsObject: o_vout_view] )
119 [o_embedded_array addObject: o_vout_view];
123 - (BOOL)windowContainsEmbedded: (id)o_window
125 return ([self viewForWindow: o_window] == nil ? NO : YES );
128 - (id)viewForWindow: (id)o_window
130 if( o_embedded_array != nil )
132 id o_enumerator = [o_embedded_array objectEnumerator];
133 id o_current_embedded;
134 if( o_window != nil )
136 while( (o_current_embedded = [o_enumerator nextObject]) )
138 if( [o_current_embedded voutWindow] == o_window )
140 return o_current_embedded;
150 /*****************************************************************************
151 * VLCVoutView implementation
152 *****************************************************************************/
153 @implementation VLCVoutView
155 - (id)initWithFrame: (NSRect)frameRect
157 self = [super initWithFrame: frameRect];
160 s_frame = &frameRect;
167 - (BOOL)setVout: (vout_thread_t *) vout
168 subView: (NSView *) view
169 frame: (NSRect *) frame
172 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
173 NSArray *o_screens = [NSScreen screens];
179 if( [o_screens count] <= 0 )
181 msg_Err( p_vout, "no OSX screens available" );
185 p_real_vout = [VLCVoutView realVout: p_vout];
187 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
188 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
190 i_device = var_GetInteger( p_vout, "macosx-vdev" );
194 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
197 /* Setup the menuitem for the multiple displays. */
198 if( var_Type( p_real_vout, "video-device" ) == 0 )
201 vlc_value_t val2, text;
204 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
206 text.psz_string = _("Fullscreen Video Device");
207 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
209 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
212 text.psz_string = _("Default");
213 var_Change( p_real_vout, "video-device",
214 VLC_VAR_ADDCHOICE, &val2, &text );
215 var_Set( p_real_vout, "video-device", val2 );
217 while( (o_screen = [o_enumerator nextObject]) != NULL )
220 NSRect s_rect = [o_screen frame];
222 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
223 "%s %d (%dx%d)", _("Screen"), i,
224 (int)s_rect.size.width, (int)s_rect.size.height );
226 text.psz_string = psz_temp;
227 val2.i_int = (int)[o_screen displayID];
228 var_Change( p_real_vout, "video-device",
229 VLC_VAR_ADDCHOICE, &val2, &text );
230 if( (int)[o_screen displayID] == i_device )
232 var_Set( p_real_vout, "video-device", val2 );
237 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
241 var_Set( p_real_vout, "intf-change", val2 );
244 /* Add the view. It's automatically resized to fit the window */
245 [self addSubview: o_view];
246 [self setAutoresizesSubviews: YES];
252 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
254 [super resizeSubviewsWithOldSize: oldBoundsSize];
255 [o_view setFrameSize: [self frame].size];
258 - (void)drawRect:(NSRect)rect
260 /* When there is no subview we draw a black background */
262 [[NSColor blackColor] set];
269 [[[[VLCMain sharedInstance] controls] fspanel] fadeOut];
271 /* Make sure we don't see a white flash */
272 [[self voutWindow] disableScreenUpdatesUntilFlush];
273 [o_view removeFromSuperview];
283 NSString * o_title = nil;
284 NSMutableString * o_mrl = nil;
285 input_thread_t * p_input;
288 if( !p_vout ) return;
290 p_input = getInput();
292 if( !p_input ) return;
294 input_item_t * p_item = input_GetItem( p_input );
296 psz_title = input_item_GetNowPlaying ( p_item );
298 psz_title = input_item_GetName( p_item );
301 o_title = [NSString stringWithUTF8String: psz_title];
303 char *psz_uri = input_item_GetURI( p_item );
305 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
315 /* FIXME once psz_access is exported, we could check if we are
316 * reading from a file in a smarter way. */
318 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
319 if( prefix_range.location != NSNotFound )
320 [o_mrl deleteCharactersInRange: prefix_range];
322 if( [o_mrl characterAtIndex:0] == '/' )
324 /* it's a local file */
325 [o_window setRepresentedFilename: o_mrl];
329 /* it's from the network or somewhere else,
330 * we clear the previous path */
331 [o_window setRepresentedFilename: @""];
333 [o_window setTitle: o_title];
337 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
339 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_ToggleBool( p_real_vout, "fullscreen" );
440 if( !p_real_vout ) return NO;
441 var_Get( p_real_vout, "fullscreen", &val );
442 return( val.b_bool );
447 var_TriggerCallback( p_real_vout, "video-snapshot" );
452 /* Disable Screensaver, when we're playing something, but allow it on pause */
453 if( !VLCIntf || !VLCIntf->p_sys )
456 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
457 UpdateSystemActivity( UsrActivity );
465 - (void)scrollWheel:(NSEvent *)theEvent
467 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] controls];
468 [o_controls scrollWheel: theEvent];
471 - (void)keyDown:(NSEvent *)o_event
475 unsigned int i_pressed_modifiers = 0;
478 i_pressed_modifiers = [o_event modifierFlags];
480 if( i_pressed_modifiers & NSShiftKeyMask )
481 val.i_int |= KEY_MODIFIER_SHIFT;
482 if( i_pressed_modifiers & NSControlKeyMask )
483 val.i_int |= KEY_MODIFIER_CTRL;
484 if( i_pressed_modifiers & NSAlternateKeyMask )
485 val.i_int |= KEY_MODIFIER_ALT;
486 if( i_pressed_modifiers & NSCommandKeyMask )
487 val.i_int |= KEY_MODIFIER_COMMAND;
489 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
493 /* Escape should always get you out of fullscreen */
494 if( key == (unichar) 0x1b )
496 if( p_real_vout && [self isFullscreen] )
498 [self toggleFullscreen];
504 val.i_int = config_GetInt( p_vout, "key-play-pause" );
506 val.i_int |= (int)CocoaKeyToVLC( key );
507 var_Set( p_vout->p_libvlc, "key-pressed", val );
509 else msg_Warn( p_vout, "could not send keyevent to VLC core" );
512 [super keyDown: o_event];
515 - (void)mouseDown:(NSEvent *)o_event
520 if( ( [o_event type] == NSLeftMouseDown ) &&
521 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
523 if( [o_event clickCount] <= 1 )
525 /* single clicking */
526 var_Get( p_vout, "mouse-button-down", &val );
528 var_Set( p_vout, "mouse-button-down", val );
532 /* multiple clicking */
533 [self toggleFullscreen];
536 else if( ( [o_event type] == NSRightMouseDown ) ||
537 ( ( [o_event type] == NSLeftMouseDown ) &&
538 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
540 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
541 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
545 [super mouseDown: o_event];
548 - (void)otherMouseDown:(NSEvent *)o_event
552 if( p_vout && [o_event type] == NSOtherMouseDown )
554 var_Get( p_vout, "mouse-button-down", &val );
556 var_Set( p_vout, "mouse-button-down", val );
559 [super mouseDown: o_event];
562 - (void)rightMouseDown:(NSEvent *)o_event
564 if( p_vout && [o_event type] == NSRightMouseDown )
566 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
567 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
570 [super mouseDown: o_event];
573 - (void)mouseUp:(NSEvent *)o_event
577 if( p_vout && [o_event type] == NSLeftMouseUp )
581 var_GetCoords( p_vout, "mouse-moved", &x, &y );
582 var_SetCoords( p_vout, "mouse-clicked", x, y );
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] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] 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 x = (((int)ml.x) - i_x) * p_vout->render.i_width / i_width;
656 if( [[o_view className] isEqualToString: @"VLCGLView"] )
658 y = (((int)(s_rect.size.height - ml.y)) - i_y) *
659 p_vout->render.i_height / i_height;
663 y = (((int)ml.y) - i_y) * p_vout->render.i_height / i_height;
665 var_SetCoords( p_vout, "mouse-moved", x, y );
667 if( [self isFullscreen] )
668 [[[[VLCMain sharedInstance] controls] fspanel] 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 *)realVout: (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)voutView: (vout_thread_t *)p_vout subView: (NSView *)view
705 frame: (NSRect *)s_frame
711 i_drawable_gl = var_GetInteger( p_vout->p_libvlc, "drawable-gl" );
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-gl" value: if it's zero, we're running in the
723 * main Mac intf; if it's non-zero, we're embedded. */
724 if( i_drawable_gl == 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] embeddedList] embeddedVout];
752 /* No embedded vout is available */
753 if( o_return == nil )
756 bzero( &null_rect, sizeof( NSRect ) );
757 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
759 [o_return setVout: p_vout subView: view frame: s_frame];
763 - (void)enterFullscreen
765 /* Save the settings for next playing item */
766 playlist_t * p_playlist = pl_Get( p_real_vout );
767 var_SetBool( p_playlist, "fullscreen", true );
770 - (void)leaveFullscreen
772 /* Save the settings for next playing item */
773 playlist_t * p_playlist = pl_Get( p_real_vout );
774 var_SetBool( p_playlist, "fullscreen", false );
779 /*****************************************************************************
780 * VLCDetachedVoutView implementation
781 *****************************************************************************/
782 @implementation VLCDetachedVoutView
784 - (id)initWithFrame: (NSRect)frameRect
786 [super initWithFrame: frameRect];
787 i_time_mouse_last_moved = 0;
791 - (BOOL)mouseDownCanMoveWindow
796 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
797 frame: (NSRect *) s_arg_frame
799 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
800 i_time_mouse_last_moved = mdate();
801 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
805 if([self isFullscreen])
806 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
808 [view setFrame: [self frame]];
815 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
816 i_time_mouse_last_moved = 0;
820 - (void)mouseMoved:(NSEvent *)o_event
822 i_time_mouse_last_moved = mdate();
823 [super mouseMoved: o_event];
826 - (void)hideMouse:(BOOL)b_hide
830 NSView *o_contents = [o_window contentView];
832 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
833 ml = [o_contents convertPoint:ml fromView:nil];
834 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
836 if( b_hide && b_inside )
838 [NSCursor setHiddenUntilMouseMoves: YES];
842 [NSCursor setHiddenUntilMouseMoves: NO];
848 /* Dooh, why do we spend processor time doing this kind of stuff? */
850 unsigned int i_mouse_hide_timeout =
851 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
853 if( i_mouse_hide_timeout < 100000 )
854 i_mouse_hide_timeout = 100000;
855 if( p_vout->b_fullscreen )
857 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
859 i_time_mouse_last_moved = mdate();
860 [self hideMouse: YES];
865 [self hideMouse: NO];
870 - (void)enterFullscreen
872 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
873 [super enterFullscreen];
877 - (void)leaveFullscreen
879 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
880 [super leaveFullscreen];
884 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
886 if( p_vout->b_fullscreen )
888 [o_window setMovableByWindowBackground: NO];
889 [super scaleWindowWithFactor: factor animate: animate];
890 [o_window setMovableByWindowBackground: YES];
894 /*****************************************************************************
895 * VLCEmbeddedVoutView implementation
896 *****************************************************************************/
898 @implementation VLCEmbeddedVoutView
902 o_embeddedwindow = [self window];
905 - (BOOL)mouseDownCanMoveWindow
910 - (id)initWithFrame: (NSRect)frameRect
912 if(self = [super initWithFrame: frameRect])
915 [[[VLCMain sharedInstance] embeddedList] addEmbeddedVout: self];
916 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
921 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
922 frame: (NSRect *)s_arg_frame
926 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
928 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
931 o_window = [self window];
933 [o_window setAcceptsMouseMovedEvents: TRUE];
935 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
937 [o_window setLevel: NSStatusWindowLevel];
940 [view setFrameSize: [self frame].size];
943 /* o_window needs to point to our o_embeddedwindow, super might have set it
944 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
945 o_window = o_embeddedwindow;
949 [o_window lockFullscreenAnimation];
951 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
955 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
957 /* Make the window the front and key window before animating */
958 if ([o_window isVisible] && (![o_window isFullscreen]))
959 [o_window makeKeyAndOrderFront: self];
961 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
963 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
965 /* Make sure our window is visible, if we are not in fullscreen */
966 if (![o_window isFullscreen])
967 [o_window makeKeyAndOrderFront: self];
968 [o_window unlockFullscreenAnimation];
975 - (void)setUsed: (BOOL)b_new_used
989 /* Don't close the window yet, wait a bit to see if a new input is poping up */
990 /* FIXME: Probably fade the window In and Out */
991 /* FIXME: fix core */
992 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
994 [[[VLCMain sharedInstance] embeddedList] releaseEmbeddedVout: self];
997 - (void)enterFullscreen
1000 [super enterFullscreen];
1002 /* We are in a VLCEmbeddedWindow */
1003 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1006 - (void)leaveFullscreen
1009 [super leaveFullscreen];
1011 /* We are in a VLCEmbeddedWindow */
1012 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1016 /*****************************************************************************
1017 * VLCVoutWindow implementation
1018 *****************************************************************************/
1019 @implementation VLCVoutWindow
1021 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1022 frame: (NSRect *) frame
1028 [self performSelectorOnMainThread: @selector(initMainThread:)
1029 withObject: NULL waitUntilDone: YES];
1031 return b_init_ok ? self : nil;
1034 - (id)initMainThread: (id) sender
1037 rect.size.height = p_vout->i_window_height;
1038 rect.size.width = p_vout->i_window_width;
1039 rect.origin.x = rect.origin.y = 70.;
1041 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1043 [self setBackgroundColor:[NSColor blackColor]];
1044 [self setHasShadow:YES];
1045 [self setMovableByWindowBackground: YES];
1047 [self makeKeyAndOrderFront: self];
1048 [self setReleasedWhenClosed: YES];
1049 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1050 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1052 /* We'll catch mouse events */
1053 [self makeFirstResponder: o_view];
1054 [self setCanBecomeKeyWindow: YES];
1055 [self setAcceptsMouseMovedEvents: YES];
1056 [self setIgnoresMouseEvents: NO];
1058 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1060 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1062 /* Find out on which screen to open the window */
1063 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1064 if( !screen ) screen = [NSScreen mainScreen];
1066 NSRect screen_rect = [screen frame];
1067 screen_rect.origin.x = screen_rect.origin.y = 0;
1069 /* Creates a window with size: screen_rect on o_screen */
1070 [self setFrame: screen_rect display: NO];
1072 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1073 [self setMovableByWindowBackground: NO];
1075 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1077 [self setLevel: NSStatusWindowLevel];
1080 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1082 /* Add the view. It's automatically resized to fit the window */
1083 [self setContentView: o_view];
1090 - (void)enterFullscreen
1092 if( fullscreen ) return;
1098 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1099 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1101 /* Find out on which screen to open the window */
1102 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1103 if( !screen ) screen = [self screen];
1106 [screen blackoutOtherScreens];
1108 [self setMovableByWindowBackground: NO];
1110 if( [screen isMainScreen] )
1111 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1113 initialFrame = [self frame];
1114 [self setFrame:[screen frame] display:YES animate:YES];
1115 [self setLevel:NSNormalWindowLevel];
1117 /* tell the fspanel to move itself to front next time it's triggered */
1118 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: i_device];
1119 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
1124 - (void)leaveFullscreen
1126 if( !fullscreen ) return;
1129 [NSScreen unblackoutScreens];
1131 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
1132 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1134 [self setFrame:initialFrame display:YES animate:YES];
1135 [self setMovableByWindowBackground: YES];
1136 if( var_GetBool( p_vout, "video-on-top" ) )
1137 [self setLevel: NSStatusWindowLevel];