Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0671abed8 | ||
|
|
569abe967f | ||
|
|
3e57efe312 | ||
|
|
2312e09105 |
@@ -135,12 +135,16 @@ preferred position controls where the hidden/kept boundary lands:
|
|||||||
hidden too; above ~300 app icons (Now Playing, TextInput) leak back.
|
hidden too; above ~300 app icons (Now Playing, TextInput) leak back.
|
||||||
- `debug.spacerPos` (Double) overrides the seed for tuning without rebuilding.
|
- `debug.spacerPos` (Double) overrides the seed for tuning without rebuilding.
|
||||||
- Pressing a tray tile calls `MenuBarItemManager.press`. A hidden item sits
|
- Pressing a tray tile calls `MenuBarItemManager.press`. A hidden item sits
|
||||||
off-screen, and its menu would open off-screen too, so press briefly
|
off-screen, and its menu opens off-screen too (verified with `--diag-press`:
|
||||||
`suspend()`s the hider, waits ~0.18s for the layout to settle, performs the
|
the menu window lands at negative x). So press briefly `suspend()`s the hider,
|
||||||
accessibility action (`kAXPressAction`, then `kAXShowMenuAction`), and
|
waits ~0.2s for the layout to settle, performs the accessibility action
|
||||||
`resume()`s ~1s later. The reveal is momentary, not for the whole time the
|
(`kAXPressAction`, then `kAXShowMenuAction`), and `resume()`s ~0.1s later. The
|
||||||
panel is open. macOS does not let us place or anchor another app's menu
|
menu is its own window anchored at the item's on-screen spot, so it survives
|
||||||
anywhere else, so a momentary reveal is the only way to show it in view.
|
re-hiding.
|
||||||
|
- **Cannot reveal a single icon.** The spacer hides a contiguous block to its
|
||||||
|
left, so a press can only reveal the whole block. Isolating one item would
|
||||||
|
need either per-item ordering control (not available) or covering the icons
|
||||||
|
with an overlay window instead of moving them off-screen.
|
||||||
- **Order matters**: `AppDelegate` must call `setupStatusItem()` *before*
|
- **Order matters**: `AppDelegate` must call `setupStatusItem()` *before*
|
||||||
`MenuBarHider.shared.prepare()`. If the hider contracts the bar first, the
|
`MenuBarHider.shared.prepare()`. If the hider contracts the bar first, the
|
||||||
hamburger is created into the collapsed space and lands off-screen.
|
hamburger is created into the collapsed space and lands off-screen.
|
||||||
|
|||||||
@@ -48,6 +48,27 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
setupStatusItem()
|
setupStatusItem()
|
||||||
MenuBarHider.shared.prepare()
|
MenuBarHider.shared.prepare()
|
||||||
|
|
||||||
|
if CommandLine.arguments.contains("--diag-press") {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
|
||||||
|
MenuBarHider.shared.suspend()
|
||||||
|
}
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2.25) {
|
||||||
|
if let item = MenuBarItemManager.enumerate().first(where: {
|
||||||
|
$0.title.lowercased().contains("wireguard")
|
||||||
|
}) {
|
||||||
|
NSLog("diag-press: pressing \(item.appName) after brief reveal")
|
||||||
|
_ = AXUIElementPerformAction(item.element, kAXPressAction as CFString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2.45) {
|
||||||
|
MenuBarHider.shared.resume()
|
||||||
|
}
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) {
|
||||||
|
dumpWindows()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if CommandLine.arguments.contains("--diag") {
|
if CommandLine.arguments.contains("--diag") {
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
|
||||||
dumpMenuBarItems()
|
dumpMenuBarItems()
|
||||||
|
|||||||
@@ -117,10 +117,11 @@ final class MenuBarItemManager: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
hider.suspend()
|
hider.suspend()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.18) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||||
_ = self.performPress(item)
|
_ = self.performPress(item)
|
||||||
// Let the menu finish appearing before the bar contracts again.
|
// The menu is its own window, positioned at the item's on-screen
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
// spot, so the bar can be re-hidden almost immediately.
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
hider.resume()
|
hider.resume()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,28 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import ApplicationServices
|
import ApplicationServices
|
||||||
|
import CoreGraphics
|
||||||
|
|
||||||
|
/// Diagnostic used by `open SimpleTopBar.app --args --diag-press`. Presses a
|
||||||
|
/// hidden item's accessibility element without revealing it and dumps the
|
||||||
|
/// resulting high-level windows, to see where its menu actually opens.
|
||||||
|
func dumpWindows() {
|
||||||
|
var lines: [String] = []
|
||||||
|
if let list = CGWindowListCopyWindowInfo([], kCGNullWindowID) as? [[String: Any]] {
|
||||||
|
for window in list {
|
||||||
|
let layer = window[kCGWindowLayer as String] as? Int ?? -1
|
||||||
|
guard layer > 20 else { continue }
|
||||||
|
let owner = window[kCGWindowOwnerName as String] as? String ?? "?"
|
||||||
|
let bounds = window[kCGWindowBounds as String] as? [String: Any] ?? [:]
|
||||||
|
let x = bounds["X"] as? Double ?? 0
|
||||||
|
let y = bounds["Y"] as? Double ?? 0
|
||||||
|
let width = bounds["Width"] as? Double ?? 0
|
||||||
|
let height = bounds["Height"] as? Double ?? 0
|
||||||
|
lines.append("\(owner) layer=\(layer) frame=\(Int(x)),\(Int(y)) \(Int(width))x\(Int(height))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try? lines.joined(separator: "\n").write(toFile: "/tmp/simpletopbar-windows.txt", atomically: true, encoding: .utf8)
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Diagnostic used by `open SimpleTopBar.app --args --dump-items`. Writes the
|
/// Diagnostic used by `open SimpleTopBar.app --args --dump-items`. Writes the
|
||||||
/// live Accessibility view of the menu bar to /tmp so it can be inspected
|
/// live Accessibility view of the menu bar to /tmp so it can be inspected
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
VERSION="${1:-0.2.3}"
|
VERSION="${1:-0.4.1}"
|
||||||
|
|
||||||
swift build -c release
|
swift build -c release
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user