Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions Amethyst/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet var versionMenuItem: NSMenuItem?
@IBOutlet var startAtLoginMenuItem: NSMenuItem?
@IBOutlet var toggleGlobalTilingMenuItem: NSMenuItem?
@IBOutlet var layoutsMenuItem: NSMenuItem?

private var isFirstLaunch = true

Expand Down Expand Up @@ -71,6 +72,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
hotKeyManager = HotKeyManager(userConfiguration: UserConfiguration.shared)

hotKeyManager?.setUpWithWindowManager(windowManager!, configuration: UserConfiguration.shared, appDelegate: self)

// Populate layouts menu now that windowManager is initialized
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.populateLayoutsMenu()
}
}

override func awakeFromNib() {
Expand All @@ -93,6 +99,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
toggleGlobalTilingMenuItem?.title = "Disable"

startAtLoginMenuItem?.state = (LoginServiceKit.isExistLoginItems(at: Bundle.main.bundlePath) ? .on : .off)

// Set up layouts menu delegate to refresh when opened
layoutsMenuItem?.submenu?.delegate = self

populateLayoutsMenu()
}

func applicationDidBecomeActive(_ notification: Notification) {
Expand Down Expand Up @@ -173,6 +184,66 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}
}

private func populateLayoutsMenu() {
guard let layoutsMenuItem = layoutsMenuItem,
let submenu = layoutsMenuItem.submenu else {
return
}

// Clear existing items
submenu.removeAllItems()

// Get enabled layout keys from user configuration
let enabledLayoutKeys = UserConfiguration.shared.layoutKeys()

// Get all available layouts with their display names
let availableLayouts = LayoutType<SIApplication.Window>.availableLayoutStrings()

// Get current layout
let focusedScreenManager = windowManager?.focusedScreenManager()
var currentLayoutKey = focusedScreenManager?.currentLayout?.layoutKey

// If no focused screen manager, fallback to the first screen manager
if focusedScreenManager == nil, let firstScreenManager = windowManager?.screenManager(at: 0) {
currentLayoutKey = firstScreenManager.currentLayout?.layoutKey
}
Comment on lines +203 to +210
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure that this is the correct way to find ScreenManager


// Filter to only enabled layouts and add menu items
for layoutKey in enabledLayoutKeys {
guard let layoutInfo = availableLayouts.first(where: { $0.key == layoutKey }) else {
continue
}

let menuItem = NSMenuItem(title: layoutInfo.name, action: #selector(selectLayout(_:)), keyEquivalent: "")
menuItem.target = self
menuItem.representedObject = layoutKey

// Mark current layout with checkmark
let isCurrentLayout = layoutKey == currentLayoutKey
menuItem.state = isCurrentLayout ? .on : .off

submenu.addItem(menuItem)
}

// If no layouts are enabled, show a disabled message
if enabledLayoutKeys.isEmpty {
let noLayoutsItem = NSMenuItem(title: "No layouts enabled", action: nil, keyEquivalent: "")
noLayoutsItem.isEnabled = false
submenu.addItem(noLayoutsItem)
}
}

@IBAction func selectLayout(_ sender: NSMenuItem) {
guard let layoutKey = sender.representedObject as? String,
let windowManager = windowManager,
let screenManager = windowManager.focusedScreenManager() else {
return
}

screenManager.selectLayout(layoutKey)
// Menu will be refreshed automatically when next opened via NSMenuDelegate
}
}

extension AppDelegate: NSWindowDelegate {
Expand All @@ -181,6 +252,22 @@ extension AppDelegate: NSWindowDelegate {
}
}

extension AppDelegate: NSMenuDelegate {
func menuNeedsUpdate(_ menu: NSMenu) {
// Refresh layouts menu when it's about to be shown
if menu == layoutsMenuItem?.submenu {
populateLayoutsMenu()
}
}

func menuWillOpen(_ menu: NSMenu) {
// Also refresh when menu is about to open
if menu == layoutsMenuItem?.submenu {
populateLayoutsMenu()
}
}
}

extension AppDelegate: UserConfigurationDelegate {
func configurationGlobalTilingDidChange(_ userConfiguration: UserConfiguration) {
var statusItemImage: NSImage?
Expand Down
7 changes: 7 additions & 0 deletions Amethyst/Base.lproj/MainMenu.xib
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
<action selector="toggleGlobalTiling:" target="494" id="3aM-9U-hWx"/>
</connections>
</menuItem>
<menuItem title="Layouts" id="layouts-menu-item">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" id="layouts-submenu">
<items/>
</menu>
</menuItem>
<menuItem title="Start Amethyst on Login" id="549">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
Expand Down Expand Up @@ -73,6 +79,7 @@
<outlet property="statusItemMenu" destination="536" id="547"/>
<outlet property="toggleGlobalTilingMenuItem" destination="rjJ-w4-5Ht" id="4Dq-e8-R1M"/>
<outlet property="versionMenuItem" destination="bNZ-Ry-Q4Q" id="jXC-pY-N2a"/>
<outlet property="layoutsMenuItem" destination="layouts-menu-item" id="layouts-menu-outlet"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
Expand Down
Loading