Changeset 584 for trunk/Cocoa/Pester/Source/PSVolumeController.m
- Timestamp:
- 09/20/09 04:54:21 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Cocoa/Pester/Source/PSVolumeController.m
r583 r584 11 11 #import "NJRNonCenteringWindow.h" 12 12 13 @interface NSMenu (SnowLeopardAdditions) 14 - (BOOL)popUpMenuPositioningItem:(NSMenuItem *)item atLocation:(NSPoint)location inView:(NSView *)view; 15 - (void)setAllowsContextMenuPlugIns:(BOOL)allows; 16 - (void)cancelTracking; 17 @end 18 19 @interface NSMenuItem (SnowLeopardAdditions) 20 - (void)setView:(NSView *)view; 21 @end 22 13 23 @implementation PSVolumeController 14 24 … … 22 32 if ( (self = [self initWithWindowNibName: @"Volume"]) != nil) { 23 33 [self window]; // connect outlets 24 NSWindow *window = [[NJRNonCenteringWindow alloc] initWithContentRect: [contentView bounds] styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: NO];25 34 26 35 if ([NJRSoundManager volumeIsNotMutedOrInvalid: volume]) 27 36 [volumeSlider setFloatValue: volume]; 28 37 29 38 delegate = [aDelegate retain]; 30 39 31 [window setContentView: contentView]; 32 [window setInitialFirstResponder: volumeSlider]; 33 [window makeFirstResponder: volumeSlider]; 34 [window setOpaque: NO]; 35 [window setBackgroundColor: [NSColor colorWithCalibratedWhite: 0.81f alpha: 0.9f]]; 36 [window setHasShadow: YES]; 37 [window setOneShot: YES]; 38 [window setDelegate: self]; 39 NSView *view = [aDelegate volumeControllerLaunchingView: self]; 40 if (view != nil) { 41 NSRect rect = [view convertRect: [view bounds] toView: nil]; 42 NSWindow *parentWindow = [view window]; 43 rect.origin = [parentWindow convertBaseToScreen: rect.origin]; 44 rect.origin.x -= [window frame].size.width - rect.size.width + 1; 45 [window setFrameTopLeftPoint: rect.origin]; 46 NSRect visibleFrame = [[parentWindow screen] visibleFrame]; 47 if (!NSContainsRect(visibleFrame, [window frame])) { 48 NSPoint viewTopLeft = { rect.origin.x, rect.origin.y + rect.size.height }; 49 [window setFrameOrigin: viewTopLeft]; 50 } 51 } 40 NSView *view = [aDelegate volumeControllerLaunchingView: self]; 52 41 53 // -[NSApplication beginModalSessionForWindow:] shows and centers the window; we use NJRNonCenteringWindow to prevent the repositioning from succeeding54 NSModalSession session = [NSApp beginModalSessionForWindow: window];55 42 // In 10.6, we can no longer force the modal session to work by "seeding" the slider with a mouse-down event. 56 // Instead, we stop the modal session on a volume change. 57 while ([NSApp runModalSession: session] == NSRunContinuesResponse) { 58 // Any mouse click events that do not change the slider value should abort. 59 NSEvent *event = [NSApp currentEvent]; 60 unsigned int eventTypeMask = NSEventMaskFromType([event type]); 61 if (eventTypeMask & (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask)) { 62 [NSApp preventWindowOrdering]; 63 [NSApp discardEventsMatchingMask: NSAnyEventMask beforeEvent: event]; 64 break; 43 // Instead, use a menu. (This should mostly work on 10.5 too, but is currently untested.) 44 if ([NSMenu instancesRespondToSelector: @selector(popUpMenuPositioningItem:atLocation:inView:)]) { 45 menu = [[NSMenu alloc] initWithTitle: @""]; 46 NSMenuItem *menuItem = [[NSMenuItem alloc] init]; 47 [menuItem setView: contentView]; 48 [menu addItem: menuItem]; 49 [menuItem release]; 50 NSPoint point; 51 if (view != nil) { 52 NSSize size = [view bounds].size; 53 point = [view isFlipped] ? NSMakePoint(0, size.height) : NSZeroPoint; 54 } else { 55 point = [NSEvent mouseLocation]; 65 56 } 66 if (eventTypeMask & (NSKeyDownMask | NSKeyUpMask)) { 67 unsigned short keyCode = [event keyCode]; 68 if (keyCode == 53 || keyCode == 36 || keyCode == 76) { // escape, return, enter 69 [NSApp discardEventsMatchingMask: NSAnyEventMask beforeEvent: event]; 70 break; 57 [menu setAllowsContextMenuPlugIns: NO]; 58 [menu popUpMenuPositioningItem: nil atLocation: point inView: view]; 59 [menu release]; 60 } else { 61 NSWindow *window = [[NJRNonCenteringWindow alloc] initWithContentRect: [contentView bounds] styleMask: NSBorderlessWindowMask backing: NSBackingStoreBuffered defer: NO]; 62 [window setContentView: contentView]; 63 [window setOpaque: NO]; 64 [window setBackgroundColor: [NSColor colorWithCalibratedWhite: 0.81f alpha: 0.9f]]; 65 [window setHasShadow: YES]; 66 [window setOneShot: YES]; 67 [window setDelegate: self]; 68 69 if (view != nil) { 70 NSRect rect = [view convertRect: [view bounds] toView: nil]; 71 NSWindow *parentWindow = [view window]; 72 rect.origin = [parentWindow convertBaseToScreen: rect.origin]; 73 rect.origin.x -= [window frame].size.width - rect.size.width + 1; 74 [window setFrameTopLeftPoint: rect.origin]; 75 NSRect visibleFrame = [[parentWindow screen] visibleFrame]; 76 if (!NSContainsRect(visibleFrame, [window frame])) { 77 NSPoint viewTopLeft = { rect.origin.x, rect.origin.y + rect.size.height }; 78 [window setFrameOrigin: viewTopLeft]; 71 79 } 72 80 } 81 // -[NSApplication beginModalSessionForWindow:] shows and centers the window; we use NJRNonCenteringWindow to prevent the repositioning from succeeding 82 NSModalSession session = [NSApp beginModalSessionForWindow: window]; 83 [volumeSlider mouseDown: [NSApp currentEvent]]; 84 [NSApp runModalSession: session]; 85 [NSApp endModalSession: session]; 86 [window close]; 73 87 } 74 [NSApp endModalSession: session]; 75 [window close]; 88 76 89 [self autorelease]; 77 // XXX make sure window and self are released78 90 } 79 91 return self; … … 89 101 { 90 102 [delegate volumeController: self didSetVolume: [sender floatValue]]; 91 [NSApp stopModal]; 103 if (NSEventMaskFromType([[NSApp currentEvent] type]) & (NSLeftMouseUpMask | NSRightMouseUpMask | NSOtherMouseUpMask)) 104 [menu cancelTracking]; 92 105 } 93 106
Note:
See TracChangeset
for help on using the changeset viewer.