【发布时间】:2019-07-08 12:36:21
【问题描述】:
由于这是相当多的代码,如果有一个示例项目可以帮助您更好地理解当前问题,我制作了一个简单的示例项目,您可以在 GitHub 上找到它:https://github.com/dehlen/Stackoverflow
我想实现一些与 macOS 截图工具非常相似的功能。当鼠标悬停在窗口上时,该窗口应突出显示。但是,我只突出显示用户可见的窗口部分时遇到问题。
我当前的实现如下:
1.获取屏幕上所有可见窗口的列表
static func all() -> [Window] {
let options = CGWindowListOption(arrayLiteral: .excludeDesktopElements, .optionOnScreenOnly)
let windowsListInfo = CGWindowListCopyWindowInfo(options, CGMainDisplayID()) //current window
let infoList = windowsListInfo as! [[String: Any]]
return infoList
.filter { $0["kCGWindowLayer"] as! Int == 0 }
.map { Window(
frame: CGRect(x: ($0["kCGWindowBounds"] as! [String: Any])["X"] as! CGFloat,
y: ($0["kCGWindowBounds"] as! [String: Any])["Y"] as! CGFloat,
width: ($0["kCGWindowBounds"] as! [String: Any])["Width"] as! CGFloat,
height: ($0["kCGWindowBounds"] as! [String: Any])["Height"] as! CGFloat),
applicationName: $0["kCGWindowOwnerName"] as! String)}
}
2。获取鼠标位置
private func registerMouseEvents() {
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
self.mouseLocation = NSEvent.mouseLocation
return $0
}
NSEvent.addGlobalMonitorForEvents(matching: [.mouseMoved]) { _ in
self.mouseLocation = NSEvent.mouseLocation
}
}
3.突出显示当前鼠标位置的窗口:
static func window(at point: CGPoint) -> Window? {
// TODO: only if frontmost
let list = all()
return list.filter { $0.frame.contains(point) }.first
}
var mouseLocation: NSPoint = NSEvent.mouseLocation {
didSet {
//TODO: don't highlight if its the same window
if let window = WindowList.window(at: mouseLocation), !window.isCapture {
highlight(window: window)
} else {
removeHighlight()
}
}
}
private func removeHighlight() {
highlightWindowController?.close()
highlightWindowController = nil
}
func highlight(window: Window) {
removeHighlight()
highlightWindowController = HighlightWindowController()
highlightWindowController?.highlight(frame: window.frame, animate: false)
highlightWindowController?.showWindow(nil)
}
class HighlightWindowController: NSWindowController, NSWindowDelegate {
// MARK: - Initializers
init() {
let bounds = NSRect(x: 0, y: 0, width: 100, height: 100)
let window = NSWindow(contentRect: bounds, styleMask: .borderless, backing: .buffered, defer: true)
window.isOpaque = false
window.level = .screenSaver
window.backgroundColor = NSColor.blue
window.alphaValue = 0.2
window.ignoresMouseEvents = true
super.init(window: window)
window.delegate = self
}
// MARK: - Public API
func highlight(frame: CGRect, animate: Bool) {
if animate {
NSAnimationContext.current.duration = 0.1
}
let target = animate ? window?.animator() : window
target?.setFrame(frame, display: false)
}
}
如您所见,光标下的窗口被突出显示,但是突出显示的窗口被绘制在其他可能相交的窗口之上。
可能的解决方案 我可以遍历列表中的可用窗口,只找到不与其他窗口重叠的矩形,以便仅为这部分而不是整个窗口绘制高亮矩形。
我在问自己,对于这个问题,这是否会是一个更优雅、更高效的解决方案。也许我可以用绘制的 HighlightWindow 的窗口级别来解决这个问题?或者是否有任何来自 Apple 的 API,我可以利用它来获得所需的行为?
【问题讨论】: