1 /*
2  * Copyright (C) Pedram Pourang (aka Tsu Jan) 2020 <tsujan2000@gmail.com>
3  *
4  * Kvantum is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Kvantum is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef WINDOWMANAGER_H
19 #define WINDOWMANAGER_H
20 
21 #include <QBasicTimer>
22 #include <QSet>
23 #include <QPointer>
24 #include <QWindow>
25 #include <QWidget>
26 
27 namespace Kvantum {
28 
29 class WindowManager: public QObject
30 {
31   Q_OBJECT
32 public:
33   enum Drag {
34     DRAG_NONE,
35     DRAG_MENUBAR_ONLY,
36     DRAG_MENUBAR_AND_PRIMARY_TOOLBAR,
37     DRAG_ALL,
38 
39     DRAG_COUNT
40   };
41 
toDrag(const QString & str)42   static Drag toDrag (const QString &str) {
43     for (int i = 0; i < DRAG_COUNT; ++i)
44     {
45       if (toStr (static_cast<Drag>(i)) == str)
46         return static_cast<Drag>(i);
47     }
48     return DRAG_NONE;
49   }
50 
toStr(Drag drag)51   static QString toStr (Drag drag) {
52     switch (drag)
53     {
54       default:
55       case DRAG_ALL: return "all";
56       case DRAG_NONE: return "none";
57       case DRAG_MENUBAR_ONLY: return "menubar";
58       case DRAG_MENUBAR_AND_PRIMARY_TOOLBAR: return "menubar_and_primary_toolbar";
59     }
60   }
61 
62   explicit WindowManager (QObject *parent, Drag drag, bool dragFromBtns);
63   ~WindowManager();
64 
65   void initialize (const QStringList &blackList = QStringList());
66 
67   void registerWidget (QWidget *widget);
68   void unregisterWidget (QWidget *widget);
69   virtual bool eventFilter (QObject *object, QEvent *event);
70 
71   /* needed in "Kvantum.cpp" for animations
72      and also for the workaround of hover bug */
dragInProgress()73   bool dragInProgress() const {
74     return dragInProgress_;
75   }
76 
77 protected:
78   void timerEvent (QTimerEvent *event);
79   bool mousePressEvent (QObject *object, QEvent *event);
80   bool mouseMoveEvent (QEvent *event);
81   bool mouseReleaseEvent (QEvent *event);
82   bool leavingWindow();
83 
enabled()84   bool enabled() const {
85     return enabled_;
86   }
setEnabled(bool value)87   void setEnabled (bool value) {
88     enabled_ = value;
89   }
90 
91   void initializeBlackList (const QStringList &list);
92   bool isBlackListed (QWidget *widget);
93   bool canDrag (QWidget *widget);
94   bool isDraggable (QWidget *widget);
95   void resetDrag();
96 
isLocked()97   bool isLocked() const {
98     return locked_;
99   }
unlock()100   void unlock() {
101     locked_ = false;
102     dragInProgress_ = false;
103   }
104 
105 private:
106   bool enabled_;
107   int dragDistance_;
108   int dragDelay_;
109   int doubleClickInterval_;
110   bool isDelayed_;
111 
112   // wrapper for exception id
113   class ExceptionId: public QPair<QString, QString>
114   {
115   public:
ExceptionId(const QString & value)116     ExceptionId (const QString &value) {
117       const QStringList args (value.split (QStringLiteral("@")));
118       if (args.isEmpty())
119         return;
120       second = args[0].trimmed();
121       if (args.size() > 1)
122         first = args[1].trimmed();
123     }
appName()124     const QString& appName() const {
125       return first;
126     }
className()127     const QString& className() const {
128       return second;
129     }
130   };
131 
132   typedef QSet<ExceptionId> ExceptionSet;
133   ExceptionSet blackList_;
134 
135   QPoint widgetDragPoint_;
136   QPoint globalDragPoint_;
137   QPoint lastWinDragPoint_; // used to find double clicks
138   QBasicTimer dragTimer_;
139   QBasicTimer doubleClickTimer_;
140   QPointer<QWindow> winTarget_;
141   QPointer<QWindow> lastWin_;
142   QPointer<QWidget> widgetTarget_;
143   QPointer<QWidget> pressedWidget_;
144   QPointer<QWidget> lastPressedWidget_;
145   bool dragAboutToStart_;
146   bool dragInProgress_;
147   bool locked_;
148   bool dragFromBtns_;
149   Drag drag_;
150 
151   /*
152      provide application-wise event filter
153      (used to unlock dragging and checking some mouse events)
154   */
155   class AppEventFilter: public QObject
156   {
157   public:
AppEventFilter(WindowManager * parent)158     AppEventFilter (WindowManager *parent) :
159                     QObject (parent),
160                     parent_ (parent) {}
161     virtual bool eventFilter (QObject *object, QEvent *event);
162 
163   private:
164     WindowManager *parent_;
165   };
166 
167   AppEventFilter *_appEventFilter;
168   /* allow access of all private members to the app event filter */
169   friend class AppEventFilter;
170 };
171 
172 }
173 
174 #endif
175