Moving borderless NSWindow fully covered with Web View
In my COCOA application I have implemented a custom borderless win开发者_如何学运维dow. The content area of the Window is fully covered by a WebView. I want this borderless window to move when user clicks and drag mouse anywhere in the content area. I tried by overriding isMovableByWindowBackground but no use. How can I fix this problem?
Calling -setMovableByWindowBackround:YES on the WebView and making the window textured might work.
This is how I did it.
#import "BorderlessWindow.h"
@implementation BorderlessWindow
@synthesize initialLocation;
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(NSUInteger)windowStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)deferCreation
{
if((self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO]))
{
return self;
}
return nil;
}
- (BOOL) canBecomeKeyWindow
{
return YES;
}
- (BOOL) acceptsFirstResponder
{
return YES;
}
- (NSTimeInterval)animationResizeTime:(NSRect)newWindowFrame
{
return 0.1;
}
- (void)sendEvent:(NSEvent *)theEvent
{
if([theEvent type] == NSKeyDown)
{
if([theEvent keyCode] == 36)
return;
}
if([theEvent type] == NSLeftMouseDown)
[self mouseDown:theEvent];
else if([theEvent type] == NSLeftMouseDragged)
[self mouseDragged:theEvent];
[super sendEvent:theEvent];
}
- (void)mouseDown:(NSEvent *)theEvent
{
self.initialLocation = [theEvent locationInWindow];
}
- (void)mouseDragged:(NSEvent *)theEvent
{
NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
NSRect windowFrame = [self frame];
NSPoint newOrigin = windowFrame.origin;
NSPoint currentLocation = [theEvent locationInWindow];
if(initialLocation.y > windowFrame.size.height - 40)
{
newOrigin.x += (currentLocation.x - initialLocation.x);
newOrigin.y += (currentLocation.y - initialLocation.y);
if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height))
{
newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
}
[self setFrameOrigin:newOrigin];
}
}
@end
And .h file:
#import <Cocoa/Cocoa.h>
@interface BorderlessWindow : NSWindow {
NSPoint initialLocation;
}
- (id)initWithContentRect:(NSRect)contentRect
styleMask:(NSUInteger)windowStyle
backing:(NSBackingStoreType)bufferingType
defer:(BOOL)deferCreation;
@property (assign) NSPoint initialLocation;
@end
Since this is the top hit on Google...the provided approach didn't work for me as WKWebView intercepts the mouse events before they reach the window. I had to instead create a subclass of WKWebView and do the work there (h/t to Apple's Photo Editor/WindowDraggableButton.swift example).
I use Xamarin, but the code is pretty simple...here are the important bits:
// How far from the top of the window you are allowed to grab the window
// to begin the drag...the title bar height, basically
public Int32 DraggableAreaHeight { get; set; } = 28;
public override void MouseDown(NSEvent theEvent)
{
base.MouseDown(theEvent);
var clickLocation = theEvent.LocationInWindow;
var windowHeight = Window.Frame.Height;
if (clickLocation.Y > (windowHeight - DraggableAreaHeight))
_dragShouldRepositionWindow = true;
}
public override void MouseUp(NSEvent theEvent)
{
base.MouseUp(theEvent);
_dragShouldRepositionWindow = false;
}
public override void MouseDragged(NSEvent theEvent)
{
base.MouseDragged(theEvent);
if (_dragShouldRepositionWindow)
{
this.Window.PerformWindowDrag(theEvent);
}
}
@starkos porvided the correct answer at https://stackoverflow.com/a/54987061/140927 The following is just the ObjC implementation in a subclass of WKWebView:
BOOL _dragShouldRepositionWindow = NO;
- (void)mouseDown:(NSEvent *)event {
[super mouseDown:event];
NSPoint loc = event.locationInWindow;
CGFloat height = self.window.frame.size.height;
if (loc.y > height - 28) {
_dragShouldRepositionWindow = YES;
}
}
- (void)mouseUp:(NSEvent *)event {
[super mouseUp:event];
_dragShouldRepositionWindow = NO;
}
- (void)mouseDragged:(NSEvent *)event {
[super mouseDragged:event];
if (_dragShouldRepositionWindow) {
[self.window performWindowDragWithEvent:event];
}
}
For further info about how to manipulate the title bar, see https://github.com/lukakerr/NSWindowStyles
精彩评论