Commit 2c333417 authored by Martin Flöser's avatar Martin Flöser
Browse files

Support modifier only shortcuts on X11

Summary:
With this change KWin/X11 reuses Wayland's modifier only shortcut
architecture. The XInput2 event filter also listens for
 * XI_RawKeyPress
 * XI_RawKeyRelease

Those events are also reported if another X11 client grabs keyboard
input. Thus KWin gets all key events, just like on Wayland.

All key events are then sent through the Xkb class which performs the
mapping from key codes to key syms and is able to detect whether the
modifier got pressed/released without another key being pressed.

This change will require a few follow up changes, which are required
also for Wayland:
 * ignore if another input device got interacted (e.g. mouse press,
   touch screen, scroll, etc)
 * use the layout from XServer instead of using our own (needed on
   Wayland in nested setup)

The biggest disadvantage of the change is that it triggers a wake
up of KWin on every key event. But as KWin already listens to all
pointer events that's not a big difference and normally a key event
will wake up the compositor any way.

Reviewers: #plasma

Subscribers: kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D2425
parent 1eac18a8
......@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// kwin
#include <kwinglobals.h>
#include "input.h"
#include "keyboard_input.h"
#include "main.h"
#include "utils.h"
#include "x11eventfilter.h"
......@@ -42,6 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <X11/Xlib.h>
#if HAVE_X11_XINPUT
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XI2proto.h>
#else
#define XI_RawMotion 0
#endif
......@@ -263,14 +265,24 @@ class XInputEventFilter : public X11EventFilter
{
public:
XInputEventFilter(X11Cursor *parent, int xi_opcode)
: X11EventFilter(XCB_GE_GENERIC, xi_opcode, QVector<int>{XI_RawMotion, XI_RawButtonPress, XI_RawButtonRelease})
: X11EventFilter(XCB_GE_GENERIC, xi_opcode, QVector<int>{XI_RawMotion, XI_RawButtonPress, XI_RawButtonRelease, XI_RawKeyPress, XI_RawKeyRelease})
, m_x11Cursor(parent)
{}
virtual ~XInputEventFilter() = default;
bool event(xcb_generic_event_t *event) override {
Q_UNUSED(event)
m_x11Cursor->schedulePoll();
xcb_ge_generic_event_t *ge = reinterpret_cast<xcb_ge_generic_event_t *>(event);
switch (ge->event_type) {
case XI_RawKeyPress:
input()->keyboard()->xkb()->updateKey(reinterpret_cast<xXIRawEvent*>(event)->detail - 8, InputRedirection::KeyboardKeyPressed);
break;
case XI_RawKeyRelease:
input()->keyboard()->xkb()->updateKey(reinterpret_cast<xXIRawEvent*>(event)->detail - 8, InputRedirection::KeyboardKeyReleased);
break;
default:
m_x11Cursor->schedulePoll();
break;
}
return false;
}
......@@ -332,6 +344,7 @@ void X11Cursor::initXInput()
}
m_hasXInput = true;
m_xiOpcode = xi_opcode;
input()->keyboard()->xkb()->reconfigure();
#endif
#endif
}
......@@ -391,6 +404,8 @@ void X11Cursor::doStartMousePolling()
XISetMask(mask1, XI_RawMotion);
XISetMask(mask1, XI_RawButtonPress);
XISetMask(mask1, XI_RawButtonRelease);
XISetMask(mask1, XI_RawKeyPress);
XISetMask(mask1, XI_RawKeyRelease);
evmasks[0].deviceid = XIAllMasterDevices;
evmasks[0].mask_len = sizeof(mask1);
......
......@@ -308,10 +308,12 @@ void Xkb::updateModifiers()
QDBusConnection::sessionBus().asyncCall(msg);
}
waylandServer()->seat()->updateKeyboardModifiers(xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_DEPRESSED)),
xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LATCHED)),
xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED)),
layout);
if (waylandServer()) {
waylandServer()->seat()->updateKeyboardModifiers(xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_DEPRESSED)),
xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LATCHED)),
xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED)),
layout);
}
}
xkb_keysym_t Xkb::toKeysym(uint32_t key)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment