marcus
marcus

Reputation: 83

Mac OS Menu Bar Add Right Click To Show Another View

I have a Mac OS menu bar which when clicked opens a popup view, I want to add upon this by incorporating a quit function. When the icon is right clicked another popup menu will be presented.

I am stuck on trying to get the another popup menu to present, I am able to detect a right click on the icon but I unable to show the popup menu view.

Preview when i left click

GIF

POPUP MENU VIEW FOR BOTH POPUPS

    @main
struct MenuNoteApp: App {
    
    let persistenceController = PersistenceController.shared
    
    @Environment(\.scenePhase) var scenePhase
    
    @NSApplicationDelegateAdaptor(AppDelegate.self) var delegate
    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
        }
        .onChange(of: scenePhase) { _ in
            persistenceController.save()
        }
    }
    
}


extension NSStatusBarButton {
    open override func rightMouseUp(with event: NSEvent) {
        // Detect right click and prints right click
        print("right click")
    }
}

class AppDelegate: NSObject,NSApplicationDelegate{
    let persistenceController = PersistenceController.shared
    
    // Status Item
    var statusItem: NSStatusItem?
    
    // PopOver
    var popOver = NSPopover()
    var popOverOptions = NSPopover()
    
    func applicationDidFinishLaunching(  _ notification: Notification){
        // Menu View
        let menuView = MenuView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
        
        // Creating PopOver
        popOver.behavior = .transient
        popOver.animates = true
        
        // Setting Empty View Controller And Setting View as SwiftUI View with help of hosting controller
        popOver.contentViewController = NSViewController()
        popOver.contentViewController?.view = NSHostingView(rootView: menuView)
        
        popOverOptions.contentViewController = NSViewController()
        popOverOptions.contentViewController?.view = NSHostingView(rootView: OptionsView())
        
        // Creating Status Bar Button
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        
        
        // Check if status button is available
        if let MenuButton = statusItem?.button {
            MenuButton.image = NSImage(systemSymbolName: "note", accessibilityDescription: nil)
            MenuButton.action = #selector(MenuButtonToggle)
        }
    }
    
    // Button Action
    @objc func MenuButtonToggle(sender: AnyObject){
        if popOver.isShown{
            popOver.performClose(sender)
        }
        else if popOverOptions.isShown{
            popOverOptions.performClose(sender)
        }
        else{
            //Present Pop Over
            if let menuButton = statusItem?.button{
               // popOver is the main view while popOverOpitions is the second view
               self.popOver.show(relativeTo: menuButton.bounds, of: menuButton, preferredEdge: NSRectEdge.minY)
            }
           
            
        }
    }
    
    
}

Upvotes: 0

Views: 301

Answers (1)

diogo
diogo

Reputation: 541

Instead of overriding functions in NSStatusBarButton, you should detect the left and right click behavior within the MenuButtonToggle function.

First, you should register the right-click action, inside your the if-let inside applicationDidFinishLaunching, like so:

if let menuButton = statusItem?.button {
    menuButton.image = NSImage(systemSymbolName: "note", accessibilityDescription: nil)
    menuButton.action = #selector(MenuButtonToggle)
    menuButton.sendAction(on: [.leftMouseUp, .rightMouseUp]) // register action on right click too
}

Then, you want to update the MenuButtonToggle function to act differently depending on left and right clicks.

@objc func menuButtonToggle(sender: AnyObject){
    // ... previous logic here

    if let event = NSApp.currentEvent {
        if event.type == NSEventType.rightMouseUp {
            // Right button click
            self.popOver.show(...)
        } else {
            // Left button click
            self.popOverOptions.show(...)
       }
    }
}

Upvotes: 2

Related Questions