]> git.sesse.net Git - vlc/blob - modules/gui/macosx/VideoView.m
macosx: fix recursive inclusion of the compatibility header
[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 #import <string.h>
34
35 #import "CompatibilityFixes.h"
36 #import "intf.h"
37 #import "VideoView.h"
38 #import "CoreInteraction.h"
39 #import "MainMenu.h"
40 #import "MainWindow.h"
41
42 #import <vlc_common.h>
43 #import <vlc_keys.h>
44
45
46 /*****************************************************************************
47  * VLCVoutView implementation
48  *****************************************************************************/
49 @implementation VLCVoutView
50
51 #pragma mark -
52 #pragma mark drag & drop support
53
54 - (void)dealloc
55 {
56     if (p_vout)
57         vlc_object_release(p_vout);
58
59     [self unregisterDraggedTypes];
60     [super dealloc];
61 }
62
63 -(id)initWithFrame:(NSRect)frameRect
64 {
65     if (self = [super initWithFrame:frameRect]) {
66         [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
67     }
68
69     i_lastScrollWheelDirection = 0;
70     f_cumulated_magnification = 0.0;
71
72     return self;
73 }
74
75 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
76 {
77     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
78         return NSDragOperationGeneric;
79     return NSDragOperationNone;
80 }
81
82 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
83 {
84     return YES;
85 }
86
87 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
88 {
89     BOOL b_returned;
90     b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
91
92     [self setNeedsDisplay:YES];
93     return b_returned;
94 }
95
96 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
97 {
98     [self setNeedsDisplay:YES];
99 }
100
101 #pragma mark -
102 #pragma mark vout actions
103
104 - (void)keyDown:(NSEvent *)o_event
105 {
106     unichar key = 0;
107     vlc_value_t val;
108     unsigned int i_pressed_modifiers = 0;
109     val.i_int = 0;
110
111     i_pressed_modifiers = [o_event modifierFlags];
112
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;
121
122     NSString * characters = [o_event charactersIgnoringModifiers];
123     if ([characters length] > 0) {
124         key = [[characters lowercaseString] characterAtIndex: 0];
125
126         if (key) {
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];
132             }
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];
136             else if (p_vout) {
137                 val.i_int |= (int)CocoaKeyToVLC(key);
138                 var_Set(p_vout->p_libvlc, "key-pressed", val);
139             }
140             else
141                 msg_Dbg(VLCIntf, "could not send keyevent to VLC core");
142
143             return;
144         }
145     }
146     [super keyDown: o_event];
147 }
148
149 - (BOOL)performKeyEquivalent:(NSEvent *)o_event
150 {
151     return [[VLCMainWindow sharedInstance] performKeyEquivalent: o_event];
152 }
153
154 - (void)mouseDown:(NSEvent *)o_event
155 {
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];
163
164     [super mouseDown: o_event];
165 }
166
167 - (void)rightMouseDown:(NSEvent *)o_event
168 {
169     if ([o_event type] == NSRightMouseDown)
170         [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
171
172     [super mouseDown: o_event];
173 }
174
175 - (void)rightMouseUp:(NSEvent *)o_event
176 {
177     if ([o_event type] == NSRightMouseUp)
178         [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
179
180     [super mouseUp: o_event];
181 }
182
183 - (void)mouseMoved:(NSEvent *)o_event
184 {
185     NSPoint ml = [self convertPoint: [o_event locationInWindow] fromView: nil];
186     if ([self mouse: ml inRect: [self bounds]])
187         [[VLCMain sharedInstance] showFullscreenController];
188
189     [super mouseMoved: o_event];
190 }
191
192 - (void)resetScrollWheelDirection
193 {
194     /* release the scroll direction 0.8 secs after the last event */
195     if (([NSDate timeIntervalSinceReferenceDate] - t_lastScrollEvent) >= 0.80)
196         i_lastScrollWheelDirection = 0;
197 }
198
199 - (void)scrollWheel:(NSEvent *)theEvent
200 {
201     intf_thread_t * p_intf = VLCIntf;
202     CGFloat f_deltaX = [theEvent deltaX];
203     CGFloat f_deltaY = [theEvent deltaY];
204
205     if (!OSX_SNOW_LEOPARD && [theEvent isDirectionInvertedFromDevice]) {
206         f_deltaX = -f_deltaX;
207         f_deltaY = -f_deltaY;
208     }
209
210     CGFloat f_yabsvalue = f_deltaY > 0.0f ? f_deltaY : -f_deltaY;
211     CGFloat f_xabsvalue = f_deltaX > 0.0f ? f_deltaX : -f_deltaX;
212
213     int i_yvlckey, i_xvlckey = 0;
214     if (f_deltaY < 0.0f)
215         i_yvlckey = KEY_MOUSEWHEELDOWN;
216     else
217         i_yvlckey = KEY_MOUSEWHEELUP;
218
219     if (f_deltaX < 0.0f)
220         i_xvlckey = KEY_MOUSEWHEELRIGHT;
221     else
222         i_xvlckey = KEY_MOUSEWHEELLEFT;
223
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
229             return;
230
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);
234
235         t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
236         [self performSelector:@selector(resetScrollWheelDirection)
237                    withObject: NULL
238                    afterDelay:1.00];
239         return;
240     }
241     if (f_xabsvalue > 0.05) {
242         if (i_lastScrollWheelDirection > 0) // last was a Y
243             return;
244
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);
248
249         t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
250         [self performSelector:@selector(resetScrollWheelDirection)
251                    withObject: NULL
252                    afterDelay:1.00];
253     }
254 }
255
256 #pragma mark -
257 #pragma mark Handling of vout related actions
258
259 - (void)setVoutThread:(vout_thread_t *)p_vout_thread
260 {
261     assert(p_vout == NULL);
262     p_vout = p_vout_thread;
263     vlc_object_hold(p_vout);
264 }
265
266 - (vout_thread_t *)voutThread
267 {
268     if (p_vout) {
269         vlc_object_hold(p_vout);
270         return p_vout;
271     }
272
273     return NULL;
274 }
275
276 - (void)releaseVoutThread
277 {
278     if (p_vout) {
279         vlc_object_release(p_vout);
280         p_vout = NULL;
281     }
282 }
283
284 #pragma mark -
285 #pragma mark Basic view behaviour and touch events handling
286
287 - (BOOL)mouseDownCanMoveWindow
288 {
289     return YES;
290 }
291
292 - (BOOL)acceptsFirstResponder
293 {
294     return YES;
295 }
296
297 - (BOOL)becomeFirstResponder
298 {
299     return YES;
300 }
301
302 - (BOOL)resignFirstResponder
303 {
304     /* while we need to be the first responder most of the time, we need to give up that status when toggling the playlist */
305     return YES;
306 }
307
308 -(void)didAddSubview:(NSView *)subview
309 {
310     [[self window] makeFirstResponder: subview];
311 }
312
313 - (void)magnifyWithEvent:(NSEvent *)event
314 {
315     f_cumulated_magnification += [event magnification];
316
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];
321
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];
325     }
326 }
327
328 - (void)beginGestureWithEvent:(NSEvent *)event
329 {
330     f_cumulated_magnification = 0.0;
331 }
332
333 @end