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