1 /*****************************************************************************
2 * VLCFullScreenControllerWindow.m: class that allow media controlling in
3 * fullscreen (with the mouse)
4 *****************************************************************************
5 * Copyright (C) 2007 Pierre d'Herbemont
6 * Copyright (C) 2007 the VideoLAN team
9 * Authors: Jérôme Decoodt <djc at videolan dot org>
10 * Felix Kühne <fkuehne at videolan dot org>
11 * Pierre d'Herbemont <pdherbemont # videolan.org>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
28 #import "VLCFullScreenControllerWindow.h"
30 @interface VLCFullScreenControllerWindow (Private)
33 - (void)updateTrackingRect;
36 /*****************************************************************************
37 * @implementation VLCFullScreenControllerWindow
40 @implementation VLCFullScreenControllerWindow
42 /* We override this initializer so we can set the NSBorderlessWindowMask styleMask, and set a few other important settings */
43 - (id)initWithContentRect:(NSRect)contentRect
44 styleMask:(unsigned int)aStyle
45 backing:(NSBackingStoreType)bufferingType
48 if( self = [super initWithContentRect:contentRect styleMask:NSTexturedBackgroundWindowMask backing:bufferingType defer:flag] )
51 [self setHasShadow: NO];
52 [self setBackgroundColor:[NSColor clearColor]];
54 /* let the window sit on top of everything else and start out completely transparent */
55 [self setLevel:NSFloatingWindowLevel];
63 [[NSNotificationCenter defaultCenter] removeObserver:self];
65 [hideWindowTimer invalidate];
66 [hideWindowTimer release];
67 [videoViewTrackingArea release];
73 hideWindowTimer = nil;
74 videoViewTrackingArea = nil;
76 [self setMovableByWindowBackground:YES];
78 /* Make sure we'll detect when to close the window, see animationDidStop:finished: */
79 CAAnimation *alphaValueAnimation = [CABasicAnimation animation];
80 [alphaValueAnimation setDelegate:self];
81 [self setAnimations:[NSDictionary dictionaryWithObject:alphaValueAnimation forKey:@"alphaValue"]];
82 hideWindowTimer = nil;
84 /* WindowView setup */
85 [[mainWindowController.videoView window] setAcceptsMouseMovedEvents:YES];
86 [[mainWindowController.videoView window] makeFirstResponder:mainWindowController.videoView];
87 [mainWindowController.videoView setPostsBoundsChangedNotifications: YES];
88 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoViewDidChangeBounds:) name:NSViewBoundsDidChangeNotification object:(id)mainWindowController.videoView];
90 /* Make sure we can know when the mouse is inside us */
91 [[self contentView] addTrackingRect:[[self contentView] bounds] owner:self userData:nil assumeInside:NO];
93 /* Bindings connection */
95 [volumeSlider setKnobImage:[NSImage imageNamed:@"fs_volume_slider_knob_highlight.png"]];
96 [volumeSlider setBackgroundImage:[NSImage imageNamed:@"fs_volume_slider_bar.png"]];
97 [volumeSlider setNeedsDisplay:YES];
98 [volumeSlider bind:@"value" toObject:[VLCLibrary sharedLibrary] withKeyPath:@"audio.volume" options: nil];
101 [mediaPositionSlider setKnobImage:[NSImage imageNamed:@"fs_time_slider_knob.png"]];
102 [mediaPositionSlider setBackgroundImage:[NSImage imageNamed:@"fs_time_slider.png"]];
103 [mediaPositionSlider setNeedsDisplay:YES];
105 [mediaPositionSlider bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
106 [mediaPositionSlider bind:@"enabled2" toObject:mainWindowController.mediaPlayer withKeyPath:@"seekable" options: nil];
108 [mediaPositionSlider bind:@"value" toObject:mainWindowController.mediaPlayer withKeyPath:@"position" options:
109 [NSDictionary dictionaryWithObjectsAndKeys:@"Float10000FoldTransformer", NSValueTransformerNameBindingOption,
110 [NSNumber numberWithBool:NO], NSConditionallySetsEnabledBindingOption, nil ]];
113 [fillScreenButton bind:@"value" toObject:mainWindowController.videoView withKeyPath:@"videoLayer.fillScreen" options: nil];
114 [fullScreenButton bind:@"value" toObject:mainWindowController.videoView withKeyPath:@"fullScreen" options: nil];
116 [mediaReadingProgressText bind:@"value" toObject:mainWindowController.mediaPlayer withKeyPath:@"time.stringValue" options: nil];
117 [mediaDescriptionText bind:@"value" toObject:mainWindowController.mediaPlayer withKeyPath:@"description" options: nil];
119 /* mainWindowController.mediaPlayer */
120 [mediaPlayerPlayPauseStopButton bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"media" options: [NSDictionary dictionaryWithObject:@"NonNilAsBoolTransformer" forKey:NSValueTransformerNameBindingOption]];
121 [mediaPlayerPlayPauseStopButton bind:@"state" toObject:mainWindowController.mediaPlayer withKeyPath:@"playing" options: nil];
122 [mediaPlayerPlayPauseStopButton bind:@"alternateImage" toObject:mainWindowController.mediaPlayer withKeyPath:@"stateAsFullScreenButtonAlternateImage" options: nil];
123 [mediaPlayerPlayPauseStopButton bind:@"image" toObject:mainWindowController.mediaPlayer withKeyPath:@"stateAsFullScreenButtonImage" options: nil];
124 [mediaPlayerBackwardPrevButton bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"playing" options: nil];
125 [mediaPlayerForwardNextButton bind:@"enabled" toObject:mainWindowController.mediaPlayer withKeyPath:@"playing" options: nil];
126 [mediaPlayerForwardNextButton setTarget:mainWindowController.mediaPlayer];
127 [mediaPlayerForwardNextButton setAction:@selector(fastForward)];
128 [mediaPlayerBackwardPrevButton setTarget:mainWindowController.mediaPlayer];
129 [mediaPlayerBackwardPrevButton setAction:@selector(rewind)];
130 [mediaPlayerPlayPauseStopButton setTarget:mainWindowController.mediaPlayer];
131 [mediaPlayerPlayPauseStopButton setAction:@selector(pause)];
133 [self bind:@"fullScreen" toObject:mainWindowController.videoView withKeyPath:@"fullScreen" options: nil];
140 /* Only to comply to KVC */
144 - (void)setFullScreen:(BOOL)fullScreen
160 /* centre the panel in the lower third of the screen */
161 NSPoint theCoordinate;
162 NSRect theScreensFrame;
163 NSRect theWindowsFrame;
165 theScreensFrame = [[self screen] frame];
167 theWindowsFrame = [self frame];
169 theCoordinate.x = (theScreensFrame.size.width - theWindowsFrame.size.width) / 2 + theScreensFrame.origin.x;
170 theCoordinate.y = (theScreensFrame.size.height / 3) - theWindowsFrame.size.height + theScreensFrame.origin.y;
171 [self setFrameTopLeftPoint: theCoordinate];
176 /*****************************************************************************
177 * @implementation VLCFullScreenControllerWindow (Private)
180 @implementation VLCFullScreenControllerWindow (Private)
183 if(![self isVisible])
184 self.alphaValue = 0.0;
186 if( !NSPointInRect([NSEvent mouseLocation],[self frame]) )
188 [hideWindowTimer invalidate];
189 [hideWindowTimer release];
190 hideWindowTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(hide) userInfo:nil repeats:NO] retain];
192 [self orderFront:self];
193 [self.animator setAlphaValue:1.0];
198 [hideWindowTimer invalidate];
199 [hideWindowTimer release];
200 hideWindowTimer = nil;
201 if ([self isVisible])
203 [self.animator setAlphaValue:0.0];
204 [NSCursor setHiddenUntilMouseMoves:YES];
206 [self updateTrackingRect];
209 - (void)updateTrackingRect
211 VLCBrowsableVideoView * videoView = mainWindowController.videoView;
213 if( videoViewTrackingArea )
215 [videoView removeTrackingArea:videoViewTrackingArea];
216 [videoViewTrackingArea release];
218 videoViewTrackingArea = [[NSTrackingArea alloc] initWithRect:[videoView bounds] options:NSTrackingMouseMoved|NSTrackingActiveAlways|NSTrackingAssumeInside|NSTrackingEnabledDuringMouseDrag owner:self userInfo:nil];
219 [videoView addTrackingArea:videoViewTrackingArea];
225 /*****************************************************************************
226 * @implementation VLCFullScreenControllerWindow (NSAnimationDelegate)
229 @implementation VLCFullScreenControllerWindow (NSAnimationDelegate)
230 - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
232 if( self.alphaValue == 0.0 )
233 [self orderOut:self];
237 /*****************************************************************************
238 * @implementation VLCFullScreenControllerWindow (NSTrackingRectCallbacksInVideoView)
241 @implementation VLCFullScreenControllerWindow (NSTrackingRectCallbacks)
242 - (void)mouseMoved:(NSEvent *)theEvent
244 if([theEvent window] != self)
250 - (void)mouseEntered:(NSEvent *)theEvent
252 if([theEvent window] == self)
254 [hideWindowTimer invalidate];
255 [hideWindowTimer release];
256 hideWindowTimer = nil;
259 - (void)mouseExited:(NSEvent *)theEvent
261 if([theEvent window] == self)
263 [hideWindowTimer invalidate];
264 [hideWindowTimer release];
265 hideWindowTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(hide) userInfo:nil repeats:NO] retain];
273 - (void)cursorUpdate:(NSEvent *)event
279 /*****************************************************************************
280 * @implementation VLCFullScreenControllerWindow (VideoViewBoundsChanges)
282 @implementation VLCFullScreenControllerWindow (VideoViewBoundsChanges)
283 - (void)videoViewDidChangeBounds:(NSNotification *)theNotification
285 [self updateTrackingRect];