@@ -133,6 +133,7 @@ struct MenuBarView: View {
133133 }
134134 . frame ( width: 840 )
135135 . background ( bgGradient)
136+ . background ( MenuBarPopupPositioner ( ) )
136137 . animation ( . easeInOut( duration: 0.22 ) , value: settings. menuBarTab)
137138 . onReceive ( Timer . publish ( every: 3.0 , on: . main, in: . common) . autoconnect ( ) ) { _ in
138139 // Keep menu popup values fresh while it is open.
@@ -3114,3 +3115,52 @@ struct MenuBarStatusRow: View {
31143115 }
31153116 }
31163117}
3118+
3119+ // MARK: - Menu Bar Popup Positioner
3120+ // Moves the MenuBarExtra popup window to the top-right corner every time it opens.
3121+ private struct MenuBarPopupPositioner : NSViewRepresentable {
3122+ func makeNSView( context: Context ) -> NSView {
3123+ let view = _PositionerView ( )
3124+ return view
3125+ }
3126+ func updateNSView( _ nsView: NSView , context: Context ) { }
3127+ }
3128+
3129+ private final class _PositionerView : NSView {
3130+ private var observer : NSObjectProtocol ?
3131+
3132+ override func viewDidMoveToWindow( ) {
3133+ super. viewDidMoveToWindow ( )
3134+ guard let window else { return }
3135+ positionTopRight ( window)
3136+
3137+ // Re-position every time the popup becomes key (i.e. every click on the icon)
3138+ observer = NotificationCenter . default. addObserver (
3139+ forName: NSWindow . didBecomeKeyNotification,
3140+ object: window,
3141+ queue: . main
3142+ ) { [ weak window] _ in
3143+ guard let window else { return }
3144+ self . positionTopRight ( window)
3145+ }
3146+ }
3147+
3148+ override func removeFromSuperview( ) {
3149+ if let observer { NotificationCenter . default. removeObserver ( observer) }
3150+ super. removeFromSuperview ( )
3151+ }
3152+
3153+ private func positionTopRight( _ window: NSWindow ) {
3154+ for delay in [ 0.05 , 0.15 , 0.3 ] {
3155+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + delay) { [ weak window] in
3156+ guard let window, window. isVisible else { return }
3157+ guard let screen = window. screen ?? NSScreen . main else { return }
3158+ let visible = screen. visibleFrame
3159+ let size = window. frame. size
3160+ let x = visible. maxX - size. width - 8
3161+ let y = visible. maxY - size. height
3162+ window. setFrameOrigin ( NSPoint ( x: x, y: y) )
3163+ }
3164+ }
3165+ }
3166+ }
0 commit comments