summaryrefslogtreecommitdiffstats
path: root/src/kernel/qdesktopwidget_x11.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2011-07-10 15:24:15 -0500
committerTimothy Pearson <[email protected]>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /src/kernel/qdesktopwidget_x11.cpp
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'src/kernel/qdesktopwidget_x11.cpp')
-rw-r--r--src/kernel/qdesktopwidget_x11.cpp355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/kernel/qdesktopwidget_x11.cpp b/src/kernel/qdesktopwidget_x11.cpp
new file mode 100644
index 0000000..1ab32a6
--- /dev/null
+++ b/src/kernel/qdesktopwidget_x11.cpp
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Implementation of QDesktopWidget class.
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the kernel module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at [email protected].
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qdesktopwidget.h"
+#include "qapplication.h"
+#include "qobjectlist.h"
+#include "qt_x11_p.h"
+
+// defined in qwidget_x11.cpp
+extern int qt_x11_create_desktop_on_screen;
+
+// defined in qapplication_x11.cpp
+extern Atom qt_net_workarea;
+extern bool qt_net_supports(Atom atom);
+
+// function to update the workarea of the screen
+static bool qt_desktopwidget_workarea_dirty = TRUE;
+void qt_desktopwidget_update_workarea()
+{
+ qt_desktopwidget_workarea_dirty = TRUE;
+}
+
+
+class QSingleDesktopWidget : public QWidget
+{
+public:
+ QSingleDesktopWidget();
+ ~QSingleDesktopWidget();
+};
+
+QSingleDesktopWidget::QSingleDesktopWidget()
+ : QWidget( 0, "desktop", WType_Desktop )
+{
+}
+
+QSingleDesktopWidget::~QSingleDesktopWidget()
+{
+ while ( children() )
+ removeChild( children()->getFirst() );
+}
+
+
+class QDesktopWidgetPrivate
+{
+public:
+ QDesktopWidgetPrivate();
+ ~QDesktopWidgetPrivate();
+
+ void init();
+
+ bool use_xinerama;
+ int defaultScreen;
+ int screenCount;
+
+ QWidget **screens;
+ QRect *rects;
+ QRect *workareas;
+};
+
+QDesktopWidgetPrivate::QDesktopWidgetPrivate()
+ : use_xinerama(FALSE), defaultScreen(0), screenCount(1),
+ screens( 0 ), rects( 0 ), workareas( 0 )
+{
+}
+
+QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
+{
+ if ( screens ) {
+ for ( int i = 0; i < screenCount; ++i ) {
+ if (i == defaultScreen) continue;
+ delete screens[i];
+ screens[i] = 0;
+ }
+
+ free(screens);
+ }
+
+ if ( rects ) delete [] rects;
+ if ( workareas ) delete [] workareas;
+}
+
+void QDesktopWidgetPrivate::init()
+{
+ // get the screen count
+ int newScreenCount;
+
+#ifndef QT_NO_XINERAMA
+ XineramaScreenInfo *xinerama_screeninfo = 0;
+ int unused;
+ use_xinerama = (XineramaQueryExtension(QPaintDevice::x11AppDisplay(),
+ &unused, &unused) &&
+ XineramaIsActive(QPaintDevice::x11AppDisplay()));
+
+ if (use_xinerama) {
+ xinerama_screeninfo =
+ XineramaQueryScreens(QPaintDevice::x11AppDisplay(), &newScreenCount);
+
+ if (xinerama_screeninfo)
+ defaultScreen = 0;
+ } else
+#endif // QT_NO_XINERAMA
+ {
+ defaultScreen = DefaultScreen(QPaintDevice::x11AppDisplay());
+ newScreenCount = ScreenCount(QPaintDevice::x11AppDisplay());
+ use_xinerama = false;
+ }
+
+ delete [] rects;
+ rects = new QRect[ newScreenCount ];
+ delete [] workareas;
+ workareas = new QRect[ newScreenCount ];
+
+ // get the geometry of each screen
+ int i, j, x, y, w, h;
+ for ( i = 0, j = 0; i < newScreenCount; i++ ) {
+
+#ifndef QT_NO_XINERAMA
+ if (use_xinerama) {
+ x = xinerama_screeninfo[i].x_org;
+ y = xinerama_screeninfo[i].y_org;
+ w = xinerama_screeninfo[i].width;
+ h = xinerama_screeninfo[i].height;
+ } else
+#endif // QT_NO_XINERAMA
+ {
+ x = 0;
+ y = 0;
+ w = WidthOfScreen(ScreenOfDisplay(QPaintDevice::x11AppDisplay(), i));
+ h = HeightOfScreen(ScreenOfDisplay(QPaintDevice::x11AppDisplay(), i));
+ }
+
+ workareas[i] = QRect();
+ rects[j].setRect(x, y, w, h);
+
+ // overlapping?
+ if (j > 0 && rects[j-1].intersects(rects[j])) {
+ // pick the bigger one, ignore the other
+ if ((rects[j].width()*rects[j].height()) >
+ (rects[j-1].width()*rects[j-1].height()))
+ rects[j-1] = rects[j];
+ }
+ else
+ j++;
+ }
+
+ if (screens) {
+ // leaks QWidget* pointers on purpose, can't delete them as pointer escapes
+ screens = (QWidget**) realloc(screens, j * sizeof(QWidget*));
+ if (j > screenCount)
+ memset(&screens[screenCount], 0, (j-screenCount) * sizeof(QWidget*));
+ }
+
+ screenCount = j;
+
+#ifndef QT_NO_XINERAMA
+ if (use_xinerama && screenCount == 1)
+ use_xinerama = false;
+
+ if (xinerama_screeninfo)
+ XFree(xinerama_screeninfo);
+#endif // QT_NO_XINERAMA
+
+}
+
+// the QDesktopWidget itself will be created on the default screen
+// as qt_x11_create_desktop_on_screen defaults to -1
+QDesktopWidget::QDesktopWidget()
+ : QWidget( 0, "desktop", WType_Desktop )
+{
+ d = new QDesktopWidgetPrivate();
+
+ /*
+ we don't call d->init() here, since the initial resize event
+ will end up calling init() a second time, which is inefficient.
+ instead, for the sending of all posted event to the desktop
+ widget (including the initial resize event, which calls
+ d->init()).
+ */
+ QApplication::sendPostedEvents( this, 0 );
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+ delete d;
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return d->use_xinerama;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return d->defaultScreen;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ return d->screenCount;
+}
+
+QWidget *QDesktopWidget::screen( int screen )
+{
+ if (d->use_xinerama)
+ return this;
+
+ if ( screen < 0 || screen >= d->screenCount )
+ screen = d->defaultScreen;
+
+ if ( ! d->screens ) {
+ d->screens = (QWidget**) calloc( d->screenCount, sizeof(QWidget*));
+ d->screens[ d->defaultScreen ] = this;
+ }
+
+ if ( ! d->screens[screen] || // not created yet
+ ! d->screens[screen]->isDesktop() ) { // reparented away
+ qt_x11_create_desktop_on_screen = screen;
+ d->screens[screen] = new QSingleDesktopWidget;
+ qt_x11_create_desktop_on_screen = -1;
+ }
+
+ return d->screens[screen];
+}
+
+const QRect& QDesktopWidget::availableGeometry( int screen ) const
+{
+ if ( qt_desktopwidget_workarea_dirty ) {
+ // the workareas are dirty, invalidate them
+ for ( int i = 0; i < d->screenCount; ++i )
+ d->workareas[i] = QRect();
+ qt_desktopwidget_workarea_dirty = FALSE;
+ }
+
+ if ( screen < 0 || screen >= d->screenCount )
+ screen = d->defaultScreen;
+
+ if ( d->workareas[screen].isValid() )
+ return d->workareas[screen];
+
+ if ( ! isVirtualDesktop() && qt_net_supports( qt_net_workarea ) ) {
+ Atom ret;
+ int format, e;
+ unsigned char *data = 0;
+ unsigned long nitems, after;
+
+ e = XGetWindowProperty( QPaintDevice::x11AppDisplay(),
+ QPaintDevice::x11AppRootWindow( screen ),
+ qt_net_workarea, 0, 4, False, XA_CARDINAL,
+ &ret, &format, &nitems, &after, &data );
+
+ if (e == Success && ret == XA_CARDINAL &&
+ format == 32 && nitems == 4) {
+ long *workarea = (long *) data;
+ d->workareas[screen].setRect( workarea[0], workarea[1],
+ workarea[2], workarea[3] );
+ } else {
+ d->workareas[screen] = screenGeometry(screen);
+ }
+ if ( data )
+ XFree( data );
+ } else {
+ d->workareas[screen] = screenGeometry(screen);
+ }
+
+ return d->workareas[screen];
+}
+
+const QRect& QDesktopWidget::screenGeometry( int screen ) const
+{
+ if ( screen < 0 || screen >= d->screenCount )
+ screen = d->defaultScreen;
+
+ return d->rects[ screen ];
+}
+
+int QDesktopWidget::screenNumber( QWidget *widget ) const
+{
+ if ( !widget )
+ return d->defaultScreen;
+
+#ifndef QT_NO_XINERAMA
+ if (d->use_xinerama) {
+ // this is how we do it for xinerama
+ QRect frame = widget->frameGeometry();
+ if ( !widget->isTopLevel() )
+ frame.moveTopLeft( widget->mapToGlobal( QPoint( 0, 0 ) ) );
+
+ int maxSize = -1;
+ int maxScreen = -1;
+
+ for ( int i = 0; i < d->screenCount; ++i ) {
+ QRect sect = d->rects[i].intersect( frame );
+ int size = sect.width() * sect.height();
+ if ( size > maxSize && sect.width() > 0 && sect.height() > 0 ) {
+ maxSize = size;
+ maxScreen = i;
+ }
+ }
+ return maxScreen;
+ }
+#endif // QT_NO_XINERAMA
+
+ return widget->x11Screen();
+}
+
+int QDesktopWidget::screenNumber( const QPoint &point ) const
+{
+ for ( int i = 0; i < d->screenCount; ++i ) {
+ if ( d->rects[i].contains( point ) )
+ return i;
+ }
+ return -1;
+}
+
+void QDesktopWidget::resizeEvent( QResizeEvent *event )
+{
+ d->init();
+ qt_desktopwidget_workarea_dirty = TRUE;
+ QWidget::resizeEvent( event );
+}