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).
icc-effect-5.14.5
Martin Gräßlin 2013-06-26 10:15:20 +02:00
parent 7b14c84819
commit 1617deabb8
5 changed files with 262 additions and 48 deletions

View File

@ -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
View 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
View 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

View File

@ -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,

View File

@ -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);