From fb77d815b23b406b6332d824b7bf768b5324b83c Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 7 Jan 2000 20:46:45 +0000 Subject: [PATCH] Menu handling fixes git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5700 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 9 +++++ Source/NSMenu.m | 44 +++++++++++++++------- Source/NSMenuView.m | 89 +++++++++++++++++++++++++++++++------------- Source/NSResponder.m | 10 +++-- 4 files changed, 110 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 141626d05..3cc23fe3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Fri Jan 7 20:30:00 2000 Richard Frith-Macdonald + + * Source/NSResponder.m: Changed _rightMouseDisplay to take the event + as a parameter. + * Source/NSMenu.m: Implemented ([-_rightMouseDisplay:]) with various + minor supporting changes. + * Source/NSMenuView.m: Lots of messing with mouse tracking in support + of right-mouse menu popup and somewhat smoother operation. + Fri Jan 7 18:09:15 2000 Nicola Pero * Headers/AppKit/NSBrowser.h: Fixed typo. diff --git a/Source/NSMenu.m b/Source/NSMenu.m index 5560836e8..fcee120f5 100644 --- a/Source/NSMenu.m +++ b/Source/NSMenu.m @@ -535,9 +535,9 @@ static NSString *NSMenuLocationsKey = @"NSMenuLocations"; - (NSPoint) locationForSubmenu: (NSMenu*)aSubmenu { - NSRect frame; - NSRect submenuFrame; - NSWindow *win_link; + NSRect frame; + NSRect submenuFrame; + NSWindow *win_link; if (![self isFollowTransient]) { @@ -1016,9 +1016,11 @@ static NSString *NSMenuLocationsKey = @"NSMenuLocations"; [titleView _releaseCloseButton]; } -- (void) _rightMouseDisplay +- (void) _rightMouseDisplay: (NSEvent*)theEvent { - // TODO: implement this method. + [self displayTransient]; + [menu_view mouseDown: theEvent]; + [self closeTransient]; } - (void) display @@ -1085,12 +1087,27 @@ static NSString *NSMenuLocationsKey = @"NSMenuLocations"; menu_follow_transient = YES; - // Cache the old submenu if any. - _oldAttachedMenu = menu_supermenu->menu_attachedMenu; - menu_supermenu->menu_attachedMenu = self; + /* + * Cache the old submenu if any and query the supermenu our position. + * Otherwise, raise menu under the mouse. + */ + if (menu_supermenu != nil) + { + _oldAttachedMenu = menu_supermenu->menu_attachedMenu; + menu_supermenu->menu_attachedMenu = self; + location = [menu_supermenu locationForSubmenu: self]; + } + else + { + NSRect frame = [aWindow frame]; - // Query the supermenu our position. - location = [menu_supermenu locationForSubmenu: self]; + location = [aWindow mouseLocationOutsideOfEventStream]; + location = [aWindow convertBaseToScreen: location]; + location.x -= frame.size.width/2; + if (location.x < 0) + location.x = 0; + location.y -= frame.size.height - 10; + } [bWindow setFrameOrigin: location]; @@ -1144,15 +1161,16 @@ static NSString *NSMenuLocationsKey = @"NSMenuLocations"; [[aWindow contentView] setNeedsDisplay: YES]; - // Restore the old submenu. - menu_supermenu->menu_attachedMenu = _oldAttachedMenu; + // Restore the old submenu (if any). + if (menu_supermenu != nil) + menu_supermenu->menu_attachedMenu = _oldAttachedMenu; menu_follow_transient = NO; menu_isPartlyOffScreen = IS_OFFSCREEN(aWindow); } -- (NSWindow *) window +- (NSWindow*) window { if (menu_follow_transient) return (NSWindow *)bWindow; diff --git a/Source/NSMenuView.m b/Source/NSMenuView.m index 6dec6299e..508b28a75 100644 --- a/Source/NSMenuView.m +++ b/Source/NSMenuView.m @@ -709,15 +709,12 @@ static float GSMenuBarHeight = 25.0; // A wild guess. [targetMenuView setHighlightedItemIndex: -1]; } -#define MOVE_THRESHOLD_DELTA 1.0 +#define MOVE_THRESHOLD_DELTA 2.0 #define DELAY_MULTIPLIER 6 -- (BOOL) trackWithEvent: (NSEvent *)event +- (BOOL) trackWithEvent: (NSEvent*)event { - NSApplication *theApp = [NSApplication sharedApplication]; - unsigned eventMask = NSLeftMouseUpMask - | NSLeftMouseDraggedMask - | NSPeriodicMask; + unsigned eventMask = NSPeriodicMask; NSDate *theDistantFuture = [NSDate distantFuture]; int index; NSPoint location; @@ -728,7 +725,28 @@ static float GSMenuBarHeight = 25.0; // A wild guess. int delayCount = 0; float xDelta = MOVE_THRESHOLD_DELTA; float yDelta = 0.0; + NSEvent *original; + NSEventType type = [event type]; + NSEventType end; + /* + * The original event is unused except to determine whether the method + * was invoked in response to a right or left mouse down. + * We pass the same event on when we want tracking to move into a + * submenu. + */ + original = AUTORELEASE(RETAIN(event)); + if (type == NSRightMouseDown) + { + end = NSRightMouseUp; + eventMask |= NSRightMouseUpMask | NSRightMouseDraggedMask; + } + else + { + end = NSLeftMouseUp; + eventMask |= NSLeftMouseUpMask | NSLeftMouseDraggedMask; + } + do { location = [window mouseLocationOutsideOfEventStream]; @@ -738,7 +756,7 @@ static float GSMenuBarHeight = 25.0; // A wild guess. { mouseMoved = YES; /* Ok - had an initial movement. */ } - if ([event type] == NSPeriodic) + if (type == NSPeriodic) { if ([menuv_menu isPartlyOffScreen]) { @@ -781,7 +799,7 @@ static float GSMenuBarHeight = 25.0; // A wild guess. */ delayCount++; if (delayCount >= DELAY_MULTIPLIER - || (xDiff < -xDelta) + || (xDiff < 0) || (yDelta < 0.0 && yDiff > -yDelta) || (yDelta > 0.0 && yDiff < -yDelta)) { @@ -798,9 +816,26 @@ static float GSMenuBarHeight = 25.0; // A wild guess. if (index == -1) { - if ([menuv_menu attachedMenu]) + NSWindow *w; + + location = [window convertBaseToScreen: location]; + + /* + * If the mouse is back in the supermenu, we return NO so that + * our caller knows the button was not released. + */ + w = [[menuv_menu supermenu] window]; + if (w != nil && NSMouseInRect(location, [w frame], NO) == YES) { - if ([[self attachedMenuView] trackWithEvent: event]) + return NO; + } + /* + * if the mouse is in our attached menu - get that menu to track it. + */ + w = [[menuv_menu attachedMenu] window]; + if (w != nil && NSMouseInRect(location, [w frame], NO) == YES) + { + if ([[self attachedMenuView] trackWithEvent: original]) return YES; } else @@ -808,10 +843,11 @@ static float GSMenuBarHeight = 25.0; // A wild guess. if (index != menuv_highlightedItemIndex) [self setHighlightedItemIndex: index]; } - +#if 0 if (([menuv_menu supermenu] && ![menuv_menu isTornOff]) || [menuv_menu isFollowTransient]) return NO; +#endif } else { @@ -841,12 +877,13 @@ static float GSMenuBarHeight = 25.0; // A wild guess. } } - event = [theApp nextEventMatchingMask: eventMask - untilDate: theDistantFuture - inMode: NSEventTrackingRunLoopMode - dequeue: YES]; + event = [NSApp nextEventMatchingMask: eventMask + untilDate: theDistantFuture + inMode: NSEventTrackingRunLoopMode + dequeue: YES]; + type = [event type]; } - while ([event type] != NSLeftMouseUp); + while (type != end); // Perform actions as needed. if (index != -1 && !alreadyAttachedMenu) @@ -883,19 +920,21 @@ static float GSMenuBarHeight = 25.0; // A wild guess. return YES; } -- (void) mouseDown: (NSEvent *)theEvent +- (void) mouseDown: (NSEvent*)theEvent { - NSMenu *candidateMenu; - NSMenu *masterMenu; - NSMenuView *masterMenuView; - NSPoint originalLocation; + NSMenu *candidateMenu; + NSMenu *masterMenu; + NSMenuView *masterMenuView; + NSPoint originalLocation; menuv_keepAttachedMenus = YES; - for (candidateMenu = masterMenu = menuv_menu; - (candidateMenu = [masterMenu supermenu]) - && (![masterMenu isTornOff] || [masterMenu isFollowTransient]); - masterMenu = candidateMenu); + masterMenu = menuv_menu; + while ((candidateMenu = [masterMenu supermenu]) != nil + && ([masterMenu isTornOff] == NO || [masterMenu isFollowTransient] == YES)) + { + masterMenu = candidateMenu; + } originalLocation = [[masterMenu window] frame].origin; diff --git a/Source/NSResponder.m b/Source/NSResponder.m index d46be5144..3c4cb635c 100644 --- a/Source/NSResponder.m +++ b/Source/NSResponder.m @@ -204,14 +204,16 @@ - (void) rightMouseDown: (NSEvent *)theEvent { - if (next_responder) - return [next_responder rightMouseDown: theEvent]; + if (next_responder != nil) + { + return [next_responder rightMouseDown: theEvent]; + } else { NSMenu *menu = [NSApp mainMenu]; - if (menu) - [menu _rightMouseDisplay]; + if (menu != nil) + [menu _rightMouseDisplay: theEvent]; else return [self noResponderFor: @selector(rightMouseDown:)]; }