问题
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 NSTrackingArea
, sending disableCursorRects
to both my NSApplication
and 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.
回答1:
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;
回答2:
Found a solution that worked for me! Here's how I did it:
Subclass NSView
and override the resetCursorRects
method, in which send addCursorRect:cursor:
with its bounds as the cursor rect and the required cursor (described here). Then make an instance of this custom NSView
with the same frame 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 setHidden:
message:
self.overlay.setHidden_(Foundation.YES)
Some additional things to note:
- Using an
NSTrackingArea
instead of the cursor rect doesn't seem to work well. For me it didn't. - I had tried the above method on the custom
WebView
itself, but it didn't work. TheWebView
's default tracking areas/cursor rects always interfere. Adding a subview on top of it blocks this behaviour, as the above code does. - Finally the overlay view should be 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.
If someone has a better solution, or can improve this one, feel free to post it.
Hope this helps someone!
来源:https://stackoverflow.com/questions/43848341/how-to-disable-all-nscursor-updates-in-my-application