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.
 
 
 
 

274 lines
7.1 KiB

/*
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef breezewindowmanager_h
#define breezewindowmanager_h
#include "breeze.h"
#include "breezestyleconfigdata.h"
#include "config-breeze.h"
#include <QEvent>
#include <QApplication>
#include <QBasicTimer>
#include <QObject>
#include <QSet>
#include <QString>
#include <QWidget>
#if BREEZE_HAVE_QTQUICK
#include <QQuickItem>
#endif
namespace Breeze
{
class WindowManager: public QObject
{
Q_OBJECT
public:
//* constructor
explicit WindowManager( QObject* );
//* initialize
/** read relevant options from config */
void initialize();
//* register widget
void registerWidget( QWidget* );
#if BREEZE_HAVE_QTQUICK
//* register quick item
void registerQuickItem( QQuickItem* );
#endif
//* unregister widget
void unregisterWidget( QWidget* );
//* event filter [reimplemented]
bool eventFilter( QObject*, QEvent* ) override;
protected:
//* timer event,
/** used to start drag if button is pressed for a long enough time */
void timerEvent( QTimerEvent* ) override;
//* 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() const
{ return _enabled; }
//* enable state
void setEnabled( bool value )
{ _enabled = value; }
//* drag mode
int dragMode() 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();
//@}
//* 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();
//* start drag
void startDrag( QWindow* );
//* utility function
bool isDockWidgetTitle( const QWidget* ) const;
//*@name lock
//@{
void setLocked( bool value )
{ _locked = value; }
//* lock
bool isLocked() const
{ return _locked; }
//@}
//* returns first widget matching given class, or nullptr if none
template<typename T> T findParent( const QWidget* ) const;
private:
//* enability
bool _enabled = true;
//* drag mode
int _dragMode = StyleConfigData::WD_FULL;
//* drag distance
/** this is copied from kwin::geometry */
int _dragDistance = QApplication::startDragDistance();
//* drag delay
/** this is copied from kwin::geometry */
int _dragDelay = QApplication::startDragTime();
//* wrapper for exception id
class ExceptionId
{
public:
//* constructor
explicit ExceptionId( const QString& value )
{
const QStringList args( value.split( QChar::fromLatin1( '@' ) ) );
if( args.isEmpty() ) return;
_exception.second = args[0].trimmed();
if( args.size()>1 ) _exception.first = args[1].trimmed();
}
const QString& appName() const
{ return _exception.first; }
const QString& className() const
{ return _exception.second; }
private:
QPair<QString, QString> _exception;
friend uint qHash( const ExceptionId& value )
{ return qHash(value._exception); }
friend bool operator == ( const ExceptionId& lhs, const ExceptionId& rhs )
{ return lhs._exception == rhs._exception; }
};
//* exception set
using ExceptionSet = QSet<ExceptionId>;
//* 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;
#if BREEZE_HAVE_QTQUICK
WeakPointer<QQuickItem> _quickTarget;
#endif
//* true if drag is about to start
bool _dragAboutToStart = false;
//* true if drag is in progress
bool _dragInProgress = false;
//* true if drag is locked
bool _locked = false;
//* true if the event we are intercepting passed trough a QQuickWidget.
/**In this case we shouldn't start a drag, because if it was to start, we would have done it in the event filter of a qquickwidget.
* Event handlers don't accept input events, but they do block QQuickItems to receive the event, so the event may have been
* managed by an handler and not blocked by the root qml item.
**/
bool _eventInQQuickWidget = false;
//* application event filter
QObject* _appEventFilter = nullptr;
//* 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 nullptr;
for( QWidget* parent = widget->parentWidget(); parent; parent = parent->parentWidget() )
{ if( T cast = qobject_cast<T>(parent) ) return cast; }
return nullptr;
}
}
#endif