I have an custom collectionView:
import AppKit
final class InternalCollectionView: NSCollectionView {
typealias KeyDownHandler = (_ event: NSEvent) -> Bool
var keyDownHandler: KeyDownHandler? = nil
// Do nothing on Cmd+A
override func selectAll(_ sender: Any?) { }
}
also I have collectionView for SwiftUI with some controller used inside:
struct FBCollectionView<Content: View>: NSViewControllerRepresentable {
//here some implementation
}
public class NSCollectionController<Content: View>: NSViewController, NSCollectionViewDelegate, NSCollectionViewDataSource, QLPreviewPanelDataSource, QLPreviewPanelDelegate {
//here some implementation
}
I need to implement logic:
- Items on drag must be drawn on their places, but not hidden [done]
- The App must to be hidden on drag outside of the App
First of all I have tried to just hide the App on drag begins. For this I have implemented method of NSCollectionController :
public func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItemsAt indexPaths: Set<IndexPath>) {
hideApp()
preventHidingItemsDuringDrag(collectionView, indexPaths: indexPaths)
}
func hideApp() {
DispatchQueue.main.async {
NSApplication.shared.hide(self)
}
appShown = false
automaticScroller.updStatus(appDisplayed: appShown)
}
but for some reason this works only on first drag(!) on each following drags app does not hide
I have tried to run this code in main thread, but didn't get any usable results
So question is:
- How to hide app on drag outside of the app?
You might consider using
addLocalMonitorForEvents(I thought aboutaddGlobalMonitorForEvents, but... as illustrated here, it would require for the app to have accessibility access)However, as noted by the OP in the comments:
So instead, let's try another to monitor the dragging session status.
Reading "Supporting Table View Drag and Drop Through File Promises", I see:
Picking up on that:
The
NSCollectionControllerclass is a controller for anNSCollectionView. It handles many tasks, including acting as the delegate and data source for the collection view, and managing the drag-and-drop interactions.In order to hide the entire application when a dragged item is moved outside the application window, the idea is to a custom class (
MyPasteboardWriter) that conforms to bothNSPasteboardWritingandNSDraggingSourceprotocols.The
NSPasteboardWritingprotocol enables the class to provide data to the pasteboard (which is used during drag-and-drop operations), whileNSDraggingSourceallows it to react to drag-and-drop events.In the
NSDraggingSourceprotocol, thedraggingSession(_:movedTo:)method is implemented to check the location of the dragged item. If the item is moved outside the application window, the application is hidden. This is done by using theNSApplication.shared.hide(nil)function.The
appShownstatic variable is used to keep track of whether the application is currently visible or not. It's important to prevent the application from attempting to hide multiple times in succession.The
draggingSession(_:sourceOperationMaskFor:)method is also implemented to specify the allowed operations (.copy, .move) when the dragging is outside the source application.Finally, the
collectionView(_:draggingSession:endedAt:dragOperation:)delegate method is used to reset theappShownflag back to true when a dragging session ends, indicating that the application can now be shown again.Make sure you properly set up the dragging session and the item you are dragging uses your custom
MyPasteboardWriteras its pasteboard writer.The class that adopts the
NSDraggingSourceprotocol and implements thedraggingSession(_:movedTo:)method must be the one used as the source object when initiating the dragging session.If you are using a different object as the source, the method won't be called.