1 /*****************************************************************************
2 * VideoView.m: MacOS X video output module
3 *****************************************************************************
4 * Copyright (C) 2002-2014 VLC authors and VideoLAN
7 * Authors: Derk-Jan Hartman <hartman at videolan dot org>
8 * Eric Petit <titer@m0k.org>
9 * Benjamin Pracht <bigben at videolan dot org>
10 * Pierre d'Herbemont <pdherbemont # videolan org>
11 * Felix Paul Kühne <fkuehne at videolan dot org>
12 * David Fuhrmann <david dot fuhrmann at googlemail dot com>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27 *****************************************************************************/
29 /*****************************************************************************
31 *****************************************************************************/
32 #import <stdlib.h> /* free() */
35 #import "CompatibilityFixes.h"
38 #import "CoreInteraction.h"
40 #import "MainWindow.h"
42 #import <vlc_common.h>
46 /*****************************************************************************
47 * VLCVoutView implementation
48 *****************************************************************************/
49 @implementation VLCVoutView
52 #pragma mark drag & drop support
57 vlc_object_release(p_vout);
59 [self unregisterDraggedTypes];
63 -(id)initWithFrame:(NSRect)frameRect
65 if (self = [super initWithFrame:frameRect]) {
66 [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
69 i_lastScrollWheelDirection = 0;
70 f_cumulated_magnification = 0.0;
75 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
77 if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
78 return NSDragOperationGeneric;
79 return NSDragOperationNone;
82 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
87 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
90 b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
92 [self setNeedsDisplay:YES];
96 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
98 [self setNeedsDisplay:YES];
102 #pragma mark vout actions
104 - (void)keyDown:(NSEvent *)o_event
108 unsigned int i_pressed_modifiers = 0;
111 i_pressed_modifiers = [o_event modifierFlags];
113 if (i_pressed_modifiers & NSShiftKeyMask)
114 val.i_int |= KEY_MODIFIER_SHIFT;
115 if (i_pressed_modifiers & NSControlKeyMask)
116 val.i_int |= KEY_MODIFIER_CTRL;
117 if (i_pressed_modifiers & NSAlternateKeyMask)
118 val.i_int |= KEY_MODIFIER_ALT;
119 if (i_pressed_modifiers & NSCommandKeyMask)
120 val.i_int |= KEY_MODIFIER_COMMAND;
122 NSString * characters = [o_event charactersIgnoringModifiers];
123 if ([characters length] > 0) {
124 key = [[characters lowercaseString] characterAtIndex: 0];
127 /* Escape should always get you out of fullscreen */
128 if (key == (unichar) 0x1b) {
129 playlist_t * p_playlist = pl_Get(VLCIntf);
130 if (var_GetBool(p_playlist, "fullscreen"))
131 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
133 /* handle Lion's default key combo for fullscreen-toggle in addition to our own hotkeys */
134 else if (key == 'f' && i_pressed_modifiers & NSControlKeyMask && i_pressed_modifiers & NSCommandKeyMask)
135 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
137 val.i_int |= (int)CocoaKeyToVLC(key);
138 var_Set(p_vout->p_libvlc, "key-pressed", val);
141 msg_Dbg(VLCIntf, "could not send keyevent to VLC core");
146 [super keyDown: o_event];
149 - (BOOL)performKeyEquivalent:(NSEvent *)o_event
151 return [[VLCMainWindow sharedInstance] performKeyEquivalent: o_event];
154 - (void)mouseDown:(NSEvent *)o_event
156 if (([o_event type] == NSLeftMouseDown) && (! ([o_event modifierFlags] & NSControlKeyMask))) {
157 if ([o_event clickCount] > 1)
158 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
159 } else if (([o_event type] == NSRightMouseDown) ||
160 (([o_event type] == NSLeftMouseDown) &&
161 ([o_event modifierFlags] & NSControlKeyMask)))
162 [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
164 [super mouseDown: o_event];
167 - (void)rightMouseDown:(NSEvent *)o_event
169 if ([o_event type] == NSRightMouseDown)
170 [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
172 [super mouseDown: o_event];
175 - (void)rightMouseUp:(NSEvent *)o_event
177 if ([o_event type] == NSRightMouseUp)
178 [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
180 [super mouseUp: o_event];
183 - (void)mouseMoved:(NSEvent *)o_event
185 NSPoint ml = [self convertPoint: [o_event locationInWindow] fromView: nil];
186 if ([self mouse: ml inRect: [self bounds]])
187 [[VLCMain sharedInstance] showFullscreenController];
189 [super mouseMoved: o_event];
192 - (void)resetScrollWheelDirection
194 /* release the scroll direction 0.8 secs after the last event */
195 if (([NSDate timeIntervalSinceReferenceDate] - t_lastScrollEvent) >= 0.80)
196 i_lastScrollWheelDirection = 0;
199 - (void)scrollWheel:(NSEvent *)theEvent
201 intf_thread_t * p_intf = VLCIntf;
202 CGFloat f_deltaX = [theEvent deltaX];
203 CGFloat f_deltaY = [theEvent deltaY];
205 if (!OSX_SNOW_LEOPARD && [theEvent isDirectionInvertedFromDevice]) {
206 f_deltaX = -f_deltaX;
207 f_deltaY = -f_deltaY;
210 CGFloat f_yabsvalue = f_deltaY > 0.0f ? f_deltaY : -f_deltaY;
211 CGFloat f_xabsvalue = f_deltaX > 0.0f ? f_deltaX : -f_deltaX;
213 int i_yvlckey, i_xvlckey = 0;
215 i_yvlckey = KEY_MOUSEWHEELDOWN;
217 i_yvlckey = KEY_MOUSEWHEELUP;
220 i_xvlckey = KEY_MOUSEWHEELRIGHT;
222 i_xvlckey = KEY_MOUSEWHEELLEFT;
224 /* in the following, we're forwarding either a x or a y event */
225 /* Multiple key events are send depending on the intensity of the event */
226 /* the opposite direction is being blocked for 0.8 secs */
227 if (f_yabsvalue > 0.05) {
228 if (i_lastScrollWheelDirection < 0) // last was a X
231 i_lastScrollWheelDirection = 1; // Y
232 for (NSUInteger i = 0; i < (int)(f_yabsvalue/4.+1.); i++)
233 var_SetInteger(p_intf->p_libvlc, "key-pressed", i_yvlckey);
235 t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
236 [self performSelector:@selector(resetScrollWheelDirection)
241 if (f_xabsvalue > 0.05) {
242 if (i_lastScrollWheelDirection > 0) // last was a Y
245 i_lastScrollWheelDirection = -1; // X
246 for (NSUInteger i = 0; i < (int)(f_xabsvalue/6.+1.); i++)
247 var_SetInteger(p_intf->p_libvlc, "key-pressed", i_xvlckey);
249 t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
250 [self performSelector:@selector(resetScrollWheelDirection)
257 #pragma mark Handling of vout related actions
259 - (void)setVoutThread:(vout_thread_t *)p_vout_thread
261 assert(p_vout == NULL);
262 p_vout = p_vout_thread;
263 vlc_object_hold(p_vout);
266 - (vout_thread_t *)voutThread
269 vlc_object_hold(p_vout);
276 - (void)releaseVoutThread
279 vlc_object_release(p_vout);
285 #pragma mark Basic view behaviour and touch events handling
287 - (BOOL)mouseDownCanMoveWindow
292 - (BOOL)acceptsFirstResponder
297 - (BOOL)becomeFirstResponder
302 - (BOOL)resignFirstResponder
304 /* while we need to be the first responder most of the time, we need to give up that status when toggling the playlist */
308 -(void)didAddSubview:(NSView *)subview
310 [[self window] makeFirstResponder: subview];
313 - (void)magnifyWithEvent:(NSEvent *)event
315 f_cumulated_magnification += [event magnification];
317 // This is the result of [NSEvent standardMagnificationThreshold].
318 // Unfortunately, this is a private API, currently.
319 CGFloat f_threshold = 0.3;
320 BOOL b_fullscreen = [(VLCVideoWindowCommon *)[self window] fullscreen];
322 if ((f_cumulated_magnification > f_threshold && !b_fullscreen) || (f_cumulated_magnification < -f_threshold && b_fullscreen)) {
323 f_cumulated_magnification = 0.0;
324 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
328 - (void)beginGestureWithEvent:(NSEvent *)event
330 f_cumulated_magnification = 0.0;