diff --git a/input.cpp b/input.cpp
index cc35d18112..708e21061f 100644
--- a/input.cpp
+++ b/input.cpp
@@ -19,6 +19,7 @@ along with this program. If not, see .
*********************************************************************/
#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 @@ InputRedirection::~InputRedirection()
{
s_self = NULL;
qDeleteAll(m_filters);
+ qDeleteAll(m_spies);
}
void InputRedirection::installInputEventFilter(InputEventFilter *filter)
@@ -1382,6 +1384,16 @@ void InputRedirection::uninstallInputEventFilter(InputEventFilter *filter)
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.h b/input.h
index 167dbf5181..dd41dcafac 100644
--- a/input.h
+++ b/input.h
@@ -41,6 +41,7 @@ namespace KWin
class GlobalShortcutsManager;
class Toplevel;
class InputEventFilter;
+class InputEventSpy;
class KeyboardInputRedirection;
class PointerConstraintsFilter;
class PointerInputRedirection;
@@ -151,6 +152,17 @@ public:
**/
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 @@ public:
**/
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 @@ private:
PointerConstraintsFilter *m_pointerConstraintsFilter = nullptr;
QVector m_filters;
+ QVector m_spies;
KSharedConfigPtr m_inputConfig;
KWIN_SINGLETON(InputRedirection)
diff --git a/input_event_spy.cpp b/input_event_spy.cpp
new file mode 100644
index 0000000000..0b1f5004f4
--- /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/input_event_spy.h b/input_event_spy.h
new file mode 100644
index 0000000000..108dca39ec
--- /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/keyboard_input.cpp b/keyboard_input.cpp
index 918d62e4cd..21ccc19190 100644
--- a/keyboard_input.cpp
+++ b/keyboard_input.cpp
@@ -19,6 +19,7 @@ along with this program. If not, see .
*********************************************************************/
#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 @@ void KeyboardInputRedirection::processKey(uint32_t key, InputRedirection::Keyboa
}
}
+ 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
index 01d7397c34..3fb0719011 100644
--- a/pointer_input.cpp
+++ b/pointer_input.cpp
@@ -21,6 +21,7 @@ along with this program. If not, see .
#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 @@ void PointerInputRedirection::processMotion(const QPointF &pos, const QSizeF &de
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 @@ void PointerInputRedirection::processButton(uint32_t button, InputRedirection::P
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 @@ void PointerInputRedirection::processAxis(InputRedirection::PointerAxis axis, qr
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 @@ void PointerInputRedirection::processSwipeGestureBegin(int fingerCount, quint32
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 @@ void PointerInputRedirection::processSwipeGestureUpdate(const QSizeF &delta, qui
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 @@ void PointerInputRedirection::processSwipeGestureEnd(quint32 time, KWin::LibInpu
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 @@ void PointerInputRedirection::processSwipeGestureCancelled(quint32 time, KWin::L
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 @@ void PointerInputRedirection::processPinchGestureBegin(int fingerCount, quint32
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 @@ void PointerInputRedirection::processPinchGestureUpdate(qreal scale, qreal angle
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 @@ void PointerInputRedirection::processPinchGestureEnd(quint32 time, KWin::LibInpu
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 @@ void PointerInputRedirection::processPinchGestureCancelled(quint32 time, KWin::L
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
index a453eb6673..1f5894a063 100644
--- a/touch_input.cpp
+++ b/touch_input.cpp
@@ -20,6 +20,7 @@ along with this program. If not, see .
#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 @@ void TouchInputRedirection::processDown(qint32 id, const QPointF &pos, quint32 t
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 @@ void TouchInputRedirection::processUp(qint32 id, quint32 time, LibInput::Device
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 @@ void TouchInputRedirection::processMotion(qint32 id, const QPointF &pos, quint32
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;
}