diff --git a/include/wx/gtk/toplevel.h b/include/wx/gtk/toplevel.h index 602a232aba..9a2c705f1d 100644 --- a/include/wx/gtk/toplevel.h +++ b/include/wx/gtk/toplevel.h @@ -164,6 +164,9 @@ private: // size hint increments int m_incWidth, m_incHeight; + // position before it last changed + wxPoint m_lastPos; + // is the frame currently iconized? bool m_isIconized; diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index c21d0e427c..81d210a865 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -326,6 +326,8 @@ void wxTopLevelWindowGTK::GTKConfigureEvent(int x, int y) if (m_x != point.x || m_y != point.y) { + m_lastPos = wxPoint(m_x, m_y); + m_x = point.x; m_y = point.y; wxMoveEvent event(point, GetId()); @@ -1495,6 +1497,62 @@ void wxTopLevelWindowGTK::SetIconizeState(bool iconize) { 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; (void)SendIconizeEvent(iconize); }