[wayland] Add support for processing touch events
InputRedirection gains basic support for processing touch events which are delegated to KWayland::Server. WaylandBackend accepts touch events from KWayland::Client and delegates them to the InputRedirection.
This commit is contained in:
parent
2e2ea354b6
commit
36f987198d
4 changed files with 175 additions and 0 deletions
118
input.cpp
118
input.cpp
|
@ -311,6 +311,21 @@ void InputRedirection::updateFocusedPointerPosition()
|
|||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::updateFocusedTouchPosition()
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
if (m_touchWindow.isNull()) {
|
||||
return;
|
||||
}
|
||||
if (auto seat = findSeat()) {
|
||||
if (m_touchWindow.data()->surface() != seat->focusedTouchSurface()) {
|
||||
return;
|
||||
}
|
||||
seat->setFocusedTouchSurfacePosition(m_touchWindow.data()->pos());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time)
|
||||
{
|
||||
// first update to new mouse position
|
||||
|
@ -487,6 +502,109 @@ void InputRedirection::processKeymapChange(int fd, uint32_t size)
|
|||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::processTouchDown(qint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
// TODO: internal handling?
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
seat->setTimestamp(time);
|
||||
if (!seat->isTouchSequence()) {
|
||||
updateTouchWindow(pos);
|
||||
}
|
||||
m_touchIdMapper.insert(id, seat->touchDown(pos));
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(pos)
|
||||
Q_UNUSED(time)
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::updateTouchWindow(const QPointF &pos)
|
||||
{
|
||||
// TODO: handle pointer grab aka popups
|
||||
Toplevel *t = findToplevel(pos.toPoint());
|
||||
auto oldWindow = m_touchWindow;
|
||||
if (!oldWindow.isNull() && t == oldWindow.data()) {
|
||||
return;
|
||||
}
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
// disconnect old surface
|
||||
if (oldWindow) {
|
||||
disconnect(oldWindow.data(), &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedTouchPosition);
|
||||
}
|
||||
if (t && t->surface()) {
|
||||
seat->setFocusedTouchSurface(t->surface(), t->pos());
|
||||
connect(t, &Toplevel::geometryChanged, this, &InputRedirection::updateFocusedTouchPosition);
|
||||
} else {
|
||||
seat->setFocusedTouchSurface(nullptr);
|
||||
t = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!t) {
|
||||
m_touchWindow.clear();
|
||||
return;
|
||||
}
|
||||
m_touchWindow = QWeakPointer<Toplevel>(t);
|
||||
}
|
||||
|
||||
|
||||
void InputRedirection::processTouchUp(qint32 id, quint32 time)
|
||||
{
|
||||
// TODO: internal handling?
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
auto it = m_touchIdMapper.constFind(id);
|
||||
if (it != m_touchIdMapper.constEnd()) {
|
||||
seat->setTimestamp(time);
|
||||
seat->touchUp(it.value());
|
||||
}
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(time)
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::processTouchMotion(qint32 id, const QPointF &pos, quint32 time)
|
||||
{
|
||||
// TODO: internal handling?
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
seat->setTimestamp(time);
|
||||
auto it = m_touchIdMapper.constFind(id);
|
||||
if (it != m_touchIdMapper.constEnd()) {
|
||||
seat->setTimestamp(time);
|
||||
seat->touchMove(it.value(), pos);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(id)
|
||||
Q_UNUSED(pos)
|
||||
Q_UNUSED(time)
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::cancelTouch()
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
seat->cancelTouchSequence();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputRedirection::touchFrame()
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
if (auto seat = findSeat()) {
|
||||
seat->touchFrame();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QEvent::Type InputRedirection::buttonStateToEvent(InputRedirection::PointerButtonState state)
|
||||
{
|
||||
switch (state) {
|
||||
|
|
15
input.h
15
input.h
|
@ -122,6 +122,11 @@ public:
|
|||
* @internal
|
||||
**/
|
||||
void processKeymapChange(int fd, uint32_t size);
|
||||
void processTouchDown(qint32 id, const QPointF &pos, quint32 time);
|
||||
void processTouchUp(qint32 id, quint32 time);
|
||||
void processTouchMotion(qint32 id, const QPointF &pos, quint32 time);
|
||||
void cancelTouch();
|
||||
void touchFrame();
|
||||
|
||||
static uint8_t toXPointerButton(uint32_t button);
|
||||
static uint8_t toXPointerButton(PointerAxis axis, qreal delta);
|
||||
|
@ -170,6 +175,8 @@ private:
|
|||
void updatePointerAfterScreenChange();
|
||||
void registerShortcutForGlobalAccelTimestamp(QAction *action);
|
||||
void updateFocusedPointerPosition();
|
||||
void updateFocusedTouchPosition();
|
||||
void updateTouchWindow(const QPointF &pos);
|
||||
QPointF m_globalPointer;
|
||||
QHash<uint32_t, PointerButtonState> m_pointerButtons;
|
||||
#if HAVE_XKB
|
||||
|
@ -179,6 +186,14 @@ private:
|
|||
* @brief The Toplevel which currently receives pointer events
|
||||
*/
|
||||
QWeakPointer<Toplevel> m_pointerWindow;
|
||||
/**
|
||||
* @brief The Toplevel which currently receives touch events
|
||||
*/
|
||||
QWeakPointer<Toplevel> m_touchWindow;
|
||||
/**
|
||||
* external/kwayland
|
||||
**/
|
||||
QHash<qint32, qint32> m_touchIdMapper;
|
||||
|
||||
GlobalShortcutsManager *m_shortcuts;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Client/subcompositor.h>
|
||||
#include <KWayland/Client/subsurface.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
#include <KWayland/Client/touch.h>
|
||||
#include <KWayland/Server/buffer_interface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
|
@ -159,6 +160,37 @@ WaylandSeat::WaylandSeat(wl_seat *seat, WaylandBackend *backend)
|
|||
}
|
||||
}
|
||||
);
|
||||
connect(m_seat, &Seat::hasTouchChanged,
|
||||
[this] (bool hasTouch) {
|
||||
if (hasTouch && !m_touch) {
|
||||
m_touch = m_seat->createTouch(this);
|
||||
connect(m_touch, &Touch::sequenceCanceled, input(), &InputRedirection::cancelTouch);
|
||||
connect(m_touch, &Touch::frameEnded, input(), &InputRedirection::touchFrame);
|
||||
connect(m_touch, &Touch::sequenceStarted, this,
|
||||
[] (TouchPoint *tp) {
|
||||
input()->processTouchDown(tp->id(), tp->position(), tp->time());
|
||||
}
|
||||
);
|
||||
connect(m_touch, &Touch::pointAdded, this,
|
||||
[] (TouchPoint *tp) {
|
||||
input()->processTouchDown(tp->id(), tp->position(), tp->time());
|
||||
}
|
||||
);
|
||||
connect(m_touch, &Touch::pointRemoved, this,
|
||||
[] (TouchPoint *tp) {
|
||||
input()->processTouchUp(tp->id(), tp->time());
|
||||
}
|
||||
);
|
||||
connect(m_touch, &Touch::pointMoved, this,
|
||||
[] (TouchPoint *tp) {
|
||||
input()->processTouchMotion(tp->id(), tp->position(), tp->time());
|
||||
}
|
||||
);
|
||||
} else {
|
||||
destroyTouch();
|
||||
}
|
||||
}
|
||||
);
|
||||
WaylandServer *server = waylandServer();
|
||||
if (server) {
|
||||
using namespace KWayland::Server;
|
||||
|
@ -174,6 +206,7 @@ WaylandSeat::~WaylandSeat()
|
|||
{
|
||||
destroyPointer();
|
||||
destroyKeyboard();
|
||||
destroyTouch();
|
||||
}
|
||||
|
||||
void WaylandSeat::destroyPointer()
|
||||
|
@ -188,6 +221,12 @@ void WaylandSeat::destroyKeyboard()
|
|||
m_keyboard = nullptr;
|
||||
}
|
||||
|
||||
void WaylandSeat::destroyTouch()
|
||||
{
|
||||
delete m_touch;
|
||||
m_touch = nullptr;
|
||||
}
|
||||
|
||||
void WaylandSeat::installCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotSpot)
|
||||
{
|
||||
if (!m_installCursor) {
|
||||
|
|
|
@ -58,6 +58,7 @@ class ShellSurface;
|
|||
class SubCompositor;
|
||||
class SubSurface;
|
||||
class Surface;
|
||||
class Touch;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,9 +106,11 @@ public:
|
|||
private:
|
||||
void destroyPointer();
|
||||
void destroyKeyboard();
|
||||
void destroyTouch();
|
||||
KWayland::Client::Seat *m_seat;
|
||||
KWayland::Client::Pointer *m_pointer;
|
||||
KWayland::Client::Keyboard *m_keyboard;
|
||||
KWayland::Client::Touch *m_touch;
|
||||
KWayland::Client::Surface *m_cursor;
|
||||
#if HAVE_WAYLAND_CURSOR
|
||||
WaylandCursorTheme *m_theme;
|
||||
|
|
Loading…
Reference in a new issue