Cocoa webview ignore mouse events in areas without content - cocoa

I have a transparent web view which is a large rectangle. The webpage it loads has smaller rectangles that don't fill the whole web view. So in those spaces not occupied by divs, you can see through the web view to whatever window or app is behind. Although you can see through, you can't click through.
I need to be able to click through the web view in parts of it that don't have active content.
Any ideas?
One of my ideas was have a transparent nsview on top of the web view, intercepting mouse downs , getting the coordinate, then referencing that coordinate in the web view and seeing if there is active content there, and if so, passing the mouse down event to the web view, but if not, ignoring it/passing it behind. This makes sense to me, but i don't know how I would accomplish this...

You need to subclass WebView and implement the hitTest: method. In your method, you need to test to see if the mouse is in one of the "active" regions of your web view and if it is not, return the view's next responder as the view passing the hit test.
//assume activeRect is some rect in your view that you want to accept mouse clicks on
- (NSView*)hitTest:(NSPoint)aPoint
{
if(NSPointInRect([self convertPoint:aPoint fromView:nil], activeRect))
{
//if the mouse is in an active area then just perform the default operation
return [super hitTest:aPoint];
}
//otherwise return the next responder
return (NSView*)[self nextResponder];
}

Related

Preventing UI interaction to the parent view

I have a WKWebView (loaded with Google) in my macOS app. On top of that, I have added a subview (Gray one, with a white box) as follows.
let controller = MyViewController()
self.addChildViewController(controller)
self.view.addSubview(controller.view)
Eventhough my new view is at the top, still I am able to click the links in the webview.
I have been overriding the mouseDown in my view and block the click. But, if I move the mouse over the links, it is changing to pointed hand mouse.
Is there any way to block the user interaction at my new view itself, so that it does not pass through to the webview?
Thanks in advance.

How to call NSScrollView autoscroll-method programmatically

I have simple chat application with text messages view-based NSTableView as you can see at the picture below.
Each message contains NSTextView instance having height to fit all the text.
All I need is to start NSScrollView (which NSTableView-instance is enclosed by) autoscrolling while the user selecting text dragging mouse far enough. Unfortunately, autoscrolling doesn't appear. In case of dragging somewhere outside of the text views all succeed.
I tried to call autoscroll:-method directly by simply push NSEvent-instance from NSTextView-subclass "mouse dragged"-event (like in example from this article):
- (void)mouseDragged:(NSEvent *)event
{
[self.scrollView autoscroll:event];
}
As I've overrode all the mouse events and implemented all the text selecting, this method often invokes. But the autoscrolling doesn't seem to work.
UPDATE
I figured out that before calling -autoscroll:-method there must be -mouseDown: of the same object. But it breaks my text selecting mechanism. The point even not in being first responder, there must be nothing but the mouseDown:-method.
Normally, a text view is within a scroll view of its own. Even if that's big enough to show all of the text without scrolling, it's still there. A call of -autoscroll: on anything within that scroll view (possibly including that scroll view itself?) will just try to scroll that scroll view, not the scroll view that contains the table view.
Try calling -autoscroll: on a view higher up in the hierarchy. Either self.scrollView.superview, the table cell view, or the table view.
Note, though, that the table view's scroll view will keep scrolling even after the cell view containing the text view is fully on-screen. In fact, it may keep scrolling it so far that it's off the screen in the other direction. Basically, it doesn't know that you're trying to select within the text view so it doesn't know to stop when the selection extends all the way to the edge of the text view.
Another approach might be to try to use a "bare" text view with no enclosing scroll view. I don't think IB will let you do that, so you'd have to do it programmatically. Bare text views don't play well with auto layout, though.

How make button in NSWindow clickable while a sheet's on top of it

I have created a custom (themed) NSWindow, by creating a borderless window and then recreating all elements of the window border/background inside the content view. I've created the window widgets (close box, zoom box, minimize box) on top of my own fake title bar using -standardWindowButton:forStyleMask:.
Trouble is, when a sheet is presented on top of my custom window (e.g. "save changes...", those buttons do not receive the clicks.
Does anybody know how I can tell NSWindow not to intercept the clicks in my minimize box? It works with a standard NSWindow. When a sheet is up, I can still send both of them to the dock, or zoom the window out.
I thought maybe there's special code in the content view that ignores clicks in subviews while a sheet is up. But it seems as if -hitTest: is called on the content view and returns the minimize widget, but the widget's action never gets triggered.
I guess I could just replace the content view and perform the action in the content view's hitTest if it is the minimize widget ... but that seems a bit ugly.

NSTextView overlay causes oddities with first responder status

I have an NSTextView in an NSScrollView, and I am programmatically inserting an NSView subclass as a subview of the NSTextView. This NSView acts as an overlay, superimposing graphical information about the text beneath it.
I thought it was working quite well until I noticed that the text view does not respond to right clicks. Other operations (editing, selection) seem to work just fine.
Also, if the first responder is changed to a sibling of the scroll view (an outline view, for example) the text view does not regain first responder status from clicking on it. The selection will change in response to clicking, but the selection highlight is gray instead of blue (indicating that the text view is not the first responder).
If I offset the frame of the overlay subview, the text view behaves 100% normally in the area not overlapped by the overlay, but the overlapped area behaves incorrectly, as outlined above.
Steps To Replicate This Behavior on Mac OS X 10.6.4:
Create a plain old non-document-based Cocoa app.
Add an `NSTextView' IBOutlet to the app delegate .h.
Add an NSTextView to the window in MainMenu.xib. Connect the textView outlet.
Type in a bit of code:
In applicationDidFinishLaunching:
NSView *overlay = [[NSView alloc] initWithFrame:textView.bounds];
[textView addSubview:overlay];
[overlay release];
Run the app, observe that right click in the text area does not work as it should, yet you can still otherwise interact with the text view.
Next, add an NSOutlineView to the window in the xib. Observe that once focus leaves the text area (if you click on the outline view) with the overlay in place, you cannot set the focus back to the text view (it will not become first responder again).
Is there some way I can enable the NSTextView to receive all of its events, even though my NSView overlay does not accept first responder or mouse events? I suspect this might be related to the field editor – perhaps it is ignoring events it thinks are destined to the overlay view?
You probably need to make your overlay an instance of a custom view class that forwards all events and accessibility messages to the text view. You may also need to convert any view-relative coordinates to the text view's coordinate system.
I don't have a lot of experience with it, but another possibility would be to use a Core Animation layer as an overlay.
A clean way to handle this is by making your overlay view a custom subclass of NSView, and then overriding the hitTest: method to always return nil. This will prevent the overlay view from participating in the responder chain. Instead, events will get sent automatically to it's superview or views higher up the view hierarchy. You might also want to override acceptsFirstResponder to return NO to be safe (in case it's accidentally set programatically).

Prevent an instance of NSView from receiving mouse events

I have an NSView in a window with core animation layer turned on.
I use this view to display images with animation from time to time. I need the entire view to be the back layer not only the images. Behind this view which I call AnimationBaseView are other views which the user interacts to.
Everything is ok except the AnimationBaseView prevents the other views from getting rightMouseDown events.
I've tried the following:
returning NO to acceptsFirstResponder to AnimationBaseView
Hiding and unhiding the AnimationBaseView as needed, but produces a nasty flicker.
Thank you for your help,
Jose.
Override - (NSView *)hitTest:(NSPoint)aPoint to return either nil or the view that should handle the mouse events

Resources