Fix showing popup menu with GTK/Wayland without active event

Since a261c80 (Avoid Gdk-CRITICAL warnings when using PopupMenu() with
Wayland, 2022-04-22) popup menus shown when there is no related current
event did not work when using default positioning. Fix this by always
providing a GdkWindow and a GdkEvent, and using a suitable substitute
when a real event is not available.
See #23892
This commit is contained in:
Paul Cornett 2023-09-24 14:20:29 -07:00
parent 3b7d81b7f2
commit df6366ff57

View file

@ -6083,14 +6083,34 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
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
GdkEvent* currentEvent = gtk_get_current_event();
GdkEvent* event = currentEvent;
GdkDevice* device = event ? gdk_event_get_device(event) : nullptr;
if (device == nullptr)
{
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);
GdkSeat* seat = gdk_display_get_default_seat(gdk_window_get_display(window));
device = gdk_seat_get_pointer(seat);
}
GdkEventButton eventTmp = { };
if (event == nullptr)
{
// An event is needed to avoid a Gtk-WARNING "no trigger event for menu popup".
// If a real one is not available, use a temporary with the fields
// set that GTK is going to use.
eventTmp.type = GDK_BUTTON_RELEASE;
eventTmp.time = GDK_CURRENT_TIME;
eventTmp.device = device;
event = (GdkEvent*)&eventTmp;
}
if (x == -1 && y == -1)
gdk_window_get_device_position(window, device, &x, &y, nullptr);
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, event);
if (currentEvent)
gdk_event_free(currentEvent);
}
else
#endif // GTK_CHECK_VERSION(3,22,0)