diff options
Diffstat (limited to 'src/plugins/decorations/adwaita/qwaylandadwaitadecoration_p.h')
-rw-r--r-- | src/plugins/decorations/adwaita/qwaylandadwaitadecoration_p.h | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/plugins/decorations/adwaita/qwaylandadwaitadecoration_p.h b/src/plugins/decorations/adwaita/qwaylandadwaitadecoration_p.h new file mode 100644 index 000000000..34874e088 --- /dev/null +++ b/src/plugins/decorations/adwaita/qwaylandadwaitadecoration_p.h @@ -0,0 +1,155 @@ +// Copyright (C) 2023 Jan Grulich <jgrulich@redhat.com> +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWAYLANDADWAITADECORATION_P_H +#define QWAYLANDADWAITADECORATION_P_H + +#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h> + +#include <QtCore/QDateTime> + +QT_BEGIN_NAMESPACE + +class QDBusVariant; +class QPainter; + +namespace QtWaylandClient { + +// +// INFO +// ------------- +// +// This is a Qt decoration plugin implementing Adwaita-like (GNOME) client-side +// window decorations. It uses xdg-desktop-portal to get the user configuration. +// This plugin was originally part of QGnomePlatform and later made a separate +// project named QAdwaitaDecorations. +// +// INFO: How SVG icons are used here? +// We try to find an SVG icon for a particular button from the current icon theme. +// This icon is then opened as a file, it's content saved and later loaded to be +// painted with QSvgRenderer, but before it's painted, we try to find following +// patterns: +// 1) fill=[\"']#[0-9A-F]{6}[\"'] +// 2) fill:#[0-9A-F]{6} +// 3) fill=[\"']currentColor[\"'] +// The color in this case doesn't match the theme and is replaced by Foreground color. +// +// FIXME/TODO: +// This plugin currently have all the colors for the decorations hardcoded. +// There might be a way to get these from GTK/libadwaita (not sure), but problem is +// we want Gtk4 version and using Gtk4 together with QGtk3Theme from QtBase that links +// to Gtk3 will not work out. Possibly in future we can make a QGtk4Theme providing us +// what we need to paint the decorations without having to deal with the colors ourself. +// +// TODO: Implement shadows + + +class QWaylandAdwaitaDecoration : public QWaylandAbstractDecoration +{ + Q_OBJECT +public: + enum ColorType { + Background, + BackgroundInactive, + Foreground, + ForegroundInactive, + Border, + BorderInactive, + ButtonBackground, + ButtonBackgroundInactive, + HoveredButtonBackground, + PressedButtonBackground + }; + + enum Placement { + Left = 0, + Right = 1 + }; + + enum Button { + None = 0x0, + Close = 0x1, + Minimize = 0x02, + Maximize = 0x04 + }; + Q_DECLARE_FLAGS(Buttons, Button); + + enum ButtonIcon { + CloseIcon, + MinimizeIcon, + MaximizeIcon, + RestoreIcon + }; + + QWaylandAdwaitaDecoration(); + virtual ~QWaylandAdwaitaDecoration() = default; + +protected: + QMargins margins(MarginsType marginsType = Full) const override; + void paint(QPaintDevice *device) override; + bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, + Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; + bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, + QEventPoint::State state, Qt::KeyboardModifiers mods) override; + +private Q_SLOTS: + void settingChanged(const QString &group, const QString &key, const QDBusVariant &value); + +private: + // Makes a call to xdg-desktop-portal (Settings) to load initial configuration + void loadConfiguration(); + // Updates color scheme from light to dark and vice-versa + void updateColors(bool isDark); + // Updates titlebar layout with position and button order + void updateTitlebarLayout(const QString &layout); + + // Returns a bounding rect for a given button type + QRectF buttonRect(Button button) const; + // Draw given button type using SVG icon (when found) or fallback to QPixmap icon + void drawButton(Button button, QPainter *painter); + + // Returns color for given type and button + QColor color(ColorType type, Button button = None); + + // Returns whether the left button was clicked i.e. pressed and released + bool clickButton(Qt::MouseButtons b, Button btn); + // Returns whether the left button was double-clicked + bool doubleClickButton(Qt::MouseButtons b, const QPointF &local, const QDateTime ¤tTime); + // Updates button hover state + void updateButtonHoverState(Button hoveredButton); + + 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); + // Request to repaint the decorations. This will be invoked when button hover changes or + // when there is a setting change (e.g. layout change). + void requestRepaint() const; + + // Button states + Button m_clicking = None; + Buttons m_hoveredButtons = None; + QDateTime m_lastButtonClick; + QPointF m_lastButtonClickPosition; + + // Configuration + QMap<Button, uint> m_buttons; + QMap<ColorType, QColor> m_colors; + QMap<ButtonIcon, QString> m_icons; + std::unique_ptr<QFont> m_font; + Placement m_placement = Right; + + QStaticText m_windowTitle; +}; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandAdwaitaDecoration::Buttons) + +} // namespace QtWaylandClient + +QT_END_NAMESPACE + +#endif // QWAYLANDADWAITADECORATION_P_H |