File indexing completed on 2024-04-28 05:32:21
0001 #ifndef oxygenwindowmanager_h 0002 #define oxygenwindowmanager_h 0003 0004 /* 0005 * oxygenwindowmanager.h 0006 * pass some window mouse press/release/move event actions to window manager 0007 * ------------------- 0008 * 0009 * SPDX-FileCopyrightText: 2010 Cédric Bellegarde <gnumdk@gmail.com> 0010 * SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0011 * 0012 * Largely inspired from Qtcurve style 0013 * SPDX-FileCopyrightText: 2003-2010 Craig Drummond <craig.p.drummond@gmail.com> 0014 * 0015 * SPDX-License-Identifier: LGPL-2.0-or-later 0016 */ 0017 0018 #include "oxygendatamap.h" 0019 #include "oxygengtkutils.h" 0020 #include "oxygenhook.h" 0021 #include "oxygensignal.h" 0022 #include "oxygentimer.h" 0023 0024 #include <gtk/gtk.h> 0025 #include <algorithm> 0026 #include <string> 0027 #include <vector> 0028 0029 namespace Oxygen 0030 { 0031 0032 class WindowManager 0033 { 0034 0035 public: 0036 0037 //! constructor 0038 WindowManager( void ); 0039 0040 //! destructor 0041 virtual ~WindowManager(); 0042 0043 //! initialize hooks 0044 void initializeHooks( void ); 0045 0046 //! returns true if window manager is used for moving 0047 bool useWMMoveResize( void ) const 0048 { return _useWMMoveResize; } 0049 0050 //! use window manager for moving, when available 0051 void setUseWMMoveResize( bool value ) 0052 { _useWMMoveResize = value; } 0053 0054 //! window grab mode 0055 enum Mode 0056 { 0057 Disabled, 0058 Minimal, 0059 Full 0060 }; 0061 0062 //! window grab mode 0063 void setDragMode( Mode mode ); 0064 0065 //! drag distance 0066 void setDragDistance( int value ) 0067 { _dragDistance = value; } 0068 0069 //! drag delay 0070 void setDragDelay( int value ) 0071 { _dragDelay = value; } 0072 0073 protected: 0074 0075 //!@name callbacks 0076 //@{ 0077 0078 //! on motion event 0079 static gboolean wmMotion( GtkWidget*, GdkEventMotion*, gpointer ); 0080 0081 //! on button press 0082 static gboolean wmButtonPress( GtkWidget*, GdkEventButton*, gpointer ); 0083 0084 //! on mouse leave 0085 static gboolean wmLeave(GtkWidget*, GdkEventCrossing*, gpointer ); 0086 0087 //! on window destroy 0088 static gboolean wmDestroy( GtkWidget*, gpointer ); 0089 0090 //! on window destroy 0091 static gboolean wmBlackListDestroy( GtkWidget*, gpointer ); 0092 0093 //! delayed drag 0094 static gboolean startDelayedDrag( gpointer ); 0095 0096 //! style-set hook 0097 static gboolean styleSetHook( GSignalInvocationHint*, guint, const GValue*, gpointer ); 0098 0099 //! mouse button release event hook 0100 static gboolean buttonReleaseHook( GSignalInvocationHint*, guint, const GValue*, gpointer ); 0101 0102 //@} 0103 0104 //! register widget 0105 /*! returns true if widget is effictively registered */ 0106 bool registerWidget( GtkWidget* ); 0107 0108 //! unregister widget 0109 void unregisterWidget( GtkWidget* ); 0110 0111 //! register blacklist widget 0112 bool registerBlackListWidget( GtkWidget* ); 0113 0114 //! unregister blacklist widget 0115 void unregisterBlackListWidget( GtkWidget* ); 0116 0117 //! start dragging widget 0118 bool startDrag( GtkWidget*, GdkEventMotion* ); 0119 0120 //! start dragging widget 0121 bool startDrag( GtkWidget*, int, int, guint32 ); 0122 0123 //! start dragging widget 0124 void startDrag( void ) 0125 { if( _dragAboutToStart && _widget ) startDrag( _widget, _globalX, _globalY, _time ); } 0126 0127 //! set cursor 0128 void setCursor( GtkWidget* ); 0129 0130 //! unset cursor 0131 void unsetCursor( GtkWidget* ); 0132 0133 //! finish dragging widget 0134 bool resetDrag( void ); 0135 0136 //! return true if window is dragable 0137 bool canDrag( GtkWidget*, GdkEventButton* ); 0138 0139 //! check cursor 0140 bool checkCursor( GdkWindow* ) const; 0141 0142 //! return true if event happen in widget 0143 bool withinWidget( GtkWidget*, GdkEventButton* ) const; 0144 0145 //! return true if event is a usable drag event 0146 bool useEvent( GtkWidget*, GdkEventButton* ); 0147 0148 //! drag status 0149 enum DragStatus 0150 { 0151 Accepted = 0, 0152 BlackListed, 0153 WidgetIsPrelight, 0154 WidgetIsButton, 0155 WidgetIsMenuItem, 0156 WidgetIsScrolledWindow, 0157 WidgetIsTabLabel, 0158 InvalidWindow, 0159 InvalidEventMask 0160 }; 0161 0162 //! return string matching drag status, for debugging 0163 std::string dragStatusString( DragStatus ) const; 0164 0165 //! return whether event is a usable drag event 0166 /*! for containers, children are also checked. The method is recursive */ 0167 DragStatus childrenUseEvent( GtkWidget*, GdkEventButton*, bool ) const; 0168 0169 //! used to decide whether a widget is black-listed 0170 class BlackListFTor 0171 { 0172 public: 0173 0174 //! constructor 0175 BlackListFTor( GObject* object ): 0176 _object( object ) 0177 {} 0178 0179 //! predicate 0180 bool operator() (const std::string& objectName ) const 0181 { return Gtk::g_object_is_a( _object, objectName ); } 0182 0183 private: 0184 0185 //! object 0186 GObject* _object; 0187 0188 }; 0189 0190 //! initialize black list 0191 /*! stores list of widgets for which you do not want the window to be grabbed */ 0192 void initializeBlackList( void ); 0193 0194 //! return true if widget is black listed for grabbing 0195 bool widgetIsBlackListed( GtkWidget* widget ) const; 0196 0197 //! return true if widget has a black listed parent 0198 bool widgetHasBlackListedParent( GtkWidget* widget ) const; 0199 0200 //! stores connections 0201 class Data 0202 { 0203 public: 0204 0205 //! constructor 0206 Data( void ) 0207 {} 0208 0209 //! destructor 0210 virtual ~Data( void ) 0211 {} 0212 0213 //! connect 0214 /*! it is needed to insert in DataMap, but does nothing */ 0215 virtual void connect( GtkWidget* ) 0216 {} 0217 0218 //! disconnect 0219 virtual void disconnect( GtkWidget* ); 0220 0221 //!@name signals 0222 //@{ 0223 Signal _leaveId; 0224 Signal _destroyId; 0225 Signal _pressId; 0226 Signal _motionId; 0227 //@} 0228 0229 }; 0230 0231 //! perform connections between widget and data 0232 void connect( GtkWidget*, Data& ); 0233 0234 private: 0235 0236 //! use WM moveResize 0237 bool _useWMMoveResize; 0238 0239 //! cursor 0240 bool _cursorLoaded; 0241 GdkCursor* _cursor; 0242 GdkCursor* _oldCursor; 0243 0244 //! drag mode 0245 Mode _dragMode; 0246 0247 //! true when hooks are initialized 0248 bool _hooksInitialized; 0249 0250 //! style set hook. Used to register widgets 0251 Hook _styleSetHook; 0252 0253 //! mouse button release event hook 0254 Hook _buttonReleaseHook; 0255 0256 //! timer 0257 Timer _timer; 0258 0259 //! true if in drag can start 0260 bool _dragAboutToStart; 0261 0262 //! true if dragging 0263 bool _dragInProgress; 0264 0265 //! drag distance 0266 int _dragDistance; 0267 0268 //! drag delay 0269 int _dragDelay; 0270 0271 //! active widget 0272 GtkWidget* _widget; 0273 0274 //! keep track of the last rejected button event to reject it again if passed to some parent widget 0275 /*! this spares some time (by not processing the same event twice), and prevents some bugs */ 0276 GdkEventButton* _lastRejectedEvent; 0277 0278 //! drag position 0279 int _x; 0280 int _y; 0281 0282 //! drag position 0283 int _globalX; 0284 int _globalY; 0285 0286 //! drag time 0287 guint32 _time; 0288 0289 //! widget typenames black-list 0290 typedef std::vector<std::string> BlackList; 0291 BlackList _blackList; 0292 0293 //! widget black-list 0294 typedef std::map< GtkWidget*, Signal > WidgetMap; 0295 WidgetMap _blackListWidgets; 0296 0297 //! map widgets to data structure 0298 DataMap<Data> _map; 0299 0300 }; 0301 0302 } 0303 0304 #endif