1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the gui module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "qdesktopwidget.h"
30
#include "qapplication.h"
32
#include "qx11info_x11.h"
33
#include "qwidget_p.h"
36
// defined in qwidget_x11.cpp
37
extern int qt_x11_create_desktop_on_screen;
39
// defined in qapplication_x11.cpp
40
extern bool qt_net_supports(Atom atom);
42
// function to update the workarea of the screen
43
static bool qt_desktopwidget_workarea_dirty = true;
44
void qt_desktopwidget_update_workarea()
46
qt_desktopwidget_workarea_dirty = true;
50
class QSingleDesktopWidget : public QWidget
53
QSingleDesktopWidget();
54
~QSingleDesktopWidget();
57
QSingleDesktopWidget::QSingleDesktopWidget()
58
: QWidget(0, Qt::Desktop)
62
QSingleDesktopWidget::~QSingleDesktopWidget()
64
const QObjectList &childList = children();
65
for (int i = childList.size(); i > 0 ;) {
67
childList.at(i)->setParent(0);
72
class QDesktopWidgetPrivate : public QWidgetPrivate
75
QDesktopWidgetPrivate();
76
~QDesktopWidgetPrivate();
89
QDesktopWidgetPrivate::QDesktopWidgetPrivate()
90
: use_xinerama(false), defaultScreen(0), screenCount(1),
91
screens(0), rects(0), workareas(0)
95
QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
98
for (int i = 0; i < screenCount; ++i) {
99
if (i == defaultScreen) continue;
107
if (rects) delete [] rects;
108
if (workareas) delete [] workareas;
111
void QDesktopWidgetPrivate::init()
113
// get the screen count
114
#ifndef QT_NO_XINERAMA
115
XineramaScreenInfo *xinerama_screeninfo = 0;
117
use_xinerama = (XineramaQueryExtension(X11->display, &unused, &unused) && XineramaIsActive(X11->display));
120
xinerama_screeninfo =
121
XineramaQueryScreens(X11->display, &screenCount);
124
#endif // QT_NO_XINERAMA
126
defaultScreen = DefaultScreen(X11->display);
127
screenCount = ScreenCount(X11->display);
131
rects = new QRect[screenCount];
133
workareas = new QRect[screenCount];
135
// get the geometry of each screen
137
for (i = 0; i < screenCount; i++) {
139
#ifndef QT_NO_XINERAMA
141
x = xinerama_screeninfo[i].x_org;
142
y = xinerama_screeninfo[i].y_org;
143
w = xinerama_screeninfo[i].width;
144
h = xinerama_screeninfo[i].height;
146
#endif // QT_NO_XINERAMA
150
w = WidthOfScreen(ScreenOfDisplay(X11->display, i));
151
h = HeightOfScreen(ScreenOfDisplay(X11->display, i));
154
rects[i].setRect(x, y, w, h);
155
workareas[i] = QRect();
158
#ifndef QT_NO_XINERAMA
159
if (xinerama_screeninfo)
160
XFree(xinerama_screeninfo);
161
#endif // QT_NO_XINERAMA
165
// the QDesktopWidget itself will be created on the default screen
166
// as qt_x11_create_desktop_on_screen defaults to -1
167
QDesktopWidget::QDesktopWidget()
168
: QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
174
QDesktopWidget::~QDesktopWidget()
178
bool QDesktopWidget::isVirtualDesktop() const
180
Q_D(const QDesktopWidget);
181
return d->use_xinerama;
184
int QDesktopWidget::primaryScreen() const
186
Q_D(const QDesktopWidget);
187
return d->defaultScreen;
190
int QDesktopWidget::numScreens() const
192
Q_D(const QDesktopWidget);
193
return d->screenCount;
196
QWidget *QDesktopWidget::screen(int screen)
202
if (screen < 0 || screen >= d->screenCount)
203
screen = d->defaultScreen;
206
d->screens = new QWidget*[d->screenCount];
207
memset(d->screens, 0, d->screenCount * sizeof(QWidget *));
208
d->screens[d->defaultScreen] = this;
211
if (! d->screens[screen] || // not created yet
212
! (d->screens[screen]->windowType() == Qt::Desktop)) { // reparented away
213
qt_x11_create_desktop_on_screen = screen;
214
d->screens[screen] = new QSingleDesktopWidget;
215
qt_x11_create_desktop_on_screen = -1;
218
return d->screens[screen];
221
const QRect QDesktopWidget::availableGeometry(int screen) const
223
Q_D(const QDesktopWidget);
224
if (qt_desktopwidget_workarea_dirty) {
225
// the workareas are dirty, invalidate them
226
for (int i = 0; i < d->screenCount; ++i)
227
d->workareas[i] = QRect();
228
qt_desktopwidget_workarea_dirty = false;
231
if (screen < 0 || screen >= d->screenCount)
232
screen = d->defaultScreen;
234
if (d->workareas[screen].isValid())
235
return d->workareas[screen];
237
if (! isVirtualDesktop() && qt_net_supports(ATOM(_NET_WORKAREA))) {
240
unsigned char *data = 0;
241
unsigned long nitems, after;
243
e = XGetWindowProperty(X11->display,
244
QX11Info::appRootWindow(screen),
245
ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL,
246
&ret, &format, &nitems, &after, &data);
248
if (e == Success && ret == XA_CARDINAL &&
249
format == 32 && nitems == 4) {
250
long *workarea = (long *) data;
251
d->workareas[screen].setRect(workarea[0], workarea[1],
252
workarea[2], workarea[3]);
254
d->workareas[screen] = screenGeometry(screen);
259
d->workareas[screen] = screenGeometry(screen);
262
return d->workareas[screen];
265
const QRect QDesktopWidget::screenGeometry(int screen) const
267
Q_D(const QDesktopWidget);
268
if (screen < 0 || screen >= d->screenCount)
269
screen = d->defaultScreen;
271
return d->rects[screen];
274
int QDesktopWidget::screenNumber(const QWidget *widget) const
276
Q_D(const QDesktopWidget);
278
return d->defaultScreen;
280
#ifndef QT_NO_XINERAMA
281
if (d->use_xinerama) {
282
// this is how we do it for xinerama
283
QRect frame = widget->frameGeometry();
284
if (!widget->isWindow())
285
frame.moveTopLeft(widget->mapToGlobal(QPoint(0, 0)));
290
for (int i = 0; i < d->screenCount; ++i) {
291
QRect sect = d->rects[i].intersect(frame);
292
int size = sect.width() * sect.height();
293
if (size > maxSize && sect.width() > 0 && sect.height() > 0) {
300
#endif // QT_NO_XINERAMA
302
return widget->x11Info().screen();
305
int QDesktopWidget::screenNumber(const QPoint &point) const
307
Q_D(const QDesktopWidget);
308
int closestScreen = -1;
309
int shortestDistance = INT_MAX;
310
for (int i = 0; i < d->screenCount; ++i) {
311
int thisDistance = d->pointToRect(point, d->rects[i]);
312
if (thisDistance < shortestDistance) {
313
shortestDistance = thisDistance;
317
return closestScreen;
320
void QDesktopWidget::resizeEvent(QResizeEvent *event)
324
qt_desktopwidget_workarea_dirty = true;
325
QWidget::resizeEvent(event);