9
votes

I am developing an Desktop application in which I should be able to take mouse events on transparent window. But, transparent NSWindow does not take mouse events. So, I have set setIgnoreMouseEvents to NO which allows the transparent window to take mouse events.

I have the problem in the following scenario: There is dynamically created rectangular shape on this window. The transparent window should not take mouse events in this region; it should be delegated to the window (of some other app) that is present behind this shape. For this purpose, if the mouseDown event is inside the shape I am setting setIgnoreMouseEvents to YES. Now, if the user performs mouse events in the area outside the shape the transparent window should take the event. Since, setIgnoreMouseEvents is set to YES, window does not take mouse events.

There is no way to identify that mouseDown event has occurred so that I can set setIgnoreMouseEvents to NO.

Could someone suggest me some best method to handle mouse events on transparent window?

Deepa

1
The magic word you are looking for is "hit testing". That is how the window can cooperate with the process of determining if the mouse should be treated as being over the window or not.Ben
I suggest you just create a tracking area for that rectangle and intercept from the responder chain in the view and then delegate that to the Window you wish to capture the desired event.Arvin
I suggest that you receive all mouse event and don't set setIgnoreMouseEvents to YES. And verify all the mouse event location (i.e. hit test) and send them to other window conditionally.Raviprakash

1 Answers

3
votes

I've just come across Quartz Event Taps, which basically let you capture the mouse event and execute your own callback.

Haven't tried it out myself, but it seems like you should be able to check where the mouse click fell and execute conditionally on the values

Here's an example:

//---------------------------------------------------------------------------  
 CGEventRef MouseTapCallback( CGEventTapProxy aProxy, CGEventType aType, CGEventRef aEvent, void* aRefcon )   
 //---------------------------------------------------------------------------  
 {  
    if( aType == kCGEventRightMouseDown ) NSLog( @"down" );  
    else if( aType == kCGEventRightMouseUp ) NSLog( @"up" );  
    else NSLog( @"other" );  

   CGPoint theLocation = CGEventGetLocation(aEvent);  
   NSLog( @"location x: %d y:%d", theLocation.x, theLocation.y );  

   return aEvent;   
 }   

 //---------------------------------------------------------------------------  
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification   
 //---------------------------------------------------------------------------  
 {  
   CGEventMask theEventMask = CGEventMaskBit(kCGEventRightMouseDown) |  
                 CGEventMaskBit(kCGEventRightMouseUp);  

   CFMachPortRef theEventTap = CGEventTapCreate( kCGSessionEventTap,   
                          kCGHeadInsertEventTap,   
                          0,   
                          theEventMask,   
                          MouseTapCallback,   
                          NULL );   

   if( !theEventTap )   
   {  
     NSLog( @"Failed to create event tap!" );  
   }   

   CFRunLoopSourceRef theRunLoopSource =   
     CFMachPortCreateRunLoopSource( kCFAllocatorDefault, theEventTap, 0);   

   CFRunLoopAddSource( CFRunLoopGetCurrent(),  
                       theRunLoopSource,   
                       kCFRunLoopCommonModes);   
   CGEventTapEnable(theEventTap, true);  
 }