File indexing completed on 2024-05-05 05:35:24

0001 #ifndef oxygenblurhelper_h
0002 #define oxygenblurhelper_h
0003 
0004 //////////////////////////////////////////////////////////////////////////////
0005 // oxygenblurhelper.h
0006 // handle regions passed to kwin for blurring
0007 // -------------------
0008 //
0009 // SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0010 //
0011 // Loosely inspired (and largely rewritten) from BeSpin style
0012 // SPDX-FileCopyrightText: 2007 Thomas Luebking <thomas.luebking@web.de>
0013 //
0014 // SPDX-License-Identifier: MIT
0015 //////////////////////////////////////////////////////////////////////////////
0016 
0017 #include "oxygen.h"
0018 #include "oxygenstylehelper.h"
0019 
0020 #include <QBasicTimer>
0021 #include <QHash>
0022 #include <QObject>
0023 #include <QSet>
0024 #include <QTimerEvent>
0025 
0026 #include <QDockWidget>
0027 #include <QMenu>
0028 #include <QRegion>
0029 #include <QToolBar>
0030 
0031 #if OXYGEN_HAVE_X11
0032 #include <xcb/xcb.h>
0033 #endif
0034 
0035 namespace Oxygen
0036 {
0037 class BlurHelper : public QObject
0038 {
0039     Q_OBJECT
0040 
0041 public:
0042     //* constructor
0043     BlurHelper(QObject *, StyleHelper &);
0044 
0045     //* enable state
0046     void setEnabled(bool value)
0047     {
0048         _enabled = value;
0049     }
0050 
0051     //* enabled
0052     bool enabled(void) const
0053     {
0054         return _enabled;
0055     }
0056 
0057     //* register widget
0058     void registerWidget(QWidget *);
0059 
0060     //* register widget
0061     void unregisterWidget(QWidget *);
0062 
0063     //* event filter
0064     bool eventFilter(QObject *, QEvent *) override;
0065 
0066 protected:
0067     //* timer event
0068     /** used to perform delayed blur region update of pending widgets */
0069     void timerEvent(QTimerEvent *event) override
0070     {
0071         if (event->timerId() == _timer.timerId()) {
0072             _timer.stop();
0073             update();
0074         } else
0075             QObject::timerEvent(event);
0076     }
0077 
0078 private Q_SLOTS:
0079 
0080     //* wiget destroyed
0081     void widgetDestroyed(QObject *object)
0082     {
0083         _widgets.remove(object);
0084     }
0085 
0086 private:
0087     //* install event filter to object, in a unique way
0088     void addEventFilter(QObject *object)
0089     {
0090         object->removeEventFilter(this);
0091         object->installEventFilter(this);
0092     }
0093 
0094     //* get list of blur-behind regions matching a given widget
0095     QRegion blurRegion(QWidget *) const;
0096 
0097     //* trim blur region to remove unnecessary areas (recursive)
0098     void trimBlurRegion(QWidget *, QWidget *, QRegion &) const;
0099 
0100     //* update blur region for all pending widgets
0101     void update(void)
0102     {
0103         for (const WidgetPointer &widget : std::as_const(_pendingWidgets)) {
0104             if (widget)
0105                 update(widget.data());
0106         }
0107 
0108         _pendingWidgets.clear();
0109     }
0110 
0111     //* update blur regions for given widget
0112     void update(QWidget *) const;
0113 
0114     //* clear blur regions for given widget
0115     void clear(QWidget *) const;
0116 
0117     //* returns true if a given widget is opaque
0118     bool isOpaque(const QWidget *widget) const;
0119 
0120     //* true if widget is a transparent window
0121     /** some additional checks are performed to make sure stuff like plasma tooltips
0122     don't get their blur region overwritten */
0123     bool isTransparent(const QWidget *widget) const;
0124 
0125     //* helper
0126     StyleHelper &_helper;
0127 
0128     //* enability
0129     bool _enabled;
0130 
0131     //* list of widgets for which blur region must be updated
0132     using WidgetPointer = WeakPointer<QWidget>;
0133     using WidgetSet = QHash<QWidget *, WidgetPointer>;
0134     WidgetSet _pendingWidgets;
0135 
0136     //* set of registered widgets
0137     QSet<const QObject *> _widgets;
0138 
0139     //* delayed update timer
0140     QBasicTimer _timer;
0141 
0142 #if OXYGEN_HAVE_X11
0143     //* blur atom
0144     xcb_atom_t _blurAtom;
0145     xcb_atom_t _opaqueAtom;
0146 #endif
0147 };
0148 }
0149 
0150 #endif