source: trunk/src/gui/kernel/qdesktopwidget_win.cpp@ 345

Last change on this file since 345 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 12.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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_OS_WINCE
49#include <sipapi.h>
50#endif
51#include "qwidget_p.h"
52#include "qdebug.h"
53
54QT_BEGIN_NAMESPACE
55
56class QDesktopWidgetPrivate : public QWidgetPrivate
57{
58public:
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
87int QDesktopWidgetPrivate::screenCount = 1;
88int QDesktopWidgetPrivate::primaryScreen = 0;
89QDesktopWidgetPrivate::EnumFunc QDesktopWidgetPrivate::enumDisplayMonitors = 0;
90QDesktopWidgetPrivate::InfoFunc QDesktopWidgetPrivate::getMonitorInfo = 0;
91QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
92QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
93static int screen_number = 0;
94int QDesktopWidgetPrivate::refcount = 0;
95#ifdef Q_OS_WINCE_WM
96// Use SIP information, if available
97// SipGetInfo is not supported by SSDK (no definition!).
98static 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
110BOOL 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
143QDesktopWidgetPrivate::QDesktopWidgetPrivate()
144{
145 ++refcount;
146}
147
148void QDesktopWidgetPrivate::init(QDesktopWidget *that)
149{
150 if (rects)
151 return;
152
153 rects = new QVector<QRect>();
154 workrects = new QVector<QRect>();
155
156#ifndef Q_OS_WINCE
157 if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
158 screenCount = 0;
159 // Trying to get the function pointers to Win98/2000 only functions
160 QLibrary user32Lib(QLatin1String("user32"));
161 if (!user32Lib.load())
162 return;
163 enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
164 QT_WA({
165 getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
166 } , {
167 getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoA");
168 });
169
170 if (!enumDisplayMonitors || !getMonitorInfo) {
171 screenCount = GetSystemMetrics(80); // SM_CMONITORS
172 rects->resize(screenCount);
173 for (int i = 0; i < screenCount; ++i)
174 rects->replace(i, that->rect());
175 return;
176 }
177 // Calls enumCallback
178 enumDisplayMonitors(0, 0, enumCallback, 0);
179 enumDisplayMonitors = 0;
180 getMonitorInfo = 0;
181 } else {
182 rects->resize(1);
183 rects->replace(0, that->rect());
184 workrects->resize(1);
185 workrects->replace(0, that->rect());
186 }
187#else
188 screenCount = 0;
189
190 QLibrary coreLib(QLatin1String("coredll"));
191 if (coreLib.load()) {
192 // CE >= 4.0 case
193 enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors");
194 getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo");
195 }
196
197 if ((!enumDisplayMonitors || !getMonitorInfo)) {
198 screenCount = GetSystemMetrics(SM_CMONITORS);
199 return;
200 }
201
202 if (!coreLib.isLoaded() || !enumDisplayMonitors || !getMonitorInfo) {
203 rects->resize(screenCount);
204 for (int i = 0; i < screenCount; ++i)
205 (*rects)[i] = that->rect();
206
207 RECT r;
208 SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
209 QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
210
211#if defined(Q_OS_WINCE_WM)
212 qt_get_sip_info(qr);
213#endif
214
215 workrects->resize(screenCount);
216 for (int j = 0; j < screenCount; ++j)
217 (*workrects)[j] = qr;
218 return;
219 }
220
221 // Calls enumCallback
222 enumDisplayMonitors(0, 0, enumCallback, 0);
223 enumDisplayMonitors = 0;
224 getMonitorInfo = 0;
225#endif // Q_OS_WINCE
226}
227
228QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
229{
230 if (!--refcount)
231 cleanup();
232}
233
234void QDesktopWidgetPrivate::cleanup()
235{
236 screen_number = 0;
237 screenCount = 1;
238 primaryScreen = 0;
239 enumDisplayMonitors = 0;
240 getMonitorInfo = 0;
241 delete rects;
242 rects = 0;
243 delete workrects;
244 workrects = 0;
245}
246
247/*
248 \omit
249 Function is commented out in header
250 \fn void *QDesktopWidget::handle(int screen) const
251
252 Returns the window system handle of the display device with the
253 index \a screen, for low-level access. Using this function is not
254 portable.
255
256 The return type varies with platform; see qwindowdefs.h for details.
257
258 \sa x11Display(), QPaintDevice::handle()
259 \endomit
260*/
261
262QDesktopWidget::QDesktopWidget()
263 : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
264{
265 setObjectName(QLatin1String("desktop"));
266 QDesktopWidgetPrivate::init(this);
267}
268
269QDesktopWidget::~QDesktopWidget()
270{
271}
272
273bool QDesktopWidget::isVirtualDesktop() const
274{
275 return true;
276}
277
278int QDesktopWidget::primaryScreen() const
279{
280 return d_func()->primaryScreen;
281}
282
283int QDesktopWidget::numScreens() const
284{
285 return d_func()->screenCount;
286}
287
288QWidget *QDesktopWidget::screen(int /* screen */)
289{
290 // It seems that a Qt::WType_Desktop cannot be moved?
291 return this;
292}
293
294//
295// MSVC 7.10 warns that d (the result of the expanded Q_D macro) as a local variable that is not referenced.
296// Therefore, we ignore that warning with the following pragmas
297// I've also tried to eliminate the macro, but to no use...
298// We pop it further down
299#ifdef Q_CC_MSVC
300# pragma warning(push)
301# pragma warning(disable : 4189)
302#endif
303const QRect QDesktopWidget::availableGeometry(int screen) const
304{
305 Q_D(const QDesktopWidget);
306#ifdef Q_OS_WINCE_WM
307 for(int i=0; i < d->workrects->size(); ++i)
308 qt_get_sip_info((*d->workrects)[i]);
309#endif
310 if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
311 if (screen < 0 || screen >= d->screenCount)
312 screen = d->primaryScreen;
313
314 return d->workrects->at(screen);
315 } else {
316 return d->workrects->at(d->primaryScreen);
317 }
318}
319
320const QRect QDesktopWidget::screenGeometry(int screen) const
321{
322 const QDesktopWidgetPrivate *d = d_func();
323 if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
324 if (screen < 0 || screen >= d->screenCount)
325 screen = d->primaryScreen;
326
327 return d->rects->at(screen);
328 } else {
329 return d->rects->at(d->primaryScreen);
330 }
331}
332
333int QDesktopWidget::screenNumber(const QWidget *widget) const
334{
335 Q_D(const QDesktopWidget);
336 if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
337 if (!widget)
338 return d->primaryScreen;
339 QRect frame = widget->frameGeometry();
340 if (!widget->isWindow())
341 frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
342
343 int maxSize = -1;
344 int maxScreen = -1;
345
346 for (int i = 0; i < d->screenCount; ++i) {
347 QRect sect = d->rects->at(i).intersected(frame);
348 int size = sect.width() * sect.height();
349 if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
350 maxSize = size;
351 maxScreen = i;
352 }
353 }
354 return maxScreen;
355 } else {
356 return d->primaryScreen;
357 }
358}
359
360int QDesktopWidget::screenNumber(const QPoint &point) const
361{
362 Q_D(const QDesktopWidget);
363 int closestScreen = -1;
364 if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) {
365 int shortestDistance = INT_MAX;
366 for (int i = 0; i < d->screenCount; ++i) {
367 int thisDistance = d->pointToRect(point, d->rects->at(i));
368 if (thisDistance < shortestDistance) {
369 shortestDistance = thisDistance;
370 closestScreen = i;
371 }
372 }
373 }
374 return closestScreen;
375}
376
377void QDesktopWidget::resizeEvent(QResizeEvent *)
378{
379 Q_D(QDesktopWidget);
380 QVector<QRect> oldrects;
381 oldrects = *d->rects;
382 QVector<QRect> oldworkrects;
383 oldworkrects = *d->workrects;
384 int oldscreencount = d->screenCount;
385
386 QDesktopWidgetPrivate::cleanup();
387 QDesktopWidgetPrivate::init(this);
388#ifdef Q_OS_WINCE_WM
389 for(int i=0; i < d->workrects->size(); ++i)
390 qt_get_sip_info((*d->workrects)[i]);
391#endif
392
393 for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
394 QRect oldrect = oldrects[i];
395 QRect newrect = d->rects->at(i);
396 if (oldrect != newrect)
397 emit resized(i);
398 }
399
400 for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
401 QRect oldrect = oldworkrects[j];
402 QRect newrect = d->workrects->at(j);
403 if (oldrect != newrect)
404 emit workAreaResized(j);
405 }
406}
407
408#ifdef Q_CC_MSVC
409# pragma warning(pop)
410#endif
411
412QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.