summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Burchell <robin.burchell@viroteck.net>2014-08-20 16:31:05 +0200
committerRobin Burchell <robin.burchell@viroteck.net>2014-09-23 12:35:31 +0200
commit8655435f86b45a343d7a36c35968fa2c7c83f9c3 (patch)
tree9ead216ddc460db68615f140afaea03b29716bb4
parent59d691d6c54932a92933ee69876b8f0bc8cf954e (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>
-rw-r--r--src/client/client.pro6
-rw-r--r--src/client/qwaylandabstractdecoration.cpp408
-rw-r--r--src/client/qwaylandabstractdecoration_p.h71
-rw-r--r--src/client/qwaylanddecorationfactory.cpp97
-rw-r--r--src/client/qwaylanddecorationfactory_p.h61
-rw-r--r--src/client/qwaylanddecorationplugin.cpp54
-rw-r--r--src/client/qwaylanddecorationplugin_p.h69
-rw-r--r--src/client/qwaylandwindow.cpp37
-rw-r--r--src/plugins/decorations/bradient/bradient.json3
-rw-r--r--src/plugins/decorations/bradient/bradient.pro17
-rw-r--r--src/plugins/decorations/bradient/main.cpp452
-rw-r--r--src/plugins/decorations/decorations.pro3
-rw-r--r--src/plugins/plugins.pro5
13 files changed, 880 insertions, 403 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 &paramList) = 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;
diff --git a/src/plugins/decorations/bradient/bradient.json b/src/plugins/decorations/bradient/bradient.json
new file mode 100644
index 000000000..e1a5ef24f
--- /dev/null
+++ b/src/plugins/decorations/bradient/bradient.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "bradient" ]
+}
diff --git a/src/plugins/decorations/bradient/bradient.pro b/src/plugins/decorations/bradient/bradient.pro
new file mode 100644
index 000000000..fd376f4a9
--- /dev/null
+++ b/src/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/decorations/bradient/main.cpp b/src/plugins/decorations/bradient/main.cpp
new file mode 100644
index 000000000..c249248c3
--- /dev/null
+++ b/src/plugins/decorations/bradient/main.cpp
@@ -0,0 +1,452 @@
+/****************************************************************************
+**
+** 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
+**
+** 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 <QtGui/QCursor>
+#include <QtGui/QPainter>
+#include <QtGui/QPalette>
+#include <QtGui/QLinearGradient>
+
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtWaylandClient/private/qwaylanddecorationplugin_p.h>
+#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h>
+#include <QtWaylandClient/private/qwaylandwindow_p.h>
+#include <QtWaylandClient/private/qwaylandshellsurface_p.h>
+
+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/decorations/decorations.pro b/src/plugins/decorations/decorations.pro
new file mode 100644
index 000000000..6d51a450f
--- /dev/null
+++ b/src/plugins/decorations/decorations.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS += \
+ bradient
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 554dd40cd..a1a8a5b7d 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,2 +1,5 @@
TEMPLATE=subdirs
-SUBDIRS += platforms hardwareintegration
+SUBDIRS += \
+ platforms \
+ hardwareintegration \
+ decorations