summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection_screens.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp146
1 files changed, 70 insertions, 76 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
index 22285b836d..c31e9b1039 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qxcbconnection.h"
#include "qxcbscreen.h"
#include "qxcbintegration.h"
@@ -191,7 +155,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
}
}
- qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
+ qCDebug(lcQpaScreen) << "updateScreens: primary output is" << std::as_const(m_screens).first()->name();
}
}
@@ -220,7 +184,7 @@ void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_cha
// If the screen became primary, reshuffle the order in QGuiApplicationPrivate
const int idx = m_screens.indexOf(screen);
if (idx > 0) {
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.swapItemsAt(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
@@ -240,7 +204,7 @@ QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
if (screen->isPrimary()) {
if (!m_screens.isEmpty())
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.prepend(screen);
} else {
@@ -255,7 +219,7 @@ QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
void QXcbConnection::destroyScreen(QXcbScreen *screen)
{
QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
- if (virtualDesktop->screens().count() == 1) {
+ if (virtualDesktop->screens().size() == 1) {
// If there are no other screens on the same virtual desktop,
// then transform the physical screen into a fake screen.
const QString nameWas = screen->name();
@@ -289,7 +253,7 @@ void QXcbConnection::updateScreen_monitor(QXcbScreen *screen, xcb_randr_monitor_
if (screen->isPrimary()) {
const int idx = m_screens.indexOf(screen);
if (idx > 0) {
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.swapItemsAt(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
@@ -304,7 +268,7 @@ QXcbScreen *QXcbConnection::createScreen_monitor(QXcbVirtualDesktop *virtualDesk
if (screen->isPrimary()) {
if (!m_screens.isEmpty())
- qAsConst(m_screens).first()->setPrimary(false);
+ std::as_const(m_screens).first()->setPrimary(false);
m_screens.prepend(screen);
} else {
@@ -330,10 +294,9 @@ QXcbScreen *QXcbConnection::findScreenForMonitorInfo(const QList<QPlatformScreen
{
for (int i = 0; i < screens.size(); ++i) {
auto s = static_cast<QXcbScreen*>(screens[i]);
- if (s->m_monitor && monitorInfo) {
- QByteArray ba1 = atomName(s->m_monitor->name);
+ if (monitorInfo) {
QByteArray ba2 = atomName(monitorInfo->name);
- if (ba1 == ba2)
+ if (s->name().toLocal8Bit() == ba2)
return s;
}
}
@@ -346,17 +309,24 @@ void QXcbConnection::initializeScreens(bool initialized)
xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup());
int xcbScreenNumber = 0; // screen number in the xcb sense
QXcbScreen *primaryScreen = nullptr;
+ if (isAtLeastXRandR15() && initialized)
+ m_screens.clear();
+
while (it.rem) {
if (isAtLeastXRandR15())
- initializeScreensFromMonitor(&it, xcbScreenNumber, primaryScreen, initialized);
+ initializeScreensFromMonitor(&it, xcbScreenNumber, &primaryScreen, initialized);
else if (isAtLeastXRandR12())
- initializeScreensFromOutput(&it, xcbScreenNumber, primaryScreen);
+ initializeScreensFromOutput(&it, xcbScreenNumber, &primaryScreen);
+ else {
+ qWarning("There is no XRandR 1.2 and later version available. There will be only fake screen(s) to use.");
+ initializeScreensWithoutXRandR(&it, xcbScreenNumber, &primaryScreen);
+ }
xcb_screen_next(&it);
++xcbScreenNumber;
}
- for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
+ for (QXcbVirtualDesktop *virtualDesktop : std::as_const(m_virtualDesktops))
virtualDesktop->subscribeToXFixesSelectionNotify();
if (m_virtualDesktops.isEmpty()) {
@@ -364,7 +334,7 @@ void QXcbConnection::initializeScreens(bool initialized)
} else {
// Ensure the primary screen is first on the list
if (primaryScreen) {
- if (qAsConst(m_screens).first() != primaryScreen) {
+ if (std::as_const(m_screens).first() != primaryScreen) {
m_screens.removeOne(primaryScreen);
m_screens.prepend(primaryScreen);
}
@@ -372,18 +342,38 @@ void QXcbConnection::initializeScreens(bool initialized)
// Push the screens to QGuiApplication
if (!initialized) {
- for (QXcbScreen *screen : qAsConst(m_screens)) {
+ for (QXcbScreen *screen : std::as_const(m_screens)) {
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
QWindowSystemInterface::handleScreenAdded(screen, screen->isPrimary());
}
}
if (!m_screens.isEmpty())
- qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
+ qCDebug(lcQpaScreen) << "initializeScreens: primary output is" << std::as_const(m_screens).first()->name();
+ }
+}
+
+void QXcbConnection::initializeScreensWithoutXRandR(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen **primaryScreen)
+{
+ // XRandR extension is missing, then create a fake/legacy screen.
+ xcb_screen_t *xcbScreen = it->data;
+ QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
+ m_virtualDesktops.append(virtualDesktop);
+ QList<QPlatformScreen *> siblings;
+
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, nullptr);
+ qCDebug(lcQpaScreen) << "created fake screen" << screen;
+ m_screens << screen;
+
+ if (primaryScreenNumber() == xcbScreenNumber) {
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
}
+ siblings << screen;
+ virtualDesktop->setScreens(std::move(siblings));
}
-void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen *primaryScreen)
+void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen **primaryScreen)
{
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
@@ -457,11 +447,11 @@ void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int
// always available if primary->output is XCB_NONE
// or currently disconnected output.
if (primaryScreenNumber() == xcbScreenNumber) {
- if (!primaryScreen || (primary && outputs[i] == primary->output)) {
- if (primaryScreen)
- primaryScreen->setPrimary(false);
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
+ if (!(*primaryScreen) || (primary && outputs[i] == primary->output)) {
+ if (*primaryScreen)
+ (*primaryScreen)->setPrimary(false);
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
siblings.prepend(siblings.takeLast());
}
}
@@ -477,15 +467,15 @@ void QXcbConnection::initializeScreensFromOutput(xcb_screen_iterator_t *it, int
qCDebug(lcQpaScreen) << "created fake screen" << screen;
m_screens << screen;
if (primaryScreenNumber() == xcbScreenNumber) {
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
}
siblings << screen;
}
virtualDesktop->setScreens(std::move(siblings));
}
-void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen *primaryScreen, bool initialized)
+void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int xcbScreenNumber, QXcbScreen **primaryScreen, bool initialized)
{
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
@@ -499,9 +489,11 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
m_virtualDesktops.append(virtualDesktop);
}
+
+ if (xcbScreenNumber != primaryScreenNumber())
+ return;
+
QList<QPlatformScreen*> old = virtualDesktop->m_screens;
- if (initialized)
- m_screens.clear();
QList<QPlatformScreen *> siblings;
@@ -519,28 +511,31 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
QXcbScreen *screen = nullptr;
if (!initialized) {
screen = new QXcbScreen(this, virtualDesktop, monitor_info, monitors_r->timestamp);
- m_screens << screen;
} else {
- screen = findScreenForMonitorInfo(virtualDesktop->m_screens, monitor_info);
+ screen = findScreenForMonitorInfo(old, monitor_info);
if (!screen) {
screen = createScreen_monitor(virtualDesktop, monitor_info, monitors_r->timestamp);
- QHighDpiScaling::updateHighDpiScaling();
} else {
- m_screens << screen;
updateScreen_monitor(screen, monitor_info, monitors_r->timestamp);
old.removeAll(screen);
}
}
-
+ if (!m_screens.contains(screen))
+ m_screens << screen;
siblings << screen;
- if (primaryScreenNumber() == xcbScreenNumber) {
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
+ // similar logic with QXcbConnection::initializeScreensFromOutput()
+ if (!(*primaryScreen) || monitor_info->primary) {
+ if (*primaryScreen)
+ (*primaryScreen)->setPrimary(false);
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
+ siblings.prepend(siblings.takeLast());
}
xcb_randr_monitor_info_next(&monitor_iter);
}
+ free(monitors_r);
if (siblings.isEmpty()) {
QXcbScreen *screen = nullptr;
@@ -558,10 +553,9 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
qCDebug(lcQpaScreen) << "create a fake screen: " << screen;
}
- if (primaryScreenNumber() == xcbScreenNumber) {
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
- }
+ *primaryScreen = screen;
+ (*primaryScreen)->setPrimary(true);
+
siblings << screen;
m_screens << screen;
}