MouseDragged not released when dragging on other views - cocoa

I have 2 subclasses of NSView that are subviews to a common superview. They dont overlap and they both intercept mousedragged calls. When I drag from one of the subclasses to the other the mousedragged function will be called until I release the mouse button even when I drag all over the screen. I though the default behavior was for the mousedragged function to be called only when the mouse was over the bounds of the receiver.
Iam also using NSTrackingArea for mouse enter, exit and move events, but from what I've been reading does not involve drag events
Thank you for your time,
Jose.

You could subclass the NSWindow and override sendEvent:. That way, you can intercept the NSLeftMouseDragged events and dispatch them in whatever way you wish.

Related

rightMouseDown not called until button released

I have an NSView subclass in which I need to detect left and right mouse down events. mouseDown: is working just fine, but rightMouseDown: doesn't fire until the mouse button has been released, at which point both the down and up methods are called in succession. How can I make the right mouse down event trigger its corresponding method immediately?
The problem was that I have a NSPanGestureRecognizer added to the NSView with its buttonMask set to 0x2 (right mouse button). If I remove or disable this gesture recogniser, it allows rightMouseDown: to be called when the right button is pressed down. I'm still trying to figure out why, but at least now I have a starting point.

How to make NSPopover properly follow the mouse pointer and ignore mouse events?

I would like to display an informational NSPopover that tracks the user's mouse cursor.
For this, I am using an NSTrackingArea to update the popover's positioningRect whenever the mouseMoved event fires.
However, this has two drawbacks:
The popover follows the mouse with a slight delay. How can I reduce this delay to make the popover appear more "glued" to the mouse pointer?
When I move the mouse pointer in the direction of the popover, the tracking area's mouseExited method gets called, which causes the popover to "absorb" the mouse movement events, so that the tracking area's mouseMoved event no longer fires. How can I avoid the popover absorbing the mouse events, or at least keep forwarding these events?
This question is very similar to Any way around this NSTrackingArea quirk?, with the distinction that I am using NSPopover, so I have nothing to set ignoresMouseEvents on.
I took a look at your problem. I was not able to eliminate the lag, but it might reduce if you set popover.animates to false.
Wrong approach:
I was able to solve the mouseExited over popover issue by adding a new border (and shadowless) window on top of the other one. The trackingArea is added to the transparent window, the popover to the original one. Depending on the transparent windows level, it is above the popover and therefore they can't interfere with each other.
In the gif below you can see the results of my tests:
Here is some of my code:
The mouse tracking:
override func mouseMoved(with event: NSEvent) {
let location = self.view.convert(event.locationInWindow, from: nil)
popover.positioningRect.origin.x = location.x
popover.positioningRect.origin.y = location.y
}
The custom window:
transparentWindow.backgroundColor = NSColor.clear
transparentWindow.isOpaque = false
transparentWindow.styleMask = .borderless
transparentWindow.makeKeyAndOrderFront(nil)
Update 11/11/2016:
I just read the question in the link you provided. There is a window to set ignoresMouseEvents on. Even though NSPopover inherits from NSObject, you have a contentViewController, which holds an view object, which holds the popovers window. (as explained here)
So simply set
popover.contentViewController?.view.window?.ignoresMouseEvents = true
after the popover is shown.

Cocoa - Giving focus to a WebView in an NSStatusItem

I've set the view for my NSStatusItem to a WebView, but I'm not able to capture hover events in the WebView because my NSStatusItem doesn't get focus, like a normal WebView would.
How do I programmatically give my NSStatusItem or its associated view focus so that the embedded WebView will capture mouse events like a normal WebView?
In case anyone cares, one way I can think of is to have the view for the NSStatusItem be a custom NSView that overrides the NSResponder methods mouseEntered:, mouseMoved: and mouseExited:. Then, I would add the WebView as a subview of the custom NSView, and each time the mouse moves inside the NSView, send the coordinates of the mouse to the Javascript in the WebView, which can figure out what element is at the position of the mouse cursor.
Basically, it would be reimplementing mouse hover at its core. Hopefully there's an easier way though.

Capturing Window Events in NSDocument

I have an document-based Cocoa application with a TextView and I would like to capture clicks on it, so I'm trying to intercept Window events like mouseDown, mouseUp, etc. then relate them to my TextView.
I've tried a two things:
1.) I made the TextView the initial first responder for the Window of my document, and overrode the mouseDown event on my document class, but it's not hitting.
2.) I subclassed NSWindow and override mouseDown, and set that subclass to my Window's class in my document xib. That event didn't hit either.
I noticed that the Window's delegate is already set to my File's Owner which is my NSDocument subclass. Why don't the events fire on my NSDocument if my document subclass is the delegate for my Window?
It's not clear why you would expect NSDocument to handle -mouseDown: events for a view in a window. NSDocument doesn't respond to -mouseDown:. NSTextView (as its name suggests) is a subclass of NSView, which is a subclass of NSResponder, which does respond to -mouseDown:.
You should give the Cocoa Event-Handling Guide a good read.
It's also not clear why you want to handle the events and pass them on to views yourself. Cocoa takes care of all of this stuff for you and will likely do a far better job of it. You should clarify your overall goal (as in "why do you want to intercept clicks and forward them to views yourself?") - there may be a far better (and likely easier) way to accomplish it.

In Cocoa, how can my NSView receive an event when the mouse is held down (but not moved)?

I'm looking for the right way to handle "mouse held down in one spot" events in my NSView subclass.
I am familiar with Cocoa's mouseDragged: event, but it is only triggered when the mouse moves. If the mouse stays in the same position, no drag event is triggered. Similarly, mouseDown: is only fired when the button is first pressed. My view needs to perform an action as long as the mouse is held down in a particular region.
What is the proper way to do this kind of thing?
Can you start performing the action when you receive a mouseDown: event, and stop when you receive mouseUp: (or mouseDragged:, if you want to stop then, too)?
I'm not sure exactly what you're trying to accomplish, but if you want an action to be repeated at set time intervals after the mouseDown:, you could set a recurring NSTimer in the mouseDown: method that gets cancelled as soon as there is a mouseDragged: or mouseUp: event.

Resources