From abd71e1305f3811c04bf3b3f7075c53d44c7f4fe Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Aug 2014 16:04:23 +0200 Subject: [PATCH 01/13] Rename QWaylandDecoration => QWaylandAbstractDecoration This is in preparation for decoration plugins. Change-Id: Idb322a7a5cbc2eb5bf2cce019073f9f4fb46297f Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/client.pro | 4 +- ...ion.cpp => qwaylandabstractdecoration.cpp} | 40 +++++++++---------- ...ion_p.h => qwaylandabstractdecoration_p.h} | 20 +++++----- .../wayland/qwaylandshmbackingstore.cpp | 4 +- .../wayland/qwaylandshmbackingstore_p.h | 4 +- .../platforms/wayland/qwaylandwindow.cpp | 8 ++-- .../platforms/wayland/qwaylandwindow_p.h | 8 ++-- .../wayland/qwaylandwlshellsurface.cpp | 2 +- .../platforms/wayland/qwaylandxdgshell.cpp | 1 - .../platforms/wayland/qwaylandxdgsurface.cpp | 2 +- 10 files changed, 46 insertions(+), 47 deletions(-) rename src/plugins/platforms/wayland/{qwaylanddecoration.cpp => qwaylandabstractdecoration.cpp} (87%) rename src/plugins/platforms/wayland/{qwaylanddecoration_p.h => qwaylandabstractdecoration_p.h} (89%) diff --git a/src/plugins/platforms/wayland/client.pro b/src/plugins/platforms/wayland/client.pro index 6aaa2541980..ed14a460e0d 100644 --- a/src/plugins/platforms/wayland/client.pro +++ b/src/plugins/platforms/wayland/client.pro @@ -69,7 +69,7 @@ SOURCES += qwaylandintegration.cpp \ qwaylandtouch.cpp \ qwaylandqtkey.cpp \ ../shared/qwaylandmimehelper.cpp \ - qwaylanddecoration.cpp \ + qwaylandabstractdecoration.cpp \ qwaylandeventthread.cpp\ qwaylandwindowmanagerintegration.cpp \ qwaylandinputcontext.cpp \ @@ -100,7 +100,7 @@ HEADERS += qwaylandintegration_p.h \ qwaylandtouch_p.h \ qwaylandqtkey_p.h \ ../shared/qwaylandmimehelper.h \ - qwaylanddecoration_p.h \ + qwaylandabstractdecoration_p.h \ qwaylandeventthread_p.h \ qwaylandwindowmanagerintegration_p.h \ qwaylandinputcontext_p.h \ diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.cpp b/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp similarity index 87% rename from src/plugins/platforms/wayland/qwaylanddecoration.cpp rename to src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp index ed4978725a4..2781b42616c 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration.cpp +++ b/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandwindow_p.h" #include "qwaylandshellsurface_p.h" @@ -123,7 +123,7 @@ static const char * const qt_normalizeup_xpm[] = { # define BUTTON_WIDTH 22 #endif -QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window) +QWaylandAbstractDecoration::QWaylandAbstractDecoration(QWaylandWindow *window) : m_window(window->window()) , m_wayland_window(window) , m_isDirty(true) @@ -142,12 +142,12 @@ QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window) m_windowTitle.setTextOption(option); } -QWaylandDecoration::~QWaylandDecoration() +QWaylandAbstractDecoration::~QWaylandAbstractDecoration() { m_wayland_window->setDecoration(0); } -const QImage &QWaylandDecoration::contentImage() +const QImage &QWaylandAbstractDecoration::contentImage() { if (m_isDirty) { //Update the decoration backingstore @@ -162,12 +162,12 @@ const QImage &QWaylandDecoration::contentImage() return m_decorationContentImage; } -void QWaylandDecoration::update() +void QWaylandAbstractDecoration::update() { m_isDirty = true; } -void QWaylandDecoration::paint(QPaintDevice *device) +void QWaylandAbstractDecoration::paint(QPaintDevice *device) { QRect surfaceRect(QPoint(), window()->frameGeometry().size()); QRect clips[] = @@ -305,7 +305,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) #endif } -bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +bool QWaylandAbstractDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(global); @@ -335,7 +335,7 @@ bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPo return true; } -bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +bool QWaylandAbstractDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) { Q_UNUSED(inputDevice); Q_UNUSED(global); @@ -357,12 +357,12 @@ bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPo return handled; } -bool QWaylandDecoration::inMouseButtonPressedState() const +bool QWaylandAbstractDecoration::inMouseButtonPressedState() const { return m_mouseButtons & Qt::NoButton; } -void QWaylandDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons) +void QWaylandAbstractDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons) { if (isLeftClicked(buttons)) { m_wayland_window->shellSurface()->resize(inputDevice, resize); @@ -370,7 +370,7 @@ void QWaylandDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_s } } -void QWaylandDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) +void QWaylandAbstractDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) { if (isLeftClicked(buttons)) { m_wayland_window->shellSurface()->move(inputDevice); @@ -378,7 +378,7 @@ void QWaylandDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseBu } } -void QWaylandDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandAbstractDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(mods); if (local.y() <= m_margins.bottom()) { @@ -402,7 +402,7 @@ void QWaylandDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const } -void QWaylandDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandAbstractDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(mods); if (local.x() <= margins().left()) { @@ -420,7 +420,7 @@ void QWaylandDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, co } } -void QWaylandDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandAbstractDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(local); Q_UNUSED(mods); @@ -428,7 +428,7 @@ void QWaylandDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, cons startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b); } -void QWaylandDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandAbstractDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(local); Q_UNUSED(mods); @@ -436,33 +436,33 @@ void QWaylandDecoration::processMouseRight(QWaylandInputDevice *inputDevice, con startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b); } -bool QWaylandDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) +bool QWaylandAbstractDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) { if ((!m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) return true; return false; } -bool QWaylandDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) +bool QWaylandAbstractDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) { if ((m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) return true; return false; } -QRectF QWaylandDecoration::closeButtonRect() const +QRectF QWaylandAbstractDecoration::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 +QRectF QWaylandAbstractDecoration::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 +QRectF QWaylandAbstractDecoration::minimizeButtonRect() const { return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); diff --git a/src/plugins/platforms/wayland/qwaylanddecoration_p.h b/src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h similarity index 89% rename from src/plugins/platforms/wayland/qwaylanddecoration_p.h rename to src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h index c240b9c9d45..c94c9951acd 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration_p.h +++ b/src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QWAYLANDDECORATION_H -#define QWAYLANDDECORATION_H +#ifndef QWAYLANDABSTRACTDECORATION_H +#define QWAYLANDABSTRACTDECORATION_H #include #include @@ -65,11 +65,11 @@ class QWaylandScreen; class QWaylandWindow; class QWaylandInputDevice; -class Q_WAYLAND_CLIENT_EXPORT QWaylandDecoration +class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration { public: - QWaylandDecoration(QWaylandWindow *window); - virtual ~QWaylandDecoration(); + QWaylandAbstractDecoration(QWaylandWindow *window); + virtual ~QWaylandAbstractDecoration(); void update(); bool isDirty() const; @@ -115,26 +115,26 @@ private: QStaticText m_windowTitle; }; -inline bool QWaylandDecoration::isDirty() const +inline bool QWaylandAbstractDecoration::isDirty() const { return m_isDirty; } -inline QMargins QWaylandDecoration::margins() const +inline QMargins QWaylandAbstractDecoration::margins() const { return m_margins; } -inline QWindow *QWaylandDecoration::window() const +inline QWindow *QWaylandAbstractDecoration::window() const { return m_window; } -inline QWaylandWindow *QWaylandDecoration::waylandWindow() const +inline QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const { return m_wayland_window; } QT_END_NAMESPACE -#endif // QWAYLANDDECORATION_H +#endif // QWAYLANDABSTRACTDECORATION_H diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index 14e1285d37b..421fae91c6b 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 @@ -295,7 +295,7 @@ void QWaylandShmBackingStore::updateDecorations() decorationPainter.drawImage(target, sourceImage, target); } -QWaylandDecoration *QWaylandShmBackingStore::windowDecoration() const +QWaylandAbstractDecoration *QWaylandShmBackingStore::windowDecoration() const { return waylandWindow()->decoration(); } diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index 33f363f6873..5c3dbb5bc27 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 { @@ -83,7 +83,7 @@ public: void beginPaint(const QRegion &); void endPaint(); - QWaylandDecoration *windowDecoration() const; + QWaylandAbstractDecoration *windowDecoration() const; QMargins windowDecorationMargins() const; QImage *entireSurface() const; diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index aaef58d997a..c900b98db6c 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -50,7 +50,7 @@ #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" @@ -505,7 +505,7 @@ bool QWaylandWindow::createDecoration() if (decoration) { if (!mWindowDecoration) - mWindowDecoration = new QWaylandDecoration(this); + mWindowDecoration = new QWaylandAbstractDecoration(this); } else { delete mWindowDecoration; mWindowDecoration = 0; @@ -514,12 +514,12 @@ bool QWaylandWindow::createDecoration() return mWindowDecoration; } -QWaylandDecoration *QWaylandWindow::decoration() const +QWaylandAbstractDecoration *QWaylandWindow::decoration() const { return mWindowDecoration; } -void QWaylandWindow::setDecoration(QWaylandDecoration *decoration) +void QWaylandWindow::setDecoration(QWaylandAbstractDecoration *decoration) { mWindowDecoration = decoration; if (subSurfaceWindow()) { diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index dbb0af2e0aa..c2df0937cd1 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; @@ -144,8 +144,8 @@ public: bool isExposed() const Q_DECL_OVERRIDE; void unfocus(); - QWaylandDecoration *decoration() const; - void setDecoration(QWaylandDecoration *decoration); + QWaylandAbstractDecoration *decoration() const; + void setDecoration(QWaylandAbstractDecoration *decoration); void handleMouse(QWaylandInputDevice *inputDevice, @@ -199,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" From 9dca9722f0d677b4bd4c88ce6526c4c71f7d228f Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Aug 2014 16:31:05 +0200 Subject: [PATCH 02/13] QtWaylandClient: Pluginize window decorations. Convert to a D-pointer, split between abstract base class and an implementation. Also move implementation of the current built-in decoration to the "bradient" plugin, named in glorious memory of the programmer-designed blue gradient that will forever sear our eyeballs. The decoration plugin may be specified using the environment variable QT_WAYLAND_DECORATION. Change-Id: Idc99ab06ae138ad299bad2b62b9595379bd007ab Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/client.pro | 6 +- .../decorations/bradient/bradient.json | 3 + .../plugins/decorations/bradient/bradient.pro | 17 + .../plugins/decorations/bradient/main.cpp | 452 ++++++++++++++++++ .../plugins/decorations/decorations.pro | 3 + .../wayland/qwaylandabstractdecoration.cpp | 422 +++------------- .../wayland/qwaylandabstractdecoration_p.h | 75 +-- .../wayland/qwaylanddecorationfactory.cpp | 97 ++++ .../wayland/qwaylanddecorationfactory_p.h | 61 +++ .../wayland/qwaylanddecorationplugin.cpp | 54 +++ .../wayland/qwaylanddecorationplugin_p.h | 69 +++ .../platforms/wayland/qwaylandwindow.cpp | 37 +- 12 files changed, 885 insertions(+), 411 deletions(-) create mode 100644 src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.json create mode 100644 src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro create mode 100644 src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp create mode 100644 src/plugins/platforms/wayland/plugins/decorations/decorations.pro create mode 100644 src/plugins/platforms/wayland/qwaylanddecorationfactory.cpp create mode 100644 src/plugins/platforms/wayland/qwaylanddecorationfactory_p.h create mode 100644 src/plugins/platforms/wayland/qwaylanddecorationplugin.cpp create mode 100644 src/plugins/platforms/wayland/qwaylanddecorationplugin_p.h diff --git a/src/plugins/platforms/wayland/client.pro b/src/plugins/platforms/wayland/client.pro index ed14a460e0d..a8a1136eaa6 100644 --- a/src/plugins/platforms/wayland/client.pro +++ b/src/plugins/platforms/wayland/client.pro @@ -3,7 +3,7 @@ QT += core-private gui-private QT_FOR_PRIVATE += platformsupport-private MODULE=waylandclient -MODULE_PLUGIN_TYPES = wayland-graphics-integration-client +MODULE_PLUGIN_TYPES = wayland-graphics-integration-client wayland-decoration-client load(qt_module) @@ -70,6 +70,8 @@ SOURCES += qwaylandintegration.cpp \ qwaylandqtkey.cpp \ ../shared/qwaylandmimehelper.cpp \ qwaylandabstractdecoration.cpp \ + qwaylanddecorationfactory.cpp \ + qwaylanddecorationplugin.cpp \ qwaylandeventthread.cpp\ qwaylandwindowmanagerintegration.cpp \ qwaylandinputcontext.cpp \ @@ -101,6 +103,8 @@ HEADERS += qwaylandintegration_p.h \ qwaylandqtkey_p.h \ ../shared/qwaylandmimehelper.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/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/plugins/decorations/bradient/main.cpp b/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp new file mode 100644 index 00000000000..c249248c320 --- /dev/null +++ b/src/plugins/platforms/wayland/plugins/decorations/bradient/main.cpp @@ -0,0 +1,452 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#define BUTTON_SPACING 5 + +#ifndef QT_NO_IMAGEFORMAT_XPM +# define BUTTON_WIDTH 10 + +static const char * const qt_close_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +".##....##.", +"..##..##..", +"...####...", +"....##....", +"...####...", +"..##..##..", +".##....##.", +"..........", +".........."}; + +static const char * const qt_maximize_xpm[]={ +"10 10 2 1", +"# c #000000", +". c None", +"#########.", +"#########.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#.......#.", +"#########.", +".........."}; + +static const char * const qt_minimize_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"..........", +"..........", +"..........", +"..........", +"..........", +"..........", +"..........", +".#######..", +".#######..", +".........."}; + +static const char * const qt_normalizeup_xpm[] = { +"10 10 2 1", +"# c #000000", +". c None", +"...######.", +"...######.", +"...#....#.", +".######.#.", +".######.#.", +".#....###.", +".#....#...", +".#....#...", +".######...", +".........."}; +#else +# define BUTTON_WIDTH 22 +#endif + +class Q_WAYLAND_CLIENT_EXPORT QWaylandBradientDecoration : public QWaylandAbstractDecoration +{ +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); + + QTextOption option(Qt::AlignHCenter | Qt::AlignVCenter); + option.setWrapMode(QTextOption::NoWrap); + m_windowTitle.setTextOption(option); +} + +QRectF QWaylandBradientDecoration::closeButtonRect() const +{ + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); +} + +QRectF QWaylandBradientDecoration::maximizeButtonRect() const +{ + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); +} + +QRectF QWaylandBradientDecoration::minimizeButtonRect() const +{ + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); +} + +QMargins QWaylandBradientDecoration::margins() const +{ + return QMargins(3, 30, 3, 3); +} + +void QWaylandBradientDecoration::paint(QPaintDevice *device) +{ + QRect surfaceRect(QPoint(), window()->frameGeometry().size()); + QRect clips[] = + { + QRect(0, 0, surfaceRect.width(), margins().top()), + QRect(0, surfaceRect.height() - margins().bottom(), surfaceRect.width(), margins().bottom()), + QRect(0, margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()), + QRect(surfaceRect.width() - margins().right(), margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()) + }; + + QRect top = clips[0]; + + QPainter p(device); + p.setRenderHint(QPainter::Antialiasing); + + // Title bar + QPoint gradCenter(top.center()+ QPoint(30, 60)); + QLinearGradient grad(top.topLeft(), top.bottomLeft()); + QColor base(m_backgroundColor); + grad.setColorAt(0, base.lighter(100)); + grad.setColorAt(1, base.darker(180)); + QPainterPath roundedRect; + roundedRect.addRoundedRect(surfaceRect, 6, 6); + for (int i = 0; i < 4; ++i) { + p.save(); + p.setClipRect(clips[i]); + p.fillPath(roundedRect, grad); + p.restore(); + } + + // Window icon + QIcon icon = waylandWindow()->windowIcon(); + if (!icon.isNull()) { + QPixmap pixmap = icon.pixmap(QSize(128, 128)); + QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + QRectF iconRect(0, 0, 22, 22); + p.drawPixmap(iconRect.adjusted(margins().left() + BUTTON_SPACING, 4, + margins().left() + BUTTON_SPACING, 4), + scaled, iconRect); + } + + // Window title + QString windowTitleText = window()->title(); + if (!windowTitleText.isEmpty()) { + if (m_windowTitle.text() != windowTitleText) { + m_windowTitle.setText(windowTitleText); + m_windowTitle.prepare(); + } + + QRect titleBar = top; + titleBar.setLeft(margins().left() + BUTTON_SPACING + + (icon.isNull() ? 0 : 22 + BUTTON_SPACING)); + titleBar.setRight(minimizeButtonRect().left() - BUTTON_SPACING); + + p.save(); + p.setClipRect(titleBar); + p.setPen(m_foregroundColor); + QSizeF size = m_windowTitle.size(); + int dx = (top.width() - size.width()) /2; + int dy = (top.height()- size.height()) /2; + QFont font = p.font(); + font.setBold(true); + p.setFont(font); + QPoint windowTitlePoint(top.topLeft().x() + dx, + top.topLeft().y() + dy); + p.drawStaticText(windowTitlePoint, m_windowTitle); + p.restore(); + } + +#ifndef QT_NO_IMAGEFORMAT_XPM + p.save(); + + // Close button + QPixmap closePixmap(qt_close_xpm); + p.drawPixmap(closeButtonRect(), closePixmap, closePixmap.rect()); + + // Maximize button + QPixmap maximizePixmap(waylandWindow()->isMaximized() + ? qt_normalizeup_xpm : qt_maximize_xpm); + p.drawPixmap(maximizeButtonRect(), maximizePixmap, maximizePixmap.rect()); + + // Minimize button + QPixmap minimizePixmap(qt_minimize_xpm); + p.drawPixmap(minimizeButtonRect(), minimizePixmap, minimizePixmap.rect()); + + p.restore(); +#else + // We don't need antialiasing from now on + p.setRenderHint(QPainter::Antialiasing, false); + + QRectF rect; + + // Default pen + QPen pen(m_foregroundColor); + p.setPen(pen); + + // Close button + p.save(); + rect = closeButtonRect(); + p.drawRect(rect); + qreal crossSize = rect.height() / 2; + QPointF crossCenter(rect.center()); + QRectF crossRect(crossCenter.x() - crossSize / 2, crossCenter.y() - crossSize / 2, crossSize, crossSize); + pen.setWidth(2); + p.setPen(pen); + p.drawLine(crossRect.topLeft(), crossRect.bottomRight()); + p.drawLine(crossRect.bottomLeft(), crossRect.topRight()); + p.restore(); + + // Maximize button + p.save(); + p.drawRect(maximizeButtonRect()); + rect = maximizeButtonRect().adjusted(5, 5, -5, -5); + 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); + p.drawRect(rect2); + } else { + p.setPen(m_foregroundColor); + p.drawRect(rect); + p.drawLine(rect.left(), rect.top() + 1, rect.right(), rect.top() + 1); + } + p.restore(); + + // Minimize button + p.save(); + p.drawRect(minimizeButtonRect()); + rect = minimizeButtonRect().adjusted(5, 5, -5, -5); + pen.setWidth(2); + p.setPen(pen); + p.drawLine(rect.bottomLeft(), rect.bottomRight()); + p.restore(); +#endif +} + +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(window()); + } else if (maximizeButtonRect().contains(local) && isLeftClicked(b)) { + window()->setWindowState(waylandWindow()->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + } else if (minimizeButtonRect().contains(local) && isLeftClicked(b)) { + window()->setWindowState(Qt::WindowMinimized); + } else if (local.y() <= margins().top()) { + processMouseTop(inputDevice,local,b,mods); + } else if (local.y() > window()->height() - margins().bottom() + margins().top()) { + processMouseBottom(inputDevice,local,b,mods); + } else if (local.x() <= margins().left()) { + processMouseLeft(inputDevice,local,b,mods); + } else if (local.x() > window()->width() - margins().right() + margins().left()) { + processMouseRight(inputDevice,local,b,mods); + } else { + waylandWindow()->restoreMouseCursor(inputDevice); + setMouseButtons(b); + return false; + } + + setMouseButtons(b); + return true; +} + +bool QWaylandBradientDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(inputDevice); + Q_UNUSED(global); + Q_UNUSED(mods); + bool handled = state == Qt::TouchPointPressed; + if (handled) { + if (closeButtonRect().contains(local)) + QWindowSystemInterface::handleCloseEvent(window()); + else if (maximizeButtonRect().contains(local)) + window()->setWindowState(waylandWindow()->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + else if (minimizeButtonRect().contains(local)) + window()->setWindowState(Qt::WindowMinimized); + else if (local.y() <= margins().top()) + waylandWindow()->shellSurface()->move(inputDevice); + else + handled = false; + } + + return handled; +} + +void QWaylandBradientDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(mods); + if (local.y() <= margins().bottom()) { + if (local.x() <= margins().left()) { + //top left bit + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); + startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_LEFT,b); + } else if (local.x() > window()->width() - margins().right()) { + //top right bit + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); + startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_RIGHT,b); + } else { + //top reszie bit + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitVCursor); + startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP,b); + } + } else { + waylandWindow()->restoreMouseCursor(inputDevice); + startMove(inputDevice,b); + } + +} + +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 + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); + startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT,b); + } else if (local.x() > window()->width() - margins().right()) { + //bottom right bit + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); + startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT,b); + } else { + //bottom bit + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitVCursor); + startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_BOTTOM,b); + } +} + +void QWaylandBradientDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(local); + Q_UNUSED(mods); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitHCursor); + startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b); +} + +void QWaylandBradientDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(local); + Q_UNUSED(mods); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitHCursor); + startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b); +} + +class QWaylandBradientDecorationPlugin : public QWaylandDecorationPlugin +{ + 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(); +} + + +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 index 2781b42616c..e247dbbad4f 100644 --- a/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp +++ b/src/plugins/platforms/wayland/qwaylandabstractdecoration.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 ** @@ -41,431 +42,148 @@ #include "qwaylandabstractdecoration_p.h" +#include #include "qwaylandwindow_p.h" #include "qwaylandshellsurface_p.h" #include "qwaylandinputdevice_p.h" #include "qwaylandscreen_p.h" -#include #include -#include -#include -#include -#include QT_BEGIN_NAMESPACE -#define BUTTON_SPACING 5 +class QWaylandAbstractDecorationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandAbstractDecoration) -#ifndef QT_NO_IMAGEFORMAT_XPM -# define BUTTON_WIDTH 10 +public: + QWaylandAbstractDecorationPrivate(); + ~QWaylandAbstractDecorationPrivate(); -static const char * const qt_close_xpm[] = { -"10 10 2 1", -"# c #000000", -". c None", -"..........", -".##....##.", -"..##..##..", -"...####...", -"....##....", -"...####...", -"..##..##..", -".##....##.", -"..........", -".........."}; + QWindow *m_window; + QWaylandWindow *m_wayland_window; -static const char * const qt_maximize_xpm[]={ -"10 10 2 1", -"# c #000000", -". c None", -"#########.", -"#########.", -"#.......#.", -"#.......#.", -"#.......#.", -"#.......#.", -"#.......#.", -"#.......#.", -"#########.", -".........."}; + bool m_isDirty; + QImage m_decorationContentImage; -static const char * const qt_minimize_xpm[] = { -"10 10 2 1", -"# c #000000", -". c None", -"..........", -"..........", -"..........", -"..........", -"..........", -"..........", -"..........", -".#######..", -".#######..", -".........."}; + Qt::MouseButtons m_mouseButtons; +}; -static const char * const qt_normalizeup_xpm[] = { -"10 10 2 1", -"# c #000000", -". c None", -"...######.", -"...######.", -"...#....#.", -".######.#.", -".######.#.", -".#....###.", -".#....#...", -".#....#...", -".######...", -".........."}; -#else -# define BUTTON_WIDTH 22 -#endif - -QWaylandAbstractDecoration::QWaylandAbstractDecoration(QWaylandWindow *window) - : m_window(window->window()) - , m_wayland_window(window) +QWaylandAbstractDecorationPrivate::QWaylandAbstractDecorationPrivate() + : m_window(0) + , m_wayland_window(0) , m_isDirty(true) , m_decorationContentImage(0) - , m_margins(3,30,3,3) , m_mouseButtons(Qt::NoButton) { - m_wayland_window->setDecoration(this); - - QPalette palette; - m_foregroundColor = palette.color(QPalette::Active, QPalette::HighlightedText); - m_backgroundColor = palette.color(QPalette::Active, QPalette::Highlight); - - QTextOption option(Qt::AlignHCenter | Qt::AlignVCenter); - option.setWrapMode(QTextOption::NoWrap); - m_windowTitle.setTextOption(option); } -QWaylandAbstractDecoration::~QWaylandAbstractDecoration() +QWaylandAbstractDecorationPrivate::~QWaylandAbstractDecorationPrivate() { m_wayland_window->setDecoration(0); } +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; + d->m_wayland_window->setDecoration(this); +} + const QImage &QWaylandAbstractDecoration::contentImage() { - if (m_isDirty) { + Q_D(QWaylandAbstractDecoration); + if (d->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); + d->m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); + d->m_decorationContentImage.fill(Qt::transparent); + this->paint(&d->m_decorationContentImage); - m_isDirty = false; + d->m_isDirty = false; } - return m_decorationContentImage; + return d->m_decorationContentImage; } void QWaylandAbstractDecoration::update() { - m_isDirty = true; + Q_D(QWaylandAbstractDecoration); + d->m_isDirty = true; } -void QWaylandAbstractDecoration::paint(QPaintDevice *device) +void QWaylandAbstractDecoration::setMouseButtons(Qt::MouseButtons mb) { - QRect surfaceRect(QPoint(), window()->frameGeometry().size()); - QRect clips[] = - { - QRect(0, 0, surfaceRect.width(), margins().top()), - QRect(0, surfaceRect.height() - margins().bottom(), surfaceRect.width(), margins().bottom()), - QRect(0, margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()), - QRect(surfaceRect.width() - margins().right(), margins().top(), margins().left(), surfaceRect.height() - margins().top() - margins().bottom()) - }; - - QRect top = clips[0]; - - QPainter p(device); - p.setRenderHint(QPainter::Antialiasing); - - // Title bar - QPoint gradCenter(top.center()+ QPoint(30, 60)); - QLinearGradient grad(top.topLeft(), top.bottomLeft()); - QColor base(m_backgroundColor); - grad.setColorAt(0, base.lighter(100)); - grad.setColorAt(1, base.darker(180)); - QPainterPath roundedRect; - roundedRect.addRoundedRect(surfaceRect, 6, 6); - for (int i = 0; i < 4; ++i) { - p.save(); - p.setClipRect(clips[i]); - p.fillPath(roundedRect, grad); - p.restore(); - } - - // Window icon - QIcon icon = m_wayland_window->windowIcon(); - if (!icon.isNull()) { - QPixmap pixmap = icon.pixmap(QSize(128, 128)); - QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - - QRectF iconRect(0, 0, 22, 22); - p.drawPixmap(iconRect.adjusted(margins().left() + BUTTON_SPACING, 4, - margins().left() + BUTTON_SPACING, 4), - scaled, iconRect); - } - - // Window title - QString windowTitleText = window()->title(); - if (!windowTitleText.isEmpty()) { - if (m_windowTitle.text() != windowTitleText) { - m_windowTitle.setText(windowTitleText); - m_windowTitle.prepare(); - } - - QRect titleBar = top; - titleBar.setLeft(m_margins.left() + BUTTON_SPACING + - (icon.isNull() ? 0 : 22 + BUTTON_SPACING)); - titleBar.setRight(minimizeButtonRect().left() - BUTTON_SPACING); - - p.save(); - p.setClipRect(titleBar); - p.setPen(m_foregroundColor); - QSizeF size = m_windowTitle.size(); - int dx = (top.width() - size.width()) /2; - int dy = (top.height()- size.height()) /2; - QFont font = p.font(); - font.setBold(true); - p.setFont(font); - QPoint windowTitlePoint(top.topLeft().x() + dx, - top.topLeft().y() + dy); - p.drawStaticText(windowTitlePoint,m_windowTitle); - p.restore(); - } - -#ifndef QT_NO_IMAGEFORMAT_XPM - p.save(); - - // Close button - QPixmap closePixmap(qt_close_xpm); - p.drawPixmap(closeButtonRect(), closePixmap, closePixmap.rect()); - - // Maximize button - QPixmap maximizePixmap(m_wayland_window->isMaximized() - ? qt_normalizeup_xpm : qt_maximize_xpm); - p.drawPixmap(maximizeButtonRect(), maximizePixmap, maximizePixmap.rect()); - - // Minimize button - QPixmap minimizePixmap(qt_minimize_xpm); - p.drawPixmap(minimizeButtonRect(), minimizePixmap, minimizePixmap.rect()); - - p.restore(); -#else - // We don't need antialiasing from now on - p.setRenderHint(QPainter::Antialiasing, false); - - QRectF rect; - - // Default pen - QPen pen(m_foregroundColor); - p.setPen(pen); - - // Close button - p.save(); - rect = closeButtonRect(); - p.drawRect(rect); - qreal crossSize = rect.height() / 2; - QPointF crossCenter(rect.center()); - QRectF crossRect(crossCenter.x() - crossSize / 2, crossCenter.y() - crossSize / 2, crossSize, crossSize); - pen.setWidth(2); - p.setPen(pen); - p.drawLine(crossRect.topLeft(), crossRect.bottomRight()); - p.drawLine(crossRect.bottomLeft(), crossRect.topRight()); - p.restore(); - - // Maximize button - p.save(); - p.drawRect(maximizeButtonRect()); - rect = maximizeButtonRect().adjusted(5, 5, -5, -5); - if (m_wayland_window->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); - p.drawRect(rect2); - } else { - p.setPen(m_foregroundColor); - p.drawRect(rect); - p.drawLine(rect.left(), rect.top() + 1, rect.right(), rect.top() + 1); - } - p.restore(); - - // Minimize button - p.save(); - p.drawRect(minimizeButtonRect()); - rect = minimizeButtonRect().adjusted(5, 5, -5, -5); - pen.setWidth(2); - p.setPen(pen); - p.drawLine(rect.bottomLeft(), rect.bottomRight()); - p.restore(); -#endif -} - -bool QWaylandAbstractDecoration::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); - } else if (maximizeButtonRect().contains(local) && isLeftClicked(b)) { - m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); - } else if (minimizeButtonRect().contains(local) && isLeftClicked(b)) { - m_window->setWindowState(Qt::WindowMinimized); - } else if (local.y() <= m_margins.top()) { - processMouseTop(inputDevice,local,b,mods); - } else if (local.y() > m_window->height() - m_margins.bottom() + m_margins.top()) { - processMouseBottom(inputDevice,local,b,mods); - } else if (local.x() <= m_margins.left()) { - processMouseLeft(inputDevice,local,b,mods); - } else if (local.x() > m_window->width() - m_margins.right() + m_margins.left()) { - processMouseRight(inputDevice,local,b,mods); - } else { - m_wayland_window->restoreMouseCursor(inputDevice); - m_mouseButtons = b; - return false; - } - - m_mouseButtons = b; - return true; -} - -bool QWaylandAbstractDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) -{ - Q_UNUSED(inputDevice); - Q_UNUSED(global); - Q_UNUSED(mods); - bool handled = state == Qt::TouchPointPressed; - if (handled) { - if (closeButtonRect().contains(local)) - QWindowSystemInterface::handleCloseEvent(m_window); - else if (maximizeButtonRect().contains(local)) - m_window->setWindowState(m_wayland_window->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); - else - handled = false; - } - - return handled; -} - -bool QWaylandAbstractDecoration::inMouseButtonPressedState() const -{ - return m_mouseButtons & Qt::NoButton; + 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)) { - m_wayland_window->shellSurface()->resize(inputDevice, resize); + 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)) { - m_wayland_window->shellSurface()->move(inputDevice); + d->m_wayland_window->shellSurface()->move(inputDevice); inputDevice->removeMouseButtonFromState(Qt::LeftButton); } } -void QWaylandAbstractDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) -{ - Q_UNUSED(mods); - if (local.y() <= m_margins.bottom()) { - if (local.x() <= margins().left()) { - //top left bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); - startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_LEFT,b); - } else if (local.x() > m_window->width() - margins().right()) { - //top right bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); - startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_RIGHT,b); - } else { - //top reszie bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor); - startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP,b); - } - } else { - m_wayland_window->restoreMouseCursor(inputDevice); - startMove(inputDevice,b); - } - -} - -void QWaylandAbstractDecoration::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); - startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT,b); - } else if (local.x() > m_window->width() - margins().right()) { - //bottom right bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); - startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT,b); - } else { - //bottom bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor); - startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_BOTTOM,b); - } -} - -void QWaylandAbstractDecoration::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); - startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b); -} - -void QWaylandAbstractDecoration::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); - startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b); -} - bool QWaylandAbstractDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) { - if ((!m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) + Q_D(QWaylandAbstractDecoration); + if ((!d->m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) return true; return false; } bool QWaylandAbstractDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) { - if ((m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) + Q_D(QWaylandAbstractDecoration); + if ((d->m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) return true; return false; } -QRectF QWaylandAbstractDecoration::closeButtonRect() const +bool QWaylandAbstractDecoration::isDirty() const { - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); + Q_D(const QWaylandAbstractDecoration); + return d->m_isDirty; } -QRectF QWaylandAbstractDecoration::maximizeButtonRect() const +QWindow *QWaylandAbstractDecoration::window() const { - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); + Q_D(const QWaylandAbstractDecoration); + return d->m_window; } -QRectF QWaylandAbstractDecoration::minimizeButtonRect() const +QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const { - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); + Q_D(const QWaylandAbstractDecoration); + return d->m_wayland_window; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h b/src/plugins/platforms/wayland/qwaylandabstractdecoration_p.h index c94c9951acd..6171cab14cb 100644 --- a/src/plugins/platforms/wayland/qwaylandabstractdecoration_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 ** @@ -64,77 +65,41 @@ class QEvent; class QWaylandScreen; class QWaylandWindow; class QWaylandInputDevice; +class QWaylandAbstractDecorationPrivate; -class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration +class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration : public QObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandAbstractDecoration) public: - QWaylandAbstractDecoration(QWaylandWindow *window); + 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 QWaylandAbstractDecoration::isDirty() const -{ - return m_isDirty; -} - -inline QMargins QWaylandAbstractDecoration::margins() const -{ - return m_margins; -} - -inline QWindow *QWaylandAbstractDecoration::window() const -{ - return m_window; -} - -inline QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const -{ - return m_wayland_window; -} - QT_END_NAMESPACE #endif // QWAYLANDABSTRACTDECORATION_H 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/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index c900b98db6c..2fc904aadd1 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -53,6 +53,7 @@ #include "qwaylandabstractdecoration_p.h" #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" +#include "qwaylanddecorationfactory_p.h" #include #include @@ -486,6 +487,7 @@ bool QWaylandWindow::createDecoration() if (!mDisplay->supportsWindowDecoration()) return false; + static bool decorationPluginFailed = false; bool decoration = false; switch (window()->type()) { case Qt::Window: @@ -503,9 +505,37 @@ bool QWaylandWindow::createDecoration() if (window()->flags() & Qt::BypassWindowManagerHint) decoration = false; - if (decoration) { - if (!mWindowDecoration) - mWindowDecoration = new QWaylandAbstractDecoration(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); + } } else { delete mWindowDecoration; mWindowDecoration = 0; @@ -519,6 +549,7 @@ QWaylandAbstractDecoration *QWaylandWindow::decoration() const return mWindowDecoration; } +// ### can't this go away? we directly set up our decorations, after all void QWaylandWindow::setDecoration(QWaylandAbstractDecoration *decoration) { mWindowDecoration = decoration; From 21571bb4fb1e65fcb6fa41a8c197765aa885a445 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Aug 2014 21:34:30 +0200 Subject: [PATCH 03/13] decorations: Remove strange set dance between QWaylandWindow & QWaylandAbstractDecoration. This makes absolutely no sense. Just do things inline. Change-Id: Ic6d4e62bc9b3c0a4533f63740f2608a0be201047 Reviewed-by: Robin Burchell --- .../platforms/wayland/qwaylandabstractdecoration.cpp | 2 -- src/plugins/platforms/wayland/qwaylandwindow.cpp | 12 +++--------- src/plugins/platforms/wayland/qwaylandwindow_p.h | 2 -- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp b/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp index e247dbbad4f..e4b81bb8363 100644 --- a/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp +++ b/src/plugins/platforms/wayland/qwaylandabstractdecoration.cpp @@ -80,7 +80,6 @@ QWaylandAbstractDecorationPrivate::QWaylandAbstractDecorationPrivate() QWaylandAbstractDecorationPrivate::~QWaylandAbstractDecorationPrivate() { - m_wayland_window->setDecoration(0); } QWaylandAbstractDecoration::QWaylandAbstractDecoration() @@ -103,7 +102,6 @@ void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window) d->m_window = window->window(); d->m_wayland_window = window; - d->m_wayland_window->setDecoration(this); } const QImage &QWaylandAbstractDecoration::contentImage() diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 2fc904aadd1..3b1de7f60c3 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -535,6 +535,9 @@ bool QWaylandWindow::createDecoration() return false; } mWindowDecoration->setWaylandWindow(this); + if (subSurfaceWindow()) { + subSurfaceWindow()->adjustPositionOfChildren(); + } } } else { delete mWindowDecoration; @@ -549,15 +552,6 @@ QWaylandAbstractDecoration *QWaylandWindow::decoration() const return mWindowDecoration; } -// ### can't this go away? we directly set up our decorations, after all -void QWaylandWindow::setDecoration(QWaylandAbstractDecoration *decoration) -{ - mWindowDecoration = decoration; - if (subSurfaceWindow()) { - subSurfaceWindow()->adjustPositionOfChildren(); - } -} - static QWindow *topLevelWindow(QWindow *window) { while (QWindow *parent = window->parent()) diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index c2df0937cd1..6c32bc3ef2f 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -145,8 +145,6 @@ public: void unfocus(); QWaylandAbstractDecoration *decoration() const; - void setDecoration(QWaylandAbstractDecoration *decoration); - void handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, From 222ed6ba7b9aa67f8f1f9d233be68d69e7b7b254 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Mon, 22 Sep 2014 16:36:26 +0300 Subject: [PATCH 04/13] Use the screen resolution to determine whether a screen is portrait We were using the screen physical size to determine if a screen is portrait or landscape, but we may not always get a valid size. Instead use the screen resolution. The orientation is then calculated in the wl_output.done handler, since we don't know the resolution yet when receiving the first wl_output.geometry event. Change-Id: I3554f916e54db829f49fa3d1ea24f7ce1ff24e7c Reviewed-by: Gunnar Sletta --- .../platforms/wayland/qwaylandscreen.cpp | 52 +++++++++++-------- .../platforms/wayland/qwaylandscreen_p.h | 1 + 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 88667ae0d4f..5c625ed4231 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -61,6 +61,7 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id) , 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..49eeea67142 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen_p.h +++ b/src/plugins/platforms/wayland/qwaylandscreen_p.h @@ -103,6 +103,7 @@ private: QRect mGeometry; int mDepth; int mRefreshRate; + int mTransform; QImage::Format mFormat; QSize mPhysicalSize; QString mOutputName; From 12cc3e6f55ea953b59162a1fa6f65fbcc4b3cd63 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Sat, 27 Sep 2014 22:00:14 +0300 Subject: [PATCH 05/13] Send also repeat key release events We were sending only key press events for the key autorepeat, going out of sync with the release events. Xorg sends both relase and press auto repeat events, do so here too. Change-Id: I41a9bfaff50afea779a7572220f6a01b507e95ac Reviewed-by: Laszlo Agocs --- .../platforms/wayland/qwaylandinputdevice.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 5198a9e31ea..6ec7b5df411 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -817,6 +817,18 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, void QWaylandInputDevice::repeatKey() { mRepeatTimer.setInterval(25); + + QWindowSystemInterface::handleExtendedKeyEvent(mKeyboard->mFocus->window(), + mKeyboard->mRepeatTime, QEvent::KeyRelease, mKeyboard->mRepeatKey, + modifiers(), + mKeyboard->mRepeatCode, +#ifndef QT_NO_WAYLAND_XKB + mKeyboard->mRepeatSym, mKeyboard->mNativeModifiers, +#else + 0, 0, +#endif + mKeyboard->mRepeatText, true); + QWindowSystemInterface::handleExtendedKeyEvent(mKeyboard->mFocus->window(), mKeyboard->mRepeatTime, QEvent::KeyPress, mKeyboard->mRepeatKey, modifiers(), From 1a3d78d81f4a0681ec42bab1706652c14df58bc1 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Sat, 27 Sep 2014 19:31:58 +0300 Subject: [PATCH 06/13] Support the creation of >= 3.x OpenGL contexts Use the EGL_KHR_create_context extension if available to create modern gl contexts. We disable window decorations on core profiles because that mandates a VAO to be used. Change-Id: Id6044e64f6736244ae9d593af4d68c4000a31de6 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylandwindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 3b1de7f60c3..5786c1fb8ff 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -700,7 +700,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) { From 5984e1e5c1fc9c6e85801888ca318a7194020742 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Thu, 2 Oct 2014 10:48:09 +0300 Subject: [PATCH 07/13] Call ::exit() from the gui thread only ::exit() is not thread safe, so make sure to not call it more than one time, once from the gui thread and once from the wayland event thread. Change-Id: I80905c6d996cb827a5101ae6d6c9bc12a267ba71 Reviewed-by: Robin Burchell --- .../platforms/wayland/qwaylanddisplay.cpp | 18 ++++++++++++++---- .../platforms/wayland/qwaylanddisplay_p.h | 1 + .../platforms/wayland/qwaylandeventthread.cpp | 11 +++++++---- .../platforms/wayland/qwaylandeventthread_p.h | 3 ++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 3eac985f6ed..8649a497c7d 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -149,6 +149,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)); @@ -167,8 +168,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); } @@ -176,8 +179,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 diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index b0142004e8b..796c54756e0 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -164,6 +164,7 @@ public slots: private: void waitForScreens(); + void exitWithError(); struct Listener { RegistryListener listener; 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: From 1ed546004cc082d211cfcdd5e2c2179623af4a53 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Mon, 6 Oct 2014 11:05:23 +0300 Subject: [PATCH 08/13] Fix shm windows sometimes not showing after being hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QWaylandShmBackingStore installs a frame callback on flush, and subsequent flushes will not attach a new buffer until the callback is fired. If the window is hidden while we're waiting for the callback, we attach a NULL buffer, so the compositor will not redraw the surface and will not fire the frame callback. When showing the window again the backing store's flush() will wait indefinitely for the frame callback to attach its buffer. To fix it destroy the frame callback when the window is hidden. This was easily noticeable when fast switching between popup menus. Change-Id: Ic0c71ed79e2fab9faf452f63b05bc4576ea9a3ba Reviewed-by: Jørgen Lind --- .../platforms/wayland/qwaylandshmbackingstore.cpp | 11 +++++++++++ .../platforms/wayland/qwaylandshmbackingstore_p.h | 1 + src/plugins/platforms/wayland/qwaylandwindow.cpp | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index 421fae91c6b..332ea9265d5 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -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); diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index 5c3dbb5bc27..319acd9a982 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -82,6 +82,7 @@ public: void resize(const QSize &size); void beginPaint(const QRegion &); void endPaint(); + void hidden(); QWaylandAbstractDecoration *windowDecoration() const; diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 5786c1fb8ff..d1ea6c1f979 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -54,6 +54,7 @@ #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" #include "qwaylanddecorationfactory_p.h" +#include "qwaylandshmbackingstore_p.h" #include #include @@ -90,6 +91,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mMouseDevice(0) , mMouseSerial(0) , mState(Qt::WindowNoState) + , mBackingStore(Q_NULLPTR) { init(mDisplay->createSurface(static_cast(this))); @@ -248,6 +250,9 @@ void QWaylandWindow::setVisible(bool visible) if (!deleteGuard.isNull()) { attach(static_cast(0), 0, 0); commit(); + if (mBackingStore) { + mBackingStore->hidden(); + } } } } From 838501541adb9b6fdd7e2e8ba678c91e073f7892 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Tue, 30 Sep 2014 17:09:49 +0300 Subject: [PATCH 09/13] Fix the compositor's wayland versioning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We cannot just assume all clients implement the same version of the various interfaces as the compositor does. Keep track of them, and react accordingly when creating a resource or sending an event. Change-Id: I9792433a14d49c5c4df0c892fc1349ce0dfb0d43 Reviewed-by: Jørgen Lind --- .../qtwaylandscanner/qtwaylandscanner.cpp | 51 ++++++++++--------- tests/auto/wayland/mockcompositor.cpp | 2 +- tests/auto/wayland/mockinput.cpp | 10 ++-- tests/auto/wayland/mocksurface.cpp | 4 +- tests/auto/wayland/mocksurface.h | 2 +- 5 files changed, 36 insertions(+), 33 deletions(-) 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; } From eac16a7b2883aeb2741ca1093c29963c7268a7fb Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Sun, 5 Oct 2014 20:45:34 +0300 Subject: [PATCH 10/13] Pass the relevant serial when setting the selection This fixes copying in Weston. Change-Id: Icbdb81078e8df4575bbe440321773131ba27ebbf Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylanddatadevice.cpp | 3 ++- src/plugins/platforms/wayland/qwaylanddatadevice_p.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) 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; From 77fd8f63c31d415ebd5f0ecf31815df670fc2e2e Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Fri, 10 Oct 2014 22:17:41 +0300 Subject: [PATCH 11/13] Be compatible with older compositors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When binding globals take care of the version the compositor provides and don't call requests that the compositor doesn't implement. Change-Id: Iea0c534fb9e005720857e2778e380b6a9c22a6f3 Reviewed-by: Jørgen Lind --- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 7 ++++--- src/plugins/platforms/wayland/qwaylanddisplay_p.h | 2 ++ src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 4 ++-- src/plugins/platforms/wayland/qwaylandinputdevice_p.h | 2 +- src/plugins/platforms/wayland/qwaylandscreen.cpp | 4 ++-- src/plugins/platforms/wayland/qwaylandscreen_p.h | 2 +- src/plugins/platforms/wayland/qwaylandwindow.cpp | 3 +++ 7 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 8649a497c7d..fda2c204e66 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -226,13 +226,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 +242,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 = new QWaylandInputDevice(this, id); + QWaylandInputDevice *inputDevice = new QWaylandInputDevice(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 796c54756e0..8d1d26bba24 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -116,6 +116,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(); @@ -198,6 +199,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/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 6ec7b5df411..39d1705c0c7 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -228,9 +228,9 @@ public: QList mPrevTouchPoints; }; -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) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h index 23e1fc74099..630640f87f2 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice_p.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice_p.h @@ -75,7 +75,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice { Q_OBJECT public: - 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/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 5c625ed4231..6e48c442e43 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -53,9 +53,9 @@ 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) diff --git a/src/plugins/platforms/wayland/qwaylandscreen_p.h b/src/plugins/platforms/wayland/qwaylandscreen_p.h index 49eeea67142..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; diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index d1ea6c1f979..6c4a339f1e0 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -429,6 +429,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) { From 351e3672d6414c6501c26ea137efdd92b80d5031 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 14 Oct 2014 10:48:10 +0200 Subject: [PATCH 12/13] Fix -no-opengl builds Task-number: QTBUG-41677 Change-Id: I039ec581e960eb70eb04aed6e65add70c563ba77 Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 2 ++ src/plugins/platforms/wayland/qwaylandintegration_p.h | 2 ++ src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp | 2 ++ src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index d9bf82e4f98..aa5a1cea8b2 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -175,12 +175,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 { diff --git a/src/plugins/platforms/wayland/qwaylandintegration_p.h b/src/plugins/platforms/wayland/qwaylandintegration_p.h index bbe98285389..699702482db 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration_p.h +++ b/src/plugins/platforms/wayland/qwaylandintegration_p.h @@ -61,7 +61,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; diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index 332ea9265d5..d407335d3f7 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -323,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 @@ -331,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 319acd9a982..1212e52fe33 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -94,7 +94,9 @@ public: QWaylandWindow *waylandWindow() const; void iterateBuffer(); +#ifndef QT_NO_OPENGL QImage toImage() const Q_DECL_OVERRIDE; +#endif private: void updateDecorations(); From a92c4a48bcaa643df56cda22b70b2ce1f6a96ba0 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Tue, 9 Sep 2014 19:42:10 +0200 Subject: [PATCH 13/13] Fix crash when cursor theme can not be loaded Also add a debug message about theme loading failure. This is not necessarily fatal, some embedded applications could still function properly without a cursor. Change-Id: Ib3e2ee43b00630ee77997c7472a95ac5a22c2cc2 Reviewed-by: Giulio Camuffo Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/qwaylandcursor.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) 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());