xwayland: Add option to additionally eavesdrop on mouse buttons
BUG: 466448
This commit is contained in:
parent
d13b6db706
commit
183637502d
8 changed files with 103 additions and 28 deletions
|
@ -14,5 +14,8 @@
|
|||
</choices>
|
||||
<default>None</default>
|
||||
</entry>
|
||||
<entry name="XwaylandEavesdropsMouse" type="Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
|
|
@ -22,21 +22,6 @@ KCM.SimpleKCM {
|
|||
implicitWidth: Kirigami.Units.gridUnit * 48
|
||||
implicitHeight: Kirigami.Units.gridUnit * 33
|
||||
|
||||
QQC2.ButtonGroup {
|
||||
buttons: form.children
|
||||
exclusive: true
|
||||
checkedButton: buttons[kcm.settings.xwaylandEavesdrops]
|
||||
onCheckedButtonChanged: {
|
||||
let idx = -1
|
||||
for (const x in buttons) {
|
||||
if (buttons[x] === checkedButton) {
|
||||
idx = x
|
||||
}
|
||||
}
|
||||
kcm.settings.xwaylandEavesdrops = idx
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
@ -55,29 +40,51 @@ KCM.SimpleKCM {
|
|||
}
|
||||
|
||||
Kirigami.FormLayout {
|
||||
id: form
|
||||
|
||||
Layout.leftMargin: Kirigami.Units.gridUnit
|
||||
Layout.rightMargin: Kirigami.Units.gridUnit
|
||||
|
||||
QQC2.RadioButton {
|
||||
id: never
|
||||
Kirigami.FormData.label: i18n("Allow legacy X11 apps to read keystrokes typed in all apps:")
|
||||
text: i18n("Never")
|
||||
checked: kcm.settings.xwaylandEavesdrops === 0
|
||||
onToggled: if (checked) kcm.settings.xwaylandEavesdrops = 0
|
||||
}
|
||||
|
||||
QQC2.RadioButton {
|
||||
text: i18n("Only non-character keys")
|
||||
text: i18n("Only Meta, Control, Alt and Shift keys")
|
||||
checked: kcm.settings.xwaylandEavesdrops === 1
|
||||
onToggled: if (checked) kcm.settings.xwaylandEavesdrops = 1
|
||||
}
|
||||
|
||||
QQC2.RadioButton {
|
||||
text: i18n("As above, plus any key typed while the Control, Alt, or Meta keys are pressed")
|
||||
checked: kcm.settings.xwaylandEavesdrops === 2
|
||||
onToggled: if (checked) kcm.settings.xwaylandEavesdrops = 2
|
||||
}
|
||||
|
||||
QQC2.RadioButton {
|
||||
id: always
|
||||
text: i18n("Always")
|
||||
checked: kcm.settings.xwaylandEavesdrops === 3
|
||||
onToggled: if (checked) kcm.settings.xwaylandEavesdrops = 3
|
||||
}
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
}
|
||||
|
||||
QQC2.CheckBox {
|
||||
text: i18n("Additionally include mouse buttons")
|
||||
checked: kcm.settings.xwaylandEavesdropsMouse
|
||||
onToggled: kcm.settings.xwaylandEavesdropsMouse = checked
|
||||
enabled: !never.checked
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: Kirigami.Units.gridUnit
|
||||
type: Kirigami.MessageType.Warning
|
||||
text: i18n("Note that using this setting will reduce system security to that of the X11 session by permitting malicious software to steal passwords and spy on the text that you type. Make sure you understand and accept this risk.")
|
||||
visible: always.checked
|
||||
|
|
|
@ -339,5 +339,8 @@
|
|||
</choices>
|
||||
<default>None</default>
|
||||
</entry>
|
||||
<entry name="XwaylandEavesdropsMouse" type="Bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
|
|
@ -55,6 +55,7 @@ Options::Options(QObject *parent)
|
|||
, m_xwaylandCrashPolicy(Options::defaultXwaylandCrashPolicy())
|
||||
, m_xwaylandMaxCrashCount(Options::defaultXwaylandMaxCrashCount())
|
||||
, m_xwaylandEavesdrops(Options::defaultXwaylandEavesdrops())
|
||||
, m_xwaylandEavesdropsMouse(Options::defaultXwaylandEavesdropsMouse())
|
||||
, m_compositingMode(Options::defaultCompositingMode())
|
||||
, m_useCompositing(Options::defaultUseCompositing())
|
||||
, m_hiddenPreviews(Options::defaultHiddenPreviews())
|
||||
|
@ -156,6 +157,15 @@ void Options::setXwaylandEavesdrops(XwaylandEavesdropsMode mode)
|
|||
Q_EMIT xwaylandEavesdropsChanged();
|
||||
}
|
||||
|
||||
void Options::setXwaylandEavesdropsMouse(bool eavesdropsMouse)
|
||||
{
|
||||
if (m_xwaylandEavesdropsMouse == eavesdropsMouse) {
|
||||
return;
|
||||
}
|
||||
m_xwaylandEavesdropsMouse = eavesdropsMouse;
|
||||
Q_EMIT xwaylandEavesdropsChanged();
|
||||
}
|
||||
|
||||
void Options::setClickRaise(bool clickRaise)
|
||||
{
|
||||
if (m_autoRaise) {
|
||||
|
@ -827,6 +837,7 @@ void Options::syncFromKcfgc()
|
|||
setXwaylandCrashPolicy(m_settings->xwaylandCrashPolicy());
|
||||
setXwaylandMaxCrashCount(m_settings->xwaylandMaxCrashCount());
|
||||
setXwaylandEavesdrops(XwaylandEavesdropsMode(m_settings->xwaylandEavesdrops()));
|
||||
setXwaylandEavesdropsMouse(m_settings->xwaylandEavesdropsMouse());
|
||||
setPlacement(m_settings->placement());
|
||||
setAutoRaise(m_settings->autoRaise());
|
||||
setAutoRaiseInterval(m_settings->autoRaiseInterval());
|
||||
|
|
|
@ -262,6 +262,10 @@ public:
|
|||
{
|
||||
return m_xwaylandEavesdrops;
|
||||
}
|
||||
bool xwaylandEavesdropsMouse() const
|
||||
{
|
||||
return m_xwaylandEavesdropsMouse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether clicking on a window raises it in FocusFollowsMouse
|
||||
|
@ -692,6 +696,7 @@ public:
|
|||
void setXwaylandCrashPolicy(XwaylandCrashPolicy crashPolicy);
|
||||
void setXwaylandMaxCrashCount(int maxCrashCount);
|
||||
void setXwaylandEavesdrops(XwaylandEavesdropsMode mode);
|
||||
void setXwaylandEavesdropsMouse(bool eavesdropsMouse);
|
||||
void setNextFocusPrefersMouse(bool nextFocusPrefersMouse);
|
||||
void setClickRaise(bool clickRaise);
|
||||
void setAutoRaise(bool autoRaise);
|
||||
|
@ -870,6 +875,10 @@ public:
|
|||
{
|
||||
return None;
|
||||
}
|
||||
static bool defaultXwaylandEavesdropsMouse()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static ActivationDesktopPolicy defaultActivationDesktopPolicy()
|
||||
{
|
||||
return ActivationDesktopPolicy::SwitchToOtherDesktop;
|
||||
|
@ -888,6 +897,7 @@ Q_SIGNALS:
|
|||
void xwaylandCrashPolicyChanged();
|
||||
void xwaylandMaxCrashCountChanged();
|
||||
void xwaylandEavesdropsChanged();
|
||||
void xwaylandEavesdropsMouseChanged();
|
||||
void nextFocusPrefersMouseChanged();
|
||||
void clickRaiseChanged();
|
||||
void autoRaiseChanged();
|
||||
|
@ -972,6 +982,7 @@ private:
|
|||
XwaylandCrashPolicy m_xwaylandCrashPolicy;
|
||||
int m_xwaylandMaxCrashCount;
|
||||
XwaylandEavesdropsMode m_xwaylandEavesdrops;
|
||||
bool m_xwaylandEavesdropsMouse;
|
||||
|
||||
CompositingType m_compositingMode;
|
||||
bool m_useCompositing;
|
||||
|
|
|
@ -222,6 +222,15 @@ void PointerInterface::sendButton(quint32 button, PointerButtonState state, quin
|
|||
}
|
||||
}
|
||||
|
||||
void PointerInterface::sendButton(quint32 button, PointerButtonState state, ClientConnection *client)
|
||||
{
|
||||
const auto pointerResources = d->pointersForClient(client);
|
||||
const quint32 serial = d->seat->display()->nextSerial();
|
||||
for (PointerInterfacePrivate::Resource *resource : pointerResources) {
|
||||
d->send_button(resource->handle, serial, d->seat->timestamp().count(), button, quint32(state));
|
||||
}
|
||||
}
|
||||
|
||||
static void updateAccumulators(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerInterfacePrivate *d, qint32 &valueAxisLowRes, qint32 &valueDiscrete)
|
||||
{
|
||||
const int newDirection = deltaV120 > 0 ? 1 : -1;
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace KWin
|
|||
class PointerSurfaceCursorPrivate;
|
||||
class PointerSurfaceCursor;
|
||||
class PointerInterfacePrivate;
|
||||
class ClientConnection;
|
||||
class SeatInterface;
|
||||
class SurfaceInterface;
|
||||
|
||||
|
@ -60,6 +61,7 @@ public:
|
|||
void sendEnter(SurfaceInterface *surface, const QPointF &position, quint32 serial);
|
||||
void sendLeave(quint32 serial);
|
||||
void sendButton(quint32 button, PointerButtonState state, quint32 serial);
|
||||
void sendButton(quint32 button, PointerButtonState state, ClientConnection *client);
|
||||
void sendAxis(Qt::Orientation orientation, qreal delta, qint32 deltaV120, PointerAxisSource source, PointerAxisRelativeDirection direction);
|
||||
void sendMotion(const QPointF &position);
|
||||
void sendFrame();
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <KSelectionOwner>
|
||||
#include <wayland/keyboard.h>
|
||||
#include <wayland/pointer.h>
|
||||
#include <wayland/seat.h>
|
||||
#include <wayland/surface.h>
|
||||
|
||||
|
@ -108,7 +109,7 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
void setMode(XwaylandEavesdropsMode mode)
|
||||
void setMode(XwaylandEavesdropsMode mode, bool eavesdropsMouse)
|
||||
{
|
||||
static const Qt::KeyboardModifiers modifierKeys = {
|
||||
Qt::ControlModifier,
|
||||
|
@ -337,22 +338,26 @@ public:
|
|||
|
||||
switch (mode) {
|
||||
case None:
|
||||
m_filter = {};
|
||||
m_filterKey = {};
|
||||
m_filterMouse = false;
|
||||
break;
|
||||
case NonCharacterKeys:
|
||||
m_filter = [](int key, Qt::KeyboardModifiers) {
|
||||
m_filterKey = [](int key, Qt::KeyboardModifiers) {
|
||||
return !characterKeys.contains(key);
|
||||
};
|
||||
m_filterMouse = eavesdropsMouse;
|
||||
break;
|
||||
case AllKeysWithModifier:
|
||||
m_filter = [](int key, Qt::KeyboardModifiers m) {
|
||||
m_filterKey = [](int key, Qt::KeyboardModifiers m) {
|
||||
return m.testAnyFlags(modifierKeys) || !characterKeys.contains(key);
|
||||
};
|
||||
m_filterMouse = eavesdropsMouse;
|
||||
break;
|
||||
case All:
|
||||
m_filter = [](int, Qt::KeyboardModifiers) {
|
||||
m_filterKey = [](int, Qt::KeyboardModifiers) {
|
||||
return true;
|
||||
};
|
||||
m_filterMouse = eavesdropsMouse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -364,7 +369,7 @@ public:
|
|||
}
|
||||
|
||||
Window *window = workspace()->activeWindow();
|
||||
if (!m_filter || !m_filter(event->key(), event->modifiers()) || (window && window->isLockScreen())) {
|
||||
if (!m_filterKey || !m_filterKey(event->key(), event->modifiers()) || (window && window->isLockScreen())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -388,7 +393,29 @@ public:
|
|||
xkb->modifierState().locked,
|
||||
xkb->currentLayout());
|
||||
|
||||
waylandServer()->seat()->keyboard()->sendKey(event->nativeScanCode(), state, xwaylandClient);
|
||||
keyboard->sendKey(event->nativeScanCode(), state, xwaylandClient);
|
||||
}
|
||||
}
|
||||
|
||||
void pointerEvent(KWin::MouseEvent *event) override
|
||||
{
|
||||
Window *window = workspace()->activeWindow();
|
||||
if (!m_filterMouse || (window && window->isLockScreen())) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto pointer = waylandServer()->seat()->pointer();
|
||||
auto surface = pointer->focusedSurface();
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClientConnection *client = surface->client();
|
||||
ClientConnection *xwaylandClient = waylandServer()->xWaylandConnection();
|
||||
if (xwaylandClient && xwaylandClient != client) {
|
||||
PointerButtonState state{event->type() == QEvent::MouseButtonPress};
|
||||
|
||||
pointer->sendButton(event->nativeButton(), state, xwaylandClient);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,7 +434,8 @@ public:
|
|||
}
|
||||
|
||||
QHash<quint32, KeyboardKeyState> m_states;
|
||||
std::function<bool(int key, Qt::KeyboardModifiers)> m_filter;
|
||||
std::function<bool(int key, Qt::KeyboardModifiers)> m_filterKey;
|
||||
bool m_filterMouse = false;
|
||||
};
|
||||
|
||||
Xwayland::Xwayland(Application *app)
|
||||
|
@ -547,6 +575,7 @@ void Xwayland::handleXwaylandReady()
|
|||
|
||||
refreshEavesdropping();
|
||||
connect(options, &Options::xwaylandEavesdropsChanged, this, &Xwayland::refreshEavesdropping);
|
||||
connect(options, &Options::xwaylandEavesdropsMouseChanged, this, &Xwayland::refreshEavesdropping);
|
||||
|
||||
Q_EMIT started();
|
||||
}
|
||||
|
@ -560,7 +589,7 @@ void Xwayland::refreshEavesdropping()
|
|||
const bool enabled = options->xwaylandEavesdrops() != None;
|
||||
if (enabled == bool(m_inputSpy)) {
|
||||
if (m_inputSpy) {
|
||||
m_inputSpy->setMode(options->xwaylandEavesdrops());
|
||||
m_inputSpy->setMode(options->xwaylandEavesdrops(), options->xwaylandEavesdropsMouse());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -568,7 +597,7 @@ void Xwayland::refreshEavesdropping()
|
|||
if (enabled) {
|
||||
m_inputSpy = std::make_unique<XwaylandInputSpy>();
|
||||
input()->installInputEventSpy(m_inputSpy.get());
|
||||
m_inputSpy->setMode(options->xwaylandEavesdrops());
|
||||
m_inputSpy->setMode(options->xwaylandEavesdrops(), options->xwaylandEavesdropsMouse());
|
||||
} else {
|
||||
input()->uninstallInputEventSpy(m_inputSpy.get());
|
||||
m_inputSpy.reset();
|
||||
|
|
Loading…
Reference in a new issue