Move workaround for initial TLW size to wxGTK itself

Add wxWindow::WXSetInitialFittingClientSize() instead of handling wxGTK
TLWs specially in the common wxSizer code and override it in wxGTK to
remember that we need to reset the client size once the window is shown.

This commit shouldn't result in any changes in the observed behaviour.
This commit is contained in:
Vadim Zeitlin
2021-04-12 17:52:23 +02:00
parent 329f60d7f3
commit fd7386ed83
5 changed files with 88 additions and 48 deletions

View File

@@ -138,6 +138,16 @@ public:
void GTKDoAfterShow();
#ifdef __WXGTK3__
void GTKUpdateClientSizeIfNecessary();
virtual void WXSetInitialFittingClientSize(int flags) wxOVERRIDE;
private:
// Flags to call WXSetInitialFittingClientSize() with if != 0.
int m_pendingFittingClientSizeFlags;
#endif // __WXGTK3__
protected:
// give hints to the Window Manager for how the size
// of the TLW can be changed by dragging

View File

@@ -139,6 +139,13 @@ enum
wxSEND_EVENT_POST = 1
};
// Flags for WXSetInitialFittingClientSize().
enum
{
wxSIZE_SET_CURRENT = 0x0001, // Set the current size.
wxSIZE_SET_MIN = 0x0002 // Set the size as the minimum allowed size.
};
// ----------------------------------------------------------------------------
// (pseudo)template list classes
// ----------------------------------------------------------------------------
@@ -1541,6 +1548,13 @@ public:
// window is part of a composite control.
bool WXSendContextMenuEvent(const wxPoint& posInScreenCoords);
// This internal function needs to be called to set the fitting client size
// (i.e. the minimum size determined by the window sizer) when the size
// that we really need to use is not known until the window is actually
// shown, as is the case for TLWs with recent GTK versions, as it will
// update the size again when it does become known, if necessary.
virtual void WXSetInitialFittingClientSize(int flags);
// get the handle of the window for the underlying window system: this
// is only used for wxWin itself or for user code which wants to call
// platform-specific APIs

View File

@@ -999,31 +999,12 @@ wxSize wxSizer::ComputeFittingWindowSize(wxWindow *window)
return window->ClientToWindowSize(ComputeFittingClientSize(window));
}
#ifdef __WXGTK3__
static void FitOnShow(wxShowEvent& event)
{
wxWindow* win = static_cast<wxWindow*>(event.GetEventObject());
wxSizer* sizer = win->GetSizer();
if (sizer)
sizer->Fit(win);
win->Unbind(wxEVT_SHOW, FitOnShow);
}
#endif
wxSize wxSizer::Fit( wxWindow *window )
{
wxCHECK_MSG( window, wxDefaultSize, "window can't be NULL" );
#ifdef __WXGTK3__
// GTK3 updates cached style information before showing a TLW,
// which may affect best size calculations, so add a handler to
// redo the calculations at that time
if (!window->IsShown() && window->IsTopLevel())
window->Bind(wxEVT_SHOW, FitOnShow);
#endif
// set client size
window->SetClientSize(ComputeFittingClientSize(window));
window->WXSetInitialFittingClientSize(wxSIZE_SET_CURRENT);
// return entire size
return window->GetSize();
@@ -1059,38 +1040,11 @@ void wxSizer::Layout()
RepositionChildren(minSize);
}
#ifdef __WXGTK3__
static void SetSizeHintsOnShow(wxShowEvent& event)
{
wxWindow* win = static_cast<wxWindow*>(event.GetEventObject());
wxSizer* sizer = win->GetSizer();
if (sizer)
sizer->SetSizeHints(win);
win->Unbind(wxEVT_SHOW, SetSizeHintsOnShow);
}
#endif
void wxSizer::SetSizeHints( wxWindow *window )
{
// Preserve the window's max size hints, but set the
// lower bound according to the sizer calculations.
// This is equivalent to calling Fit(), except that we need to set
// the size hints _in between_ the two steps performed by Fit
// (1. ComputeFittingClientSize, 2. SetClientSize). That's because
// otherwise SetClientSize() could have no effect if there already are
// size hints in effect that forbid requested client size.
#ifdef __WXGTK3__
// see comment in Fit()
if (!window->IsShown() && window->IsTopLevel())
window->Bind(wxEVT_SHOW, SetSizeHintsOnShow);
#endif
const wxSize clientSize = ComputeFittingClientSize(window);
window->SetMinClientSize(clientSize);
window->SetClientSize(clientSize);
window->WXSetInitialFittingClientSize(wxSIZE_SET_CURRENT | wxSIZE_SET_MIN);
}
#if WXWIN_COMPATIBILITY_2_8

View File

@@ -1002,6 +1002,25 @@ wxSize wxWindowBase::WindowToClientSize(const wxSize& size) const
size.y == -1 ? -1 : size.y - diff.y);
}
void wxWindowBase::WXSetInitialFittingClientSize(int flags)
{
wxSizer* const sizer = GetSizer();
if ( !sizer )
return;
const wxSize
size = sizer->ComputeFittingClientSize(static_cast<wxWindow *>(this));
// It is important to set the min client size before changing the size
// itself as the existing size hints could prevent SetClientSize() from
// working otherwise.
if ( flags & wxSIZE_SET_MIN )
SetMinClientSize(size);
if ( flags & wxSIZE_SET_CURRENT )
SetClientSize(size);
}
void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
{
if ( m_windowVariant != variant )

View File

@@ -612,6 +612,10 @@ void wxTopLevelWindowGTK::Init()
m_incWidth = m_incHeight = 0;
m_urgency_hint = -2;
#ifdef __WXGTK3__
m_pendingFittingClientSizeFlags = 0;
#endif // __WXGTK3__
}
bool wxTopLevelWindowGTK::Create( wxWindow *parent,
@@ -1161,6 +1165,12 @@ bool wxTopLevelWindowGTK::Show( bool show )
bool change = base_type::Show(show);
#ifdef __WXGTK3__
if (change && show)
{
// We may need to redo it after showing the window.
GTKUpdateClientSizeIfNecessary();
}
if (m_needSizeEvent)
{
m_needSizeEvent = false;
@@ -1525,8 +1535,41 @@ void wxTopLevelWindowGTK::GTKDoAfterShow()
wxShowEvent showEvent(GetId(), true);
showEvent.SetEventObject(this);
HandleWindowEvent(showEvent);
#ifdef __WXGTK3__
// Set the client size again if necessary, we should be able to do it
// correctly by now as the style cache should be up to date.
GTKUpdateClientSizeIfNecessary();
#endif // __WXGTK3__
}
#ifdef __WXGTK3__
void wxTopLevelWindowGTK::GTKUpdateClientSizeIfNecessary()
{
if ( m_pendingFittingClientSizeFlags )
{
WXSetInitialFittingClientSize(m_pendingFittingClientSizeFlags);
m_pendingFittingClientSizeFlags = 0;
}
}
void wxTopLevelWindowGTK::WXSetInitialFittingClientSize(int flags)
{
// In any case, update the size immediately.
wxTopLevelWindowBase::WXSetInitialFittingClientSize(flags);
// But if we're not shown yet, the fitting size may be wrong because GTK
// style cache hasn't been updated yet and we need to do it again when the
// window becomes visible as we can be sure that by then we'll be able to
// compute the best size correctly.
if ( !IsShown() )
m_pendingFittingClientSizeFlags = flags;
}
#endif // __WXGTK3__
// ----------------------------------------------------------------------------
// frame title/icon
// ----------------------------------------------------------------------------