From b0d053c1eac3100e02468c73798111028819ad0a Mon Sep 17 00:00:00 2001 From: Paul Cornett Date: Thu, 20 Dec 2012 18:46:58 +0000 Subject: [PATCH] Use client size determined by size-allocate when possible Our client size calculation can be wrong for reasons beyond our control, notably on Ubuntu 12.04 with overlay scrollbars where the GtkScrolledWindow "scrollbar-spacing" is wrong. By using the true size from size-allocate when it becomes available, we can recover from an earlier incorrect client size calculation. See #14871 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73231 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/window.h | 6 +++++- src/gtk/frame.cpp | 18 +++++++++++++----- src/gtk/mdi.cpp | 2 +- src/gtk/minifram.cpp | 4 ++++ src/gtk/toplevel.cpp | 22 ++++++++++++++-------- src/gtk/window.cpp | 50 +++++++++++++++++++++++++++---------------------- 6 files changed, 65 insertions(+), 37 deletions(-) diff --git a/include/wx/gtk/window.h b/include/wx/gtk/window.h index 4c9078e..4e41857 100644 --- a/include/wx/gtk/window.h +++ b/include/wx/gtk/window.h @@ -255,7 +255,11 @@ public: // position and size of the window int m_x, m_y; int m_width, m_height; - int m_oldClientWidth,m_oldClientHeight; + int m_clientWidth, m_clientHeight; + // Whether the client size variables above are known to be correct + // (because they have been validated by a size-allocate) and should + // be used to report client size + bool m_useCachedClientSize; // see the docs in src/gtk/window.cpp GtkWidget *m_widget; // mostly the widget seen by the rest of GTK diff --git a/src/gtk/frame.cpp b/src/gtk/frame.cpp index 940c5c2..421643d 100644 --- a/src/gtk/frame.cpp +++ b/src/gtk/frame.cpp @@ -74,6 +74,9 @@ void wxFrame::DoGetClientSize( int *width, int *height ) const wxFrameBase::DoGetClientSize(width, height); + if (m_useCachedClientSize) + return; + if (height) { #if wxUSE_MENUS_NATIVE @@ -287,7 +290,8 @@ void wxFrame::DetachMenuBar() wxFrameBase::DetachMenuBar(); // make sure next size_allocate causes a wxSizeEvent - m_oldClientWidth = 0; + m_useCachedClientSize = false; + m_clientWidth = 0; } void wxFrame::AttachMenuBar( wxMenuBar *menuBar ) @@ -314,7 +318,8 @@ void wxFrame::AttachMenuBar( wxMenuBar *menuBar ) #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2/!wxUSE_LIBHILDON && !wxUSE_LIBHILDON2 } // make sure next size_allocate causes a wxSizeEvent - m_oldClientWidth = 0; + m_useCachedClientSize = false; + m_clientWidth = 0; } #endif // wxUSE_MENUS_NATIVE @@ -365,7 +370,8 @@ void wxFrame::SetToolBar(wxToolBar *toolbar) gtk_widget_set_size_request(toolbar->m_widget, -1, -1); } // make sure next size_allocate causes a wxSizeEvent - m_oldClientWidth = 0; + m_useCachedClientSize = false; + m_clientWidth = 0; } #endif // wxUSE_TOOLBAR @@ -382,7 +388,8 @@ void wxFrame::SetStatusBar(wxStatusBar *statbar) gtk_box_set_child_packing(GTK_BOX(m_mainWidget), statbar->m_widget, false, false, 0, GTK_PACK_END); // make sure next size_allocate on statusbar causes a size event - statbar->m_oldClientWidth = 0; + statbar->m_useCachedClientSize = false; + statbar->m_clientWidth = 0; int h = -1; if (statbar->m_wxwindow) { @@ -392,6 +399,7 @@ void wxFrame::SetStatusBar(wxStatusBar *statbar) gtk_widget_set_size_request(statbar->m_widget, -1, h); } // make sure next size_allocate causes a wxSizeEvent - m_oldClientWidth = 0; + m_useCachedClientSize = false; + m_clientWidth = 0; } #endif // wxUSE_STATUSBAR diff --git a/src/gtk/mdi.cpp b/src/gtk/mdi.cpp index c9c2cb3..5480673 100644 --- a/src/gtk/mdi.cpp +++ b/src/gtk/mdi.cpp @@ -191,7 +191,7 @@ void wxMDIParentFrame::DoGetClientSize(int* width, int* height) const { wxFrame::DoGetClientSize(width, height); - if (height) + if (!m_useCachedClientSize && height) { wxMDIChildFrame* active_child_frame = GetActiveChild(); if (active_child_frame) diff --git a/src/gtk/minifram.cpp b/src/gtk/minifram.cpp index 3f435ee..073587e 100644 --- a/src/gtk/minifram.cpp +++ b/src/gtk/minifram.cpp @@ -435,6 +435,10 @@ bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title void wxMiniFrame::DoGetClientSize(int* width, int* height) const { wxFrame::DoGetClientSize(width, height); + + if (m_useCachedClientSize) + return; + if (width) { *width -= 2 * m_miniEdge; diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index b118883..d6ad28c 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -216,11 +216,12 @@ extern "C" { static void size_allocate(GtkWidget*, GtkAllocation* alloc, wxTopLevelWindowGTK* win) { - if (win->m_oldClientWidth != alloc->width || - win->m_oldClientHeight != alloc->height) + win->m_useCachedClientSize = true; + if (win->m_clientWidth != alloc->width || + win->m_clientHeight != alloc->height) { - win->m_oldClientWidth = alloc->width; - win->m_oldClientHeight = alloc->height; + win->m_clientWidth = alloc->width; + win->m_clientHeight = alloc->height; GtkAllocation a; gtk_widget_get_allocation(win->m_widget, &a); @@ -343,7 +344,8 @@ gtk_frame_map_callback( GtkWidget*, // tlw that was "rolled up" with some WMs. // Queue a resize rather than sending size event directly to allow // children to be made visible first. - win->m_oldClientWidth = 0; + win->m_useCachedClientSize = false; + win->m_clientWidth = 0; gtk_widget_queue_resize(win->m_wxwindow); } // it is possible for m_isShown to be false here, see bug #9909 @@ -1067,12 +1069,13 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si if (m_width != oldSize.x || m_height != oldSize.y) { m_deferShowAllowed = true; + m_useCachedClientSize = false; int w, h; GTKDoGetSize(&w, &h); gtk_window_resize(GTK_WINDOW(m_widget), w, h); - GetClientSize(&m_oldClientWidth, &m_oldClientHeight); + DoGetClientSize(&m_clientWidth, &m_clientHeight); wxSizeEvent event(GetSize(), GetId()); event.SetEventObject(this); HandleWindowEvent(event); @@ -1102,6 +1105,8 @@ void wxTopLevelWindowGTK::DoGetClientSize( int *width, int *height ) const if ( height ) *height = 0; } + else if (m_useCachedClientSize) + base_type::DoGetClientSize(width, height); else { GTKDoGetSize(width, height); @@ -1159,6 +1164,7 @@ void wxTopLevelWindowGTK::GTKUpdateDecorSize(const wxSize& decorSize) GetCachedDecorSize() = decorSize; if (m_updateDecorSize && m_decorSize != decorSize) { + m_useCachedClientSize = false; const wxSize diff = decorSize - m_decorSize; m_decorSize = decorSize; bool resized = false; @@ -1186,7 +1192,7 @@ void wxTopLevelWindowGTK::GTKUpdateDecorSize(const wxSize& decorSize) m_height += diff.y; if (m_width < 1) m_width = 1; if (m_height < 1) m_height = 1; - m_oldClientWidth = 0; + m_clientWidth = 0; gtk_widget_queue_resize(m_wxwindow); } } @@ -1194,7 +1200,7 @@ void wxTopLevelWindowGTK::GTKUpdateDecorSize(const wxSize& decorSize) { // gtk_widget_show() was deferred, do it now m_deferShow = false; - GetClientSize(&m_oldClientWidth, &m_oldClientHeight); + DoGetClientSize(&m_clientWidth, &m_clientHeight); wxSizeEvent sizeEvent(GetSize(), GetId()); sizeEvent.SetEventObject(this); HandleWindowEvent(sizeEvent); diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 66e9818..64d1133 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -1910,10 +1910,11 @@ size_allocate(GtkWidget*, GtkAllocation* alloc, wxWindow* win) if (w < 0) w = 0; if (h < 0) h = 0; } - if (win->m_oldClientWidth != w || win->m_oldClientHeight != h) + win->m_useCachedClientSize = true; + if (win->m_clientWidth != w || win->m_clientHeight != h) { - win->m_oldClientWidth = w; - win->m_oldClientHeight = h; + win->m_clientWidth = w; + win->m_clientHeight = h; // this callback can be connected to m_wxwindow, // so always get size from m_widget->allocation GtkAllocation a; @@ -1960,18 +1961,9 @@ static void style_updated(GtkWidget*, wxWindow* win) static void style_updated(GtkWidget*, GtkStyle*, wxWindow* win) #endif { - if (win->IsTopLevel()) - { - wxSysColourChangedEvent event; - event.SetEventObject(win); - win->GTKProcessEvent(event); - } - else - { - // Border width could change, which will change client size. - // Make sure size event occurs for this - win->m_oldClientWidth = 0; - } + wxSysColourChangedEvent event; + event.SetEventObject(win); + win->GTKProcessEvent(event); } //----------------------------------------------------------------------------- @@ -2035,8 +2027,7 @@ void wxWindowGTK::GTKHandleRealized() GTKUpdateCursor(true, false); - if (m_wxwindow && - (IsTopLevel() || HasFlag(wxBORDER_RAISED | wxBORDER_SUNKEN | wxBORDER_THEME))) + if (m_wxwindow && IsTopLevel()) { // attaching to style changed signal after realization avoids initial // changes we don't care about @@ -2064,8 +2055,11 @@ void wxWindowGTK::GTKHandleUnrealize() if (m_imData) gtk_im_context_set_client_window(m_imData->context, NULL); - g_signal_handlers_disconnect_by_func( - m_wxwindow, (void*)style_updated, this); + if (IsTopLevel()) + { + g_signal_handlers_disconnect_by_func( + m_wxwindow, (void*)style_updated, this); + } } } @@ -2214,8 +2208,9 @@ void wxWindowGTK::Init() m_scrollPos[dir] = 0; } - m_oldClientWidth = - m_oldClientHeight = 0; + m_clientWidth = + m_clientHeight = 0; + m_useCachedClientSize = false; m_clipPaintRegion = false; @@ -2731,6 +2726,10 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags height = m_height; const bool sizeChange = m_width != width || m_height != height; + + if (sizeChange) + m_useCachedClientSize = false; + if (sizeChange || m_x != x || m_y != y) { m_x = x; @@ -2760,7 +2759,7 @@ void wxWindowGTK::DoSetSize( int x, int y, int width, int height, int sizeFlags { // update these variables to keep size_allocate handler // from sending another size event for this change - GetClientSize( &m_oldClientWidth, &m_oldClientHeight ); + DoGetClientSize(&m_clientWidth, &m_clientHeight); wxSizeEvent event( wxSize(m_width,m_height), GetId() ); event.SetEventObject( this ); @@ -2825,6 +2824,13 @@ void wxWindowGTK::DoGetClientSize( int *width, int *height ) const { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); + if (m_useCachedClientSize) + { + if (width) *width = m_clientWidth; + if (height) *height = m_clientHeight; + return; + } + int w = m_width; int h = m_height; -- 2.7.4