client: rework xkb context/keymap/state handling
- Use smart pointers from xkbcommon_support-private. - Remove needless strdup() calls. - Don't recreate context. And move it into qwaylanddisplay so it can be shared in future between several keyboards. It contains things like a logging level and include paths. Change-Id: I5d1f667e710046e6b62aa2caf82fdb2decc24520 Reviewed-by: Johan Helsing <johan.helsing@qt.io>
This commit is contained in:
parent
9a782df3e7
commit
90fe97b017
@ -16,7 +16,7 @@ CONFIG -= precompile_header
|
|||||||
CONFIG += link_pkgconfig wayland-scanner
|
CONFIG += link_pkgconfig wayland-scanner
|
||||||
|
|
||||||
qtConfig(xkbcommon) {
|
qtConfig(xkbcommon) {
|
||||||
QT_PRIVATE += xkbcommon_support-private
|
QT_FOR_PRIVATE += xkbcommon_support-private
|
||||||
}
|
}
|
||||||
|
|
||||||
qtHaveModule(linuxaccessibility_support_private): \
|
qtHaveModule(linuxaccessibility_support_private): \
|
||||||
|
@ -142,6 +142,12 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
|
|||||||
|
|
||||||
mWindowManagerIntegration.reset(new QWaylandWindowManagerIntegration(this));
|
mWindowManagerIntegration.reset(new QWaylandWindowManagerIntegration(this));
|
||||||
|
|
||||||
|
#if QT_CONFIG(xkbcommon)
|
||||||
|
mXkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
|
||||||
|
if (!mXkbContext)
|
||||||
|
qCWarning(lcQpaWayland, "failed to create xkb context");
|
||||||
|
#endif
|
||||||
|
|
||||||
forceRoundTrip();
|
forceRoundTrip();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,10 @@
|
|||||||
|
|
||||||
#include <qpa/qplatforminputcontextfactory_p.h>
|
#include <qpa/qplatforminputcontextfactory_p.h>
|
||||||
|
|
||||||
|
#if QT_CONFIG(xkbcommon)
|
||||||
|
#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct wl_cursor_image;
|
struct wl_cursor_image;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -111,6 +115,10 @@ public:
|
|||||||
QWaylandDisplay(QWaylandIntegration *waylandIntegration);
|
QWaylandDisplay(QWaylandIntegration *waylandIntegration);
|
||||||
~QWaylandDisplay(void) override;
|
~QWaylandDisplay(void) override;
|
||||||
|
|
||||||
|
#if QT_CONFIG(xkbcommon)
|
||||||
|
struct xkb_context *xkbContext() const { return mXkbContext.get(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
QList<QWaylandScreen *> screens() const { return mScreens; }
|
QList<QWaylandScreen *> screens() const { return mScreens; }
|
||||||
|
|
||||||
QWaylandScreen *screenForOutput(struct wl_output *output) const;
|
QWaylandScreen *screenForOutput(struct wl_output *output) const;
|
||||||
@ -246,6 +254,10 @@ private:
|
|||||||
void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
|
void registry_global(uint32_t id, const QString &interface, uint32_t version) override;
|
||||||
void registry_global_remove(uint32_t id) override;
|
void registry_global_remove(uint32_t id) override;
|
||||||
|
|
||||||
|
#if QT_CONFIG(xkbcommon)
|
||||||
|
QXkbCommon::ScopedXKBContext mXkbContext;
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class QWaylandIntegration;
|
friend class QWaylandIntegration;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,10 +70,6 @@
|
|||||||
|
|
||||||
#include <QtGui/QGuiApplication>
|
#include <QtGui/QGuiApplication>
|
||||||
|
|
||||||
#if QT_CONFIG(xkbcommon)
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QtWaylandClient {
|
namespace QtWaylandClient {
|
||||||
@ -85,51 +81,34 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
bool QWaylandInputDevice::Keyboard::createDefaultKeyMap()
|
bool QWaylandInputDevice::Keyboard::createDefaultKeymap()
|
||||||
{
|
{
|
||||||
if (mXkbContext && mXkbMap && mXkbState) {
|
struct xkb_context *ctx = mParent->mQDisplay->xkbContext();
|
||||||
return true;
|
if (!ctx)
|
||||||
}
|
return false;
|
||||||
|
|
||||||
xkb_rule_names names;
|
struct xkb_rule_names names;
|
||||||
names.rules = strdup("evdev");
|
names.rules = "evdev";
|
||||||
names.model = strdup("pc105");
|
names.model = "pc105";
|
||||||
names.layout = strdup("us");
|
names.layout = "us";
|
||||||
names.variant = strdup("");
|
names.variant = "";
|
||||||
names.options = strdup("");
|
names.options = "";
|
||||||
|
|
||||||
mXkbContext = xkb_context_new(xkb_context_flags(0));
|
mXkbKeymap.reset(xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||||
if (mXkbContext) {
|
if (mXkbKeymap)
|
||||||
mXkbMap = xkb_map_new_from_names(mXkbContext, &names, xkb_map_compile_flags(0));
|
mXkbState.reset(xkb_state_new(mXkbKeymap.get()));
|
||||||
if (mXkbMap) {
|
|
||||||
mXkbState = xkb_state_new(mXkbMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mXkbContext || !mXkbMap || !mXkbState) {
|
if (!mXkbKeymap || !mXkbState) {
|
||||||
qWarning() << "xkb_map_new_from_names failed, no key input";
|
qCWarning(lcQpaWayland, "failed to create default keymap");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandInputDevice::Keyboard::releaseKeyMap()
|
|
||||||
{
|
|
||||||
if (mXkbState)
|
|
||||||
xkb_state_unref(mXkbState);
|
|
||||||
if (mXkbMap)
|
|
||||||
xkb_map_unref(mXkbMap);
|
|
||||||
if (mXkbContext)
|
|
||||||
xkb_context_unref(mXkbContext);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QWaylandInputDevice::Keyboard::~Keyboard()
|
QWaylandInputDevice::Keyboard::~Keyboard()
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(xkbcommon)
|
|
||||||
releaseKeyMap();
|
|
||||||
#endif
|
|
||||||
if (mFocus)
|
if (mFocus)
|
||||||
QWindowSystemInterface::handleWindowActivated(nullptr);
|
QWindowSystemInterface::handleWindowActivated(nullptr);
|
||||||
if (mParent->mVersion >= 3)
|
if (mParent->mVersion >= 3)
|
||||||
@ -501,7 +480,7 @@ Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const
|
|||||||
if (!mXkbState)
|
if (!mXkbState)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = QWaylandXkb::modifiers(mXkbState);
|
ret = QWaylandXkb::modifiers(mXkbState.get());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -761,16 +740,16 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the old keymap resources in the case they were already created in
|
mXkbKeymap.reset(xkb_keymap_new_from_string(mParent->mQDisplay->xkbContext(), map_str,
|
||||||
// the key event or when the compositor issues a new map
|
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
releaseKeyMap();
|
XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||||
|
|
||||||
mXkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
||||||
mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
||||||
munmap(map_str, size);
|
munmap(map_str, size);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
mXkbState = xkb_state_new(mXkbMap);
|
if (mXkbKeymap)
|
||||||
|
mXkbState.reset(xkb_state_new(mXkbKeymap.get()));
|
||||||
|
else
|
||||||
|
mXkbState.reset(nullptr);
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(format);
|
Q_UNUSED(format);
|
||||||
Q_UNUSED(fd);
|
Q_UNUSED(fd);
|
||||||
@ -860,11 +839,10 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
|
|||||||
mParent->mQDisplay->setLastInputDevice(mParent, serial, window);
|
mParent->mQDisplay->setLastInputDevice(mParent, serial, window);
|
||||||
|
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
if (!createDefaultKeyMap()) {
|
if ((!mXkbKeymap || !mXkbState) && !createDefaultKeymap())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code);
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState.get(), code);
|
||||||
|
|
||||||
Qt::KeyboardModifiers modifiers = mParent->modifiers();
|
Qt::KeyboardModifiers modifiers = mParent->modifiers();
|
||||||
|
|
||||||
@ -878,7 +856,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
|
|||||||
|
|
||||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
&& xkb_keymap_key_repeats(mXkbMap, code)
|
&& xkb_keymap_key_repeats(mXkbKeymap.get(), code)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
mRepeatKey = qtkey;
|
mRepeatKey = qtkey;
|
||||||
@ -952,7 +930,7 @@ void QWaylandInputDevice::Keyboard::keyboard_modifiers(uint32_t serial,
|
|||||||
Q_UNUSED(serial);
|
Q_UNUSED(serial);
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
if (mXkbState)
|
if (mXkbState)
|
||||||
xkb_state_update_mask(mXkbState,
|
xkb_state_update_mask(mXkbState.get(),
|
||||||
mods_depressed, mods_latched, mods_locked,
|
mods_depressed, mods_latched, mods_locked,
|
||||||
0, 0, group);
|
0, 0, group);
|
||||||
mNativeModifiers = mods_depressed | mods_latched | mods_locked;
|
mNativeModifiers = mods_depressed | mods_latched | mods_locked;
|
||||||
|
@ -65,8 +65,7 @@
|
|||||||
#include <QtWaylandClient/private/qwayland-wayland.h>
|
#include <QtWaylandClient/private/qwayland-wayland.h>
|
||||||
|
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
|
||||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
@ -209,11 +208,7 @@ public:
|
|||||||
|
|
||||||
QWaylandInputDevice *mParent = nullptr;
|
QWaylandInputDevice *mParent = nullptr;
|
||||||
::wl_surface *mFocus = nullptr;
|
::wl_surface *mFocus = nullptr;
|
||||||
#if QT_CONFIG(xkbcommon)
|
|
||||||
xkb_context *mXkbContext = nullptr;
|
|
||||||
xkb_keymap *mXkbMap = nullptr;
|
|
||||||
xkb_state *mXkbState = nullptr;
|
|
||||||
#endif
|
|
||||||
uint32_t mNativeModifiers = 0;
|
uint32_t mNativeModifiers = 0;
|
||||||
|
|
||||||
int mRepeatKey;
|
int mRepeatKey;
|
||||||
@ -222,9 +217,6 @@ public:
|
|||||||
int mRepeatRate = 25;
|
int mRepeatRate = 25;
|
||||||
int mRepeatDelay = 400;
|
int mRepeatDelay = 400;
|
||||||
QString mRepeatText;
|
QString mRepeatText;
|
||||||
#if QT_CONFIG(xkbcommon)
|
|
||||||
xkb_keysym_t mRepeatSym;
|
|
||||||
#endif
|
|
||||||
QTimer mRepeatTimer;
|
QTimer mRepeatTimer;
|
||||||
|
|
||||||
Qt::KeyboardModifiers modifiers() const;
|
Qt::KeyboardModifiers modifiers() const;
|
||||||
@ -236,12 +228,17 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
bool createDefaultKeyMap();
|
bool createDefaultKeymap();
|
||||||
void releaseKeyMap();
|
|
||||||
#endif
|
#endif
|
||||||
void sendKey(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
|
void sendKey(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
|
||||||
quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
|
quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
|
||||||
const QString& text = QString(), bool autorep = false, ushort count = 1);
|
const QString& text = QString(), bool autorep = false, ushort count = 1);
|
||||||
|
|
||||||
|
#if QT_CONFIG(xkbcommon)
|
||||||
|
xkb_keysym_t mRepeatSym = XKB_KEY_NoSymbol;
|
||||||
|
QXkbCommon::ScopedXKBKeymap mXkbKeymap;
|
||||||
|
QXkbCommon::ScopedXKBState mXkbState;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, public QtWayland::wl_pointer
|
class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Pointer : public QObject, public QtWayland::wl_pointer
|
||||||
|
@ -479,7 +479,7 @@ void QWaylandIntegration::reconfigureInputContext()
|
|||||||
mInputContext.reset(QPlatformInputContextFactory::create(defaultInputContext));
|
mInputContext.reset(QPlatformInputContextFactory::create(defaultInputContext));
|
||||||
|
|
||||||
#if QT_CONFIG(xkbcommon)
|
#if QT_CONFIG(xkbcommon)
|
||||||
QXkbCommon::setXkbContext(mInputContext.data(), xkb_context_new(XKB_CONTEXT_NO_FLAGS));
|
QXkbCommon::setXkbContext(mInputContext.data(), mDisplay->xkbContext());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Even if compositor-side input context handling has been requested, we fallback to
|
// Even if compositor-side input context handling has been requested, we fallback to
|
||||||
|
Loading…
x
Reference in New Issue
Block a user