~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/kernel/qdesktopwidget_x11.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the gui module of the Qt Toolkit.
 
6
**
 
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.
 
10
**
 
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.
 
15
**
 
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.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
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.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qdesktopwidget.h"
 
30
#include "qapplication.h"
 
31
#include "qt_x11_p.h"
 
32
#include "qx11info_x11.h"
 
33
#include "qwidget_p.h"
 
34
#include <limits.h>
 
35
 
 
36
// defined in qwidget_x11.cpp
 
37
extern int qt_x11_create_desktop_on_screen;
 
38
 
 
39
// defined in qapplication_x11.cpp
 
40
extern bool qt_net_supports(Atom atom);
 
41
 
 
42
// function to update the workarea of the screen
 
43
static bool qt_desktopwidget_workarea_dirty = true;
 
44
void qt_desktopwidget_update_workarea()
 
45
{
 
46
    qt_desktopwidget_workarea_dirty = true;
 
47
}
 
48
 
 
49
 
 
50
class QSingleDesktopWidget : public QWidget
 
51
{
 
52
public:
 
53
    QSingleDesktopWidget();
 
54
    ~QSingleDesktopWidget();
 
55
};
 
56
 
 
57
QSingleDesktopWidget::QSingleDesktopWidget()
 
58
    : QWidget(0, Qt::Desktop)
 
59
{
 
60
}
 
61
 
 
62
QSingleDesktopWidget::~QSingleDesktopWidget()
 
63
{
 
64
    const QObjectList &childList = children();
 
65
    for (int i = childList.size(); i > 0 ;) {
 
66
        --i;
 
67
        childList.at(i)->setParent(0);
 
68
    }
 
69
}
 
70
 
 
71
 
 
72
class QDesktopWidgetPrivate : public QWidgetPrivate
 
73
{
 
74
public:
 
75
    QDesktopWidgetPrivate();
 
76
    ~QDesktopWidgetPrivate();
 
77
 
 
78
    void init();
 
79
 
 
80
    bool use_xinerama;
 
81
    int defaultScreen;
 
82
    int screenCount;
 
83
 
 
84
    QWidget **screens;
 
85
    QRect *rects;
 
86
    QRect *workareas;
 
87
};
 
88
 
 
89
QDesktopWidgetPrivate::QDesktopWidgetPrivate()
 
90
    : use_xinerama(false), defaultScreen(0), screenCount(1),
 
91
      screens(0), rects(0), workareas(0)
 
92
{
 
93
}
 
94
 
 
95
QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
 
96
{
 
97
    if (screens) {
 
98
        for (int i = 0; i < screenCount; ++i) {
 
99
            if (i == defaultScreen) continue;
 
100
            delete screens[i];
 
101
            screens[i] = 0;
 
102
        }
 
103
 
 
104
        delete [] screens;
 
105
    }
 
106
 
 
107
    if (rects)     delete [] rects;
 
108
    if (workareas) delete [] workareas;
 
109
}
 
110
 
 
111
void QDesktopWidgetPrivate::init()
 
112
{
 
113
    // get the screen count
 
114
#ifndef QT_NO_XINERAMA
 
115
    XineramaScreenInfo *xinerama_screeninfo = 0;
 
116
    int unused;
 
117
    use_xinerama = (XineramaQueryExtension(X11->display, &unused, &unused) && XineramaIsActive(X11->display));
 
118
 
 
119
    if (use_xinerama) {
 
120
        xinerama_screeninfo =
 
121
            XineramaQueryScreens(X11->display, &screenCount);
 
122
        defaultScreen = 0;
 
123
    } else
 
124
#endif // QT_NO_XINERAMA
 
125
    {
 
126
        defaultScreen = DefaultScreen(X11->display);
 
127
        screenCount = ScreenCount(X11->display);
 
128
    }
 
129
 
 
130
    delete [] rects;
 
131
    rects     = new QRect[screenCount];
 
132
    delete [] workareas;
 
133
    workareas = new QRect[screenCount];
 
134
 
 
135
    // get the geometry of each screen
 
136
    int i, x, y, w, h;
 
137
    for (i = 0; i < screenCount; i++) {
 
138
 
 
139
#ifndef QT_NO_XINERAMA
 
140
        if (use_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;
 
145
        } else
 
146
#endif // QT_NO_XINERAMA
 
147
            {
 
148
                x = 0;
 
149
                y = 0;
 
150
                w = WidthOfScreen(ScreenOfDisplay(X11->display, i));
 
151
                h = HeightOfScreen(ScreenOfDisplay(X11->display, i));
 
152
            }
 
153
 
 
154
        rects[i].setRect(x, y, w, h);
 
155
        workareas[i] = QRect();
 
156
    }
 
157
 
 
158
#ifndef QT_NO_XINERAMA
 
159
    if (xinerama_screeninfo)
 
160
        XFree(xinerama_screeninfo);
 
161
#endif // QT_NO_XINERAMA
 
162
 
 
163
}
 
164
 
 
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)
 
169
{
 
170
    Q_D(QDesktopWidget);
 
171
    d->init();
 
172
}
 
173
 
 
174
QDesktopWidget::~QDesktopWidget()
 
175
{
 
176
}
 
177
 
 
178
bool QDesktopWidget::isVirtualDesktop() const
 
179
{
 
180
    Q_D(const QDesktopWidget);
 
181
    return d->use_xinerama;
 
182
}
 
183
 
 
184
int QDesktopWidget::primaryScreen() const
 
185
{
 
186
    Q_D(const QDesktopWidget);
 
187
    return d->defaultScreen;
 
188
}
 
189
 
 
190
int QDesktopWidget::numScreens() const
 
191
{
 
192
    Q_D(const QDesktopWidget);
 
193
    return d->screenCount;
 
194
}
 
195
 
 
196
QWidget *QDesktopWidget::screen(int screen)
 
197
{
 
198
    Q_D(QDesktopWidget);
 
199
    if (d->use_xinerama)
 
200
        return this;
 
201
 
 
202
    if (screen < 0 || screen >= d->screenCount)
 
203
        screen = d->defaultScreen;
 
204
 
 
205
    if (! d->screens) {
 
206
        d->screens = new QWidget*[d->screenCount];
 
207
        memset(d->screens, 0, d->screenCount * sizeof(QWidget *));
 
208
        d->screens[d->defaultScreen] = this;
 
209
    }
 
210
 
 
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;
 
216
    }
 
217
 
 
218
    return d->screens[screen];
 
219
}
 
220
 
 
221
const QRect QDesktopWidget::availableGeometry(int screen) const
 
222
{
 
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;
 
229
    }
 
230
 
 
231
    if (screen < 0 || screen >= d->screenCount)
 
232
        screen = d->defaultScreen;
 
233
 
 
234
    if (d->workareas[screen].isValid())
 
235
        return d->workareas[screen];
 
236
 
 
237
    if (! isVirtualDesktop() && qt_net_supports(ATOM(_NET_WORKAREA))) {
 
238
        Atom ret;
 
239
        int format, e;
 
240
        unsigned char *data = 0;
 
241
        unsigned long nitems, after;
 
242
 
 
243
        e = XGetWindowProperty(X11->display,
 
244
                                QX11Info::appRootWindow(screen),
 
245
                                ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL,
 
246
                                &ret, &format, &nitems, &after, &data);
 
247
 
 
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]);
 
253
        } else {
 
254
            d->workareas[screen] = screenGeometry(screen);
 
255
        }
 
256
        if (data)
 
257
            XFree(data);
 
258
    } else {
 
259
        d->workareas[screen] = screenGeometry(screen);
 
260
    }
 
261
 
 
262
    return d->workareas[screen];
 
263
}
 
264
 
 
265
const QRect QDesktopWidget::screenGeometry(int screen) const
 
266
{
 
267
    Q_D(const QDesktopWidget);
 
268
    if (screen < 0 || screen >= d->screenCount)
 
269
        screen = d->defaultScreen;
 
270
 
 
271
    return d->rects[screen];
 
272
}
 
273
 
 
274
int QDesktopWidget::screenNumber(const QWidget *widget) const
 
275
{
 
276
    Q_D(const QDesktopWidget);
 
277
    if (!widget)
 
278
        return d->defaultScreen;
 
279
 
 
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)));
 
286
 
 
287
        int maxSize = -1;
 
288
        int maxScreen = -1;
 
289
 
 
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) {
 
294
                maxSize = size;
 
295
                maxScreen = i;
 
296
            }
 
297
        }
 
298
        return maxScreen;
 
299
    }
 
300
#endif // QT_NO_XINERAMA
 
301
 
 
302
    return widget->x11Info().screen();
 
303
}
 
304
 
 
305
int QDesktopWidget::screenNumber(const QPoint &point) const
 
306
{
 
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;
 
314
            closestScreen = i;
 
315
        }
 
316
    }
 
317
    return closestScreen;
 
318
}
 
319
 
 
320
void QDesktopWidget::resizeEvent(QResizeEvent *event)
 
321
{
 
322
    Q_D(QDesktopWidget);
 
323
    d->init();
 
324
    qt_desktopwidget_workarea_dirty = true;
 
325
    QWidget::resizeEvent(event);
 
326
}