Fix position returned for iconized windows in wxGTK

Don't lose window position when the window is iconized, as this prevents
it from being correctly saved by wxPersitentTLW, for example, resulting
in failures in the corresponding unit test.

Unfortunately there doesn't seem to be any simple way to just ignore the
bogus (0, 0) configure events that we get from GTK when the window is
iconized, as explained in the comment, so we're reduced to remembering
the last position and restoring it when we realize that the window got
minimized and not moved, after all. This is obviously not ideal, as
there is still a lapse of time when (0, 0) is returned, but there just
doesn't seem to be anything better to do.
This commit is contained in:
Vadim Zeitlin
2019-07-16 02:22:02 +02:00
parent 8d405b80e4
commit 70f40e2f6a
2 changed files with 61 additions and 0 deletions

View File

@@ -164,6 +164,9 @@ private:
// size hint increments // size hint increments
int m_incWidth, m_incHeight; int m_incWidth, m_incHeight;
// position before it last changed
wxPoint m_lastPos;
// is the frame currently iconized? // is the frame currently iconized?
bool m_isIconized; bool m_isIconized;

View File

@@ -326,6 +326,8 @@ void wxTopLevelWindowGTK::GTKConfigureEvent(int x, int y)
if (m_x != point.x || m_y != point.y) if (m_x != point.x || m_y != point.y)
{ {
m_lastPos = wxPoint(m_x, m_y);
m_x = point.x; m_x = point.x;
m_y = point.y; m_y = point.y;
wxMoveEvent event(point, GetId()); wxMoveEvent event(point, GetId());
@@ -1495,6 +1497,62 @@ void wxTopLevelWindowGTK::SetIconizeState(bool iconize)
{ {
if ( iconize != m_isIconized ) if ( iconize != m_isIconized )
{ {
/*
We get a configure-event _before_ the window is iconized with dummy
(0, 0) coordinates. Unfortunately we can't just ignore this event
when we get it, because we can't know if we're going to be iconized
or not: even remembering that we should be soon in Iconize() itself
doesn't help due to the crazy sequence of events generated by GTK,
e.g. under X11 for the sequence of Iconize() and Show() calls we
get the following events with GTK2:
- window-state changes to GDK_WINDOW_STATE_ICONIFIED | WITHDRAWN
- window-state changes to just GDK_WINDOW_STATE_ICONIFIED
- map event
- window-state changes to normal
- configure event with normal size
- window-state changes to GDK_WINDOW_STATE_ICONIFIED
- configure event with normal size
- configure event with (0, 0) size
- window-state changes to normal (yes, again)
- configure event with (0, 0) size
- window-state changes to GDK_WINDOW_STATE_ICONIFIED
So even though we could ignore the first (0, 0) configure event, we
still wouldn't be able to ignore the second one, happening after
the inexplicable switch to normal state.
For completeness, with GTK3 the sequence of events is simpler, but
still very unhelpful for our purposes:
- window-state changes to GDK_WINDOW_STATE_ICONIFIED
- window-state changes to normal
- map event
- configure event with normal size
- configure event with normal size (yes, because one is not enough)
- configure event with (0, 0) size
- configure event with (0, 0) size (because why not have 2 of them)
- window-state changes to GDK_WINDOW_STATE_ICONIFIED
Here again we have (0, 0) configure events happening _after_ the
window-state switch to normal, that would reset our flag.
In conclusion, we have no choice but to assume that the window got
really moved, but at least we can remember its previous position in
order to restore it here if it turns out that it was just iconized.
*/
if ( iconize )
{
if ( wxPoint(m_x, m_y) == wxPoint(0, 0) )
{
m_x = m_lastPos.x;
m_y = m_lastPos.y;
// This is not really necessary, but seems tidier.
m_lastPos = wxPoint();
}
}
m_isIconized = iconize; m_isIconized = iconize;
(void)SendIconizeEvent(iconize); (void)SendIconizeEvent(iconize);
} }