You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

320 lines
8.4 KiB

#ifndef breezewindowmanager_h
#define breezewindowmanager_h
//////////////////////////////////////////////////////////////////////////////
// breezewindowmanager.h
// pass some window mouse press/release/move event actions to window manager
// -------------------
//
// Copyright (C) 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License version 2 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this library; see the file COPYING.LIB. If not, write to
// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
// Boston, MA 02110-1301, USA.
//////////////////////////////////////////////////////////////////////////////
#include "breeze.h"
#include <QEvent>
#include <QBasicTimer>
#include <QObject>
#include <QSet>
#include <QString>
#include <QWidget>
#if HAVE_X11
#include <xcb/xcb.h>
#endif
namespace Breeze
{
class WindowManager: public QObject
{
Q_OBJECT
public:
//* constructor
explicit WindowManager( QObject* );
//* destructor
virtual ~WindowManager( void )
{}
//* initialize
/** read relevant options from BreezeStyleConfigData */
void initialize( void );
//* register widget
void registerWidget( QWidget* );
//* unregister widget
void unregisterWidget( QWidget* );
//* event filter [reimplemented]
virtual bool eventFilter( QObject*, QEvent* );
protected:
//* timer event,
/** used to start drag if button is pressed for a long enough time */
void timerEvent( QTimerEvent* );
//* mouse press event
bool mousePressEvent( QObject*, QEvent* );
//* mouse move event
bool mouseMoveEvent( QObject*, QEvent* );
//* mouse release event
bool mouseReleaseEvent( QObject*, QEvent* );
//*@name configuration
//@{
//* enable state
bool enabled( void ) const
{ return _enabled; }
//* enable state
void setEnabled( bool value )
{ _enabled = value; }
//* returns true if window manager is used for moving
bool useWMMoveResize( void ) const
{ return supportWMMoveResize() && _useWMMoveResize; }
//* use window manager for moving, when available
void setUseWMMoveResize( bool value )
{ _useWMMoveResize = value; }
//* drag mode
int dragMode( void ) const
{ return _dragMode; }
//* drag mode
void setDragMode( int value )
{ _dragMode = value; }
//* drag distance (pixels)
void setDragDistance( int value )
{ _dragDistance = value; }
//* drag delay (msec)
void setDragDelay( int value )
{ _dragDelay = value; }
//* set list of whiteListed widgets
/**
white list is read from options and is used to adjust
per-app window dragging issues
*/
void initializeWhiteList();
//* set list of blackListed widgets
/**
black list is read from options and is used to adjust
per-app window dragging issues
*/
void initializeBlackList( void );
//@}
//* returns true if widget is dragable
bool isDragable( QWidget* );
//* returns true if widget is dragable
bool isBlackListed( QWidget* );
//* returns true if widget is dragable
bool isWhiteListed( QWidget* ) const;
//* returns true if drag can be started from current widget
bool canDrag( QWidget* );
//* returns true if drag can be started from current widget and position
/** child at given position is passed as second argument */
bool canDrag( QWidget*, QWidget*, const QPoint& );
//* reset drag
void resetDrag( void );
//* start drag
void startDrag( QWidget*, const QPoint& );
//* returns true if window manager is used for moving
/** right now this is true only for X11 */
bool supportWMMoveResize( void ) const;
//* utility function
bool isDockWidgetTitle( const QWidget* ) const;
//*@name lock
//@{
void setLocked( bool value )
{ _locked = value; }
//* lock
bool isLocked( void ) const
{ return _locked; }
//@}
//* returns first widget matching given class, or 0L if none
template<typename T> T findParent( const QWidget* ) const;
private:
//* enability
bool _enabled;
//* use WM moveResize
bool _useWMMoveResize;
//* drag mode
int _dragMode;
//* drag distance
/** this is copied from kwin::geometry */
int _dragDistance;
//* drag delay
/** this is copied from kwin::geometry */
int _dragDelay;
//* wrapper for exception id
class ExceptionId: public QPair<QString, QString>
{
public:
//* constructor
explicit ExceptionId( const QString& value )
{
const QStringList args( value.split( QChar::fromLatin1( '@' ) ) );
if( args.isEmpty() ) return;
second = args[0].trimmed();
if( args.size()>1 ) first = args[1].trimmed();
}
const QString& appName( void ) const
{ return first; }
const QString& className( void ) const
{ return second; }
};
//* exception set
typedef QSet<ExceptionId> ExceptionSet;
//* list of white listed special widgets
/**
it is read from options and is used to adjust
per-app window dragging issues
*/
ExceptionSet _whiteList;
//* list of black listed special widgets
/**
it is read from options and is used to adjust
per-app window dragging issues
*/
ExceptionSet _blackList;
//* drag point
QPoint _dragPoint;
QPoint _globalDragPoint;
//* drag timer
QBasicTimer _dragTimer;
//* target being dragged
/** Weak pointer is used in case the target gets deleted while drag is in progress */
WeakPointer<QWidget> _target;
//* true if drag is about to start
bool _dragAboutToStart;
//* true if drag is in progress
bool _dragInProgress;
//* true if drag is locked
bool _locked;
//* cursor override
/** used to keep track of application cursor being overridden when dragging in non-WM mode */
bool _cursorOverride;
//* provide application-wise event filter
/**
it us used to unlock dragging and make sure event look is properly restored
after a drag has occurred
*/
class AppEventFilter: public QObject
{
public:
//* constructor
explicit AppEventFilter( WindowManager* parent ):
QObject( parent ),
_parent( parent )
{}
//* event filter
virtual bool eventFilter( QObject*, QEvent* );
protected:
//* application-wise event.
/** needed to catch end of XMoveResize events */
bool appMouseEvent( QObject*, QEvent* );
private:
//* parent
WindowManager* _parent;
};
//* application event filter
AppEventFilter* _appEventFilter;
#if HAVE_X11
xcb_atom_t _moveResizeAtom;
#endif
//* allow access of all private members to the app event filter
friend class AppEventFilter;
};
//____________________________________________________________________
template<typename T>
T WindowManager::findParent( const QWidget* widget ) const
{
if( !widget ) return 0L;
for( QWidget* parent = widget->parentWidget(); parent; parent = parent->parentWidget() )
{ if( T cast = qobject_cast<T>(parent) ) return cast; }
return 0L;
}
}
#endif