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

0001 #ifndef oxygenwindowmanager_h
0002 #define oxygenwindowmanager_h
0003 /*
0004     SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "oxygen.h"
0009 
0010 #include <QEvent>
0011 
0012 #include <QBasicTimer>
0013 #include <QObject>
0014 #include <QQuickItem>
0015 #include <QSet>
0016 #include <QString>
0017 #include <QWidget>
0018 
0019 namespace Oxygen
0020 {
0021 class WindowManager : public QObject
0022 {
0023     Q_OBJECT
0024 
0025 public:
0026     //* constructor
0027     explicit WindowManager(QObject *);
0028 
0029     //* initialize
0030     /** read relevant options from config */
0031     void initialize(void);
0032 
0033     //* register widget
0034     void registerWidget(QWidget *);
0035 
0036     //* register quick item
0037     void registerQuickItem(QQuickItem *);
0038 
0039     //* unregister widget
0040     void unregisterWidget(QWidget *);
0041 
0042     //* event filter [reimplemented]
0043     bool eventFilter(QObject *, QEvent *) override;
0044 
0045 protected:
0046     //* timer event,
0047     /** used to start drag if button is pressed for a long enough time */
0048     void timerEvent(QTimerEvent *) override;
0049 
0050 private:
0051     //* mouse press event
0052     bool mousePressEvent(QObject *, QEvent *);
0053 
0054     //* mouse move event
0055     bool mouseMoveEvent(QObject *, QEvent *);
0056 
0057     //* mouse release event
0058     bool mouseReleaseEvent(QObject *, QEvent *);
0059 
0060     //*@name configuration
0061     //@{
0062 
0063     //* enable state
0064     bool enabled(void) const
0065     {
0066         return _enabled;
0067     }
0068 
0069     //* enable state
0070     void setEnabled(bool value)
0071     {
0072         _enabled = value;
0073     }
0074 
0075     //* returns true if window manager is used for moving
0076     bool useWMMoveResize(void) const
0077     {
0078         return _useWMMoveResize;
0079     }
0080 
0081     //* use window manager for moving, when available
0082     void setUseWMMoveResize(bool value)
0083     {
0084         _useWMMoveResize = value;
0085     }
0086 
0087     //* drag mode
0088     int dragMode(void) const
0089     {
0090         return _dragMode;
0091     }
0092 
0093     //* drag mode
0094     void setDragMode(int value)
0095     {
0096         _dragMode = value;
0097     }
0098 
0099     //* drag distance (pixels)
0100     void setDragDistance(int value)
0101     {
0102         _dragDistance = value;
0103     }
0104 
0105     //* drag delay (msec)
0106     void setDragDelay(int value)
0107     {
0108         _dragDelay = value;
0109     }
0110 
0111     //* set list of whiteListed widgets
0112     /**
0113     white list is read from options and is used to adjust
0114     per-app window dragging issues
0115     */
0116     void initializeWhiteList();
0117 
0118     //* set list of blackListed widgets
0119     /**
0120     black list is read from options and is used to adjust
0121     per-app window dragging issues
0122     */
0123     void initializeBlackList(void);
0124 
0125     //@}
0126 
0127     //* returns true if widget is dragable
0128     bool isDragable(QWidget *);
0129 
0130     //* returns true if widget is dragable
0131     bool isBlackListed(QWidget *);
0132 
0133     //* returns true if widget is dragable
0134     bool isWhiteListed(QWidget *) const;
0135 
0136     //* returns true if drag can be started from current widget
0137     bool canDrag(QWidget *);
0138 
0139     //* returns true if drag can be started from current widget and position
0140     /** child at given position is passed as second argument */
0141     bool canDrag(QWidget *, QWidget *, const QPoint &);
0142 
0143     //* reset drag
0144     void resetDrag(void);
0145 
0146     //* start drag
0147     void startDrag(QWindow *);
0148 
0149     //* utility function
0150     bool isDockWidgetTitle(const QWidget *) const;
0151 
0152     //*@name lock
0153     //@{
0154 
0155     void setLocked(bool value)
0156     {
0157         _locked = value;
0158     }
0159 
0160     //* lock
0161     bool isLocked(void) const
0162     {
0163         return _locked;
0164     }
0165 
0166     //@}
0167 
0168     //* returns first widget matching given class, or nullptr if none
0169     template<typename T>
0170     T findParent(const QWidget *) const;
0171 
0172     //* enability
0173     bool _enabled;
0174 
0175     //* use WM moveResize
0176     bool _useWMMoveResize;
0177 
0178     //* drag mode
0179     int _dragMode;
0180 
0181     //* drag distance
0182     /** this is copied from kwin::geometry */
0183     int _dragDistance;
0184 
0185     //* drag delay
0186     /** this is copied from kwin::geometry */
0187     int _dragDelay;
0188 
0189     //* wrapper for exception id
0190     class ExceptionId : public QPair<QString, QString>
0191     {
0192     public:
0193         //* constructor
0194         explicit ExceptionId(const QString &value)
0195         {
0196             const QStringList args(value.split(QChar::fromLatin1('@')));
0197             if (args.isEmpty())
0198                 return;
0199             second = args[0].trimmed();
0200             if (args.size() > 1)
0201                 first = args[1].trimmed();
0202         }
0203 
0204         const QString &appName(void) const
0205         {
0206             return first;
0207         }
0208 
0209         const QString &className(void) const
0210         {
0211             return second;
0212         }
0213     };
0214 
0215     //* exception set
0216     using ExceptionSet = QSet<ExceptionId>;
0217 
0218     //* list of white listed special widgets
0219     /**
0220     it is read from options and is used to adjust
0221     per-app window dragging issues
0222     */
0223     ExceptionSet _whiteList;
0224 
0225     //* list of black listed special widgets
0226     /**
0227     it is read from options and is used to adjust
0228     per-app window dragging issues
0229     */
0230     ExceptionSet _blackList;
0231 
0232     //* drag point
0233     QPoint _dragPoint;
0234     QPoint _globalDragPoint;
0235 
0236     //* drag timer
0237     QBasicTimer _dragTimer;
0238 
0239     //* target being dragged
0240     /** Weak pointer is used in case the target gets deleted while drag is in progress */
0241     WeakPointer<QWidget> _target;
0242 
0243     WeakPointer<QQuickItem> _quickTarget;
0244 
0245     //* true if drag is about to start
0246     bool _dragAboutToStart;
0247 
0248     //* true if drag is in progress
0249     bool _dragInProgress;
0250 
0251     //* true if drag is locked
0252     bool _locked;
0253 
0254     //* cursor override
0255     /** used to keep track of application cursor being overridden when dragging in non-WM mode */
0256     bool _cursorOverride;
0257 
0258     //* application event filter
0259     QObject *_appEventFilter;
0260 
0261     //* allow access of all private members to the app event filter
0262     friend class AppEventFilter;
0263 };
0264 
0265 //____________________________________________________________________
0266 template<typename T>
0267 T WindowManager::findParent(const QWidget *widget) const
0268 {
0269     if (!widget)
0270         return nullptr;
0271     for (QWidget *parent = widget->parentWidget(); parent; parent = parent->parentWidget()) {
0272         if (T cast = qobject_cast<T>(parent))
0273             return cast;
0274     }
0275 
0276     return nullptr;
0277 }
0278 }
0279 
0280 #endif