diff options
author | Robin Burchell <robin.burchell@viroteck.net> | 2014-08-20 16:31:05 +0200 |
---|---|---|
committer | Robin Burchell <robin.burchell@viroteck.net> | 2014-09-23 12:35:31 +0200 |
commit | 8655435f86b45a343d7a36c35968fa2c7c83f9c3 (patch) | |
tree | 9ead216ddc460db68615f140afaea03b29716bb4 /src/client | |
parent | 59d691d6c54932a92933ee69876b8f0bc8cf954e (diff) |
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 <robin.burchell@viroteck.net>
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/client.pro | 6 | ||||
-rw-r--r-- | src/client/qwaylandabstractdecoration.cpp | 408 | ||||
-rw-r--r-- | src/client/qwaylandabstractdecoration_p.h | 71 | ||||
-rw-r--r-- | src/client/qwaylanddecorationfactory.cpp | 97 | ||||
-rw-r--r-- | src/client/qwaylanddecorationfactory_p.h | 61 | ||||
-rw-r--r-- | src/client/qwaylanddecorationplugin.cpp | 54 | ||||
-rw-r--r-- | src/client/qwaylanddecorationplugin_p.h | 69 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 37 |
8 files changed, 401 insertions, 402 deletions
diff --git a/src/client/client.pro b/src/client/client.pro index ed14a460e..a8a1136ea 100644 --- a/src/client/client.pro +++ b/src/client/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/client/qwaylandabstractdecoration.cpp b/src/client/qwaylandabstractdecoration.cpp index 2781b4261..e247dbbad 100644 --- a/src/client/qwaylandabstractdecoration.cpp +++ b/src/client/qwaylandabstractdecoration.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> ** 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 <private/qobject_p.h> #include "qwaylandwindow_p.h" #include "qwaylandshellsurface_p.h" #include "qwaylandinputdevice_p.h" #include "qwaylandscreen_p.h" -#include <QtGui/QGuiApplication> #include <QtGui/QImage> -#include <QtGui/QCursor> -#include <QtGui/QPainter> -#include <QtGui/QPalette> -#include <QtGui/QLinearGradient> QT_BEGIN_NAMESPACE -#define BUTTON_SPACING 5 - -#ifndef QT_NO_IMAGEFORMAT_XPM -# define BUTTON_WIDTH 10 +class QWaylandAbstractDecorationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandAbstractDecoration) -static const char * const qt_close_xpm[] = { -"10 10 2 1", -"# c #000000", -". c None", -"..........", -".##....##.", -"..##..##..", -"...####...", -"....##....", -"...####...", -"..##..##..", -".##....##.", -"..........", -".........."}; +public: + QWaylandAbstractDecorationPrivate(); + ~QWaylandAbstractDecorationPrivate(); -static const char * const qt_maximize_xpm[]={ -"10 10 2 1", -"# c #000000", -". c None", -"#########.", -"#########.", -"#.......#.", -"#.......#.", -"#.......#.", -"#.......#.", -"#.......#.", -"#.......#.", -"#########.", -".........."}; + QWindow *m_window; + QWaylandWindow *m_wayland_window; -static const char * const qt_minimize_xpm[] = { -"10 10 2 1", -"# c #000000", -". c None", -"..........", -"..........", -"..........", -"..........", -"..........", -"..........", -"..........", -".#######..", -".#######..", -".........."}; + bool m_isDirty; + QImage m_decorationContentImage; -static const char * const qt_normalizeup_xpm[] = { -"10 10 2 1", -"# c #000000", -". c None", -"...######.", -"...######.", -"...#....#.", -".######.#.", -".######.#.", -".#....###.", -".#....#...", -".#....#...", -".######...", -".........."}; -#else -# define BUTTON_WIDTH 22 -#endif + Qt::MouseButtons m_mouseButtons; +}; -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); } -const QImage &QWaylandAbstractDecoration::contentImage() +QWaylandAbstractDecoration::QWaylandAbstractDecoration() + : QObject(*new QWaylandAbstractDecorationPrivate) { - if (m_isDirty) { - //Update the decoration backingstore - - m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); - m_decorationContentImage.fill(Qt::transparent); - this->paint(&m_decorationContentImage); - - m_isDirty = false; - } - - return m_decorationContentImage; } -void QWaylandAbstractDecoration::update() +QWaylandAbstractDecoration::~QWaylandAbstractDecoration() { - m_isDirty = true; } -void QWaylandAbstractDecoration::paint(QPaintDevice *device) +// 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) { - 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()); + Q_D(QWaylandAbstractDecoration); - p.restore(); -#else - // We don't need antialiasing from now on - p.setRenderHint(QPainter::Antialiasing, false); + // double initialization is probably not great + Q_ASSERT(!d->m_window && !d->m_wayland_window); - 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 + d->m_window = window->window(); + d->m_wayland_window = window; + d->m_wayland_window->setDecoration(this); } -bool QWaylandAbstractDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) - +const QImage &QWaylandAbstractDecoration::contentImage() { - Q_UNUSED(global); + Q_D(QWaylandAbstractDecoration); + if (d->m_isDirty) { + //Update the decoration backingstore + + d->m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); + d->m_decorationContentImage.fill(Qt::transparent); + this->paint(&d->m_decorationContentImage); - // 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; + d->m_isDirty = false; } - m_mouseButtons = b; - return true; + return d->m_decorationContentImage; } -bool QWaylandAbstractDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +void QWaylandAbstractDecoration::update() { - 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; + Q_D(QWaylandAbstractDecoration); + d->m_isDirty = true; } -bool QWaylandAbstractDecoration::inMouseButtonPressedState() const +void QWaylandAbstractDecoration::setMouseButtons(Qt::MouseButtons mb) { - 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/client/qwaylandabstractdecoration_p.h b/src/client/qwaylandabstractdecoration_p.h index c94c9951a..6171cab14 100644 --- a/src/client/qwaylandabstractdecoration_p.h +++ b/src/client/qwaylandabstractdecoration_p.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> ** 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; - - void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons); - void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons); - QMargins margins() const; + virtual QMargins margins() const = 0; QWindow *window() const; - QWaylandWindow *waylandWindow() 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: - void paint(QPaintDevice *device); + virtual void paint(QPaintDevice *device) = 0; + + void setMouseButtons(Qt::MouseButtons mb); -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); + void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons); + void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons); 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/client/qwaylanddecorationfactory.cpp b/src/client/qwaylanddecorationfactory.cpp new file mode 100644 index 000000000..6f1f74693 --- /dev/null +++ b/src/client/qwaylanddecorationfactory.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** 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 <QtCore/private/qfactoryloader_p.h> +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> + +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<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(directLoader(), name, args)) + return ret; + } + if (QWaylandAbstractDecoration *ret = qLoadPlugin1<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(loader(), name, args)) + return ret; +#endif + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/client/qwaylanddecorationfactory_p.h b/src/client/qwaylanddecorationfactory_p.h new file mode 100644 index 000000000..a7729bcaf --- /dev/null +++ b/src/client/qwaylanddecorationfactory_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** 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 <QtWaylandClient/private/qwaylandclientexport_p.h> +#include <QtCore/QStringList> + +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/client/qwaylanddecorationplugin.cpp b/src/client/qwaylanddecorationplugin.cpp new file mode 100644 index 000000000..edad5f5f0 --- /dev/null +++ b/src/client/qwaylanddecorationplugin.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** 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/client/qwaylanddecorationplugin_p.h b/src/client/qwaylanddecorationplugin_p.h new file mode 100644 index 000000000..6ed8935db --- /dev/null +++ b/src/client/qwaylanddecorationplugin_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** 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 <QtWaylandClient/private/qwaylandclientexport_p.h> + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> +#include <QtCore/QObject> + +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/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index c900b98db..2fc904aad 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -53,6 +53,7 @@ #include "qwaylandabstractdecoration_p.h" #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" +#include "qwaylanddecorationfactory_p.h" #include <QtCore/QFileInfo> #include <QtCore/QPointer> @@ -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; |