diff --git a/debug_console.cpp b/debug_console.cpp
index d6ef0c9796..6eeb8fd710 100644
--- a/debug_console.cpp
+++ b/debug_console.cpp
@@ -36,12 +36,274 @@ along with this program. If not, see .
#include
#include
// Qt
+#include
#include
#include
namespace KWin
{
+
+static QString tableHeaderRow(const QString &title)
+{
+ return QStringLiteral("%1 |
").arg(title);
+}
+
+template
+static
+QString tableRow(const QString &title, const T &argument)
+{
+ return QStringLiteral("%1 | %2 |
").arg(title).arg(argument);
+}
+
+static QString timestampRow(quint32 timestamp)
+{
+ return tableRow(i18n("Timestamp"), timestamp);
+}
+
+static QString buttonToString(Qt::MouseButton button)
+{
+ switch (button) {
+ case Qt::LeftButton:
+ return i18nc("A mouse button", "Left");
+ case Qt::RightButton:
+ return i18nc("A mouse button", "Right");
+ case Qt::MiddleButton:
+ return i18nc("A mouse button", "Middle");
+ case Qt::BackButton:
+ return i18nc("A mouse button", "Back");
+ case Qt::ForwardButton:
+ return i18nc("A mouse button", "Forward");
+ case Qt::TaskButton:
+ return i18nc("A mouse button", "Task");
+ case Qt::ExtraButton4:
+ return i18nc("A mouse button", "Extra Button 4");
+ case Qt::ExtraButton5:
+ return i18nc("A mouse button", "Extra Button 5");
+ case Qt::ExtraButton6:
+ return i18nc("A mouse button", "Extra Button 6");
+ case Qt::ExtraButton7:
+ return i18nc("A mouse button", "Extra Button 7");
+ case Qt::ExtraButton8:
+ return i18nc("A mouse button", "Extra Button 8");
+ case Qt::ExtraButton9:
+ return i18nc("A mouse button", "Extra Button 9");
+ case Qt::ExtraButton10:
+ return i18nc("A mouse button", "Extra Button 10");
+ case Qt::ExtraButton11:
+ return i18nc("A mouse button", "Extra Button 11");
+ case Qt::ExtraButton12:
+ return i18nc("A mouse button", "Extra Button 12");
+ case Qt::ExtraButton13:
+ return i18nc("A mouse button", "Extra Button 13");
+ case Qt::ExtraButton14:
+ return i18nc("A mouse button", "Extra Button 14");
+ case Qt::ExtraButton15:
+ return i18nc("A mouse button", "Extra Button 15");
+ case Qt::ExtraButton16:
+ return i18nc("A mouse button", "Extra Button 16");
+ case Qt::ExtraButton17:
+ return i18nc("A mouse button", "Extra Button 17");
+ case Qt::ExtraButton18:
+ return i18nc("A mouse button", "Extra Button 18");
+ case Qt::ExtraButton19:
+ return i18nc("A mouse button", "Extra Button 19");
+ case Qt::ExtraButton20:
+ return i18nc("A mouse button", "Extra Button 20");
+ case Qt::ExtraButton21:
+ return i18nc("A mouse button", "Extra Button 21");
+ case Qt::ExtraButton22:
+ return i18nc("A mouse button", "Extra Button 22");
+ case Qt::ExtraButton23:
+ return i18nc("A mouse button", "Extra Button 23");
+ case Qt::ExtraButton24:
+ return i18nc("A mouse button", "Extra Button 24");
+ default:
+ return QString();
+ }
+}
+
+static QString buttonsToString(Qt::MouseButtons buttons)
+{
+ QString ret;
+ for (uint i = 1; i < Qt::ExtraButton24; i = i << 1) {
+ if (buttons & i) {
+ ret.append(buttonToString(Qt::MouseButton(uint(buttons) & i)));
+ ret.append(QStringLiteral(" "));
+ }
+ };
+ return ret;
+}
+
+static const QString s_hr = QStringLiteral("
");
+static const QString s_tableStart = QStringLiteral("");
+static const QString s_tableEnd = QStringLiteral("
");
+
+DebugConsoleFilter::DebugConsoleFilter(QTextEdit *textEdit)
+ : InputEventFilter()
+ , m_textEdit(textEdit)
+{
+}
+
+DebugConsoleFilter::~DebugConsoleFilter() = default;
+
+bool DebugConsoleFilter::pointerEvent(QMouseEvent *event, quint32 nativeButton)
+{
+ QString text = s_hr;
+ const QString timestamp = timestampRow(event->timestamp());
+
+ text.append(s_tableStart);
+ switch (event->type()) {
+ case QEvent::MouseMove:
+ text.append(tableHeaderRow(i18nc("A mouse pointer motion event", "Pointer Motion")));
+ text.append(timestamp);
+ text.append(tableRow(i18nc("The global mouse pointer position", "Global Position"), QStringLiteral("%1/%2").arg(event->pos().x()).arg(event->pos().y())));
+ break;
+ case QEvent::MouseButtonPress:
+ text.append(tableHeaderRow(i18nc("A mouse pointer button press event", "Pointer Button Press")));
+ text.append(timestamp);
+ text.append(tableRow(i18nc("A button in a mouse press/release event", "Button"), buttonToString(event->button())));
+ text.append(tableRow(i18nc("A button in a mouse press/release event", "Native Button code"), nativeButton));
+ text.append(tableRow(i18nc("All currently pressed buttons in a mouse press/release event", "Pressed Buttons"), buttonsToString(event->buttons())));
+ break;
+ case QEvent::MouseButtonRelease:
+ text.append(tableHeaderRow(i18nc("A mouse pointer button release event", "Pointer Button Release")));
+ text.append(timestamp);
+ text.append(tableRow(i18nc("A button in a mouse press/release event", "Button"), buttonToString(event->button())));
+ text.append(tableRow(i18nc("A button in a mouse press/release event", "Native Button code"), nativeButton));
+ text.append(tableRow(i18nc("All currently pressed buttons in a mouse press/release event", "Pressed Buttons"), buttonsToString(event->buttons())));
+ break;
+ default:
+ break;
+ }
+ text.append(s_tableEnd);
+
+ m_textEdit->insertHtml(text);
+ m_textEdit->ensureCursorVisible();
+ return false;
+}
+
+bool DebugConsoleFilter::wheelEvent(QWheelEvent *event)
+{
+ QString text = s_hr;
+ text.append(s_tableStart);
+ text.append(tableHeaderRow(i18nc("A mouse pointer axis (wheel) event", "Pointer Axis")));
+ text.append(timestampRow(event->timestamp()));
+ const Qt::Orientation orientation = event->angleDelta().x() == 0 ? Qt::Vertical : Qt::Horizontal;
+ text.append(tableRow(i18nc("The orientation of a pointer axis event", "Orientation"),
+ orientation == Qt::Horizontal ? i18nc("An orientation of a pointer axis event", "Horizontal")
+ : i18nc("An orientation of a pointer axis event", "Vertical")));
+ text.append(tableRow(QStringLiteral("Delta"), orientation == Qt::Horizontal ? event->angleDelta().x() : event->angleDelta().y()));
+ text.append(s_tableEnd);
+
+ m_textEdit->insertHtml(text);
+ m_textEdit->ensureCursorVisible();
+ return false;
+}
+
+bool DebugConsoleFilter::keyEvent(QKeyEvent *event)
+{
+ QString text = s_hr;
+ text.append(s_tableStart);
+
+ switch (event->type()) {
+ case QEvent::KeyPress:
+ text.append(tableHeaderRow(i18nc("A key press event", "Key Press")));
+ break;
+ case QEvent::KeyRelease:
+ text.append(tableHeaderRow(i18nc("A key release event", "Key Release")));
+ break;
+ default:
+ break;
+ }
+ auto modifiersToString = [event] {
+ QString ret;
+ if (event->modifiers().testFlag(Qt::ShiftModifier)) {
+ ret.append(i18nc("A keyboard modifier", "Shift"));
+ ret.append(QStringLiteral(" "));
+ }
+ if (event->modifiers().testFlag(Qt::ControlModifier)) {
+ ret.append(i18nc("A keyboard modifier", "Control"));
+ ret.append(QStringLiteral(" "));
+ }
+ if (event->modifiers().testFlag(Qt::AltModifier)) {
+ ret.append(i18nc("A keyboard modifier", "Alt"));
+ ret.append(QStringLiteral(" "));
+ }
+ if (event->modifiers().testFlag(Qt::MetaModifier)) {
+ ret.append(i18nc("A keyboard modifier", "Meta"));
+ ret.append(QStringLiteral(" "));
+ }
+ if (event->modifiers().testFlag(Qt::KeypadModifier)) {
+ ret.append(i18nc("A keyboard modifier", "Keypad"));
+ ret.append(QStringLiteral(" "));
+ }
+ if (event->modifiers().testFlag(Qt::GroupSwitchModifier)) {
+ ret.append(i18nc("A keyboard modifier", "Group-switch"));
+ ret.append(QStringLiteral(" "));
+ }
+ return ret;
+ };
+ text.append(timestampRow(event->timestamp()));
+ text.append(tableRow(i18nc("Whether the event is an automatic key repeat", "Repeat"), event->isAutoRepeat()));
+ text.append(tableRow(i18nc("The code as read from the input device", "Scan code"), event->nativeScanCode()));
+ text.append(tableRow(i18nc("The translated code to an Xkb symbol", "Xkb symbol"), event->nativeVirtualKey()));
+ text.append(tableRow(i18nc("The translated code interpreted as text", "Utf8"), event->text()));
+ text.append(tableRow(i18nc("The currently active modifiers", "Modifiers"), modifiersToString()));
+
+ text.append(s_tableEnd);
+
+ m_textEdit->insertHtml(text);
+ m_textEdit->ensureCursorVisible();
+ return false;
+}
+
+bool DebugConsoleFilter::touchDown(quint32 id, const QPointF &pos, quint32 time)
+{
+ QString text = s_hr;
+ text.append(s_tableStart);
+ text.append(tableHeaderRow(i18nc("A touch down event", "Touch down")));
+ text.append(timestampRow(time));
+ text.append(tableRow(i18nc("The id of the touch point in the touch event", "Point identifier"), id));
+ text.append(tableRow(i18nc("The global position of the touch point", "Global position"),
+ QStringLiteral("%1/%2").arg(pos.x()).arg(pos.y())));
+ text.append(s_tableEnd);
+
+ m_textEdit->insertHtml(text);
+ m_textEdit->ensureCursorVisible();
+ return false;
+}
+
+bool DebugConsoleFilter::touchMotion(quint32 id, const QPointF &pos, quint32 time)
+{
+ QString text = s_hr;
+ text.append(s_tableStart);
+ text.append(tableHeaderRow(i18nc("A touch motion event", "Touch Motion")));
+ text.append(timestampRow(time));
+ text.append(tableRow(i18nc("The id of the touch point in the touch event", "Point identifier"), id));
+ text.append(tableRow(i18nc("The global position of the touch point", "Global position"),
+ QStringLiteral("%1/%2").arg(pos.x()).arg(pos.y())));
+ text.append(s_tableEnd);
+
+ m_textEdit->insertHtml(text);
+ m_textEdit->ensureCursorVisible();
+ return false;
+}
+
+bool DebugConsoleFilter::touchUp(quint32 id, quint32 time)
+{
+ QString text = s_hr;
+ text.append(s_tableStart);
+ text.append(tableHeaderRow(i18nc("A touch up event", "Touch Up")));
+ text.append(timestampRow(time));
+ text.append(tableRow(i18nc("The id of the touch point in the touch event", "Point identifier"), id));
+ text.append(s_tableEnd);
+
+ m_textEdit->insertHtml(text);
+ m_textEdit->ensureCursorVisible();
+ return false;
+}
+
DebugConsole::DebugConsole()
: QWidget()
, m_ui(new Ui::DebugConsole)
@@ -55,6 +317,7 @@ DebugConsole::DebugConsole()
if (kwinApp()->operationMode() == Application::OperationMode::OperationModeX11) {
m_ui->surfacesButton->setDisabled(true);
+ m_ui->inputEventsButton->setDisabled(true);
}
connect(m_ui->quitButton, &QAbstractButton::clicked, this, &DebugConsole::deleteLater);
@@ -64,8 +327,11 @@ DebugConsole::DebugConsole()
return;
}
m_ui->surfacesButton->setChecked(false);
+ m_ui->inputEventsButton->setChecked(false);
m_ui->treeView->model()->deleteLater();
m_ui->treeView->setModel(new DebugConsoleModel(this));
+ m_ui->treeView->setVisible(true);
+ m_ui->inputTextEdit->setVisible(false);
}
);
connect(m_ui->surfacesButton, &QAbstractButton::toggled, this,
@@ -74,10 +340,30 @@ DebugConsole::DebugConsole()
return;
}
m_ui->windowsButton->setChecked(false);
+ m_ui->inputEventsButton->setChecked(false);
m_ui->treeView->model()->deleteLater();
m_ui->treeView->setModel(new SurfaceTreeModel(this));
+ m_ui->treeView->setVisible(true);
+ m_ui->inputTextEdit->setVisible(false);
}
);
+ connect(m_ui->inputEventsButton, &QAbstractButton::toggled, this,
+ [this] (bool toggled) {
+ if (!toggled) {
+ return;
+ }
+ m_ui->windowsButton->setChecked(false);
+ m_ui->surfacesButton->setChecked(false);
+ m_ui->treeView->setVisible(false);
+ m_ui->inputTextEdit->setVisible(true);
+ if (m_inputFilter.isNull()) {
+ m_inputFilter.reset(new DebugConsoleFilter(m_ui->inputTextEdit));
+ input()->prepandInputEventFilter(m_inputFilter.data());
+ }
+ }
+ );
+
+ m_ui->inputTextEdit->setVisible(false);
// for X11
setWindowFlags(Qt::X11BypassWindowManagerHint);
diff --git a/debug_console.h b/debug_console.h
index d68683e08c..596e6aeddc 100644
--- a/debug_console.h
+++ b/debug_console.h
@@ -21,11 +21,14 @@ along with this program. If not, see .
#define KWIN_DEBUG_CONSOLE_H
#include
+#include "input.h"
#include
#include
#include
+class QTextEdit;
+
namespace Ui
{
class DebugConsole;
@@ -37,6 +40,7 @@ namespace KWin
class Client;
class ShellClient;
class Unmanaged;
+class DebugConsoleFilter;
class KWIN_EXPORT DebugConsoleModel : public QAbstractItemModel
{
@@ -98,6 +102,7 @@ public:
private:
QScopedPointer m_ui;
+ QScopedPointer m_inputFilter;
};
class SurfaceTreeModel : public QAbstractItemModel
@@ -114,6 +119,23 @@ public:
QModelIndex parent(const QModelIndex &child) const override;
};
+class DebugConsoleFilter : public InputEventFilter
+{
+public:
+ explicit DebugConsoleFilter(QTextEdit *textEdit);
+ virtual ~DebugConsoleFilter();
+
+ bool pointerEvent(QMouseEvent *event, quint32 nativeButton) override;
+ bool wheelEvent(QWheelEvent *event) override;
+ bool keyEvent(QKeyEvent *event) override;
+ bool touchDown(quint32 id, const QPointF &pos, quint32 time) override;
+ bool touchMotion(quint32 id, const QPointF &pos, quint32 time) override;
+ bool touchUp(quint32 id, quint32 time) override;
+
+private:
+ QTextEdit *m_textEdit;
+};
+
}
#endif
diff --git a/debug_console.ui b/debug_console.ui
index 735014558f..5d4589a04f 100644
--- a/debug_console.ui
+++ b/debug_console.ui
@@ -39,6 +39,16 @@
+ -
+
+
+ Input Events
+
+
+ true
+
+
+
-
@@ -68,6 +78,16 @@
+ -
+
+
+ false
+
+
+ true
+
+
+