views:

183

answers:

1

Hello,

I created a local event loop and showed up a borderless window (derived from NSPanel), I found in the event loop there's no NSMouseMoved event received, although I can receive Mouse button down/up events.

What should I do to get the NSMouseMoved events? I found making the float window as key window can receive the NSMouseMoved events, but I don't want to change key window. And it appears this is possible, because I found after clicking the test App Icon in System Dock Bar, I can receive the mousemoved events, and the key window/mainwindow are unchanged.

Here's the my test code: (Create a Cocoa App project names FloatWindowTest, and put a button to link with the onClick: IBAction). Thanks in advance!

-Jonny

#import "FloatWindowTestAppDelegate.h"

@interface FloatWindow : NSPanel
@end

@interface FloatWindowContentView : NSView
@end

@implementation FloatWindowTestAppDelegate

@synthesize window;

- (void)delayedAction:(id)sender
{
    // What does this function do?
    // 1. create a float window
    // 2. create a local event loop
    // 3. print out the events got from nextEventMatchingMask.
    // 4. send it to float window.

    // What is the problem?
    // In local event loop, althrough the event mask has set NSMouseMovedMask
    // there's no mouse moved messages received.
    //

    FloatWindow* floatWindow = [[FloatWindow alloc] init];

    NSEvent* event = [NSApp currentEvent];
    NSPoint screenOrigin = [[self window] convertBaseToScreen:[event locationInWindow]];    
    [floatWindow setFrameTopLeftPoint:screenOrigin];
    [floatWindow orderFront:nil];


    //Making the float window as Key window will work, however
    //change active window is not anticipated.
    //[floatWindow makeKeyAndOrderFront:nil];

    BOOL done = NO;
    while (!done) 
    {
        NSAutoreleasePool* pool = [NSAutoreleasePool new];
        NSUInteger eventMask = NSLeftMouseDownMask|
        NSLeftMouseUpMask|
        NSMouseMovedMask|
        NSMouseEnteredMask|
        NSMouseExitedMask|
        NSLeftMouseDraggedMask;

        NSEvent* event = [NSApp nextEventMatchingMask:eventMask 
                                            untilDate:[NSDate distantFuture]
                                               inMode:NSDefaultRunLoopMode 
                                              dequeue:YES];

        //why I cannot get NSMouseMoved event??
        NSLog(@"new event %@", [event description]);
        [floatWindow sendEvent:event];
        [pool drain];
    }

    [floatWindow release];
    return;
}

-(IBAction)onClick:(id)sender
{
    //Tried to postpone the local event loop
    //after return from button's mouse tracking loop.
    //but not fixes this problem.
    [[NSRunLoop currentRunLoop]
           performSelector:@selector(delayedAction:) 
                    target:self 
                  argument:nil 
                     order:0 
                     modes:[NSArray arrayWithObject:NSDefaultRunLoopMode]];
}
@end



@implementation FloatWindow

- (id)init
{
    NSRect contentRect = NSMakeRect(200,300,200,300);
    self = [super initWithContentRect:contentRect
                            styleMask:NSTitledWindowMask
                              backing:NSBackingStoreBuffered 
                                defer:YES];

    if (self) {
        [self setLevel:NSFloatingWindowLevel];

        NSRect frameRect = [self frameRectForContentRect:contentRect];
        NSView* view = [[[FloatWindowContentView alloc] 
                         initWithFrame:frameRect] autorelease];
        [self setContentView:view];

        [self setAcceptsMouseMovedEvents:YES];
        [self setIgnoresMouseEvents:NO];
    }    
    return self;                        
}

- (BOOL)becomesKeyOnlyIfNeeded
{
    return YES;
}

- (void)becomeMainWindow
{
    NSLog(@"becomeMainWindow");
    [super becomeMainWindow];
}

- (void)becomeKeyWindow
{
    NSLog(@"becomeKeyWindow");
    [super becomeKeyWindow];
}

@end

@implementation FloatWindowContentView

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
    return YES;
}

- (BOOL)acceptsFirstResponder
{   
    return YES;
}

- (id)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    if (self) {
        NSTrackingArea* area;
        area = [[NSTrackingArea alloc] initWithRect:frameRect
                                            options:NSTrackingActiveAlways|
                                                    NSTrackingMouseMoved|
                                                    NSTrackingMouseEnteredAndExited 
                                              owner:self 
                                           userInfo:nil];
        [self addTrackingArea:area];
        [area release];
    }
    return self;
}

- (void)drawRect:(NSRect)rect
{
    [[NSColor redColor] set];
    NSRectFill([self bounds]);
}

- (BOOL)becomeFirstResponder
{
    NSLog(@"becomeFirstResponder");
    return [super becomeFirstResponder];
}

@end
A: 

I think I find the right answer. This is somehow related to tell NSWindow to accept MouseMoved event. but what to my surprise is, The window should accept mouseMoved events isn't the Floating Window, but the current Key window. So the solution is simple, just enable key window to accept mouse moved events before starting tracking, and revert the switch after ending tracking.

Jonny