popUpMenuPositioningItem:atLocation:inView:切换到另一个应用程序时挂起

发布于 2024-10-29 22:34:46 字数 1212 浏览 0 评论 0 原文

我正在开发一个无停靠应用程序(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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

镜花水月 2024-11-05 22:34:46

看来该问题是由于应用程序激活和 popUpMenu 发生在同一事件周期中造成的。我找到了一种解决方法,在 这篇文章

总之,您需要首先激活应用程序(使用 [NSApp activateIgnoringOtherApps:YES];),然后弹出菜单,确保这发生在新的事件周期中:您可以使用一个 NSTimer 来触发菜单。

- (void) someMethod {
    // Some code
    [NSApp activateIgnoringOtherApps:YES];
    [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showMenu) userInfo:nil repeats:NO];
    //Some other code
}

- (void) showMenu {
    // This will show the menu at the current mouse position
    [aMenu popUpMenuPositioningItem:[mainMenu itemAtIndex:0] atLocation:[NSEvent mouseLocation] inView:nil];
}

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.

- (void) someMethod {
    // Some code
    [NSApp activateIgnoringOtherApps:YES];
    [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(showMenu) userInfo:nil repeats:NO];
    //Some other code
}

- (void) showMenu {
    // This will show the menu at the current mouse position
    [aMenu popUpMenuPositioningItem:[mainMenu itemAtIndex:0] atLocation:[NSEvent mouseLocation] inView:nil];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文