Introduce the beginning of an InputRedirection class
So far this new class is not yet doing much. The WaylandBackend forwards the received pointer events to this InputRedirection class. From there signals are emitted to inform internal areas about the changes first. The events are currently forwarded to X through the xtest extension. This will be removed in future. Input will be forwarded directly to the surface which wants it (no matter whether X11 or Wayland).
This commit is contained in:
parent
7b14c84819
commit
1617deabb8
5 changed files with 262 additions and 48 deletions
|
@ -103,6 +103,7 @@ set(kwin_KDEINIT_SRCS
|
|||
cursor.cpp
|
||||
tabgroup.cpp
|
||||
focuschain.cpp
|
||||
input.cpp
|
||||
netinfo.cpp
|
||||
placement.cpp
|
||||
atoms.cpp
|
||||
|
|
121
input.cpp
Normal file
121
input.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "input.h"
|
||||
// TODO: remove xtest
|
||||
#include <xcb/xtest.h>
|
||||
// system
|
||||
#include <linux/input.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
KWIN_SINGLETON_FACTORY(InputRedirection)
|
||||
|
||||
InputRedirection::InputRedirection(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
InputRedirection::~InputRedirection()
|
||||
{
|
||||
s_self = NULL;
|
||||
}
|
||||
|
||||
void InputRedirection::processPointerMotion(const QPointF &pos, uint32_t time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
// first update to new mouse position
|
||||
// const QPointF oldPos = m_globalPointer;
|
||||
m_globalPointer = pos;
|
||||
emit globalPointerChanged(m_globalPointer);
|
||||
|
||||
// TODO: check which part of KWin would like to intercept the event
|
||||
// TODO: redirect to proper client
|
||||
|
||||
// TODO: don't use xtest
|
||||
xcb_test_fake_input(connection(), XCB_MOTION_NOTIFY, 0, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE,
|
||||
pos.x(), pos.y(), 0);
|
||||
}
|
||||
|
||||
void InputRedirection::processPointerButton(uint32_t button, InputRedirection::PointerButtonState state, uint32_t time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
m_pointerButtons[button] = state;
|
||||
emit pointerButtonStateChanged(button, state);
|
||||
|
||||
// TODO: check which part of KWin would like to intercept the event
|
||||
// TODO: redirect to proper client
|
||||
|
||||
// TODO: don't use xtest
|
||||
uint8_t type = XCB_BUTTON_PRESS;
|
||||
if (state == KWin::InputRedirection::PointerButtonReleased) {
|
||||
type = XCB_BUTTON_RELEASE;
|
||||
}
|
||||
// TODO: there must be a better way for mapping
|
||||
uint8_t xButton = 0;
|
||||
switch (button) {
|
||||
case BTN_LEFT:
|
||||
xButton = XCB_BUTTON_INDEX_1;
|
||||
break;
|
||||
case BTN_RIGHT:
|
||||
xButton = XCB_BUTTON_INDEX_3;
|
||||
break;
|
||||
case BTN_MIDDLE:
|
||||
xButton = XCB_BUTTON_INDEX_2;
|
||||
break;
|
||||
default:
|
||||
// TODO: add more buttons
|
||||
return;
|
||||
}
|
||||
xcb_test_fake_input(connection(), type, xButton, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
|
||||
}
|
||||
|
||||
void InputRedirection::processPointerAxis(InputRedirection::PointerAxis axis, qreal delta, uint32_t time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
if (delta == 0) {
|
||||
return;
|
||||
}
|
||||
emit pointerAxisChanged(axis, delta);
|
||||
|
||||
// TODO: check which part of KWin would like to intercept the event
|
||||
// TODO: redirect to proper client
|
||||
|
||||
// TODO: don't use xtest
|
||||
uint8_t xButton = 0;
|
||||
switch (axis) {
|
||||
case PointerAxisVertical:
|
||||
xButton = delta > 0 ? XCB_BUTTON_INDEX_5 : XCB_BUTTON_INDEX_4;
|
||||
break;
|
||||
case PointerAxisHorizontal:
|
||||
// no enum values defined for buttons larger than 5
|
||||
xButton = delta > 0 ? 7 : 6;
|
||||
break;
|
||||
default:
|
||||
// doesn't exist
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < qAbs(delta); ++i) {
|
||||
xcb_test_fake_input(connection(), XCB_BUTTON_PRESS, xButton, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
|
||||
xcb_test_fake_input(connection(), XCB_BUTTON_RELEASE, xButton, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
134
input.h
Normal file
134
input.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_INPUT_H
|
||||
#define KWIN_INPUT_H
|
||||
#include <kwinglobals.h>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief This class is responsible for redirecting incoming input to the surface which currently
|
||||
* has input or send enter/leave events.
|
||||
*
|
||||
* In addition input is intercepted before passed to the surfaces to have KWin internal areas
|
||||
* getting input first (e.g. screen edges) and filter the input event out if we currently have
|
||||
* a full input grab.
|
||||
*
|
||||
*/
|
||||
class InputRedirection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum PointerButtonState {
|
||||
PointerButtonReleased,
|
||||
PointerButtonPressed
|
||||
};
|
||||
enum PointerAxis {
|
||||
PointerAxisVertical,
|
||||
PointerAxisHorizontal
|
||||
};
|
||||
virtual ~InputRedirection();
|
||||
|
||||
/**
|
||||
* @return const QPointF& The current global pointer position
|
||||
*/
|
||||
const QPointF &globalPointer() const;
|
||||
/**
|
||||
* @brief The last known state of the @p button. If @p button is still unknown the state is
|
||||
* @c PointerButtonReleased.
|
||||
*
|
||||
* @param button The button for which the last known state should be queried.
|
||||
* @return KWin::InputRedirection::PointerButtonState
|
||||
*/
|
||||
PointerButtonState pointerButtonState(uint32_t button) const;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void processPointerMotion(const QPointF &pos, uint32_t time);
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void processPointerButton(uint32_t button, PointerButtonState state, uint32_t time);
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
void processPointerAxis(PointerAxis axis, qreal delta, uint32_t time);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* @brief Emitted when the global pointer position changed
|
||||
*
|
||||
* @param pos The new global pointer position.
|
||||
*/
|
||||
void globalPointerChanged(const QPointF &pos);
|
||||
/**
|
||||
* @brief Emitted when the state of a pointer button changed.
|
||||
*
|
||||
* @param button The button which changed
|
||||
* @param state The new button state
|
||||
*/
|
||||
void pointerButtonStateChanged(uint32_t button, PointerButtonState state);
|
||||
/**
|
||||
* @brief Emitted when a pointer axis changed
|
||||
*
|
||||
* @param axis The axis on which the even occurred
|
||||
* @param delta The delta of the event.
|
||||
*/
|
||||
void pointerAxisChanged(PointerAxis axis, qreal delta);
|
||||
|
||||
private:
|
||||
QPointF m_globalPointer;
|
||||
QHash<uint32_t, PointerButtonState> m_pointerButtons;
|
||||
|
||||
KWIN_SINGLETON(InputRedirection)
|
||||
friend InputRedirection *input();
|
||||
};
|
||||
|
||||
inline
|
||||
InputRedirection *input()
|
||||
{
|
||||
return InputRedirection::s_self;
|
||||
}
|
||||
|
||||
inline
|
||||
const QPointF &InputRedirection::globalPointer() const
|
||||
{
|
||||
return m_globalPointer;
|
||||
}
|
||||
|
||||
inline
|
||||
InputRedirection::PointerButtonState InputRedirection::pointerButtonState(uint32_t button) const
|
||||
{
|
||||
auto it = m_pointerButtons.constFind(button);
|
||||
if (it != m_pointerButtons.constEnd()) {
|
||||
return it.value();
|
||||
} else {
|
||||
return KWin::InputRedirection::PointerButtonReleased;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
#endif // KWIN_INPUT_H
|
|
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// KWin
|
||||
#include "cursor.h"
|
||||
#include "main.h"
|
||||
#include "input.h"
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
#include <QImage>
|
||||
|
@ -33,7 +34,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// Wayland
|
||||
#include <wayland-client-protocol.h>
|
||||
// system
|
||||
#include <linux/input.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
@ -137,9 +137,7 @@ static void pointerHandleMotion(void *data, wl_pointer *pointer, uint32_t time,
|
|||
{
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(pointer)
|
||||
Q_UNUSED(time)
|
||||
xcb_test_fake_input(connection(), XCB_MOTION_NOTIFY, 0, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE,
|
||||
wl_fixed_to_int(sx), wl_fixed_to_int(sy), 0);
|
||||
input()->processPointerMotion(QPoint(wl_fixed_to_double(sx), wl_fixed_to_double(sy)), time);
|
||||
}
|
||||
|
||||
static void pointerHandleButton(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time,
|
||||
|
@ -148,56 +146,14 @@ static void pointerHandleButton(void *data, wl_pointer *pointer, uint32_t serial
|
|||
Q_UNUSED(data)
|
||||
Q_UNUSED(pointer)
|
||||
Q_UNUSED(serial)
|
||||
Q_UNUSED(time)
|
||||
uint8_t type = XCB_BUTTON_PRESS;
|
||||
if (state == WL_POINTER_BUTTON_STATE_RELEASED) {
|
||||
type = XCB_BUTTON_RELEASE;
|
||||
}
|
||||
// TODO: there must be a better way for mapping
|
||||
uint8_t xButton = 0;
|
||||
switch (button) {
|
||||
case BTN_LEFT:
|
||||
xButton = XCB_BUTTON_INDEX_1;
|
||||
break;
|
||||
case BTN_RIGHT:
|
||||
xButton = XCB_BUTTON_INDEX_3;
|
||||
break;
|
||||
case BTN_MIDDLE:
|
||||
xButton = XCB_BUTTON_INDEX_2;
|
||||
break;
|
||||
default:
|
||||
// TODO: add more buttons
|
||||
return;
|
||||
}
|
||||
xcb_test_fake_input(connection(), type, xButton, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
|
||||
input()->processPointerButton(button, static_cast<InputRedirection::PointerButtonState>(state), time);
|
||||
}
|
||||
|
||||
static void pointerHandleAxis(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(pointer)
|
||||
Q_UNUSED(time)
|
||||
uint8_t xButton = 0;
|
||||
const int delta = wl_fixed_to_int(value);
|
||||
if (delta == 0) {
|
||||
return;
|
||||
}
|
||||
switch (axis) {
|
||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||
xButton = delta > 0 ? XCB_BUTTON_INDEX_5 : XCB_BUTTON_INDEX_4;
|
||||
break;
|
||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||
// no enum values defined for buttons larger than 5
|
||||
xButton = delta > 0 ? 7 : 6;
|
||||
break;
|
||||
default:
|
||||
// doesn't exist
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < qAbs(delta); ++i) {
|
||||
xcb_test_fake_input(connection(), XCB_BUTTON_PRESS, xButton, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
|
||||
xcb_test_fake_input(connection(), XCB_BUTTON_RELEASE, xButton, XCB_TIME_CURRENT_TIME, XCB_WINDOW_NONE, 0, 0, 0);
|
||||
}
|
||||
input()->processPointerAxis(static_cast<InputRedirection::PointerAxis>(axis), wl_fixed_to_double(value), time);
|
||||
}
|
||||
|
||||
static void keyboardHandleKeymap(void *data, wl_keyboard *keyboard,
|
||||
|
|
|
@ -40,6 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "effects.h"
|
||||
#include "focuschain.h"
|
||||
#include "group.h"
|
||||
#include "input.h"
|
||||
#include "killwindow.h"
|
||||
#include "netinfo.h"
|
||||
#include "outline.h"
|
||||
|
@ -151,6 +152,7 @@ Workspace::Workspace(bool restore)
|
|||
Wayland::WaylandBackend::create(this);
|
||||
#endif
|
||||
|
||||
InputRedirection::create(this);
|
||||
// start the cursor support
|
||||
Cursor::create(this);
|
||||
|
||||
|
|
Loading…
Reference in a new issue