Basically I want to create the effect of that provided in the system's menu bar. A user presses on one of the menu headings, and as he moves across the different headings, the menus open up automatically.
The snag is that if I open a pop-up menu for a button, the user has to click again to dismiss it. The entire runloop is on hold as I believe the pop-up menu is modal. How do I go about being able to send a [somePopUpMenu cancelTracking] when the user moves to the next button?
Here's code I'm currently trying out in my NSWindow subclass. The point is that once the mouse exits a button, the mouse is automatically clicked (leftdown/leftup) on the next button, the timer is invalidated and the popup menu is cancelled.
Assuming a popup menu is open and the mouse exists, the leftdown/leftup events are fired (I know this works as I log them in NSLog's for mouseDown and mouseUp), the timer is invalidated, but the pop up menu is still showing, and the other button "clicked" on by the fake events doesn't show anything. Also, the whole thing gets into a loop and there's frantic mouseDown/mouseUp being sent for some reason.
Worth noting the the popup menu is created in another object, though the hookToMenu has a proper reference to it (I confirmed via debug/stepping through).
Dunno if I'm borking the event tracking timer or doing it the wrong way. I did try it via a window controller as well but got the same results.
Any help on this would be appreciated.
-(void)stopTimer
{
[timer invalidate];
[hookToMenu cancelTracking]; //hookToMenu is NSMenu*
}
-startFireDateTimer
{
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
timer = [[NSTimer alloc] initWithFireDate:nil interval:0 target:self selector:@selector(targetMethod) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSEventTrackingRunLoopMode];
[timer release];
}
-(void)targetMethod
{
NSEvent *newEvent;
newEvent=[NSApp nextEventMatchingMask:NSMouseExitedMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:NO];
if ([newEvent type]==NSMouseExited)
{
NSPoint mouseLoc;
mouseLoc=[newEvent locationInWindow];
int type=NSLeftMouseDown;
int type2=NSLeftMouseUp;
int windowNumber=[self windowNumber];
id fakeMouseUpEvent=[NSEvent mouseEventWithType:type
location:mouseLoc
modifierFlags:nil
timestamp:[NSDate timeIntervalSinceReferenceDate]
windowNumber:windowNumber
context:nil
eventNumber:nil
clickCount:1
pressure:1];
id fakeMouseUpEvent2=[NSEvent mouseEventWithType:type2
location:mouseLoc
modifierFlags:nil
timestamp:[NSDate timeIntervalSinceReferenceDate]
windowNumber:windowNumber
context:nil
eventNumber:nil
clickCount:1
pressure:1];
[NSApp sendEvent:fakeMouseUpEvent];
[NSApp sendEvent:fakeMouseUpEvent2];
[self stopTimer];
}
}
-(void)mouseDown:(NSEvent *)theEvent
{
[self startFireDateTimer];
NSLog(@"WINDOW: mouse down in window!");
[super mouseDown:theEvent];
}
-(void)mouseUp:(NSEvent *)theEvent
{
NSLog(@"WINDOW: mouse up in window!");
[super mouseUp:theEvent];
}