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