diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection_screens.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_screens.cpp | 146 |
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; } |