]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/toplvcmn.cpp
reuse Clear() instead of duplicating its code in Close()
[wxWidgets.git] / src / common / toplvcmn.cpp
index c519fbc7c9005e0c8fdfc28c2a347a2ae1725643..d99000e5e24428c455252cf89662b60bddfeca28 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        common/toplvcmn.cpp
+// Name:        src/common/toplvcmn.cpp
 // Purpose:     common (for all platforms) wxTopLevelWindow functions
 // Author:      Julian Smart, Vadim Zeitlin
 // Created:     01/02/97
@@ -155,31 +155,74 @@ wxSize wxTopLevelWindowBase::GetDefaultSize()
 
 void wxTopLevelWindowBase::DoCentre(int dir)
 {
-    wxRect rectCentre;
+    // we need the display rect anyhow so store it first
+    int nDisplay = wxDisplay::GetFromWindow(this);
+    wxDisplay dpy(nDisplay == wxNOT_FOUND ? 0 : nDisplay);
+    const wxRect rectDisplay(dpy.GetClientArea());
+
+    // what should we centre this window on?
+    wxRect rectParent;
     if ( !(dir & wxCENTRE_ON_SCREEN) && GetParent() )
     {
-        // centre on parent window
-        rectCentre = GetParent()->GetRect();
+        // centre on parent window: notice that we need screen coordinates for
+        // positioning this TLW
+        rectParent = GetParent()->GetScreenRect();
+
+        // if the parent is entirely off screen (happens at least with MDI
+        // parent frame under Mac but could happen elsewhere too if the frame
+        // was hidden/moved away for some reason), don't use it as otherwise
+        // this window wouldn't be visible at all
+        if ( !rectDisplay.Inside(rectParent.GetTopLeft()) &&
+                !rectParent.Inside(rectParent.GetBottomRight()) )
+        {
+            // this is enough to make IsEmpty() test below pass
+            rectParent.width = 0;
+        }
     }
-    else
+
+    if ( rectParent.IsEmpty() )
     {
         // we were explicitely asked to centre this window on the entire screen
         // or if we have no parent anyhow and so can't centre on it
-#if wxUSE_DISPLAY
-        const int nDisplay = wxDisplay::GetFromWindow(this);
-        if ( nDisplay != wxNOT_FOUND )
-        {
-            rectCentre = wxDisplay(nDisplay).GetGeometry();
-        }
-        else
-#endif // wxUSE_DISPLAY
+        rectParent = rectDisplay;
+    }
+
+    // centering maximized window on screen is no-op
+    if((rectParent == rectDisplay) && IsMaximized())
+        return;
+
+    // the new window rect candidate
+    wxRect rect = GetRect().CentreIn(rectParent, dir);
+
+    // we don't want to place the window off screen if Centre() is called as
+    // this is (almost?) never wanted and it would be very difficult to prevent
+    // it from happening from the user code if we didn't check for it here
+    if ( rectDisplay.Inside(rect.GetTopLeft()) )
+    {
+        if ( !rectDisplay.Inside(rect.GetBottomRight()) )
         {
-            wxDisplaySize(&rectCentre.width, &rectCentre.height);
+            // check if we can move the window so that the bottom right corner
+            // is visible without hiding the top left one
+            int dx = rectDisplay.GetRight() - rect.GetRight();
+            int dy = rectDisplay.GetBottom() - rect.GetBottom();
+            rect.Offset(dx, dy);
         }
+        //else: the window top left and bottom right corner are both visible,
+        //      although the window might still be not entirely on screen (with
+        //      2 staggered displays for example) we wouldn't be able to
+        //      improve the layout much in such case, so just leave it as is
+    }
+    else // make top left corner visible
+    {
+        if ( rect.x < rectDisplay.x )
+            rect.x = rectDisplay.x;
+
+        if ( rect.y < rectDisplay.y )
+            rect.y = rectDisplay.y;
     }
 
-    // window may be at -1 if it's centered on a secondary display, for example
-    SetSize(GetRect().CentreIn(rectCentre, dir), wxSIZE_ALLOW_MINUS_ONE);
+    // -1 could be valid coordinate here if there are several displays
+    SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);
 }
 
 // ----------------------------------------------------------------------------
@@ -306,4 +349,3 @@ void wxTopLevelWindowBase::RequestUserAttention(int WXUNUSED(flags))
     // it's probably better than do nothing, isn't it?
     Raise();
 }
-