Fix menuitem actions in macOS 10.15.1 (#234)
This commit is contained in:
parent
fcca7c970e
commit
f698e58767
@ -42,6 +42,7 @@
|
||||
499A485C22ED793C00F6C675 /* NSView+Nib.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499A485B22ED793C00F6C675 /* NSView+Nib.swift */; };
|
||||
499A485E22ED9B7C00F6C675 /* NSTableView+Reload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499A485D22ED9B7C00F6C675 /* NSTableView+Reload.swift */; };
|
||||
499A486522EEA3FD00F6C675 /* Array+Safe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 499A486422EEA3FC00F6C675 /* Array+Safe.swift */; };
|
||||
49ABB749236B0F9E00535CD7 /* UnsafePointer+bridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ABB748236B0F9E00535CD7 /* UnsafePointer+bridge.swift */; };
|
||||
49B1086A216A356D0064FFCE /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49B10869216A356D0064FFCE /* String+Extension.swift */; };
|
||||
49BC061C212931F4005A0FE7 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BC061B212931F4005A0FE7 /* AboutViewController.swift */; };
|
||||
49C9EF64223E78F5005D8B6A /* ClashProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49C9EF63223E78F5005D8B6A /* ClashProxy.swift */; };
|
||||
@ -141,6 +142,7 @@
|
||||
499A485B22ED793C00F6C675 /* NSView+Nib.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSView+Nib.swift"; sourceTree = "<group>"; };
|
||||
499A485D22ED9B7C00F6C675 /* NSTableView+Reload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reload.swift"; sourceTree = "<group>"; };
|
||||
499A486422EEA3FC00F6C675 /* Array+Safe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+Safe.swift"; sourceTree = "<group>"; };
|
||||
49ABB748236B0F9E00535CD7 /* UnsafePointer+bridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UnsafePointer+bridge.swift"; sourceTree = "<group>"; };
|
||||
49B10869216A356D0064FFCE /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
|
||||
49BC061B212931F4005A0FE7 /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
|
||||
49C9EF63223E78F5005D8B6A /* ClashProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClashProxy.swift; sourceTree = "<group>"; };
|
||||
@ -324,6 +326,7 @@
|
||||
4966E9E5211824F300A391FB /* NSImage+extension.swift */,
|
||||
496BDEDF21196F1E00C5207F /* Logger.swift */,
|
||||
49B10869216A356D0064FFCE /* String+Extension.swift */,
|
||||
49ABB748236B0F9E00535CD7 /* UnsafePointer+bridge.swift */,
|
||||
);
|
||||
path = Basic;
|
||||
sourceTree = "<group>";
|
||||
@ -590,6 +593,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
49ABB749236B0F9E00535CD7 /* UnsafePointer+bridge.swift in Sources */,
|
||||
499A485522ED707300F6C675 /* RemoteConfigViewController.swift in Sources */,
|
||||
49CF3B5C20CE8068001EBF94 /* ClashResourceManager.swift in Sources */,
|
||||
4952C3D02117027C004A4FA8 /* ConfigFileManager.swift in Sources */,
|
||||
|
15
ClashX/Basic/UnsafePointer+bridge.swift
Normal file
15
ClashX/Basic/UnsafePointer+bridge.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// UnsafePointer+bridge.swift
|
||||
// ClashX
|
||||
//
|
||||
// Created by yicheng on 2019/10/31.
|
||||
// Copyright © 2019 west2online. All rights reserved.
|
||||
//
|
||||
|
||||
func bridge<T: AnyObject>(obj: T) -> UnsafeMutableRawPointer {
|
||||
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
|
||||
}
|
||||
|
||||
func bridge<T: AnyObject>(ptr: UnsafeRawPointer) -> T {
|
||||
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
|
||||
}
|
@ -12,6 +12,9 @@ class ProxyGroupMenuItemView: NSView {
|
||||
let groupNameLabel: NSTextField
|
||||
let selectProxyLabel: NSTextField
|
||||
let arrowImageView = NSTextField(labelWithString: "▶")
|
||||
var isMouseInsideView = false
|
||||
var isMenuOpen = false
|
||||
|
||||
init(group: ClashProxyName, targetProxy: ClashProxyName) {
|
||||
groupNameLabel = NSTextField(labelWithString: group)
|
||||
selectProxyLabel = NSTextField(labelWithString: targetProxy)
|
||||
@ -55,6 +58,15 @@ class ProxyGroupMenuItemView: NSView {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func updateTrackingAreas() {
|
||||
super.updateTrackingAreas()
|
||||
if #available(macOS 10.15.1, *) {
|
||||
trackingAreas.forEach { removeTrackingArea($0) }
|
||||
enclosingMenuItem?.submenu?.delegate = self
|
||||
addTrackingArea(NSTrackingArea(rect: bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil))
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidMoveToSuperview() {
|
||||
super.viewDidMoveToSuperview()
|
||||
if #available(macOS 10.15, *) {} else {
|
||||
@ -64,10 +76,30 @@ class ProxyGroupMenuItemView: NSView {
|
||||
}
|
||||
}
|
||||
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isMouseInsideView = true
|
||||
setNeedsDisplay(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isMouseInsideView = false
|
||||
setNeedsDisplay(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
guard let menu = enclosingMenuItem else { return }
|
||||
if menu.isHighlighted {
|
||||
let isHighlighted: Bool
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isHighlighted = isMouseInsideView || isMenuOpen
|
||||
} else {
|
||||
isHighlighted = menu.isHighlighted
|
||||
}
|
||||
if isHighlighted {
|
||||
NSColor.selectedMenuItemColor.setFill()
|
||||
groupNameLabel.textColor = NSColor.white
|
||||
selectProxyLabel.textColor = NSColor.white
|
||||
@ -81,3 +113,19 @@ class ProxyGroupMenuItemView: NSView {
|
||||
dirtyRect.fill()
|
||||
}
|
||||
}
|
||||
|
||||
extension ProxyGroupMenuItemView: NSMenuDelegate {
|
||||
func menuWillOpen(_ menu: NSMenu) {
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isMenuOpen = true
|
||||
setNeedsDisplay(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
func menuDidClose(_ menu: NSMenu) {
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isMenuOpen = false
|
||||
setNeedsDisplay(bounds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
// Copyright © 2019 west2online. All rights reserved.
|
||||
//
|
||||
|
||||
import Carbon
|
||||
import Cocoa
|
||||
|
||||
class ProxyGroupSpeedTestMenuItem: NSMenuItem {
|
||||
@ -41,8 +42,10 @@ class ProxyGroupSpeedTestMenuItem: NSMenuItem {
|
||||
}
|
||||
|
||||
fileprivate class ProxyGroupSpeedTestMenuItemView: NSView {
|
||||
let label: NSTextField
|
||||
let font = NSFont.menuFont(ofSize: 14)
|
||||
private let label: NSTextField
|
||||
private let font = NSFont.menuFont(ofSize: 14)
|
||||
private var isMouseInsideView = false
|
||||
private var eventHandler: EventHandlerRef?
|
||||
|
||||
init(_ title: String) {
|
||||
label = NSTextField(labelWithString: title)
|
||||
@ -60,11 +63,12 @@ fileprivate class ProxyGroupSpeedTestMenuItemView: NSView {
|
||||
}
|
||||
|
||||
private func startBenchmark() {
|
||||
guard let group = (enclosingMenuItem as? ProxyGroupSpeedTestMenuItem)?.proxyGroup else { return }
|
||||
|
||||
guard let group = (enclosingMenuItem as? ProxyGroupSpeedTestMenuItem)?.proxyGroup
|
||||
else { return }
|
||||
let testGroup = DispatchGroup()
|
||||
label.stringValue = NSLocalizedString("Testing", comment: "")
|
||||
enclosingMenuItem?.isEnabled = false
|
||||
setNeedsDisplay(bounds)
|
||||
for proxyName in group.speedtestAble {
|
||||
testGroup.enter()
|
||||
ApiRequest.getProxyDelay(proxyName: proxyName) { delay in
|
||||
@ -82,6 +86,60 @@ fileprivate class ProxyGroupSpeedTestMenuItemView: NSView {
|
||||
self.label.stringValue = menu.title
|
||||
self.label.textColor = NSColor.labelColor
|
||||
menu.isEnabled = true
|
||||
self.setNeedsDisplay(self.bounds)
|
||||
}
|
||||
}
|
||||
|
||||
override func updateTrackingAreas() {
|
||||
super.updateTrackingAreas()
|
||||
if #available(macOS 10.15.1, *) {
|
||||
trackingAreas.forEach { removeTrackingArea($0) }
|
||||
addTrackingArea(NSTrackingArea(rect: bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil))
|
||||
addTrackingArea(NSTrackingArea(rect: bounds, options: [.mouseMoved, .activeAlways], owner: self, userInfo: nil))
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidMoveToWindow() {
|
||||
super.viewDidMoveToWindow()
|
||||
if #available(macOS 10.15.1, *) {
|
||||
setupCarbon()
|
||||
}
|
||||
}
|
||||
|
||||
// https://gist.github.com/p0deje/da5e5cfda6be8cb87c2e7caad3a3df63
|
||||
// https://stackoverflow.com/questions/53273191/custom-carbon-key-event-handler-fails-after-mouse-events
|
||||
@available(macOS 10.15.1, *)
|
||||
private func setupCarbon() {
|
||||
if window != nil {
|
||||
if let dispatcher = GetEventDispatcherTarget() {
|
||||
let eventHandlerCallback: EventHandlerUPP = { eventHandlerCallRef, eventRef, userData in
|
||||
guard let userData = userData else { return 0 }
|
||||
let itemView: ProxyGroupSpeedTestMenuItemView = bridge(ptr: userData)
|
||||
itemView.startBenchmark()
|
||||
let response = CallNextEventHandler(eventHandlerCallRef, eventRef!)
|
||||
return response
|
||||
}
|
||||
|
||||
let eventSpecs = [EventTypeSpec(eventClass: OSType(kEventClassMouse), eventKind: UInt32(kEventMouseUp))]
|
||||
|
||||
InstallEventHandler(dispatcher, eventHandlerCallback, 1, eventSpecs, bridge(obj: self), &eventHandler)
|
||||
}
|
||||
} else {
|
||||
RemoveEventHandler(eventHandler)
|
||||
}
|
||||
}
|
||||
|
||||
override func mouseEntered(with event: NSEvent) {
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isMouseInsideView = true
|
||||
setNeedsDisplay(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isMouseInsideView = false
|
||||
setNeedsDisplay(bounds)
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,13 +151,22 @@ fileprivate class ProxyGroupSpeedTestMenuItemView: NSView {
|
||||
}
|
||||
|
||||
override func mouseUp(with event: NSEvent) {
|
||||
startBenchmark()
|
||||
if #available(macOS 10.15.1, *) {} else {
|
||||
startBenchmark()
|
||||
}
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
guard let menu = enclosingMenuItem else { return }
|
||||
if menu.isHighlighted {
|
||||
|
||||
let isHighlighted: Bool
|
||||
if #available(macOS 10.15.1, *) {
|
||||
isHighlighted = isMouseInsideView
|
||||
} else {
|
||||
isHighlighted = menu.isHighlighted
|
||||
}
|
||||
if isHighlighted && menu.isEnabled {
|
||||
NSColor.selectedMenuItemColor.setFill()
|
||||
label.textColor = NSColor.white
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user