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