Qt 4.8
qdesktopwidget_x11.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 "qapplication.h"
43 #include "qdesktopwidget.h"
44 #include "qlibrary.h"
45 #include "qt_x11_p.h"
46 #include "qvariant.h"
47 #include "qwidget_p.h"
48 #include "qx11info_x11.h"
49 #include <limits.h>
50 
52 
53 // defined in qwidget_x11.cpp
55 
56 
57 // function to update the workarea of the screen
60 {
62 }
63 
64 
66 {
67 public:
70 };
71 
73  : QWidget(0, Qt::Desktop)
74 {
75 }
76 
78 {
79  const QObjectList &childList = children();
80  for (int i = childList.size(); i > 0 ;) {
81  --i;
82  childList.at(i)->setParent(0);
83  }
84 }
85 
86 
88 {
89 public:
92 
93  void init();
94 
98 
102 };
103 
105  : use_xinerama(false), defaultScreen(0), screenCount(1),
106  screens(0), rects(0), workareas(0)
107 {
108 }
109 
111 {
112  if (screens) {
113  for (int i = 0; i < screenCount; ++i) {
114  if (i == defaultScreen) continue;
115  delete screens[i];
116  screens[i] = 0;
117  }
118 
119  free (screens);
120  }
121 
122  if (rects) delete [] rects;
123  if (workareas) delete [] workareas;
124 }
125 
127 {
128  // get the screen count
129  int newScreenCount = ScreenCount(X11->display);
130 #ifndef QT_NO_XINERAMA
131 
132  XineramaScreenInfo *xinerama_screeninfo = 0;
133 
134  // we ignore the Xinerama extension when using the display is
135  // using traditional multi-screen (with multiple root windows)
136  if (newScreenCount == 1
137  && X11->ptrXineramaQueryExtension
138  && X11->ptrXineramaIsActive
139  && X11->ptrXineramaQueryScreens) {
140  int unused;
141  use_xinerama = (X11->ptrXineramaQueryExtension(X11->display, &unused, &unused)
142  && X11->ptrXineramaIsActive(X11->display));
143  }
144 
145  if (use_xinerama) {
146  xinerama_screeninfo =
147  X11->ptrXineramaQueryScreens(X11->display, &newScreenCount);
148  }
149 
150  if (xinerama_screeninfo) {
151  defaultScreen = 0;
152  } else
153 #endif // QT_NO_XINERAMA
154  {
155  defaultScreen = DefaultScreen(X11->display);
156  newScreenCount = ScreenCount(X11->display);
157  use_xinerama = false;
158  }
159 
160  delete [] rects;
161  rects = new QRect[newScreenCount];
162  delete [] workareas;
163  workareas = new QRect[newScreenCount];
164 
165  // get the geometry of each screen
166  int i, j, x, y, w, h;
167  for (i = 0, j = 0; i < newScreenCount; i++, j++) {
168 
169 #ifndef QT_NO_XINERAMA
170  if (use_xinerama) {
171  x = xinerama_screeninfo[i].x_org;
172  y = xinerama_screeninfo[i].y_org;
173  w = xinerama_screeninfo[i].width;
174  h = xinerama_screeninfo[i].height;
175  } else
176 #endif // QT_NO_XINERAMA
177  {
178  x = 0;
179  y = 0;
180  w = WidthOfScreen(ScreenOfDisplay(X11->display, i));
181  h = HeightOfScreen(ScreenOfDisplay(X11->display, i));
182  }
183 
184  rects[j].setRect(x, y, w, h);
185 
186  if (use_xinerama && j > 0 && rects[j-1].intersects(rects[j])) {
187  // merge a "cloned" screen with the previous, hiding all crtcs
188  // that are currently showing a sub-rect of the previous screen
189  if ((rects[j].width()*rects[j].height()) >
190  (rects[j-1].width()*rects[j-1].height()))
191  rects[j-1] = rects[j];
192  j--;
193  }
194 
195  workareas[i] = QRect();
196  }
197 
198  if (screens) {
199  // leaks QWidget* pointers on purpose, can't delete them as pointer escapes
200  screens = q_check_ptr((QWidget**) realloc(screens, j * sizeof(QWidget*)));
201  if (j > screenCount)
202  memset(&screens[screenCount], 0, (j-screenCount) * sizeof(QWidget*));
203  }
204 
205  screenCount = j;
206 
207 #ifndef QT_NO_XINERAMA
208  if (use_xinerama && screenCount == 1)
209  use_xinerama = false;
210 
211  if (xinerama_screeninfo)
212  XFree(xinerama_screeninfo);
213 #endif // QT_NO_XINERAMA
214 
215 }
216 
217 // the QDesktopWidget itself will be created on the default screen
218 // as qt_x11_create_desktop_on_screen defaults to -1
221 {
223  d->init();
224 }
225 
227 {
228 }
229 
231 {
232  Q_D(const QDesktopWidget);
233  return d->use_xinerama;
234 }
235 
237 {
238  Q_D(const QDesktopWidget);
239  return d->defaultScreen;
240 }
241 
242 int QDesktopWidget::numScreens() const
243 {
244  Q_D(const QDesktopWidget);
245  return d->screenCount;
246 }
247 
248 QWidget *QDesktopWidget::screen(int screen)
249 {
251  if (d->use_xinerama)
252  return this;
253 
254  if (screen < 0 || screen >= d->screenCount)
255  screen = d->defaultScreen;
256 
257  if (! d->screens) {
258  d->screens = (QWidget**) calloc( d->screenCount, sizeof(QWidget*));
259  d->screens[d->defaultScreen] = this;
260  }
261 
262  if (! d->screens[screen] || // not created yet
263  ! (d->screens[screen]->windowType() == Qt::Desktop)) { // reparented away
265  d->screens[screen] = new QSingleDesktopWidget;
267  }
268 
269  return d->screens[screen];
270 }
271 
272 const QRect QDesktopWidget::availableGeometry(int screen) const
273 {
274  Q_D(const QDesktopWidget);
276  // the workareas are dirty, invalidate them
277  for (int i = 0; i < d->screenCount; ++i)
278  d->workareas[i] = QRect();
280  }
281 
282  if (screen < 0 || screen >= d->screenCount)
283  screen = d->defaultScreen;
284 
285  if (d->workareas[screen].isValid())
286  return d->workareas[screen];
287 
288  if (X11->isSupportedByWM(ATOM(_NET_WORKAREA))) {
289  int x11Screen = isVirtualDesktop() ? DefaultScreen(X11->display) : screen;
290 
291  Atom ret;
292  int format, e;
293  unsigned char *data = 0;
294  unsigned long nitems, after;
295 
296  e = XGetWindowProperty(X11->display,
297  QX11Info::appRootWindow(x11Screen),
298  ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL,
299  &ret, &format, &nitems, &after, &data);
300 
301  QRect workArea;
302  if (e == Success && ret == XA_CARDINAL &&
303  format == 32 && nitems == 4) {
304  long *workarea = (long *) data;
305  workArea = QRect(workarea[0], workarea[1], workarea[2], workarea[3]);
306  } else {
307  workArea = screenGeometry(screen);
308  }
309 
310  if (isVirtualDesktop()) {
311  // intersect the workarea (which spawns all Xinerama screens) with the rect for the
312  // requested screen
313  workArea &= screenGeometry(screen);
314  }
315 
316  d->workareas[screen] = workArea;
317 
318  if (data)
319  XFree(data);
320  } else {
321  d->workareas[screen] = screenGeometry(screen);
322  }
323 
324  return d->workareas[screen];
325 }
326 
327 const QRect QDesktopWidget::screenGeometry(int screen) const
328 {
329  Q_D(const QDesktopWidget);
330  if (screen < 0 || screen >= d->screenCount)
331  screen = d->defaultScreen;
332 
333  return d->rects[screen];
334 }
335 
337 {
338  Q_D(const QDesktopWidget);
339  if (!widget)
340  return d->defaultScreen;
341 
342 #ifndef QT_NO_XINERAMA
343  if (d->use_xinerama) {
344  // this is how we do it for xinerama
345  QRect frame = widget->frameGeometry();
346  if (!widget->isWindow())
347  frame.moveTopLeft(widget->mapToGlobal(QPoint(0, 0)));
348 
349  int maxSize = -1;
350  int maxScreen = -1;
351 
352  for (int i = 0; i < d->screenCount; ++i) {
353  QRect sect = d->rects[i].intersected(frame);
354  int size = sect.width() * sect.height();
355  if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
356  maxSize = size;
357  maxScreen = i;
358  }
359  }
360  return maxScreen;
361  }
362 #endif // QT_NO_XINERAMA
363 
364  return widget->x11Info().screen();
365 }
366 
367 int QDesktopWidget::screenNumber(const QPoint &point) const
368 {
369  Q_D(const QDesktopWidget);
370  int closestScreen = -1;
371  int shortestDistance = INT_MAX;
372  for (int i = 0; i < d->screenCount; ++i) {
373  int thisDistance = d->pointToRect(point, d->rects[i]);
374  if (thisDistance < shortestDistance) {
375  shortestDistance = thisDistance;
376  closestScreen = i;
377  }
378  }
379  return closestScreen;
380 }
381 
383 {
385  int oldScreenCount = d->screenCount;
386  QVector<QRect> oldRects(oldScreenCount);
387  for (int i = 0; i < oldScreenCount; ++i) {
388  oldRects[i] = d->rects[i];
389  }
390 
391  d->init();
392 
393  for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) {
394  if (oldRects.at(i) != d->rects[i])
395  emit resized(i);
396  }
397 
398  if (oldScreenCount != d->screenCount) {
399  emit screenCountChanged(d->screenCount);
400  }
401 
403  QWidget::resizeEvent(event);
404 }
405 
double d
Definition: qnumeric_p.h:62
T * q_check_ptr(T *p)
Definition: qglobal.h:1857
void resizeEvent(QResizeEvent *e)
This event handler can be reimplemented in a subclass to receive widget resize events which are passe...
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
EventRef event
QPointer< QWidget > widget
static int defaultScreen
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition: qwidget.h:945
static Qt::HANDLE appRootWindow(int screen=-1)
Returns a handle for the applications root window on the given screen.
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
const QX11Info & x11Info() const
Returns information about the configuration of the X display used to display the widget.
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
virtual void resizeEvent(QResizeEvent *)
This event handler can be reimplemented in a subclass to receive widget resize events which are passe...
Definition: qwidget.cpp:9587
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
#define X11
Definition: qt_x11_p.h:724
#define Q_D(Class)
Definition: qglobal.h:2482
void setParent(QObject *)
Makes the object a child of parent.
Definition: qobject.cpp:1950
#define ATOM(x)
Definition: qt_x11_p.h:723
QWidgetData data
Definition: qwidget_p.h:755
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
#define calloc(a, b)
static bool init
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
bool isVirtualDesktop() const
void * unused
Definition: qobject_p.h:208
static QVector< QRect > * rects
The QResizeEvent class contains event parameters for resize events.
Definition: qevent.h:349
int numScreens() const
int qt_x11_create_desktop_on_screen
Definition: qwidget_x11.cpp:99
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
QList< QDesktopScreenWidget * > screens
QWidget * screen(int screen=-1)
const QRect screenGeometry(int screen=-1) const
static QRect screenGeometry(const QWidget *widget)
Definition: qwidget_p.h:600
static bool qt_desktopwidget_workarea_dirty
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
if(void) toggleToolbarShown
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
Definition: qnamespace.h:54
void qt_desktopwidget_update_workarea()
const QObjectList & children() const
Returns a list of child objects.
Definition: qobject.h:197
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
int screen() const
Returns the number of the screen currently in use.