X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/13d3511257d0f2cad7a2fdb81b7f9dff0e136016..2091f5e71a1d04cf9277565121725f764d466a06:/src/gtk/menu.cpp?ds=sidebyside diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index 89f152917f..2a2e7bdc25 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -44,6 +44,11 @@ // we use normal item but with a special id for the menu title static const int wxGTK_TITLE_ID = -3; +// defined in window.cpp +#ifndef __WXGTK20__ + extern guint32 wxGtkTimeLastClick; +#endif + //----------------------------------------------------------------------------- // idle system //----------------------------------------------------------------------------- @@ -1522,3 +1527,124 @@ static wxString GetGtkHotKey( const wxMenuItem& item ) } #endif // wxUSE_ACCEL + +// ---------------------------------------------------------------------------- +// Pop-up menu stuff +// ---------------------------------------------------------------------------- + +#if wxUSE_MENUS_NATIVE + +extern "C" +void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting ) +{ + *is_waiting = FALSE; +} + +void SetInvokingWindow( wxMenu *menu, wxWindow* win ) +{ + menu->SetInvokingWindow( win ); + + wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); + while (node) + { + wxMenuItem *menuitem = node->GetData(); + if (menuitem->IsSubMenu()) + { + SetInvokingWindow( menuitem->GetSubMenu(), win ); + } + + node = node->GetNext(); + } +} + +extern "C" +void wxPopupMenuPositionCallback( GtkMenu *menu, + gint *x, gint *y, +#ifdef __WXGTK20__ + gboolean * WXUNUSED(whatever), +#endif + gpointer user_data ) +{ + // ensure that the menu appears entirely on screen + GtkRequisition req; + gtk_widget_get_child_requisition(GTK_WIDGET(menu), &req); + + wxSize sizeScreen = wxGetDisplaySize(); + wxPoint *pos = (wxPoint*)user_data; + + gint xmax = sizeScreen.x - req.width, + ymax = sizeScreen.y - req.height; + + *x = pos->x < xmax ? pos->x : xmax; + *y = pos->y < ymax ? pos->y : ymax; +} + +bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) +{ + wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") ); + + wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") ); + + // NOTE: if you change this code, you need to update + // the same code in taskbar.cpp as well. This + // is ugly code duplication, I know. + + SetInvokingWindow( menu, this ); + + menu->UpdateUI(); + + bool is_waiting = true; + + gulong handler = gtk_signal_connect( GTK_OBJECT(menu->m_menu), + "hide", + GTK_SIGNAL_FUNC(gtk_pop_hide_callback), + (gpointer)&is_waiting ); + + wxPoint pos; + gpointer userdata; + GtkMenuPositionFunc posfunc; + if ( x == -1 && y == -1 ) + { + // use GTK's default positioning algorithm + userdata = NULL; + posfunc = NULL; + } + else + { + pos = ClientToScreen(wxPoint(x, y)); + userdata = &pos; + posfunc = wxPopupMenuPositionCallback; + } + + wxMenuEvent eventOpen(wxEVT_MENU_OPEN, -1, menu); + DoCommonMenuCallbackCode(menu, eventOpen); + + gtk_menu_popup( + GTK_MENU(menu->m_menu), + (GtkWidget *) NULL, // parent menu shell + (GtkWidget *) NULL, // parent menu item + posfunc, // function to position it + userdata, // client data + 0, // button used to activate it +#ifdef __WXGTK20__ + gtk_get_current_event_time() +#else + wxGtkTimeLastClick // the time of activation +#endif + ); + + while (is_waiting) + { + gtk_main_iteration(); + } + + gtk_signal_disconnect(GTK_OBJECT(menu->m_menu), handler); + + wxMenuEvent eventClose(wxEVT_MENU_CLOSE, -1, menu); + DoCommonMenuCallbackCode(menu, eventClose); + + return true; +} + +#endif // wxUSE_MENUS_NATIVE +