1 /*****************************************************************************
2  *   Copyright 2010 Craig Drummond <craig.p.drummond@gmail.com>              *
3  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
4  *                                                                           *
5  *   This program is free software; you can redistribute it and/or modify    *
6  *   it under the terms of the GNU Lesser General Public License as          *
7  *   published by the Free Software Foundation; either version 2.1 of the    *
8  *   License, or (at your option) version 3, or any later version accepted   *
9  *   by the membership of KDE e.V. (or its successor approved by the         *
10  *   membership of KDE e.V.), which shall act as a proxy defined in          *
11  *   Section 6 of version 3 of the license.                                  *
12  *                                                                           *
13  *   This program is distributed in the hope that it will be useful,         *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
16  *   Lesser General Public License for more details.                         *
17  *                                                                           *
18  *   You should have received a copy of the GNU Lesser General Public        *
19  *   License along with this library. If not,                                *
20  *   see <http://www.gnu.org/licenses/>.                                     *
21  *****************************************************************************/
22 
23 #ifndef __WINDOW_MANAGER_H__
24 #define __WINDOW_MANAGER_H__
25 
26 // Copied from oxygenwindowmanager.h svnversion: 1137195
27 
28 //////////////////////////////////////////////////////////////////////////////
29 // windowmanager.h
30 // pass some window mouse press/release/move event actions to window manager
31 // -------------------
32 //
33 // Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
34 //
35 // Largely inspired from BeSpin style
36 // Copyright (C) 2007 Thomas Luebking <thomas.luebking@web.de>
37 //
38 // Permission is hereby granted, free of charge, to any person obtaining a copy
39 // of this software and associated documentation files (the "Software"), to
40 // deal in the Software without restriction, including without limitation the
41 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
42 // sell copies of the Software, and to permit persons to whom the Software is
43 // furnished to do so, subject to the following conditions:
44 //
45 // The above copyright notice and this permission notice shall be included in
46 // all copies or substantial portions of the Software.
47 //
48 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
49 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
50 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
51 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
52 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
53 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
54 // IN THE SOFTWARE.
55 //////////////////////////////////////////////////////////////////////////////
56 
57 #include <QEvent>
58 #include <QBasicTimer>
59 #include <QSet>
60 #include <QString>
61 #include <QPointer>
62 #include <QWidget>
63 
64 namespace QtCurve {
65 class WindowManager: public QObject {
66     Q_OBJECT
67 public:
68     explicit WindowManager(QObject*);
69 
70     //! initialize
71     /*! read relevant options from OxygenStyleConfigData */
72     void initialize( int windowDrag, const QStringList &whiteList=QStringList(),
73                      const QStringList &blackList=QStringList());
74 
75     //! register widget
76     void registerWidget(QWidget*);
77 
78     //! unregister widget
79     void unregisterWidget(QWidget*);
80 
81     //! event filter [reimplemented]
82     bool eventFilter(QObject*, QEvent*) override;
83 
84 protected:
85     //! timer event,
86     /*! used to start drag if button is pressed for a long enough time */
87     void timerEvent(QTimerEvent*) override;
88     //! mouse press event
89     bool mousePressEvent( QObject*, QEvent* );
90     //! mouse move event
91     bool mouseMoveEvent( QObject*, QEvent* );
92     //! mouse release event
93     bool mouseReleaseEvent( QObject*, QEvent* );
94     //!@name configuration
95     //@{
96     //! enable state
97     bool
enabled()98     enabled() const
99     {
100         return _enabled;
101     }
102 
103     //! enable state
104     void
setEnabled(bool value)105     setEnabled(bool value)
106     {
107         _enabled = value;
108     }
109 
110     //! returns true if window manager is used for moving
111     bool
useWMMoveResize()112     useWMMoveResize() const
113     {
114         return _useWMMoveResize;
115     }
116 
117     //! drag mode
dragMode()118     int dragMode() const
119     {
120         return _dragMode;
121     }
122 
123     //! drag mode
setDragMode(int value)124     void setDragMode(int value)
125     {
126         _dragMode = value;
127     }
128 
129     //! drag distance (pixels)
setDragDistance(int value)130     void setDragDistance(int value)
131     {
132         _dragDistance = value;
133     }
134 
135     //! drag delay (msec)
setDragDelay(int value)136     void setDragDelay(int value)
137     {
138         _dragDelay = value;
139     }
140 
141     //! set list of whiteListed widgets
142     /*!
143       white list is read from options and is used to adjust
144       per-app window dragging issues
145     */
146     void initializeWhiteList(const QStringList &list);
147 
148     //! set list of blackListed widgets
149     /*!
150       black list is read from options and is used to adjust
151       per-app window dragging issues
152     */
153     void initializeBlackList(const QStringList &list);
154 
155     //@}
156 
157     //! returns true if widget is dragable
158     bool isDragable(QWidget*);
159 
160     //! returns true if widget is dragable
161     bool isBlackListed(QWidget*);
162 
163     //! returns true if widget is dragable
164     bool isWhiteListed(QWidget*) const;
165 
166     //! returns true if drag can be started from current widget
167     bool canDrag(QWidget*);
168 
169     //! returns true if drag can be started from current widget and position
170     /*! child at given position is passed as second argument */
171     bool canDrag(QWidget*, QWidget*, const QPoint&);
172 
173     //! reset drag
174     void resetDrag();
175 
176     //! start drag
177     void startDrag(QWidget*, const QPoint&);
178 
179     //! utility function
180     bool isDockWidgetTitle(const QWidget*) const;
181 
182     //!@name lock
183     //@{
184 
185     void
setLocked(bool value)186     setLocked(bool value)
187     {
188         _locked = value;
189     }
190 
191     //! lock
192     bool
isLocked()193     isLocked() const
194     {
195         return _locked;
196     }
197 
198     //@}
199 
200 private:
201     //! enability
202     bool _enabled;
203 
204     //! use WM moveResize
205     bool _useWMMoveResize;
206 
207     //! drag mode
208     int _dragMode;
209 
210     //! drag distance
211     /*! this is copied from kwin::geometry */
212     int _dragDistance;
213 
214     //! drag delay
215     /*! this is copied from kwin::geometry */
216     int _dragDelay;
217 
218     //! wrapper for exception id
219     class ExceptionId: public QPair<QString, QString> {
220     public:
221         //! constructor
ExceptionId(const QString & value)222         ExceptionId(const QString &value)
223         {
224             const QStringList args(value.split("@"));
225             if (args.isEmpty())
226                 return;
227             second = args[0].trimmed();
228             if (args.size() > 1) {
229                 first = args[1].trimmed();
230             }
231         }
232 
233         const QString&
appName()234         appName() const
235         {
236             return first;
237         }
238 
239         const QString&
className()240         className() const
241         {
242             return second;
243         }
244     };
245 
246     //! exception set
247     typedef QSet<ExceptionId> ExceptionSet;
248 
249     //! list of white listed special widgets
250     /*!
251       it is read from options and is used to adjust
252       per-app window dragging issues
253     */
254     ExceptionSet _whiteList;
255 
256     //! list of black listed special widgets
257     /*!
258       it is read from options and is used to adjust
259       per-app window dragging issues
260     */
261     ExceptionSet _blackList;
262 
263     //! drag point
264     QPoint _dragPoint;
265     QPoint _globalDragPoint;
266 
267     //! drag timer
268     QBasicTimer _dragTimer;
269 
270     //! target being dragged
271     /*! QPointer is used in case the target gets deleted while drag
272       is in progress */
273     QPointer<QWidget> _target;
274 
275     //! true if drag is about to start
276     bool _dragAboutToStart;
277 
278     //! true if drag is in progress
279     bool _dragInProgress;
280 
281     //! true if drag is locked
282     bool _locked;
283 
284     //! cursor override
285     /*! used to keep track of application cursor being overridden when dragging in non-WM mode */
286     bool _cursorOverride;
287 
288     //! provide application-wise event filter
289     /*!
290       it us used to unlock dragging and make sure event look is properly restored
291       after a drag has occurred
292     */
293     class AppEventFilter: public QObject {
294     public:
295         //! constructor
AppEventFilter(WindowManager * parent)296         AppEventFilter(WindowManager* parent):
297             QObject(parent),
298             _parent(parent)
299         {}
300 
301         //! event filter
302         bool eventFilter( QObject*, QEvent* ) override;
303 
304     protected:
305         //! application-wise event.
306         /*! needed to catch end of XMoveResize events */
307         bool appMouseEvent( QObject*, QEvent* );
308 
309     private:
310         //! parent
311         WindowManager* _parent;
312     };
313 
314     //! application event filter
315     AppEventFilter* _appEventFilter;
316 
317     //! allow access of all private members to the app event filter
318     friend class AppEventFilter;
319 };
320 
321 }
322 
323 #endif
324