我正在开发一个无停靠应用程序(LSUIElement
true)。当用户单击相应的 NSStatusItem 或使用键盘快捷键时,应用程序会弹出一个菜单。
我的问题是,每当用户切换到另一个应用程序(使用 ⌘-TAB)而不先关闭菜单时,所有以编程方式弹出菜单的方法都会挂起。我尝试过 popUpMenuPositioningItem:atLocation:inView:
、popUpContextMenu:withEvent:forView:
以及 NSStatusItem
上的相应方法 (popUpStatusItemMenu: )。
如果用户使用 ESC 键关闭菜单,则一切正常,但如果用户切换到不同的应用程序,则上述方法永远不会返回(它们似乎同步运行,并在菜单关闭时返回)。应用程序不会崩溃,并且有一些技巧可以重新获得控制(调用 exposé,或单击任何弹出菜单的 NSStatusItem
)。
如果应用程序有停靠图标(即将LSUIElement
设置为 false),该问题就会消失。
这是使用键盘快捷键时弹出菜单的代码:
[mainMenu popUpMenuPositioningItem:[mainMenu itemAtIndex:0]
atLocation:[NSEvent mouseLocation]
inView:nil];
这是单击 NSStatusItem
时弹出菜单的代码:
- (void)mouseDown:(NSEvent *)event
{
[statusItem popUpStatusItemMenu:[statusItem menu]];
}
mouseDown:
方法位于附加到 NSStatusItem
的自定义 NSView
。
知道如何解决这个问题吗?
感谢您的帮助。
更新
问题也与正在激活的应用程序有关(我在显示菜单之前使用 [NSApp activateIgnoringOtherApps:YES];
,或者在某些情况下无法使用键盘导航菜单)。
I am working on a dockless application (LSUIElement
true). The application pops up a menu when the user clicks on the corresponding NSStatusItem
, or when a keyboard shortcut is used.
My problem is that all methods to pop up a menu programmatically hang whenever the user switches to another application (using ⌘-TAB) without dismissing the menu first. I have tried popUpMenuPositioningItem:atLocation:inView:
, popUpContextMenu:withEvent:forView:
, and the corresponding method on NSStatusItem
(popUpStatusItemMenu:
).
If the user dismisses the menu with the ESC key everything works fine, but if the user switches to a different application, the above-mentioned methods never return (they seem to run synchronously and return when the menu is dismissed). The application does not crash, and there are a couple of tricks to regain control (invoking exposé, or clicking on any NSStatusItem
which pops up a menu).
The problem disappears if the application has a dock icon (i.e. setting LSUIElement
to false).
This is the code popping up the menu when the keyboard shortcut is used:
[mainMenu popUpMenuPositioningItem:[mainMenu itemAtIndex:0]
atLocation:[NSEvent mouseLocation]
inView:nil];
And this is the code popping up the menu when the NSStatusItem
is clicked:
- (void)mouseDown:(NSEvent *)event
{
[statusItem popUpStatusItemMenu:[statusItem menu]];
}
The mouseDown:
method is in the custom NSView
attached to the NSStatusItem
.
Any idea on how to fix this?
Thanks for your help.
Update
The problem is also linked to the application being activated (I use [NSApp activateIgnoringOtherApps:YES];
before showing the menu, or in some cases it is not possible to navigate the menu with the keyboard).
发布评论
评论(1)
看来该问题是由于应用程序激活和 popUpMenu 发生在同一事件周期中造成的。我找到了一种解决方法,在 这篇文章。
总之,您需要首先激活应用程序(使用
[NSApp activateIgnoringOtherApps:YES];
),然后弹出菜单,确保这发生在新的事件周期中:您可以使用一个 NSTimer 来触发菜单。It appears that the problem is due to the application activation and popUpMenu happening in the same event cycle. I have found a workaround, described in more details in this post.
Is summary, you need to activate the application first (using
[NSApp activateIgnoringOtherApps:YES];
), and pop up the menu after, making sure this happens in a new event cycle: you can achieve this using a NSTimer to trigger the menu.