File indexing completed on 2024-04-28 05:26:27
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 "breezestyleconfigdata.h" 0011 #include "config-breeze.h" 0012 0013 #include <QEvent> 0014 0015 #include <QApplication> 0016 #include <QBasicTimer> 0017 #include <QObject> 0018 #include <QSet> 0019 #include <QString> 0020 #include <QWidget> 0021 0022 #if BREEZE_HAVE_QTQUICK 0023 #include <QQuickItem> 0024 #endif 0025 0026 namespace Breeze 0027 { 0028 class WindowManager : public QObject 0029 { 0030 Q_OBJECT 0031 0032 public: 0033 //* constructor 0034 explicit WindowManager(QObject *); 0035 0036 //* initialize 0037 /** read relevant options from config */ 0038 void initialize(); 0039 0040 //* register widget 0041 void registerWidget(QWidget *); 0042 0043 #if BREEZE_HAVE_QTQUICK 0044 //* register quick item 0045 void registerQuickItem(QQuickItem *); 0046 #endif 0047 0048 //* unregister widget 0049 void unregisterWidget(QWidget *); 0050 0051 //* event filter [reimplemented] 0052 bool eventFilter(QObject *, QEvent *) override; 0053 0054 protected: 0055 //* timer event, 0056 /** used to start drag if button is pressed for a long enough time */ 0057 void timerEvent(QTimerEvent *) override; 0058 0059 //* mouse press event 0060 bool mousePressEvent(QObject *, QEvent *); 0061 0062 //* mouse move event 0063 bool mouseMoveEvent(QObject *, QEvent *); 0064 0065 //* mouse release event 0066 bool mouseReleaseEvent(QObject *, QEvent *); 0067 0068 //*@name configuration 0069 //@{ 0070 0071 //* enable state 0072 bool enabled() const 0073 { 0074 return _enabled; 0075 } 0076 0077 //* enable state 0078 void setEnabled(bool value) 0079 { 0080 _enabled = value; 0081 } 0082 0083 //* drag mode 0084 int dragMode() const 0085 { 0086 return _dragMode; 0087 } 0088 0089 //* drag mode 0090 void setDragMode(int value) 0091 { 0092 _dragMode = value; 0093 } 0094 0095 //* drag distance (pixels) 0096 void setDragDistance(int value) 0097 { 0098 _dragDistance = value; 0099 } 0100 0101 //* drag delay (msec) 0102 void setDragDelay(int value) 0103 { 0104 _dragDelay = value; 0105 } 0106 0107 //* set list of whiteListed widgets 0108 /** 0109 white list is read from options and is used to adjust 0110 per-app window dragging issues 0111 */ 0112 void initializeWhiteList(); 0113 0114 //* set list of blackListed widgets 0115 /** 0116 black list is read from options and is used to adjust 0117 per-app window dragging issues 0118 */ 0119 void initializeBlackList(); 0120 0121 //@} 0122 0123 //* returns true if widget is dragable 0124 bool isDragable(QWidget *); 0125 0126 //* returns true if widget is dragable 0127 bool isBlackListed(QWidget *); 0128 0129 //* returns true if widget is dragable 0130 bool isWhiteListed(QWidget *) const; 0131 0132 //* returns true if drag can be started from current widget 0133 bool canDrag(QWidget *); 0134 0135 //* returns true if drag can be started from current widget and position 0136 /** child at given position is passed as second argument */ 0137 bool canDrag(QWidget *, QWidget *, const QPoint &); 0138 0139 //* reset drag 0140 void resetDrag(); 0141 0142 //* start drag 0143 void startDrag(QWindow *); 0144 0145 //* utility function 0146 bool isDockWidgetTitle(const QWidget *) const; 0147 0148 //*@name lock 0149 //@{ 0150 0151 void setLocked(bool value) 0152 { 0153 _locked = value; 0154 } 0155 0156 //* lock 0157 bool isLocked() const 0158 { 0159 return _locked; 0160 } 0161 0162 //@} 0163 0164 //* returns first widget matching given class, or nullptr if none 0165 template<typename T> 0166 T findParent(const QWidget *) const; 0167 0168 private: 0169 //* enability 0170 bool _enabled = true; 0171 0172 //* drag mode 0173 int _dragMode = StyleConfigData::WD_FULL; 0174 0175 //* drag distance 0176 /** this is copied from kwin::geometry */ 0177 int _dragDistance = QApplication::startDragDistance(); 0178 0179 //* drag delay 0180 /** this is copied from kwin::geometry */ 0181 int _dragDelay = QApplication::startDragTime(); 0182 0183 //* wrapper for exception id 0184 class ExceptionId 0185 { 0186 public: 0187 //* constructor 0188 explicit ExceptionId(const QString &value) 0189 { 0190 const QStringList args(value.split(QChar::fromLatin1('@'))); 0191 if (args.isEmpty()) { 0192 return; 0193 } 0194 _exception.second = args[0].trimmed(); 0195 if (args.size() > 1) { 0196 _exception.first = args[1].trimmed(); 0197 } 0198 } 0199 0200 const QString &appName() const 0201 { 0202 return _exception.first; 0203 } 0204 0205 const QString &className() const 0206 { 0207 return _exception.second; 0208 } 0209 0210 private: 0211 QPair<QString, QString> _exception; 0212 0213 friend size_t qHash(const ExceptionId &value, size_t seed = 0) 0214 { 0215 return qHash(value._exception, seed); 0216 } 0217 0218 friend bool operator==(const ExceptionId &lhs, const ExceptionId &rhs) 0219 { 0220 return lhs._exception == rhs._exception; 0221 } 0222 }; 0223 0224 //* exception set 0225 using ExceptionSet = QSet<ExceptionId>; 0226 0227 //* list of white listed special widgets 0228 /** 0229 it is read from options and is used to adjust 0230 per-app window dragging issues 0231 */ 0232 ExceptionSet _whiteList; 0233 0234 //* list of black listed special widgets 0235 /** 0236 it is read from options and is used to adjust 0237 per-app window dragging issues 0238 */ 0239 ExceptionSet _blackList; 0240 0241 //* drag point 0242 QPoint _dragPoint; 0243 QPoint _globalDragPoint; 0244 0245 //* drag timer 0246 QBasicTimer _dragTimer; 0247 0248 //* target being dragged 0249 /** Weak pointer is used in case the target gets deleted while drag is in progress */ 0250 WeakPointer<QWidget> _target; 0251 0252 #if BREEZE_HAVE_QTQUICK 0253 WeakPointer<QQuickItem> _quickTarget; 0254 #endif 0255 0256 //* true if drag is about to start 0257 bool _dragAboutToStart = false; 0258 0259 //* true if drag is in progress 0260 bool _dragInProgress = false; 0261 0262 //* true if drag is locked 0263 bool _locked = false; 0264 0265 //* true if the event we are intercepting passed trough a QQuickWidget. 0266 /**In this case we shouldn't start a drag, because if it was to start, we would have done it in the event filter of a qquickwidget. 0267 * Event handlers don't accept input events, but they do block QQuickItems to receive the event, so the event may have been 0268 * managed by an handler and not blocked by the root qml item. 0269 **/ 0270 bool _eventInQQuickWidget = false; 0271 0272 //* application event filter 0273 QObject *_appEventFilter = nullptr; 0274 0275 //* allow access of all private members to the app event filter 0276 friend class AppEventFilter; 0277 }; 0278 0279 //____________________________________________________________________ 0280 template<typename T> 0281 T WindowManager::findParent(const QWidget *widget) const 0282 { 0283 if (!widget) { 0284 return nullptr; 0285 } 0286 for (QWidget *parent = widget->parentWidget(); parent; parent = parent->parentWidget()) { 0287 if (T cast = qobject_cast<T>(parent)) { 0288 return cast; 0289 } 0290 } 0291 0292 return nullptr; 0293 } 0294 0295 }