1 /*****************************************************************************
2 * vout.m: MacOS X video output module
3 *****************************************************************************
4 * Copyright (C) 2001-2007 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 K
\9fhne <fkuehne at videolan dot org>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
28 *****************************************************************************/
30 /*****************************************************************************
32 *****************************************************************************/
33 #include <errno.h> /* ENOMEM */
34 #include <stdlib.h> /* free() */
35 #include <string.h> /* strerror() */
37 /* BeginFullScreen, EndFullScreen */
38 #include <QuickTime/QuickTime.h>
47 /*****************************************************************************
48 * DeviceCallback: Callback triggered when the video-device variable is changed
49 *****************************************************************************/
50 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
51 vlc_value_t old_val, vlc_value_t new_val, void *param )
54 vout_thread_t *p_vout = (vout_thread_t *)p_this;
56 msg_Dbg( p_vout, "set %d", new_val.i_int );
57 var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
58 var_Set( p_vout->p_libvlc, "video-device", new_val );
60 val.b_bool = VLC_TRUE;
61 var_Set( p_vout, "intf-change", val );
66 /*****************************************************************************
67 * VLCEmbeddedList implementation
68 *****************************************************************************/
69 @implementation VLCEmbeddedList
74 o_embedded_array = [NSMutableArray array];
82 for( i = 0; i < [o_embedded_array count]; i++ )
84 id o_vout_view = [o_embedded_array objectAtIndex: i];
85 if( ![o_vout_view isUsed] )
87 [o_vout_view setUsed: YES];
94 - (void)releaseEmbeddedVout: (id)o_vout_view
96 if( [o_embedded_array containsObject: o_vout_view] )
98 [o_vout_view setUsed: NO];
102 msg_Warn( VLCIntf, "cannot find Video Output");
106 - (void)addEmbeddedVout: (id)o_vout_view
108 if( ![o_embedded_array containsObject: o_vout_view] )
110 [o_embedded_array addObject: o_vout_view];
114 - (BOOL)windowContainsEmbedded: (id)o_window
116 /* if( ![[o_window className] isEqualToString: @"VLCWindow"] )
118 NSLog( @"We were not given a VLCWindow" );
120 return ([self getViewForWindow: o_window] == nil ? NO : YES );
123 - (id)getViewForWindow: (id)o_window
125 id o_enumerator = [o_embedded_array objectEnumerator];
126 id o_current_embedded;
128 while( (o_current_embedded = [o_enumerator nextObject]) )
130 if( [o_current_embedded getWindow] == o_window )
132 return o_current_embedded;
140 /*****************************************************************************
141 * VLCVoutView implementation
142 *****************************************************************************/
143 @implementation VLCVoutView
145 - (id)initWithFrame:(NSRect)frameRect
147 [super initWithFrame: frameRect];
150 s_frame = &frameRect;
157 - (BOOL)setVout: (vout_thread_t *) vout subView: (NSView *) view
158 frame: (NSRect *) frame
161 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
162 NSArray *o_screens = [NSScreen screens];
168 if( [o_screens count] <= 0 )
170 msg_Err( p_vout, "no OSX screens available" );
174 p_real_vout = [VLCVoutView getRealVout: p_vout];
176 /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
177 if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 )
179 i_device = var_GetInteger( p_vout, "macosx-vdev" );
183 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
186 /* Setup the menuitem for the multiple displays. */
187 if( var_Type( p_real_vout, "video-device" ) == 0 )
190 vlc_value_t val2, text;
193 var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER |
195 text.psz_string = _("Video Device");
196 var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
198 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
201 text.psz_string = _("Default");
202 var_Change( p_real_vout, "video-device",
203 VLC_VAR_ADDCHOICE, &val2, &text );
204 var_Set( p_real_vout, "video-device", val2 );
206 while( (o_screen = [o_enumerator nextObject]) != NULL )
209 NSRect s_rect = [o_screen frame];
211 snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1,
212 "%s %d (%dx%d)", _("Screen"), i,
213 (int)s_rect.size.width, (int)s_rect.size.height );
215 text.psz_string = psz_temp;
217 var_Change( p_real_vout, "video-device",
218 VLC_VAR_ADDCHOICE, &val2, &text );
221 var_Set( p_real_vout, "video-device", val2 );
226 var_AddCallback( p_real_vout, "video-device", DeviceCallback,
229 val2.b_bool = VLC_TRUE;
230 var_Set( p_real_vout, "intf-change", val2 );
233 /* Add the view. It's automatically resized to fit the window */
234 [self addSubview: o_view];
235 [self setAutoresizesSubviews: YES];
241 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
243 [super resizeSubviewsWithOldSize: oldBoundsSize];
244 [o_view setFrameSize: [self frame].size];
249 [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeOut];
251 [o_view removeFromSuperview];
261 NSMutableString * o_title = nil, * o_mrl = nil;
262 input_thread_t * p_input;
269 p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT );
271 if( p_input == NULL )
276 if( input_GetItem(p_input)->psz_name != NULL )
277 o_title = [NSMutableString stringWithUTF8String:
278 input_GetItem(p_input)->psz_name];
279 if( input_GetItem(p_input)->psz_uri != NULL )
280 o_mrl = [NSMutableString stringWithUTF8String:
281 input_GetItem(p_input)->psz_uri];
287 /* FIXME once psz_access is exported, we could check if we are
288 * reading from a file in a smarter way. */
290 NSRange prefix_range = [o_mrl rangeOfString: @"file:"];
291 if( prefix_range.location != NSNotFound )
292 [o_mrl deleteCharactersInRange: prefix_range];
294 if( [o_mrl characterAtIndex:0] == '/' )
296 /* it's a local file */
297 [o_window setRepresentedFilename: o_mrl];
301 /* it's from the network or somewhere else,
302 * we clear the previous path */
303 [o_window setRepresentedFilename: @""];
305 [o_window setTitle: o_title];
309 [o_window setTitle: [NSString stringWithCString: VOUT_TITLE]];
311 vlc_object_release( p_input );
315 - (void)setOnTop:(BOOL)b_on_top
319 [o_window setLevel: NSStatusWindowLevel];
323 [o_window setLevel: NSNormalWindowLevel];
327 - (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate
330 int i_corrected_height, i_corrected_width;
332 NSPoint topleftscreen;
334 if ( !p_vout->b_fullscreen )
338 topleftbase.y = [o_window frame].size.height;
339 topleftscreen = [o_window convertBaseToScreen: topleftbase];
341 if( p_vout->render.i_height * p_vout->render.i_aspect >
342 p_vout->render.i_width * VOUT_ASPECT_FACTOR )
344 i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect /
346 newsize.width = (int) ( i_corrected_width * factor );
347 newsize.height = (int) ( p_vout->render.i_height * factor );
351 i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR /
352 p_vout->render.i_aspect;
353 newsize.width = (int) ( p_vout->render.i_width * factor );
354 newsize.height = (int) ( i_corrected_height * factor );
357 /* Calculate the window's new size */
358 new_frame.size.width = [o_window frame].size.width -
359 [self frame].size.width + newsize.width;
360 new_frame.size.height = [o_window frame].size.height -
361 [self frame].size.height + newsize.height;
363 new_frame.origin.x = topleftscreen.x;
364 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
366 [o_window setFrame: new_frame display: animate animate: animate];
368 p_vout->i_changes |= VOUT_SIZE_CHANGE;
372 - (void)toggleFloatOnTop
376 if( !p_real_vout ) return;
377 if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool)
379 val.b_bool = VLC_FALSE;
383 val.b_bool = VLC_TRUE;
385 var_Set( p_real_vout, "video-on-top", val );
388 - (void)toggleFullscreen
391 if( !p_real_vout ) return;
392 var_Get( p_real_vout, "fullscreen", &val );
393 val.b_bool = !val.b_bool;
394 var_Set( p_real_vout, "fullscreen", val );
395 if( [self isFullscreen] )
396 [[[[VLCMain sharedInstance] getControls] getFSPanel] setActive: nil];
398 [[[[VLCMain sharedInstance] getControls] getFSPanel] setNonActive: nil];
404 var_Get( p_real_vout, "fullscreen", &val );
405 return( val.b_bool );
410 vout_Control( p_real_vout, VOUT_SNAPSHOT );
415 /* Disable Screensaver, when we're playing something, but allow it on pause */
416 if( VLCIntf->p_sys->i_play_status == PLAYING_S )
417 UpdateSystemActivity( UsrActivity );
425 - (void)keyDown:(NSEvent *)o_event
429 unsigned int i_pressed_modifiers = 0;
432 i_pressed_modifiers = [o_event modifierFlags];
434 if( i_pressed_modifiers & NSShiftKeyMask )
435 val.i_int |= KEY_MODIFIER_SHIFT;
436 if( i_pressed_modifiers & NSControlKeyMask )
437 val.i_int |= KEY_MODIFIER_CTRL;
438 if( i_pressed_modifiers & NSAlternateKeyMask )
439 val.i_int |= KEY_MODIFIER_ALT;
440 if( i_pressed_modifiers & NSCommandKeyMask )
441 val.i_int |= KEY_MODIFIER_COMMAND;
443 key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0];
447 /* Escape should always get you out of fullscreen */
448 if( key == (unichar) 0x1b )
450 if( p_real_vout && [self isFullscreen] )
452 [self toggleFullscreen];
455 else if ( key == ' ' )
458 val.i_int = config_GetInt( p_vout, "key-play-pause" );
459 var_Set( p_vout->p_libvlc, "key-pressed", val );
463 val.i_int |= CocoaKeyToVLC( key );
464 var_Set( p_vout->p_libvlc, "key-pressed", val );
469 [super keyDown: o_event];
473 - (void)mouseDown:(NSEvent *)o_event
479 if( ( [o_event type] == NSLeftMouseDown ) &&
480 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
482 if( [o_event clickCount] <= 1 )
484 /* single clicking */
485 var_Get( p_vout, "mouse-button-down", &val );
487 var_Set( p_vout, "mouse-button-down", val );
491 /* multiple clicking */
492 [self toggleFullscreen];
495 else if( ( [o_event type] == NSRightMouseDown ) ||
496 ( ( [o_event type] == NSLeftMouseDown ) &&
497 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
499 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
500 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]];
504 [super mouseDown: o_event];
507 - (void)otherMouseDown:(NSEvent *)o_event
511 if( p_vout && [o_event type] == NSOtherMouseDown )
513 var_Get( p_vout, "mouse-button-down", &val );
515 var_Set( p_vout, "mouse-button-down", val );
518 [super mouseDown: o_event];
521 - (void)rightMouseDown:(NSEvent *)o_event
523 if( p_vout && [o_event type] == NSRightMouseDown )
525 msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" );
526 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]];
529 [super mouseDown: o_event];
532 - (void)mouseUp:(NSEvent *)o_event
536 if( p_vout && [o_event type] == NSLeftMouseUp )
539 b_val.b_bool = VLC_TRUE;
540 var_Set( p_vout, "mouse-clicked", b_val );
542 var_Get( p_vout, "mouse-button-down", &val );
544 var_Set( p_vout, "mouse-button-down", val );
547 [super mouseUp: o_event];
550 - (void)otherMouseUp:(NSEvent *)o_event
554 if( p_vout && [o_event type] == NSOtherMouseUp )
556 var_Get( p_vout, "mouse-button-down", &val );
558 var_Set( p_vout, "mouse-button-down", val );
561 [super mouseUp: o_event];
564 - (void)rightMouseUp:(NSEvent *)o_event
566 if( p_vout && [o_event type] == NSRightMouseUp )
568 /* FIXME: this isn't the appropriate place, but we can't receive
569 * NSRightMouseDown some how */
570 msg_Dbg( p_vout, "received NSRightMouseUp" );
571 [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]];
574 [super mouseUp: o_event];
577 - (void)mouseDragged:(NSEvent *)o_event
579 [self mouseMoved: o_event];
582 - (void)otherMouseDragged:(NSEvent *)o_event
584 [self mouseMoved: o_event];
587 - (void)rightMouseDragged:(NSEvent *)o_event
589 [self mouseMoved: o_event];
592 - (void)mouseMoved:(NSEvent *)o_event
600 s_rect = [o_view bounds];
601 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
602 b_inside = [o_view mouse: ml inRect: s_rect];
607 unsigned int i_width, i_height, i_x, i_y;
609 vout_PlacePicture( p_vout, (unsigned int)s_rect.size.width,
610 (unsigned int)s_rect.size.height,
611 &i_x, &i_y, &i_width, &i_height );
613 val.i_int = ( ((int)ml.x) - i_x ) *
614 p_vout->render.i_width / i_width;
615 var_Set( p_vout, "mouse-x", val );
617 if( [[o_view className] isEqualToString: @"VLCGLView"] )
619 val.i_int = ( ((int)(s_rect.size.height - ml.y)) - i_y ) *
620 p_vout->render.i_height / i_height;
624 val.i_int = ( ((int)ml.y) - i_y ) *
625 p_vout->render.i_height / i_height;
627 var_Set( p_vout, "mouse-y", val );
629 val.b_bool = VLC_TRUE;
630 var_Set( p_vout, "mouse-moved", val );
632 if( [self isFullscreen] )
633 [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeIn];
636 [super mouseMoved: o_event];
639 - (BOOL)acceptsFirstResponder
644 - (BOOL)becomeFirstResponder
649 - (BOOL)resignFirstResponder
651 /* We need to stay the first responder or we'll miss some
656 /* Class methods used by the different vout modules */
658 + (vout_thread_t *)getRealVout: (vout_thread_t *)p_vout
660 /* p_real_vout: the vout we have to use to check for video-on-top
661 and a few other things. If we are the QuickTime output, it's us.
662 It we are the OpenGL provider, it is our parent. */
663 if( p_vout->i_object_type == VLC_OBJECT_OPENGL )
665 return (vout_thread_t *) p_vout->p_parent;
674 + (id)getVoutView: (vout_thread_t *)p_vout subView: (NSView *)view
675 frame: (NSRect *)s_frame
677 vlc_value_t value_drawable;
681 var_Get( p_vout->p_libvlc, "drawable", &value_drawable );
683 var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
684 var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
685 var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
686 var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
687 var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
688 var_Create( p_vout, "macosx-embedded", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
691 /* We only wait for NSApp to initialise if we're not embedded (as in the
692 * case of the Mozilla plugin). We can tell whether we're embedded or not
693 * by examining the "drawable" value: if it's zero, we're running in the
694 * main Mac intf; if it's non-zero, we're embedded. */
695 if( value_drawable.i_int == 0 )
697 /* Wait for a MacOS X interface to appear. Timeout is 2 seconds. */
698 for( i_timeout = 20 ; i_timeout-- ; )
702 msleep( INTF_IDLE_SLEEP );
708 /* No MacOS X intf, unable to communicate with MT */
709 msg_Err( p_vout, "no MacOS X interface present" );
714 if ( VLCIntf && !(p_vout->b_fullscreen) &&
715 !(var_GetBool( p_vout, "macosx-background" )) &&
716 var_GetBool( p_vout, "macosx-embedded") )
718 o_return = [[[VLCMain sharedInstance] getEmbeddedList]
724 /* No embedded vout is available */
725 if( o_return == nil )
728 bzero( &null_rect, sizeof( NSRect ) );
729 o_return = [[VLCDetachedVoutView alloc] initWithFrame: null_rect ];
731 [o_return setVout: p_vout subView: view frame: s_frame];
737 /*****************************************************************************
738 * VLCDetachedVoutView implementation
739 *****************************************************************************/
740 @implementation VLCDetachedVoutView
742 - (id)initWithFrame: (NSRect)frameRect
744 [super initWithFrame: frameRect];
745 i_time_mouse_last_moved = 0;
749 - (bool)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
750 frame: (NSRect *) s_arg_frame
752 BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame];
753 i_time_mouse_last_moved = mdate();
754 o_window = [[VLCWindow alloc] initWithVout: p_arg_vout view: self
757 [view setFrame: [self frame]];
759 if( var_GetBool( p_real_vout, "video-on-top" ) )
761 [o_window setLevel: NSStatusWindowLevel];
765 [o_window setAcceptsMouseMovedEvents: TRUE];
771 [o_window closeWindow];
772 [o_window setAcceptsMouseMovedEvents: NO];
773 i_time_mouse_last_moved = 0;
777 - (void)mouseMoved:(NSEvent *)o_event
779 i_time_mouse_last_moved = mdate();
780 [super mouseMoved: o_event];
783 - (void)hideMouse:(BOOL)b_hide
787 NSView *o_contents = [o_window contentView];
789 ml = [o_window convertScreenToBase:[NSEvent mouseLocation]];
790 ml = [o_contents convertPoint:ml fromView:nil];
791 b_inside = [o_contents mouse: ml inRect: [o_contents bounds]];
793 if( b_hide && b_inside )
795 [NSCursor setHiddenUntilMouseMoves: YES];
799 [NSCursor setHiddenUntilMouseMoves: NO];
806 if( p_vout->b_fullscreen )
808 if( mdate() - i_time_mouse_last_moved > 3000000 )
810 [self hideMouse: YES];
815 [self hideMouse: NO];
821 /*****************************************************************************
822 * VLCEmbeddedVoutView implementation
823 *****************************************************************************/
825 @implementation VLCEmbeddedVoutView
827 - (id)initWithFrame: (NSRect)frameRect
829 [super initWithFrame: frameRect];
831 [[[VLCMain sharedInstance] getEmbeddedList] addEmbeddedVout: self];
835 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
836 frame: (NSRect *) s_arg_frame
840 b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
843 o_window = [self window];
844 [o_window makeKeyAndOrderFront: self];
845 [o_window setAcceptsMouseMovedEvents: TRUE];
847 if( var_GetBool( p_real_vout, "video-on-top" ) )
849 [o_window setLevel: NSStatusWindowLevel];
852 [view setFrameSize: [self frame].size];
857 - (void)setUsed: (BOOL)b_new_used
870 [o_window setAcceptsMouseMovedEvents: NO];
871 [[[VLCMain sharedInstance] getEmbeddedList] releaseEmbeddedVout: self];
877 @implementation VLCDetachedEmbeddedVoutView
879 - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view
880 frame: (NSRect *) s_arg_frame
882 BOOL b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame];
886 [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
888 [self scaleWindowWithFactor: 1.0 animate: NO];
889 [o_window makeKeyAndOrderFront: self];
896 [o_window orderOut: self];
902 /*****************************************************************************
903 * VLCWindow implementation
904 *****************************************************************************/
905 @implementation VLCWindow
907 - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view
908 frame: (NSRect *) frame
914 [self performSelectorOnMainThread: @selector(initReal:)
915 withObject: NULL waitUntilDone: YES];
925 - (id)initReal: (id) sender
927 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
928 NSArray *o_screens = [NSScreen screens];
930 vlc_bool_t b_menubar_screen = VLC_FALSE;
933 b_init_ok = VLC_FALSE;
935 p_real_vout = [VLCVoutView getRealVout: p_vout];
936 i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" );
937 b_black = var_GetBool( p_vout, "macosx-black" );
938 b_embedded = var_GetBool( p_vout, "macosx-embedded" );
940 /* Find out on which screen to open the window */
941 if( i_device <= 0 || i_device > (int)[o_screens count] )
943 /* No preference specified. Use the main screen */
944 o_screen = [NSScreen mainScreen];
945 i_device = [o_screens indexOfObject: o_screen];
946 if( o_screen == [o_screens objectAtIndex: 0] )
947 b_menubar_screen = VLC_TRUE;
952 o_screen = [o_screens objectAtIndex: i_device];
953 b_menubar_screen = ( i_device == 0 );
956 if( p_vout->b_fullscreen )
958 CGDisplayFadeReservationToken token;
959 NSRect screen_rect = [o_screen frame];
960 screen_rect.origin.x = screen_rect.origin.y = 0;
962 /* move the FSPanel to front in case that it is currently shown
963 * this won't and is not supposed to work when it's fading right now */
964 if( [[[[VLCMain sharedInstance] getControls] getFSPanel] isDisplayed] )
965 [[[[VLCMain sharedInstance] getControls] getFSPanel] orderFront: self];
967 /* tell the fspanel to move itself to front next time it's triggered */
968 [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: i_device];
970 /* Creates a window with size: screen_rect on o_screen */
971 [self initWithContentRect: screen_rect
972 styleMask: NSBorderlessWindowMask
973 backing: NSBackingStoreBuffered
974 defer: YES screen: o_screen];
976 if( b_black == VLC_TRUE )
978 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
979 CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, true );
980 CGReleaseDisplayFadeReservation( token );
982 for( i = 0 ; i < [o_screens count]; i++)
986 CGDirectDisplayID displayID;
987 CGGammaValue redMin, redMax, redGamma,
988 greenMin, greenMax, greenGamma,
989 blueMin, blueMax, blueGamma;
991 CGDisplayCount dspyCnt;
994 if( i == (unsigned int)i_device ) continue;
996 screen_rect = [[o_screens objectAtIndex: i] frame];
998 gPoint.x = screen_rect.origin.x;
999 gPoint.y = screen_rect.origin.y;
1000 CGGetDisplaysWithPoint( gPoint, 1, &(dispSettings.displayID), &dspyCnt);
1001 CGGetDisplayTransferByFormula(
1002 dispSettings.displayID,
1003 &dispSettings.redMin, &dispSettings.redMax, &dispSettings.redGamma,
1004 &dispSettings.greenMin, &dispSettings.greenMax, &dispSettings.greenGamma,
1005 &dispSettings.blueMin, &dispSettings.blueMax, &dispSettings.blueGamma );
1006 CGSetDisplayTransferByFormula(
1007 dispSettings.displayID,
1008 dispSettings.redMin, 0, dispSettings.redGamma,
1009 dispSettings.greenMin, 0, dispSettings.greenGamma,
1010 dispSettings.blueMin, 0, dispSettings.blueGamma );
1013 if( b_menubar_screen )
1015 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1017 if( b_black == VLC_TRUE )
1019 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
1020 CGDisplayFade( token, 2 , kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, false );
1021 CGReleaseDisplayFadeReservation( token);
1024 else if( var_GetBool( p_vout, "macosx-background" ) )
1026 NSRect screen_rect = [o_screen frame];
1027 screen_rect.origin.x = screen_rect.origin.y = 0;
1029 /* Creates a window with size: screen_rect on o_screen */
1030 [self initWithContentRect: screen_rect
1031 styleMask: NSBorderlessWindowMask
1032 backing: NSBackingStoreBuffered
1033 defer: YES screen: o_screen];
1035 [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)];
1039 unsigned int i_stylemask = NSTitledWindowMask |
1040 NSMiniaturizableWindowMask |
1041 NSClosableWindowMask |
1042 NSResizableWindowMask;
1047 s_rect.size.width = p_vout->i_window_width;
1048 s_rect.size.height = p_vout->i_window_height;
1055 [self initWithContentRect: s_rect
1056 styleMask: i_stylemask
1057 backing: NSBackingStoreBuffered
1058 defer: YES screen: o_screen];
1060 [self setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )];
1068 [self makeKeyAndOrderFront: nil];
1069 [self setReleasedWhenClosed: YES];
1071 /* We'll catch mouse events */
1072 [self makeFirstResponder: o_view];
1074 /* Add the view. It's automatically resized to fit the window */
1075 [self setContentView: o_view];
1079 b_init_ok = VLC_TRUE;
1090 /* XXX waitUntilDone = NO to avoid a possible deadlock when hitting
1092 [self setContentView: NULL];
1093 [self performSelectorOnMainThread: @selector(closeReal:)
1094 withObject: NULL waitUntilDone: NO];
1097 - (id)closeReal:(id)sender
1099 if( b_black == VLC_TRUE )
1101 CGDisplayFadeReservationToken token;
1102 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
1103 CGDisplayFade( token, 2, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, false );
1104 CGReleaseDisplayFadeReservation( token);
1105 CGDisplayRestoreColorSyncSettings();
1107 SetSystemUIMode( kUIModeNormal, 0);
1109 /* this does only work in embedded mode */
1110 if( b_embedded == VLC_TRUE )
1111 [[[[VLCMain sharedInstance] getControls] getFSPanel] orderOut: self];
1121 - (BOOL)canBecomeKeyWindow
1126 /* Sometimes crashes VLC....
1127 - (BOOL)performKeyEquivalent:(NSEvent *)o_event
1129 return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event];
1132 /* This is actually the same as VLCControls::stop. */
1134 - (BOOL)windowShouldClose:(id)sender
1136 playlist_t * p_playlist = vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
1138 if( p_playlist == NULL )
1143 playlist_Stop( p_playlist );
1144 vlc_object_release( p_playlist );
1146 /* The window will be closed by the intf later. */