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