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 /* if( ![[o_window className] isEqualToString: @"VLCVoutWindow"] )
127 NSLog( @"We were not given a VLCVoutWindow" );
129 return ([self viewForWindow: o_window] == nil ? NO : YES );
132 - (id)viewForWindow: (id)o_window
134 if( o_embedded_array != nil )
136 id o_enumerator = [o_embedded_array objectEnumerator];
137 id o_current_embedded;
138 if( o_window != nil )
140 while( (o_current_embedded = [o_enumerator nextObject]) )
142 if( [o_current_embedded voutWindow] == o_window )
144 return o_current_embedded;
154 /*****************************************************************************
155 * VLCVoutView implementation
156 *****************************************************************************/
157 @implementation VLCVoutView
159 - (id)initWithFrame: (NSRect)frameRect
161 self = [super initWithFrame: frameRect];
164 s_frame = &frameRect;
171 - (BOOL)setVout: (vout_thread_t *) vout
172 subView: (NSView *) view
173 frame: (NSRect *) frame
176 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
177 NSArray *o_screens = [NSScreen screens];
183 if( [o_screens count] <= 0 )
185 msg_Err( p_vout, "no OSX screens available" );
189 p_real_vout = [VLCVoutView realVout: p_vout];
191 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
192 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
194 i_device = var_GetInteger( p_vout, "macosx-vdev" );
198 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
201 /* Setup the menuitem for the multiple displays. */
202 if( var_Type( p_real_vout, "video-device" ) == 0 )
205 vlc_value_t val2, text;
208 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
210 text.psz_string = _("Fullscreen Video Device");
211 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
213 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
216 text.psz_string = _("Default");
217 var_Change( p_real_vout, "video-device",
218 VLC_VAR_ADDCHOICE, &val2, &text );
219 var_Set( p_real_vout, "video-device", val2 );
221 while( (o_screen = [o_enumerator nextObject]) != NULL )
224 NSRect s_rect = [o_screen frame];
226 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
227 "%s %d (%dx%d)", _("Screen"), i,
228 (int)s_rect.size.width, (int)s_rect.size.height );
230 text.psz_string = psz_temp;
231 val2.i_int = (int)[o_screen displayID];
232 var_Change( p_real_vout, "video-device",
233 VLC_VAR_ADDCHOICE, &val2, &text );
234 if( (int)[o_screen displayID] == i_device )
236 var_Set( p_real_vout, "video-device", val2 );
241 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
245 var_Set( p_real_vout, "intf-change", val2 );
248 /* Add the view. It's automatically resized to fit the window */
249 [self addSubview: o_view];
250 [self setAutoresizesSubviews: YES];
256 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
258 [super resizeSubviewsWithOldSize: oldBoundsSize];
259 [o_view setFrameSize: [self frame].size];
262 - (void)drawRect:(NSRect)rect
264 /* When there is no subview we draw a black background */
266 [[NSColor blackColor] set];
273 [[[[VLCMain sharedInstance] controls] fspanel] fadeOut];
275 /* Make sure we don't see a white flash */
276 [[self voutWindow] disableScreenUpdatesUntilFlush];
277 [o_view removeFromSuperview];
287 NSString * o_title = nil;
288 NSMutableString * o_mrl = nil;
289 input_thread_t * p_input;
292 if( !p_vout ) return;
294 p_input = getInput();
296 if( !p_input ) return;
298 input_item_t * p_item = input_GetItem( p_input );
300 psz_title = input_item_GetNowPlaying ( p_item );
302 psz_title = input_item_GetName( p_item );
305 o_title = [NSString stringWithUTF8String: psz_title];
307 char *psz_uri = input_item_GetURI( p_item );
309 o_mrl = [NSMutableString stringWithUTF8String: psz_uri];
319 /* FIXME once psz_access is exported, we could check if we are
320 * reading from a file in a smarter way. */
322 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
323 if( prefix_range.location != NSNotFound )
324 [o_mrl deleteCharactersInRange: prefix_range];
326 if( [o_mrl characterAtIndex:0] == '/' )
328 /* it's a local file */
329 [o_window setRepresentedFilename: o_mrl];
333 /* it's from the network or somewhere else,
334 * we clear the previous path */
335 [o_window setRepresentedFilename: @""];
337 [o_window setTitle: o_title];
341 [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]];
343 vlc_object_release( p_input );
346 - (void)setOnTop:(BOOL)b_on_top
350 [o_window setLevel: NSStatusWindowLevel];
354 [o_window setLevel: NSNormalWindowLevel];
358 - (NSSize)voutSizeForFactor: (float)factor
360 int i_corrected_height, i_corrected_width;
363 if( p_vout->render.i_height * p_vout->render.i_aspect >
364 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
366 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
368 newsize.width = (int) ( i_corrected_width * factor );
369 newsize.height = (int) ( p_vout->render.i_height * factor );
373 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
374 p_vout->render.i_aspect;
375 newsize.width = (int) ( p_vout->render.i_width * factor );
376 newsize.height = (int) ( i_corrected_height * factor );
382 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
384 if ( !p_vout->b_fullscreen )
388 NSPoint topleftscreen;
392 topleftbase.y = [o_window frame].size.height;
393 topleftscreen = [o_window convertBaseToScreen: topleftbase];
395 newsize = [self voutSizeForFactor:factor];
397 /* In fullscreen mode we need to use a view that is different from
398 * ourselves, with the VLCEmbeddedWindow */
399 if([o_window isKindOfClass:[VLCEmbeddedWindow class]])
400 mainView = [o_window mainView];
404 /* Calculate the window's new size */
405 new_frame.size.width = [o_window frame].size.width -
406 [mainView frame].size.width + newsize.width;
407 new_frame.size.height = [o_window frame].size.height -
408 [mainView frame].size.height + newsize.height;
410 new_frame.origin.x = topleftscreen.x;
411 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
413 [o_window setFrame:new_frame display:animate animate:animate];
414 p_vout->i_changes |= VOUT_SIZE_CHANGE;
418 - (void)toggleFloatOnTop
422 if( !p_real_vout ) return;
423 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
431 var_Set( p_real_vout, "video-on-top", val );
434 - (void)toggleFullscreen
437 if( !p_real_vout ) return;
438 var_ToggleBool( p_real_vout, "fullscreen" );
444 if( !p_real_vout ) return NO;
445 var_Get( p_real_vout, "fullscreen", &val );
446 return( val.b_bool );
451 var_TriggerCallback( p_real_vout, "video-snapshot" );
456 /* Disable Screensaver, when we're playing something, but allow it on pause */
457 if( !VLCIntf || !VLCIntf->p_sys )
460 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
461 UpdateSystemActivity( UsrActivity );
469 - (void)scrollWheel:(NSEvent *)theEvent
471 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] controls];
472 [o_controls scrollWheel: theEvent];
475 - (void)keyDown:(NSEvent *)o_event
479 unsigned int i_pressed_modifiers = 0;
482 i_pressed_modifiers = [o_event modifierFlags];
484 if( i_pressed_modifiers & NSShiftKeyMask )
485 val.i_int |= KEY_MODIFIER_SHIFT;
486 if( i_pressed_modifiers & NSControlKeyMask )
487 val.i_int |= KEY_MODIFIER_CTRL;
488 if( i_pressed_modifiers & NSAlternateKeyMask )
489 val.i_int |= KEY_MODIFIER_ALT;
490 if( i_pressed_modifiers & NSCommandKeyMask )
491 val.i_int |= KEY_MODIFIER_COMMAND;
493 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
497 /* Escape should always get you out of fullscreen */
498 if( key == (unichar) 0x1b )
500 if( p_real_vout && [self isFullscreen] )
502 [self toggleFullscreen];
508 val.i_int = config_GetInt( p_vout, "key-play-pause" );
510 val.i_int |= (int)CocoaKeyToVLC( key );
511 var_Set( p_vout->p_libvlc, "key-pressed", val );
513 else NSLog( @"Could not send keyevent to VLC core" );
516 [super keyDown: o_event];
519 - (void)mouseDown:(NSEvent *)o_event
524 if( ( [o_event type] == NSLeftMouseDown ) &&
525 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
527 if( [o_event clickCount] <= 1 )
529 /* single clicking */
530 var_Get( p_vout, "mouse-button-down", &val );
532 var_Set( p_vout, "mouse-button-down", val );
536 /* multiple clicking */
537 [self toggleFullscreen];
540 else if( ( [o_event type] == NSRightMouseDown ) ||
541 ( ( [o_event type] == NSLeftMouseDown ) &&
542 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
544 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
545 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
549 [super mouseDown: o_event];
552 - (void)otherMouseDown:(NSEvent *)o_event
556 if( p_vout && [o_event type] == NSOtherMouseDown )
558 var_Get( p_vout, "mouse-button-down", &val );
560 var_Set( p_vout, "mouse-button-down", val );
563 [super mouseDown: o_event];
566 - (void)rightMouseDown:(NSEvent *)o_event
568 if( p_vout && [o_event type] == NSRightMouseDown )
570 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
571 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
574 [super mouseDown: o_event];
577 - (void)mouseUp:(NSEvent *)o_event
581 if( p_vout && [o_event type] == NSLeftMouseUp )
583 var_SetBool( p_vout, "mouse-clicked", true );
585 var_Get( p_vout, "mouse-button-down", &val );
587 var_Set( p_vout, "mouse-button-down", val );
590 [super mouseUp: o_event];
593 - (void)otherMouseUp:(NSEvent *)o_event
597 if( p_vout && [o_event type] == NSOtherMouseUp )
599 var_Get( p_vout, "mouse-button-down", &val );
601 var_Set( p_vout, "mouse-button-down", val );
604 [super mouseUp: o_event];
607 - (void)rightMouseUp:(NSEvent *)o_event
609 if( p_vout && [o_event type] == NSRightMouseUp )
611 /* FIXME: this isn't the appropriate place, but we can't receive
612 * NSRightMouseDown some how */
613 msg_Dbg( p_vout, "received NSRightMouseUp" );
614 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] voutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] controls] voutView]];
617 [super mouseUp: o_event];
620 - (void)mouseDragged:(NSEvent *)o_event
622 [self mouseMoved: o_event];
625 - (void)otherMouseDragged:(NSEvent *)o_event
627 [self mouseMoved: o_event];
630 - (void)rightMouseDragged:(NSEvent *)o_event
632 [self mouseMoved: o_event];
635 - (void)mouseMoved:(NSEvent *)o_event
643 s_rect = [o_view bounds];
644 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
645 b_inside = [o_view mouse: ml inRect: s_rect];
650 unsigned int i_width, i_height, i_x, i_y;
652 vout_PlacePicture( p_vout, (unsigned int)s_rect.size.width,
653 (unsigned int)s_rect.size.height,
654 &i_x, &i_y, &i_width, &i_height );
656 val.i_int = ( ((int)ml.x) - i_x ) *
657 p_vout->render.i_width / i_width;
658 var_Set( p_vout, "mouse-x", val );
660 if( [[o_view className] isEqualToString: @"VLCGLView"] )
662 val.i_int = ( ((int)(s_rect.size.height - ml.y)) - i_y ) *
663 p_vout->render.i_height / i_height;
667 val.i_int = ( ((int)ml.y) - i_y ) *
668 p_vout->render.i_height / i_height;
670 var_Set( p_vout, "mouse-y", val );
671 var_TriggerCallback( p_vout, "mouse-moved" );
673 if( [self isFullscreen] )
674 [[[[VLCMain sharedInstance] controls] fspanel] fadeIn];
677 [super mouseMoved: o_event];
680 - (BOOL)acceptsFirstResponder
685 - (BOOL)becomeFirstResponder
690 - (BOOL)resignFirstResponder
692 /* We need to stay the first responder or we'll miss some
697 /* Class methods used by the different vout modules */
699 + (vout_thread_t *)realVout: (vout_thread_t *)p_vout
701 /* p_real_vout: the vout we have to use to check for video-on-top
702 and a few other things. If we are the QuickTime output, it's us.
703 It we are the OpenGL provider, it is our parent.
704 Since we can't be the QuickTime output anymore, we need to be
706 FIXME: check with the caca and x11 vouts! */
707 return (vout_thread_t *) p_vout->p_parent;
710 + (id)voutView: (vout_thread_t *)p_vout subView: (NSView *)view
711 frame: (NSRect *)s_frame
717 i_drawable_gl = var_GetInteger( p_vout->p_libvlc, "drawable-gl" );
719 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
720 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
721 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
722 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
723 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
724 var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
726 /* We only wait for NSApp to initialise if we're not embedded (as in the
727 * case of the Mozilla plugin). We can tell whether we're embedded or not
728 * by examining the "drawable-gl" value: if it's zero, we're running in the
729 * main Mac intf; if it's non-zero, we're embedded. */
730 if( i_drawable_gl == 0 )
732 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
733 for( i_timeout = 20 ; i_timeout-- ; )
737 msleep( INTF_IDLE_SLEEP );
743 /* No MacOS X intf, unable to communicate with MT */
744 msg_Err( p_vout, "no MacOS X interface present" );
749 if ( VLCIntf && !(p_vout->b_fullscreen) &&
750 !(var_GetBool( p_vout, "macosx-background" )) &&
751 var_GetBool( p_vout, "embedded-video") )
753 o_return = [[[VLCMain sharedInstance] embeddedList] embeddedVout];
758 /* No embedded vout is available */
759 if( o_return == nil )
762 bzero( &null_rect, sizeof( NSRect ) );
763 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
765 [o_return setVout: p_vout subView: view frame: s_frame];
769 - (void)enterFullscreen
771 /* Save the settings for next playing item */
772 playlist_t * p_playlist = pl_Get( p_real_vout );
773 var_SetBool( p_playlist, "fullscreen", true );
776 - (void)leaveFullscreen
778 /* Save the settings for next playing item */
779 playlist_t * p_playlist = pl_Get( p_real_vout );
780 var_SetBool( p_playlist, "fullscreen", false );
785 /*****************************************************************************
786 * VLCDetachedVoutView implementation
787 *****************************************************************************/
788 @implementation VLCDetachedVoutView
790 - (id)initWithFrame: (NSRect)frameRect
792 [super initWithFrame: frameRect];
793 i_time_mouse_last_moved = 0;
797 - (BOOL)mouseDownCanMoveWindow
802 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
803 frame: (NSRect *) s_arg_frame
805 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
806 i_time_mouse_last_moved = mdate();
807 o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self
811 if([self isFullscreen])
812 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
814 [view setFrame: [self frame]];
821 [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES];
822 i_time_mouse_last_moved = 0;
826 - (void)mouseMoved:(NSEvent *)o_event
828 i_time_mouse_last_moved = mdate();
829 [super mouseMoved: o_event];
832 - (void)hideMouse:(BOOL)b_hide
836 NSView *o_contents = [o_window contentView];
838 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
839 ml = [o_contents convertPoint:ml fromView:nil];
840 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
842 if( b_hide && b_inside )
844 [NSCursor setHiddenUntilMouseMoves: YES];
848 [NSCursor setHiddenUntilMouseMoves: NO];
854 /* Dooh, why do we spend processor time doing this kind of stuff? */
856 unsigned int i_mouse_hide_timeout =
857 var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000;
859 if( i_mouse_hide_timeout < 100000 )
860 i_mouse_hide_timeout = 100000;
861 if( p_vout->b_fullscreen )
863 if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout )
865 i_time_mouse_last_moved = mdate();
866 [self hideMouse: YES];
871 [self hideMouse: NO];
876 - (void)enterFullscreen
878 [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO];
879 [super enterFullscreen];
883 - (void)leaveFullscreen
885 [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO];
886 [super leaveFullscreen];
890 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
892 if( p_vout->b_fullscreen )
894 [o_window setMovableByWindowBackground: NO];
895 [super scaleWindowWithFactor: factor animate: animate];
896 [o_window setMovableByWindowBackground: YES];
900 /*****************************************************************************
901 * VLCEmbeddedVoutView implementation
902 *****************************************************************************/
904 @implementation VLCEmbeddedVoutView
908 o_embeddedwindow = [self window];
911 - (BOOL)mouseDownCanMoveWindow
916 - (id)initWithFrame: (NSRect)frameRect
918 if(self = [super initWithFrame: frameRect])
921 [[[VLCMain sharedInstance] embeddedList] addEmbeddedVout: self];
922 o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */
927 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
928 frame: (NSRect *)s_arg_frame
932 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
934 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
937 o_window = [self window];
939 [o_window setAcceptsMouseMovedEvents: TRUE];
941 if( var_CreateGetBool( p_real_vout, "video-on-top" ) )
943 [o_window setLevel: NSStatusWindowLevel];
946 [view setFrameSize: [self frame].size];
949 /* o_window needs to point to our o_embeddedwindow, super might have set it
950 * to the fullscreen window that o_embeddedwindow setups during fullscreen */
951 o_window = o_embeddedwindow;
955 [o_window lockFullscreenAnimation];
957 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
961 [NSObject cancelPreviousPerformRequestsWithTarget:o_window];
963 /* Make the window the front and key window before animating */
964 if ([o_window isVisible] && (![o_window isFullscreen]))
965 [o_window makeKeyAndOrderFront: self];
967 if ( [self window] != o_embeddedwindow )
968 [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])];
970 [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]];
972 /* Make sure our window is visible, if we are not in fullscreen */
973 if (![o_window isFullscreen])
974 [o_window makeKeyAndOrderFront: self];
975 [o_window unlockFullscreenAnimation];
982 - (void)setUsed: (BOOL)b_new_used
996 /* Don't close the window yet, wait a bit to see if a new input is poping up */
997 /* FIXME: Probably fade the window In and Out */
998 /* FIXME: fix core */
999 [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.];
1001 [[[VLCMain sharedInstance] embeddedList] releaseEmbeddedVout: self];
1004 - (void)enterFullscreen
1007 [super enterFullscreen];
1009 /* We are in a VLCEmbeddedWindow */
1010 [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES];
1013 - (void)leaveFullscreen
1016 [super leaveFullscreen];
1018 /* We are in a VLCEmbeddedWindow */
1019 [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES];
1023 /*****************************************************************************
1024 * VLCVoutWindow implementation
1025 *****************************************************************************/
1026 @implementation VLCVoutWindow
1028 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
1029 frame: (NSRect *) frame
1035 [self performSelectorOnMainThread: @selector(initMainThread:)
1036 withObject: NULL waitUntilDone: YES];
1038 return b_init_ok ? self : nil;
1041 - (id)initMainThread: (id) sender
1044 rect.size.height = p_vout->i_window_height;
1045 rect.size.width = p_vout->i_window_width;
1046 rect.origin.x = rect.origin.y = 70.;
1048 if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
1050 [self setBackgroundColor:[NSColor blackColor]];
1051 [self setHasShadow:YES];
1052 [self setMovableByWindowBackground: YES];
1054 [self makeKeyAndOrderFront: self];
1055 [self setReleasedWhenClosed: YES];
1056 [self setFrameUsingName:@"VLCVoutWindowDetached"];
1057 [self setFrameAutosaveName:@"VLCVoutWindowDetached"];
1059 /* We'll catch mouse events */
1060 [self makeFirstResponder: o_view];
1061 [self setCanBecomeKeyWindow: YES];
1062 [self setAcceptsMouseMovedEvents: YES];
1063 [self setIgnoresMouseEvents: NO];
1065 if( var_CreateGetBool( p_vout, "macosx-background" ) )
1067 int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1069 /* Find out on which screen to open the window */
1070 NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1071 if( !screen ) screen = [NSScreen mainScreen];
1073 NSRect screen_rect = [screen frame];
1074 screen_rect.origin.x = screen_rect.origin.y = 0;
1076 /* Creates a window with size: screen_rect on o_screen */
1077 [self setFrame: screen_rect display: NO];
1079 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1080 [self setMovableByWindowBackground: NO];
1082 if( var_CreateGetBool( p_vout, "video-on-top" ) )
1084 [self setLevel: NSStatusWindowLevel];
1087 [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
1089 /* Add the view. It's automatically resized to fit the window */
1090 [self setContentView: o_view];
1097 - (void)enterFullscreen
1099 if( fullscreen ) return;
1105 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
1106 b_black = var_CreateGetBool( p_vout, "macosx-black" );
1108 /* Find out on which screen to open the window */
1109 screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
1110 if( !screen ) screen = [self screen];
1113 [screen blackoutOtherScreens];
1115 [self setMovableByWindowBackground: NO];
1117 if( [screen isMainScreen] )
1118 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1120 initialFrame = [self frame];
1121 [self setFrame:[screen frame] display:YES animate:YES];
1122 [self setLevel:NSNormalWindowLevel];
1124 /* tell the fspanel to move itself to front next time it's triggered */
1125 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: i_device];
1126 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
1131 - (void)leaveFullscreen
1133 if( !fullscreen ) return;
1136 [NSScreen unblackoutScreens];
1138 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
1139 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1141 [self setFrame:initialFrame display:YES animate:YES];
1142 [self setMovableByWindowBackground: YES];
1143 if( var_GetBool( p_vout, "video-on-top" ) )
1144 [self setLevel: NSStatusWindowLevel];