diff --git a/src/plugins/platforms/wayland/client.pro b/src/plugins/platforms/wayland/client.pro index 22271ee4512..ef3cff054fc 100644 --- a/src/plugins/platforms/wayland/client.pro +++ b/src/plugins/platforms/wayland/client.pro @@ -5,7 +5,8 @@ QT_FOR_PRIVATE += platformsupport-private MODULE=waylandclient MODULE_PLUGIN_TYPES = \ wayland-graphics-integration-client \ - wayland-inputdevice-integration + wayland-inputdevice-integration \ + wayland-decoration-client load(qt_module) @@ -71,7 +72,9 @@ SOURCES += qwaylandintegration.cpp \ qwaylandtouch.cpp \ qwaylandqtkey.cpp \ ../shared/qwaylandmimehelper.cpp \ - qwaylanddecoration.cpp \ + qwaylandabstractdecoration.cpp \ + qwaylanddecorationfactory.cpp \ + qwaylanddecorationplugin.cpp \ qwaylandeventthread.cpp\ qwaylandwindowmanagerintegration.cpp \ qwaylandinputcontext.cpp \ @@ -102,7 +105,9 @@ HEADERS += qwaylandintegration_p.h \ qwaylandtouch_p.h \ qwaylandqtkey_p.h \ ../shared/qwaylandmimehelper.h \ - qwaylanddecoration_p.h \ + qwaylandabstractdecoration_p.h \ + qwaylanddecorationfactory_p.h \ + qwaylanddecorationplugin_p.h \ qwaylandeventthread_p.h \ qwaylandwindowmanagerintegration_p.h \ qwaylandinputcontext_p.h \ diff --git a/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h b/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h index 255a6685415..5fa187e6997 100644 --- a/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h +++ b/src/plugins/platforms/wayland/inputdeviceintegration/qwaylandinputdeviceintegration_p.h @@ -56,7 +56,7 @@ public: QWaylandInputDeviceIntegration() {} virtual ~QWaylandInputDeviceIntegration() {} - virtual QWaylandInputDevice *createInputDevice(QWaylandDisplay *d, uint32_t id) = 0; + virtual QWaylandInputDevice *createInputDevice(QWaylandDisplay *d, int version, uint32_t id) = 0; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.json b/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.json new file mode 100644 index 00000000000..e1a5ef24fe8 --- /dev/null +++ b/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "bradient" ] +} diff --git a/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro b/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro new file mode 100644 index 00000000000..fd376f4a985 --- /dev/null +++ b/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro @@ -0,0 +1,17 @@ +PLUGIN_TYPE = wayland-decoration-client +load(qt_plugin) + +QT += waylandclient-private + +OTHER_FILES += \ + bradient.json + +SOURCES += main.cpp + +contains(QT_CONFIG, no-pkg-config) { + LIBS += -lwayland-client +} else { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-client +} + diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.cpp b/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp similarity index 63% rename from src/plugins/platforms/wayland/qwaylanddecoration.cpp rename to src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp index ed4978725a4..c249248c320 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration.cpp +++ b/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2014 Robin Burchell ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -39,20 +40,18 @@ ** ****************************************************************************/ -#include "qwaylanddecoration_p.h" - -#include "qwaylandwindow_p.h" -#include "qwaylandshellsurface_p.h" -#include "qwaylandinputdevice_p.h" -#include "qwaylandscreen_p.h" - -#include -#include #include #include #include #include +#include + +#include +#include +#include +#include + QT_BEGIN_NAMESPACE #define BUTTON_SPACING 5 @@ -123,16 +122,35 @@ static const char * const qt_normalizeup_xpm[] = { # define BUTTON_WIDTH 22 #endif -QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window) - : m_window(window->window()) - , m_wayland_window(window) - , m_isDirty(true) - , m_decorationContentImage(0) - , m_margins(3,30,3,3) - , m_mouseButtons(Qt::NoButton) +class Q_WAYLAND_CLIENT_EXPORT QWaylandBradientDecoration : public QWaylandAbstractDecoration { - m_wayland_window->setDecoration(this); +public: + QWaylandBradientDecoration(); +protected: + QMargins margins() const Q_DECL_OVERRIDE; + void paint(QPaintDevice *device) Q_DECL_OVERRIDE; + bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods) Q_DECL_OVERRIDE; + bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) Q_DECL_OVERRIDE; +private: + void processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + QRectF closeButtonRect() const; + QRectF maximizeButtonRect() const; + QRectF minimizeButtonRect() const; + + QColor m_foregroundColor; + QColor m_backgroundColor; + QStaticText m_windowTitle; +}; + + + +QWaylandBradientDecoration::QWaylandBradientDecoration() + : QWaylandAbstractDecoration() +{ QPalette palette; m_foregroundColor = palette.color(QPalette::Active, QPalette::HighlightedText); m_backgroundColor = palette.color(QPalette::Active, QPalette::Highlight); @@ -142,32 +160,30 @@ QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window) m_windowTitle.setTextOption(option); } -QWaylandDecoration::~QWaylandDecoration() +QRectF QWaylandBradientDecoration::closeButtonRect() const { - m_wayland_window->setDecoration(0); + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); } -const QImage &QWaylandDecoration::contentImage() +QRectF QWaylandBradientDecoration::maximizeButtonRect() const { - if (m_isDirty) { - //Update the decoration backingstore - - m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); - m_decorationContentImage.fill(Qt::transparent); - this->paint(&m_decorationContentImage); - - m_isDirty = false; - } - - return m_decorationContentImage; + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); } -void QWaylandDecoration::update() +QRectF QWaylandBradientDecoration::minimizeButtonRect() const { - m_isDirty = true; + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); } -void QWaylandDecoration::paint(QPaintDevice *device) +QMargins QWaylandBradientDecoration::margins() const +{ + return QMargins(3, 30, 3, 3); +} + +void QWaylandBradientDecoration::paint(QPaintDevice *device) { QRect surfaceRect(QPoint(), window()->frameGeometry().size()); QRect clips[] = @@ -199,7 +215,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) } // Window icon - QIcon icon = m_wayland_window->windowIcon(); + QIcon icon = waylandWindow()->windowIcon(); if (!icon.isNull()) { QPixmap pixmap = icon.pixmap(QSize(128, 128)); QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); @@ -219,7 +235,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) } QRect titleBar = top; - titleBar.setLeft(m_margins.left() + BUTTON_SPACING + + titleBar.setLeft(margins().left() + BUTTON_SPACING + (icon.isNull() ? 0 : 22 + BUTTON_SPACING)); titleBar.setRight(minimizeButtonRect().left() - BUTTON_SPACING); @@ -234,7 +250,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) p.setFont(font); QPoint windowTitlePoint(top.topLeft().x() + dx, top.topLeft().y() + dy); - p.drawStaticText(windowTitlePoint,m_windowTitle); + p.drawStaticText(windowTitlePoint, m_windowTitle); p.restore(); } @@ -246,7 +262,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) p.drawPixmap(closeButtonRect(), closePixmap, closePixmap.rect()); // Maximize button - QPixmap maximizePixmap(m_wayland_window->isMaximized() + QPixmap maximizePixmap(waylandWindow()->isMaximized() ? qt_normalizeup_xpm : qt_maximize_xpm); p.drawPixmap(maximizeButtonRect(), maximizePixmap, maximizePixmap.rect()); @@ -282,7 +298,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) p.save(); p.drawRect(maximizeButtonRect()); rect = maximizeButtonRect().adjusted(5, 5, -5, -5); - if (m_wayland_window->isMaximized()) { + if (waylandWindow()->isMaximized()) { QRectF rect1 = rect.adjusted(rect.width() / 3, 0, 0, -rect.height() / 3); QRectF rect2 = rect.adjusted(0, rect.height() / 4, -rect.width() / 4, 0); p.drawRect(rect1); @@ -305,37 +321,37 @@ void QWaylandDecoration::paint(QPaintDevice *device) #endif } -bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +bool QWaylandBradientDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(global); // Figure out what area mouse is in if (closeButtonRect().contains(local) && isLeftClicked(b)) { - QWindowSystemInterface::handleCloseEvent(m_window); + QWindowSystemInterface::handleCloseEvent(window()); } else if (maximizeButtonRect().contains(local) && isLeftClicked(b)) { - m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + window()->setWindowState(waylandWindow()->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); } else if (minimizeButtonRect().contains(local) && isLeftClicked(b)) { - m_window->setWindowState(Qt::WindowMinimized); - } else if (local.y() <= m_margins.top()) { + window()->setWindowState(Qt::WindowMinimized); + } else if (local.y() <= margins().top()) { processMouseTop(inputDevice,local,b,mods); - } else if (local.y() > m_window->height() - m_margins.bottom() + m_margins.top()) { + } else if (local.y() > window()->height() - margins().bottom() + margins().top()) { processMouseBottom(inputDevice,local,b,mods); - } else if (local.x() <= m_margins.left()) { + } else if (local.x() <= margins().left()) { processMouseLeft(inputDevice,local,b,mods); - } else if (local.x() > m_window->width() - m_margins.right() + m_margins.left()) { + } else if (local.x() > window()->width() - margins().right() + margins().left()) { processMouseRight(inputDevice,local,b,mods); } else { - m_wayland_window->restoreMouseCursor(inputDevice); - m_mouseButtons = b; + waylandWindow()->restoreMouseCursor(inputDevice); + setMouseButtons(b); return false; } - m_mouseButtons = b; + setMouseButtons(b); return true; } -bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +bool QWaylandBradientDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) { Q_UNUSED(inputDevice); Q_UNUSED(global); @@ -343,13 +359,13 @@ bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPo bool handled = state == Qt::TouchPointPressed; if (handled) { if (closeButtonRect().contains(local)) - QWindowSystemInterface::handleCloseEvent(m_window); + QWindowSystemInterface::handleCloseEvent(window()); else if (maximizeButtonRect().contains(local)) - m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + window()->setWindowState(waylandWindow()->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); else if (minimizeButtonRect().contains(local)) - m_window->setWindowState(Qt::WindowMinimized); - else if (local.y() <= m_margins.top()) - m_wayland_window->shellSurface()->move(inputDevice); + window()->setWindowState(Qt::WindowMinimized); + else if (local.y() <= margins().top()) + waylandWindow()->shellSurface()->move(inputDevice); else handled = false; } @@ -357,115 +373,80 @@ bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPo return handled; } -bool QWaylandDecoration::inMouseButtonPressedState() const -{ - return m_mouseButtons & Qt::NoButton; -} - -void QWaylandDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons) -{ - if (isLeftClicked(buttons)) { - m_wayland_window->shellSurface()->resize(inputDevice, resize); - inputDevice->removeMouseButtonFromState(Qt::LeftButton); - } -} - -void QWaylandDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) -{ - if (isLeftClicked(buttons)) { - m_wayland_window->shellSurface()->move(inputDevice); - inputDevice->removeMouseButtonFromState(Qt::LeftButton); - } -} - -void QWaylandDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(mods); - if (local.y() <= m_margins.bottom()) { + if (local.y() <= margins().bottom()) { if (local.x() <= margins().left()) { //top left bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_LEFT,b); - } else if (local.x() > m_window->width() - margins().right()) { + } else if (local.x() > window()->width() - margins().right()) { //top right bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_RIGHT,b); } else { //top reszie bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitVCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP,b); } } else { - m_wayland_window->restoreMouseCursor(inputDevice); + waylandWindow()->restoreMouseCursor(inputDevice); startMove(inputDevice,b); } } -void QWaylandDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(mods); if (local.x() <= margins().left()) { //bottom left bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT,b); - } else if (local.x() > m_window->width() - margins().right()) { + } else if (local.x() > window()->width() - margins().right()) { //bottom right bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT,b); } else { //bottom bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitVCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_BOTTOM,b); } } -void QWaylandDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(local); Q_UNUSED(mods); - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitHCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitHCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b); } -void QWaylandDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(local); Q_UNUSED(mods); - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitHCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitHCursor); startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b); } -bool QWaylandDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) +class QWaylandBradientDecorationPlugin : public QWaylandDecorationPlugin { - if ((!m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) - return true; - return false; + Q_OBJECT + Q_PLUGIN_METADATA(IID QWaylandDecorationFactoryInterface_iid FILE "bradient.json") +public: + QWaylandAbstractDecoration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; +}; + +QWaylandAbstractDecoration *QWaylandBradientDecorationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + Q_UNUSED(system); + return new QWaylandBradientDecoration(); } -bool QWaylandDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) -{ - if ((m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) - return true; - return false; -} - -QRectF QWaylandDecoration::closeButtonRect() const -{ - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); -} - -QRectF QWaylandDecoration::maximizeButtonRect() const -{ - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); -} - -QRectF QWaylandDecoration::minimizeButtonRect() const -{ - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); -} QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platforms/wayland/plugins/decorations/decorations.pro b/src/plugins/platforms/wayland/plugins/decorations/decorations.pro new file mode 100644 index 00000000000..6d51a450fb2 --- /dev/null +++ b/src/plugins/platforms/wayland/plugins/decorations/decorations.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS += \ + bradient diff --git a/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp b/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp new file mode 100644 index 00000000000..e4b81bb8363 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandabstractdecoration_p.h" + +#include +#include "qwaylandwindow_p.h" +#include "qwaylandshellsurface_p.h" +#include "qwaylandinputdevice_p.h" +#include "qwaylandscreen_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QWaylandAbstractDecorationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandAbstractDecoration) + +public: + QWaylandAbstractDecorationPrivate(); + ~QWaylandAbstractDecorationPrivate(); + + QWindow *m_window; + QWaylandWindow *m_wayland_window; + + bool m_isDirty; + QImage m_decorationContentImage; + + Qt::MouseButtons m_mouseButtons; +}; + +QWaylandAbstractDecorationPrivate::QWaylandAbstractDecorationPrivate() + : m_window(0) + , m_wayland_window(0) + , m_isDirty(true) + , m_decorationContentImage(0) + , m_mouseButtons(Qt::NoButton) +{ +} + +QWaylandAbstractDecorationPrivate::~QWaylandAbstractDecorationPrivate() +{ +} + +QWaylandAbstractDecoration::QWaylandAbstractDecoration() + : QObject(*new QWaylandAbstractDecorationPrivate) +{ +} + +QWaylandAbstractDecoration::~QWaylandAbstractDecoration() +{ +} + +// we do this as a setter to get around plugin factory creates not really +// being a great way to pass arguments +void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window) +{ + Q_D(QWaylandAbstractDecoration); + + // double initialization is probably not great + Q_ASSERT(!d->m_window && !d->m_wayland_window); + + d->m_window = window->window(); + d->m_wayland_window = window; +} + +const QImage &QWaylandAbstractDecoration::contentImage() +{ + Q_D(QWaylandAbstractDecoration); + if (d->m_isDirty) { + //Update the decoration backingstore + + d->m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); + d->m_decorationContentImage.fill(Qt::transparent); + this->paint(&d->m_decorationContentImage); + + d->m_isDirty = false; + } + + return d->m_decorationContentImage; +} + +void QWaylandAbstractDecoration::update() +{ + Q_D(QWaylandAbstractDecoration); + d->m_isDirty = true; +} + +void QWaylandAbstractDecoration::setMouseButtons(Qt::MouseButtons mb) +{ + Q_D(QWaylandAbstractDecoration); + d->m_mouseButtons = mb; +} + +void QWaylandAbstractDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons) +{ + Q_D(QWaylandAbstractDecoration); + if (isLeftClicked(buttons)) { + d->m_wayland_window->shellSurface()->resize(inputDevice, resize); + inputDevice->removeMouseButtonFromState(Qt::LeftButton); + } +} + +void QWaylandAbstractDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) +{ + Q_D(QWaylandAbstractDecoration); + if (isLeftClicked(buttons)) { + d->m_wayland_window->shellSurface()->move(inputDevice); + inputDevice->removeMouseButtonFromState(Qt::LeftButton); + } +} + +bool QWaylandAbstractDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) +{ + Q_D(QWaylandAbstractDecoration); + if ((!d->m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) + return true; + return false; +} + +bool QWaylandAbstractDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) +{ + Q_D(QWaylandAbstractDecoration); + if ((d->m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) + return true; + return false; +} + +bool QWaylandAbstractDecoration::isDirty() const +{ + Q_D(const QWaylandAbstractDecoration); + return d->m_isDirty; +} + +QWindow *QWaylandAbstractDecoration::window() const +{ + Q_D(const QWaylandAbstractDecoration); + return d->m_window; +} + +QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const +{ + Q_D(const QWaylandAbstractDecoration); + return d->m_wayland_window; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddecoration_p.h b/src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h similarity index 61% rename from src/plugins/platforms/wayland/qwaylanddecoration_p.h rename to src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h index c240b9c9d45..6171cab14cb 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration_p.h +++ b/src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2014 Robin Burchell ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -39,8 +40,8 @@ ** ****************************************************************************/ -#ifndef QWAYLANDDECORATION_H -#define QWAYLANDDECORATION_H +#ifndef QWAYLANDABSTRACTDECORATION_H +#define QWAYLANDABSTRACTDECORATION_H #include #include @@ -64,77 +65,41 @@ class QEvent; class QWaylandScreen; class QWaylandWindow; class QWaylandInputDevice; +class QWaylandAbstractDecorationPrivate; -class Q_WAYLAND_CLIENT_EXPORT QWaylandDecoration +class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration : public QObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandAbstractDecoration) public: - QWaylandDecoration(QWaylandWindow *window); - virtual ~QWaylandDecoration(); + QWaylandAbstractDecoration(); + virtual ~QWaylandAbstractDecoration(); + + void setWaylandWindow(QWaylandWindow *window); + QWaylandWindow *waylandWindow() const; void update(); bool isDirty() const; - bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods); - bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods); - bool inMouseButtonPressedState() const; + virtual QMargins margins() const = 0; + QWindow *window() const; + const QImage &contentImage(); + + virtual bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods) = 0; + virtual bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) = 0; + +protected: + virtual void paint(QPaintDevice *device) = 0; + + void setMouseButtons(Qt::MouseButtons mb); void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons); void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons); - QMargins margins() const; - QWindow *window() const; - QWaylandWindow *waylandWindow() const; - const QImage &contentImage(); - -protected: - void paint(QPaintDevice *device); - -private: - void processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); - void processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); - void processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); - void processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); bool isLeftClicked(Qt::MouseButtons newMouseButtonState); bool isLeftReleased(Qt::MouseButtons newMouseButtonState); - - QRectF closeButtonRect() const; - QRectF maximizeButtonRect() const; - QRectF minimizeButtonRect() const; - - QWindow *m_window; - QWaylandWindow *m_wayland_window; - - bool m_isDirty; - QImage m_decorationContentImage; - - QMargins m_margins; - Qt::MouseButtons m_mouseButtons; - - QColor m_foregroundColor; - QColor m_backgroundColor; - QStaticText m_windowTitle; }; -inline bool QWaylandDecoration::isDirty() const -{ - return m_isDirty; -} - -inline QMargins QWaylandDecoration::margins() const -{ - return m_margins; -} - -inline QWindow *QWaylandDecoration::window() const -{ - return m_window; -} - -inline QWaylandWindow *QWaylandDecoration::waylandWindow() const -{ - return m_wayland_window; -} - QT_END_NAMESPACE -#endif // QWAYLANDDECORATION_H +#endif // QWAYLANDABSTRACTDECORATION_H diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index 90789b0dfc7..2a1339a79f4 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -66,12 +66,15 @@ QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) if (!hasCursorSize || cursorSize <= 0) cursorSize = 32; mCursorTheme = wl_cursor_theme_load(cursorTheme, cursorSize, mDisplay->shm()); + if (!mCursorTheme) + qDebug() << "Could not load theme" << cursorTheme; initCursorMap(); } QWaylandCursor::~QWaylandCursor() { - wl_cursor_theme_destroy(mCursorTheme); + if (mCursorTheme) + wl_cursor_theme_destroy(mCursorTheme); } struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape) @@ -160,6 +163,9 @@ wl_cursor *QWaylandCursor::requestCursor(WaylandCursor shape) //If the cursor has not been loaded already, load it if (!cursor) { + if (!mCursorTheme) + return NULL; + QList cursorNames = mCursorNamesMap.values(shape); foreach (QByteArray name, cursorNames) { cursor = wl_cursor_theme_get_cursor(mCursorTheme, name.constData()); diff --git a/src/plugins/platforms/wayland/qwaylanddatadevice.cpp b/src/plugins/platforms/wayland/qwaylanddatadevice.cpp index 74f879f972d..83e74ce6ca9 100644 --- a/src/plugins/platforms/wayland/qwaylanddatadevice.cpp +++ b/src/plugins/platforms/wayland/qwaylanddatadevice.cpp @@ -60,6 +60,7 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice) : QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat())) , m_display(manager->display()) + , m_inputDevice(inputDevice) , m_enterSerial(0) , m_dragWindow(0) , m_dragPoint() @@ -92,7 +93,7 @@ void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source) m_selectionSource.reset(source); if (source) connect(source, &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::selectionSourceCancelled); - set_selection(source ? source->object() : 0, 0 /* TODO m_display->serial() */); + set_selection(source ? source->object() : Q_NULLPTR, m_inputDevice->serial()); } QWaylandDataOffer *QWaylandDataDevice::dragOffer() const diff --git a/src/plugins/platforms/wayland/qwaylanddatadevice_p.h b/src/plugins/platforms/wayland/qwaylanddatadevice_p.h index dae91290ebf..ef82d84ddb3 100644 --- a/src/plugins/platforms/wayland/qwaylanddatadevice_p.h +++ b/src/plugins/platforms/wayland/qwaylanddatadevice_p.h @@ -88,7 +88,7 @@ private Q_SLOTS: private: QWaylandDisplay *m_display; - + QWaylandInputDevice *m_inputDevice; uint32_t m_enterSerial; QWindow *m_dragWindow; QPoint m_dragPoint; diff --git a/src/plugins/platforms/wayland/qwaylanddecorationfactory.cpp b/src/plugins/platforms/wayland/qwaylanddecorationfactory.cpp new file mode 100644 index 00000000000..6f1f74693fe --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddecorationfactory.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddecorationfactory_p.h" +#include "qwaylanddecorationplugin_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QWaylandDecorationFactoryInterface_iid, QLatin1String("/wayland-decoration-client"), Qt::CaseInsensitive)) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, + (QWaylandDecorationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) +#endif + +QStringList QWaylandDecorationFactory::keys(const QString &pluginPath) +{ +#ifndef QT_NO_LIBRARY + QStringList list; + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + list = directLoader()->keyMap().values(); + if (!list.isEmpty()) { + const QString postFix = QStringLiteral(" (from ") + + QDir::toNativeSeparators(pluginPath) + + QLatin1Char(')'); + const QStringList::iterator end = list.end(); + for (QStringList::iterator it = list.begin(); it != end; ++it) + (*it).append(postFix); + } + } + list.append(loader()->keyMap().values()); + return list; +#else + return QStringList(); +#endif +} + +QWaylandAbstractDecoration *QWaylandDecorationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath) +{ +#ifndef QT_NO_LIBRARY + // Try loading the plugin from platformPluginPath first: + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + if (QWaylandAbstractDecoration *ret = qLoadPlugin1(directLoader(), name, args)) + return ret; + } + if (QWaylandAbstractDecoration *ret = qLoadPlugin1(loader(), name, args)) + return ret; +#endif + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddecorationfactory_p.h b/src/plugins/platforms/wayland/qwaylanddecorationfactory_p.h new file mode 100644 index 00000000000..a7729bcafda --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddecorationfactory_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDECORATIONFACTORY_H +#define QWAYLANDDECORATIONFACTORY_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWaylandAbstractDecoration; + +class Q_WAYLAND_CLIENT_EXPORT QWaylandDecorationFactory +{ +public: + static QStringList keys(const QString &pluginPath = QString()); + static QWaylandAbstractDecoration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString()); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDDECORATIONFACTORY_H diff --git a/src/plugins/platforms/wayland/qwaylanddecorationplugin.cpp b/src/plugins/platforms/wayland/qwaylanddecorationplugin.cpp new file mode 100644 index 00000000000..edad5f5f0af --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddecorationplugin.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddecorationplugin_p.h" + +QT_BEGIN_NAMESPACE + +QWaylandDecorationPlugin::QWaylandDecorationPlugin(QObject *parent) + : QObject(parent) +{ +} +QWaylandDecorationPlugin::~QWaylandDecorationPlugin() +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddecorationplugin_p.h b/src/plugins/platforms/wayland/qwaylanddecorationplugin_p.h new file mode 100644 index 00000000000..6ed8935db2a --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddecorationplugin_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, 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. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDECORATIONPLUGIN_H +#define QWAYLANDDECORATIONPLUGIN_H + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QWaylandAbstractDecoration; + +#define QWaylandDecorationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandDecorationFactoryInterface.5.4" + +class Q_WAYLAND_CLIENT_EXPORT QWaylandDecorationPlugin : public QObject +{ + Q_OBJECT +public: + explicit QWaylandDecorationPlugin(QObject *parent = 0); + ~QWaylandDecorationPlugin(); + + virtual QWaylandAbstractDecoration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDDECORATIONPLUGIN_H diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index c4a702d74a8..023050326e7 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -159,6 +159,7 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) init(registry); connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests())); + connect(mEventThreadObject, &QWaylandEventThread::fatalError, this, &QWaylandDisplay::exitWithError); mWindowManagerIntegration.reset(new QWaylandWindowManagerIntegration(this)); @@ -177,8 +178,10 @@ QWaylandDisplay::~QWaylandDisplay(void) void QWaylandDisplay::flushRequests() { - if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) - mEventThreadObject->checkErrorAndExit(); + if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) { + mEventThreadObject->checkError(); + exitWithError(); + } wl_display_flush(mDisplay); } @@ -186,8 +189,15 @@ void QWaylandDisplay::flushRequests() void QWaylandDisplay::blockingReadEvents() { - if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) - mEventThreadObject->checkErrorAndExit(); + if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) { + mEventThreadObject->checkError(); + exitWithError(); + } +} + +void QWaylandDisplay::exitWithError() +{ + ::exit(1); } QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const @@ -226,13 +236,14 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin struct ::wl_registry *registry = object(); if (interface == QStringLiteral("wl_output")) { - QWaylandScreen *screen = new QWaylandScreen(this, id); + QWaylandScreen *screen = new QWaylandScreen(this, version, id); mScreens.append(screen); // We need to get the output events before creating surfaces forceRoundTrip(); mWaylandIntegration->screenAdded(screen); } else if (interface == QStringLiteral("wl_compositor")) { - mCompositor.init(registry, id, 3); + mCompositorVersion = qMin((int)version, 3); + mCompositor.init(registry, id, mCompositorVersion); } else if (interface == QStringLiteral("wl_shm")) { mShm = static_cast(wl_registry_bind(registry, id, &wl_shm_interface,1)); } else if (interface == QStringLiteral("xdg_shell") @@ -241,7 +252,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin } else if (interface == QStringLiteral("wl_shell")){ mShell.reset(new QtWayland::wl_shell(registry, id, 1)); } else if (interface == QStringLiteral("wl_seat")) { - QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, id); + QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, version, id); mInputDevices.append(inputDevice); } else if (interface == QStringLiteral("wl_data_device_manager")) { mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 05bd7f15a76..2f12ee7f9b3 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -117,6 +117,7 @@ public: const struct wl_compositor *wl_compositor() const { return mCompositor.object(); } QtWayland::wl_compositor *compositor() { return &mCompositor; } + int compositorVersion() const { return mCompositorVersion; } QtWayland::wl_shell *shell() { return mShell.data(); } QtWayland::xdg_shell *shellXdg(); @@ -165,6 +166,7 @@ public slots: private: void waitForScreens(); + void exitWithError(); struct Listener { RegistryListener listener; @@ -198,6 +200,7 @@ private: int mWritableNotificationFd; bool mScreensInitialized; QList mGlobals; + int mCompositorVersion; void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE; void registry_global_remove(uint32_t id) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/wayland/qwaylandeventthread.cpp b/src/plugins/platforms/wayland/qwaylandeventthread.cpp index b7266765e61..22efd6a2a72 100644 --- a/src/plugins/platforms/wayland/qwaylandeventthread.cpp +++ b/src/plugins/platforms/wayland/qwaylandeventthread.cpp @@ -73,7 +73,7 @@ void QWaylandEventThread::displayConnect() // ### be careful what you do, this function may also be called from other // threads to clean up & exit. -void QWaylandEventThread::checkErrorAndExit() +void QWaylandEventThread::checkError() const { int ecode = wl_display_get_error(m_display); if ((ecode == EPIPE || ecode == ECONNRESET)) { @@ -82,13 +82,16 @@ void QWaylandEventThread::checkErrorAndExit() } else { qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); } - ::exit(1); } void QWaylandEventThread::readWaylandEvents() { - if (wl_display_dispatch(m_display) < 0) - checkErrorAndExit(); + if (wl_display_dispatch(m_display) < 0) { + checkError(); + m_readNotifier->setEnabled(false); + emit fatalError(); + return; + } emit newEventsRead(); } diff --git a/src/plugins/platforms/wayland/qwaylandeventthread_p.h b/src/plugins/platforms/wayland/qwaylandeventthread_p.h index d51d627b962..2df4b05c2e5 100644 --- a/src/plugins/platforms/wayland/qwaylandeventthread_p.h +++ b/src/plugins/platforms/wayland/qwaylandeventthread_p.h @@ -63,7 +63,7 @@ public: wl_display *display() const; - void checkErrorAndExit(); + void checkError() const; private slots: void readWaylandEvents(); @@ -72,6 +72,7 @@ private slots: signals: void newEventsRead(); + void fatalError(); private: diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 4f72d6146e8..43c5807d419 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -157,9 +157,9 @@ QWaylandInputDevice::Touch::~Touch() wl_touch_destroy(object()); } -QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id) +QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id) : QObject() - , QtWayland::wl_seat(display->wl_registry(), id, 2) + , QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 2)) , mQDisplay(display) , mDisplay(display->wl_display()) , mCaps(0) @@ -770,6 +770,17 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, void QWaylandInputDevice::Keyboard::repeatKey() { mRepeatTimer.setInterval(25); + QWindowSystemInterface::handleExtendedKeyEvent(mFocus->window(), + mRepeatTime, QEvent::KeyRelease, mRepeatKey, + modifiers(), + mRepeatCode, +#ifndef QT_NO_WAYLAND_XKB + mRepeatSym, mNativeModifiers, +#else + 0, 0, +#endif + mRepeatText, true); + QWindowSystemInterface::handleExtendedKeyEvent(mFocus->window(), mRepeatTime, QEvent::KeyPress, mRepeatKey, modifiers(), diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h index 0c6ecfb640d..f1c2645456a 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h @@ -81,7 +81,7 @@ public: class Pointer; class Touch; - QWaylandInputDevice(QWaylandDisplay *display, uint32_t id); + QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id); ~QWaylandInputDevice(); uint32_t capabilities() const { return mCaps; } diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index ad99c67b9f3..27613eef714 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -181,12 +181,14 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) cons return new QWaylandShmWindow(window); } +#ifndef QT_NO_OPENGL QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { if (mDisplay->clientBufferIntegration()) return mDisplay->clientBufferIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle()); return 0; } +#endif // QT_NO_OPENGL QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const { @@ -367,12 +369,12 @@ void QWaylandIntegration::initializeShellIntegration() } } -QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, uint32_t id) +QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id) { if (mInputDeviceIntegration) { - return mInputDeviceIntegration->createInputDevice(display, id); + return mInputDeviceIntegration->createInputDevice(display, version, id); } - return new QWaylandInputDevice(display, id); + return new QWaylandInputDevice(display, version, id); } void QWaylandIntegration::initializeInputDeviceIntegration() diff --git a/src/plugins/platforms/wayland/qwaylandintegration_p.h b/src/plugins/platforms/wayland/qwaylandintegration_p.h index 9741b1a786d..c0909418e76 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration_p.h +++ b/src/plugins/platforms/wayland/qwaylandintegration_p.h @@ -63,7 +63,9 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; +#ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; +#endif QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; QAbstractEventDispatcher *createEventDispatcher() const; @@ -91,7 +93,7 @@ public: QPlatformTheme *createPlatformTheme(const QString &name) const; - QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, uint32_t id); + QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, int version, uint32_t id); virtual QWaylandClientBufferIntegration *clientBufferIntegration() const; virtual QWaylandServerBufferIntegration *serverBufferIntegration() const; diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 88667ae0d4f..6e48c442e43 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -53,14 +53,15 @@ QT_BEGIN_NAMESPACE -QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id) +QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id) : QPlatformScreen() - , QtWayland::wl_output(waylandDisplay->wl_registry(), id, 2) + , QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2)) , m_outputId(id) , mWaylandDisplay(waylandDisplay) , mExtendedOutput(0) , mDepth(32) , mRefreshRate(60000) + , mTransform(-1) , mFormat(QImage::Format_ARGB32_Premultiplied) , mOutputName(QStringLiteral("Screen%1").arg(id)) , m_orientation(Qt::PrimaryOrientation) @@ -178,29 +179,7 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y, Q_UNUSED(subpixel); Q_UNUSED(make); - bool isPortrait = height > width; - switch (transform) { - 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; - } - - QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); + mTransform = transform; if (!model.isEmpty()) mOutputName = model; @@ -214,6 +193,33 @@ void QWaylandScreen::output_done() // the done event is sent after all the geometry and the mode events are sent, // and the last mode event to be sent is the active one, so we can trust the // values of mGeometry and mRefreshRate here + + 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; + } + + QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); + mTransform = -1; + } QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry, mGeometry); QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate()); } diff --git a/src/plugins/platforms/wayland/qwaylandscreen_p.h b/src/plugins/platforms/wayland/qwaylandscreen_p.h index 866ac26ea2c..d3173e0c9a1 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen_p.h +++ b/src/plugins/platforms/wayland/qwaylandscreen_p.h @@ -56,7 +56,7 @@ class QWaylandExtendedOutput; class Q_WAYLAND_CLIENT_EXPORT QWaylandScreen : public QPlatformScreen, QtWayland::wl_output { public: - QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id); + QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id); ~QWaylandScreen(); QWaylandDisplay *display() const; @@ -103,6 +103,7 @@ private: QRect mGeometry; int mDepth; int mRefreshRate; + int mTransform; QImage::Format mFormat; QSize mPhysicalSize; QString mOutputName; diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index 14e1285d37b..d407335d3f7 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -42,7 +42,7 @@ #include "qwaylandwindow_p.h" #include "qwaylanddisplay_p.h" #include "qwaylandscreen_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include #include @@ -140,6 +140,9 @@ QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window) QWaylandShmBackingStore::~QWaylandShmBackingStore() { + if (QWaylandWindow *w = waylandWindow()) + w->setBackingStore(Q_NULLPTR); + if (mFrameCallback) wl_callback_destroy(mFrameCallback); @@ -175,6 +178,14 @@ void QWaylandShmBackingStore::endPaint() waylandWindow()->setCanResize(true); } +void QWaylandShmBackingStore::hidden() +{ + if (mFrameCallback) { + wl_callback_destroy(mFrameCallback); + mFrameCallback = Q_NULLPTR; + } +} + void QWaylandShmBackingStore::ensureSize() { waylandWindow()->setBackingStore(this); @@ -295,7 +306,7 @@ void QWaylandShmBackingStore::updateDecorations() decorationPainter.drawImage(target, sourceImage, target); } -QWaylandDecoration *QWaylandShmBackingStore::windowDecoration() const +QWaylandAbstractDecoration *QWaylandShmBackingStore::windowDecoration() const { return waylandWindow()->decoration(); } @@ -312,6 +323,7 @@ QWaylandWindow *QWaylandShmBackingStore::waylandWindow() const return static_cast(window()->handle()); } +#ifndef QT_NO_OPENGL QImage QWaylandShmBackingStore::toImage() const { // Invoked from QPlatformBackingStore::composeAndFlush() that is called @@ -320,6 +332,7 @@ QImage QWaylandShmBackingStore::toImage() const return *contentSurface(); } +#endif // QT_NO_OPENGL void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time) { diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index 33f363f6873..1212e52fe33 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE class QWaylandDisplay; -class QWaylandDecoration; +class QWaylandAbstractDecoration; class QWaylandWindow; class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer { @@ -82,8 +82,9 @@ public: void resize(const QSize &size); void beginPaint(const QRegion &); void endPaint(); + void hidden(); - QWaylandDecoration *windowDecoration() const; + QWaylandAbstractDecoration *windowDecoration() const; QMargins windowDecorationMargins() const; QImage *entireSurface() const; @@ -93,7 +94,9 @@ public: QWaylandWindow *waylandWindow() const; void iterateBuffer(); +#ifndef QT_NO_OPENGL QImage toImage() const Q_DECL_OVERRIDE; +#endif private: void updateDecorations(); diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index ec00d1af614..9f7bdda1fa9 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -50,9 +50,11 @@ #include "qwaylandwlshellsurface_p.h" #include "qwaylandxdgsurface_p.h" #include "qwaylandsubsurface_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" +#include "qwaylanddecorationfactory_p.h" +#include "qwaylandshmbackingstore_p.h" #include #include @@ -90,6 +92,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mMouseSerial(0) , mState(Qt::WindowNoState) , mMask() + , mBackingStore(Q_NULLPTR) { init(mDisplay->createSurface(static_cast(this))); @@ -249,6 +252,9 @@ void QWaylandWindow::setVisible(bool visible) if (!deleteGuard.isNull()) { attach(static_cast(0), 0, 0); commit(); + if (mBackingStore) { + mBackingStore->hidden(); + } } } } @@ -443,6 +449,9 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) { + if (mDisplay->compositorVersion() < 2) + return; + wl_output_transform transform; bool isPortrait = window()->screen() && window()->screen()->primaryOrientation() == Qt::PortraitOrientation; switch (orientation) { @@ -506,6 +515,7 @@ bool QWaylandWindow::createDecoration() if (!mDisplay->supportsWindowDecoration()) return false; + static bool decorationPluginFailed = false; bool decoration = false; switch (window()->type()) { case Qt::Window: @@ -523,9 +533,40 @@ bool QWaylandWindow::createDecoration() if (window()->flags() & Qt::BypassWindowManagerHint) decoration = false; - if (decoration) { - if (!mWindowDecoration) - mWindowDecoration = new QWaylandDecoration(this); + if (decoration && !decorationPluginFailed) { + if (!mWindowDecoration) { + QStringList decorations = QWaylandDecorationFactory::keys(); + if (decorations.empty()) { + qWarning() << "No decoration plugins available. Running with no decorations."; + decorationPluginFailed = true; + return false; + } + + QString targetKey; + QByteArray decorationPluginName = qgetenv("QT_WAYLAND_DECORATION"); + if (!decorationPluginName.isEmpty()) { + targetKey = QString::fromLocal8Bit(decorationPluginName); + if (!decorations.contains(targetKey)) { + qWarning() << "Requested decoration " << targetKey << " not found, falling back to default"; + targetKey = QString(); // fallthrough + } + } + + if (targetKey.isEmpty()) + targetKey = decorations.first(); // first come, first served. + + + mWindowDecoration = QWaylandDecorationFactory::create(targetKey, QStringList()); + if (!mWindowDecoration) { + qWarning() << "Could not create decoration from factory! Running with no decorations."; + decorationPluginFailed = true; + return false; + } + mWindowDecoration->setWaylandWindow(this); + if (subSurfaceWindow()) { + subSurfaceWindow()->adjustPositionOfChildren(); + } + } } else { delete mWindowDecoration; mWindowDecoration = 0; @@ -534,19 +575,11 @@ bool QWaylandWindow::createDecoration() return mWindowDecoration; } -QWaylandDecoration *QWaylandWindow::decoration() const +QWaylandAbstractDecoration *QWaylandWindow::decoration() const { return mWindowDecoration; } -void QWaylandWindow::setDecoration(QWaylandDecoration *decoration) -{ - mWindowDecoration = decoration; - if (subSurfaceWindow()) { - subSurfaceWindow()->adjustPositionOfChildren(); - } -} - static QWindow *topLevelWindow(QWindow *window) { while (QWindow *parent = window->parent()) @@ -695,7 +728,6 @@ bool QWaylandWindow::setWindowStateInternal(Qt::WindowState state) // QPlatformWindow::setWindowState returns, so we cannot rely on QWindow::windowState // here. We use then this mState variable. mState = state; - createDecoration(); if (mShellSurface) { switch (state) { diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 7da43c7b95f..0c55cd88d50 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -60,7 +60,7 @@ class QWaylandDisplay; class QWaylandBuffer; class QWaylandShellSurface; class QWaylandSubSurface; -class QWaylandDecoration; +class QWaylandAbstractDecoration; class QWaylandInputDevice; class QWaylandScreen; class QWaylandShmBackingStore; @@ -146,9 +146,7 @@ public: bool isExposed() const Q_DECL_OVERRIDE; void unfocus(); - QWaylandDecoration *decoration() const; - void setDecoration(QWaylandDecoration *decoration); - + QWaylandAbstractDecoration *decoration() const; void handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, @@ -201,7 +199,7 @@ protected: QWaylandShellSurface *mShellSurface; QWaylandSubSurface *mSubSurfaceWindow; - QWaylandDecoration *mWindowDecoration; + QWaylandAbstractDecoration *mWindowDecoration; bool mMouseEventsInContentArea; Qt::MouseButtons mMousePressedInContentArea; Qt::CursorShape m_cursorShape; diff --git a/src/plugins/platforms/wayland/qwaylandwlshellsurface.cpp b/src/plugins/platforms/wayland/qwaylandwlshellsurface.cpp index a8e89ec98c2..86115fa38b2 100644 --- a/src/plugins/platforms/wayland/qwaylandwlshellsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwlshellsurface.cpp @@ -44,7 +44,7 @@ #include "qwaylanddisplay_p.h" #include "qwaylandwindow_p.h" #include "qwaylandinputdevice_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandscreen_p.h" #include "qwaylandextendedsurface_p.h" diff --git a/src/plugins/platforms/wayland/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/qwaylandxdgshell.cpp index 8a96a0304b7..f31d63f4266 100644 --- a/src/plugins/platforms/wayland/qwaylandxdgshell.cpp +++ b/src/plugins/platforms/wayland/qwaylandxdgshell.cpp @@ -44,7 +44,6 @@ #include "qwaylanddisplay_p.h" #include "qwaylandwindow_p.h" #include "qwaylandinputdevice_p.h" -#include "qwaylanddecoration_p.h" #include "qwaylandscreen_p.h" #include diff --git a/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp b/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp index 126c9db72b3..318ff86d944 100644 --- a/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandxdgsurface.cpp @@ -44,7 +44,7 @@ #include "qwaylanddisplay_p.h" #include "qwaylandwindow_p.h" #include "qwaylandinputdevice_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandscreen_p.h" #include "qwaylandextendedsurface_p.h" diff --git a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp index c99bf2b4815..ae5ec40db2e 100644 --- a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp @@ -416,8 +416,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" class %s %s\n {\n", serverExport.constData(), interfaceName); printf(" public:\n"); - printf(" %s(struct ::wl_client *client, int id);\n", interfaceName); - printf(" %s(struct ::wl_display *display);\n", interfaceName); + printf(" %s(struct ::wl_client *client, int id, int version);\n", interfaceName); + printf(" %s(struct ::wl_display *display, int version);\n", interfaceName); printf(" %s();\n", interfaceName); printf("\n"); printf(" virtual ~%s();\n", interfaceName); @@ -432,16 +432,17 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" struct ::wl_resource *handle;\n"); printf("\n"); printf(" struct ::wl_client *client() const { return handle->client; }\n"); + printf(" int version() const { return wl_resource_get_version(handle); }\n"); printf("\n"); printf(" static Resource *fromResource(struct ::wl_resource *resource) { return static_cast(resource->data); }\n"); printf(" };\n"); printf("\n"); - printf(" void init(struct ::wl_client *client, int id);\n"); - printf(" void init(struct ::wl_display *display);\n"); + printf(" void init(struct ::wl_client *client, int id, int version);\n"); + printf(" void init(struct ::wl_display *display, int version);\n"); printf("\n"); - printf(" Resource *add(struct ::wl_client *client);\n"); - printf(" Resource *add(struct ::wl_client *client, int id);\n"); - printf(" Resource *add(struct wl_list *resource_list, struct ::wl_client *client, int id);\n"); + printf(" Resource *add(struct ::wl_client *client, int version);\n"); + printf(" Resource *add(struct ::wl_client *client, int id, int version);\n"); + printf(" Resource *add(struct wl_list *resource_list, struct ::wl_client *client, int id, int version);\n"); printf("\n"); printf(" Resource *resource() { return m_resource; }\n"); printf(" const Resource *resource() const { return m_resource; }\n"); @@ -491,7 +492,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n"); printf(" static void destroy_func(struct ::wl_resource *client_resource);\n"); printf("\n"); - printf(" Resource *bind(struct ::wl_client *client, uint32_t id);\n"); + printf(" Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n"); if (hasRequests) { printf("\n"); @@ -511,6 +512,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" QMultiMap m_resource_map;\n"); printf(" Resource *m_resource;\n"); printf(" struct ::wl_global *m_global;\n"); + printf(" uint32_t m_globalVersion;\n"); printf(" };\n"); if (j < interfaces.size() - 1) @@ -551,21 +553,21 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr QByteArray stripped = stripInterfaceName(interface.name, prefix); const char *interfaceNameStripped = stripped.constData(); - printf(" %s::%s(struct ::wl_client *client, int id)\n", interfaceName, interfaceName); + printf(" %s::%s(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName); printf(" : m_resource_map()\n"); printf(" , m_resource(0)\n"); printf(" , m_global(0)\n"); printf(" {\n"); - printf(" init(client, id);\n"); + printf(" init(client, id, version);\n"); printf(" }\n"); printf("\n"); - printf(" %s::%s(struct ::wl_display *display)\n", interfaceName, interfaceName); + printf(" %s::%s(struct ::wl_display *display, int version)\n", interfaceName, interfaceName); printf(" : m_resource_map()\n"); printf(" , m_resource(0)\n"); printf(" , m_global(0)\n"); printf(" {\n"); - printf(" init(display);\n"); + printf(" init(display, version);\n"); printf(" }\n"); printf("\n"); @@ -582,31 +584,32 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" }\n"); printf("\n"); - printf(" void %s::init(struct ::wl_client *client, int id)\n", interfaceName); + printf(" void %s::init(struct ::wl_client *client, int id, int version)\n", interfaceName); printf(" {\n"); - printf(" m_resource = bind(client, id);\n"); + printf(" m_resource = bind(client, id, version);\n"); printf(" }\n"); printf("\n"); - printf(" %s::Resource *%s::add(struct ::wl_client *client)\n", interfaceName, interfaceName); + printf(" %s::Resource *%s::add(struct ::wl_client *client, int version)\n", interfaceName, interfaceName); printf(" {\n"); - printf(" Resource *resource = bind(client, 0);\n"); + printf(" Resource *resource = bind(client, 0, version);\n"); printf(" m_resource_map.insert(client, resource);\n"); printf(" return resource;\n"); printf(" }\n"); printf("\n"); - printf(" %s::Resource *%s::add(struct ::wl_client *client, int id)\n", interfaceName, interfaceName); + printf(" %s::Resource *%s::add(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName); printf(" {\n"); - printf(" Resource *resource = bind(client, id);\n"); + printf(" Resource *resource = bind(client, id, version);\n"); printf(" m_resource_map.insert(client, resource);\n"); printf(" return resource;\n"); printf(" }\n"); printf("\n"); - printf(" void %s::init(struct ::wl_display *display)\n", interfaceName); + printf(" void %s::init(struct ::wl_display *display, int version)\n", interfaceName); printf(" {\n"); - printf(" m_global = wl_global_create(display, &::%s_interface, ::%s_interface.version, this, bind_func);\n", interfaceName, interfaceName); + printf(" m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName); + printf(" m_globalVersion = version;\n"); printf(" }\n"); printf("\n"); @@ -628,8 +631,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" void %s::bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id)\n", interfaceName); printf(" {\n"); - printf(" Q_UNUSED(version);\n"); - printf(" static_cast<%s *>(data)->add(client, id);\n", interfaceName); + printf(" %s *that = static_cast<%s *>(data);\n", interfaceName, interfaceName); + printf(" that->add(client, id, qMin(that->m_globalVersion, version));\n"); printf(" }\n"); printf("\n"); @@ -652,12 +655,12 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr //We should consider changing bind so that it doesn't special case id == 0 //and use function overloading instead. Jan do you have a lot of code dependent on this behavior? - printf(" %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id)\n", interfaceName, interfaceName); + printf(" %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName); printf(" {\n"); printf(" Resource *resource = %s_allocate();\n", interfaceNameStripped); printf(" resource->%s_object = this;\n", interfaceNameStripped); printf("\n"); - printf(" struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, ::%s_interface.version, id);\n", interfaceName, interfaceName); + printf(" struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, version, id);\n", interfaceName); printf(" wl_resource_set_implementation(handle, %s, resource, destroy_func);", interfaceMember.constData()); printf("\n"); printf(" resource->handle = handle;\n"); diff --git a/tests/auto/wayland/mockcompositor.cpp b/tests/auto/wayland/mockcompositor.cpp index cb0e6576e90..665b7dd738d 100644 --- a/tests/auto/wayland/mockcompositor.cpp +++ b/tests/auto/wayland/mockcompositor.cpp @@ -238,7 +238,7 @@ void Compositor::dispatchEvents(int timeout) static void compositor_create_surface(wl_client *client, wl_resource *compositorResource, uint32_t id) { Compositor *compositor = static_cast(compositorResource->data); - compositor->addSurface(new Surface(client, id, compositor)); + compositor->addSurface(new Surface(client, id, wl_resource_get_version(compositorResource), compositor)); } static void compositor_create_region(wl_client *client, wl_resource *compositorResource, uint32_t id) diff --git a/tests/auto/wayland/mockinput.cpp b/tests/auto/wayland/mockinput.cpp index fbe44de41cd..754aa45904a 100644 --- a/tests/auto/wayland/mockinput.cpp +++ b/tests/auto/wayland/mockinput.cpp @@ -101,7 +101,7 @@ void Compositor::sendKeyRelease(void *data, const QList ¶meters) } Seat::Seat(Compositor *compositor, struct ::wl_display *display) - : wl_seat(display) + : wl_seat(display, 2) , m_compositor(compositor) , m_keyboard(new Keyboard(compositor)) , m_pointer(new Pointer(compositor)) @@ -119,12 +119,12 @@ void Seat::seat_bind_resource(Resource *resource) void Seat::seat_get_keyboard(Resource *resource, uint32_t id) { - m_keyboard->add(resource->client(), id); + m_keyboard->add(resource->client(), id, resource->version()); } void Seat::seat_get_pointer(Resource *resource, uint32_t id) { - m_pointer->add(resource->client(), id); + m_pointer->add(resource->client(), id, resource->version()); } Keyboard::Keyboard(Compositor *compositor) @@ -240,7 +240,7 @@ DataDevice::~DataDevice() } DataDeviceManager::DataDeviceManager(Compositor *compositor, wl_display *display) - : wl_data_device_manager(display) + : wl_data_device_manager(display, 1) , m_compositor(compositor) { @@ -255,7 +255,7 @@ void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, { if (!m_data_device) m_data_device.reset(new DataDevice(m_compositor)); - m_data_device->add(resource->client(), id); + m_data_device->add(resource->client(), id, 1); } } diff --git a/tests/auto/wayland/mocksurface.cpp b/tests/auto/wayland/mocksurface.cpp index 2e4c2bc73a4..330213bdea9 100644 --- a/tests/auto/wayland/mocksurface.cpp +++ b/tests/auto/wayland/mocksurface.cpp @@ -44,8 +44,8 @@ namespace Impl { -Surface::Surface(wl_client *client, uint32_t id, Compositor *compositor) - : QtWaylandServer::wl_surface(client, id) +Surface::Surface(wl_client *client, uint32_t id, int v, Compositor *compositor) + : QtWaylandServer::wl_surface(client, id, v) , m_buffer(Q_NULLPTR) , m_compositor(compositor) , m_mockSurface(new MockSurface(this)) diff --git a/tests/auto/wayland/mocksurface.h b/tests/auto/wayland/mocksurface.h index f2a2f4eb355..33ced43854c 100644 --- a/tests/auto/wayland/mocksurface.h +++ b/tests/auto/wayland/mocksurface.h @@ -50,7 +50,7 @@ namespace Impl { class Surface : public QtWaylandServer::wl_surface { public: - Surface(wl_client *client, uint32_t id, Compositor *compositor); + Surface(wl_client *client, uint32_t id, int v, Compositor *compositor); ~Surface(); Compositor *compositor() const { return m_compositor; }