X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fb4b0165b22fef2c47e97e90ef5257ca8eadc804..d67fc8b73514909eb198223333e11be4d900f431:/src/gtk/window.cpp diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a3975752f1..e44324e210 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -183,14 +183,12 @@ Cursors, too, have been a constant source of pleasure. The main difficulty is that a GdkWindow inherits a cursor if the programmer sets a new cursor - for the parent. To prevent this from doing too much harm, I use idle time - to set the cursor over and over again, starting from the toplevel windows - and ending with the youngest generation (speaking of parent and child windows). + for the parent. To prevent this from doing too much harm, SetCursor calls + GTKUpdateCursor, which will recursively re-set the cursors of all child windows. Also don't forget that cursors (like much else) are connected to GdkWindows, not GtkWidgets and that the "window" field of a GtkWidget might very well point to the GdkWindow of the parent widget (-> "window-less widget") and that the two obviously have very different meanings. - */ //----------------------------------------------------------------------------- @@ -281,11 +279,11 @@ wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget), extern "C" { static gboolean -gtk_window_expose_callback( GtkWidget* widget, +gtk_window_expose_callback( GtkWidget*, GdkEventExpose *gdk_event, wxWindow *win ) { - if (gdk_event->window == widget->window) + if (gdk_event->window == win->GTKGetDrawingWindow()) { win->GetUpdateRegion() = wxRegion( gdk_event->region ); win->GtkSendPaintEvents(); @@ -304,7 +302,10 @@ extern "C" { static gboolean expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win) { - if (gdk_event->window != widget->window) + if (gdk_event->window != gtk_widget_get_parent_window(win->m_wxwindow)) + return false; + + if (!win->IsShown()) return false; const GtkAllocation& alloc = win->m_wxwindow->allocation; @@ -1831,9 +1832,9 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win) if (win->m_imData) { gtk_im_context_set_client_window( win->m_imData->context, - widget->window); + win->m_wxwindow ? win->GTKGetDrawingWindow() : widget->window); } - + // We cannot set colours and fonts before the widget // been realized, so we do this directly after realization // or otherwise in idle time @@ -1847,6 +1848,8 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win) wxWindowCreateEvent event( win ); event.SetEventObject( win ); win->GTKProcessEvent( event ); + + win->GTKUpdateCursor(true, false); } //----------------------------------------------------------------------------- @@ -1925,30 +1928,6 @@ void gtk_window_style_set_callback( GtkWidget *WXUNUSED(widget), } // extern "C" -// Helper to suspend colour change event event processing while we change a widget's style -class wxSuspendStyleEvents -{ -public: - wxSuspendStyleEvents(wxWindow* win) - { - m_win = NULL; - if (win->m_wxwindow && win->IsTopLevel()) - { - m_win = win; - g_signal_handlers_block_by_func( - m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win); - } - } - ~wxSuspendStyleEvents() - { - if (m_win) - g_signal_handlers_unblock_by_func( - m_win->m_wxwindow, (void*)gtk_window_style_set_callback, m_win); - } - - wxWindow* m_win; -}; - // ---------------------------------------------------------------------------- // this wxWindowBase function is implemented here (in platform-specific file) // because it is static and so couldn't be made virtual @@ -1964,7 +1943,7 @@ wxWindow *wxWindowBase::DoFindFocus() void wxWindowGTK::AddChildGTK(wxWindowGTK* child) { wxASSERT_MSG(m_wxwindow, "Cannot add a child to a window without a client area"); - + // the window might have been scrolled already, we // have to adapt the position wxPizza* pizza = WX_PIZZA(m_wxwindow); @@ -1973,8 +1952,7 @@ void wxWindowGTK::AddChildGTK(wxWindowGTK* child) gtk_widget_set_size_request( child->m_widget, child->m_width, child->m_height); - gtk_fixed_put( - GTK_FIXED(m_wxwindow), child->m_widget, child->m_x, child->m_y); + pizza->put(child->m_widget, child->m_x, child->m_y); } //----------------------------------------------------------------------------- @@ -2112,7 +2090,7 @@ bool wxWindowGTK::Create( wxWindow *parent, #endif - m_wxwindow = wxPizza::New(m_windowStyle,this); + m_wxwindow = wxPizza::New(m_windowStyle); #ifndef __WXUNIVERSAL__ if (HasFlag(wxPizza::BORDER_STYLES)) { @@ -2235,6 +2213,12 @@ wxWindowGTK::~wxWindowGTK() // delete before the widgets to avoid a crash on solaris delete m_imData; + // avoid problem with GTK+ 2.18 where a frozen window causes the whole + // TLW to be frozen, and if the window is then destroyed, nothing ever + // gets painted again + if (IsFrozen()) + DoThaw(); + if (m_widget) { // Note that gtk_widget_destroy() does not destroy the widget, it just @@ -2341,40 +2325,25 @@ void wxWindowGTK::PostCreation() G_CALLBACK(size_allocate), this); } - if (m_wxwindow) - { #if GTK_CHECK_VERSION(2, 8, 0) - if (!gtk_check_version(2,8,0)) + if ( gtk_check_version(2,8,0) == NULL ) + { + // Make sure we can notify the app when mouse capture is lost + if ( m_wxwindow ) { - // Make sure we can notify the app when mouse capture is lost g_signal_connect (m_wxwindow, "grab_broken_event", G_CALLBACK (gtk_window_grab_broken), this); } -#endif - } - if ( connect_widget != m_wxwindow ) - { -#if GTK_CHECK_VERSION(2, 8, 0) - if (!gtk_check_version(2,8,0)) + if ( connect_widget != m_wxwindow ) { - // Make sure we can notify app code when mouse capture is lost g_signal_connect (connect_widget, "grab_broken_event", G_CALLBACK (gtk_window_grab_broken), this); } -#endif } +#endif // GTK+ >= 2.8 -#ifdef GTK_IS_FILE_CHOOSER_BUTTON - if (!gtk_check_version(2,6,0) && GTK_IS_FILE_CHOOSER_BUTTON(m_widget)) - { - // If we connect to the "size_request" signal of a GtkFileChooserButton - // then that control won't be sized properly when placed inside sizers - // (this can be tested removing this elseif and running XRC or WIDGETS samples) - // FIXME: what should be done here ? - } else -#endif - if ( !IsTopLevel() ) // top level windows use their own callback + if ( GTKShouldConnectSizeRequest() ) { // This is needed if we want to add our windows into native // GTK controls, such as the toolbar. With this callback, the @@ -2397,6 +2366,11 @@ void wxWindowGTK::PostCreation() gtk_widget_show( m_widget ); } +gulong wxWindowGTK::GTKConnectWidget(const char *signal, void (*callback)()) +{ + return g_signal_connect(m_widget, signal, callback, this); +} + void wxWindowGTK::ConnectWidget( GtkWidget *widget ) { g_signal_connect (widget, "key_press_event", @@ -2443,9 +2417,9 @@ bool wxWindowGTK::Destroy() void wxWindowGTK::DoMoveWindow(int x, int y, int width, int height) { gtk_widget_set_size_request(m_widget, width, height); - + // inform the parent to perform the move - wxASSERT_MSG(m_parent && m_parent->m_wxwindow, + wxASSERT_MSG(m_parent && m_parent->m_wxwindow, "the parent window has no client area?"); WX_PIZZA(m_parent->m_wxwindow)->move(m_widget, x, y); } @@ -2542,7 +2516,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags event.SetEventObject( this ); HandleWindowEvent( event ); } - } else + } else if (sizeFlags & wxSIZE_FORCE_EVENT) { wxSizeEvent event( wxSize(m_width,m_height), GetId() ); @@ -2594,38 +2568,6 @@ void wxWindowGTK::OnInternalIdle() m_needsStyleChange = false; } - wxCursor cursor = m_cursor; - if (g_globalCursor.Ok()) cursor = g_globalCursor; - - if (cursor.Ok()) - { - /* I now set the cursor anew in every OnInternalIdle call - as setting the cursor in a parent window also effects the - windows above so that checking for the current cursor is - not possible. */ - - if (m_wxwindow && (m_wxwindow != m_widget)) - { - GdkWindow *window = m_wxwindow->window; - if (window) - gdk_window_set_cursor( window, cursor.GetCursor() ); - - if (!g_globalCursor.Ok()) - cursor = *wxSTANDARD_CURSOR; - - window = m_widget->window; - if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget))) - gdk_window_set_cursor( window, cursor.GetCursor() ); - - } - else if ( m_widget ) - { - GdkWindow *window = m_widget->window; - if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) ) - gdk_window_set_cursor( window, cursor.GetCursor() ); - } - } - if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen()) UpdateWindowUI(wxUPDATE_UI_FROMIDLE); } @@ -3458,33 +3400,40 @@ bool wxWindowGTK::SetCursor( const wxCursor &cursor ) return true; } -void wxWindowGTK::GTKUpdateCursor() +void wxWindowGTK::GTKUpdateCursor(bool update_self /*=true*/, bool recurse /*=true*/) { - wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor()); - if ( cursor.Ok() ) + if (update_self) { - wxArrayGdkWindows windowsThis; - GdkWindow * const winThis = GTKGetWindow(windowsThis); - if ( winThis ) - { - gdk_window_set_cursor(winThis, cursor.GetCursor()); - } - else + wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor()); + if ( cursor.Ok() ) { - const size_t count = windowsThis.size(); - for ( size_t n = 0; n < count; n++ ) + wxArrayGdkWindows windowsThis; + GdkWindow* window = GTKGetWindow(windowsThis); + if (window) + gdk_window_set_cursor( window, cursor.GetCursor() ); + else { - GdkWindow *win = windowsThis[n]; - if ( !win ) + const size_t count = windowsThis.size(); + for ( size_t n = 0; n < count; n++ ) { - wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?")); - continue; + GdkWindow *win = windowsThis[n]; + // It can be zero if the window has not been realized yet. + if ( win ) + { + gdk_window_set_cursor(win, cursor.GetCursor()); + } } - - gdk_window_set_cursor(win, cursor.GetCursor()); } } } + + if (recurse) + { + for (wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it) + { + (*it)->GTKUpdateCursor( true ); + } + } } void wxWindowGTK::WarpPointer( int x, int y ) @@ -3572,6 +3521,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), if (!GTK_WIDGET_MAPPED (w)) return; + GdkWindow* window = GTKGetDrawingWindow(); if (rect) { int x = rect->x; @@ -3582,24 +3532,27 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground), r.y = rect->y; r.width = rect->width; r.height = rect->height; - gdk_window_invalidate_rect( m_wxwindow->window, &r, TRUE ); + gdk_window_invalidate_rect(window, &r, true); } else - gdk_window_invalidate_rect( m_wxwindow->window, NULL, TRUE ); + gdk_window_invalidate_rect(window, NULL, true); } } void wxWindowGTK::Update() { - if (m_widget && m_widget->window) + if (m_widget && GTK_WIDGET_MAPPED(m_widget)) { GdkDisplay* display = gtk_widget_get_display(m_widget); // Flush everything out to the server, and wait for it to finish. // This ensures nothing will overwrite the drawing we are about to do. gdk_display_sync(display); - gdk_window_process_updates(m_widget->window, TRUE); - + GdkWindow* window = GTKGetDrawingWindow(); + if (window == NULL) + window = m_widget->window; + gdk_window_process_updates(window, true); + // Flush again, but no need to wait for it to finish gdk_display_flush(display); } @@ -3703,7 +3656,7 @@ void wxWindowGTK::GtkSendPaintEvents() rect.height = upd.GetHeight(); gtk_paint_flat_box( parent->m_widget->style, - m_wxwindow->window, + GTKGetDrawingWindow(), (GtkStateType)GTK_WIDGET_STATE(m_wxwindow), GTK_SHADOW_NONE, &rect, @@ -3917,12 +3870,30 @@ void wxWindowGTK::GTKApplyWidgetStyle(bool forceStyle) void wxWindowGTK::DoApplyWidgetStyle(GtkRcStyle *style) { - wxSuspendStyleEvents s(static_cast(this)); + if ( m_wxwindow ) + { + // block the signal temporarily to avoid sending + // wxSysColourChangedEvents when we change the colours ourselves + bool unblock = false; + if ( IsTopLevel() ) + { + unblock = true; + g_signal_handlers_block_by_func( + m_wxwindow, (void *)gtk_window_style_set_callback, this); + } - if (m_wxwindow) gtk_widget_modify_style(m_wxwindow, style); + + if ( unblock ) + { + g_signal_handlers_unblock_by_func( + m_wxwindow, (void *)gtk_window_style_set_callback, this); + } + } else + { gtk_widget_modify_style(m_widget, style); + } } bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) @@ -3934,7 +3905,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) GdkWindow *window; if ( m_wxwindow ) { - window = m_wxwindow->window; + window = GTKGetDrawingWindow(); } else { @@ -3977,23 +3948,6 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style) #if wxUSE_MENUS_NATIVE -static 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" { static void wxPopupMenuPositionCallback( GtkMenu *menu, @@ -4020,10 +3974,6 @@ 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") ); - - SetInvokingWindow( menu, this ); - menu->UpdateUI(); wxPoint pos; @@ -4100,7 +4050,7 @@ bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const { - return m_wxwindow ? m_wxwindow->window : m_widget->window; + return m_wxwindow ? GTKGetDrawingWindow() : m_widget->window; } bool wxWindowGTK::SetFont( const wxFont &font ) @@ -4123,7 +4073,7 @@ void wxWindowGTK::DoCaptureMouse() GdkWindow *window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = GTKGetDrawingWindow(); else window = GetConnectWidget()->window; @@ -4156,7 +4106,7 @@ void wxWindowGTK::DoReleaseMouse() GdkWindow *window = NULL; if (m_wxwindow) - window = m_wxwindow->window; + window = GTKGetDrawingWindow(); else window = GetConnectWidget()->window; @@ -4364,7 +4314,7 @@ void wxWindowGTK::GTKScrolledWindowSetBorder(GtkWidget* w, int wxstyle) if(wxstyle & wxBORDER_RAISED) gtkstyle = GTK_SHADOW_OUT; - else if (wxstyle & wxBORDER_SUNKEN) + else if ((wxstyle & wxBORDER_SUNKEN) || (wxstyle & wxBORDER_THEME)) gtkstyle = GTK_SHADOW_IN; #if 0 // Now obsolete @@ -4441,7 +4391,7 @@ extern "C" // this is called if we attempted to freeze unrealized widget when it finally // is realized (and so can be frozen): -static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data)) +static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win) { wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) ); wxASSERT( GTK_WIDGET_REALIZED(w) ); @@ -4450,10 +4400,13 @@ static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data)) ( w, (void*)wx_frozen_widget_realize, - NULL + win ); - gdk_window_freeze_updates(w->window); + GdkWindow* window = w->window; + if (w == win->m_wxwindow) + window = win->GTKGetDrawingWindow(); + gdk_window_freeze_updates(window); } } // extern "C" @@ -4472,12 +4425,15 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget *w) w, "realize", G_CALLBACK(wx_frozen_widget_realize), - NULL + this ); return; } - gdk_window_freeze_updates(w->window); + GdkWindow* window = w->window; + if (w == m_wxwindow) + window = GTKGetDrawingWindow(); + gdk_window_freeze_updates(window); } void wxWindowGTK::GTKThawWidget(GtkWidget *w) @@ -4492,12 +4448,15 @@ void wxWindowGTK::GTKThawWidget(GtkWidget *w) ( w, (void*)wx_frozen_widget_realize, - NULL + this ); return; } - gdk_window_thaw_updates(w->window); + GdkWindow* window = w->window; + if (w == m_wxwindow) + window = GTKGetDrawingWindow(); + gdk_window_thaw_updates(window); } void wxWindowGTK::DoFreeze()