Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it work automatically when used in a menu bar app #40

Open
tesths opened this issue Aug 1, 2019 · 11 comments
Open

Make it work automatically when used in a menu bar app #40

tesths opened this issue Aug 1, 2019 · 11 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@tesths
Copy link

tesths commented Aug 1, 2019

I make an app, just with statusbar and menu item. And I add preferences in the menu item.
But when the Preferences open, I can't use cmd+w close it. Only has to click red close button in the left up corner.

@Mortennn
Copy link
Contributor

Mortennn commented Aug 1, 2019

You can't because your app misses an app menu.

As a workaround, you could use a library to bind cmd+w to closing the preferences window.

@tesths
Copy link
Author

tesths commented Aug 2, 2019

You can't because your app misses an app menu.

As a workaround, you could use a library to bind cmd+w to closing the preferences window.

@Mortennn Thanks for your advise. But I already try your solution. It has some problem.
MASShortcut is global binding. If I bind cmd+w to my app, other app can not use cmd+w to close windows. I have to stop my app, so that other apps will be normal to use cmd+w to close it's window.

@tesths
Copy link
Author

tesths commented Aug 20, 2019

I think it's my fault.
As apple document says

All of an application’s menus in the menu bar are owned by one NSMenu instance that’s created by the application when it starts up. You can retrieve this main menu with the NSApplication method mainMenu.

So I add custom menu programmatically. And now I can close it by cmd+w.
I just reference Working without a nib, Part 10: Mac Main Menu. All things done.

@tesths tesths closed this as completed Aug 20, 2019
@sindresorhus
Copy link
Owner

sindresorhus commented Nov 1, 2019

I think we could add something to make this just work.

  1. If the app is a menu bar app, call NSApp.activate(ignoringOtherApps: true) in PreferencesWindowController.show().
  2. If the app is a menu bar app, we could add the Command+C and Command+M shortcuts:
final class WindowForMenuBarApp: NSWindow {
	override var canBecomeMain: Bool { true }
	override var canBecomeKey: Bool { true }
	override var acceptsFirstResponder: Bool { true }

	override func cancelOperation(_ sender: Any?) {
		performClose(self)
	}

	override func keyDown(with event: NSEvent) {
		if event.modifiers == .command {
			if event.charactersIgnoringModifiers == "w" {
				performClose(self)
				return
			}

			if event.charactersIgnoringModifiers == "m" {
				performMiniaturize(self)
				return
			}
		}

		super.keyDown(with: event)
	}
}

@DivineDominion @SamusAranX Thoughts?

@sindresorhus sindresorhus reopened this Nov 1, 2019
@sindresorhus sindresorhus added enhancement New feature or request help wanted Extra attention is needed labels Nov 1, 2019
@sindresorhus sindresorhus changed the title Menu Bar App can't use shortcut close Preference Make it work automatically when used in a menu bar app Nov 1, 2019
@DivineDominion
Copy link
Collaborator

I don't understand the use case, yet. Even menu bar apps can have an (invisible) main menu that handles the shortcuts. (I maintain 2 that work nicely.)

I think this is workaround the app developers need to implement, not the Preferences library. Since preferences are so central to apps, there's no harm in showing a workaround as a code snippet or as another example app target. (I would prefer the latter.)

@sindresorhus
Copy link
Owner

Even menu bar apps can have an (invisible) main menu that handles the shortcuts. (I maintain 2 that work nicely.)

Without also showing the Dock icon when the window is shown? That's news to me.

I think this is workaround the app developers need to implement, not the Preferences library.

I'm arguing this for egoistic reasons, as I plan to use Preferences in one of my menu bar apps, and it would be nice if it just worked. After all, the point of this package is to make it easier to add a Preferences window, and many apps are menu bar apps, so it's not like this is a niche problem. I think most menu bar apps either don't care about fixing this or don't even know it's an issue. So the ultimate gain of us adding this here is generally better UX in many apps for the user, which is a big win.

@DivineDominion
Copy link
Collaborator

DivineDominion commented Nov 12, 2019 via email

@sindresorhus
Copy link
Owner

If you want to try, create a new Cocoa app from scratch, add the LSUIElement Info.plist key, and add a text view to the main window. Copy and paste should just work. Now disable or remove the "Edit" main menu (that is not even visible during the app runtime) and try again.

Wow. Interesting. I could have sworn that did not use to work, but I have not had a MainMenu.xib in my menu bar app for years.

@sindresorhus
Copy link
Owner

Tidbit: When using SwiftUI, that (Command+C, etc) works even with a main menu.

@iolate
Copy link

iolate commented Apr 10, 2022

I just reference Working without a nib, Part 10: Mac Main Menu. All things done.

Here is code for my menu bar app with SwiftUI.
Since main menu are invisible on menu bar app, I removed File/Edit submenu rules and removed localized string.

import Cocoa

@objc protocol EditMenuActions {
    func redo(_ sender: AnyObject)
    func undo(_ sender: AnyObject)
}

class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationWillFinishLaunching(_ notification: Notification) {
        let mainMenu = NSMenu(title: "MainMenu")
        let menuItem = mainMenu.addItem(withTitle: "", action: nil, keyEquivalent: "")
        
        let submenu = NSMenu()
        submenu.addItem(withTitle: "Close Window", action: #selector(NSWindow.performClose(_:)), keyEquivalent: "w")
        submenu.addItem(withTitle: "Undo", action: #selector(EditMenuActions.undo(_:)), keyEquivalent: "z")
        submenu.addItem(withTitle: "Redo", action: #selector(EditMenuActions.redo(_:)), keyEquivalent: "Z")
        submenu.addItem(withTitle: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x")
        submenu.addItem(withTitle: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c")
        submenu.addItem(withTitle: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v")
        submenu.addItem(withTitle: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a")
        
        mainMenu.setSubmenu(submenu, for: menuItem)
        NSApp.mainMenu = mainMenu
    }
}

@DivineDominion
Copy link
Collaborator

@iolate 👍 Keep in mind that if users set custom keyboard shortcuts, though, and using a non-English language for macOS, their rebound keys might be broken if you do not localize the titles. https://support.apple.com/en-sa/guide/mac-help/mchlp2271/mac

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

5 participants