src/gui/kernel/qdesktopwidget_win.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdesktopwidget.h"
       
    43 #include "qt_windows.h"
       
    44 #include "qapplication_p.h"
       
    45 #include "qlibrary.h"
       
    46 #include <qvector.h>
       
    47 #include <limits.h>
       
    48 #ifdef Q_WS_WINCE
       
    49 #include <sipapi.h>
       
    50 #endif
       
    51 #include "qwidget_p.h"
       
    52 #include "qdebug.h"
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 class QDesktopWidgetPrivate : public QWidgetPrivate
       
    57 {
       
    58 public:
       
    59     QDesktopWidgetPrivate();
       
    60     ~QDesktopWidgetPrivate();
       
    61 
       
    62     static void init(QDesktopWidget *that);
       
    63     static void cleanup();
       
    64     static int screenCount;
       
    65     static int primaryScreen;
       
    66 
       
    67     static QVector<QRect> *rects;
       
    68     static QVector<QRect> *workrects;
       
    69 
       
    70     struct MONITORINFO
       
    71     {
       
    72         DWORD   cbSize;
       
    73         RECT    rcMonitor;
       
    74         RECT    rcWork;
       
    75         DWORD   dwFlags;
       
    76     };
       
    77 
       
    78     typedef BOOL (WINAPI *InfoFunc)(HMONITOR, MONITORINFO*);
       
    79     typedef BOOL (CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
       
    80     typedef BOOL (WINAPI *EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM);
       
    81 
       
    82     static EnumFunc enumDisplayMonitors;
       
    83     static InfoFunc getMonitorInfo;
       
    84     static int refcount;
       
    85 };
       
    86 
       
    87 int QDesktopWidgetPrivate::screenCount = 1;
       
    88 int QDesktopWidgetPrivate::primaryScreen = 0;
       
    89 QDesktopWidgetPrivate::EnumFunc QDesktopWidgetPrivate::enumDisplayMonitors = 0;
       
    90 QDesktopWidgetPrivate::InfoFunc QDesktopWidgetPrivate::getMonitorInfo = 0;
       
    91 QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
       
    92 QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
       
    93 static int screen_number = 0;
       
    94 int QDesktopWidgetPrivate::refcount = 0;
       
    95 #ifdef Q_WS_WINCE_WM
       
    96 // Use SIP information, if available
       
    97 // SipGetInfo is not supported by SSDK (no definition!). 
       
    98 static inline void qt_get_sip_info(QRect &rect)
       
    99 {
       
   100     SIPINFO sip;
       
   101     memset(&sip, 0, sizeof(SIPINFO));
       
   102     sip.cbSize = sizeof(SIPINFO);
       
   103     if (SipGetInfo(&sip))
       
   104         rect = QRect(QPoint(sip.rcVisibleDesktop.left, sip.rcVisibleDesktop.top),
       
   105         QPoint(sip.rcVisibleDesktop.right - 1, sip.rcVisibleDesktop.bottom - 1));
       
   106 }
       
   107 #endif
       
   108 
       
   109 
       
   110 BOOL CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
       
   111 {
       
   112     QDesktopWidgetPrivate::screenCount++;
       
   113     QDesktopWidgetPrivate::rects->resize(QDesktopWidgetPrivate::screenCount);
       
   114     QDesktopWidgetPrivate::workrects->resize(QDesktopWidgetPrivate::screenCount);
       
   115     // Get the MONITORINFO block
       
   116     QDesktopWidgetPrivate::MONITORINFO info;
       
   117     memset(&info, 0, sizeof(QDesktopWidgetPrivate::MONITORINFO));
       
   118     info.cbSize = sizeof(QDesktopWidgetPrivate::MONITORINFO);
       
   119     BOOL res = QDesktopWidgetPrivate::getMonitorInfo(hMonitor, &info);
       
   120     if (!res) {
       
   121         (*QDesktopWidgetPrivate::rects)[screen_number] = QRect();
       
   122         (*QDesktopWidgetPrivate::workrects)[screen_number] = QRect();
       
   123         return true;
       
   124     }
       
   125 
       
   126     // Fill list of rects
       
   127     RECT r = info.rcMonitor;
       
   128     QRect qr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
       
   129     (*QDesktopWidgetPrivate::rects)[screen_number] = qr;
       
   130 
       
   131     r = info.rcWork;
       
   132     qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
       
   133     (*QDesktopWidgetPrivate::workrects)[screen_number] = qr;
       
   134 
       
   135     if (info.dwFlags & 0x00000001) //MONITORINFOF_PRIMARY
       
   136         QDesktopWidgetPrivate::primaryScreen = screen_number;
       
   137 
       
   138     ++screen_number;
       
   139     // Stop the enumeration if we have them all
       
   140     return true;
       
   141 }
       
   142 
       
   143 QDesktopWidgetPrivate::QDesktopWidgetPrivate()
       
   144 {
       
   145     ++refcount;
       
   146 }
       
   147 
       
   148 void QDesktopWidgetPrivate::init(QDesktopWidget *that)
       
   149 {
       
   150     if (rects)
       
   151         return;
       
   152 
       
   153     rects = new QVector<QRect>();
       
   154     workrects = new QVector<QRect>();
       
   155     screenCount = 0;
       
   156 
       
   157 #ifndef Q_OS_WINCE
       
   158     QLibrary user32Lib(QLatin1String("user32"));
       
   159     if (user32Lib.load()) {
       
   160         enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
       
   161         getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
       
   162     }
       
   163 
       
   164     if (!enumDisplayMonitors || !getMonitorInfo) {
       
   165         screenCount = GetSystemMetrics(80);  // SM_CMONITORS
       
   166         rects->resize(screenCount);
       
   167         for (int i = 0; i < screenCount; ++i)
       
   168             rects->replace(i, that->rect());
       
   169         return;
       
   170     }
       
   171     // Calls enumCallback
       
   172     enumDisplayMonitors(0, 0, enumCallback, 0);
       
   173     enumDisplayMonitors = 0;
       
   174     getMonitorInfo = 0;
       
   175 #else
       
   176     QLibrary coreLib(QLatin1String("coredll"));
       
   177     if (coreLib.load()) {
       
   178         // CE >= 4.0 case
       
   179         enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors");
       
   180         getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo");
       
   181     }
       
   182 
       
   183     if ((!enumDisplayMonitors || !getMonitorInfo)) {
       
   184         screenCount = GetSystemMetrics(SM_CMONITORS);
       
   185         return;
       
   186     }
       
   187 
       
   188     if (!coreLib.isLoaded() || !enumDisplayMonitors || !getMonitorInfo) {
       
   189         rects->resize(screenCount);
       
   190         for (int i = 0; i < screenCount; ++i)
       
   191             (*rects)[i] = that->rect();
       
   192 
       
   193         RECT r;
       
   194         SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
       
   195         QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
       
   196 
       
   197 #if defined(Q_WS_WINCE_WM)
       
   198         qt_get_sip_info(qr);
       
   199 #endif
       
   200 
       
   201         workrects->resize(screenCount);
       
   202         for (int j = 0; j < screenCount; ++j)
       
   203             (*workrects)[j] = qr;
       
   204         return;
       
   205     }
       
   206 
       
   207     // Calls enumCallback
       
   208     enumDisplayMonitors(0, 0, enumCallback, 0);
       
   209     enumDisplayMonitors = 0;
       
   210     getMonitorInfo = 0;
       
   211 #endif // Q_WS_WINCE
       
   212 }
       
   213 
       
   214 QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
       
   215 {
       
   216     if (!--refcount)
       
   217         cleanup();
       
   218 }
       
   219 
       
   220 void QDesktopWidgetPrivate::cleanup()
       
   221 {
       
   222     screen_number = 0;
       
   223     screenCount = 1;
       
   224     primaryScreen = 0;
       
   225     enumDisplayMonitors = 0;
       
   226     getMonitorInfo = 0;
       
   227     delete rects;
       
   228     rects = 0;
       
   229     delete workrects;
       
   230     workrects = 0;
       
   231 }
       
   232 
       
   233 /*
       
   234     \omit
       
   235     Function is commented out in header
       
   236     \fn void *QDesktopWidget::handle(int screen) const
       
   237 
       
   238     Returns the window system handle of the display device with the
       
   239     index \a screen, for low-level access.  Using this function is not
       
   240     portable.
       
   241 
       
   242     The return type varies with platform; see qwindowdefs.h for details.
       
   243 
       
   244     \sa x11Display(), QPaintDevice::handle()
       
   245     \endomit
       
   246 */
       
   247 
       
   248 QDesktopWidget::QDesktopWidget()
       
   249     : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
       
   250 {
       
   251     setObjectName(QLatin1String("desktop"));
       
   252     QDesktopWidgetPrivate::init(this);
       
   253 }
       
   254 
       
   255 QDesktopWidget::~QDesktopWidget()
       
   256 {
       
   257 }
       
   258 
       
   259 bool QDesktopWidget::isVirtualDesktop() const
       
   260 {
       
   261     return true;
       
   262 }
       
   263 
       
   264 int QDesktopWidget::primaryScreen() const
       
   265 {
       
   266     return d_func()->primaryScreen;
       
   267 }
       
   268 
       
   269 int QDesktopWidget::numScreens() const
       
   270 {
       
   271     return d_func()->screenCount;
       
   272 }
       
   273 
       
   274 QWidget *QDesktopWidget::screen(int /* screen */)
       
   275 {
       
   276     // It seems that a Qt::WType_Desktop cannot be moved?
       
   277     return this;
       
   278 }
       
   279 
       
   280 //
       
   281 // MSVC 7.10 warns that d (the result of the expanded Q_D macro) as a local variable that is not referenced.
       
   282 // Therefore, we ignore that warning with the following pragmas
       
   283 // I've also tried to eliminate the macro, but to no use...
       
   284 // We pop it further down
       
   285 #ifdef Q_CC_MSVC
       
   286 # pragma warning(push)
       
   287 # pragma warning(disable : 4189)
       
   288 #endif
       
   289 const QRect QDesktopWidget::availableGeometry(int screen) const
       
   290 {
       
   291     Q_D(const QDesktopWidget);
       
   292 #ifdef Q_WS_WINCE_WM
       
   293     for(int i=0; i < d->workrects->size(); ++i)
       
   294         qt_get_sip_info((*d->workrects)[i]);
       
   295 #endif
       
   296     if (screen < 0 || screen >= d->screenCount)
       
   297         screen = d->primaryScreen;
       
   298 
       
   299     return d->workrects->at(screen);
       
   300 }
       
   301 
       
   302 const QRect QDesktopWidget::screenGeometry(int screen) const
       
   303 {
       
   304     const QDesktopWidgetPrivate *d = d_func();
       
   305     if (screen < 0 || screen >= d->screenCount)
       
   306         screen = d->primaryScreen;
       
   307 
       
   308     return d->rects->at(screen);
       
   309 }
       
   310 
       
   311 int QDesktopWidget::screenNumber(const QWidget *widget) const
       
   312 {
       
   313     Q_D(const QDesktopWidget);
       
   314     if (!widget)
       
   315         return d->primaryScreen;
       
   316 
       
   317     QRect frame = widget->frameGeometry();
       
   318     if (!widget->isWindow())
       
   319         frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
       
   320 
       
   321     int maxSize = -1;
       
   322     int maxScreen = -1;
       
   323 
       
   324     for (int i = 0; i < d->screenCount; ++i) {
       
   325         QRect sect = d->rects->at(i).intersected(frame);
       
   326         int size = sect.width() * sect.height();
       
   327         if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
       
   328             maxSize = size;
       
   329             maxScreen = i;
       
   330         }
       
   331     }
       
   332 
       
   333     return maxScreen;
       
   334 }
       
   335 
       
   336 int QDesktopWidget::screenNumber(const QPoint &point) const
       
   337 {
       
   338     Q_D(const QDesktopWidget);
       
   339 
       
   340     int closestScreen = -1;
       
   341     int shortestDistance = INT_MAX;
       
   342 
       
   343     for (int i = 0; i < d->screenCount; ++i) {
       
   344         int thisDistance = d->pointToRect(point, d->rects->at(i));
       
   345         if (thisDistance < shortestDistance) {
       
   346             shortestDistance = thisDistance;
       
   347             closestScreen = i;
       
   348         }
       
   349     }
       
   350 
       
   351     return closestScreen;
       
   352 }
       
   353 
       
   354 void QDesktopWidget::resizeEvent(QResizeEvent *)
       
   355 {
       
   356     Q_D(QDesktopWidget);
       
   357     const QVector<QRect> oldrects(*d->rects);
       
   358     const QVector<QRect> oldworkrects(*d->workrects);
       
   359     int oldscreencount = d->screenCount;
       
   360 
       
   361     QDesktopWidgetPrivate::cleanup();
       
   362     QDesktopWidgetPrivate::init(this);
       
   363 #ifdef Q_WS_WINCE_WM
       
   364     for(int i=0; i < d->workrects->size(); ++i)
       
   365         qt_get_sip_info((*d->workrects)[i]);
       
   366 #endif
       
   367 
       
   368     for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
       
   369         const QRect oldrect = oldrects[i];
       
   370         const QRect newrect = d->rects->at(i);
       
   371         if (oldrect != newrect)
       
   372             emit resized(i);
       
   373     }
       
   374 
       
   375     for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
       
   376         const QRect oldrect = oldworkrects[j];
       
   377         const QRect newrect = d->workrects->at(j);
       
   378         if (oldrect != newrect)
       
   379             emit workAreaResized(j);
       
   380     }
       
   381 
       
   382     if (oldscreencount != d->screenCount) {
       
   383         emit screenCountChanged(d->screenCount);
       
   384     }
       
   385 }
       
   386 
       
   387 #ifdef Q_CC_MSVC
       
   388 # pragma warning(pop)
       
   389 #endif
       
   390 
       
   391 QT_END_NAMESPACE