Macでもファイルドロップを実装中。

This commit is contained in:
Kirurobo
2020-11-29 15:20:44 +09:00
parent 656333e5e7
commit 224080b280
29 changed files with 329 additions and 66 deletions

View File

@@ -7,12 +7,14 @@
objects = {
/* Begin PBXBuildFile section */
731C6C6E25724025002E9709 /* OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 731C6C6D25724025002E9709 /* OverlayView.swift */; };
73575EF522BE0AB300E9F019 /* LibUniWinC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73575EF422BE0AB300E9F019 /* LibUniWinC.swift */; };
73575EF922BE18B200E9F019 /* LibUniWinC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 73575EF822BE18B200E9F019 /* LibUniWinC.mm */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
7306572424F1F87900FAB8BC /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
731C6C6D25724025002E9709 /* OverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlayView.swift; sourceTree = "<group>"; };
73575EF422BE0AB300E9F019 /* LibUniWinC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibUniWinC.swift; sourceTree = "<group>"; };
73575EF822BE18B200E9F019 /* LibUniWinC.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LibUniWinC.mm; sourceTree = "<group>"; };
73DFCB7722B8ED3300DA41F2 /* LibUniWinC.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LibUniWinC.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -53,6 +55,7 @@
73575EF422BE0AB300E9F019 /* LibUniWinC.swift */,
73575EF822BE18B200E9F019 /* LibUniWinC.mm */,
7306572424F1F87900FAB8BC /* README.md */,
731C6C6D25724025002E9709 /* OverlayView.swift */,
);
path = LibUniWinC;
sourceTree = "<group>";
@@ -146,6 +149,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
731C6C6E25724025002E9709 /* OverlayView.swift in Sources */,
73575EF922BE18B200E9F019 /* LibUniWinC.mm in Sources */,
73575EF522BE0AB300E9F019 /* LibUniWinC.swift in Sources */,
);
@@ -285,8 +289,8 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11;
MARKETING_VERSION = 0.4.1;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.5.9;
PRODUCT_BUNDLE_IDENTIFIER = com.kirurobo.libuniwinc;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -313,8 +317,8 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.11;
MARKETING_VERSION = 0.4.1;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.5.9;
PRODUCT_BUNDLE_IDENTIFIER = com.kirurobo.libuniwinc;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;

View File

@@ -12,6 +12,10 @@
#import <Foundation/Foundation.h>
#import "LibUniWinC-Swift.h"
// Actually the argument type is wchar_t*
using StringCallback = void(* _Nonnull)(const void* _Nonnull);
UNIWINC_EXPORT BOOL IsActive() {
return [LibUniWinC isActive];
}
@@ -89,7 +93,7 @@ UNIWINC_EXPORT SInt32 GetCurrentMonitor() {
return [LibUniWinC getCurrentMonitor];
}
UNIWINC_EXPORT BOOL GetMonitorCount() {
UNIWINC_EXPORT SInt32 GetMonitorCount() {
return [LibUniWinC getMonitorCount];
}
@@ -97,6 +101,18 @@ UNIWINC_EXPORT BOOL GetMonitorRectangle(SInt32 monitorIndex, Float32* x, Float32
return [LibUniWinC getMonitorRectangleWithMonitorIndex:monitorIndex x:x y:y width:width height:height];
}
UNIWINC_EXPORT BOOL SetAllowDrop(BOOL enabled) {
return [LibUniWinC setAllowDropWithEnabled: enabled];
}
UNIWINC_EXPORT BOOL RegisterFileDropCallback(StringCallback callback) {
return [LibUniWinC registerFileDropCallbackWithCallback: callback];
}
UNIWINC_EXPORT BOOL UnregisterFileDropCallback() {
return [LibUniWinC unregisterFileDropCallback];
}
UNIWINC_EXPORT BOOL SetCursorPosition(Float32 x, Float32 y) {
return [LibUniWinC setCursorPositionWithX:x y:y];
}

View File

@@ -91,6 +91,9 @@ public class LibUniWinC : NSObject {
}
}
/// Callback function with wchar_t pointer
public typealias stringCallback = (@convention(c) (UnsafeRawPointer) -> Void)
// MARK: - Static variables
@@ -103,6 +106,11 @@ public class LibUniWinC : NSObject {
///
private static var orgWindowInfo: OriginalWindowInfo = OriginalWindowInfo()
/// Sub view to implement file dropping
private static var overlayView: OverlayView? = nil
public static var fileDropCallback: stringCallback? = nil
///
private static var primaryMonitorHeight: CGFloat = 0
@@ -150,6 +158,12 @@ public class LibUniWinC : NSObject {
//
orgWindowInfo.Restore(window: targetWindow!)
// Remove the subview
if (overlayView != nil) {
targetWindow?.contentView?.willRemoveSubview(overlayView!)
overlayView = nil
}
targetWindow = nil
}
@@ -173,7 +187,7 @@ public class LibUniWinC : NSObject {
}
private static func _updateScreenSize() -> Void {
// https://stackoverrun.com/ja/q/1746184
// Reference: https://stackoverrun.com/ja/q/1746184
primaryMonitorHeight = NSScreen.screens.map {$0.frame.origin.y + $0.frame.height}.max()!
//
@@ -203,7 +217,7 @@ public class LibUniWinC : NSObject {
}
///
private static func setup() -> Void {
private static func _setup() -> Void {
//
_updateScreenSize()
@@ -217,7 +231,6 @@ public class LibUniWinC : NSObject {
_updateScreenSize()
}
state.isReady = true
}
@@ -239,7 +252,7 @@ public class LibUniWinC : NSObject {
//
if (!state.isReady) {
setup()
_setup()
}
//
@@ -255,17 +268,24 @@ public class LibUniWinC : NSObject {
NotificationCenter.default.addObserver(
forName: NSWindow.didEnterFullScreenNotification,
object: nil,
queue: OperationQueue.main) { notification -> Void in
_reapplyWindowStyles()
queue: OperationQueue.main)
{
notification -> Void in _reapplyWindowStyles()
}
//
NotificationCenter.default.addObserver(
forName: NSWindow.didExitFullScreenNotification,
object: nil,
queue: OperationQueue.main) { notification -> Void in
_reapplyWindowStyles()
queue: OperationQueue.main)
{
notification -> Void in _reapplyWindowStyles()
}
// Add a subview to handle file dropping
overlayView = OverlayView(frame: window.frame)
window.contentView?.addSubview(overlayView!)
//overlayView?.fitToSuperView()
}
///
@@ -570,7 +590,23 @@ public class LibUniWinC : NSObject {
x.pointee = Float32(frame.minX)
y.pointee = Float32(frame.minY)
width.pointee = Float32(frame.width)
height.pointee = Float32(frame.height)
//height.pointee = Float32(frame.height)
height.pointee = Float32(fileDropCallback.debugDescription.count)
return true
}
@objc public static func setAllowDrop(enabled: Bool) -> Bool {
overlayView?.setEnabled(enabled: enabled)
return true
}
@objc public static func registerFileDropCallback(callback: @escaping stringCallback) -> Bool {
fileDropCallback = callback
return true
}
@objc public static func unregisterFileDropCallback() -> Bool {
fileDropCallback = nil
return true
}

View File

@@ -0,0 +1,123 @@
//
// OverlayView.swift
// LibUniWinC
//
// Created by Kirurobo on 2020/11/28.
// Copyright © 2020 Kirurobo. All rights reserved.
//
import Cocoa
protocol FileDroppedDelegate {
func complete(result: String)
}
class OverlayView: NSView {
// Reference: https://stackoverflow.com/questions/31657523/get-file-path-using-drag-and-drop-swift-macos
var pathsString: String = ""
var enabled = true
public func setEnabled(enabled: Bool) {
self.enabled = enabled
}
private func setup() {
self.registerForDraggedTypes(
[NSPasteboard.PasteboardType.URL, NSPasteboard.PasteboardType.fileURL]
)
}
public func fitToSuperView() -> Void {
if (superview == nil) {
return
}
// Fit to the parent frame
let constraints = [
self.centerXAnchor.constraint(equalTo: superview!.centerXAnchor),
self.centerYAnchor.constraint(equalTo: superview!.centerYAnchor),
self.widthAnchor.constraint(equalTo: superview!.widthAnchor),
self.heightAnchor.constraint(equalTo: superview!.heightAnchor)
]
NSLayoutConstraint.activate(constraints)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
override init(frame: NSRect) {
super.init(frame: frame)
setup()
}
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
if (self.enabled) {
return .copy
} else {
return .generic
}
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
if (!self.enabled) {
return false
}
guard
let urls = sender.draggingPasteboard.propertyList(
forType: NSPasteboard.PasteboardType(rawValue: "NSFilenamesPboardType")
) as? NSArray
else {
return false
}
// Make new-line separated string
let files: String = urls.componentsJoined(by: "¥n")
guard let ustr = files.data(using: .utf8)
else {
return false
}
let buffer = UnsafeMutablePointer<uint8>.allocate(capacity: ustr.count + 1)
for i in 0..<ustr.count {
buffer[i] = ustr[i]
//buffer[i] = wchar_t.zero
}
buffer[ustr.count] = uint8.zero
// Do callback
LibUniWinC.fileDropCallback?(buffer)
buffer.deallocate()
// Store file paths
self.pathsString = files
return true
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
// Drawing code here.
NSColor.red.set()
let figure = NSBezierPath()
figure.move(to: dirtyRect.origin)
figure.line(to: NSMakePoint(dirtyRect.width, dirtyRect.height))
figure.line(to: NSMakePoint(dirtyRect.width - 5, dirtyRect.height))
figure.line(to: NSMakePoint(dirtyRect.width, dirtyRect.height - 5))
figure.line(to: NSMakePoint(dirtyRect.width, dirtyRect.height))
figure.lineWidth = 2
figure.stroke()
}
}
extension String {
func withWideChars<Result>(_ body: (UnsafePointer<wchar_t>) -> Result) -> Result {
let unicodestr = self.unicodeScalars.map { wchar_t(bitPattern: $0.value) } + [0]
return unicodestr.withUnsafeBufferPointer { body($0.baseAddress!) }
}
}