X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fmisc.m;h=afd485a3ef0e415c544fdf0e284817a1c2f61577;hb=38dbd37adf32cf04e1caf17ceb7888a4a5ec2f40;hp=1eaec9463cbc1fa1531cdfb6f95777950b68515c;hpb=136957ea779cccb6afe1debadb6985b3080c07e8;p=vlc diff --git a/modules/gui/macosx/misc.m b/modules/gui/macosx/misc.m index 1eaec9463c..afd485a3ef 100644 --- a/modules/gui/macosx/misc.m +++ b/modules/gui/macosx/misc.m @@ -1,7 +1,7 @@ /***************************************************************************** * misc.m: code not specific to vlc ***************************************************************************** - * Copyright (C) 2003 VideoLAN + * Copyright (C) 2003-2007 the VideoLAN team * $Id$ * * Authors: Jon Lech Johansen @@ -18,13 +18,324 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #include +#include "intf.h" /* VLCApplication */ #include "misc.h" #include "playlist.h" +#include "controls.h" + +/***************************************************************************** + * NSAnimation (VLCAdditions) + * + * Missing extension to NSAnimation + *****************************************************************************/ + +@implementation NSAnimation (VLCAdditions) +/* fake class attributes */ +static NSMapTable *VLCAdditions_userInfo = NULL; + ++ (void)load +{ + /* init our fake object attribute */ + VLCAdditions_userInfo = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 16); +} + +- (void)dealloc +{ + NSMapRemove(VLCAdditions_userInfo, self); + [super dealloc]; +} + +- (void)setUserInfo: (void *)userInfo +{ + NSMapInsert(VLCAdditions_userInfo, self, (void*)userInfo); +} + +- (void *)userInfo +{ + return NSMapGet(VLCAdditions_userInfo, self); +} +@end + +/***************************************************************************** + * NSScreen (VLCAdditions) + * + * Missing extension to NSScreen + *****************************************************************************/ + +@implementation NSScreen (VLCAdditions) + +static NSMutableArray *blackoutWindows = NULL; + ++ (void)load +{ + /* init our fake object attribute */ + blackoutWindows = [[NSMutableArray alloc] initWithCapacity:1]; +} + ++ (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID +{ + int i; + + for( i = 0; i < [[NSScreen screens] count]; i++ ) + { + NSScreen *screen = [[NSScreen screens] objectAtIndex: i]; + if([screen displayID] == displayID) + return screen; + } + return nil; +} + +- (BOOL)isMainScreen +{ + return ([self displayID] == [[[NSScreen screens] objectAtIndex:0] displayID]); +} + +- (BOOL)isScreen: (NSScreen*)screen +{ + return ([self displayID] == [screen displayID]); +} + +- (CGDirectDisplayID)displayID +{ + return (CGDirectDisplayID)_screenNumber; +} + +- (void)blackoutOtherScreens +{ + unsigned int i; + + /* Free our previous blackout window (follow blackoutWindow alloc strategy) */ + [blackoutWindows makeObjectsPerformSelector:@selector(close)]; + [blackoutWindows removeAllObjects]; + + + for(i = 0; i < [[NSScreen screens] count]; i++) + { + NSScreen *screen = [[NSScreen screens] objectAtIndex: i]; + VLCWindow *blackoutWindow; + NSRect screen_rect; + + if([self isScreen: screen]) + continue; + + screen_rect = [screen frame]; + screen_rect.origin.x = screen_rect.origin.y = 0.0f; + + /* blackoutWindow alloc strategy + - The NSMutableArray blackoutWindows has the blackoutWindow references + - blackoutOtherDisplays is responsible for alloc/releasing its Windows + */ + blackoutWindow = [[VLCWindow alloc] initWithContentRect: screen_rect styleMask: NSBorderlessWindowMask + backing: NSBackingStoreBuffered defer: NO screen: screen]; + [blackoutWindow setBackgroundColor:[NSColor blackColor]]; + [blackoutWindow setLevel: NSFloatingWindowLevel]; /* Disappear when Expose is triggered */ + + [blackoutWindow orderFront: self animate: YES]; + + [blackoutWindows addObject: blackoutWindow]; + [blackoutWindow release]; + } +} + ++ (void)unblackoutScreens +{ + unsigned int i; + + for(i = 0; i < [blackoutWindows count]; i++) + { + VLCWindow *blackoutWindow = [blackoutWindows objectAtIndex: i]; + [blackoutWindow closeAndAnimate: YES]; + } +} + +@end + +/***************************************************************************** + * VLCWindow + * + * Missing extension to NSWindow + *****************************************************************************/ + +@implementation VLCWindow +- (id)initWithContentRect:(NSRect)contentRect styleMask:(unsigned int)styleMask + backing:(NSBackingStoreType)backingType defer:(BOOL)flag +{ + self = [super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag]; + if( self ) + b_isset_canBecomeKeyWindow = NO; + return self; +} +- (void)setCanBecomeKeyWindow: (BOOL)canBecomeKey +{ + b_isset_canBecomeKeyWindow = YES; + b_canBecomeKeyWindow = canBecomeKey; +} + +- (BOOL)canBecomeKeyWindow +{ + if(b_isset_canBecomeKeyWindow) + return b_canBecomeKeyWindow; + + return [super canBecomeKeyWindow]; +} + +- (void)closeAndAnimate: (BOOL)animate +{ + NSInvocation *invoc; + + if (!animate || MACOS_VERSION < 10.4f) + { + [super close]; + return; + } + + invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(close)]]; + [invoc setTarget: (id)super]; + + if (![self isVisible] || [self alphaValue] == 0.0) + { + [super close]; + return; + } + + [self orderOut: self animate: YES callback: invoc]; +} + +- (void)orderOut: (id)sender animate: (BOOL)animate +{ + NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(orderOut:)]]; + [invoc setTarget: (id)super]; + [invoc setArgument: sender atIndex: 0]; + [self orderOut: sender animate: animate callback: invoc]; +} + +- (void)orderOut: (id)sender animate: (BOOL)animate callback:(NSInvocation *)callback +{ + NSViewAnimation *anim; + NSViewAnimation *current_anim; + NSMutableDictionary *dict; + + if (!animate || MACOS_VERSION < 10.4f) + { + [self orderOut: sender]; + return; + } + + dict = [[NSMutableDictionary alloc] initWithCapacity:2]; + + [dict setObject:self forKey:NSViewAnimationTargetKey]; + + [dict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey]; + anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; + [dict release]; + + [anim setAnimationBlockingMode:NSAnimationNonblocking]; + [anim setDuration:0.9]; + [anim setFrameRate:30]; + [anim setUserInfo: callback]; + + @synchronized(self) { + current_anim = self->animation; + + if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeOutEffect && [current_anim isAnimating]) + { + [anim release]; + } + else + { + if (current_anim) + { + [current_anim stopAnimation]; + [anim setCurrentProgress:1.0-[current_anim currentProgress]]; + [current_anim release]; + } + else + [anim setCurrentProgress:1.0 - [self alphaValue]]; + self->animation = anim; + [self setDelegate: self]; + [anim startAnimation]; + } + } +} + +- (void)orderFront: (id)sender animate: (BOOL)animate +{ + NSViewAnimation *anim; + NSViewAnimation *current_anim; + NSMutableDictionary *dict; + + if (!animate || MACOS_VERSION < 10.4f) + { + [super orderFront: sender]; + [self setAlphaValue: 1.0]; + return; + } + + if (![self isVisible]) + { + [self setAlphaValue: 0.0]; + [super orderFront: sender]; + } + else if ([self alphaValue] == 1.0) + { + [super orderFront: self]; + return; + } + + dict = [[NSMutableDictionary alloc] initWithCapacity:2]; + + [dict setObject:self forKey:NSViewAnimationTargetKey]; + + [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey]; + anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]]; + [dict release]; + + [anim setAnimationBlockingMode:NSAnimationNonblocking]; + [anim setDuration:0.5]; + [anim setFrameRate:30]; + + @synchronized(self) { + current_anim = self->animation; + + if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeInEffect && [current_anim isAnimating]) + { + [anim release]; + } + else + { + if (current_anim) + { + [current_anim stopAnimation]; + [anim setCurrentProgress:1.0 - [current_anim currentProgress]]; + [current_anim release]; + } + else + [anim setCurrentProgress:[self alphaValue]]; + self->animation = anim; + [self setDelegate: self]; + [self orderFront: sender]; + [anim startAnimation]; + } + } +} + +- (void)animationDidEnd:(NSAnimation*)anim +{ + if ([self alphaValue] <= 0.0) + { + NSInvocation * invoc; + [super orderOut: nil]; + [self setAlphaValue: 1.0]; + if ((invoc = [anim userInfo])) + [invoc invoke]; + } +} +@end /***************************************************************************** * VLCControllerWindow @@ -38,8 +349,22 @@ self = [super initWithContentRect:contentRect styleMask:styleMask //& ~NSTitledWindowMask backing:backingType defer:flag]; + [[VLCMain sharedInstance] updateTogglePlaylistState]; + return( self ); } + +- (BOOL)performKeyEquivalent:(NSEvent *)o_event +{ + /* We indeed want to prioritize Cocoa key equivalent against libvlc, + so we perform the menu equivalent now. */ + if([[NSApp mainMenu] performKeyEquivalent:o_event]) + return TRUE; + + return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event] || + [(VLCControls *)[[VLCMain sharedInstance] getControls] keyEvent:o_event]; +} + @end @@ -56,6 +381,15 @@ [super dealloc]; } +#if GC_ENABLED +- (void)finalize +{ + /* dealloc doesn't get called on 10.5 if GC is enabled, so we need to provide the basic functionality here */ + [self unregisterDraggedTypes]; + [super finalize]; +} +#endif + - (void)awakeFromNib { [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, @@ -102,7 +436,7 @@ o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"]; o_array = [o_array arrayByAddingObject: o_dic]; } - [(VLCPlaylist *)[[NSApp delegate] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; + [(VLCPlaylist *)[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; return YES; } } @@ -134,6 +468,15 @@ [super dealloc]; } +#if GC_ENABLED +- (void)finalize +{ + /* dealloc doesn't get called on 10.5 if GC is enabled, so we need to provide the basic functionality here */ + [self unregisterDraggedTypes]; + [super finalize]; +} +#endif + - (void)awakeFromNib { [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType, @@ -164,6 +507,7 @@ NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil]; NSString *o_desired_type = [o_paste availableTypeFromArray:o_types]; NSData *o_carried_data = [o_paste dataForType:o_desired_type]; + BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" ); if( o_carried_data ) { @@ -180,7 +524,10 @@ o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"]; o_array = [o_array arrayByAddingObject: o_dic]; } - [(VLCPlaylist *)[[NSApp delegate] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; + if( b_autoplay ) + [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; + else + [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:YES]; return YES; } } @@ -199,167 +546,156 @@ /***************************************************************************** * MPSlider *****************************************************************************/ - @implementation MPSlider -+ (Class)cellClass +void _drawKnobInRect(NSRect knobRect) { - return( [MPSliderCell class] ); + // Center knob in given rect + knobRect.origin.x += (int)((float)(knobRect.size.width - 7)/2.0); + knobRect.origin.y += (int)((float)(knobRect.size.height - 7)/2.0); + + // Draw diamond + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 6, 1, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 5, 3, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 4, 5, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 0, knobRect.origin.y + 3, 7, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 2, 5, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 1, 3, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 0, 1, 1), NSCompositeSourceOver); } -@end - -/***************************************************************************** - * MPSliderCell - *****************************************************************************/ - -@implementation MPSliderCell - -- (id)init +void _drawFrameInRect(NSRect frameRect) { - self = [super init]; - - if( self != nil ) - { - _bgColor = [[NSColor colorWithDeviceRed: 0.8627451 - green: 0.8784314 - blue: 0.7725490 - alpha: 1.0] retain]; - _knobColor = [[NSColor blackColor] retain]; - } - NSLog(@"boe"); - return( self ); + // Draw frame + NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y + frameRect.size.height-1, frameRect.size.width, 1), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver); + NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x+frameRect.size.width-1, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver); } -- (void)dealloc +- (void)drawRect:(NSRect)rect { - [_bgColor release]; - [_knobColor release]; - [super dealloc]; + // Draw default to make sure the slider behaves correctly + [[NSGraphicsContext currentContext] saveGraphicsState]; + NSRectClip(NSZeroRect); + [super drawRect:rect]; + [[NSGraphicsContext currentContext] restoreGraphicsState]; + + // Full size + rect = [self bounds]; + int diff = (int)(([[self cell] knobThickness] - 7.0)/2.0) - 1; + rect.origin.x += diff-1; + rect.origin.y += diff; + rect.size.width -= 2*diff-2; + rect.size.height -= 2*diff; + + // Draw dark + NSRect knobRect = [[self cell] knobRectFlipped:NO]; + [[[NSColor blackColor] colorWithAlphaComponent:0.6] set]; + _drawFrameInRect(rect); + _drawKnobInRect(knobRect); + + // Draw shadow + [[[NSColor blackColor] colorWithAlphaComponent:0.1] set]; + rect.origin.x++; + rect.origin.y++; + knobRect.origin.x++; + knobRect.origin.y++; + _drawFrameInRect(rect); + _drawKnobInRect(knobRect); } -- (void)setBackgroundColor:(NSColor *)newColor -{ - [_bgColor release]; - _bgColor = [newColor retain]; -} +@end -- (NSColor *)backgroundColor -{ - return( _bgColor ); -} -- (void)setKnobColor:(NSColor *)newColor -{ - [_knobColor release]; - _knobColor = [newColor retain]; -} +/***************************************************************************** + * ITSlider + *****************************************************************************/ -- (NSColor *)knobColor -{ - return( _knobColor ); -} +@implementation ITSlider -- (void)setKnobThickness:(float)f_value +- (void)awakeFromNib { - _knobThickness = f_value; + if ([[self cell] class] != [ITSliderCell class]) { + // replace cell + NSSliderCell *oldCell = [self cell]; + NSSliderCell *newCell = [[[ITSliderCell alloc] init] autorelease]; + [newCell setTag:[oldCell tag]]; + [newCell setTarget:[oldCell target]]; + [newCell setAction:[oldCell action]]; + [newCell setControlSize:[oldCell controlSize]]; + [newCell setType:[oldCell type]]; + [newCell setState:[oldCell state]]; + [newCell setAllowsTickMarkValuesOnly:[oldCell allowsTickMarkValuesOnly]]; + [newCell setAltIncrementValue:[oldCell altIncrementValue]]; + [newCell setControlTint:[oldCell controlTint]]; + [newCell setKnobThickness:[oldCell knobThickness]]; + [newCell setMaxValue:[oldCell maxValue]]; + [newCell setMinValue:[oldCell minValue]]; + [newCell setDoubleValue:[oldCell doubleValue]]; + [newCell setNumberOfTickMarks:[oldCell numberOfTickMarks]]; + [newCell setEditable:[oldCell isEditable]]; + [newCell setEnabled:[oldCell isEnabled]]; + [newCell setEntryType:[oldCell entryType]]; + [newCell setHighlighted:[oldCell isHighlighted]]; + [newCell setTickMarkPosition:[oldCell tickMarkPosition]]; + [self setCell:newCell]; + } } -- (float)knobThickness -{ - return( _knobThickness ); -} +@end -- (NSSize)cellSizeForBounds:(NSRect)s_rc -{ - return( s_rc.size ); -} +/***************************************************************************** + * ITSliderCell + *****************************************************************************/ +@implementation ITSliderCell -- (void)drawWithFrame:(NSRect)s_rc inView:(NSView *)o_view +- (id)init { - if( _scFlags.weAreVertical ) - { - s_rc.origin.x = 1; s_rc.size.width -= 3; - s_rc.origin.y = 2; s_rc.size.height -= 5; - } - else - { - s_rc.origin.x = 2; s_rc.size.width -= 5; - s_rc.origin.y = 1; s_rc.size.height -= 3; - } - - [super drawWithFrame: s_rc inView: o_view]; + self = [super init]; + _knobOff = [[NSImage imageNamed:@"volumeslider_normal"] retain]; + _knobOn = [[NSImage imageNamed:@"volumeslider_blue"] retain]; + b_mouse_down = FALSE; + return self; } -- (void)drawBarInside:(NSRect)s_rc flipped:(BOOL)b_flipped +- (void)dealloc { - NSRect s_arc; - - s_rc.size.width += (s_rc.origin.x * 2) + 1; - s_rc.size.height += (s_rc.origin.y * 2) + 1; - s_rc.origin.x = s_rc.origin.y = 0; - - [[NSGraphicsContext currentContext] setShouldAntialias: NO]; - - [_bgColor set]; - NSRectFill( s_rc ); - - s_arc = s_rc; - s_arc.origin.x += 1.5; - s_arc.origin.y += 1.5; - s_arc.size.width -= s_arc.origin.x; - s_arc.size.height -= s_arc.origin.y; - [[_bgColor shadowWithLevel: 0.1] set]; - [NSBezierPath strokeRect: s_arc]; - - s_arc.origin = s_rc.origin; - [[NSColor blackColor] set]; - [NSBezierPath strokeRect: s_arc]; - - [[NSGraphicsContext currentContext] setShouldAntialias: YES]; + [_knobOff release]; + [_knobOn release]; + [super dealloc]; } -- (NSRect)knobRectFlipped:(BOOL)b_flipped +- (void)drawKnob:(NSRect)knob_rect { - NSSize s_size; - NSPoint s_pto; - float floatValue; - - floatValue = [self floatValue]; - - if( _scFlags.weAreVertical && b_flipped ) - { - floatValue = _maxValue + _minValue - floatValue; - } - - floatValue = (floatValue - _minValue) / (_maxValue - _minValue); + NSImage *knob; - if( _scFlags.weAreVertical ) - { - s_size = NSMakeSize( _trackRect.size.width, _knobThickness ? - _knobThickness : _trackRect.size.width ); - s_pto = _trackRect.origin; - s_pto.y += (_trackRect.size.height - s_size.height) * floatValue; - } + if( b_mouse_down ) + knob = _knobOn; else - { - s_size = NSMakeSize( _knobThickness ? _knobThickness : - _trackRect.size.height, _trackRect.size.height ); - s_pto = _trackRect.origin; - s_pto.x += (_trackRect.size.width - s_size.width) * floatValue; - } + knob = _knobOff; - return NSMakeRect( s_pto.x, s_pto.y, s_size.width, s_size.height ); + [[self controlView] lockFocus]; + [knob compositeToPoint:NSMakePoint( knob_rect.origin.x + 1, + knob_rect.origin.y + knob_rect.size.height -2 ) + operation:NSCompositeSourceOver]; + [[self controlView] unlockFocus]; } -- (void)drawKnob:(NSRect)s_rc +- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView: + (NSView *)controlView mouseIsUp:(BOOL)flag { - [[NSGraphicsContext currentContext] setShouldAntialias: NO]; - - [_knobColor set]; - NSRectFill( s_rc ); + b_mouse_down = NO; + [self drawKnob]; + [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag]; +} - [[NSGraphicsContext currentContext] setShouldAntialias: YES]; +- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView +{ + b_mouse_down = YES; + [self drawKnob]; + return [super startTrackingAt:startPoint inView:controlView]; } @end +