diff --git a/backends/x11/x11windowed_backend.cpp b/backends/x11/x11windowed_backend.cpp
index 9f88b83757..1db28ae77f 100644
--- a/backends/x11/x11windowed_backend.cpp
+++ b/backends/x11/x11windowed_backend.cpp
@@ -35,6 +35,8 @@ along with this program. If not, see .
#include
#include
#include
+// xcb
+#include
// system
#include
#include
@@ -51,6 +53,9 @@ X11WindowedBackend::X11WindowedBackend(QObject *parent)
X11WindowedBackend::~X11WindowedBackend()
{
if (m_connection) {
+ if (m_keySymbols) {
+ xcb_key_symbols_free(m_keySymbols);
+ }
if (m_window) {
xcb_unmap_window(m_connection, m_window);
xcb_destroy_window(m_connection, m_window);
@@ -121,7 +126,7 @@ void X11WindowedBackend::createWindow()
m_winInfo = new NETWinInfo(m_connection, m_window, m_screen->root, NET::WMWindowType, NET::Properties2());
m_winInfo->setWindowType(NET::Normal);
- m_winInfo->setName(i18n("KDE Wayland Compositor (%1)", waylandServer()->display()->socketName()).toUtf8().constData());
+ updateWindowTitle();
m_winInfo->setPid(QCoreApplication::applicationPid());
QIcon windowIcon = QIcon::fromTheme(QStringLiteral("kwin"));
auto addIcon = [this, &windowIcon] (const QSize &size) {
@@ -179,6 +184,13 @@ void X11WindowedBackend::handleEvent(xcb_generic_event_t *e)
case XCB_KEY_RELEASE: {
auto event = reinterpret_cast(e);
if (eventType == XCB_KEY_PRESS) {
+ if (!m_keySymbols) {
+ m_keySymbols = xcb_key_symbols_alloc(m_connection);
+ }
+ const xcb_keysym_t kc = xcb_key_symbols_get_keysym(m_keySymbols, event->detail, 0);
+ if (kc == XK_Control_R) {
+ grabKeyboard(event->time);
+ }
keyboardKeyPressed(event->detail - 8, event->time);
} else {
keyboardKeyReleased(event->detail - 8, event->time);
@@ -199,11 +211,60 @@ void X11WindowedBackend::handleEvent(xcb_generic_event_t *e)
case XCB_EXPOSE:
handleExpose(reinterpret_cast(e));
break;
+ case XCB_MAPPING_NOTIFY:
+ if (m_keySymbols) {
+ xcb_refresh_keyboard_mapping(m_keySymbols, reinterpret_cast(e));
+ }
+ break;
default:
break;
}
}
+void X11WindowedBackend::grabKeyboard(xcb_timestamp_t time)
+{
+ const bool oldState = m_keyboardGrabbed;
+ if (m_keyboardGrabbed) {
+ xcb_ungrab_keyboard(m_connection, time);
+ xcb_ungrab_pointer(m_connection, time);
+ m_keyboardGrabbed = false;
+ } else {
+ const auto c = xcb_grab_keyboard_unchecked(m_connection, false, m_window, time,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
+ ScopedCPointer grab(xcb_grab_keyboard_reply(m_connection, c, nullptr));
+ if (grab.isNull()) {
+ return;
+ }
+ if (grab->status == XCB_GRAB_STATUS_SUCCESS) {
+ const auto c = xcb_grab_pointer_unchecked(m_connection, false, m_window,
+ XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
+ XCB_EVENT_MASK_POINTER_MOTION |
+ XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
+ m_window, XCB_CURSOR_NONE, time);
+ ScopedCPointer grab(xcb_grab_pointer_reply(m_connection, c, nullptr));
+ if (grab.isNull() || grab->status != XCB_GRAB_STATUS_SUCCESS) {
+ xcb_ungrab_keyboard(m_connection, time);
+ return;
+ }
+ m_keyboardGrabbed = true;
+ }
+ }
+ if (oldState != m_keyboardGrabbed) {
+ updateWindowTitle();
+ xcb_flush(m_connection);
+ }
+}
+
+void X11WindowedBackend::updateWindowTitle()
+{
+ const QString grab = m_keyboardGrabbed ? i18n("Press right control to ungrab input") : i18n("Press right control key to grab input");
+ const QString title = QStringLiteral("%1 (%2) - %3").arg(i18n("KDE Wayland Compositor"))
+ .arg(waylandServer()->display()->socketName())
+ .arg(grab);
+ m_winInfo->setName(title.toUtf8().constData());
+}
+
void X11WindowedBackend::handleClientMessage(xcb_client_message_event_t *event)
{
if (event->window != m_window) {
diff --git a/backends/x11/x11windowed_backend.h b/backends/x11/x11windowed_backend.h
index c2ac8634aa..dc7c1564d2 100644
--- a/backends/x11/x11windowed_backend.h
+++ b/backends/x11/x11windowed_backend.h
@@ -30,6 +30,7 @@ along with this program. If not, see .
struct _XDisplay;
typedef struct _XDisplay Display;
+typedef struct _XCBKeySymbols xcb_key_symbols_t;
class NETWinInfo;
namespace KWin
@@ -78,6 +79,8 @@ Q_SIGNALS:
private:
void createWindow();
void startEventReading();
+ void grabKeyboard(xcb_timestamp_t time);
+ void updateWindowTitle();
void handleEvent(xcb_generic_event_t *event);
void handleClientMessage(xcb_client_message_event_t *event);
void handleButtonPress(xcb_button_press_event_t *event);
@@ -87,6 +90,7 @@ private:
xcb_connection_t *m_connection = nullptr;
xcb_screen_t *m_screen = nullptr;
+ xcb_key_symbols_t *m_keySymbols = nullptr;
int m_screenNumber = 0;
xcb_window_t m_window = XCB_WINDOW_NONE;
QSize m_size;
@@ -95,6 +99,7 @@ private:
xcb_cursor_t m_cursor = XCB_CURSOR_NONE;
Display *m_display = nullptr;
NETWinInfo *m_winInfo = nullptr;
+ bool m_keyboardGrabbed = false;
};
}