From 13254da6c3192937812983f44ce95fe8e1bc602c Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 17 Jul 2009 15:40:49 +0200 Subject: Implement QDesktopWidget::screenCountChanged signal on desktop platforms, and add manual testcase. Provide replacement "screenCount" for numScreens and document numScreens as obsolete to be more consistent with other APIs. --- dist/changes-4.6.0 | 4 + doc/src/qdesktopwidget.qdoc | 83 ++++++----- src/gui/kernel/qapplication_x11.cpp | 13 +- src/gui/kernel/qdesktopwidget.h | 4 + src/gui/kernel/qdesktopwidget_mac.mm | 64 +++++---- src/gui/kernel/qdesktopwidget_mac_p.h | 3 +- src/gui/kernel/qdesktopwidget_win.cpp | 18 +-- src/gui/kernel/qdesktopwidget_x11.cpp | 25 ++++ tests/manual/qdesktopwidget/main.cpp | 188 +++++++++++++++++++++++++ tests/manual/qdesktopwidget/qdesktopwidget.pro | 2 + 10 files changed, 323 insertions(+), 81 deletions(-) create mode 100644 tests/manual/qdesktopwidget/main.cpp create mode 100644 tests/manual/qdesktopwidget/qdesktopwidget.pro diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index 4c7bf52..5e211ff 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -68,3 +68,7 @@ information about a particular change. to the item's position and transformation, you can set the flag QGraphicsItem::ItemSendsGeometryChanges (which is enabled by default by QGraphicsWidget and QGraphicsProxyWidget). + +- QDesktopWidget on X11 no longer emits the resized(int) signal when screens + are added or removed. This was not done on other platforms. Use the + screenCountChanged signal instead diff --git a/doc/src/qdesktopwidget.qdoc b/doc/src/qdesktopwidget.qdoc index 1158904..383ccfc 100644 --- a/doc/src/qdesktopwidget.qdoc +++ b/doc/src/qdesktopwidget.qdoc @@ -54,9 +54,9 @@ Systems with more than one graphics card and monitor can manage the physical screen space available either as multiple desktops, or as a large virtual desktop, which usually has the size of the bounding - rectangle of all the screens (see isVirtualDesktop()). For an + rectangle of all the screens (see virtualDesktop). For an application, one of the available screens is the primary screen, i.e. - the screen where the main widget resides (see primaryScreen()). All + the screen where the main widget resides (see primaryScreen). All windows opened in the context of the application should be constrained to the boundaries of the primary screen; for example, it would be inconvenient if a dialog box popped up on a different @@ -64,16 +64,16 @@ The QDesktopWidget provides information about the geometry of the available screens with screenGeometry(). The number of screens - available is returned by numScreens(). The screen number that a - particular point or widget is located in is returned by - screenNumber(). + available is returned by screenCount, and the screenCountChanged + signal is emitted when screens are added or removed during runtime. + The screen number that a particular point or widget is located in + is returned by screenNumber(). Widgets provided by Qt use this class, for example, to place tooltips, menus and dialog boxes according to the parent or - application widget. - - Applications can use this class to save window positions, or to place - child widgets on one screen. + application widget. Applications can use this class to save window + positions, or to place child widgets and dialogs on one particular + screen. \img qdesktopwidget.png Managing Multiple Screens @@ -115,30 +115,15 @@ */ /*! - \fn bool QDesktopWidget::isVirtualDesktop() const - - Returns true if the system manages the available screens in a - virtual desktop; otherwise returns false. - - For virtual desktops, screen() will always return the same widget. - The size of the virtual desktop is the size of this desktop - widget. -*/ - -/*! - \fn int QDesktopWidget::primaryScreen() const - - Returns the index of the primary screen. - - \sa numScreens() -*/ - -/*! \fn int QDesktopWidget::numScreens() const - + Returns the number of available screens. + + \obsolete + + This function is deprecated. Use screenCount instead. - \sa primaryScreen() + \sa primaryScreen */ /*! @@ -146,13 +131,12 @@ Returns a widget that represents the screen with index \a screen (a value of -1 means the default screen). - If the system uses a virtual desktop, the returned widget will have the geometry of the entire virtual desktop; i.e., bounding every \a screen. - \sa primaryScreen(), numScreens(), isVirtualDesktop() + \sa primaryScreen, screenCount, virtualDesktop */ /*! @@ -216,7 +200,7 @@ Returns the index of the screen that contains the largest part of \a widget, or -1 if the widget not on a screen. - \sa primaryScreen() + \sa primaryScreen */ /*! @@ -226,7 +210,7 @@ Returns the index of the screen that contains the \a point, or the screen which is the shortest distance from the \a point. - \sa primaryScreen() + \sa primaryScreen */ /*! @@ -245,3 +229,34 @@ This signal is emitted when the work area available on \a screen changes. */ + +/*! + \property QDesktopWidget::screenCount + \brief the number of screens currently available on the system. + + \sa screenCountChanged() +*/ + +/*! + \property QDesktopWidget::primaryScreen + \brief the index of the screen that is configured to be the primary screen + on the system. +*/ + +/*! + \property QDesktopWidget::virtualDesktop + + \brief if the system manages the available screens in a virtual desktop. + + For virtual desktops, screen() will always return the same widget. + The size of the virtual desktop is the size of this desktop + widget. +*/ + +/*! + \fn void QDesktopWidget::screenCountChanged(int newCount) + + This signal is emitted when the number of screens changes to \a newCount. + + \sa screenCount +*/ diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index cc41299..a07ccdd 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -3441,19 +3441,10 @@ int QApplication::x11ProcessEvent(XEvent* event) QSize oldSize(w->size()); w->data->crect.setWidth(DisplayWidth(X11->display, scr)); w->data->crect.setHeight(DisplayHeight(X11->display, scr)); - QVarLengthArray oldSizes(desktop->numScreens()); - for (int i = 0; i < desktop->numScreens(); ++i) - oldSizes[i] = desktop->screenGeometry(i); QResizeEvent e(w->size(), oldSize); QApplication::sendEvent(w, &e); - for (int i = 0; i < qMin(oldSizes.count(), desktop->numScreens()); ++i) { - if (oldSizes[i] != desktop->screenGeometry(i)) - emit desktop->resized(i); - } - for (int i = oldSizes.count(); i < desktop->numScreens(); ++i) - emit desktop->resized(i); // added - for (int i = desktop->numScreens(); i < oldSizes.count(); ++i) - emit desktop->resized(i); // removed + if (w != desktop) + QApplication::sendEvent(desktop, &e); } #endif // QT_NO_XRANDR diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h index 470f10a..5ac953c 100644 --- a/src/gui/kernel/qdesktopwidget.h +++ b/src/gui/kernel/qdesktopwidget.h @@ -85,6 +85,7 @@ public: Q_SIGNALS: void resized(int); void workAreaResized(int); + void screenCountChanged(int); protected: void resizeEvent(QResizeEvent *e); @@ -97,6 +98,9 @@ private: friend class QApplicationPrivate; }; +inline int QDesktopWidget::screenCount() const +{ return numScreens(); } + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qdesktopwidget_mac.mm b/src/gui/kernel/qdesktopwidget_mac.mm index 2489fe4..7dd74da 100644 --- a/src/gui/kernel/qdesktopwidget_mac.mm +++ b/src/gui/kernel/qdesktopwidget_mac.mm @@ -97,15 +97,13 @@ QT_USE_NAMESPACE Q_GLOBAL_STATIC(QDesktopWidgetImplementation, qdesktopWidgetImplementation) QDesktopWidgetImplementation::QDesktopWidgetImplementation() - : appScreen(0), displays(0) + : appScreen(0) { onResize(); } QDesktopWidgetImplementation::~QDesktopWidgetImplementation() { - if (displays) - [displays release]; } QDesktopWidgetImplementation *QDesktopWidgetImplementation::instance() @@ -118,13 +116,7 @@ QRect QDesktopWidgetImplementation::availableRect(int screenIndex) const if (screenIndex < 0 || screenIndex >= screenCount) screenIndex = appScreen; - NSRect r = [[displays objectAtIndex:screenIndex] visibleFrame]; - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - - const int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - return QRectF(r.origin.x, flippedY, - r.size.width, r.size.height).toRect(); + return availableRects[screenIndex].toRect(); } QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const @@ -132,22 +124,28 @@ QRect QDesktopWidgetImplementation::screenRect(int screenIndex) const if (screenIndex < 0 || screenIndex >= screenCount) screenIndex = appScreen; - NSRect r = [[displays objectAtIndex:screenIndex] frame]; - NSRect primaryRect = [[displays objectAtIndex:0] frame]; - - const int flippedY = - r.origin.y + // account for position offset and - primaryRect.size.height - r.size.height; // height difference. - return QRectF(r.origin.x, flippedY, - r.size.width, r.size.height).toRect(); + return screenRects[screenIndex].toRect(); } void QDesktopWidgetImplementation::onResize() { - if (displays) - [displays release]; - - displays = [[NSScreen screens] retain]; - screenCount = [displays count]; + QMacCocoaAutoReleasePool pool; + NSArray *displays = [NSScreen screens]; + screenCount = [displays count]; + + screenRects.clear(); + availableRects.clear(); + NSRect primaryRect = [[displays objectAtIndex:0] frame]; + for (int i = 0; iappScreen; QRect frame = widget->frameGeometry(); @@ -216,7 +214,7 @@ int QDesktopWidget::screenNumber(const QWidget *widget) const int QDesktopWidget::screenNumber(const QPoint &point) const { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); int closestScreen = -1; int shortestDistance = INT_MAX; for (int i = 0; i < d->screenCount; ++i) { @@ -232,13 +230,25 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *) { - QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + QDesktopWidgetImplementation *d = qdesktopWidgetImplementation(); + + const int oldScreenCount = d->screenCount; + const QVector oldRects(d->screenRects); + const QVector oldWorks(d->availableRects); d->onResize(); - for (int i = 0; i < d->screenCount; ++i) { - emit resized(i); + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldRects.at(i) != d->screenRects.at(i)) + emit resized(i); + } + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldWorks.at(i) != d->availableRects.at(i)) + emit workAreaResized(i); } + + if (oldscreencount != d->screenCount) + emit screenCountChanged(d->screenCount); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_mac_p.h b/src/gui/kernel/qdesktopwidget_mac_p.h index 0fdc455..e9d5d9f 100644 --- a/src/gui/kernel/qdesktopwidget_mac_p.h +++ b/src/gui/kernel/qdesktopwidget_mac_p.h @@ -64,7 +64,8 @@ public: int appScreen; int screenCount; - NSArray *displays; + QVector availableRects; + QVector screenRects; QRect availableRect(int screenIndex) const; QRect screenRect(int screenIndex) const; diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index fb176b7..a89e08f 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -354,10 +354,8 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *) { Q_D(QDesktopWidget); - QVector oldrects; - oldrects = *d->rects; - QVector oldworkrects; - oldworkrects = *d->workrects; + const QVector oldrects(*d->rects); + const QVector oldworkrects(*d->workrects); int oldscreencount = d->screenCount; QDesktopWidgetPrivate::cleanup(); @@ -368,18 +366,22 @@ void QDesktopWidget::resizeEvent(QResizeEvent *) #endif for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) { - QRect oldrect = oldrects[i]; - QRect newrect = d->rects->at(i); + const QRect oldrect = oldrects[i]; + const QRect newrect = d->rects->at(i); if (oldrect != newrect) emit resized(i); } for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) { - QRect oldrect = oldworkrects[j]; - QRect newrect = d->workrects->at(j); + const QRect oldrect = oldworkrects[j]; + const QRect newrect = d->workrects->at(j); if (oldrect != newrect) emit workAreaResized(j); } + + if (oldscreencount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } } #ifdef Q_CC_MSVC diff --git a/src/gui/kernel/qdesktopwidget_x11.cpp b/src/gui/kernel/qdesktopwidget_x11.cpp index 59d3239..1555fc0 100644 --- a/src/gui/kernel/qdesktopwidget_x11.cpp +++ b/src/gui/kernel/qdesktopwidget_x11.cpp @@ -372,7 +372,32 @@ int QDesktopWidget::screenNumber(const QPoint &point) const void QDesktopWidget::resizeEvent(QResizeEvent *event) { Q_D(QDesktopWidget); + int oldScreenCount = d->screenCount; + QVector oldRects(oldScreenCount); + QVector oldWorks(oldScreenCount); + for (int i = 0; i < oldScreenCount; ++i) { + oldRects[i] = d->rects[i]; + oldWorks[i] = d->workareas[i]; + } + d->init(); + + for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { + if (oldRects.at(i) != d->rects[i]) + emit resized(i); + } + + // ### workareas are just reset by init, not filled with new values + // ### so this will not work correctly + for (int j = 0; j < qMin(oldScreenCount, d->screenCount); ++j) { + if (oldWorks.at(j) != d->workareas[j]) + emit workAreaResized(j); + } + + if (oldScreenCount != d->screenCount) { + emit screenCountChanged(d->screenCount); + } + qt_desktopwidget_workarea_dirty = true; QWidget::resizeEvent(event); } diff --git a/tests/manual/qdesktopwidget/main.cpp b/tests/manual/qdesktopwidget/main.cpp new file mode 100644 index 0000000..1afc82e --- /dev/null +++ b/tests/manual/qdesktopwidget/main.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +class DesktopView : public QGraphicsView +{ + Q_OBJECT +public: + DesktopView() + : that(0) + { + scene = new QGraphicsScene; + setScene(scene); + + QDesktopWidget *desktop = QApplication::desktop(); + connect(desktop, SIGNAL(resized(int)), this, SLOT(updateScene())); + connect(desktop, SIGNAL(workAreaResized(int)), this, SLOT(updateScene())); + connect(desktop, SIGNAL(screenCountChanged(int)), this, SLOT(updateScene())); + + updateScene(); + + QTransform transform; + transform.scale(0.25, 0.25); + setTransform(transform); + + setBackgroundBrush(Qt::darkGray); + } + +protected: + void moveEvent(QMoveEvent *e) + { + if (that) { + that->setRect(appRect()); + scene->update(); + } + QGraphicsView::moveEvent(e); + } + void resizeEvent(QResizeEvent *e) + { + if (that) { + that->setRect(appRect()); + } + QGraphicsView::resizeEvent(e); + } + +private slots: + void updateScene() + { + scene->clear(); + + const QDesktopWidget *desktop = QApplication::desktop(); + const bool isVirtualDesktop = desktop->isVirtualDesktop(); + const int homeScreen = desktop->screenNumber(this); + + QRect sceneRect; + int screenCount = desktop->screenCount(); + for (int s = 0; s < screenCount; ++s) { + const bool isPrimary = desktop->primaryScreen() == s; + const QRect screenRect = desktop->screenGeometry(s); + const QRect workRect = desktop->availableGeometry(s); + const QBrush fillBrush = palette().brush(isPrimary ? QPalette::Active : QPalette::Inactive, QPalette::Highlight); + QGraphicsRectItem *screen = new QGraphicsRectItem(0, 0, screenRect.width(), screenRect.height()); + + if (isVirtualDesktop) { + thatRoot = QPoint(); + screen->setPos(screenRect.x(), screenRect.y()); + } else { + // for non-virtual desktops we assume that screens are + // simply next to each other + if (s) + screen->setPos(sceneRect.right(), 0); + if (s == homeScreen) + thatRoot = screen->pos().toPoint(); + } + + screen->setBrush(fillBrush); + scene->addItem(screen); + sceneRect.setLeft(qMin(sceneRect.left(), screenRect.left())); + sceneRect.setRight(qMax(sceneRect.right(), screenRect.right())); + sceneRect.setTop(qMin(sceneRect.top(), screenRect.top())); + sceneRect.setBottom(qMax(sceneRect.bottom(), screenRect.bottom())); + + QGraphicsRectItem *workArea = new QGraphicsRectItem(screen); + workArea->setRect(0, 0, workRect.width(), workRect.height()); + workArea->setPos(workRect.x() - screenRect.x(), workRect.y() - screenRect.y()); + workArea->setBrush(Qt::white); + + QGraphicsSimpleTextItem *screenNumber = new QGraphicsSimpleTextItem(workArea); + screenNumber->setText(QString::number(s)); + screenNumber->setPen(QPen(Qt::black, 1)); + screenNumber->setBrush(fillBrush); + screenNumber->setFont(QFont("Arial Black", 18)); + screenNumber->setTransform(QTransform().scale(10, 10)); + screenNumber->setTransformOrigin(screenNumber->boundingRect().center()); + QSizeF center = (workRect.size() - screenNumber->boundingRect().size()) / 2; + screenNumber->setPos(center.width(), center.height()); + + screen->show(); + screen->setZValue(1); + } + + if (isVirtualDesktop) { + QGraphicsRectItem *virtualDesktop = new QGraphicsRectItem; + virtualDesktop->setRect(sceneRect); + virtualDesktop->setPen(QPen(Qt::black)); + virtualDesktop->setBrush(Qt::DiagCrossPattern); + scene->addItem(virtualDesktop); + virtualDesktop->setZValue(-1); + virtualDesktop->show(); + } + + that = new QGraphicsRectItem; + that->setBrush(Qt::red); + that->setOpacity(0.5); + that->setZValue(2); + that->setRect(appRect()); + that->show(); + scene->addItem(that); + + scene->setSceneRect(sceneRect); + scene->update(); + } + + QRect appRect() const + { + QRect rect = frameGeometry(); + if (!QApplication::desktop()->isVirtualDesktop()) { + rect.translate(thatRoot); + } + return rect; + } + +private: + QGraphicsScene *scene; + QGraphicsRectItem *that; + QPoint thatRoot; +}; + +#include "main.moc" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + DesktopView view; + view.show(); + + return app.exec(); +} diff --git a/tests/manual/qdesktopwidget/qdesktopwidget.pro b/tests/manual/qdesktopwidget/qdesktopwidget.pro new file mode 100644 index 0000000..93d56eb --- /dev/null +++ b/tests/manual/qdesktopwidget/qdesktopwidget.pro @@ -0,0 +1,2 @@ +TEMPLATE = app +SOURCES += main.cpp -- cgit v0.12