From a6b2a4642f07cd6e52b447e1e441b257990a8d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sun, 25 Oct 2015 01:11:28 +0200 Subject: Fix incorrect screen number reported by QDesktopWidget Screens connected to separate graphics cards are detected as separate screens which don't have offset. This patch fixes obtaining the screen number by QWidget: it uses the screen assigned to the root widget. The patch also assigns a proper QScreen to each QDesktopWidget screen(). It also fixes closing a popup menu by clicking on another screen. Task-number: QTBUG-48545 Change-Id: I3d76261c0c067293d39949c4428b2d8dfd085dc7 Reviewed-by: Shawn Rutledge --- src/widgets/kernel/qdesktopwidget.cpp | 31 ++++++++++++++++++++++++++----- src/widgets/widgets/qmenu.cpp | 6 +++++- 2 files changed, 31 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index b88b3cc61d..d21e60198e 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -36,6 +36,7 @@ #include "qdesktopwidget_p.h" #include "qscreen.h" #include "qwidget_p.h" +#include "qwindow.h" QT_BEGIN_NAMESPACE @@ -99,13 +100,18 @@ void QDesktopWidgetPrivate::_q_updateScreens() QRegion virtualGeometry; - // update the geometry of each screen widget, determine virtual geometry - // and emit change signals afterwards. + // update the geometry of each screen widget, determine virtual geometry, + // set the new screen for window handle and emit change signals afterwards. QList changedScreens; for (int i = 0; i < screens.length(); i++) { - const QRect screenGeometry = screenList.at(i)->geometry(); - if (screenGeometry != screens.at(i)->geometry()) { - screens.at(i)->setGeometry(screenGeometry); + QDesktopScreenWidget *screenWidget = screens.at(i); + QScreen *qScreen = screenList.at(i); + QWindow *winHandle = screenWidget->windowHandle(); + if (winHandle && winHandle->screen() != qScreen) + winHandle->setScreen(qScreen); + const QRect screenGeometry = qScreen->geometry(); + if (screenGeometry != screenWidget->geometry()) { + screenWidget->setGeometry(screenGeometry); changedScreens.push_back(i); } virtualGeometry += screenGeometry; @@ -191,6 +197,21 @@ int QDesktopWidget::screenNumber(const QWidget *w) const if (!w) return 0; + // Find the root widget, get a QScreen pointer from it and find + // the screen number. + const QWidget *root = w; + const QWidget *tmp = w; + while ((tmp = tmp->parentWidget())) + root = tmp; + QWindow *winHandle = root->windowHandle(); + if (winHandle) { + int screenIdx = QGuiApplication::screens().indexOf(winHandle->screen()); + if (screenIdx > -1) + return screenIdx; + } + + // If the screen number cannot be obtained using QScreen pointer, + // get it from window position using screen geometry. QRect frame = w->frameGeometry(); if (!w->isWindow()) frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 4239e7f3d4..ea3e4c4488 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -2586,7 +2586,11 @@ void QMenu::mousePressEvent(QMouseEvent *e) Q_D(QMenu); if (d->aboutToHide || d->mouseEventTaken(e)) return; - if (!rect().contains(e->pos())) { + // Workaround for XCB on multiple screens which doesn't have offset. If the menu is open on one screen + // and mouse clicks on second screen, e->pos() is QPoint(0,0) and the menu doesn't hide. This trick makes + // possible to hide the menu when mouse clicks on another screen (e->screenPos() returns correct value). + // Only when mouse clicks in QPoint(0,0) on second screen, the menu doesn't hide. + if ((e->pos().isNull() && !e->screenPos().isNull()) || !rect().contains(e->pos())) { if (d->noReplayFor && QRect(d->noReplayFor->mapToGlobal(QPoint()), d->noReplayFor->size()).contains(e->globalPos())) setAttribute(Qt::WA_NoMouseReplay); -- cgit v1.2.3