File indexing completed on 2024-05-12 16:58:28

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef breeze_helper_h
0008 #define breeze_helper_h
0009 
0010 #include "breeze.h"
0011 #include "breezeanimationdata.h"
0012 #include "breezemetrics.h"
0013 #include "breezesettings.h"
0014 #include "config-breeze.h"
0015 
0016 #include <KConfigWatcher>
0017 #include <KSharedConfig>
0018 #include <KStatefulBrush>
0019 
0020 #include <QIcon>
0021 #include <QPainterPath>
0022 #include <QToolBar>
0023 #include <QWidget>
0024 
0025 namespace Breeze
0026 {
0027 //* breeze style helper class.
0028 /** contains utility functions used at multiple places in both breeze style and breeze window decoration */
0029 class Helper : public QObject
0030 {
0031     Q_OBJECT
0032 
0033 public:
0034     //* constructor
0035     explicit Helper(KSharedConfig::Ptr, QObject *parent = nullptr);
0036 
0037     //* destructor
0038     virtual ~Helper()
0039     {
0040     }
0041 
0042     //* load configuration
0043     virtual void loadConfig();
0044 
0045     //* pointer to shared config
0046     KSharedConfig::Ptr config() const;
0047 
0048     //* pointer to kdecoration config
0049     QSharedPointer<InternalSettings> decorationConfig() const;
0050 
0051     //*@name color utilities
0052     //@{
0053 
0054     //* add alpha channel multiplier to color
0055     QColor alphaColor(QColor color, qreal alpha) const;
0056 
0057     //* mouse over color
0058     QColor hoverColor(const QPalette &palette) const
0059     {
0060         return _viewHoverBrush.brush(palette).color();
0061     }
0062 
0063     //* focus color
0064     QColor focusColor(const QPalette &palette) const
0065     {
0066         return _viewFocusBrush.brush(palette).color();
0067     }
0068 
0069     //* mouse over color for buttons
0070     QColor buttonHoverColor(const QPalette &palette) const
0071     {
0072         return _buttonHoverBrush.brush(palette).color();
0073     }
0074 
0075     //* focus color for buttons
0076     QColor buttonFocusColor(const QPalette &palette) const
0077     {
0078         return _buttonFocusBrush.brush(palette).color();
0079     }
0080 
0081     //* negative text color (used for close button)
0082     QColor negativeText(const QPalette &palette) const
0083     {
0084         return _viewNegativeTextBrush.brush(palette).color();
0085     }
0086 
0087     //* neutral text color
0088     QColor neutralText(const QPalette &palette) const
0089     {
0090         return _viewNeutralTextBrush.brush(palette).color();
0091     }
0092 
0093     //* shadow
0094     QColor shadowColor(const QPalette &palette, qreal opacity = 0.125) const
0095     {
0096         return QColor::fromRgbF(0, 0, 0, opacity);
0097     }
0098 
0099     //* titlebar color
0100     const QColor &titleBarColor(bool active) const
0101     {
0102         return active ? _activeTitleBarColor : _inactiveTitleBarColor;
0103     }
0104 
0105     //* titlebar text color
0106     const QColor &titleBarTextColor(bool active) const
0107     {
0108         return active ? _activeTitleBarTextColor : _inactiveTitleBarTextColor;
0109     }
0110 
0111     //* frame outline color, using animations
0112     QColor frameOutlineColor(const QPalette &,
0113                              bool mouseOver = false,
0114                              bool hasFocus = false,
0115                              qreal opacity = AnimationData::OpacityInvalid,
0116                              AnimationMode = AnimationNone) const;
0117 
0118     //* focus outline color, using animations
0119     QColor focusOutlineColor(const QPalette &) const;
0120 
0121     //* hover outline color, using animations
0122     QColor hoverOutlineColor(const QPalette &) const;
0123 
0124     //* focus outline color, using animations
0125     QColor buttonFocusOutlineColor(const QPalette &) const;
0126 
0127     //* hover outline color, using animations
0128     QColor buttonHoverOutlineColor(const QPalette &) const;
0129 
0130     //* side panel outline color, using animations
0131     QColor sidePanelOutlineColor(const QPalette &, bool hasFocus = false, qreal opacity = AnimationData::OpacityInvalid, AnimationMode = AnimationNone) const;
0132 
0133     //* frame background color
0134     QColor frameBackgroundColor(const QPalette &palette) const
0135     {
0136         return frameBackgroundColor(palette, palette.currentColorGroup());
0137     }
0138 
0139     //* frame background color
0140     QColor frameBackgroundColor(const QPalette &, QPalette::ColorGroup) const;
0141 
0142     //* arrow outline color
0143     QColor arrowColor(const QPalette &, QPalette::ColorGroup, QPalette::ColorRole) const;
0144 
0145     //* arrow outline color
0146     QColor arrowColor(const QPalette &palette, QPalette::ColorRole role) const
0147     {
0148         return arrowColor(palette, palette.currentColorGroup(), role);
0149     }
0150 
0151     //* arrow outline color, using animations
0152     QColor arrowColor(const QPalette &, bool mouseOver, bool hasFocus, qreal opacity = AnimationData::OpacityInvalid, AnimationMode = AnimationNone) const;
0153 
0154     //* slider outline color, using animations
0155     QColor
0156     sliderOutlineColor(const QPalette &, bool mouseOver, bool hasFocus, qreal opacity = AnimationData::OpacityInvalid, AnimationMode = AnimationNone) const;
0157 
0158     //* scrollbar handle color, using animations
0159     QColor
0160     scrollBarHandleColor(const QPalette &, bool mouseOver, bool hasFocus, qreal opacity = AnimationData::OpacityInvalid, AnimationMode = AnimationNone) const;
0161 
0162     //* checkbox indicator, using animations
0163     QColor
0164     checkBoxIndicatorColor(const QPalette &, bool mouseOver, bool active, qreal opacity = AnimationData::OpacityInvalid, AnimationMode = AnimationNone) const;
0165 
0166     //* separator color
0167     QColor separatorColor(const QPalette &) const;
0168 
0169     //* merge active and inactive palettes based on ratio, for smooth enable state change transition
0170     QPalette disabledPalette(const QPalette &, qreal ratio) const;
0171 
0172     //@}
0173 
0174     //*@name rendering utilities
0175     //@{
0176 
0177     //* debug frame
0178     void renderDebugFrame(QPainter *, const QRect &) const;
0179 
0180     //* focus rect
0181     void renderFocusRect(QPainter *, const QRect &, const QColor &, const QColor &outline = QColor(), Sides = {}) const;
0182 
0183     //* focus line
0184     void renderFocusLine(QPainter *, const QRect &, const QColor &) const;
0185 
0186     //* generic frame
0187     void renderFrame(QPainter *, const QRect &, const QColor &color, const QColor &outline = QColor()) const;
0188 
0189     //* generic frame, with separators only on the side
0190     void renderFrameWithSides(QPainter *, const QRect &, const QColor &color, Qt::Edges edges, const QColor &outline = QColor()) const;
0191 
0192     //* side panel frame
0193     void renderSidePanelFrame(QPainter *, const QRect &, const QColor &outline, Side) const;
0194 
0195     //* menu frame
0196     void renderMenuFrame(QPainter *, const QRect &, const QColor &color, const QColor &outline, bool roundCorners = true, bool isTopMenu = false) const;
0197 
0198     //* button frame
0199     void renderButtonFrame(QPainter *painter,
0200                            const QRect &rect,
0201                            const QPalette &palette,
0202                            const QHash<QByteArray, bool> &stateProperties,
0203                            qreal bgAnimation = AnimationData::OpacityInvalid,
0204                            qreal penAnimation = AnimationData::OpacityInvalid) const;
0205 
0206     //* toolbutton frame
0207     void renderToolBoxFrame(QPainter *, const QRect &, int tabWidth, const QColor &color) const;
0208 
0209     //* tab widget frame
0210     void renderTabWidgetFrame(QPainter *, const QRect &, const QColor &color, const QColor &outline, Corners) const;
0211 
0212     //* selection frame
0213     void renderSelection(QPainter *, const QRect &, const QColor &) const;
0214 
0215     //* separator
0216     void renderSeparator(QPainter *, const QRect &, const QColor &, bool vertical = false) const;
0217 
0218     //* checkbox
0219     void renderCheckBoxBackground(QPainter *,
0220                                   const QRect &,
0221                                   const QPalette &palette,
0222                                   CheckBoxState state,
0223                                   bool neutalHighlight,
0224                                   bool sunken,
0225                                   qreal animation = AnimationData::OpacityInvalid) const;
0226 
0227     //* checkbox
0228     void renderCheckBox(QPainter *,
0229                         const QRect &,
0230                         const QPalette &palette,
0231                         bool mouseOver,
0232                         CheckBoxState state,
0233                         CheckBoxState target,
0234                         bool neutalHighlight,
0235                         bool sunken,
0236                         qreal animation = AnimationData::OpacityInvalid,
0237                         qreal hoverAnimation = AnimationData::OpacityInvalid) const;
0238 
0239     //* radio button
0240     void renderRadioButtonBackground(QPainter *,
0241                                      const QRect &,
0242                                      const QPalette &palette,
0243                                      RadioButtonState state,
0244                                      bool neutalHighlight,
0245                                      bool sunken,
0246                                      qreal animation = AnimationData::OpacityInvalid) const;
0247 
0248     //* radio button
0249     void renderRadioButton(QPainter *,
0250                            const QRect &,
0251                            const QPalette &palette,
0252                            bool mouseOver,
0253                            RadioButtonState state,
0254                            bool neutalHighlight,
0255                            bool sunken,
0256                            qreal animation = AnimationData::OpacityInvalid,
0257                            qreal hoverAnimation = AnimationData::OpacityInvalid) const;
0258 
0259     //* slider groove
0260     void renderSliderGroove(QPainter *, const QRect &, const QColor &) const;
0261 
0262     //* slider handle
0263     void renderSliderHandle(QPainter *, const QRect &, const QColor &, const QColor &outline, const QColor &shadow, bool sunken) const;
0264 
0265     //* dial groove
0266     void renderDialGroove(QPainter *, const QRect &, const QColor &fg, const QColor &bg, qreal first, qreal last) const;
0267 
0268     //* progress bar groove
0269     void renderProgressBarGroove(QPainter *, const QRect &, const QColor &fg, const QColor &bg) const;
0270 
0271     //* progress bar contents (animated)
0272     void renderProgressBarBusyContents(QPainter *painter,
0273                                        const QRect &rect,
0274                                        const QColor &first,
0275                                        const QColor &second,
0276                                        bool horizontal,
0277                                        bool reverse,
0278                                        int progress) const;
0279 
0280     //* scrollbar groove
0281     void renderScrollBarGroove(QPainter *painter, const QRect &rect, const QColor &color) const;
0282 
0283     //* scrollbar handle
0284     void renderScrollBarHandle(QPainter *, const QRect &, const QColor &fg, const QColor &bg) const;
0285 
0286     //* separator between scrollbar and contents
0287     void renderScrollBarBorder(QPainter *, const QRect &, const QColor &) const;
0288 
0289     //* tabbar tab
0290     void
0291     renderTabBarTab(QPainter *, const QRect &, const QPalette &palette, const QHash<QByteArray, bool> &stateProperties, Corners corners, qreal animation) const;
0292     // TODO(janet): document should be set based on whether or not we consider the
0293     // tab user-editable, but Qt apps often misuse or don't use documentMode property
0294     // so we're currently just always setting it to true for now
0295 
0296     //* generic arrow
0297     void renderArrow(QPainter *, const QRect &, const QColor &, ArrowOrientation) const;
0298 
0299     //* generic button (for mdi decorations, tabs and dock widgets)
0300     void renderDecorationButton(QPainter *, const QRect &, const QColor &, ButtonType, bool inverted) const;
0301 
0302     //* generic shadow for rounded rectangles
0303     void renderRoundedRectShadow(QPainter *, const QRectF &, const QColor &, qreal radius = Metrics::Frame_FrameRadius - PenWidth::Shadow / 2) const;
0304 
0305     //* generic shadow for ellipses
0306     void renderEllipseShadow(QPainter *, const QRectF &, const QColor &) const;
0307 
0308     //@}
0309 
0310     //*@name compositing utilities
0311     //@{
0312 
0313     //* true if style was compiled for and is running on X11
0314     static bool isX11();
0315 
0316     //* true if running on platform Wayland
0317     static bool isWayland();
0318 
0319     //* returns true if compositing is active
0320     bool compositingActive() const;
0321 
0322     //* returns true if a given widget supports alpha channel
0323     bool hasAlphaChannel(const QWidget *) const;
0324 
0325     //* returns true if the tools area should be drawn
0326     bool shouldDrawToolsArea(const QWidget *) const;
0327 
0328     //@}
0329 
0330     //* frame radius
0331     constexpr qreal frameRadius(const int penWidth = PenWidth::NoPen, const qreal bias = 0) const
0332     {
0333         return qMax(Metrics::Frame_FrameRadius - (0.5 * penWidth) + bias, 0.0);
0334     }
0335 
0336     //* frame radius with new pen width
0337     constexpr qreal frameRadiusForNewPenWidth(const qreal oldRadius, const int penWidth) const
0338     {
0339         return qMax(oldRadius - (0.5 * penWidth), 0.0);
0340     }
0341 
0342     //* return a QRectF with the appropriate size for a rectangle with a pen stroke
0343     QRectF strokedRect(const QRectF &rect, const qreal penWidth = PenWidth::Frame) const;
0344 
0345     //* return a QRectF with the appropriate size for a rectangle with a shadow around it
0346     QRectF shadowedRect(const QRectF &rect, const qreal shadowSize = PenWidth::Shadow) const
0347     {
0348         return rect.adjusted(shadowSize, shadowSize, -shadowSize, -shadowSize);
0349     }
0350 
0351     QPixmap coloredIcon(const QIcon &icon, const QPalette &palette, const QSize &size, QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off);
0352 
0353 protected:
0354     //* return rounded path in a given rect, with only selected corners rounded, and for a given radius
0355     QPainterPath roundedPath(const QRectF &, Corners, qreal) const;
0356 
0357 private:
0358     //* configuration
0359     KSharedConfig::Ptr _config;
0360 
0361     //* KWin configuration
0362     KSharedConfig::Ptr _kwinConfig;
0363 
0364     //* decoration configuration
0365     QSharedPointer<InternalSettings> _decorationConfig;
0366 
0367     //*@name brushes
0368     //@{
0369     KStatefulBrush _viewFocusBrush;
0370     KStatefulBrush _viewHoverBrush;
0371     KStatefulBrush _buttonFocusBrush;
0372     KStatefulBrush _buttonHoverBrush;
0373     KStatefulBrush _viewNegativeTextBrush;
0374     KStatefulBrush _viewNeutralTextBrush;
0375     //@}
0376 
0377     //*@name windeco colors
0378     //@{
0379     QColor _activeTitleBarColor;
0380     QColor _activeTitleBarTextColor;
0381     QColor _inactiveTitleBarColor;
0382     QColor _inactiveTitleBarTextColor;
0383     //@}
0384 
0385     mutable bool _cachedAutoValid = false;
0386 
0387     friend class ToolsAreaManager;
0388 };
0389 
0390 }
0391 
0392 #endif