QStateMachine was moved to qtsxml module, which is not ported to Qt6 yet. We use QStateMachine for the semantics it gives us, not because of its implementation. The implementation is trivial, so do it outselves. We used very little from QStateMachine.
212 lines
5.7 KiB
C++
212 lines
5.7 KiB
C++
/*
|
|
This file is part of KDDockWidgets.
|
|
|
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
|
|
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
|
*/
|
|
|
|
#ifndef KD_DRAGCONTROLLER_P_H
|
|
#define KD_DRAGCONTROLLER_P_H
|
|
|
|
#include "docks_export.h"
|
|
|
|
#include "TitleBar_p.h"
|
|
#include "WindowBeingDragged_p.h"
|
|
|
|
#include <QPoint>
|
|
#include <QMimeData>
|
|
|
|
#include <memory>
|
|
|
|
namespace KDDockWidgets {
|
|
|
|
class StateBase;
|
|
class DropArea;
|
|
class Draggable;
|
|
class FallbackMouseGrabber;
|
|
class MinimalStateMachine;
|
|
|
|
class State : public QObject
|
|
{
|
|
public:
|
|
explicit State(MinimalStateMachine *parent);
|
|
|
|
template <typename Obj, typename Signal>
|
|
void addTransition(Obj *, Signal, State *dest);
|
|
bool isCurrentState() const;
|
|
|
|
virtual void onEntry() = 0;
|
|
private:
|
|
MinimalStateMachine *const m_machine;
|
|
};
|
|
|
|
class MinimalStateMachine : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit MinimalStateMachine(QObject *parent = nullptr);
|
|
|
|
State *currentState() const;
|
|
void setCurrentState(State *);
|
|
|
|
private:
|
|
State *m_currentState = nullptr;
|
|
};
|
|
|
|
class DOCKS_EXPORT DragController : public MinimalStateMachine
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
enum State {
|
|
State_None = 0,
|
|
State_PreDrag,
|
|
State_Dragging
|
|
};
|
|
Q_ENUM(State)
|
|
|
|
static DragController *instance();
|
|
|
|
// Registers something that wants to be able to be dragged
|
|
void registerDraggable(Draggable *);
|
|
void unregisterDraggable(Draggable *);
|
|
|
|
bool isDragging() const;
|
|
bool isInNonClientDrag() const;
|
|
bool isInClientDrag() const;
|
|
|
|
void grabMouseFor(QWidgetOrQuick *);
|
|
void releaseMouse(QWidgetOrQuick *);
|
|
|
|
FloatingWindow *floatingWindowBeingDragged() const;
|
|
|
|
///@brief Returns the window being dragged
|
|
WindowBeingDragged* windowBeingDragged() const;
|
|
|
|
/// Experimental, internal, not for general use.
|
|
void enableFallbackMouseGrabber();
|
|
|
|
Q_SIGNALS:
|
|
void mousePressed();
|
|
void manhattanLengthMove();
|
|
void dragCanceled();
|
|
void dropped();
|
|
|
|
protected:
|
|
bool eventFilter(QObject *, QEvent *) override;
|
|
|
|
private:
|
|
friend class StateBase;
|
|
friend class StateNone;
|
|
friend class StatePreDrag;
|
|
friend class StateDragging;
|
|
friend class StateDropped;
|
|
friend class StateDraggingWayland;
|
|
|
|
DragController(QObject * = nullptr);
|
|
StateBase *activeState() const;
|
|
WidgetType *qtTopLevelUnderCursor() const;
|
|
DropArea *dropAreaUnderCursor() const;
|
|
Draggable *draggableForQObject(QObject *o) const;
|
|
QPoint m_pressPos;
|
|
QPoint m_offset;
|
|
|
|
Draggable::List m_draggables;
|
|
Draggable *m_draggable = nullptr;
|
|
std::unique_ptr<WindowBeingDragged> m_windowBeingDragged;
|
|
DropArea *m_currentDropArea = nullptr;
|
|
bool m_nonClientDrag = false;
|
|
FallbackMouseGrabber *m_fallbackMouseGrabber = nullptr;
|
|
};
|
|
|
|
class StateBase : public State
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit StateBase(DragController *parent);
|
|
~StateBase();
|
|
|
|
// Not using QEvent here, to abstract platform differences regarding production of such events
|
|
virtual bool handleMouseButtonPress(Draggable * /*receiver*/, QPoint /*globalPos*/, QPoint /*pos*/) { return false; }
|
|
virtual bool handleMouseMove(QPoint /*globalPos*/) { return false; }
|
|
virtual bool handleMouseButtonRelease(QPoint /*globalPos*/) { return false; }
|
|
virtual bool handleMouseDoubleClick() { return false; }
|
|
|
|
// Only interesting for Wayland
|
|
virtual bool handleDragEnter(QDragEnterEvent *, DropArea *) { return false; }
|
|
virtual bool handleDragLeave(DropArea *) { return false; }
|
|
virtual bool handleDragMove(QDragMoveEvent *, DropArea *) { return false; }
|
|
virtual bool handleDrop(QDropEvent *, DropArea *) { return false; }
|
|
|
|
// Returns whether this is the current state
|
|
bool isActiveState() const;
|
|
|
|
DragController *const q;
|
|
};
|
|
|
|
class StateNone : public StateBase
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit StateNone(DragController *parent);
|
|
~StateNone() override;
|
|
void onEntry() override;
|
|
bool handleMouseButtonPress(Draggable *draggable, QPoint globalPos, QPoint pos) override;
|
|
};
|
|
|
|
class StatePreDrag : public StateBase
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit StatePreDrag(DragController *parent);
|
|
~StatePreDrag() override;
|
|
void onEntry() override;
|
|
bool handleMouseMove(QPoint globalPos) override;
|
|
bool handleMouseButtonRelease(QPoint) override;
|
|
bool handleMouseDoubleClick() override;
|
|
};
|
|
|
|
// Used on all platforms except Wayland. @see StateDraggingWayland
|
|
class StateDragging : public StateBase
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit StateDragging(DragController *parent);
|
|
~StateDragging() override;
|
|
void onEntry() override;
|
|
bool handleMouseButtonRelease(QPoint globalPos) override;
|
|
bool handleMouseMove(QPoint globalPos) override;
|
|
bool handleMouseDoubleClick() override;
|
|
};
|
|
|
|
// Used on wayland only to use QDrag instead of setting geometry on mouse-move.
|
|
class StateDraggingWayland : public StateDragging
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit StateDraggingWayland(DragController *parent);
|
|
~StateDraggingWayland() override;
|
|
void onEntry() override;
|
|
bool handleMouseButtonRelease(QPoint globalPos) override;
|
|
bool handleDragEnter(QDragEnterEvent *, DropArea *) override;
|
|
bool handleDragMove(QDragMoveEvent *, DropArea *) override;
|
|
bool handleDragLeave(DropArea *) override;
|
|
bool handleDrop(QDropEvent *, DropArea *) override;
|
|
bool m_inQDrag = false;
|
|
};
|
|
|
|
// A sub-class just so we don't use QMimeData directly. We'll only accept drops if its mime data
|
|
// Can be qobject_casted to this class. For safety.
|
|
class WaylandMimeData : public QMimeData
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|