6619faa6ac
InputRedirection forwards pointer events (currently motion, press and release) through the EffectsHandlerImpl for the case that an effect has intercepted pointer events. If the KWin operation mode is not X11 only, the window for intercepting the mouse events is no longer created.
183 lines
5.8 KiB
C++
183 lines
5.8 KiB
C++
/********************************************************************
|
|
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"
|
|
#include "effects.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: keyboard modifiers
|
|
QMouseEvent event(QEvent::MouseMove, m_globalPointer.toPoint(), m_globalPointer.toPoint(),
|
|
Qt::NoButton, qtButtonStates(), 0);
|
|
// check whether an effect has a mouse grab
|
|
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(&event)) {
|
|
// an effect grabbed the pointer, we do not forward the event to surfaces
|
|
return;
|
|
}
|
|
// 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: keyboard modifiers
|
|
QMouseEvent event(buttonStateToEvent(state), m_globalPointer.toPoint(), m_globalPointer.toPoint(),
|
|
buttonToQtMouseButton(button), qtButtonStates(), 0);
|
|
// check whether an effect has a mouse grab
|
|
if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(&event)) {
|
|
// an effect grabbed the pointer, we do not forward the event to surfaces
|
|
return;
|
|
}
|
|
// 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: Axis support for effect redirection
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
QEvent::Type InputRedirection::buttonStateToEvent(InputRedirection::PointerButtonState state)
|
|
{
|
|
switch (state) {
|
|
case KWin::InputRedirection::PointerButtonReleased:
|
|
return QEvent::MouseButtonRelease;
|
|
case KWin::InputRedirection::PointerButtonPressed:
|
|
return QEvent::MouseButtonPress;
|
|
}
|
|
return QEvent::None;
|
|
}
|
|
|
|
Qt::MouseButton InputRedirection::buttonToQtMouseButton(uint32_t button)
|
|
{
|
|
switch (button) {
|
|
case BTN_LEFT:
|
|
return Qt::LeftButton;
|
|
case BTN_MIDDLE:
|
|
return Qt::MiddleButton;
|
|
case BTN_RIGHT:
|
|
return Qt::RightButton;
|
|
case BTN_BACK:
|
|
return Qt::XButton1;
|
|
case BTN_FORWARD:
|
|
return Qt::XButton2;
|
|
}
|
|
return Qt::NoButton;
|
|
}
|
|
|
|
Qt::MouseButtons InputRedirection::qtButtonStates() const
|
|
{
|
|
Qt::MouseButtons buttons;
|
|
for (auto it = m_pointerButtons.constBegin(); it != m_pointerButtons.constEnd(); ++it) {
|
|
if (it.value() == KWin::InputRedirection::PointerButtonReleased) {
|
|
continue;
|
|
}
|
|
Qt::MouseButton button = buttonToQtMouseButton(it.key());
|
|
if (button != Qt::NoButton) {
|
|
buttons |= button;
|
|
}
|
|
}
|
|
return buttons;
|
|
}
|
|
|
|
|
|
} // namespace
|