-
Notifications
You must be signed in to change notification settings - Fork 266
[desktop_drop] Fix mouse event blocking for PlatformView in macOS #436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,13 +84,36 @@ class DropTarget: NSView { | |
| init(frame frameRect: NSRect, channel: FlutterMethodChannel) { | ||
| self.channel = channel | ||
| super.init(frame: frameRect) | ||
| self.wantsLayer = true | ||
| self.layer?.backgroundColor = NSColor.clear.cgColor | ||
| } | ||
|
|
||
| required init?(coder: NSCoder) { | ||
| fatalError("init(coder:) has not been implemented") | ||
| } | ||
|
|
||
| override func hitTest(_ point: NSPoint) -> NSView? { | ||
| if !isDragging { | ||
| return nil | ||
| } | ||
| if NSApp.currentEvent?.type == .leftMouseDragged || | ||
| NSApp.currentEvent?.type == .rightMouseDragged { | ||
| return super.hitTest(point) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| private var isDragging = false | ||
|
|
||
| private func isDragEvent(_ event: NSEvent?) -> Bool { | ||
| guard let event = event else { return false } | ||
| return event.type == .leftMouseDragged || | ||
| event.type == .rightMouseDragged || | ||
| event.type == .otherMouseDragged | ||
| } | ||
|
Comment on lines
+95
to
+113
|
||
|
|
||
| override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation { | ||
| isDragging = true | ||
| channel.invokeMethod("entered", arguments: convertPoint(sender.draggingLocation)) | ||
| return .copy | ||
| } | ||
|
|
@@ -101,9 +124,14 @@ class DropTarget: NSView { | |
| } | ||
|
|
||
| override func draggingExited(_ sender: NSDraggingInfo?) { | ||
| isDragging = false | ||
| channel.invokeMethod("exited", arguments: nil) | ||
| } | ||
|
|
||
| override func draggingEnded(_ sender: NSDraggingInfo) { | ||
| isDragging = false | ||
| } | ||
|
|
||
| /// Create a per-drop destination for promised files (avoids name collisions). | ||
| private func uniqueDropDestination() -> URL { | ||
| let base = FileManager.default.temporaryDirectory.appendingPathComponent("Drops", isDirectory: true) | ||
|
|
@@ -193,10 +221,59 @@ class DropTarget: NSView { | |
| group.notify(queue: .main) { | ||
| self.channel.invokeMethod("performOperation_macos", arguments: items) | ||
| } | ||
| isDragging = false | ||
| return true | ||
| } | ||
|
|
||
| func convertPoint(_ location: NSPoint) -> [CGFloat] { | ||
| return [location.x, bounds.height - location.y] | ||
| } | ||
|
|
||
| override func mouseDown(with event: NSEvent) { | ||
| if !isDragging && !isDragEvent(event) { | ||
| nextResponder?.mouseDown(with: event) | ||
| } else { | ||
| super.mouseDown(with: event) | ||
| } | ||
| } | ||
|
|
||
| override func mouseUp(with event: NSEvent) { | ||
| if !isDragging && !isDragEvent(event) { | ||
| nextResponder?.mouseUp(with: event) | ||
| } else { | ||
| super.mouseUp(with: event) | ||
| } | ||
| } | ||
|
|
||
| override func mouseDragged(with event: NSEvent) { | ||
| if !isDragging && !isDragEvent(event) { | ||
| nextResponder?.mouseDragged(with: event) | ||
| } else { | ||
| super.mouseDragged(with: event) | ||
| } | ||
| } | ||
|
|
||
| override func mouseMoved(with event: NSEvent) { | ||
| if !isDragging && !isDragEvent(event) { | ||
| nextResponder?.mouseMoved(with: event) | ||
| } else { | ||
| super.mouseMoved(with: event) | ||
| } | ||
| } | ||
|
|
||
| override func rightMouseDown(with event: NSEvent) { | ||
| if !isDragging && !isDragEvent(event) { | ||
| nextResponder?.rightMouseDown(with: event) | ||
| } else { | ||
| super.rightMouseDown(with: event) | ||
| } | ||
| } | ||
|
|
||
| override func rightMouseUp(with event: NSEvent) { | ||
| if !isDragging && !isDragEvent(event) { | ||
| nextResponder?.rightMouseUp(with: event) | ||
| } else { | ||
| super.rightMouseUp(with: event) | ||
| } | ||
| } | ||
|
Comment on lines
+232
to
+278
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hitTest(_:)returnsnilwheneverisDraggingis false, butisDraggingis only set to true insidedraggingEntered. On macOS, AppKit typically determines the drag destination view via hit-testing; if this view never hit-tests positive at the start of a drag,draggingEnteredmay never be delivered and drag & drop can stop working entirely. Consider allowing hit-testing for drag sessions regardless ofisDragging(e.g., base the decision solely on the current drag event / dragging session), then useisDraggingonly to control subsequent event handling/state.