void wxMDIChildFrame::SetMenuBar( wxMenuBar *menu_bar ) { wxASSERT_MSG( m_menuBar == NULL, "Only one menubar allowed" ); m_menuBar = menu_bar; if (m_menuBar) { wxMDIParentFrame *mdi_frame = (wxMDIParentFrame*)m_parent->GetParent(); m_menuBar->SetParent( mdi_frame ); /* insert the invisible menu bar into the _parent_ mdi frame */ m_menuBar->Show(false); gtk_box_pack_start(GTK_BOX(mdi_frame->m_mainWidget), m_menuBar->m_widget, false, false, 0); gtk_box_reorder_child(GTK_BOX(mdi_frame->m_mainWidget), m_menuBar->m_widget, 0); gulong handler_id = g_signal_handler_find( m_menuBar->m_widget, GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), g_signal_lookup("size_request", GTK_TYPE_WIDGET), 0, NULL, NULL, m_menuBar); if (handler_id != 0) g_signal_handler_disconnect(m_menuBar->m_widget, handler_id); gtk_widget_set_size_request(m_menuBar->m_widget, -1, -1); } }
void wxFrame::SetToolBar(wxToolBar *toolbar) { m_frameToolBar = toolbar; if (toolbar) { if (toolbar->IsVertical()) { // Vertical toolbar and m_wxwindow go into an hbox, inside the // vbox (m_mainWidget). hbox is created on demand. GtkWidget* hbox = gtk_widget_get_parent(m_wxwindow); if (!GTK_IS_HBOX(hbox)) { hbox = gtk_hbox_new(false, 0); gtk_widget_show(hbox); gtk_container_add(GTK_CONTAINER(m_mainWidget), hbox); gtk_widget_reparent(m_wxwindow, hbox); } gtk_widget_reparent(toolbar->m_widget, hbox); gtk_box_set_child_packing(GTK_BOX(hbox), toolbar->m_widget, false, false, 0, GTK_PACK_START); int pos = 0; // left if (toolbar->HasFlag(wxTB_RIGHT)) pos = 1; // right gtk_box_reorder_child(GTK_BOX(hbox), toolbar->m_widget, pos); } else { // Horizontal toolbar goes into vbox (m_mainWidget) gtk_widget_reparent(toolbar->m_widget, m_mainWidget); gtk_box_set_child_packing(GTK_BOX(m_mainWidget), toolbar->m_widget, false, false, 0, GTK_PACK_START); int pos = 0; // top if (m_frameMenuBar) pos = 1; // below menubar if (toolbar->HasFlag(wxTB_BOTTOM)) pos += 2; // below client area (m_wxwindow) gtk_box_reorder_child( GTK_BOX(m_mainWidget), toolbar->m_widget, pos); } // disconnect wxWindowGTK "size_request" handler, // it interferes with sizing of detached GtkHandleBox gulong handler_id = g_signal_handler_find( toolbar->m_widget, GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), g_signal_lookup("size_request", GTK_TYPE_WIDGET), 0, NULL, NULL, toolbar); if (handler_id != 0) g_signal_handler_disconnect(toolbar->m_widget, handler_id); // reset size request to allow native sizing to work gtk_widget_set_size_request(toolbar->m_widget, -1, -1); } // make sure next size_allocate causes a wxSizeEvent m_oldClientWidth = 0; }
wxMenu::~wxMenu() { // Destroying a menu generates a "hide" signal even if it's not shown // currently, so disconnect it to avoid dummy wxEVT_MENU_CLOSE events // generation. g_signal_handlers_disconnect_matched(m_menu, GSignalMatchType(G_SIGNAL_MATCH_DATA), 0, 0, NULL, NULL, this); if (m_owner) { gtk_widget_destroy(m_owner); g_object_unref(m_owner); } else gtk_widget_destroy(m_menu); g_object_unref(m_menu); g_object_unref(m_accel); }
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) { if ( !wxMenuBase::DoRemove(item) ) return NULL; GtkWidget * const mitem = item->GetMenuItem(); g_signal_handlers_disconnect_matched(mitem, GSignalMatchType(G_SIGNAL_MATCH_DATA), 0, 0, NULL, NULL, item); #ifdef __WXGTK3__ gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), NULL); #else gtk_menu_item_remove_submenu(GTK_MENU_ITEM(mitem)); #endif gtk_widget_destroy(mitem); item->SetMenuItem(NULL); return item; }
void wxFrame::AttachMenuBar( wxMenuBar *menuBar ) { wxFrameBase::AttachMenuBar(menuBar); if (m_frameMenuBar) { #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 hildon_window_set_menu(HILDON_WINDOW(m_widget), GTK_MENU(m_frameMenuBar->m_menubar)); #else // !wxUSE_LIBHILDON && !wxUSE_LIBHILDON2 m_frameMenuBar->SetParent(this); // menubar goes into top of vbox (m_mainWidget) gtk_box_pack_start( GTK_BOX(m_mainWidget), menuBar->m_widget, false, false, 0); gtk_box_reorder_child(GTK_BOX(m_mainWidget), menuBar->m_widget, 0); // disconnect wxWindowGTK "size_request" handler, // it interferes with sizing of detached GtkHandleBox gulong handler_id = g_signal_handler_find( menuBar->m_widget, GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), g_signal_lookup("size_request", GTK_TYPE_WIDGET), 0, NULL, NULL, menuBar); if (handler_id != 0) g_signal_handler_disconnect(menuBar->m_widget, handler_id); // reset size request to allow native sizing to work gtk_widget_set_size_request(menuBar->m_widget, -1, -1); gtk_widget_show( m_frameMenuBar->m_widget ); #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2/!wxUSE_LIBHILDON && !wxUSE_LIBHILDON2 } // make sure next size_allocate causes a wxSizeEvent m_oldClientWidth = 0; }
bool wxTopLevelWindowGTK::Show( bool show ) { wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") ); #ifdef GDK_WINDOWING_X11 bool deferShow = show && !m_isShown && m_deferShow; if (deferShow) { deferShow = m_deferShowAllowed && gs_requestFrameExtentsStatus != 2 && !gtk_widget_get_realized(m_widget) && g_signal_handler_find(m_widget, GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA), g_signal_lookup("property_notify_event", GTK_TYPE_WIDGET), 0, NULL, NULL, this); if (deferShow) { GdkScreen* screen = gtk_widget_get_screen(m_widget); GdkAtom atom = gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false); deferShow = gdk_x11_screen_supports_net_wm_hint(screen, atom) != 0; // If _NET_REQUEST_FRAME_EXTENTS not supported, don't allow changes // to m_decorSize, it breaks saving/restoring window size with // GetSize()/SetSize() because it makes window bigger between each // restore and save. m_updateDecorSize = deferShow; } m_deferShow = deferShow; } if (deferShow) { // Initial show. If WM supports _NET_REQUEST_FRAME_EXTENTS, defer // calling gtk_widget_show() until _NET_FRAME_EXTENTS property // notification is received, so correct frame extents are known. // This allows resizing m_widget to keep the overall size in sync with // what wxWidgets expects it to be without an obvious change in the // window size immediately after it becomes visible. // Realize m_widget, so m_widget->window can be used. Realizing normally // causes the widget tree to be size_allocated, which generates size // events in the wrong order. However, the size_allocates will not be // done if the allocation is not the default (1,1). GtkAllocation alloc; gtk_widget_get_allocation(m_widget, &alloc); const int alloc_width = alloc.width; if (alloc_width == 1) { alloc.width = 2; gtk_widget_set_allocation(m_widget, &alloc); } gtk_widget_realize(m_widget); if (alloc_width == 1) { alloc.width = 1; gtk_widget_set_allocation(m_widget, &alloc); } // send _NET_REQUEST_FRAME_EXTENTS XClientMessageEvent xevent; memset(&xevent, 0, sizeof(xevent)); xevent.type = ClientMessage; GdkWindow* window = gtk_widget_get_window(m_widget); xevent.window = GDK_WINDOW_XID(window); xevent.message_type = gdk_x11_atom_to_xatom_for_display( gdk_window_get_display(window), gdk_atom_intern("_NET_REQUEST_FRAME_EXTENTS", false)); xevent.format = 32; Display* display = GDK_DISPLAY_XDISPLAY(gdk_window_get_display(window)); XSendEvent(display, DefaultRootWindow(display), false, SubstructureNotifyMask | SubstructureRedirectMask, (XEvent*)&xevent); if (gs_requestFrameExtentsStatus == 0) { // if WM does not respond to request within 1 second, // we assume support for _NET_REQUEST_FRAME_EXTENTS is not working m_netFrameExtentsTimerId = g_timeout_add(1000, request_frame_extents_timeout, this); } // defer calling gtk_widget_show() m_isShown = true; return true; } #endif // GDK_WINDOWING_X11 if (show && !gtk_widget_get_realized(m_widget)) { // size_allocate signals occur in reverse order (bottom to top). // Things work better if the initial wxSizeEvents are sent (from the // top down), before the initial size_allocate signals occur. wxSizeEvent event(GetSize(), GetId()); event.SetEventObject(this); HandleWindowEvent(event); } bool change = base_type::Show(show); if (change && !show) { // make sure window has a non-default position, so when it is shown // again, it won't be repositioned by WM as if it were a new window // Note that this must be done _after_ the window is hidden. gtk_window_move((GtkWindow*)m_widget, m_x, m_y); } return change; }