diff --git a/input.h b/input.h --- a/input.h +++ b/input.h @@ -41,6 +41,7 @@ class GlobalShortcutsManager; class Toplevel; class InputEventFilter; +class InputEventSpy; class KeyboardInputRedirection; class PointerConstraintsFilter; class PointerInputRedirection; @@ -151,6 +152,17 @@ **/ void prepandInputEventFilter(InputEventFilter *filter); void uninstallInputEventFilter(InputEventFilter *filter); + + /** + * Installs the @p spy for spying on events. + **/ + void installInputEventSpy(InputEventSpy *spy); + + /** + * Uninstalls the @p spy. This happens automatically when deleting an InputEventSpy. + **/ + void uninstallInputEventSpy(InputEventSpy *spy); + Toplevel *findToplevel(const QPoint &pos); GlobalShortcutsManager *shortcuts() const { return m_shortcuts; @@ -166,6 +178,24 @@ **/ void processFilters(std::function function); + /** + * Sends an event through all input event spies. + * The @p function is invoked on each InputEventSpy. + * + * The UnaryFunction is defined like the UnaryFunction of std::for_each. + * The signature of the function should be equivalent to the following: + * @code + * void function(const InputEventSpy *spy); + * @endcode + * + * The intended usage is to std::bind the method to invoke on the spies with all arguments + * bind. + **/ + template + void processSpies(UnaryFunction function) { + std::for_each(m_spies.constBegin(), m_spies.constEnd(), function); + } + KeyboardInputRedirection *keyboard() const { return m_keyboard; } @@ -245,6 +275,7 @@ PointerConstraintsFilter *m_pointerConstraintsFilter = nullptr; QVector m_filters; + QVector m_spies; KSharedConfigPtr m_inputConfig; KWIN_SINGLETON(InputRedirection) diff --git a/input.cpp b/input.cpp --- a/input.cpp +++ b/input.cpp @@ -19,6 +19,7 @@ *********************************************************************/ #include "input.h" #include "input_event.h" +#include "input_event_spy.h" #include "keyboard_input.h" #include "pointer_input.h" #include "touch_input.h" @@ -1365,6 +1366,7 @@ { s_self = NULL; qDeleteAll(m_filters); + qDeleteAll(m_spies); } void InputRedirection::installInputEventFilter(InputEventFilter *filter) @@ -1382,6 +1384,16 @@ m_filters.removeAll(filter); } +void InputRedirection::installInputEventSpy(InputEventSpy *spy) +{ + m_spies << spy; +} + +void InputRedirection::uninstallInputEventSpy(InputEventSpy *spy) +{ + m_spies.removeOne(spy); +} + void InputRedirection::init() { m_shortcuts->init(); diff --git a/input_event_spy.h b/input_event_spy.h new file mode 100644 --- /dev/null +++ b/input_event_spy.h @@ -0,0 +1,86 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2016 Martin Gräßlin + +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 . +*********************************************************************/ +#ifndef KWIN_INPUT_EVENT_SPY_H +#define KWIN_INPUT_EVENT_SPY_H +#include + +#include + +namespace KWin +{ +class KeyEvent; +class MouseEvent; +class WheelEvent; + + +/** + * Base class for spying on input events inside InputRedirection. + * + * This class is quite similar to InputEventFilter, except that it does not + * support event filtering. Each InputEventSpy gets to see all input events, + * the processing happens prior to sending events through the InputEventFilters. + * + * Deleting an instance of InputEventSpy automatically uninstalls it from + * InputRedirection. + **/ +class KWIN_EXPORT InputEventSpy +{ +public: + InputEventSpy(); + virtual ~InputEventSpy(); + + /** + * Event spy for pointer events which can be described by a MouseEvent. + * + * @param event The event information about the move or button press/release + **/ + virtual void pointerEvent(MouseEvent *event); + /** + * Event spy for pointer axis events. + * + * @param event The event information about the axis event + **/ + virtual void wheelEvent(WheelEvent *event); + /** + * Event spy for keyboard events. + * + * @param event The event information about the key event + **/ + virtual void keyEvent(KeyEvent *event); + virtual void touchDown(quint32 id, const QPointF &pos, quint32 time); + virtual void touchMotion(quint32 id, const QPointF &pos, quint32 time); + virtual void touchUp(quint32 id, quint32 time); + + virtual void pinchGestureBegin(int fingerCount, quint32 time); + virtual void pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time); + virtual void pinchGestureEnd(quint32 time); + virtual void pinchGestureCancelled(quint32 time); + + virtual void swipeGestureBegin(int fingerCount, quint32 time); + virtual void swipeGestureUpdate(const QSizeF &delta, quint32 time); + virtual void swipeGestureEnd(quint32 time); + virtual void swipeGestureCancelled(quint32 time); + +}; + + +} // namespace KWin + +#endif diff --git a/input_event_spy.cpp b/input_event_spy.cpp new file mode 100644 --- /dev/null +++ b/input_event_spy.cpp @@ -0,0 +1,116 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2016 Martin Gräßlin + +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 . +*********************************************************************/ +#include "input_event_spy.h" +#include "input.h" + +namespace KWin +{ + +InputEventSpy::InputEventSpy() = default; + +InputEventSpy::~InputEventSpy() +{ + if (input()) { + input()->uninstallInputEventSpy(this); + } +} + +void InputEventSpy::pointerEvent(MouseEvent *event) +{ + Q_UNUSED(event) +} + +void InputEventSpy::wheelEvent(WheelEvent *event) +{ + Q_UNUSED(event) +} + +void InputEventSpy::keyEvent(KeyEvent *event) +{ + Q_UNUSED(event) +} + +void InputEventSpy::touchDown(quint32 id, const QPointF &point, quint32 time) +{ + Q_UNUSED(id) + Q_UNUSED(point) + Q_UNUSED(time) +} + +void InputEventSpy::touchMotion(quint32 id, const QPointF &point, quint32 time) +{ + Q_UNUSED(id) + Q_UNUSED(point) + Q_UNUSED(time) +} + +void InputEventSpy::touchUp(quint32 id, quint32 time) +{ + Q_UNUSED(id) + Q_UNUSED(time) +} + +void InputEventSpy::pinchGestureBegin(int fingerCount, quint32 time) +{ + Q_UNUSED(fingerCount) + Q_UNUSED(time) +} + +void InputEventSpy::pinchGestureUpdate(qreal scale, qreal angleDelta, const QSizeF &delta, quint32 time) +{ + Q_UNUSED(scale) + Q_UNUSED(angleDelta) + Q_UNUSED(delta) + Q_UNUSED(time) +} + +void InputEventSpy::pinchGestureEnd(quint32 time) +{ + Q_UNUSED(time) +} + +void InputEventSpy::pinchGestureCancelled(quint32 time) +{ + Q_UNUSED(time) +} + +void InputEventSpy::swipeGestureBegin(int fingerCount, quint32 time) +{ + Q_UNUSED(fingerCount) + Q_UNUSED(time) +} + +void InputEventSpy::swipeGestureUpdate(const QSizeF &delta, quint32 time) +{ + Q_UNUSED(delta) + Q_UNUSED(time) +} + +void InputEventSpy::swipeGestureEnd(quint32 time) +{ + Q_UNUSED(time) +} + +void InputEventSpy::swipeGestureCancelled(quint32 time) +{ + Q_UNUSED(time) +} + +} diff --git a/keyboard_input.cpp b/keyboard_input.cpp --- a/keyboard_input.cpp +++ b/keyboard_input.cpp @@ -19,6 +19,7 @@ *********************************************************************/ #include "keyboard_input.h" #include "input_event.h" +#include "input_event_spy.h" #include "abstract_client.h" #include "options.h" #include "utils.h" @@ -675,6 +676,7 @@ } } + m_input->processSpies(std::bind(&InputEventSpy::keyEvent, std::placeholders::_1, &event)); m_input->processFilters(std::bind(&InputEventFilter::keyEvent, std::placeholders::_1, &event)); } diff --git a/pointer_input.cpp b/pointer_input.cpp --- a/pointer_input.cpp +++ b/pointer_input.cpp @@ -21,6 +21,7 @@ #include "platform.h" #include "effects.h" #include "input_event.h" +#include "input_event_spy.h" #include "osd.h" #include "screens.h" #include "shell_client.h" @@ -230,6 +231,7 @@ delta, deltaNonAccelerated, timeUsec, device); event.setModifiersRelevantForGlobalShortcuts(m_input->modifiersRelevantForGlobalShortcuts()); + m_input->processSpies(std::bind(&InputEventSpy::pointerEvent, std::placeholders::_1, &event)); m_input->processFilters(std::bind(&InputEventFilter::pointerEvent, std::placeholders::_1, &event, 0)); } @@ -258,6 +260,7 @@ m_input->keyboardModifiers(), time, QSizeF(), QSizeF(), 0, device); event.setModifiersRelevantForGlobalShortcuts(m_input->modifiersRelevantForGlobalShortcuts()); + m_input->processSpies(std::bind(&InputEventSpy::pointerEvent, std::placeholders::_1, &event)); m_input->processFilters(std::bind(&InputEventFilter::pointerEvent, std::placeholders::_1, &event, button)); } @@ -278,6 +281,7 @@ m_qtButtons, m_input->keyboardModifiers(), time, device); wheelEvent.setModifiersRelevantForGlobalShortcuts(m_input->modifiersRelevantForGlobalShortcuts()); + m_input->processSpies(std::bind(&InputEventSpy::wheelEvent, std::placeholders::_1, &wheelEvent)); m_input->processFilters(std::bind(&InputEventFilter::wheelEvent, std::placeholders::_1, &wheelEvent)); } @@ -288,6 +292,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::swipeGestureBegin, std::placeholders::_1, fingerCount, time)); m_input->processFilters(std::bind(&InputEventFilter::swipeGestureBegin, std::placeholders::_1, fingerCount, time)); } @@ -298,6 +303,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::swipeGestureUpdate, std::placeholders::_1, delta, time)); m_input->processFilters(std::bind(&InputEventFilter::swipeGestureUpdate, std::placeholders::_1, delta, time)); } @@ -308,6 +314,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::swipeGestureEnd, std::placeholders::_1, time)); m_input->processFilters(std::bind(&InputEventFilter::swipeGestureEnd, std::placeholders::_1, time)); } @@ -318,6 +325,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::swipeGestureCancelled, std::placeholders::_1, time)); m_input->processFilters(std::bind(&InputEventFilter::swipeGestureCancelled, std::placeholders::_1, time)); } @@ -328,6 +336,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::pinchGestureBegin, std::placeholders::_1, fingerCount, time)); m_input->processFilters(std::bind(&InputEventFilter::pinchGestureBegin, std::placeholders::_1, fingerCount, time)); } @@ -338,6 +347,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::pinchGestureUpdate, std::placeholders::_1, scale, angleDelta, delta, time)); m_input->processFilters(std::bind(&InputEventFilter::pinchGestureUpdate, std::placeholders::_1, scale, angleDelta, delta, time)); } @@ -348,6 +358,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::pinchGestureEnd, std::placeholders::_1, time)); m_input->processFilters(std::bind(&InputEventFilter::pinchGestureEnd, std::placeholders::_1, time)); } @@ -358,6 +369,7 @@ return; } + m_input->processSpies(std::bind(&InputEventSpy::pinchGestureCancelled, std::placeholders::_1, time)); m_input->processFilters(std::bind(&InputEventFilter::pinchGestureCancelled, std::placeholders::_1, time)); } diff --git a/touch_input.cpp b/touch_input.cpp --- a/touch_input.cpp +++ b/touch_input.cpp @@ -20,6 +20,7 @@ #include "touch_input.h" #include "abstract_client.h" #include "input.h" +#include "input_event_spy.h" #include "toplevel.h" #include "wayland_server.h" #include "workspace.h" @@ -151,6 +152,7 @@ return; } m_windowUpdatedInCycle = false; + m_input->processSpies(std::bind(&InputEventSpy::touchDown, std::placeholders::_1, id, pos, time)); m_input->processFilters(std::bind(&InputEventFilter::touchDown, std::placeholders::_1, id, pos, time)); m_windowUpdatedInCycle = false; } @@ -162,6 +164,7 @@ return; } m_windowUpdatedInCycle = false; + m_input->processSpies(std::bind(&InputEventSpy::touchUp, std::placeholders::_1, id, time)); m_input->processFilters(std::bind(&InputEventFilter::touchUp, std::placeholders::_1, id, time)); m_windowUpdatedInCycle = false; } @@ -173,6 +176,7 @@ return; } m_windowUpdatedInCycle = false; + m_input->processSpies(std::bind(&InputEventSpy::touchMotion, std::placeholders::_1, id, pos, time)); m_input->processFilters(std::bind(&InputEventFilter::touchMotion, std::placeholders::_1, id, pos, time)); m_windowUpdatedInCycle = false; }