diff options
Diffstat (limited to 'src/client/qwaylandscreen.cpp')
-rw-r--r-- | src/client/qwaylandscreen.cpp | 210 |
1 files changed, 128 insertions, 82 deletions
diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp index e70796832..d51e8c6a0 100644 --- a/src/client/qwaylandscreen.cpp +++ b/src/client/qwaylandscreen.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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) 2016 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 "qwaylandscreen_p.h" @@ -53,8 +17,18 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { +QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandDisplay* display, uint id, uint version) + : QtWayland::zxdg_output_manager_v1(display->wl_registry(), id, qMin(3u, version)) +{ +} + +QWaylandXdgOutputManagerV1::~QWaylandXdgOutputManagerV1() +{ + destroy(); +} + QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id) - : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2)) + : QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 3)) , m_outputId(id) , mWaylandDisplay(waylandDisplay) , mOutputName(QStringLiteral("Screen%1").arg(id)) @@ -66,7 +40,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uin qCWarning(lcQpaWayland) << "wl_output done event not supported by compositor," << "QScreen may not work correctly"; mWaylandDisplay->forceRoundTrip(); // Give the compositor a chance to send geometry etc. - mOutputDone = true; // Fake the done event + mProcessedEvents |= OutputDoneEvent; // Fake the done event maybeInitialize(); } } @@ -75,16 +49,32 @@ QWaylandScreen::~QWaylandScreen() { if (zxdg_output_v1::isInitialized()) zxdg_output_v1::destroy(); + if (wl_output::version() >= WL_OUTPUT_RELEASE_SINCE_VERSION) + wl_output::release(); + else + wl_output_destroy(wl_output::object()); +} + +uint QWaylandScreen::requiredEvents() const +{ + uint ret = OutputDoneEvent; + + if (mWaylandDisplay->xdgOutputManager()) { + if (mWaylandDisplay->xdgOutputManager()->version() >= 2) + ret |= XdgOutputNameEvent; + + if (mWaylandDisplay->xdgOutputManager()->version() < 3) + ret |= XdgOutputDoneEvent; + } + return ret; } void QWaylandScreen::maybeInitialize() { Q_ASSERT(!mInitialized); - if (!mOutputDone) - return; - - if (mWaylandDisplay->xdgOutputManager() && !mXdgOutputDone) + const uint requiredEvents = this->requiredEvents(); + if ((mProcessedEvents & requiredEvents) != requiredEvents) return; mInitialized = true; @@ -95,7 +85,7 @@ void QWaylandScreen::maybeInitialize() updateXdgOutputProperties(); } -void QWaylandScreen::initXdgOutput(QtWayland::zxdg_output_manager_v1 *xdgOutputManager) +void QWaylandScreen::initXdgOutput(QWaylandXdgOutputManagerV1 *xdgOutputManager) { Q_ASSERT(xdgOutputManager); if (zxdg_output_v1::isInitialized()) @@ -165,22 +155,29 @@ QList<QPlatformScreen *> QWaylandScreen::virtualSiblings() const { QList<QPlatformScreen *> list; const QList<QWaylandScreen*> screens = mWaylandDisplay->screens(); - list.reserve(screens.count()); - for (QWaylandScreen *screen : qAsConst(screens)) { + auto *placeholder = mWaylandDisplay->placeholderScreen(); + + list.reserve(screens.size() + (placeholder ? 1 : 0)); + + for (QWaylandScreen *screen : std::as_const(screens)) { if (screen->screen()) list << screen; } + + if (placeholder) + list << placeholder; + return list; } -void QWaylandScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) +QWindow *QWaylandScreen::topLevelAt(const QPoint & pos) const { - const auto allWindows = QGuiApplication::allWindows(); - for (QWindow *window : allWindows) { - QWaylandWindow *w = static_cast<QWaylandWindow *>(window->handle()); - if (w && w->waylandScreen() == this) - w->setOrientationMask(mask); + if (QWaylandWindow::fixedToplevelPositions) { + Q_UNUSED(pos); + return nullptr; } + + return QPlatformScreen::topLevelAt(pos); } Qt::ScreenOrientation QWaylandScreen::orientation() const @@ -210,9 +207,37 @@ QPlatformCursor *QWaylandScreen::cursor() const } #endif // QT_CONFIG(cursor) -QWaylandScreen * QWaylandScreen::waylandScreenFromWindow(QWindow *window) +QPlatformScreen::SubpixelAntialiasingType QWaylandScreen::subpixelAntialiasingTypeHint() const +{ + QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint(); + if (type == QPlatformScreen::Subpixel_None) { + switch (mSubpixel) { + case wl_output::subpixel_unknown: + case wl_output::subpixel_none: + type = QPlatformScreen::Subpixel_None; + break; + case wl_output::subpixel_horizontal_rgb: + type = QPlatformScreen::Subpixel_RGB; + break; + case wl_output::subpixel_horizontal_bgr: + type = QPlatformScreen::Subpixel_BGR; + break; + case wl_output::subpixel_vertical_rgb: + type = QPlatformScreen::Subpixel_VRGB; + break; + case wl_output::subpixel_vertical_bgr: + type = QPlatformScreen::Subpixel_VBGR; + break; + } + } + return type; +} + +QWaylandScreen *QWaylandScreen::waylandScreenFromWindow(QWindow *window) { QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(window); + if (platformScreen->isPlaceholder()) + return nullptr; return static_cast<QWaylandScreen *>(platformScreen); } @@ -223,6 +248,35 @@ QWaylandScreen *QWaylandScreen::fromWlOutput(::wl_output *output) return nullptr; } +Qt::ScreenOrientation QWaylandScreen::toScreenOrientation(int wlTransform, + Qt::ScreenOrientation fallback) const +{ + auto orientation = fallback; + bool isPortrait = mGeometry.height() > mGeometry.width(); + switch (wlTransform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation; + break; + case WL_OUTPUT_TRANSFORM_90: + orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation; + break; + case WL_OUTPUT_TRANSFORM_180: + orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation; + break; + case WL_OUTPUT_TRANSFORM_270: + orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation; + break; + // Ignore these ones, at least for now + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + break; + } + + return orientation; +} + void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refresh) { if (!(flags & WL_OUTPUT_MODE_CURRENT)) @@ -243,11 +297,10 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y, const QString &model, int32_t transform) { - Q_UNUSED(subpixel); - mManufacturer = make; mModel = model; + mSubpixel = subpixel; mTransform = transform; mPhysicalSize = QSize(width, height); @@ -261,39 +314,25 @@ void QWaylandScreen::output_scale(int32_t factor) void QWaylandScreen::output_done() { - mOutputDone = true; - if (mInitialized) + mProcessedEvents |= OutputDoneEvent; + + if (mInitialized) { updateOutputProperties(); - else + if (zxdg_output_v1::isInitialized()) + updateXdgOutputProperties(); + } else { maybeInitialize(); + } } void QWaylandScreen::updateOutputProperties() { if (mTransform >= 0) { - bool isPortrait = mGeometry.height() > mGeometry.width(); - switch (mTransform) { - case WL_OUTPUT_TRANSFORM_NORMAL: - m_orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation; - break; - case WL_OUTPUT_TRANSFORM_90: - m_orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation; - break; - case WL_OUTPUT_TRANSFORM_180: - m_orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation; - break; - case WL_OUTPUT_TRANSFORM_270: - m_orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation; - break; - // Ignore these ones, at least for now - case WL_OUTPUT_TRANSFORM_FLIPPED: - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - break; + auto newOrientation = toScreenOrientation(mTransform, m_orientation); + if (m_orientation != newOrientation) { + m_orientation = newOrientation; + QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); } - - QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); mTransform = -1; } @@ -316,7 +355,10 @@ void QWaylandScreen::zxdg_output_v1_logical_size(int32_t width, int32_t height) void QWaylandScreen::zxdg_output_v1_done() { - mXdgOutputDone = true; + if (Q_UNLIKELY(mWaylandDisplay->xdgOutputManager()->version() >= 3)) + qWarning(lcQpaWayland) << "zxdg_output_v1.done received on version 3 or newer, this is most likely a bug in the compositor"; + + mProcessedEvents |= XdgOutputDoneEvent; if (mInitialized) updateXdgOutputProperties(); else @@ -325,7 +367,11 @@ void QWaylandScreen::zxdg_output_v1_done() void QWaylandScreen::zxdg_output_v1_name(const QString &name) { + if (Q_UNLIKELY(mInitialized)) + qWarning(lcQpaWayland) << "zxdg_output_v1.name received after output has been initialized, this is most likely a bug in the compositor"; + mOutputName = name; + mProcessedEvents |= XdgOutputNameEvent; } void QWaylandScreen::updateXdgOutputProperties() |