In my macOS application, I have a custom WebView. When the user moves the mouse cursor over different elements in the WebView's webpage like text, links, etc. (which are implemented as subviews, I think), the cursor updates automatically, based on the type of the element.
My requirement is that I want to set a custom cursor for the WebView (even for my entire application if possible), and not let it change whatsoever, at least till I programmatically change it in some other part of the code. I tried to set the NSCursor in the AppDelegate's
applicationDidFinishLaunching: method, but it gets instantly reset.
I have tried many solutions like setting an
disableCursorRects to both my
NSWindow, and even monitoring cursor update events, without much success.
So is there a way to disable all NSCursor updates within my application? I would set it to my custom cursor in
applicationDidFinishLaunching: and want it to remain the same as long as the application runs, or I change it in code.
You can use a user stylesheet in the WebView to set the default curser for html elements.
WebPreferences *preferences = [[[WebPreferences alloc] initWithIdentifier:@"TestIdentifier"] autorelease]; NSURL *stylesheetURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"yosemite-stylesheet" withExtension:@"css" subdirectory:@"Welcome"]; preferences.userStyleSheetEnabled = YES; preferences.userStyleSheetLocation = stylesheetURL; self.webView.preferences = preferences;Answer2:
Found a solution that worked for me! Here's how I did it:
NSView and override the
resetCursorRects method, in which send
addCursorRect:cursor: with its bounds as the cursor rect and the required cursor (described <a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CursorMgmt/Tasks/ChangingCursors.html" rel="nofollow">here</a>). Then make an instance of this custom
NSView <em>with the same frame</em> as the
WebView, and add it to the later as a subview. This will act as a transparent overlay over the
WebView. It affects only the cursor and does not interfere with mouse clicks or keypresses.
Here's the code in PyObjC (the concept should apply in Objective C as well):
# Overlay View (NSView subclass) class OverLayView(AppKit.NSView): def resetCursorRects(self): self.addCursorRect_cursor_(self.bounds(), my_custom_cursor) # In my main class ... self.overlay = OverLayView.alloc().initWithFrame_(self.webview.bounds()) self.webview.addSubview_(self.overlay) ...
If I ever want to reset the cursor back to auto, I can just remove this overlay view, or even better, set it temporarily hidden by sending it the
Some additional things to note:<ul><li>Using an
NSTrackingAreainstead of the cursor rect doesn't seem to work well. For me it didn't.</li> <li>I had tried the above method on the custom
WebViewitself, but it didn't work. The
WebView's default tracking areas/cursor rects always interfere. Adding a subview on top of it blocks this behaviour, as the above code does.</li> <li>Finally the overlay view <em>should be</em> a subview of the
WebView. If both are sibling views of the same superview, Cocoa doesn't guarantee which one will be on top of the other.</li> </ul>
If someone has a better solution, or can improve this one, feel free to post it.
Hope this helps someone!