Add support for touch events in the Effect system
Summary: The Effect class is extended by three new virtual methods: * touchDown * touchMotion * touchUp The methods return a boolean value so that the events can be filtered out. E.g. an effect which has also a mouse grab installed wants to filter out all events, other effects don't need the events exclusively. This is a difference to how e.g. keyboard and pointer events are handled. But is more close to how KWin's internal input event passing works and makes it easier to get touch event: one does not explicitly has to grab the events. It's also closer to Wayland where all input events are available. As a first example the Present Windows effect is adjusted and allows to activate windows through the touch screen. As much code as possible is shared with pointer input. Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2450
This commit is contained in:
parent
d68a3fecd7
commit
6af0cc6ebe
7 changed files with 206 additions and 6 deletions
34
effects.cpp
34
effects.cpp
|
@ -672,6 +672,40 @@ bool EffectsHandlerImpl::isMouseInterception() const
|
|||
return m_grabbedMouseEffects.count() > 0;
|
||||
}
|
||||
|
||||
|
||||
bool EffectsHandlerImpl::touchDown(quint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
// TODO: reverse call order?
|
||||
for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
||||
if (it->second->touchDown(id, pos, time)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::touchMotion(quint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
// TODO: reverse call order?
|
||||
for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
||||
if (it->second->touchMotion(id, pos, time)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::touchUp(quint32 id, quint32 time)
|
||||
{
|
||||
// TODO: reverse call order?
|
||||
for (auto it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it) {
|
||||
if (it->second->touchUp(id, time)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::registerGlobalShortcut(const QKeySequence &shortcut, QAction *action)
|
||||
{
|
||||
input()->registerShortcut(shortcut, action);
|
||||
|
|
|
@ -232,6 +232,10 @@ public:
|
|||
return m_scene;
|
||||
}
|
||||
|
||||
bool touchDown(quint32 id, const QPointF &pos, quint32 time);
|
||||
bool touchMotion(quint32 id, const QPointF &pos, quint32 time);
|
||||
bool touchUp(quint32 id, quint32 time);
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotCurrentTabAboutToChange(EffectWindow* from, EffectWindow* to);
|
||||
void slotTabAdded(EffectWindow* from, EffectWindow* to);
|
||||
|
|
|
@ -553,6 +553,11 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
|||
}
|
||||
}
|
||||
}
|
||||
inputEventUpdate(me->pos(), me->type(), me->button());
|
||||
}
|
||||
|
||||
void PresentWindowsEffect::inputEventUpdate(const QPoint &pos, QEvent::Type type, Qt::MouseButton button)
|
||||
{
|
||||
// Which window are we hovering over? Always trigger as we don't always get move events before clicking
|
||||
// We cannot use m_motionManager.windowAtPoint() as the window might not be visible
|
||||
EffectWindowList windows = m_motionManager.managedWindows();
|
||||
|
@ -562,7 +567,7 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
|||
DataHash::const_iterator winData = m_windowData.constFind(windows.at(i));
|
||||
if (winData == m_windowData.constEnd())
|
||||
continue;
|
||||
if (m_motionManager.transformedGeometry(windows.at(i)).contains(cursorPos()) &&
|
||||
if (m_motionManager.transformedGeometry(windows.at(i)).contains(pos) &&
|
||||
winData->visible && !winData->deleted) {
|
||||
hovering = true;
|
||||
if (windows.at(i) && m_highlightedWindow != windows.at(i))
|
||||
|
@ -572,15 +577,15 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
|||
}
|
||||
if (!hovering)
|
||||
setHighlightedWindow(NULL);
|
||||
if (m_highlightedWindow && m_motionManager.transformedGeometry(m_highlightedWindow).contains(me->pos()))
|
||||
if (m_highlightedWindow && m_motionManager.transformedGeometry(m_highlightedWindow).contains(pos))
|
||||
updateCloseWindow();
|
||||
else if (m_closeView)
|
||||
m_closeView->hide();
|
||||
|
||||
if (e->type() == QEvent::MouseButtonRelease) {
|
||||
if (type == QEvent::MouseButtonRelease) {
|
||||
if (highlightCandidate)
|
||||
setHighlightedWindow(highlightCandidate);
|
||||
if (me->button() == Qt::LeftButton) {
|
||||
if (button == Qt::LeftButton) {
|
||||
if (hovering) {
|
||||
// mouse is hovering above a window - use MouseActionsWindow
|
||||
mouseActionWindow(m_leftButtonWindow);
|
||||
|
@ -589,7 +594,7 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
|||
mouseActionDesktop(m_leftButtonDesktop);
|
||||
}
|
||||
}
|
||||
if (me->button() == Qt::MidButton) {
|
||||
if (button == Qt::MidButton) {
|
||||
if (hovering) {
|
||||
// mouse is hovering above a window - use MouseActionsWindow
|
||||
mouseActionWindow(m_middleButtonWindow);
|
||||
|
@ -598,7 +603,7 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
|||
mouseActionDesktop(m_middleButtonDesktop);
|
||||
}
|
||||
}
|
||||
if (me->button() == Qt::RightButton) {
|
||||
if (button == Qt::RightButton) {
|
||||
if (hovering) {
|
||||
// mouse is hovering above a window - use MouseActionsWindow
|
||||
mouseActionWindow(m_rightButtonWindow);
|
||||
|
@ -611,6 +616,52 @@ void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
|||
setHighlightedWindow(highlightCandidate);
|
||||
}
|
||||
|
||||
bool PresentWindowsEffect::touchDown(quint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
if (!m_activated) {
|
||||
return false;
|
||||
}
|
||||
// only if we don't track a touch id yet
|
||||
if (!m_touch.active) {
|
||||
m_touch.active = true;
|
||||
m_touch.id = id;
|
||||
inputEventUpdate(pos.toPoint());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresentWindowsEffect::touchMotion(quint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(time)
|
||||
if (!m_activated) {
|
||||
return false;
|
||||
}
|
||||
if (m_touch.active && m_touch.id == id) {
|
||||
// only update for the touch id we track
|
||||
inputEventUpdate(pos.toPoint());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresentWindowsEffect::touchUp(quint32 id, quint32 time)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(time)
|
||||
if (!m_activated) {
|
||||
return false;
|
||||
}
|
||||
if (m_touch.active && m_touch.id == id) {
|
||||
m_touch.active = false;
|
||||
m_touch.id = 0;
|
||||
if (m_highlightedWindow) {
|
||||
mouseActionWindow(m_leftButtonWindow);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PresentWindowsEffect::mouseActionWindow(WindowMouseAction& action)
|
||||
{
|
||||
switch(action) {
|
||||
|
|
|
@ -126,6 +126,10 @@ public:
|
|||
virtual void grabbedKeyboardEvent(QKeyEvent *e);
|
||||
virtual bool isActive() const;
|
||||
|
||||
bool touchDown(quint32 id, const QPointF &pos, quint32 time) override;
|
||||
bool touchMotion(quint32 id, const QPointF &pos, quint32 time) override;
|
||||
bool touchUp(quint32 id, quint32 time) override;
|
||||
|
||||
int requestedEffectChainPosition() const override {
|
||||
return 70;
|
||||
}
|
||||
|
@ -265,6 +269,7 @@ protected:
|
|||
// Helper functions for mouse actions
|
||||
void mouseActionWindow(WindowMouseAction& action);
|
||||
void mouseActionDesktop(DesktopMouseAction& action);
|
||||
void inputEventUpdate(const QPoint &pos, QEvent::Type type = QEvent::None, Qt::MouseButton button = Qt::NoButton);
|
||||
|
||||
private:
|
||||
PresentWindowsEffectProxy m_proxy;
|
||||
|
@ -330,6 +335,10 @@ private:
|
|||
CloseWindowView* m_closeView;
|
||||
EffectWindow* m_closeWindow;
|
||||
Qt::Corner m_closeButtonCorner;
|
||||
struct {
|
||||
quint32 id = 0;
|
||||
bool active = false;
|
||||
} m_touch;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
18
input.cpp
18
input.cpp
|
@ -344,6 +344,24 @@ public:
|
|||
static_cast< EffectsHandlerImpl* >(effects)->grabbedKeyboardEvent(event);
|
||||
return true;
|
||||
}
|
||||
bool touchDown(quint32 id, const QPointF &pos, quint32 time) override {
|
||||
if (!effects) {
|
||||
return false;
|
||||
}
|
||||
return static_cast< EffectsHandlerImpl* >(effects)->touchDown(id, pos, time);
|
||||
}
|
||||
bool touchMotion(quint32 id, const QPointF &pos, quint32 time) override {
|
||||
if (!effects) {
|
||||
return false;
|
||||
}
|
||||
return static_cast< EffectsHandlerImpl* >(effects)->touchMotion(id, pos, time);
|
||||
}
|
||||
bool touchUp(quint32 id, quint32 time) override {
|
||||
if (!effects) {
|
||||
return false;
|
||||
}
|
||||
return static_cast< EffectsHandlerImpl* >(effects)->touchUp(id, time);
|
||||
}
|
||||
};
|
||||
|
||||
class MoveResizeFilter : public InputEventFilter {
|
||||
|
|
|
@ -672,6 +672,29 @@ xcb_window_t Effect::x11RootWindow() const
|
|||
return effects->x11RootWindow();
|
||||
}
|
||||
|
||||
bool Effect::touchDown(quint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(pos)
|
||||
Q_UNUSED(time)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Effect::touchMotion(quint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(pos)
|
||||
Q_UNUSED(time)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Effect::touchUp(quint32 id, quint32 time)
|
||||
{
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(time)
|
||||
return false;
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// EffectFactory
|
||||
//****************************************
|
||||
|
|
|
@ -545,6 +545,67 @@ public:
|
|||
**/
|
||||
virtual int requestedEffectChainPosition() const;
|
||||
|
||||
|
||||
/**
|
||||
* A touch point was pressed.
|
||||
*
|
||||
* If the effect wants to exclusively use the touch event it should return @c true.
|
||||
* If @c false is returned the touch event is passed to further effects.
|
||||
*
|
||||
* In general an Effect should only return @c true if it is the exclusive effect getting
|
||||
* input events. E.g. has grabbed mouse events.
|
||||
*
|
||||
* Default implementation returns @c false.
|
||||
*
|
||||
* @param id The unique id of the touch point
|
||||
* @param pos The position of the touch point in global coordinates
|
||||
* @param time Timestamp
|
||||
*
|
||||
* @see touchMotion
|
||||
* @see touchUp
|
||||
* @since 5.8
|
||||
**/
|
||||
virtual bool touchDown(quint32 id, const QPointF &pos, quint32 time);
|
||||
/**
|
||||
* A touch point moved.
|
||||
*
|
||||
* If the effect wants to exclusively use the touch event it should return @c true.
|
||||
* If @c false is returned the touch event is passed to further effects.
|
||||
*
|
||||
* In general an Effect should only return @c true if it is the exclusive effect getting
|
||||
* input events. E.g. has grabbed mouse events.
|
||||
*
|
||||
* Default implementation returns @c false.
|
||||
*
|
||||
* @param id The unique id of the touch point
|
||||
* @param pos The position of the touch point in global coordinates
|
||||
* @param time Timestamp
|
||||
*
|
||||
* @see touchDown
|
||||
* @see touchUp
|
||||
* @since 5.8
|
||||
**/
|
||||
virtual bool touchMotion(quint32 id, const QPointF &pos, quint32 time);
|
||||
/**
|
||||
* A touch point was released.
|
||||
*
|
||||
* If the effect wants to exclusively use the touch event it should return @c true.
|
||||
* If @c false is returned the touch event is passed to further effects.
|
||||
*
|
||||
* In general an Effect should only return @c true if it is the exclusive effect getting
|
||||
* input events. E.g. has grabbed mouse events.
|
||||
*
|
||||
* Default implementation returns @c false.
|
||||
*
|
||||
* @param id The unique id of the touch point
|
||||
* @param time Timestamp
|
||||
*
|
||||
* @see touchDown
|
||||
* @see touchMotion
|
||||
* @since 5.8
|
||||
**/
|
||||
virtual bool touchUp(quint32 id, quint32 time);
|
||||
|
||||
static QPoint cursorPos();
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue