mouseMoved event stopping when mouse is down - cocoa

I have implemented a custom NSView (marked as ) and am able to get mouseUp:, mouseDown: and mouseMoved: events. To this I have acceptsFirstResponder returning YES, and also call the following in awakeFromNib:
[[self window] makeFirstResponder:self];
[[self window] seAcceptsMouseMovedEvents:true];
However the extremely strange thing is that if I click and drag, the mouseMoved: events stop coming in until I let go of the mouse button and get a mouseUp:
I have seen other related posts, but they all say that if the view is first responder (and it is), then I should be receiving these events.
Why is the mousemoved: event stopping?

-(void)mouseDragged:(NSEvent *)event
is called instead of
-(void)mouseMoved:(NSEvent *)event
when the left mouse button is down. So if you have anything you need to do in both cases, call a common method to do it from both of these.

Related

AppDelegate stops getting windowDidResize

I have a single window cocoa app. In appDidFinishLaunching I have [[self window] setDelegate: self]. When the app first launches windowDidResize gets called without issue. After a few actions, it doesn't get called again. I haven't closed the window or called anything to do with the window. Haven't changed the delegate, window or self. If I drop in a few
NSLog(#"Window: %# Self: %# Delegate: %#", [self window], self, [_window delegate]);
it's exactly the same before and after it stops working. I do do a fair bit with the notification center, posting and acting on my own notifications but delegates don't rely on notification center, correct? Any tips on figuring out what's happening here?

Handling mouse over on NSCell (NSTextAttachmentCell)

Can't figure out how to handle mouse move over NSCell (or NSTextAttachmentCell). Is it possible ?
You can add a tracking area in the view that contains the cell and implement mouseEntered: and mouseExited: (and mouseMoved if you need that also) in that view. Here is an example where I added a tracking area one a button (button is the IBOutlet for the button). I added this code in the view's awakeFromNib method:
NSTrackingArea *buttonArea = [[NSTrackingArea alloc] initWithRect:self.button.frame options:NSTrackingMouseEnteredAndExited|NSTrackingMouseMoved|NSTrackingActiveInActiveApp owner:self userInfo:nil];
[self addTrackingArea:buttonArea];
This will cause the view to receive mouseEntered, mouseMoved, and mouseExited messages when the cursor enters the frame of the button.

NSWindow doesn't receive keyboard events

I am creating an NSWindow from a bundle loaded at runtime so I don't have the source code for the NSWindow that is created at app launch. When I show my window, it receives mouse event but it does not receive any keyboard events. I have tried adding the window with the following methods:
[_myWindow makeKeyAndOrderFront:nil];
[[NSApplication sharedApplication].mainWindow addChildWindow:_myWindow ordered:NSWindowAbove];
[NSApp beginModalSessionForWindow:_myWindow];
In all 3 cases it appears the main window is eating all the keyboard events. The mouse events also leak through to the original window (I can see mouse over highlights and buttons respond to clicks through my window). I have also tried:
[_myWindow makeMainWindow];
[_myWindow orderWindow:NSWindowAbove relativeTo:[originalWindow windowNumber]];
Any tips to get keyboard events to land on my window would be greatly appreciated.
You can subclass NSApplication and override sendEvent: to print [[NSApplication sharedApplication] keyWindow] before sending the event to the keyWindow (don't forget to call the super to actually send the event).
If the key window does not receive the events, then you might have an event monitor somewhere that grabs the events before they are dispatched.

Mouse Events Bleeding Through NSView

I have an NSView which covers its parent window's content view. This view has a click event handler which removes it from the content view. Inside this view, I have another view. When I drag the mouse in this inner view, the mouse events are applied not only to the view in the front, but also to the views behind. Additionally, the cursors from the views behind are showing up as well. This is the same problem occurring here: NSView overlay passes mouse events to underlying subviews? but the answer there won't work for my project because I can't open another window.
Without seeing your event-handling code it's difficult to know what's happening, but I suspect you might be calling super's implementation of the various event-handling methods in your implementations.
NSView is a subclass of NSResponder, so by default un-handled events are passed up the responder chain. The superview of a view is the next object in the responder chain, so if you call, for example, [super mouseDown:event] in your implementation of ‑mouseDown:, the event will be passed to the superview.
The fix is to ensure you don't call super's implementation in your event handlers.
This is incorrect:
- (void)mouseDown:(NSEvent*)anEvent
{
//do something
[super mouseDown:event];
}
This is correct:
- (void)mouseDown:(NSEvent*)anEvent
{
//do something
}
Rob's answer and Maz's comment on that answer solve this issue, but just to make it absolutely explicit. In order to prevent a NSView from bleeding it's mouse events to the parent, one must implement the empty methods.
// NSResponder =========================================
- (void) mouseDown:(NSEvent*)event {}
- (void) mouseDragged:(NSEvent*)event {}
- (void) mouseUp:(NSEvent*)event {}

NSEvent - NSLeftMouseDown

I'm trying to trigger basic functions using NSEvent and mouse clicks. For example close the window when pressing left mouse button. What else do I need in this method?
Thanks.
- (void)mouseDown:(NSEvent *)theEvent {
if ([theEvent type] == NSLeftMouseDown){
[window orderOut:nil];
}
}
Assuming this is in a custom view and the window outlet is connected (or you fill in that variable with [self window] when the view is added to a superview), that should be all you need. I would suggest handling mouseUp: instead of mouseDown:, though, to give the user the opportunity to back out by moving the mouse outside of your view.
You might also consider using an NSButton instead of (or inside of) a custom view. You could hook it up directly to the window's performClose: or orderOut: action.

Resources