Skip to content

Commit

Permalink
Cocoa allows NSMenuItems that got a submenu to be selected and send t…
Browse files Browse the repository at this point in the history
…he action to their target upon mouse up
  • Loading branch information
cyclaero committed Sep 10, 2015
1 parent a9869d0 commit a2c28c2
Showing 1 changed file with 72 additions and 72 deletions.
144 changes: 72 additions & 72 deletions AppKit/NSMenu.subproj/NSMenuView.m
Original file line number Diff line number Diff line change
Expand Up @@ -170,72 +170,72 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
screen=[self _screenForPoint:point];
}

if (keyboardNavigationAction == kNSMenuKeyboardNavigationNone) {
// We're not current dealing with a keyboard event
// Take a look at the visible menu stack (we're within a big loop so views can come and
// go and the mouse can wander all over) deepest first
while(--count>=0){
// get the deepest one
NSMenuView *checkView=[viewStack objectAtIndex:count];
// And find out where the mouse is relative to it
NSPoint checkPoint=[[checkView window] convertScreenToBase:point];
checkPoint=[checkView convertPoint:checkPoint fromView:nil];
// If it's inside the menu view
if(NSMouseInRect(checkPoint,[checkView bounds],[checkView isFlipped])){
MENUDEBUG(@"found a menu: %@", checkView);
// Which item is the cursor on top of?
unsigned itemIndex=[checkView itemIndexAtPoint:checkPoint];

MENUDEBUG(@"found an item index: %u", itemIndex);

// If it's not the currently selected item
if(itemIndex!=[checkView selectedItemIndex]){
NSMenuView *branch;
// This looks like it's dealing with pushed cascading menu
// views that are no longer needed because the user has moved
// on - so pop them all off.
while (count+1<[viewStack count]) {
NSView* view = [viewStack lastObject];
MENUDEBUG(@"popping cascading view: %@", view);
[[view window] close];
[viewStack removeLastObject];
}
// And now select the new item
[checkView setSelectedItemIndex:itemIndex];
// If it's got a cascading menu then push that on the stack
if((branch=[checkView viewAtSelectedIndexPositionOnScreen:screen])!=nil) {
MENUDEBUG(@"adding a new cascading view: %@", branch);
[viewStack addObject:branch];
}
}
// And bail out of the while loop - we're in the right place
break;
} else {
// We've wandered off the menu so don't show anything selected if it's the deepest
// visible view
if (checkView == [viewStack lastObject]) {
MENUDEBUG(@"clearing selection in view: %@", checkView);
// The mouse is outside of the top menu - be sure no item is selected anymore
[checkView setSelectedItemIndex:NSNotFound];
}
}
}
// Looks like we've popped everything so nothing can be selected
if(count<0){
MENUDEBUG(@"clearing all selection");
[[viewStack lastObject] setSelectedItemIndex:NSNotFound];
}
}
if (keyboardNavigationAction == kNSMenuKeyboardNavigationNone) {
// We're not current dealing with a keyboard event
// Take a look at the visible menu stack (we're within a big loop so views can come and
// go and the mouse can wander all over) deepest first
while(--count>=0){
// get the deepest one
NSMenuView *checkView=[viewStack objectAtIndex:count];
// And find out where the mouse is relative to it
NSPoint checkPoint=[[checkView window] convertScreenToBase:point];
checkPoint=[checkView convertPoint:checkPoint fromView:nil];
// If it's inside the menu view
if(NSMouseInRect(checkPoint,[checkView bounds],[checkView isFlipped])){
MENUDEBUG(@"found a menu: %@", checkView);
// Which item is the cursor on top of?
unsigned itemIndex=[checkView itemIndexAtPoint:checkPoint];

MENUDEBUG(@"found an item index: %u", itemIndex);

// If it's not the currently selected item
if(itemIndex!=[checkView selectedItemIndex]){
NSMenuView *branch;
// This looks like it's dealing with pushed cascading menu
// views that are no longer needed because the user has moved
// on - so pop them all off.
while (count+1<[viewStack count]) {
NSView* view = [viewStack lastObject];
MENUDEBUG(@"popping cascading view: %@", view);
[[view window] close];
[viewStack removeLastObject];
}
// And now select the new item
[checkView setSelectedItemIndex:itemIndex];
// If it's got a cascading menu then push that on the stack
if((branch=[checkView viewAtSelectedIndexPositionOnScreen:screen])!=nil) {
MENUDEBUG(@"adding a new cascading view: %@", branch);
[viewStack addObject:branch];
}
}
// And bail out of the while loop - we're in the right place
break;
} else {
// We've wandered off the menu so don't show anything selected if it's the deepest
// visible view
if (checkView == [viewStack lastObject]) {
MENUDEBUG(@"clearing selection in view: %@", checkView);
// The mouse is outside of the top menu - be sure no item is selected anymore
[checkView setSelectedItemIndex:NSNotFound];
}
}
}
// Looks like we've popped everything so nothing can be selected
if(count<0){
MENUDEBUG(@"clearing all selection");
[[viewStack lastObject] setSelectedItemIndex:NSNotFound];
}
}

[event release];

Expand Down Expand Up @@ -400,7 +400,7 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
}
break;
case kNSMenuKeyboardNavigationRight:
{
{
MENUDEBUG(@"Right...");
NSMenuView *branch = nil;
// If there's a submenu at the current selected index
Expand All @@ -416,7 +416,7 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
[viewStack removeLastObject];
}
}
}
}
break;
case kNSMenuKeyboardNavigationLetter:
{
Expand Down Expand Up @@ -498,7 +498,7 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
// The menu is really active after a mouse up (which means the menu will stay sticky)...
// The timestamp is to avoid false clicks - make sure there's a delay so the user can
if ([event timestamp] - firstTimestamp > kMenuInitialClickThreshold &&
[viewStack count]==1 && [item isEnabled] && ![item hasSubmenu]) {
[viewStack count]==1 && [item isEnabled]) {
MENUDEBUG(@"Handling selected item - exiting");
state=STATE_EXIT;
} else {
Expand All @@ -515,7 +515,7 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
item=[activeView itemAtSelectedIndex];
if([event type]==NSLeftMouseUp){
MENUDEBUG(@"mouseUp on item: %@", item);
if(item == nil || ([viewStack count]<=2) || ([item isEnabled] && ![item hasSubmenu])) {
if(item == nil || ([viewStack count]<=2) || [item isEnabled]) {
MENUDEBUG(@"mouse up - exiting because of many possible reasons...");
state=STATE_EXIT;
} else {
Expand All @@ -533,7 +533,7 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
MENUDEBUG(@"done with the event loop");

// If we've got a menu still visible
if([viewStack count]>0) {
if(item == nil && [viewStack count]>0) {
// Get the selected item
item=[[viewStack lastObject] itemAtSelectedIndex];
MENUDEBUG(@"got the selected item at the top most menu view: %@", item);
Expand All @@ -550,7 +550,7 @@ -(NSMenuItem *)trackForEvent:(NSEvent *)event {
[[self window] setAcceptsMouseMovedEvents:oldAcceptsMouseMovedEvents];
[self setNeedsDisplay:YES];

return ([item isEnabled] && ![item hasSubmenu])?item:(NSMenuItem *)nil;
return ([item isEnabled])?item:(NSMenuItem *)nil;
}

-(void)mouseDown:(NSEvent *)event {
Expand Down

0 comments on commit a2c28c2

Please sign in to comment.