152 lines
5 KiB
Swift
152 lines
5 KiB
Swift
|
|
import Cocoa
|
||
|
|
import FlutterMacOS
|
||
|
|
|
||
|
|
extension NSScreen {
|
||
|
|
var displayID: CGDirectDisplayID {
|
||
|
|
return deviceDescription[NSDeviceDescriptionKey(rawValue: "NSScreenNumber")] as? CGDirectDisplayID ?? 0
|
||
|
|
}
|
||
|
|
|
||
|
|
public func toDictionary() -> NSDictionary {
|
||
|
|
var name: String = "";
|
||
|
|
if #available(macOS 10.15, *) {
|
||
|
|
name = self.localizedName
|
||
|
|
}
|
||
|
|
let size: NSDictionary = [
|
||
|
|
"width": self.frame.width,
|
||
|
|
"height": self.frame.height,
|
||
|
|
]
|
||
|
|
let visiblePosition: NSDictionary = [
|
||
|
|
"dx": self.visibleFrame.topLeft.x,
|
||
|
|
"dy": self.visibleFrame.topLeft.y,
|
||
|
|
]
|
||
|
|
let visibleSize: NSDictionary = [
|
||
|
|
"width": self.visibleFrame.width,
|
||
|
|
"height": self.visibleFrame.height,
|
||
|
|
]
|
||
|
|
let dict: NSDictionary = [
|
||
|
|
"id": self.displayID.description,
|
||
|
|
"name": name,
|
||
|
|
"size": size,
|
||
|
|
"visiblePosition": visiblePosition,
|
||
|
|
"visibleSize": visibleSize,
|
||
|
|
]
|
||
|
|
return dict;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extension NSRect {
|
||
|
|
var topLeft: CGPoint {
|
||
|
|
set {
|
||
|
|
let screenFrameRect = NSScreen.screens[0].frame
|
||
|
|
origin.x = newValue.x
|
||
|
|
origin.y = screenFrameRect.height - newValue.y - size.height
|
||
|
|
}
|
||
|
|
get {
|
||
|
|
let screenFrameRect = NSScreen.screens[0].frame
|
||
|
|
return CGPoint(x: origin.x, y: screenFrameRect.height - origin.y - size.height)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public class ScreenRetrieverMacosPlugin: NSObject, FlutterPlugin,FlutterStreamHandler {
|
||
|
|
private var _eventSink: FlutterEventSink?
|
||
|
|
|
||
|
|
var externalDisplayCount:Int = 0
|
||
|
|
|
||
|
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
||
|
|
let channel = FlutterMethodChannel(name: "dev.leanflutter.plugins/screen_retriever", binaryMessenger: registrar.messenger)
|
||
|
|
let instance = ScreenRetrieverMacosPlugin()
|
||
|
|
registrar.addMethodCallDelegate(instance, channel: channel)
|
||
|
|
let eventChannel = FlutterEventChannel(name: "dev.leanflutter.plugins/screen_retriever_event", binaryMessenger: registrar.messenger)
|
||
|
|
eventChannel.setStreamHandler(instance)
|
||
|
|
|
||
|
|
instance.externalDisplayCount = NSScreen.screens.count
|
||
|
|
instance.setupNotificationCenter()
|
||
|
|
}
|
||
|
|
|
||
|
|
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
|
||
|
|
self._eventSink = events
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
|
||
|
|
public func onCancel(withArguments arguments: Any?) -> FlutterError? {
|
||
|
|
self._eventSink = nil
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func setupNotificationCenter() {
|
||
|
|
NotificationCenter.default.addObserver(
|
||
|
|
self,
|
||
|
|
selector: #selector(handleDisplayConnection),
|
||
|
|
name: NSApplication.didChangeScreenParametersNotification,
|
||
|
|
object: nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
@objc func handleDisplayConnection(notification: Notification) {
|
||
|
|
if externalDisplayCount < NSScreen.screens.count {
|
||
|
|
_emitEvent("display-added")
|
||
|
|
externalDisplayCount = NSScreen.screens.count
|
||
|
|
} else if externalDisplayCount > NSScreen.screens.count {
|
||
|
|
_emitEvent("display-removed")
|
||
|
|
externalDisplayCount = NSScreen.screens.count
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public func _emitEvent(_ eventName: String) {
|
||
|
|
guard let eventSink = self._eventSink else {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
let event: NSDictionary = [
|
||
|
|
"type": eventName,
|
||
|
|
]
|
||
|
|
eventSink(event)
|
||
|
|
}
|
||
|
|
|
||
|
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||
|
|
switch call.method {
|
||
|
|
case "getCursorScreenPoint":
|
||
|
|
getCursorScreenPoint(call, result: result)
|
||
|
|
break
|
||
|
|
case "getPrimaryDisplay":
|
||
|
|
getPrimaryDisplay(call, result: result)
|
||
|
|
break
|
||
|
|
case "getAllDisplays":
|
||
|
|
getAllDisplays(call, result: result)
|
||
|
|
break
|
||
|
|
default:
|
||
|
|
result(FlutterMethodNotImplemented)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public func getCursorScreenPoint(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||
|
|
let currentScreen = NSScreen.main!
|
||
|
|
let mouseLocation: NSPoint = NSEvent.mouseLocation;
|
||
|
|
|
||
|
|
var visibleHeight = currentScreen.frame.maxY
|
||
|
|
for screen in NSScreen.screens {
|
||
|
|
if (visibleHeight > screen.frame.maxY) {
|
||
|
|
visibleHeight = screen.frame.maxY
|
||
|
|
}
|
||
|
|
}
|
||
|
|
let data: NSDictionary = [
|
||
|
|
"dx": mouseLocation.x,
|
||
|
|
"dy": visibleHeight - mouseLocation.y,
|
||
|
|
]
|
||
|
|
result(data)
|
||
|
|
}
|
||
|
|
|
||
|
|
public func getPrimaryDisplay(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||
|
|
result(NSScreen.screens[0].toDictionary())
|
||
|
|
}
|
||
|
|
|
||
|
|
public func getAllDisplays(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
||
|
|
let data: NSDictionary = [
|
||
|
|
"displays": NSScreen.screens.map({ screen in
|
||
|
|
return screen.toDictionary()
|
||
|
|
}),
|
||
|
|
]
|
||
|
|
result(data)
|
||
|
|
}
|
||
|
|
}
|