Merge branch 'gtk-initial-size'
Fix initial size of TLWs in wxGTK when using both sizers and explicit SetSize() calls. See https://github.com/wxWidgets/wxWidgets/pull/2322 See #16088, #19134.
This commit is contained in:
@@ -136,6 +136,20 @@ public:
|
||||
|
||||
void GTKUpdateDecorSize(const DecorSize& decorSize);
|
||||
|
||||
void GTKDoAfterShow();
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
void GTKUpdateClientSizeIfNecessary();
|
||||
|
||||
virtual void SetMinSize(const wxSize& minSize) wxOVERRIDE;
|
||||
|
||||
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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 )
|
||||
|
@@ -445,9 +445,7 @@ gtk_frame_map_callback( GtkWidget*,
|
||||
// it is possible for m_isShown to be false here, see bug #9909
|
||||
if (win->wxWindowBase::Show(true))
|
||||
{
|
||||
wxShowEvent eventShow(win->GetId(), true);
|
||||
eventShow.SetEventObject(win);
|
||||
win->GetEventHandler()->ProcessEvent(eventShow);
|
||||
win->GTKDoAfterShow();
|
||||
}
|
||||
|
||||
// restore focus-on-map setting in case ShowWithoutActivating() was called
|
||||
@@ -614,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,
|
||||
@@ -1163,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;
|
||||
@@ -1272,6 +1280,19 @@ void wxTopLevelWindowGTK::DoSetSize( int x, int y, int width, int height, int si
|
||||
m_deferShowAllowed = true;
|
||||
m_useCachedClientSize = false;
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
// Reset pending client size, it is not relevant any more and shouldn't
|
||||
// be set when the window is shown, as we don't want it to replace the
|
||||
// size explicitly specified here. Note that we do still want to set
|
||||
// the minimum client size, as increasing the total size shouldn't
|
||||
// allow shrinking the frame beyond its minimum fitting size.
|
||||
//
|
||||
// Also note that if we're called from WXSetInitialFittingClientSize()
|
||||
// itself, this will be overwritten again with the pending flags when
|
||||
// we return.
|
||||
m_pendingFittingClientSizeFlags &= ~wxSIZE_SET_CURRENT;
|
||||
#endif // __WXGTK3__
|
||||
|
||||
int w, h;
|
||||
GTKDoGetSize(&w, &h);
|
||||
gtk_window_resize(GTK_WINDOW(m_widget), w, h);
|
||||
@@ -1499,9 +1520,8 @@ void wxTopLevelWindowGTK::GTKUpdateDecorSize(const DecorSize& decorSize)
|
||||
SendSizeEvent();
|
||||
}
|
||||
#endif
|
||||
wxShowEvent showEvent(GetId(), true);
|
||||
showEvent.SetEventObject(this);
|
||||
HandleWindowEvent(showEvent);
|
||||
|
||||
GTKDoAfterShow();
|
||||
}
|
||||
#endif // GDK_WINDOWING_X11
|
||||
}
|
||||
@@ -1523,6 +1543,54 @@ wxTopLevelWindowGTK::DecorSize& wxTopLevelWindowGTK::GetCachedDecorSize()
|
||||
return size[index];
|
||||
}
|
||||
|
||||
void wxTopLevelWindowGTK::GTKDoAfterShow()
|
||||
{
|
||||
#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__
|
||||
|
||||
wxShowEvent showEvent(GetId(), true);
|
||||
showEvent.SetEventObject(this);
|
||||
HandleWindowEvent(showEvent);
|
||||
}
|
||||
|
||||
#ifdef __WXGTK3__
|
||||
|
||||
void wxTopLevelWindowGTK::GTKUpdateClientSizeIfNecessary()
|
||||
{
|
||||
if ( m_pendingFittingClientSizeFlags )
|
||||
{
|
||||
WXSetInitialFittingClientSize(m_pendingFittingClientSizeFlags);
|
||||
|
||||
m_pendingFittingClientSizeFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wxTopLevelWindowGTK::SetMinSize(const wxSize& minSize)
|
||||
{
|
||||
wxTopLevelWindowBase::SetMinSize(minSize);
|
||||
|
||||
// Explicitly set minimum size should override the pending size, if any.
|
||||
m_pendingFittingClientSizeFlags &= ~wxSIZE_SET_MIN;
|
||||
}
|
||||
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user