X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fvout.m;h=9f738b050292fab7b92940e10e004fb433e22ebf;hb=135139eaaf6bcb9008f8a6f689bc6ade226a12c7;hp=3bb355f64bb43dd8ff492540d0c51f596c2c4129;hpb=acb0bedc7d7ff9e341ae9f872d581eac13e895af;p=vlc diff --git a/modules/gui/macosx/vout.m b/modules/gui/macosx/vout.m index 3bb355f64b..9f738b0502 100644 --- a/modules/gui/macosx/vout.m +++ b/modules/gui/macosx/vout.m @@ -1,7 +1,7 @@ /***************************************************************************** * vout.m: MacOS X video output module ***************************************************************************** - * Copyright (C) 2001-2005 the VideoLAN team + * Copyright (C) 2001-2008 the VideoLAN team * $Id$ * * Authors: Colin Delacroix @@ -10,6 +10,7 @@ * Derk-Jan Hartman * Eric Petit * Benjamin Pracht + * Felix Paul Kühne * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +32,7 @@ *****************************************************************************/ #include /* ENOMEM */ #include /* free() */ -#include /* strerror() */ +#include /* BeginFullScreen, EndFullScreen */ #include @@ -39,8 +40,10 @@ #include #include "intf.h" +#include "fspanel.h" #include "vout.h" - +#import "controls.h" +#import "embeddedwindow.h" /***************************************************************************** * DeviceCallback: Callback triggered when the video-device variable is changed @@ -52,10 +55,10 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, vout_thread_t *p_vout = (vout_thread_t *)p_this; msg_Dbg( p_vout, "set %d", new_val.i_int ); - var_Create( p_vout->p_vlc, "video-device", VLC_VAR_INTEGER ); - var_Set( p_vout->p_vlc, "video-device", new_val ); + var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER ); + var_Set( p_vout->p_libvlc, "video-device", new_val ); - val.b_bool = VLC_TRUE; + val.b_bool = true; var_Set( p_vout, "intf-change", val ); return VLC_SUCCESS; } @@ -97,7 +100,7 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, } else { - msg_Warn( VLCIntf, "Cannot find Video Output"); + msg_Warn( VLCIntf, "cannot find Video Output"); } } @@ -111,9 +114,9 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (BOOL)windowContainsEmbedded: (id)o_window { -/* if( ![[o_window className] isEqualToString: @"VLCWindow"] ) +/* if( ![[o_window className] isEqualToString: @"VLCVoutWindow"] ) { - NSLog( @"We were not given a VLCWindow" ); + NSLog( @"We were not given a VLCVoutWindow" ); }*/ return ([self getViewForWindow: o_window] == nil ? NO : YES ); } @@ -140,7 +143,7 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, *****************************************************************************/ @implementation VLCVoutView -- (id)initWithFrame:(NSRect)frameRect +- (id)initWithFrame: (NSRect)frameRect { [super initWithFrame: frameRect]; p_vout = NULL; @@ -152,8 +155,9 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, return self; } -- (BOOL)setVout: (vout_thread_t *) vout subView: (NSView *) view - frame: (NSRect *) frame +- (BOOL)setVout: (vout_thread_t *) vout + subView: (NSView *) view + frame: (NSRect *) frame { int i_device; NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; @@ -172,13 +176,13 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, p_real_vout = [VLCVoutView getRealVout: p_vout]; /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */ - if( var_Type( p_real_vout->p_vlc, "video-device" ) == 0 ) + if( var_Type( p_real_vout->p_libvlc, "video-device" ) == 0 ) { i_device = var_GetInteger( p_vout, "macosx-vdev" ); } else { - i_device = var_GetInteger( p_real_vout->p_vlc, "video-device" ); + i_device = var_GetInteger( p_real_vout->p_libvlc, "video-device" ); } /* Setup the menuitem for the multiple displays. */ @@ -190,7 +194,7 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, var_Create( p_real_vout, "video-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); - text.psz_string = _("Video Device"); + text.psz_string = _("Fullscreen Video Device"); var_Change( p_real_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL ); NSEnumerator * o_enumerator = [o_screens objectEnumerator]; @@ -211,10 +215,10 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, (int)s_rect.size.width, (int)s_rect.size.height ); text.psz_string = psz_temp; - val2.i_int = i; + val2.i_int = (int)[o_screen displayID]; var_Change( p_real_vout, "video-device", VLC_VAR_ADDCHOICE, &val2, &text ); - if( i == i_device ) + if( (int)[o_screen displayID] == i_device ) { var_Set( p_real_vout, "video-device", val2 ); } @@ -224,7 +228,7 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, var_AddCallback( p_real_vout, "video-device", DeviceCallback, NULL ); - val2.b_bool = VLC_TRUE; + val2.b_bool = true; var_Set( p_real_vout, "intf-change", val2 ); } @@ -242,8 +246,21 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, [o_view setFrameSize: [self frame].size]; } +- (void)drawRect:(NSRect)rect +{ + /* When there is no subview we draw a black background */ + [self lockFocus]; + [[NSColor blackColor] set]; + NSRectFill(rect); + [self unlockFocus]; +} + - (void)closeVout { + [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeOut]; + + /* Make sure we don't see a white flash */ + [[self window] disableScreenUpdatesUntilFlush]; [o_view removeFromSuperview]; o_view = nil; p_vout = NULL; @@ -254,44 +271,61 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (void)updateTitle { - NSMutableString * o_title = nil, * o_mrl = nil; + NSString * o_title = nil; + NSMutableString * o_mrl = nil; input_thread_t * p_input; + char * psz_title; - if( p_vout == NULL ) - { - return; - } + if( !p_vout ) return; p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT ); - if( p_input == NULL ) - { - return; - } + if( !p_input ) return; + + input_item_t * p_item = input_GetItem( p_input ); + + psz_title = input_item_GetNowPlaying ( p_item ); + if( !psz_title ) + psz_title = input_item_GetName( p_item ); + + if( psz_title ) + o_title = [NSString stringWithUTF8String: psz_title]; + + char *psz_uri = input_item_GetURI( p_item ); + if( psz_uri ) + o_mrl = [NSMutableString stringWithUTF8String: psz_uri]; - if( p_input->input.p_item->psz_name != NULL ) - o_title = [NSMutableString stringWithUTF8String: - p_input->input.p_item->psz_name]; - if( p_input->input.p_item->psz_uri != NULL ) - o_mrl = [NSMutableString stringWithUTF8String: - p_input->input.p_item->psz_uri]; - if( o_title == nil ) + free( psz_title ); + free( psz_uri ); + + if( !o_title ) o_title = o_mrl; if( o_mrl != nil ) { - if( p_input->input.p_access && !strcmp( p_input->input.p_access->p_module->psz_shortname, "File" ) ) + /* FIXME once psz_access is exported, we could check if we are + * reading from a file in a smarter way. */ + + NSRange prefix_range = [o_mrl rangeOfString: @"file:"]; + if( prefix_range.location != NSNotFound ) + [o_mrl deleteCharactersInRange: prefix_range]; + + if( [o_mrl characterAtIndex:0] == '/' ) { - NSRange prefix_range = [o_mrl rangeOfString: @"file:"]; - if( prefix_range.location != NSNotFound ) - [o_mrl deleteCharactersInRange: prefix_range]; + /* it's a local file */ [o_window setRepresentedFilename: o_mrl]; } + else + { + /* it's from the network or somewhere else, + * we clear the previous path */ + [o_window setRepresentedFilename: @""]; + } [o_window setTitle: o_title]; } else { - [o_window setTitle: [NSString stringWithCString: VOUT_TITLE]]; + [o_window setTitle: [NSString stringWithUTF8String: VOUT_TITLE]]; } vlc_object_release( p_input ); } @@ -309,47 +343,62 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, } } -- (void)scaleWindowWithFactor: (float)factor +- (NSSize)voutSizeForFactor: (float)factor { - NSSize newsize; int i_corrected_height, i_corrected_width; - NSPoint topleftbase; - NSPoint topleftscreen; + NSSize newsize; + + if( p_vout->render.i_height * p_vout->render.i_aspect > + p_vout->render.i_width * VOUT_ASPECT_FACTOR ) + { + i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect / + VOUT_ASPECT_FACTOR; + newsize.width = (int) ( i_corrected_width * factor ); + newsize.height = (int) ( p_vout->render.i_height * factor ); + } + else + { + i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR / + p_vout->render.i_aspect; + newsize.width = (int) ( p_vout->render.i_width * factor ); + newsize.height = (int) ( i_corrected_height * factor ); + } + + return newsize; +} +- (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate +{ if ( !p_vout->b_fullscreen ) { + NSSize newsize; + NSPoint topleftbase; + NSPoint topleftscreen; + NSView *mainView; NSRect new_frame; topleftbase.x = 0; topleftbase.y = [o_window frame].size.height; topleftscreen = [o_window convertBaseToScreen: topleftbase]; - if( p_vout->render.i_height * p_vout->render.i_aspect > - p_vout->render.i_width * VOUT_ASPECT_FACTOR ) - { - i_corrected_width = p_vout->render.i_height * p_vout->render.i_aspect / - VOUT_ASPECT_FACTOR; - newsize.width = (int) ( i_corrected_width * factor ); - newsize.height = (int) ( p_vout->render.i_height * factor ); - } + newsize = [self voutSizeForFactor:factor]; + + /* In fullscreen mode we need to use a view that is different from + * ourselves, with the VLCEmbeddedWindow */ + if([o_window isKindOfClass:[VLCEmbeddedWindow class]]) + mainView = [o_window mainView]; else - { - i_corrected_height = p_vout->render.i_width * VOUT_ASPECT_FACTOR / - p_vout->render.i_aspect; - newsize.width = (int) ( p_vout->render.i_width * factor ); - newsize.height = (int) ( i_corrected_height * factor ); - } + mainView = self; /* Calculate the window's new size */ new_frame.size.width = [o_window frame].size.width - - [self frame].size.width + newsize.width; + [mainView frame].size.width + newsize.width; new_frame.size.height = [o_window frame].size.height - - [self frame].size.height + newsize.height; + [mainView frame].size.height + newsize.height; new_frame.origin.x = topleftscreen.x; new_frame.origin.y = topleftscreen.y - new_frame.size.height; - [o_window setFrame: new_frame display: YES]; - + [o_window setFrame:new_frame display:animate animate:animate]; p_vout->i_changes |= VOUT_SIZE_CHANGE; } } @@ -358,13 +407,14 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, { vlc_value_t val; + if( !p_real_vout ) return; if( var_Get( p_real_vout, "video-on-top", &val )>=0 && val.b_bool) { - val.b_bool = VLC_FALSE; + val.b_bool = false; } else { - val.b_bool = VLC_TRUE; + val.b_bool = true; } var_Set( p_real_vout, "video-on-top", val ); } @@ -372,6 +422,7 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (void)toggleFullscreen { vlc_value_t val; + if( !p_real_vout ) return; var_Get( p_real_vout, "fullscreen", &val ); val.b_bool = !val.b_bool; var_Set( p_real_vout, "fullscreen", val ); @@ -380,6 +431,7 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (BOOL)isFullscreen { vlc_value_t val; + if( !p_real_vout ) return NO; var_Get( p_real_vout, "fullscreen", &val ); return( val.b_bool ); } @@ -391,8 +443,12 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (void)manage { - /* Disable Screensaver */ - UpdateSystemActivity( UsrActivity ); + /* Disable Screensaver, when we're playing something, but allow it on pause */ + if( !VLCIntf || !VLCIntf->p_sys || !VLCIntf->p_sys->i_play_status ) + return; + + if( VLCIntf->p_sys->i_play_status == PLAYING_S ) + UpdateSystemActivity( UsrActivity ); } - (id)getWindow @@ -400,6 +456,12 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, return o_window; } +- (void)scrollWheel:(NSEvent *)theEvent +{ + VLCControls * o_controls = (VLCControls *)[[NSApp delegate] getControls]; + [o_controls scrollWheel: theEvent]; +} + - (void)keyDown:(NSEvent *)o_event { unichar key = 0; @@ -418,176 +480,133 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, if( i_pressed_modifiers & NSCommandKeyMask ) val.i_int |= KEY_MODIFIER_COMMAND; - key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0]; + key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0]; if( key ) { /* Escape should always get you out of fullscreen */ if( key == (unichar) 0x1b ) { - if( [self isFullscreen] ) + if( p_real_vout && [self isFullscreen] ) { [self toggleFullscreen]; } } - else if ( key == ' ' ) - { - vlc_value_t val; - val.i_int = config_GetInt( p_vout, "key-play-pause" ); - var_Set( p_vout->p_vlc, "key-pressed", val ); - } - else + else if ( p_vout ) { - val.i_int |= CocoaKeyToVLC( key ); - var_Set( p_vout->p_vlc, "key-pressed", val ); + if( key == ' ') + val.i_int = config_GetInt( p_vout, "key-play-pause" ); + else + val.i_int |= (int)CocoaKeyToVLC( key ); + var_Set( p_vout->p_libvlc, "key-pressed", val ); } + else NSLog( @"Could not send keyevent to VLC core" ); } else - { [super keyDown: o_event]; - } } - (void)mouseDown:(NSEvent *)o_event { vlc_value_t val; - if( p_vout ) { - switch( [o_event type] ) + if( ( [o_event type] == NSLeftMouseDown ) && + ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) ) { - case NSLeftMouseDown: + if( [o_event clickCount] <= 1 ) { + /* single clicking */ var_Get( p_vout, "mouse-button-down", &val ); val.i_int |= 1; var_Set( p_vout, "mouse-button-down", val ); } - break; - - default: - [super mouseDown: o_event]; - break; + else + { + /* multiple clicking */ + [self toggleFullscreen]; + } + } + else if( ( [o_event type] == NSRightMouseDown ) || + ( ( [o_event type] == NSLeftMouseDown ) && + ( [o_event modifierFlags] & NSControlKeyMask ) ) ) + { + msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" ); + [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]]; } } + + [super mouseDown: o_event]; } - (void)otherMouseDown:(NSEvent *)o_event { vlc_value_t val; - if( p_vout ) + if( p_vout && [o_event type] == NSOtherMouseDown ) { - switch( [o_event type] ) - { - case NSOtherMouseDown: - { - var_Get( p_vout, "mouse-button-down", &val ); - val.i_int |= 2; - var_Set( p_vout, "mouse-button-down", val ); - } - break; - - default: - [super mouseDown: o_event]; - break; - } + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int |= 2; + var_Set( p_vout, "mouse-button-down", val ); } + + [super mouseDown: o_event]; } - (void)rightMouseDown:(NSEvent *)o_event { - vlc_value_t val; - - if( p_vout ) + if( p_vout && [o_event type] == NSRightMouseDown ) { - switch( [o_event type] ) - { - case NSRightMouseDown: - { - var_Get( p_vout, "mouse-button-down", &val ); - val.i_int |= 4; - var_Set( p_vout, "mouse-button-down", val ); - } - break; - - default: - [super mouseDown: o_event]; - break; - } + msg_Dbg( p_vout, "received NSRightMouseDown (specific method)" ); + [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]]; } + + [super mouseDown: o_event]; } - (void)mouseUp:(NSEvent *)o_event { vlc_value_t val; - if( p_vout ) + if( p_vout && [o_event type] == NSLeftMouseUp ) { - switch( [o_event type] ) - { - case NSLeftMouseUp: - { - vlc_value_t b_val; - b_val.b_bool = VLC_TRUE; - var_Set( p_vout, "mouse-clicked", b_val ); + vlc_value_t b_val; + b_val.b_bool = true; + var_Set( p_vout, "mouse-clicked", b_val ); - var_Get( p_vout, "mouse-button-down", &val ); - val.i_int &= ~1; - var_Set( p_vout, "mouse-button-down", val ); - } - break; - - default: - [super mouseUp: o_event]; - break; - } + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int &= ~1; + var_Set( p_vout, "mouse-button-down", val ); } + + [super mouseUp: o_event]; } - (void)otherMouseUp:(NSEvent *)o_event { vlc_value_t val; - if( p_vout ) + if( p_vout && [o_event type] == NSOtherMouseUp ) { - switch( [o_event type] ) - { - case NSOtherMouseUp: - { - var_Get( p_vout, "mouse-button-down", &val ); - val.i_int &= ~2; - var_Set( p_vout, "mouse-button-down", val ); - } - break; - - default: - [super mouseUp: o_event]; - break; - } + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int &= ~2; + var_Set( p_vout, "mouse-button-down", val ); } + + [super mouseUp: o_event]; } - (void)rightMouseUp:(NSEvent *)o_event { - vlc_value_t val; - - if( p_vout ) + if( p_vout && [o_event type] == NSRightMouseUp ) { - switch( [o_event type] ) - { - case NSRightMouseUp: - { - var_Get( p_vout, "mouse-button-down", &val ); - val.i_int &= ~4; - var_Set( p_vout, "mouse-button-down", val ); - } - break; - - default: - [super mouseUp: o_event]; - break; - } + /* FIXME: this isn't the appropriate place, but we can't receive + * NSRightMouseDown some how */ + msg_Dbg( p_vout, "received NSRightMouseUp" ); + [NSMenu popUpContextMenu: [[VLCMain sharedInstance] getVoutMenu] withEvent: o_event forView: [[[VLCMain sharedInstance] getControls] getVoutView]]; } + + [super mouseUp: o_event]; } - (void)mouseDragged:(NSEvent *)o_event @@ -642,10 +661,13 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, } var_Set( p_vout, "mouse-y", val ); - val.b_bool = VLC_TRUE; + val.b_bool = true; var_Set( p_vout, "mouse-moved", val ); } + if( [self isFullscreen] ) + [[[[VLCMain sharedInstance] getControls] getFSPanel] fadeIn]; } + [super mouseMoved: o_event]; } @@ -690,18 +712,15 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, vlc_value_t value_drawable; int i_timeout; id o_return = nil; - vout_thread_t * p_real_vout = [VLCVoutView getRealVout: p_vout]; - var_Get( p_vout->p_vlc, "drawable", &value_drawable ); + var_Get( p_vout->p_libvlc, "drawable", &value_drawable ); var_Create( p_vout, "macosx-vdev", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); - var_Create( p_vout, "macosx-fill", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "macosx-stretch", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "macosx-opaqueness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); var_Create( p_vout, "macosx-background", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "macosx-black", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - var_Create( p_vout, "macosx-embedded", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); - + var_Create( p_vout, "embedded-video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); /* We only wait for NSApp to initialise if we're not embedded (as in the * case of the Mozilla plugin). We can tell whether we're embedded or not @@ -727,8 +746,8 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, else { if ( VLCIntf && !(p_vout->b_fullscreen) && - !(var_GetBool( p_real_vout, "macosx-background" )) && - var_GetBool( p_vout, "macosx-embedded") ) + !(var_GetBool( p_vout, "macosx-background" )) && + var_GetBool( p_vout, "embedded-video") ) { o_return = [[[VLCMain sharedInstance] getEmbeddedList] getEmbeddedVout]; @@ -747,6 +766,22 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, return o_return; } +- (void)enterFullscreen +{ + /* Save the settings for next playing item */ + playlist_t * p_playlist = pl_Yield( p_real_vout ); + var_SetBool( p_playlist, "fullscreen", true ); + pl_Release( p_real_vout ); +} + +- (void)leaveFullscreen +{ + /* Save the settings for next playing item */ + playlist_t * p_playlist = pl_Yield( p_real_vout ); + var_SetBool( p_playlist, "fullscreen", false ); + pl_Release( p_real_vout ); +} + @end /***************************************************************************** @@ -761,23 +796,31 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, return self; } +- (BOOL)mouseDownCanMoveWindow +{ + return YES; +} + - (bool)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view frame: (NSRect *) s_arg_frame { BOOL b_return = [super setVout: p_arg_vout subView: view frame:s_arg_frame]; i_time_mouse_last_moved = mdate(); - o_window = [[VLCWindow alloc] initWithVout: p_arg_vout view: self + o_window = [[VLCVoutWindow alloc] initWithVout: p_arg_vout view: self frame: s_arg_frame]; + [self updateTitle]; - [view setFrame: [self frame]]; - [o_window setAcceptsMouseMovedEvents: TRUE]; + if([self isFullscreen]) + [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES]; + else + [view setFrame: [self frame]]; + return b_return; } - (void)closeVout { - [o_window closeWindow]; - [o_window setAcceptsMouseMovedEvents: NO]; + [o_window performSelectorOnMainThread: @selector(close) withObject: NULL waitUntilDone: YES]; i_time_mouse_last_moved = 0; [super closeVout]; } @@ -810,11 +853,18 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (void)manage { + /* Dooh, why do we spend processor time doing this kind of stuff? */ [super manage]; + unsigned int i_mouse_hide_timeout = + var_CreateGetInteger(p_vout, "mouse-hide-timeout") * 1000; + + if( i_mouse_hide_timeout < 100000 ) + i_mouse_hide_timeout = 100000; if( p_vout->b_fullscreen ) { - if( mdate() - i_time_mouse_last_moved > 3000000 ) + if( mdate() - i_time_mouse_last_moved > i_mouse_hide_timeout ) { + i_time_mouse_last_moved = mdate(); [self hideMouse: YES]; } } @@ -824,6 +874,29 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, } } + +- (void)enterFullscreen +{ + [o_window performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: NO]; + [super enterFullscreen]; + +} + +- (void)leaveFullscreen +{ + [o_window performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: NO]; + [super leaveFullscreen]; +} + + +- (void)scaleWindowWithFactor: (float)factor animate: (BOOL)animate +{ + if( p_vout->b_fullscreen ) + return; + [o_window setMovableByWindowBackground: NO]; + [super scaleWindowWithFactor: factor animate: animate]; + [o_window setMovableByWindowBackground: YES]; +} @end /***************************************************************************** @@ -832,27 +905,78 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, @implementation VLCEmbeddedVoutView +- (void)awakeFromNib +{ + o_embeddedwindow = [self window]; +} + +- (BOOL)mouseDownCanMoveWindow +{ + return YES; +} + - (id)initWithFrame: (NSRect)frameRect { - [super initWithFrame: frameRect]; - b_used = NO; - [[[VLCMain sharedInstance] getEmbeddedList] addEmbeddedVout: self]; + if(self = [super initWithFrame: frameRect]) + { + b_used = NO; + [[[VLCMain sharedInstance] getEmbeddedList] addEmbeddedVout: self]; + o_embeddedwindow = nil; /* Filled later on in -awakeFromNib */ + } return self; } - (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view - frame: (NSRect *) s_arg_frame - + frame: (NSRect *)s_arg_frame { BOOL b_return; + + [NSObject cancelPreviousPerformRequestsWithTarget:o_window]; + b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame]; if( b_return ) { o_window = [self window]; - [o_window makeKeyAndOrderFront: self]; + [o_window setAcceptsMouseMovedEvents: TRUE]; + + if( var_CreateGetBool( p_real_vout, "video-on-top" ) ) + { + [o_window setLevel: NSStatusWindowLevel]; + } + [view setFrameSize: [self frame].size]; } + + /* o_window needs to point to our o_embeddedwindow, super might have set it + * to the fullscreen window that o_embeddedwindow setups during fullscreen */ + o_window = o_embeddedwindow; + + if( b_return ) + { + [o_window lockFullscreenAnimation]; + + [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )]; + + [self updateTitle]; + + [NSObject cancelPreviousPerformRequestsWithTarget:o_window]; + + /* Make the window the front and key window before animating */ + if ([o_window isVisible] && (![o_window isFullscreen])) + [o_window makeKeyAndOrderFront: self]; + + [self scaleWindowWithFactor: 1.0 animate: [o_window isVisible] && (![o_window isFullscreen])]; + + [o_embeddedwindow setVideoRatio:[self voutSizeForFactor:1.0]]; + + /* Make sure our window is visible, if we are not in fullscreen */ + if (![o_window isFullscreen]) + [o_window makeKeyAndOrderFront: self]; + [o_window unlockFullscreenAnimation]; + + } + return b_return; } @@ -869,42 +993,38 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, - (void)closeVout { [super closeVout]; - [o_window setAcceptsMouseMovedEvents: NO]; - [[[VLCMain sharedInstance] getEmbeddedList] releaseEmbeddedVout: self]; -} + /* Don't close the window yet, wait a bit to see if a new input is poping up */ + /* FIXME: Probably fade the window In and Out */ + /* FIXME: fix core */ + [o_embeddedwindow performSelector:@selector(orderOut:) withObject:nil afterDelay:3.]; -@end - -@implementation VLCDetachedEmbeddedVoutView + [[[VLCMain sharedInstance] getEmbeddedList] releaseEmbeddedVout: self]; +} -- (BOOL)setVout: (vout_thread_t *) p_arg_vout subView: (NSView *) view - frame: (NSRect *) s_arg_frame +- (void)enterFullscreen { - BOOL b_return = [super setVout: p_arg_vout subView: view frame: s_arg_frame]; + /* Save settings */ + [super enterFullscreen]; - if( b_return ) - { - [o_window setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )]; - [self updateTitle]; - [self scaleWindowWithFactor: 1.0]; - [o_window makeKeyAndOrderFront: self]; - } - return b_return; + /* We are in a VLCEmbeddedWindow */ + [o_embeddedwindow performSelectorOnMainThread: @selector(enterFullscreen) withObject: NULL waitUntilDone: YES]; } -- (void)closeVout +- (void)leaveFullscreen { - [o_window orderOut: self]; - [super closeVout]; -} + /* Save settings */ + [super leaveFullscreen]; + /* We are in a VLCEmbeddedWindow */ + [o_embeddedwindow performSelectorOnMainThread: @selector(leaveFullscreen) withObject: NULL waitUntilDone: YES]; +} @end /***************************************************************************** - * VLCWindow implementation + * VLCVoutWindow implementation *****************************************************************************/ -@implementation VLCWindow +@implementation VLCVoutWindow - (id) initWithVout: (vout_thread_t *) vout view: (VLCVoutView *) view frame: (NSRect *) frame @@ -912,236 +1032,122 @@ int DeviceCallback( vlc_object_t *p_this, const char *psz_variable, p_vout = vout; o_view = view; s_frame = frame; - - [self performSelectorOnMainThread: @selector(initReal:) + b_init_ok = NO; + [self performSelectorOnMainThread: @selector(initMainThread:) withObject: NULL waitUntilDone: YES]; - if( !b_init_ok ) - { - return NULL; - } - - return self; + return b_init_ok ? self : nil; } -- (id)initReal: (id) sender +- (id)initMainThread: (id) sender { - NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; - NSArray *o_screens = [NSScreen screens]; - NSScreen *o_screen; - vlc_bool_t b_menubar_screen = VLC_FALSE; - int i_device; - - b_init_ok = VLC_FALSE; + NSRect rect; + rect.size.height = p_vout->i_window_height; + rect.size.width = p_vout->i_window_width; + rect.origin.x = rect.origin.y = 70.; - p_fullscreen_state = NULL; - p_real_vout = [VLCVoutView getRealVout: p_vout]; - i_device = var_GetInteger( p_real_vout->p_vlc, "video-device" ); - - /* Find out on which screen to open the window */ - if( i_device <= 0 || i_device > (int)[o_screens count] ) + if( self = [super initWithContentRect:rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]) { - /* No preference specified. Use the main screen */ - o_screen = [NSScreen mainScreen]; - i_device = [o_screens indexOfObject: o_screen]; - if( o_screen == [o_screens objectAtIndex: 0] ) - b_menubar_screen = VLC_TRUE; - } - else - { - i_device--; - o_screen = [o_screens objectAtIndex: i_device]; - b_menubar_screen = ( i_device == 0 ); - } + [self setBackgroundColor:[NSColor blackColor]]; + [self setHasShadow:YES]; + [self setMovableByWindowBackground: YES]; + [self center]; + [self makeKeyAndOrderFront: self]; + [self setReleasedWhenClosed: YES]; + [self setFrameUsingName:@"VLCVoutWindowDetached"]; + [self setFrameAutosaveName:@"VLCVoutWindowDetached"]; + + /* We'll catch mouse events */ + [self makeFirstResponder: o_view]; + [self setCanBecomeKeyWindow: YES]; + [self setAcceptsMouseMovedEvents: YES]; + [self setIgnoresMouseEvents: NO]; + + if( var_CreateGetBool( p_vout, "macosx-background" ) ) + { + int i_device = var_GetInteger( p_vout->p_libvlc, "video-device" ); - if( p_vout->b_fullscreen ) - { - CGDisplayFadeReservationToken token; - NSRect screen_rect = [o_screen frame]; - screen_rect.origin.x = screen_rect.origin.y = 0; + /* Find out on which screen to open the window */ + NSScreen * screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device]; + if( !screen ) screen = [NSScreen mainScreen]; - /* Creates a window with size: screen_rect on o_screen */ - [self initWithContentRect: screen_rect - styleMask: NSBorderlessWindowMask - backing: NSBackingStoreBuffered - defer: YES screen: o_screen]; + NSRect screen_rect = [screen frame]; + screen_rect.origin.x = screen_rect.origin.y = 0; - if( var_GetBool( p_real_vout, "macosx-black" ) ) - { - CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); - CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, true ); - CGReleaseDisplayFadeReservation( token ); - unsigned int i; - for( i = 0 ; i < [o_screens count]; i++) - { - struct - { - CGDirectDisplayID displayID; - CGGammaValue redMin, redMax, redGamma, - greenMin, greenMax, greenGamma, - blueMin, blueMax, blueGamma; - } dispSettings; - CGDisplayCount dspyCnt; - CGPoint gPoint; - - if( i == (unsigned int)i_device ) continue; - - screen_rect = [[o_screens objectAtIndex: i] frame]; - - gPoint.x = screen_rect.origin.x; - gPoint.y = screen_rect.origin.y; - CGGetDisplaysWithPoint( gPoint, 1, &(dispSettings.displayID), &dspyCnt); - CGGetDisplayTransferByFormula( - dispSettings.displayID, - &dispSettings.redMin, &dispSettings.redMax, &dispSettings.redGamma, - &dispSettings.greenMin, &dispSettings.greenMax, &dispSettings.greenGamma, - &dispSettings.blueMin, &dispSettings.blueMax, &dispSettings.blueGamma ); - CGSetDisplayTransferByFormula( - dispSettings.displayID, - dispSettings.redMin, 0, dispSettings.redGamma, - dispSettings.greenMin, 0, dispSettings.greenGamma, - dispSettings.blueMin, 0, dispSettings.blueGamma ); - } - } - if( b_menubar_screen ) - { - BeginFullScreen( &p_fullscreen_state, NULL, 0, 0, - NULL, NULL, fullScreenAllowEvents ); + /* Creates a window with size: screen_rect on o_screen */ + [self setFrame: screen_rect display: NO]; + + [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)]; + [self setMovableByWindowBackground: NO]; } - if( var_GetBool( p_real_vout, "macosx-black" ) ) + if( var_CreateGetBool( p_vout, "video-on-top" ) ) { - CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); - CGDisplayFade( token, 2 , kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, false ); - CGReleaseDisplayFadeReservation( token); + [self setLevel: NSStatusWindowLevel]; } - } - else if( var_GetBool( p_real_vout, "macosx-background" ) ) - { - NSRect screen_rect = [o_screen frame]; - screen_rect.origin.x = screen_rect.origin.y = 0; - /* Creates a window with size: screen_rect on o_screen */ - [self initWithContentRect: screen_rect - styleMask: NSBorderlessWindowMask - backing: NSBackingStoreBuffered - defer: YES screen: o_screen]; + [self setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )]; - [self setLevel: CGWindowLevelForKey(kCGDesktopWindowLevelKey)]; + /* Add the view. It's automatically resized to fit the window */ + [self setContentView: o_view]; + + b_init_ok = YES; } - else - { - unsigned int i_stylemask = NSTitledWindowMask | - NSMiniaturizableWindowMask | - NSClosableWindowMask | - NSResizableWindowMask; + return self; +} - NSRect s_rect; - if( !s_frame ) - { - s_rect.size.width = p_vout->i_window_width; - s_rect.size.height = p_vout->i_window_height; - } - else - { - s_rect = *s_frame; - } +- (void)enterFullscreen +{ + if( fullscreen ) return; - [self initWithContentRect: s_rect - styleMask: i_stylemask - backing: NSBackingStoreBuffered - defer: YES screen: o_screen]; + NSScreen *screen; + int i_device; + BOOL b_black = NO; - [self setAlphaValue: var_GetFloat( p_vout, "macosx-opaqueness" )]; + i_device = var_GetInteger( p_vout->p_libvlc, "video-device" ); + b_black = var_CreateGetBool( p_vout, "macosx-black" ); - if( var_GetBool( p_real_vout, "video-on-top" ) ) - { - [self setLevel: NSStatusWindowLevel]; - } + /* Find out on which screen to open the window */ + screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device]; + if( !screen ) screen = [self screen]; - if( !s_frame ) - { - [self center]; - } - } + if( b_black ) + [screen blackoutOtherScreens]; - [self makeKeyAndOrderFront: nil]; - [self setReleasedWhenClosed: YES]; + [self setMovableByWindowBackground: NO]; - /* We'll catch mouse events */ - [self makeFirstResponder: o_view]; + if( [screen isMainScreen] ) + SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); - /* Add the view. It's automatically resized to fit the window */ - [self setContentView: o_view]; + initialFrame = [self frame]; + [self setFrame:[screen frame] display:YES animate:YES]; + [self setLevel:NSNormalWindowLevel]; - [o_pool release]; + /* tell the fspanel to move itself to front next time it's triggered */ + [[[[VLCMain sharedInstance] getControls] getFSPanel] setVoutWasUpdated: i_device]; + [[[[VLCMain sharedInstance] getControls] getFSPanel] setActive: nil]; - b_init_ok = VLC_TRUE; - return self; + fullscreen = YES; } -- (void)close +- (void)leaveFullscreen { - [o_view closeVout]; -} + if( !fullscreen ) return; + fullscreen = NO; -- (void) closeWindow -{ - /* XXX waitUntilDone = NO to avoid a possible deadlock when hitting - Command-Q */ - [self setContentView: NULL]; - [self performSelectorOnMainThread: @selector(closeReal:) - withObject: NULL waitUntilDone: NO]; -} + [NSScreen unblackoutScreens]; -- (id) closeReal: (id) sender -{ - if( p_fullscreen_state ) - EndFullScreen( p_fullscreen_state, 0 ); - if( var_GetBool( p_vout, "macosx-black" ) ) - { - CGDisplayFadeReservationToken token; - CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token); - CGDisplayFade( token, 2, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, false ); - CGReleaseDisplayFadeReservation( token); - CGDisplayRestoreColorSyncSettings(); - } - [super close]; - return NULL; + [[[[VLCMain sharedInstance] getControls] getFSPanel] setNonActive: nil]; + SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar); + [self setFrame:initialFrame display:YES animate:YES]; + [self setMovableByWindowBackground: YES]; + if( var_GetBool( p_vout, "video-on-top" ) ) + [self setLevel: NSStatusWindowLevel]; } -- (id)getVoutView +- (id)getVoutView // FIXME Naming scheme! { return o_view; } -- (BOOL)canBecomeKeyWindow -{ - return YES; -} - -/* Sometimes crashes VLC.... -- (BOOL)performKeyEquivalent:(NSEvent *)o_event -{ - return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event]; -}*/ - -/* This is actually the same as VLCControls::stop. */ - -- (BOOL)windowShouldClose:(id)sender -{ - playlist_t * p_playlist = vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( p_playlist == NULL ) - { - return NO; - } - - playlist_Stop( p_playlist ); - vlc_object_release( p_playlist ); - - /* The window will be closed by the intf later. */ - return NO; -} - - @end +