KWin
Loading...
Searching...
No Matches
touch_input.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2013, 2016 Martin Gräßlin <mgraesslin@kde.org>
6 SPDX-FileCopyrightText: 2018 Roman Gilg <subdiff@gmail.com>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9*/
10#include "touch_input.h"
11
12#include <config-kwin.h>
13
15#include "input_event_spy.h"
16#include "pointer_input.h"
17#include "wayland/seat.h"
18#include "wayland_server.h"
19#include "window.h"
20#include "workspace.h"
21// KDecoration
22#include <KDecoration2/Decoration>
23// screenlocker
24#if KWIN_BUILD_SCREENLOCKER
25#include <KScreenLocker/KsldApp>
26#endif
27// Qt
28#include <QHoverEvent>
29#include <QWindow>
30
31namespace KWin
32{
33
38
40
42{
43 Q_ASSERT(!inited());
44 waylandServer()->seat()->setHasTouch(input()->hasTouch());
47
48 setInited(true);
50
51#if KWIN_BUILD_SCREENLOCKER
52 if (waylandServer()->hasScreenLockerIntegration()) {
53 connect(ScreenLocker::KSldApp::self(), &ScreenLocker::KSldApp::lockStateChanged, this, [this]() {
54 cancel();
55 // position doesn't matter
56 update();
57 });
58 }
59#endif
60 connect(workspace(), &QObject::destroyed, this, [this] {
61 setInited(false);
62 });
63 connect(waylandServer(), &QObject::destroyed, this, [this] {
64 setInited(false);
65 });
66}
67
69{
70 if (m_windowUpdatedInCycle) {
71 return true;
72 }
73 m_windowUpdatedInCycle = true;
74 if (waylandServer()->seat()->isDragTouch()) {
75 return true;
76 }
77 if (m_activeTouchPoints.count() > 1) {
78 // first touch defines focus
79 return true;
80 }
81 return false;
82}
83
85{
86 // we can only determine a position with at least one touch point
87 return !m_activeTouchPoints.isEmpty();
88}
89
90void TouchInputRedirection::focusUpdate(Window *focusOld, Window *focusNow)
91{
92 // TODO: handle pointer grab aka popups
93
94 if (focusOld && focusOld->isClient()) {
95 focusOld->pointerLeaveEvent();
96 }
97 disconnect(m_focusGeometryConnection);
98 m_focusGeometryConnection = QMetaObject::Connection();
99
100 if (focusNow && focusNow->isClient()) {
101 focusNow->pointerEnterEvent(m_lastPosition);
102 }
103
104 auto seat = waylandServer()->seat();
105 if (!focusNow || !focusNow->surface()) {
106 seat->setFocusedTouchSurface(nullptr);
107 return;
108 }
109
110 // TODO: invalidate pointer focus?
111
112 // FIXME: add input transformation API to SeatInterface for touch input
113 seat->setFocusedTouchSurface(focusNow->surface(), -1 * focusNow->inputTransformation().map(focusNow->pos()) + focusNow->pos());
114 m_focusGeometryConnection = connect(focusNow, &Window::frameGeometryChanged, this, [this]() {
115 if (!focus()) {
116 return;
117 }
118 auto seat = waylandServer()->seat();
119 if (focus()->surface() != seat->focusedTouchSurface()) {
120 return;
121 }
122 seat->setFocusedTouchSurfacePosition(-1 * focus()->inputTransformation().map(focus()->pos()) + focus()->pos());
123 });
124}
125
126void TouchInputRedirection::cleanupDecoration(Decoration::DecoratedClientImpl *old, Decoration::DecoratedClientImpl *now)
127{
128 // nothing to do
129}
130
131void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, std::chrono::microseconds time, InputDevice *device)
132{
133 if (!inited()) {
134 return;
135 }
136 m_lastPosition = pos;
137 m_windowUpdatedInCycle = false;
138 m_activeTouchPoints.insert(id);
139 if (m_activeTouchPoints.count() == 1) {
140 update();
142 }
143 input()->setLastInputHandler(this);
144 input()->processSpies(std::bind(&InputEventSpy::touchDown, std::placeholders::_1, id, pos, time));
145 input()->processFilters(std::bind(&InputEventFilter::touchDown, std::placeholders::_1, id, pos, time));
146 m_windowUpdatedInCycle = false;
147}
148
149void TouchInputRedirection::processUp(qint32 id, std::chrono::microseconds time, InputDevice *device)
150{
151 if (!inited()) {
152 return;
153 }
154 if (!m_activeTouchPoints.remove(id)) {
155 return;
156 }
157 input()->setLastInputHandler(this);
158 m_windowUpdatedInCycle = false;
159 input()->processSpies(std::bind(&InputEventSpy::touchUp, std::placeholders::_1, id, time));
160 input()->processFilters(std::bind(&InputEventFilter::touchUp, std::placeholders::_1, id, time));
161 m_windowUpdatedInCycle = false;
162 if (m_activeTouchPoints.count() == 0) {
163 update();
164 }
165}
166
167void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time, InputDevice *device)
168{
169 if (!inited()) {
170 return;
171 }
172 if (!m_activeTouchPoints.contains(id)) {
173 return;
174 }
175 input()->setLastInputHandler(this);
176 m_lastPosition = pos;
177 m_windowUpdatedInCycle = false;
178 input()->processSpies(std::bind(&InputEventSpy::touchMotion, std::placeholders::_1, id, pos, time));
179 input()->processFilters(std::bind(&InputEventFilter::touchMotion, std::placeholders::_1, id, pos, time));
180 m_windowUpdatedInCycle = false;
181}
182
184{
185 if (!inited()) {
186 return;
187 }
188 // If the touch sequence is artificially cancelled by the compositor, touch motion and touch
189 // up events will be silently ignored and won't be passed down through the event filter chain.
190 // If the touch sequence is cancelled because we received a TOUCH_CANCEL event from libinput,
191 // the compositor will not receive any TOUCH_MOTION or TOUCH_UP events for that slot.
192 if (!m_activeTouchPoints.isEmpty()) {
193 m_activeTouchPoints.clear();
194 input()->processFilters(std::bind(&InputEventFilter::touchCancel, std::placeholders::_1));
195 }
196}
197
199{
200 if (!inited() || !waylandServer()->seat()->hasTouch()) {
201 return;
202 }
203 input()->processFilters(std::bind(&InputEventFilter::touchFrame, std::placeholders::_1));
204}
205
206}
207
208#include "moc_touch_input.cpp"
bool inited() const
Definition input.h:520
Window * focus() const
Window currently having pointer input focus (this might be different from the Window at the position ...
Definition input.cpp:3521
void setInited(bool set)
Definition input.h:524
virtual void init()
Definition input.cpp:3410
virtual bool touchUp(qint32 id, std::chrono::microseconds time)
Definition input.cpp:140
virtual bool touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time)
Definition input.cpp:130
virtual bool touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time)
Definition input.cpp:135
virtual bool touchCancel()
Definition input.cpp:145
virtual bool touchFrame()
Definition input.cpp:150
virtual void touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time)
virtual void touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time)
virtual void touchUp(qint32 id, std::chrono::microseconds time)
This class is responsible for redirecting incoming input to the surface which currently has input or ...
Definition input.h:70
void processSpies(UnaryFunction function)
Definition input.h:211
void processFilters(UnaryPredicate function)
Definition input.h:192
void hasTouchChanged(bool set)
void setLastInputHandler(QObject *device)
Definition input.cpp:2739
void setHasTouch(bool has)
Definition seat.cpp:372
void processMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time, InputDevice *device=nullptr)
bool focusUpdatesBlocked() override
void processUp(qint32 id, std::chrono::microseconds time, InputDevice *device=nullptr)
TouchInputRedirection(InputRedirection *parent)
void processDown(qint32 id, const QPointF &pos, std::chrono::microseconds time, InputDevice *device=nullptr)
bool positionValid() const override
SeatInterface * seat() const
QMatrix4x4 inputTransformation() const
Definition window.cpp:374
QPointF pos
Definition window.h:79
virtual bool isClient() const
Definition window.cpp:302
SurfaceInterface * surface() const
Definition window.cpp:342
virtual void pointerEnterEvent(const QPointF &globalPos)
Definition window.cpp:2821
virtual void pointerLeaveEvent()
Definition window.cpp:2847
void frameGeometryChanged(const QRectF &oldGeometry)
void setActiveCursorOutput(Output *output)
KWayland::Client::Seat * seat
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549