Calling PopupMenu with default position arguments on a frame does not work on Wayland when there's no current gtk event or trigger event.
See screenshot from KiCad. gtk_menu_popup_at_rect fails because rect_window is NULL.

Stack trace in KiCad:
libgtk-3.so.0!gtk_menu_popup_at_rect(GtkMenu * menu, GdkWindow * rect_window, const GdkRectangle * rect, GdkGravity rect_anchor, GdkGravity menu_anchor, const GdkEvent * trigger_event) (.../gtk+3.0/gtk+3.0-3.24.37/gtk/gtkmenu.c:2280)
libgtk-3.so.0!gtk_menu_popup_at_pointer(GtkMenu * menu, const GdkEvent * trigger_event) (.../gtk+3.0/gtk+3.0-3.24.37/gtk/gtkmenu.c:2430)
libwx_gtk3u_core-3.3.so.0!wxWindow::DoPopupMenu(wxWindow * const this, wxMenu * menu, int x, int y) (.../wxWidgets/src/gtk/window.cpp:6088)
libwx_gtk3u_core-3.3.so.0!wxWindowBase::PopupMenu(wxWindowBase * const this, wxMenu * menu, int x, int y) (.../wxWidgets/src/common/wincmn.cpp:3028)
_eeschema.kiface!wxWindowBase::PopupMenu(wxWindowBase * const this, wxMenu * menu, const wxPoint & pos) (/usr/local/include/wx-3.3/wx/window.h:1349)
_eeschema.kiface!TOOL_MANAGER::DispatchContextMenu(TOOL_MANAGER * const this, const TOOL_EVENT & aEvent) (.../kicad/common/tool/tool_manager.cpp:940)
_eeschema.kiface!TOOL_MANAGER::processEvent(TOOL_MANAGER * const this, const TOOL_EVENT & aEvent) (.../kicad/common/tool/tool_manager.cpp:1208)
_eeschema.kiface!TOOL_MANAGER::ProcessEvent(TOOL_MANAGER * const this, const TOOL_EVENT & aEvent) (.../kicad/common/tool/tool_manager.cpp:1018)
_eeschema.kiface!TOOL_DISPATCHER::handleMouseButton(TOOL_DISPATCHER * const this, wxEvent & aEvent, int aIndex, bool aMotion) (.../kicad/common/tool/tool_dispatcher.cpp:257)
_eeschema.kiface!TOOL_DISPATCHER::DispatchWxEvent(TOOL_DISPATCHER * const this, wxEvent & aEvent) (.../kicad/common/tool/tool_dispatcher.cpp:488)
_eeschema.kiface!EDA_DRAW_PANEL_GAL::OnEvent(EDA_DRAW_PANEL_GAL * const this, wxEvent & aEvent) (.../kicad/common/draw_panel_gal.cpp:581)
libwx_baseu-3.3.so.0!wxAppConsoleBase::HandleEvent(const wxAppConsoleBase * const this, wxEvtHandler * handler, wxEventFunction func, wxEvent & event) (.../wxWidgets/src/common/appbase.cpp:643)
libwx_baseu-3.3.so.0!wxAppConsoleBase::CallEventHandler(const wxAppConsoleBase * const this, wxEvtHandler * handler, wxEventFunctor & functor, wxEvent & event) (.../wxWidgets/src/common/appbase.cpp:655)
libwx_baseu-3.3.so.0!wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase & entry, wxEvtHandler * handler, wxEvent & event) (.../wxWidgets/src/common/event.cpp:1394)
libwx_baseu-3.3.so.0!wxEvtHandler::SearchDynamicEventTable(wxEvtHandler * const this, wxEvent & event) (.../wxWidgets/src/common/event.cpp:1854)
libwx_baseu-3.3.so.0!wxEvtHandler::TryHereOnly(wxEvtHandler * const this, wxEvent & event) (.../wxWidgets/src/common/event.cpp:1577)
libwx_baseu-3.3.so.0!wxEvtHandler::TryBeforeAndHere(wxEvtHandler * const this, wxEvent & event) (.../wxWidgets/include/wx/event.h:3991)
libwx_baseu-3.3.so.0!wxEvtHandler::ProcessEventLocally(wxEvtHandler * const this, wxEvent & event) (.../wxWidgets/src/common/event.cpp:1514)
libwx_baseu-3.3.so.0!wxEvtHandler::ProcessEvent(wxEvtHandler * const this, wxEvent & event) (.../wxWidgets/src/common/event.cpp:1487)
libwx_baseu-3.3.so.0!wxEvtHandler::ProcessPendingEvents(wxEvtHandler * const this) (.../wxWidgets/src/common/event.cpp:1361)
libwx_baseu-3.3.so.0!wxAppConsoleBase::ProcessPendingEvents(wxAppConsoleBase * const this) (.../wxWidgets/src/common/appbase.cpp:552)
libwx_gtk3u_core-3.3.so.0!wxApp::DoIdle(wxApp * const this) (.../wxWidgets/src/gtk/app.cpp:147)
libwx_gtk3u_core-3.3.so.0!wxapp_idle_callback() (.../wxWidgets/src/gtk/app.cpp:99)
libglib-2.0.so.0!g_main_context_dispatch (Unknown Source:0)
libglib-2.0.so.0![Unknown/Just-In-Time compiled code] (Unknown Source:0)
libglib-2.0.so.0!g_main_loop_run (Unknown Source:0)
libgtk-3.so.0!gtk_main() (.../gtk+3.0/gtk+3.0-3.24.37/gtk/gtkmain.c:1329)
libwx_gtk3u_core-3.3.so.0!wxGUIEventLoop::DoRun(wxGUIEventLoop * const this) (.../wxWidgets/src/gtk/evtloop.cpp:61)
libwx_baseu-3.3.so.0!wxEventLoopBase::Run(wxEventLoopBase * const this) (.../wxWidgets/src/common/evtloopcmn.cpp:87)
libwx_baseu-3.3.so.0!wxAppConsoleBase::MainLoop(wxAppConsoleBase * const this) (.../wxWidgets/src/common/appbase.cpp:363)
libwx_baseu-3.3.so.0!wxAppConsoleBase::OnRun(wxAppConsoleBase * const this) (.../wxWidgets/src/common/appbase.cpp:281)
libwx_gtk3u_core-3.3.so.0!wxAppBase::OnRun(wxAppBase * const this) (.../wxWidgets/src/common/appcmn.cpp:334)
APP_SINGLE_TOP::OnRun(APP_SINGLE_TOP * const this) (.../kicad/common/single_top.cpp:206)
libwx_baseu-3.3.so.0!wxEntry(int & argc, wxChar ** argv) (.../wxWidgets/src/common/init.cpp:492)
libwx_baseu-3.3.so.0!wxEntry(int & argc, char ** argv) (.../wxWidgets/src/common/init.cpp:503)
main(int argc, char ** argv) (.../kicad/common/single_top.cpp:286)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Commit that introduced gtk_menu_popup_at_pointer: a261c80
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
The following patch fixes the issue (I don't know if it is 100% correct of course).
diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 48b8621cc7..7aae931dd2 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -6085,7 +6085,26 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) if (wxGTKImpl::IsWayland(window) && wx_is_at_least_gtk3(22)) { if (x == -1 && y == -1) - gtk_menu_popup_at_pointer(GTK_MENU(menu->m_menu), nullptr); + { + GdkEvent * event = gtk_get_current_event(); + + if (!event) + { + event = gdk_event_new(GDK_BUTTON_PRESS); + event->button.type = GDK_BUTTON_PRESS; + event->button.window = g_object_ref(window); + event->button.time = GDK_CURRENT_TIME; + + GdkDisplay* display = gdk_window_get_display(window); + wxGCC_WARNING_SUPPRESS(deprecated-declarations) + GdkDeviceManager * device_manager = gdk_display_get_device_manager(display); + event->button.device = gdk_device_manager_get_client_pointer(device_manager); + wxGCC_WARNING_RESTORE() + } + + gtk_menu_popup_at_pointer(GTK_MENU(menu->m_menu), event); + gdk_event_free(event); + } else { const GdkRectangle rect = { x, y, 1, 1 };
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I guess the correct solution here is to keep a copy of the "trigger event", i.e. the last mouse event probably, and pass it to gtk_menu_popup_at_pointer()?
But the simplest solution would be to check if we're dispatching a (non-idle) event and use the old function in this case -- this would result in a warning but would still work, wouldn't it?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
This patch also works, and gets rid of this assert:
Gdk-Message: 00:33:34.360: Window 0x56341abc59d0 is a temporary window without parent, application will not be able to position it on screen.
(menu:177467): Gdk-CRITICAL **: 00:33:34.363: gdk_wayland_window_handle_configure_popup: assertion 'impl->transient_for' failed
diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 48b8621cc7..1c3c813c6f 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -6080,24 +6080,11 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) } menu->m_popupShown = true; -#if GTK_CHECK_VERSION(3,22,0) - GdkWindow* window = gtk_widget_get_window(m_wxwindow ? m_wxwindow : m_widget); - if (wxGTKImpl::IsWayland(window) && wx_is_at_least_gtk3(22)) - { - if (x == -1 && y == -1) - gtk_menu_popup_at_pointer(GTK_MENU(menu->m_menu), nullptr); - else - { - const GdkRectangle rect = { x, y, 1, 1 }; - gtk_menu_popup_at_rect(GTK_MENU(menu->m_menu), - window, &rect, GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, nullptr); - } - } - else -#endif // GTK_CHECK_VERSION(3,22,0) { wxGCC_WARNING_SUPPRESS(deprecated-declarations) + gtk_menu_attach_to_widget(GTK_MENU(menu->m_menu), GTK_WIDGET(m_widget), nullptr); + gtk_menu_popup( GTK_MENU(menu->m_menu), nullptr, // parent menu shell
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
With any of these fixes, press-and-hold left mouse button action to show a menu (via wxTimerEvent) does not work in KiCad. The menu disappears then the mouse button gets released. While the mouse button is down, the menu entries can not be selected using mouse.
https://github.com/wxWidgets/wxWidgets/assets/37658952/6462335d-c1f6-4282-927f-2dde66940611
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Turns out the above is only an issue in Plasma (KDE), not in GNOME, GNOME Classic, Ubuntu, Weston sessions.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
BTW, I can reproduce the problem under GNOME with just
diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp index 5f32257c6b..d4e68c726c 100644 --- a/samples/minimal/minimal.cpp +++ b/samples/minimal/minimal.cpp @@ -175,6 +175,14 @@ MyFrame::MyFrame(const wxString& title) CreateStatusBar(2); SetStatusText("Welcome to wxWidgets!"); #endif // wxUSE_STATUSBAR + + Bind(wxEVT_RIGHT_UP, [this](wxMouseEvent&) { + CallAfter([this]() { + wxMenu menu; + menu.Append(wxID_ABOUT, "About me"); + PopupMenu(&menu); + }); + }); }
and I can confirm that the fixes above work -- at least when using the default position of the menu. If the position is specified, the menu doesn't appear at all for me when using Wayland.
So I've decided to not use the position at all as it seems better than maybe (because apparently it does get shown in some circumstances, if it works for you?) not showing it at all.
Please see #23896, and let me know if you see any problem with it. If not, I'd like to apply it to 3.2.3 too. TIA!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
Closed #23892 as completed.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
This has been fixed in master and will be part of 3.2.3, so closing.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()