]> git.sesse.net Git - vlc/blob - modules/gui/macosx/VideoView.m
macosx: do not handle triple clicks explicitely
[vlc] / modules / gui / macosx / VideoView.m
1 /*****************************************************************************
2  * VideoView.m: MacOS X video output module
3  *****************************************************************************
4  * Copyright (C) 2002-2014 VLC authors and VideoLAN
5  * $Id$
6  *
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>
13  *
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.
18  *
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.
23  *
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  *****************************************************************************/
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 #import <stdlib.h>                                                 /* free() */
33
34 #import "CompatibilityFixes.h"
35 #import "intf.h"
36 #import "VideoView.h"
37 #import "CoreInteraction.h"
38 #import "MainMenu.h"
39
40 #import <vlc_keys.h>
41
42
43 /*****************************************************************************
44  * VLCVoutView implementation
45  *****************************************************************************/
46 @implementation VLCVoutView
47
48 #pragma mark -
49 #pragma mark drag & drop support
50
51 - (void)dealloc
52 {
53     if (p_vout)
54         vlc_object_release(p_vout);
55
56     [self unregisterDraggedTypes];
57     [super dealloc];
58 }
59
60 -(id)initWithFrame:(NSRect)frameRect
61 {
62     if (self = [super initWithFrame:frameRect]) {
63         [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
64     }
65
66     i_lastScrollWheelDirection = 0;
67     f_cumulated_magnification = 0.0;
68
69     return self;
70 }
71
72 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
73 {
74     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
75         return NSDragOperationGeneric;
76     return NSDragOperationNone;
77 }
78
79 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
80 {
81     return YES;
82 }
83
84 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
85 {
86     BOOL b_returned;
87     b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
88
89     [self setNeedsDisplay:YES];
90     return b_returned;
91 }
92
93 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
94 {
95     [self setNeedsDisplay:YES];
96 }
97
98 #pragma mark -
99 #pragma mark vout actions
100
101 - (void)keyDown:(NSEvent *)o_event
102 {
103     unichar key = 0;
104     vlc_value_t val;
105     unsigned int i_pressed_modifiers = 0;
106     val.i_int = 0;
107
108     i_pressed_modifiers = [o_event modifierFlags];
109
110     if (i_pressed_modifiers & NSShiftKeyMask)
111         val.i_int |= KEY_MODIFIER_SHIFT;
112     if (i_pressed_modifiers & NSControlKeyMask)
113         val.i_int |= KEY_MODIFIER_CTRL;
114     if (i_pressed_modifiers & NSAlternateKeyMask)
115         val.i_int |= KEY_MODIFIER_ALT;
116     if (i_pressed_modifiers & NSCommandKeyMask)
117         val.i_int |= KEY_MODIFIER_COMMAND;
118
119     NSString * characters = [o_event charactersIgnoringModifiers];
120     if ([characters length] > 0) {
121         key = [[characters lowercaseString] characterAtIndex: 0];
122
123         if (key) {
124             /* Escape should always get you out of fullscreen */
125             if (key == (unichar) 0x1b) {
126                 playlist_t * p_playlist = pl_Get(VLCIntf);
127                  if (var_GetBool(p_playlist, "fullscreen"))
128                      [[VLCCoreInteraction sharedInstance] toggleFullscreen];
129             }
130             /* handle Lion's default key combo for fullscreen-toggle in addition to our own hotkeys */
131             else if (key == 'f' && i_pressed_modifiers & NSControlKeyMask && i_pressed_modifiers & NSCommandKeyMask)
132                 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
133             else if (p_vout) {
134                 val.i_int |= (int)CocoaKeyToVLC(key);
135                 var_Set(p_vout->p_libvlc, "key-pressed", val);
136             }
137             else
138                 msg_Dbg(VLCIntf, "could not send keyevent to VLC core");
139
140             return;
141         }
142     }
143     [super keyDown: o_event];
144 }
145
146 - (BOOL)performKeyEquivalent:(NSEvent *)o_event
147 {
148     return [[VLCMainWindow sharedInstance] performKeyEquivalent: o_event];
149 }
150
151 - (void)mouseDown:(NSEvent *)o_event
152 {
153     if (([o_event type] == NSLeftMouseDown) && (! ([o_event modifierFlags] &  NSControlKeyMask))) {
154         if ([o_event clickCount] == 2)
155             [[VLCCoreInteraction sharedInstance] toggleFullscreen];
156
157     } else if (([o_event type] == NSRightMouseDown) ||
158                (([o_event type] == NSLeftMouseDown) &&
159                ([o_event modifierFlags] &  NSControlKeyMask)))
160         [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
161
162     [super mouseDown: o_event];
163 }
164
165 - (void)rightMouseDown:(NSEvent *)o_event
166 {
167     if ([o_event type] == NSRightMouseDown)
168         [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
169
170     [super mouseDown: o_event];
171 }
172
173 - (void)rightMouseUp:(NSEvent *)o_event
174 {
175     if ([o_event type] == NSRightMouseUp)
176         [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
177
178     [super mouseUp: o_event];
179 }
180
181 - (void)mouseMoved:(NSEvent *)o_event
182 {
183     NSPoint ml = [self convertPoint: [o_event locationInWindow] fromView: nil];
184     if ([self mouse: ml inRect: [self bounds]])
185         [[VLCMain sharedInstance] showFullscreenController];
186
187     [super mouseMoved: o_event];
188 }
189
190 - (void)resetScrollWheelDirection
191 {
192     /* release the scroll direction 0.8 secs after the last event */
193     if (([NSDate timeIntervalSinceReferenceDate] - t_lastScrollEvent) >= 0.80)
194         i_lastScrollWheelDirection = 0;
195 }
196
197 - (void)scrollWheel:(NSEvent *)theEvent
198 {
199     intf_thread_t * p_intf = VLCIntf;
200     CGFloat f_deltaX = [theEvent deltaX];
201     CGFloat f_deltaY = [theEvent deltaY];
202
203     if (!OSX_SNOW_LEOPARD && [theEvent isDirectionInvertedFromDevice]) {
204         f_deltaX = -f_deltaX;
205         f_deltaY = -f_deltaY;
206     }
207
208     CGFloat f_yabsvalue = f_deltaY > 0.0f ? f_deltaY : -f_deltaY;
209     CGFloat f_xabsvalue = f_deltaX > 0.0f ? f_deltaX : -f_deltaX;
210
211     int i_yvlckey, i_xvlckey = 0;
212     if (f_deltaY < 0.0f)
213         i_yvlckey = KEY_MOUSEWHEELDOWN;
214     else
215         i_yvlckey = KEY_MOUSEWHEELUP;
216
217     if (f_deltaX < 0.0f)
218         i_xvlckey = KEY_MOUSEWHEELRIGHT;
219     else
220         i_xvlckey = KEY_MOUSEWHEELLEFT;
221
222     /* in the following, we're forwarding either a x or a y event */
223     /* Multiple key events are send depending on the intensity of the event */
224     /* the opposite direction is being blocked for 0.8 secs */
225     if (f_yabsvalue > 0.05) {
226         if (i_lastScrollWheelDirection < 0) // last was a X
227             return;
228
229         i_lastScrollWheelDirection = 1; // Y
230         for (NSUInteger i = 0; i < (int)(f_yabsvalue/4.+1.); i++)
231             var_SetInteger(p_intf->p_libvlc, "key-pressed", i_yvlckey);
232
233         t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
234         [self performSelector:@selector(resetScrollWheelDirection)
235                    withObject: NULL
236                    afterDelay:1.00];
237         return;
238     }
239     if (f_xabsvalue > 0.05) {
240         if (i_lastScrollWheelDirection > 0) // last was a Y
241             return;
242
243         i_lastScrollWheelDirection = -1; // X
244         for (NSUInteger i = 0; i < (int)(f_xabsvalue/6.+1.); i++)
245             var_SetInteger(p_intf->p_libvlc, "key-pressed", i_xvlckey);
246
247         t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
248         [self performSelector:@selector(resetScrollWheelDirection)
249                    withObject: NULL
250                    afterDelay:1.00];
251     }
252 }
253
254 #pragma mark -
255 #pragma mark Handling of vout related actions
256
257 - (void)setVoutThread:(vout_thread_t *)p_vout_thread
258 {
259     assert(p_vout == NULL);
260     p_vout = p_vout_thread;
261     vlc_object_hold(p_vout);
262 }
263
264 - (vout_thread_t *)voutThread
265 {
266     if (p_vout) {
267         vlc_object_hold(p_vout);
268         return p_vout;
269     }
270
271     return NULL;
272 }
273
274 - (void)releaseVoutThread
275 {
276     if (p_vout) {
277         vlc_object_release(p_vout);
278         p_vout = NULL;
279     }
280 }
281
282 #pragma mark -
283 #pragma mark Basic view behaviour and touch events handling
284
285 - (BOOL)mouseDownCanMoveWindow
286 {
287     return YES;
288 }
289
290 - (BOOL)acceptsFirstResponder
291 {
292     return YES;
293 }
294
295 - (BOOL)becomeFirstResponder
296 {
297     return YES;
298 }
299
300 - (BOOL)resignFirstResponder
301 {
302     /* while we need to be the first responder most of the time, we need to give up that status when toggling the playlist */
303     return YES;
304 }
305
306 -(void)didAddSubview:(NSView *)subview
307 {
308     [[self window] makeFirstResponder: subview];
309 }
310
311 - (void)magnifyWithEvent:(NSEvent *)event
312 {
313     f_cumulated_magnification += [event magnification];
314
315     // This is the result of [NSEvent standardMagnificationThreshold].
316     // Unfortunately, this is a private API, currently.
317     CGFloat f_threshold = 0.3;
318     BOOL b_fullscreen = [(VLCVideoWindowCommon *)[self window] fullscreen];
319
320     if ((f_cumulated_magnification > f_threshold && !b_fullscreen) || (f_cumulated_magnification < -f_threshold && b_fullscreen)) {
321         f_cumulated_magnification = 0.0;
322         [[VLCCoreInteraction sharedInstance] toggleFullscreen];
323     }
324 }
325
326 - (void)beginGestureWithEvent:(NSEvent *)event
327 {
328     f_cumulated_magnification = 0.0;
329 }
330
331 @end