summaryrefslogtreecommitdiffstats
path: root/src/client/qwaylandabstractdecoration.cpp
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 /src/client/qwaylandabstractdecoration.cpp
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>
Diffstat (limited to 'src/client/qwaylandabstractdecoration.cpp')
-rw-r--r--src/client/qwaylandabstractdecoration.cpp408
1 files changed, 63 insertions, 345 deletions
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