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>
58 /*****************************************************************************
59 * DeviceCallback: Callback triggered when the video-device variable is changed
60 *****************************************************************************/
61 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
62 vlc_value_t old_val, vlc_value_t new_val, void *param )
65 vout_thread_t *p_vout = (vout_thread_t *)p_this;
67 msg_Dbg( p_vout, "set %"PRId64, new_val.i_int );
68 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
69 var_Set( p_vout->p_libvlc, "video-device", new_val );
72 var_Set( p_vout, "intf-change", val );
77 /*****************************************************************************
78 * VLCEmbeddedList implementation
79 *****************************************************************************/
80 @implementation VLCEmbeddedList
85 o_embedded_array = [NSMutableArray array];
93 for( i = 0; i < [o_embedded_array count]; i++ )
95 id o_vout_view = [o_embedded_array objectAtIndex: i];
96 if( ![o_vout_view isUsed] )
98 [o_vout_view setUsed: YES];
105 - (void)releaseEmbeddedVout: (id)o_vout_view
107 if( [o_embedded_array containsObject: o_vout_view] )
109 [o_vout_view setUsed: NO];
113 msg_Warn( VLCIntf, "cannot find Video Output");
117 - (void)addEmbeddedVout: (id)o_vout_view
119 if( ![o_embedded_array containsObject: o_vout_view] )
121 [o_embedded_array addObject: o_vout_view];
125 - (BOOL)windowContainsEmbedded: (id)o_window
127 return ([self viewForWindow: o_window] == nil ? NO : YES );
130 - (id)viewForWindow: (id)o_window
132 if( o_embedded_array != nil )
134 id o_enumerator = [o_embedded_array objectEnumerator];
135 id o_current_embedded;
136 if( o_window != nil )
138 while( (o_current_embedded = [o_enumerator nextObject]) )
140 if( [o_current_embedded voutWindow] == o_window )
142 return o_current_embedded;
152 /*****************************************************************************
153 * VLCVoutView implementation
154 *****************************************************************************/
155 @implementation VLCVoutView
157 - (id)initWithFrame: (NSRect)frameRect
159 self = [super initWithFrame: frameRect];
162 s_frame = &frameRect;
169 - (BOOL)setVout: (vout_thread_t *) vout
170 subView: (NSView *) view
171 frame: (NSRect *) frame
174 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
175 NSArray *o_screens = [NSScreen screens];
181 if( [o_screens count] <= 0 )
183 msg_Err( VLCIntf, "no OSX screens available" );
187 p_real_vout = [VLCVoutView realVout: p_vout];
189 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
190 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
192 i_device = var_GetInteger( p_vout, "macosx-vdev" );
196 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
199 /* Setup the menuitem for the multiple displays. */
200 if( var_Type( p_real_vout, "video-device" ) == 0 )
203 vlc_value_t val2, text;
206 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
208 text.psz_string = _("Fullscreen Video Device");
209 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
211 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
214 text.psz_string = _("Default");
215 var_Change( p_real_vout, "video-device",
216 VLC_VAR_ADDCHOICE, &val2, &text );
217 var_Set( p_real_vout, "video-device", val2 );
219 while( (o_screen = [o_enumerator nextObject]) != NULL )
222 NSRect s_rect = [o_screen frame];
224 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
225 "%s %d (%dx%d)", _("Screen"), i,
226 (int)s_rect.size.width, (int)s_rect.size.height );
228 text.psz_string = psz_temp;
229 val2.i_int = (int)[o_screen displayID];
230 var_Change( p_real_vout, "video-device",
231 VLC_VAR_ADDCHOICE, &val2, &text );
232 if( (int)[o_screen displayID] == i_device )
234 var_Set( p_real_vout, "video-device", val2 );
239 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
243 var_Set( p_real_vout, "intf-change", val2 );
246 /* Add the view. It's automatically resized to fit the window */
247 [self addSubview: o_view];
248 [self setAutoresizesSubviews: YES];
254 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
256 [super resizeSubviewsWithOldSize: oldBoundsSize];
257 [o_view setFrameSize: [self frame].size];
260 - (void)drawRect:(NSRect)rect
262 /* When there is no subview we draw a black background */
264 [[NSColor blackColor] set];
271 [[[[VLCMain sharedInstance] controls] fspanel] fadeOut];
273 /* Make sure we don't see a white flash */
274 [[self voutWindow] disableScreenUpdatesUntilFlush];
275 [o_view removeFromSuperview];
285 NSString * o_title = nil;
286 NSMutableString * o_mrl = nil;
287 input_thread_t * p_input;
290 if( !p_vout ) return;
292 p_input = getInput();
294 if( !p_input ) return;
296 input_item_t * p_item = input_GetItem( p_input );
298 psz_title = input_item_GetNowPlaying ( p_item );
300 psz_title = input_item_GetName( p_item );
303 o_title = [NSString stringWithUTF8String: psz_title];
305 char *psz_uri = input_item_GetURI( p_item );
307 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
317 /* FIXME once psz_access is exported, we could check if we are
318 * reading from a file in a smarter way. */
320 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
321 if( prefix_range.location != NSNotFound )
322 [o_mrl deleteCharactersInRange: prefix_range];
324 if( [o_mrl characterAtIndex:0] == '/' )
326 /* it's a local file */
327 [o_window setRepresentedFilename: o_mrl];
331 /* it's from the network or somewhere else,
332 * we clear the previous path */
333 [o_window setRepresentedFilename: @""];
335 [o_window setTitle: o_title];
339 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
341 vlc_object_release( p_input );
344 - (void)setOnTop:(BOOL)b_on_top
348 [o_window setLevel: NSStatusWindowLevel];
352 [o_window setLevel: NSNormalWindowLevel];
356 - (NSSize)voutSizeForFactor: (float)factor
358 int i_corrected_height, i_corrected_width;
361 if( p_vout->render.i_height * p_vout->render.i_aspect >
362 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
364 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
366 newsize.width = (int) ( i_corrected_width * factor );
367 newsize.height = (int) ( p_vout->render.i_height * factor );
371 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
372 p_vout->render.i_aspect;
373 newsize.width = (int) ( p_vout->render.i_width * factor );
374 newsize.height = (int) ( i_corrected_height * factor );
380 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
382 if ( !p_vout->b_fullscreen )
386 NSPoint topleftscreen;
390 topleftbase.y = [o_window frame].size.height;
391 topleftscreen = [o_window convertBaseToScreen: topleftbase];
393 newsize = [self voutSizeForFactor:factor];
395 /* In fullscreen mode we need to use a view that is different from
396 * ourselves, with the VLCEmbeddedWindow */
397 if([o_window isKindOfClass:[VLCEmbeddedWindow class]])
398 mainView = [o_window mainView];
402 /* Calculate the window's new size */
403 new_frame.size.width = [o_window frame].size.width -
404 [mainView frame].size.width + newsize.width;
405 new_frame.size.height = [o_window frame].size.height -
406 [mainView frame].size.height + newsize.height;
408 new_frame.origin.x = topleftscreen.x;
409 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
411 [o_window setFrame:new_frame display:animate animate:animate];
412 p_vout->i_changes |= VOUT_SIZE_CHANGE;
416 - (void)toggleFloatOnTop
420 if( !p_real_vout ) return;
421 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
429 var_Set( p_real_vout, "video-on-top", val );
432 - (void)toggleFullscreen
435 if( !p_real_vout ) return;
436 var_ToggleBool( p_real_vout, "fullscreen" );
442 if( !p_real_vout ) return NO;
443 var_Get( p_real_vout, "fullscreen", &val );
444 return( val.b_bool );
449 var_TriggerCallback( p_real_vout, "video-snapshot" );
454 /* Disable Screensaver, when we're playing something, but allow it on pause */
455 if( !VLCIntf || !VLCIntf->p_sys )
458 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
459 UpdateSystemActivity( UsrActivity );
467 - (void)scrollWheel:(NSEvent *)theEvent
469 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] controls];
470 [o_controls scrollWheel: theEvent];
473 - (void)keyDown:(NSEvent *)o_event
477 unsigned int i_pressed_modifiers = 0;
480 i_pressed_modifiers = [o_event modifierFlags];
482 if( i_pressed_modifiers & NSShiftKeyMask )
483 val.i_int |= KEY_MODIFIER_SHIFT;
484 if( i_pressed_modifiers & NSControlKeyMask )
485 val.i_int |= KEY_MODIFIER_CTRL;
486 if( i_pressed_modifiers & NSAlternateKeyMask )
487 val.i_int |= KEY_MODIFIER_ALT;
488 if( i_pressed_modifiers & NSCommandKeyMask )
489 val.i_int |= KEY_MODIFIER_COMMAND;
491 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
495 /* Escape should always get you out of fullscreen */
496 if( key == (unichar) 0x1b )
498 if( p_real_vout && [self isFullscreen] )
500 [self toggleFullscreen];
506 val.i_int = config_GetInt( p_vout, "key-play-pause" );
508 val.i_int |= (int)CocoaKeyToVLC( key );
509 var_Set( p_vout->p_libvlc, "key-pressed", val );
511 else msg_Dbg( VLCIntf, "could not send keyevent to VLC core" );
514 [super keyDown: o_event];
517 - (void)mouseDown:(NSEvent *)o_event
522 if( ( [o_event type] == NSLeftMouseDown ) &&
523 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
525 if( [o_event clickCount] <= 1 )
527 /* single clicking */
528 var_Get( p_vout, "mouse-button-down", &val );
530 var_Set( p_vout, "mouse-button-down", val );
534 /* multiple clicking */
535 [self toggleFullscreen];
538 else if( ( [o_event type] == NSRightMouseDown ) ||
539 ( ( [o_event type] == NSLeftMouseDown ) &&
540 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
542 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
543 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
547 [super mouseDown: o_event];
550 - (void)otherMouseDown:(NSEvent *)o_event
554 if( p_vout && [o_event type] == NSOtherMouseDown )
556 var_Get( p_vout, "mouse-button-down", &val );
558 var_Set( p_vout, "mouse-button-down", val );
561 [super mouseDown: o_event];
564 - (void)rightMouseDown:(NSEvent *)o_event
566 if( p_vout && [o_event type] == NSRightMouseDown )
568 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
569 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
572 [super mouseDown: o_event];
575 - (void)mouseUp:(NSEvent *)o_event
579 if( p_vout && [o_event type] == NSLeftMouseUp )
583 var_GetCoords( p_vout, "mouse-moved", &x, &y );
584 var_SetCoords( p_vout, "mouse-clicked", x, y );
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 x = (((int)ml.x) - i_x) * p_vout->render.i_width / i_width;
658 if( [[o_view className] isEqualToString: @"VLCGLView"] )
660 y = (((int)(s_rect.size.height - ml.y)) - i_y) *
661 p_vout->render.i_height / i_height;
665 y = (((int)ml.y) - i_y) * p_vout->render.i_height / i_height;
667 var_SetCoords( p_vout, "mouse-moved", x, y );
669 if( [self isFullscreen] )
670 [[[[VLCMain sharedInstance] controls] fspanel] fadeIn];
673 [super mouseMoved: o_event];
676 - (BOOL)acceptsFirstResponder
681 - (BOOL)becomeFirstResponder
686 - (BOOL)resignFirstResponder
688 /* We need to stay the first responder or we'll miss some
693 /* Class methods used by the different vout modules */
695 + (vout_thread_t *)realVout: (vout_thread_t *)p_vout
697 /* p_real_vout: the vout we have to use to check for video-on-top
698 and a few other things. If we are the QuickTime output, it's us.
699 It we are the OpenGL provider, it is our parent.
700 Since we can't be the QuickTime output anymore, we need to be
702 FIXME: check with the caca and x11 vouts! */
703 return (vout_thread_t *) p_vout->p_parent;
706 + (id)voutView: (vout_thread_t *)p_vout subView: (NSView *)view
707 frame: (NSRect *)s_frame
713 i_drawable_gl = var_GetInteger( p_vout->p_libvlc, "drawable-gl" );
715 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
716 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
717 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
718 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
719 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
720 var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
722 /* We only wait for NSApp to initialise if we're not embedded (as in the
723 * case of the Mozilla plugin). We can tell whether we're embedded or not
724 * by examining the "drawable-gl" value: if it's zero, we're running in the
725 * main Mac intf; if it's non-zero, we're embedded. */
726 if( i_drawable_gl == 0 )
728 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
729 for( i_timeout = 20 ; i_timeout-- ; )
733 msleep( INTF_IDLE_SLEEP );
739 /* No MacOS X intf, unable to communicate with MT */
740 msg_Err( p_vout, "no MacOS X interface present" );
745 if ( VLCIntf && !(p_vout->b_fullscreen) &&
746 !(var_GetBool( p_vout, "macosx-background" )) &&
747 var_GetBool( p_vout, "embedded-video") )
749 o_return = [[[VLCMain sharedInstance] embeddedList] embeddedVout];
754 /* No embedded vout is available */
755 if( o_return == nil )
758 memset( &null_rect, 0, sizeof( NSRect ) );
759 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
761 [o_return setVout: p_vout subView: view frame: s_frame];
765 - (void)enterFullscreen
767 /* Save the settings for next playing item */
768 playlist_t * p_playlist = pl_Get( p_real_vout );
769 var_SetBool( p_playlist, "fullscreen", true );
772 - (void)leaveFullscreen
774 /* Save the settings for next playing item */
775 playlist_t * p_playlist = pl_Get( p_real_vout );
776 var_SetBool( p_playlist, "fullscreen", false );
781 /*****************************************************************************
782 * VLCDetachedVoutView implementation
783 *****************************************************************************/
784 @implementation VLCDetachedVoutView
786 - (id)initWithFrame: (NSRect)frameRect
788 [super initWithFrame: frameRect];
789 i_time_mouse_last_moved = 0;
793 - (BOOL)mouseDownCanMoveWindow
798 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
799 frame: (NSRect *) s_arg_frame
801 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
802 i_time_mouse_last_moved = mdate();
803 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
807 if([self isFullscreen])
808 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
810 [view setFrame: [self frame]];
817 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
818 i_time_mouse_last_moved = 0;
822 - (void)mouseMoved:(NSEvent *)o_event
824 i_time_mouse_last_moved = mdate();
825 [super mouseMoved: o_event];
828 - (void)hideMouse:(BOOL)b_hide
832 NSView *o_contents = [o_window contentView];
834 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
835 ml = [o_contents convertPoint:ml fromView:nil];
836 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
838 if( b_hide && b_inside )
840 [NSCursor setHiddenUntilMouseMoves: YES];
844 [NSCursor setHiddenUntilMouseMoves: NO];
850 /* Dooh, why do we spend processor time doing this kind of stuff? */
852 unsigned int i_mouse_hide_timeout =
853 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
855 if( i_mouse_hide_timeout < 100000 )
856 i_mouse_hide_timeout = 100000;
857 if( p_vout->b_fullscreen )
859 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
861 i_time_mouse_last_moved = mdate();
862 [self hideMouse: YES];
867 [self hideMouse: NO];
872 - (void)enterFullscreen
874 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
875 [super enterFullscreen];
879 - (void)leaveFullscreen
881 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
882 [super leaveFullscreen];
886 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
888 if( p_vout->b_fullscreen )
890 [o_window setMovableByWindowBackground: NO];
891 [super scaleWindowWithFactor: factor animate: animate];
892 [o_window setMovableByWindowBackground: YES];
896 /*****************************************************************************
897 * VLCEmbeddedVoutView implementation
898 *****************************************************************************/
900 @implementation VLCEmbeddedVoutView
904 o_embeddedwindow = [self window];
907 - (BOOL)mouseDownCanMoveWindow
912 - (id)initWithFrame: (NSRect)frameRect
914 if(self = [super initWithFrame: frameRect])
917 [[[VLCMain sharedInstance] embeddedList] addEmbeddedVout: self];
918 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
923 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
924 frame: (NSRect *)s_arg_frame
928 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
930 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
933 o_window = [self window];
935 [o_window setAcceptsMouseMovedEvents: TRUE];
937 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
939 [o_window setLevel: NSStatusWindowLevel];
942 [view setFrameSize: [self frame].size];
945 /* o_window needs to point to our o_embeddedwindow, super might have set it
946 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
947 o_window = o_embeddedwindow;
951 [o_window lockFullscreenAnimation];
953 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
957 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
959 /* Make the window the front and key window before animating */
960 if ([o_window isVisible] && (![o_window isFullscreen]))
961 [o_window makeKeyAndOrderFront: self];
963 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
965 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
967 /* Make sure our window is visible, if we are not in fullscreen */
968 if (![o_window isFullscreen])
969 [o_window makeKeyAndOrderFront: self];
970 [o_window unlockFullscreenAnimation];
977 - (void)setUsed: (BOOL)b_new_used
991 /* Don't close the window yet, wait a bit to see if a new input is poping up */
992 /* FIXME: Probably fade the window In and Out */
993 /* FIXME: fix core */
994 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
996 [[[VLCMain sharedInstance] embeddedList] releaseEmbeddedVout: self];
999 - (void)enterFullscreen
1002 [super enterFullscreen];
1004 /* We are in a VLCEmbeddedWindow */
1005 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1008 - (void)leaveFullscreen
1011 [super leaveFullscreen];
1013 /* We are in a VLCEmbeddedWindow */
1014 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1018 /*****************************************************************************
1019 * VLCVoutWindow implementation
1020 *****************************************************************************/
1021 @implementation VLCVoutWindow
1023 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1024 frame: (NSRect *) frame
1030 [self performSelectorOnMainThread: @selector(initMainThread:)
1031 withObject: NULL waitUntilDone: YES];
1033 return b_init_ok ? self : nil;
1036 - (id)initMainThread: (id) sender
1039 rect.size.height = p_vout->i_window_height;
1040 rect.size.width = p_vout->i_window_width;
1041 rect.origin.x = rect.origin.y = 70.;
1043 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1045 [self setBackgroundColor:[NSColor blackColor]];
1046 [self setHasShadow:YES];
1047 [self setMovableByWindowBackground: YES];
1049 [self makeKeyAndOrderFront: self];
1050 [self setReleasedWhenClosed: YES];
1051 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1052 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1054 /* We'll catch mouse events */
1055 [self makeFirstResponder: o_view];
1056 [self setCanBecomeKeyWindow: YES];
1057 [self setAcceptsMouseMovedEvents: YES];
1058 [self setIgnoresMouseEvents: NO];
1060 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1062 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1064 /* Find out on which screen to open the window */
1065 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1066 if( !screen ) screen = [NSScreen mainScreen];
1068 NSRect screen_rect = [screen frame];
1069 screen_rect.origin.x = screen_rect.origin.y = 0;
1071 /* Creates a window with size: screen_rect on o_screen */
1072 [self setFrame: screen_rect display: NO];
1074 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1075 [self setMovableByWindowBackground: NO];
1077 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1079 [self setLevel: NSStatusWindowLevel];
1082 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1084 /* Add the view. It's automatically resized to fit the window */
1085 [self setContentView: o_view];
1092 - (void)enterFullscreen
1094 if( fullscreen ) return;
1100 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1101 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1103 /* Find out on which screen to open the window */
1104 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1105 if( !screen ) screen = [self screen];
1108 [screen blackoutOtherScreens];
1110 [self setMovableByWindowBackground: NO];
1112 if( [screen isMainScreen] )
1113 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1115 initialFrame = [self frame];
1116 [self setFrame:[screen frame] display:YES animate:YES];
1117 [self setLevel:NSNormalWindowLevel];
1119 /* tell the fspanel to move itself to front next time it's triggered */
1120 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: i_device];
1121 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
1126 - (void)leaveFullscreen
1128 if( !fullscreen ) return;
1131 [NSScreen unblackoutScreens];
1133 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
1134 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];