Qt 4.8
qdesktopwidget_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 <private/qsystemlibrary_p.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 
55 
57 {
58 public:
61 
62  static void init(QDesktopWidget *that);
63  static void cleanup();
64  static int screenCount;
65  static int primaryScreen;
66 
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 (QT_WIN_CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM);
80  typedef BOOL (WINAPI *EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM);
81 
84  static int refcount;
85 };
86 
93 static int screen_number = 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 QT_WIN_CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
111 {
113  QDesktopWidgetPrivate::rects->resize(QDesktopWidgetPrivate::screenCount);
114  QDesktopWidgetPrivate::workrects->resize(QDesktopWidgetPrivate::screenCount);
115  // Get the MONITORINFO block
117  memset(&info, 0, 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
137 
138  ++screen_number;
139  // Stop the enumeration if we have them all
140  return true;
141 }
142 
144 {
145  ++refcount;
146 }
147 
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  QSystemLibrary user32Lib(QLatin1String("user32"));
159  enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors");
160  getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW");
161 
163  screenCount = GetSystemMetrics(80); // SM_CMONITORS
164  rects->resize(screenCount);
165  for (int i = 0; i < screenCount; ++i)
166  rects->replace(i, that->rect());
167  return;
168  }
169  // Calls enumCallback
172  getMonitorInfo = 0;
173 #else
174  QSystemLibrary coreLib(QLatin1String("coredll"));
175  // CE >= 4.0 case
176  enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors");
177  getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo");
178 
179  if ((!enumDisplayMonitors || !getMonitorInfo)) {
180  screenCount = GetSystemMetrics(SM_CMONITORS);
181  return;
182  }
183 
184  if (!coreLib.isLoaded() || !enumDisplayMonitors || !getMonitorInfo) {
185  rects->resize(screenCount);
186  for (int i = 0; i < screenCount; ++i)
187  (*rects)[i] = that->rect();
188 
189  RECT r;
190  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
191  QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
192 
193 #if defined(Q_WS_WINCE_WM)
194  qt_get_sip_info(qr);
195 #endif
196 
197  workrects->resize(screenCount);
198  for (int j = 0; j < screenCount; ++j)
199  (*workrects)[j] = qr;
200  return;
201  }
202 
203  // Calls enumCallback
206  getMonitorInfo = 0;
207 #endif // Q_WS_WINCE
208 }
209 
211 {
212  if (!--refcount)
213  cleanup();
214 }
215 
217 {
218  screen_number = 0;
219  screenCount = 1;
220  primaryScreen = 0;
222  getMonitorInfo = 0;
223  delete rects;
224  rects = 0;
225  delete workrects;
226  workrects = 0;
227 }
228 
229 /*
230  \omit
231  Function is commented out in header
232  \fn void *QDesktopWidget::handle(int screen) const
233 
234  Returns the window system handle of the display device with the
235  index \a screen, for low-level access. Using this function is not
236  portable.
237 
238  The return type varies with platform; see qwindowdefs.h for details.
239 
240  \sa x11Display(), QPaintDevice::handle()
241  \endomit
242 */
243 
246 {
247  setObjectName(QLatin1String("desktop"));
249 }
250 
252 {
253 }
254 
256 {
257  return true;
258 }
259 
261 {
262  return d_func()->primaryScreen;
263 }
264 
265 int QDesktopWidget::numScreens() const
266 {
267  return d_func()->screenCount;
268 }
269 
270 QWidget *QDesktopWidget::screen(int /* screen */)
271 {
272  // It seems that a Qt::WType_Desktop cannot be moved?
273  return this;
274 }
275 
276 //
277 // MSVC 7.10 warns that d (the result of the expanded Q_D macro) as a local variable that is not referenced.
278 // Therefore, we ignore that warning with the following pragmas
279 // I've also tried to eliminate the macro, but to no use...
280 // We pop it further down
281 #ifdef Q_CC_MSVC
282 # pragma warning(push)
283 # pragma warning(disable : 4189)
284 #endif
285 const QRect QDesktopWidget::availableGeometry(int screen) const
286 {
287  Q_D(const QDesktopWidget);
288 #ifdef Q_WS_WINCE_WM
289  for(int i=0; i < d->workrects->size(); ++i)
290  qt_get_sip_info((*d->workrects)[i]);
291 #endif
292  if (screen < 0 || screen >= d->screenCount)
293  screen = d->primaryScreen;
294 
295  return d->workrects->at(screen);
296 }
297 
298 const QRect QDesktopWidget::screenGeometry(int screen) const
299 {
300  const QDesktopWidgetPrivate *d = d_func();
301  if (screen < 0 || screen >= d->screenCount)
302  screen = d->primaryScreen;
303 
304  return d->rects->at(screen);
305 }
306 
308 {
309  Q_D(const QDesktopWidget);
310  if (!widget)
311  return d->primaryScreen;
312 
313  QRect frame = widget->frameGeometry();
314  if (!widget->isWindow())
315  frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0)));
316 
317  int maxSize = -1;
318  int maxScreen = -1;
319 
320  for (int i = 0; i < d->screenCount; ++i) {
321  QRect sect = d->rects->at(i).intersected(frame);
322  int size = sect.width() * sect.height();
323  if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
324  maxSize = size;
325  maxScreen = i;
326  }
327  }
328 
329  return maxScreen;
330 }
331 
332 int QDesktopWidget::screenNumber(const QPoint &point) const
333 {
334  Q_D(const QDesktopWidget);
335 
336  int closestScreen = -1;
337  int shortestDistance = INT_MAX;
338 
339  for (int i = 0; i < d->screenCount; ++i) {
340  int thisDistance = d->pointToRect(point, d->rects->at(i));
341  if (thisDistance < shortestDistance) {
342  shortestDistance = thisDistance;
343  closestScreen = i;
344  }
345  }
346 
347  return closestScreen;
348 }
349 
351 {
353  const QVector<QRect> oldrects(*d->rects);
354  const QVector<QRect> oldworkrects(*d->workrects);
355  int oldscreencount = d->screenCount;
356 
359 #ifdef Q_WS_WINCE_WM
360  for(int i=0; i < d->workrects->size(); ++i)
361  qt_get_sip_info((*d->workrects)[i]);
362 #endif
363 
364  for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
365  const QRect oldrect = oldrects[i];
366  const QRect newrect = d->rects->at(i);
367  if (oldrect != newrect)
368  emit resized(i);
369  }
370 
371  for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
372  const QRect oldrect = oldworkrects[j];
373  const QRect newrect = d->workrects->at(j);
374  if (oldrect != newrect)
375  emit workAreaResized(j);
376  }
377 
378  if (oldscreencount != d->screenCount) {
379  emit screenCountChanged(d->screenCount);
380  }
381 }
382 
383 #ifdef Q_CC_MSVC
384 # pragma warning(pop)
385 #endif
386 
double d
Definition: qnumeric_p.h:62
static int screen_number
void resizeEvent(QResizeEvent *e)
This event handler can be reimplemented in a subclass to receive widget resize events which are passe...
static mach_timebase_info_data_t info
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPointer< QWidget > widget
void replace(int i, const T &t)
Replaces the item at index position i with value.
Definition: qvector.h:382
#define SPI_GETWORKAREA
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition: qwidget.h:945
BOOL QT_WIN_CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM)
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
static EnumFunc enumDisplayMonitors
QRect frameGeometry
geometry of the widget relative to its parent including any window frame
Definition: qwidget.h:159
int primaryScreen() const
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
#define Q_D(Class)
Definition: qglobal.h:2482
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
static InfoFunc getMonitorInfo
#define QT_WIN_CALLBACK
Definition: qglobal.h:1178
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
BOOL(WINAPI * InfoFunc)(HMONITOR, MONITORINFO *)
#define emit
Definition: qobjectdefs.h:76
bool isVirtualDesktop() const
static QVector< QRect > * rects
The QResizeEvent class contains event parameters for resize events.
Definition: qevent.h:349
int numScreens() const
static QVector< QRect > * workrects
QRect rect() const
void moveTopLeft(const QPoint &p)
Moves the rectangle, leaving the top-left corner at the given position.
Definition: qrect.h:368
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QWidget * screen(int screen=-1)
void * resolve(const char *symbol)
const QRect screenGeometry(int screen=-1) const
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
BOOL(QT_WIN_CALLBACK * EnumProc)(HMONITOR, HDC, LPRECT, LPARAM)
BOOL(WINAPI * EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM)
int screenNumber(const QWidget *widget=0) const
const QRect availableGeometry(int screen=-1) const
QPoint mapToGlobal(const QPoint &) const
Translates the widget coordinate pos to global screen coordinates.
#define INT_MAX