Macでもファイルドロップを実装中。
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
123
Xcode/LibUniWinC/OverlayView.swift
Normal file
123
Xcode/LibUniWinC/OverlayView.swift
Normal 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!) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user