Skip to content

Commit

Permalink
Ensure appearance panels stay pinned to the top of the screen
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanbaird committed Feb 5, 2024
1 parent cea3d46 commit d7b4a48
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 43 deletions.
21 changes: 20 additions & 1 deletion Ice/MenuBar/MenuBarAppearancePanel/MenuBarAppearancePanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ class MenuBarAppearancePanel: NSPanel {
}
.store(in: &c)

// ensure the panel stays pinned to the top of the screen
// if the size of the screen changes, i.e. when scaling a
// VM window
Timer.publish(every: 1, on: .main, in: .common)
.autoconnect()
.sink { [weak self] _ in
guard
let self,
let screen
else {
return
}
setFrame(menuBarFrame(forScreen: screen), display: true)
}
.store(in: &c)

cancellables = c
}

Expand All @@ -84,7 +100,10 @@ class MenuBarAppearancePanel: NSPanel {
/// - Parameter screen: The screen to use to compute the
/// frame of the menu bar.
func menuBarFrame(forScreen screen: NSScreen) -> CGRect {
guard let menuBarFrame = appearanceManager?.menuBarManager?.menuBarFrame else {
guard
let menuBarManager = appearanceManager?.menuBarManager,
let menuBarFrame: CGRect = try? menuBarManager.menuBar?.attribute(.frame)
else {
return .zero
}
return CGRect(
Expand Down
42 changes: 0 additions & 42 deletions Ice/MenuBar/MenuBarManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ import SwiftUI

/// Manager for the state of the menu bar.
final class MenuBarManager: ObservableObject {
/// An error that can be thrown during menu bar operations.
enum MenuBarError: Error {
/// The given accessibility role of a UI element is not
/// what was expected.
case invalidRole(expected: Role, found: Role?)
}

/// Set to `true` to tell the menu bar to save its sections.
@Published var needsSave = false

Expand Down Expand Up @@ -56,9 +49,6 @@ final class MenuBarManager: ObservableObject {
/// The UI element that represents the menu bar.
@Published var menuBar: UIElement?

/// The frame of the menu bar.
@Published var menuBarFrame: CGRect?

/// The sections currently in the menu bar.
@Published private(set) var sections = [MenuBarSection]() {
willSet {
Expand Down Expand Up @@ -317,19 +307,6 @@ final class MenuBarManager: ObservableObject {
}
.store(in: &c)

$menuBar
.receive(on: DispatchQueue.main)
.sink { [weak self] menuBar in
guard
let self,
let menuBar
else {
return
}
updateMenuBarFrame(menuBar: menuBar)
}
.store(in: &c)

// propagate changes up from child observable objects
appearanceManager.objectWillChange
.sink { [weak self] in
Expand Down Expand Up @@ -461,25 +438,6 @@ final class MenuBarManager: ObservableObject {
sections[index].controlItem = sortedControlItems[index]
}
}

/// Updates the menu bar frame using the given UI element.
///
/// - IMPORTANT: The UI element that is passed to the `menuBar`
/// parameter _must_ have the `menuBar` role, or an error will
/// be logged and the menu bar frame will not be updated.
///
/// - Parameter menuBar: The UI element representing the menu bar.
private func updateMenuBarFrame(menuBar: UIElement) {
do {
let role = try menuBar.role()
guard role == .menuBar else {
throw MenuBarError.invalidRole(expected: .menuBar, found: role)
}
menuBarFrame = try menuBar.attribute(.frame)
} catch {
Logger.menuBarManager.error("Error updating menu bar frame: \(error)")
}
}
}

// MARK: MenuBarManager: BindingExposable
Expand Down

0 comments on commit d7b4a48

Please sign in to comment.