fixed centering of top level windows on secondary displays (replaces patch 1267173)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37436 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2006-02-10 00:02:06 +00:00
parent 1bfb73b877
commit 1f464296de
5 changed files with 53 additions and 145 deletions

View File

@ -82,6 +82,7 @@ All (GUI):
- Added SetSheetStyle to wxPropertySheetDialog and allowed it to
behave like a Mac OS X settings dialog.
- Added <disabled> XRC tag for wxToolBar elements and <bg> for wxToolBar itself
- Fixed centering of top level windows on secondary displays
wxMSW:

View File

@ -177,6 +177,11 @@ public:
virtual void SetRightMenu(int id = wxID_ANY, const wxString& label = wxEmptyString, wxMenu *subMenu = NULL) = 0;
#endif // __SMARTPHONE__
// centre the window on screen: this is just a shortcut
void CentreOnScreen(int dir = wxBOTH) { DoCentre(dir | wxCENTRE_ON_SCREEN); }
void CenterOnScreen(int dir = wxBOTH) { CentreOnScreen(dir); }
// implementation only from now on
// -------------------------------
@ -216,6 +221,10 @@ protected:
virtual void DoClientToScreen(int *x, int *y) const;
virtual void DoScreenToClient(int *x, int *y) const;
// add support for wxCENTRE_ON_SCREEN
virtual void DoCentre(int dir);
// test whether this window makes part of the frame
// (menubar, toolbar and statusbar are excluded from automatic layout)
virtual bool IsOneOfBars(const wxWindow *WXUNUSED(win)) const

View File

@ -332,15 +332,11 @@ public:
// the generic centre function - centers the window on parent by`
// default or on screen if it doesn't have parent or
// wxCENTER_ON_SCREEN flag is given
void Centre( int direction = wxBOTH );
void Center( int direction = wxBOTH ) { Centre(direction); }
// centre on screen (only works for top level windows)
void CentreOnScreen(int dir = wxBOTH) { Centre(dir | wxCENTER_ON_SCREEN); }
void CenterOnScreen(int dir = wxBOTH) { CentreOnScreen(dir); }
void Centre(int dir = wxBOTH) { DoCentre(dir); }
void Center(int dir = wxBOTH) { DoCentre(dir); }
// centre with respect to the the parent window
void CentreOnParent(int dir = wxBOTH) { Centre(dir | wxCENTER_FRAME); }
void CentreOnParent(int dir = wxBOTH) { DoCentre(dir); }
void CenterOnParent(int dir = wxBOTH) { CentreOnParent(dir); }
// set window size to wrap around its children
@ -1295,6 +1291,11 @@ protected:
// arrange themselves inside the given rectangle
virtual void DoMoveWindow(int x, int y, int width, int height) = 0;
// centre the window in the specified direction on parent, note that
// wxCENTRE_ON_SCREEN shouldn't be specified here, it only makes sense for
// TLWs
virtual void DoCentre(int dir);
#if wxUSE_TOOLTIPS
virtual void DoSetToolTip( wxToolTip *tip );
#endif // wxUSE_TOOLTIPS

View File

@ -29,6 +29,8 @@
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/display.h"
// ----------------------------------------------------------------------------
// event table
// ----------------------------------------------------------------------------
@ -151,6 +153,35 @@ wxSize wxTopLevelWindowBase::GetDefaultSize()
return size;
}
void wxTopLevelWindowBase::DoCentre(int dir)
{
wxRect rectCentre;
if ( !(dir & wxCENTRE_ON_SCREEN) && GetParent() )
{
// centre on parent window
rectCentre = GetParent()->GetRect();
}
else
{
// 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
{
wxDisplaySize(&rectCentre.width, &rectCentre.height);
}
}
// window may be at -1 if it's centered on a secondary display, for example
SetSize(GetRect().CentreIn(rectCentre, dir), wxSIZE_ALLOW_MINUS_ONE);
}
// ----------------------------------------------------------------------------
// wxTopLevelWindow size management: we exclude the areas taken by
// menu/status/toolbars from the client area, so the client area is what's

View File

@ -74,10 +74,6 @@
#include "wx/caret.h"
#endif // wxUSE_CARET
#if wxUSE_DISPLAY
#include "wx/display.h"
#endif
#if wxUSE_SYSTEM_OPTIONS
#include "wx/sysopt.h"
#endif
@ -400,142 +396,12 @@ bool wxWindowBase::DestroyChildren()
// ----------------------------------------------------------------------------
// centre the window with respect to its parent in either (or both) directions
void wxWindowBase::Centre(int direction)
void wxWindowBase::DoCentre(int dir)
{
// the position/size of the parent window or of the entire screen
wxPoint posParent;
int widthParent, heightParent;
wxCHECK_RET( !(dir & wxCENTRE_ON_SCREEN) && GetParent(),
_T("this method only implements centering child windows") );
wxWindow *parent = NULL;
wxTopLevelWindow *winTop = NULL;
if ( !(direction & wxCENTRE_ON_SCREEN) )
{
// find the parent to centre this window on: it should be the
// immediate parent for the controls but the top level parent for the
// top level windows (like dialogs)
parent = GetParent();
if ( IsTopLevel() )
{
while ( parent && !parent->IsTopLevel() )
{
parent = parent->GetParent();
}
}
// there is no wxTopLevelWindow under wxMotif yet
#ifndef __WXMOTIF__
// we shouldn't center the dialog on the iconized window: under
// Windows, for example, this places it completely off the screen
if ( parent )
{
winTop = wxDynamicCast(parent, wxTopLevelWindow);
if ( winTop && winTop->IsIconized() )
{
winTop = NULL;
parent = NULL;
}
}
#endif // __WXMOTIF__
// did we find the parent?
if ( !parent )
{
// no other choice
direction |= wxCENTRE_ON_SCREEN;
}
}
if ( direction & wxCENTRE_ON_SCREEN )
{
//RN: If we are using wxDisplay we get
//the dimensions of the monitor the window is on,
//otherwise we get the dimensions of the primary monitor
//FIXME: wxDisplay::GetFromWindow only implemented on MSW
#if wxUSE_DISPLAY && defined(__WXMSW__)
int nDisplay = wxDisplay::GetFromWindow((wxWindow*)this);
if(nDisplay != wxNOT_FOUND)
{
wxDisplay windowDisplay(nDisplay);
wxRect displayRect = windowDisplay.GetGeometry();
widthParent = displayRect.width;
heightParent = displayRect.height;
}
else
#endif
// centre with respect to the whole screen
wxDisplaySize(&widthParent, &heightParent);
}
else
{
if ( IsTopLevel() )
{
if(winTop)
winTop->GetRectForTopLevelChildren(&posParent.x, &posParent.y, &widthParent, &heightParent);
else
{
// centre on the parent
parent->GetSize(&widthParent, &heightParent);
// adjust to the parents position
posParent = parent->GetPosition();
}
}
else
{
// centre inside the parents client rectangle
parent->GetClientSize(&widthParent, &heightParent);
}
}
int width, height;
GetSize(&width, &height);
int xNew = wxDefaultCoord,
yNew = wxDefaultCoord;
if ( direction & wxHORIZONTAL )
xNew = (widthParent - width)/2;
if ( direction & wxVERTICAL )
yNew = (heightParent - height)/2;
xNew += posParent.x;
yNew += posParent.y;
// FIXME: This needs to get the client display rect of the display
// the window is (via wxDisplay::GetFromWindow).
// Base size of the visible dimensions of the display
// to take into account the taskbar. And the Mac menu bar at top.
wxRect clientrect = wxGetClientDisplayRect();
// NB: in wxMSW, negative position may not necessarily mean "out of screen",
// but it may mean that the window is placed on other than the main
// display. Therefore we only make sure centered window is on the main display
// if the parent is at least partially present here.
if (posParent.x + widthParent >= 0) // if parent is (partially) on the main display
{
if (xNew < clientrect.GetLeft())
xNew = clientrect.GetLeft();
else if (xNew + width > clientrect.GetRight())
xNew = clientrect.GetRight() - width;
}
if (posParent.y + heightParent >= 0) // if parent is (partially) on the main display
{
if (yNew + height > clientrect.GetBottom())
yNew = clientrect.GetBottom() - height;
// Make certain that the title bar is initially visible
// always, even if this would push the bottom of the
// dialog off the visible area of the display
if (yNew < clientrect.GetTop())
yNew = clientrect.GetTop();
}
// move the window to this position (keeping the old size but using
// SetSize() and not Move() to allow xNew and/or yNew to be wxDefaultCoord)
SetSize(xNew, yNew, width, height, wxSIZE_ALLOW_MINUS_ONE);
SetSize(GetRect().CentreIn(GetParent()->GetClientSize(), dir));
}
// fits the window around the children