]> git.sesse.net Git - vlc/blob - modules/gui/macosx/fspanel.m
macosx: video effects panel: synchronize text field and stepper values properly by...
[vlc] / modules / gui / macosx / fspanel.m
1 /*****************************************************************************
2  * fspanel.m: MacOS X full screen panel
3  *****************************************************************************
4  * Copyright (C) 2006-2012 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Jérôme Decoodt <djc at videolan dot org>
8  *          Felix Paul Kühne <fkuehne at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #import "intf.h"
29 #import "CoreInteraction.h"
30 #import "MainWindow.h"
31 #import "misc.h"
32 #import "fspanel.h"
33 #import "CompatibilityFixes.h"
34
35 @interface VLCFSPanel ()
36 - (void)hideMouse;
37 @end
38
39 /*****************************************************************************
40  * VLCFSPanel
41  *****************************************************************************/
42 @implementation VLCFSPanel
43 /* We override this initializer so we can set the NSBorderlessWindowMask styleMask, and set a few other important settings */
44 - (id)initWithContentRect:(NSRect)contentRect
45                 styleMask:(NSUInteger)aStyle
46                   backing:(NSBackingStoreType)bufferingType
47                     defer:(BOOL)flag
48 {
49     id win = [super initWithContentRect:contentRect styleMask:NSTexturedBackgroundWindowMask backing:bufferingType defer:flag];
50     [win setOpaque:NO];
51     [win setHasShadow: NO];
52     [win setBackgroundColor:[NSColor clearColor]];
53     if (!OSX_SNOW_LEOPARD)
54         [win setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
55
56     /* let the window sit on top of everything else and start out completely transparent */
57     [win setLevel:NSModalPanelWindowLevel];
58     i_device = 0;
59     hideAgainTimer = fadeTimer = nil;
60     [self setNonActive:nil];
61     return win;
62 }
63
64 - (void)awakeFromNib
65 {
66     [self setContentView:[[VLCFSPanelView alloc] initWithFrame: [self frame]]];
67     BOOL isInside = (NSPointInRect([NSEvent mouseLocation],[self frame]));
68     [[self contentView] addTrackingRect:[[self contentView] bounds] owner:self userData:nil assumeInside:isInside];
69     if (isInside)
70         [self mouseEntered:NULL];
71     if (!isInside)
72         [self mouseExited:NULL];
73
74     [self center];
75
76     /* get a notification if VLC isn't the active app anymore */
77     [[NSNotificationCenter defaultCenter]
78     addObserver: self
79        selector: @selector(setNonActive:)
80            name: NSApplicationDidResignActiveNotification
81          object: NSApp];
82
83     /* get a notification if VLC is the active app again */
84     [[NSNotificationCenter defaultCenter]
85     addObserver: self
86        selector: @selector(setActive:)
87            name: NSApplicationDidBecomeActiveNotification
88          object: NSApp];
89 }
90
91 /* make sure that we don't become key, since we can't handle hotkeys */
92 - (BOOL)canBecomeKeyWindow
93 {
94     return NO;
95 }
96
97 - (BOOL)mouseDownCanMoveWindow
98 {
99     return YES;
100 }
101
102 -(void)dealloc
103 {
104     [[NSNotificationCenter defaultCenter] removeObserver: self];
105
106     if (hideAgainTimer) {
107         [hideAgainTimer invalidate];
108         [hideAgainTimer release];
109     }
110
111     if (o_vout_window)
112         [o_vout_window release];
113
114     [self setFadeTimer:nil];
115     [super dealloc];
116 }
117
118 -(void)center
119 {
120     /* centre the panel in the lower third of the screen */
121     NSPoint theCoordinate;
122     NSRect theScreensFrame;
123     NSRect theWindowsFrame;
124     NSScreen *screen;
125
126     /* user-defined screen */
127     screen = [NSScreen screenWithDisplayID: (CGDirectDisplayID)i_device];
128
129     if (!screen)
130         /* invalid preferences or none specified, using main screen */
131         screen = [NSScreen mainScreen];
132
133     theScreensFrame = [screen frame];
134     theWindowsFrame = [self frame];
135
136     theCoordinate.x = (theScreensFrame.size.width - theWindowsFrame.size.width) / 2 + theScreensFrame.origin.x;
137     theCoordinate.y = (theScreensFrame.size.height / 3) - theWindowsFrame.size.height + theScreensFrame.origin.y;
138     [self setFrameTopLeftPoint: theCoordinate];
139 }
140
141 - (void)setPlay
142 {
143     [[self contentView] setPlay];
144 }
145
146 - (void)setPause
147 {
148     [[self contentView] setPause];
149 }
150
151 - (void)setStreamTitle:(NSString *)o_title
152 {
153     [[self contentView] setStreamTitle: o_title];
154 }
155
156 - (void)setStreamPos:(float) f_pos andTime:(NSString *)o_time
157 {
158     [[self contentView] setStreamPos:f_pos andTime: o_time];
159 }
160
161 - (void)setSeekable:(BOOL) b_seekable
162 {
163     [[self contentView] setSeekable: b_seekable];
164 }
165
166 - (void)setVolumeLevel: (int)i_volumeLevel
167 {
168     [[self contentView] setVolumeLevel: i_volumeLevel];
169 }
170
171 - (void)setNonActive:(id)noData
172 {
173     b_nonActive = YES;
174     [self orderOut: self];
175
176     /* here's fadeOut, just without visibly fading */
177     b_displayed = NO;
178     [self setAlphaValue:0.0];
179     [self setFadeTimer:nil];
180     b_fadeQueued = NO;
181 }
182
183 - (void)setActive:(id)noData
184 {
185     b_nonActive = NO;
186     [[VLCMain sharedInstance] showFullscreenController];
187 }
188
189 /* This routine is called repeatedly to fade in the window */
190 - (void)focus:(NSTimer *)timer
191 {
192     /* we need to push ourselves to front if the vout window was closed since our last display */
193     if (b_voutWasUpdated) {
194         [self orderFront: self];
195         b_voutWasUpdated = NO;
196     }
197
198     if ([self alphaValue] < 1.0)
199         [self setAlphaValue:[self alphaValue]+0.1];
200     if ([self alphaValue] >= 1.0) {
201         b_displayed = YES;
202         [self setAlphaValue: 1.0];
203         [self setFadeTimer:nil];
204         if (b_fadeQueued) {
205             b_fadeQueued=NO;
206             [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unfocus:) userInfo:NULL repeats:YES]];
207         }
208     }
209 }
210
211 /* This routine is called repeatedly to hide the window */
212 - (void)unfocus:(NSTimer *)timer
213 {
214     if (b_keptVisible) {
215         b_keptVisible = NO;
216         b_fadeQueued = NO;
217         [self setFadeTimer: NULL];
218         [self fadeIn];
219         return;
220     }
221     if ([self alphaValue] > 0.0)
222         [self setAlphaValue:[self alphaValue]-0.05];
223     if ([self alphaValue] <= 0.05) {
224         b_displayed = NO;
225         [self setAlphaValue:0.0];
226         [self setFadeTimer:nil];
227         if (b_fadeQueued) {
228             b_fadeQueued=NO;
229             [self setFadeTimer:
230                 [NSTimer scheduledTimerWithTimeInterval:0.1
231                                                  target:self
232                                                selector:@selector(focus:)
233                                                userInfo:NULL
234                                                 repeats:YES]];
235         }
236     }
237 }
238
239 - (void)mouseExited:(NSEvent *)theEvent
240 {
241     /* give up our focus, so the vout may show us again without letting the user clicking it */
242     if (o_vout_window && var_GetBool(pl_Get(VLCIntf), "fullscreen"))
243         [o_vout_window makeKeyWindow];
244 }
245
246 - (void)hideMouse
247 {
248     [NSCursor setHiddenUntilMouseMoves: YES];
249 }
250
251 - (void)fadeIn
252 {
253     /* in case that the user don't want us to appear, make sure we hide the mouse */
254
255     if (!config_GetInt(VLCIntf, "macosx-fspanel")) {
256         float time = (float)var_CreateGetInteger(VLCIntf, "mouse-hide-timeout") / 1000.;
257         [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(hideMouse) userInfo:nil repeats:NO]];
258         return;
259     }
260
261     if (b_nonActive)
262         return;
263
264     [self orderFront: nil];
265
266     if ([self alphaValue] < 1.0 || b_displayed != YES) {
267         if (![self fadeTimer])
268             [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(focus:) userInfo:[NSNumber numberWithShort:1] repeats:YES]];
269         else if ([[[self fadeTimer] userInfo] shortValue]==0)
270             b_fadeQueued=YES;
271     }
272     [self autoHide];
273 }
274
275 - (void)fadeOut
276 {
277     if (NSPointInRect([NSEvent mouseLocation],[self frame]))
278         return;
279
280     if (([self alphaValue] > 0.0)) {
281         if (![self fadeTimer])
282             [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(unfocus:) userInfo:[NSNumber numberWithShort:0] repeats:YES]];
283         else if ([[[self fadeTimer] userInfo] shortValue]==1)
284             b_fadeQueued=YES;
285     }
286 }
287
288 /* triggers a timer to autoHide us again after some seconds of no activity */
289 - (void)autoHide
290 {
291     /* this will tell the timer to start over again or to start at all */
292     b_keptVisible = YES;
293
294     /* get us a valid timer */
295     if (! b_alreadyCounting) {
296         i_timeToKeepVisibleInSec = var_CreateGetInteger(VLCIntf, "mouse-hide-timeout") / 500;
297         if (hideAgainTimer) {
298             [hideAgainTimer invalidate];
299             [hideAgainTimer autorelease];
300         }
301         /* released in -autoHide and -dealloc */
302         hideAgainTimer = [[NSTimer scheduledTimerWithTimeInterval: 0.5
303                                                           target: self
304                                                         selector: @selector(keepVisible:)
305                                                         userInfo: nil
306                                                          repeats: YES] retain];
307         b_alreadyCounting = YES;
308     }
309 }
310
311 - (void)keepVisible:(NSTimer *)timer
312 {
313     /* if the user triggered an action, start over again */
314     if (b_keptVisible)
315         b_keptVisible = NO;
316
317     /* count down until we hide ourselfes again and do so if necessary */
318     if (--i_timeToKeepVisibleInSec < 1) {
319         [self hideMouse];
320         [self fadeOut];
321         [hideAgainTimer invalidate]; /* released in -autoHide and -dealloc */
322         b_alreadyCounting = NO;
323     }
324 }
325
326 /* A getter and setter for our main timer that handles window fading */
327 - (NSTimer *)fadeTimer
328 {
329     return fadeTimer;
330 }
331
332 - (void)setFadeTimer:(NSTimer *)timer
333 {
334     [timer retain];
335     [fadeTimer invalidate];
336     [fadeTimer autorelease];
337     fadeTimer=timer;
338 }
339
340 - (void)mouseDown:(NSEvent *)theEvent
341 {
342     mouseClic = [theEvent locationInWindow];
343 }
344
345 - (void)mouseDragged:(NSEvent *)theEvent
346 {
347     NSPoint point = [NSEvent mouseLocation];
348     point.x -= mouseClic.x;
349     point.y -= mouseClic.y;
350     [self setFrameOrigin:point];
351 }
352
353 - (void)setVoutWasUpdated: (VLCWindow *)o_window
354 {
355     b_voutWasUpdated = YES;
356     if (o_vout_window)
357         [o_vout_window release];
358     o_vout_window = [o_window retain];
359     int i_newdevice = (int)[[o_vout_window screen] displayID];
360     if (i_newdevice != i_device) {
361         i_device = i_newdevice;
362         [self center];
363     }
364 }
365 @end
366
367 /*****************************************************************************
368  * FSPanelView
369  *****************************************************************************/
370 @implementation VLCFSPanelView
371
372 #define addButton(o_button, imageOff, imageOn, _x, _y, action, AXDesc, ToolTip)               \
373     s_rc.origin.x = _x;                                                                         \
374     s_rc.origin.y = _y;                                                                         \
375     o_button = [[NSButton alloc] initWithFrame: s_rc];                                 \
376     [o_button setButtonType: NSMomentaryChangeButton];                                          \
377     [o_button setBezelStyle: NSRegularSquareBezelStyle];                                        \
378     [o_button setBordered: NO];                                                                 \
379     [o_button setFont:[NSFont systemFontOfSize:0]];                                             \
380     [o_button setImage:[NSImage imageNamed:imageOff]];                                 \
381     [o_button setAlternateImage:[NSImage imageNamed:imageOn]];                         \
382     [o_button sizeToFit];                                                                       \
383     [o_button setTarget: self];                                                                 \
384     [o_button setAction: @selector(action:)];                                                   \
385     [[o_button cell] accessibilitySetOverrideValue:AXDesc forAttribute:NSAccessibilityDescriptionAttribute]; \
386     [[o_button cell] accessibilitySetOverrideValue:ToolTip forAttribute:NSAccessibilityTitleAttribute]; \
387     [o_button setToolTip: ToolTip]; \
388     [self addSubview:o_button];
389
390 #define addTextfield(class, o_text, align, font, color)                                    \
391     o_text = [[class alloc] initWithFrame: s_rc];                            \
392     [o_text setDrawsBackground: NO];                                                        \
393     [o_text setBordered: NO];                                                               \
394     [o_text setEditable: NO];                                                               \
395     [o_text setSelectable: NO];                                                             \
396     [o_text setStringValue: _NS("(no item is being played)")];                                                    \
397     [o_text setAlignment: align];                                                           \
398     [o_text setTextColor: [NSColor color]];                                                 \
399     [o_text setFont:[NSFont font:[NSFont smallSystemFontSize]]];                     \
400     [self addSubview:o_text];
401
402 - (id)initWithFrame:(NSRect)frameRect
403 {
404     id view = [super initWithFrame:frameRect];
405     fillColor = [[NSColor clearColor] retain];
406     NSRect s_rc = [self frame];
407     addButton(o_prev, @"fs_skip_previous" , @"fs_skip_previous_highlight", 174, 15, prev, _NS("Click to go to the previous playlist item."), _NS("Previous"));
408     addButton(o_bwd, @"fs_rewind"        , @"fs_rewind_highlight"       , 211, 14, backward, _NS("Click and hold to skip backward through the current media."), _NS("Backward"));
409     addButton(o_play, @"fs_play"          , @"fs_play_highlight"         , 267, 10, play, _NS("Click to play or pause the current media."), _NS("Play/Pause"));
410     addButton(o_fwd, @"fs_forward"       , @"fs_forward_highlight"      , 313, 14, forward, _NS("Click and hold to skip forward through the current media."), _NS("Forward"));
411     addButton(o_next, @"fs_skip_next"     , @"fs_skip_next_highlight"    , 365, 15, next, _NS("Click to go to the next playlist item."), _NS("Next"));
412     addButton(o_fullscreen, @"fs_exit_fullscreen", @"fs_exit_fullscreen_hightlight", 507, 13, toggleFullscreen, _NS("Click to exit fullscreen playback."), _NS("Toggle Fullscreen mode"));
413 /*
414     addButton(o_button, @"image (off state)", @"image (on state)", 38, 51, something, accessibility help string, usual tool tip);
415  */
416     [o_fwd setContinuous:YES];
417     [o_bwd setContinuous:YES];
418
419     /* time slider */
420     s_rc = [self frame];
421     s_rc.origin.x = 15;
422     s_rc.origin.y = 45;
423     s_rc.size.width = 518;
424     s_rc.size.height = 13;
425     o_fs_timeSlider = [[VLCFSTimeSlider alloc] initWithFrame: s_rc];
426     [o_fs_timeSlider setMinValue:0];
427     [o_fs_timeSlider setMaxValue:10000];
428     [o_fs_timeSlider setFloatValue: 0];
429     [o_fs_timeSlider setContinuous: YES];
430     [o_fs_timeSlider setTarget: self];
431     [o_fs_timeSlider setAction: @selector(fsTimeSliderUpdate:)];
432     [[o_fs_volumeSlider cell] accessibilitySetOverrideValue:_NS("Position") forAttribute:NSAccessibilityTitleAttribute];
433     [[o_fs_timeSlider cell] accessibilitySetOverrideValue:_NS("Click and move the mouse while keeping the button pressed to use this slider to change current playback position.") forAttribute:NSAccessibilityDescriptionAttribute];
434     [self addSubview: o_fs_timeSlider];
435
436     /* volume slider */
437     s_rc = [self frame];
438     s_rc.origin.x = 26;
439     s_rc.origin.y = 20;
440     s_rc.size.width = 95;
441     s_rc.size.height = 10;
442     o_fs_volumeSlider = [[VLCFSVolumeSlider alloc] initWithFrame: s_rc];
443     [o_fs_volumeSlider setMinValue:0];
444     [o_fs_volumeSlider setMaxValue:AOUT_VOLUME_MAX];
445     [o_fs_volumeSlider setIntValue:AOUT_VOLUME_DEFAULT];
446     [o_fs_volumeSlider setContinuous: YES];
447     [o_fs_volumeSlider setTarget: self];
448     [o_fs_volumeSlider setAction: @selector(fsVolumeSliderUpdate:)];
449     [[o_fs_volumeSlider cell] accessibilitySetOverrideValue:_NS("Volume") forAttribute:NSAccessibilityTitleAttribute];
450     [[o_fs_volumeSlider cell] accessibilitySetOverrideValue:_NS("Click and move the mouse while keeping the button pressed to use this slider to change the volume.") forAttribute:NSAccessibilityDescriptionAttribute];
451     [self addSubview: o_fs_volumeSlider];
452
453     /* time counter and stream title output fields */
454     s_rc = [self frame];
455     s_rc.origin.x = 98;
456     s_rc.origin.y = 64;
457     s_rc.size.width = 352;
458     s_rc.size.height = 14;
459     addTextfield(NSTextField, o_streamTitle_txt, NSCenterTextAlignment, systemFontOfSize, whiteColor);
460     s_rc.origin.x = 471;
461     s_rc.origin.y = 64;
462     s_rc.size.width = 65;
463     addTextfield(VLCTimeField, o_streamPosition_txt, NSRightTextAlignment, systemFontOfSize, whiteColor);
464
465     o_background_img = [[NSImage imageNamed:@"fs_background"] retain];
466     o_vol_sld_img = [[NSImage imageNamed:@"fs_volume_slider_bar"] retain];
467     o_vol_mute_img = [[NSImage imageNamed:@"fs_volume_mute"] retain];
468     o_vol_max_img = [[NSImage imageNamed:@"fs_volume_max"] retain];
469     o_time_sld_img = [[NSImage imageNamed:@"fs_time_slider"] retain];
470
471     return view;
472 }
473
474 - (void)dealloc
475 {
476     [o_background_img release];
477     [o_vol_sld_img release];
478     [o_vol_mute_img release];
479     [o_vol_max_img release];
480     [o_time_sld_img release];
481     [o_fs_timeSlider release];
482     [o_fs_volumeSlider release];
483     [o_prev release];
484     [o_next release];
485     [o_bwd release];
486     [o_play release];
487     [o_fwd release];
488     [o_fullscreen release];
489     [o_streamTitle_txt release];
490     [o_streamPosition_txt release];
491     [super dealloc];
492 }
493
494 - (void)setPlay
495 {
496     [o_play setImage:[NSImage imageNamed:@"fs_play"]];
497     [o_play setAlternateImage: [NSImage imageNamed:@"fs_play_highlight"]];
498 }
499
500 - (void)setPause
501 {
502     [o_play setImage: [NSImage imageNamed:@"fs_pause"]];
503     [o_play setAlternateImage: [NSImage imageNamed:@"fs_pause_highlight"]];
504 }
505
506 - (void)setStreamTitle:(NSString *)o_title
507 {
508     [o_streamTitle_txt setStringValue: o_title];
509 }
510
511 - (void)setStreamPos:(float) f_pos andTime:(NSString *)o_time
512 {
513     [o_streamPosition_txt setStringValue: o_time];
514     [o_fs_timeSlider setFloatValue: f_pos];
515 }
516
517 - (void)setSeekable:(BOOL)b_seekable
518 {
519     [o_bwd setEnabled: b_seekable];
520     [o_fwd setEnabled: b_seekable];
521     [o_fs_timeSlider setEnabled: b_seekable];
522 }
523
524 - (void)setVolumeLevel: (int)i_volumeLevel
525 {
526     [o_fs_volumeSlider setIntValue: i_volumeLevel];
527 }
528
529 - (IBAction)play:(id)sender
530 {
531     [[VLCCoreInteraction sharedInstance] play];
532 }
533
534 - (IBAction)forward:(id)sender
535 {
536     if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.16) {
537         // we just skipped 4 "continous" events, otherwise we are too fast
538         [[VLCCoreInteraction sharedInstance] forwardExtraShort];
539         last_fwd_event = [NSDate timeIntervalSinceReferenceDate];
540     }
541 }
542
543 - (IBAction)backward:(id)sender
544 {
545     if (([NSDate timeIntervalSinceReferenceDate] - last_bwd_event) > 0.16) {
546         // we just skipped 4 "continous" events, otherwise we are too fast
547         [[VLCCoreInteraction sharedInstance] backwardExtraShort];
548         last_bwd_event = [NSDate timeIntervalSinceReferenceDate];
549     }
550 }
551
552 - (IBAction)prev:(id)sender
553 {
554     [[VLCCoreInteraction sharedInstance] previous];
555 }
556
557 - (IBAction)next:(id)sender
558 {
559     [[VLCCoreInteraction sharedInstance] next];
560 }
561
562 - (IBAction)toggleFullscreen:(id)sender
563 {
564     [[VLCCoreInteraction sharedInstance] toggleFullscreen];
565 }
566
567 - (IBAction)fsTimeSliderUpdate:(id)sender
568 {
569     input_thread_t * p_input;
570     p_input = pl_CurrentInput(VLCIntf);
571     if (p_input != NULL) {
572         vlc_value_t pos;
573
574         pos.f_float = [o_fs_timeSlider floatValue] / 10000.;
575         var_Set(p_input, "position", pos);
576         vlc_object_release(p_input);
577     }
578     [[VLCMain sharedInstance] updatePlaybackPosition];
579 }
580
581 - (IBAction)fsVolumeSliderUpdate:(id)sender
582 {
583     [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
584 }
585
586 #define addImage(image, _x, _y, mode)                                                       \
587     image_size = [image size];                                                              \
588     image_rect.size = image_size;                                                           \
589     image_rect.origin.x = 0;                                                                \
590     image_rect.origin.y = 0;                                                                \
591     frame.origin.x = _x;                                                                    \
592     frame.origin.y = _y;                                                                    \
593     frame.size = image_size;                                                                \
594     [image drawInRect:frame fromRect:image_rect operation:mode fraction:1];
595
596 - (void)drawRect:(NSRect)rect
597 {
598     NSRect frame = [self frame];
599     NSRect image_rect;
600     NSSize image_size;
601     NSImage *img;
602     addImage(o_background_img, 0, 0, NSCompositeCopy);
603     addImage(o_vol_sld_img, 26, 23, NSCompositeSourceOver);
604     addImage(o_vol_mute_img, 16, 18, NSCompositeSourceOver);
605     addImage(o_vol_max_img, 124, 18, NSCompositeSourceOver);
606     addImage(o_time_sld_img, 15, 45, NSCompositeSourceOver);
607 }
608
609 @end
610
611 /*****************************************************************************
612  * VLCFSTimeSlider
613  *****************************************************************************/
614 @implementation VLCFSTimeSlider
615 - (void)drawKnobInRect:(NSRect)knobRect
616 {
617     NSRect image_rect;
618     NSImage *img = [NSImage imageNamed:@"fs_time_slider_knob_highlight"];
619     image_rect.size = [img size];
620     image_rect.origin.x = 0;
621     image_rect.origin.y = 0;
622     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
623     knobRect.size.width = image_rect.size.width;
624     knobRect.size.height = image_rect.size.height;
625     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
626 }
627
628 - (void)drawRect:(NSRect)rect
629 {
630     /* Draw default to make sure the slider behaves correctly */
631     [[NSGraphicsContext currentContext] saveGraphicsState];
632     NSRectClip(NSZeroRect);
633     [super drawRect:rect];
634     [[NSGraphicsContext currentContext] restoreGraphicsState];
635
636     NSRect knobRect = [[self cell] knobRectFlipped:NO];
637     knobRect.origin.y+=4;
638     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
639     [self drawKnobInRect: knobRect];
640 }
641
642 @end
643
644 /*****************************************************************************
645 * VLCFSVolumeSlider
646 *****************************************************************************/
647 @implementation VLCFSVolumeSlider
648 - (void)drawKnobInRect:(NSRect) knobRect
649 {
650     NSRect image_rect;
651     NSImage *img = [NSImage imageNamed:@"fs_volume_slider_knob"];
652     image_rect.size = [img size];
653     image_rect.origin.x = 0;
654     image_rect.origin.y = 0;
655     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
656     knobRect.size.width = image_rect.size.width;
657     knobRect.size.height = image_rect.size.height;
658     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
659 }
660
661 - (void)drawRect:(NSRect)rect
662 {
663     /* Draw default to make sure the slider behaves correctly */
664     [[NSGraphicsContext currentContext] saveGraphicsState];
665     NSRectClip(NSZeroRect);
666     [super drawRect:rect];
667     [[NSGraphicsContext currentContext] restoreGraphicsState];
668
669     NSRect knobRect = [[self cell] knobRectFlipped:NO];
670     knobRect.origin.y+=6;
671     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
672     [self drawKnobInRect: knobRect];
673 }
674
675 @end
676