diff --git a/include/wx/gtk/window.h b/include/wx/gtk/window.h index 66171148b8..4db8b9d73f 100644 --- a/include/wx/gtk/window.h +++ b/include/wx/gtk/window.h @@ -255,6 +255,8 @@ public: // (because they have been validated by a size-allocate) and should // be used to report client size bool m_useCachedClientSize; + // Whether the GtkAllocation and GdkWindow positions are known to be correct + bool m_isGtkPositionValid; // 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/window.cpp b/src/gtk/window.cpp index 4221a1c1d6..f63565a8c5 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -2049,6 +2049,7 @@ size_allocate(GtkWidget*, GtkAllocation* alloc, wxWindow* win) win->m_y = a.y; } win->m_useCachedClientSize = true; + win->m_isGtkPositionValid = true; if (win->m_clientWidth != w || win->m_clientHeight != h) { win->m_clientWidth = w; @@ -2210,6 +2211,8 @@ void wxWindowGTK::GTKHandleRealized() void wxWindowGTK::GTKHandleUnrealize() { + m_isGtkPositionValid = false; + // unrealizing a frozen window seems to have some lingering effect // preventing updates to the affected area if (IsFrozen()) @@ -2365,6 +2368,7 @@ void wxWindowGTK::Init() m_clientWidth = m_clientHeight = 0; m_useCachedClientSize = false; + m_isGtkPositionValid = false; m_clipPaintRegion = false; @@ -2909,11 +2913,14 @@ 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; + const bool positionChange = m_x != x || m_y != y; if (sizeChange) m_useCachedClientSize = false; + if (positionChange) + m_isGtkPositionValid = false; - if (sizeChange || m_x != x || m_y != y) + if (sizeChange || positionChange) { m_x = x; m_y = y; @@ -3136,7 +3143,37 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (gtk_widget_get_window(m_widget) == NULL) return; + if (!m_isGtkPositionValid && !IsTopLevel() && m_parent) + { + m_parent->DoClientToScreen(x, y); + int xx, yy; + DoGetPosition(&xx, &yy); + if (m_wxwindow) + { + GtkBorder border; + WX_PIZZA(m_wxwindow)->get_border(border); + xx += border.left; + yy += border.top; + } + if (y) *y += yy; + if (x) + { + if (GetLayoutDirection() != wxLayout_RightToLeft) + *x += xx; + else + { + int w; + // undo RTL conversion done by parent + m_parent->DoGetClientSize(&w, NULL); + *x = w - *x; + + DoGetClientSize(&w, NULL); + *x += xx; + *x = w - *x; + } + } + return; + } GdkWindow *source = NULL; if (m_wxwindow) @@ -3144,6 +3181,8 @@ void wxWindowGTK::DoClientToScreen( int *x, int *y ) const else source = gtk_widget_get_window(m_widget); + wxCHECK_RET(source, "ClientToScreen failed on unrealized window"); + int org_x = 0; int org_y = 0; gdk_window_get_origin( source, &org_x, &org_y ); @@ -3175,7 +3214,37 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); - if (!gtk_widget_get_realized(m_widget)) return; + if (!m_isGtkPositionValid && !IsTopLevel() && m_parent) + { + m_parent->DoScreenToClient(x, y); + int xx, yy; + DoGetPosition(&xx, &yy); + if (m_wxwindow) + { + GtkBorder border; + WX_PIZZA(m_wxwindow)->get_border(border); + xx += border.left; + yy += border.top; + } + if (y) *y -= yy; + if (x) + { + if (GetLayoutDirection() != wxLayout_RightToLeft) + *x -= xx; + else + { + int w; + // undo RTL conversion done by parent + m_parent->DoGetClientSize(&w, NULL); + *x = w - *x; + + DoGetClientSize(&w, NULL); + *x -= xx; + *x = w - *x; + } + } + return; + } GdkWindow *source = NULL; if (m_wxwindow) @@ -3183,6 +3252,8 @@ void wxWindowGTK::DoScreenToClient( int *x, int *y ) const else source = gtk_widget_get_window(m_widget); + wxCHECK_RET(source, "ScreenToClient failed on unrealized window"); + int org_x = 0; int org_y = 0; gdk_window_get_origin( source, &org_x, &org_y );