Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: Icddf8720dae2cf594e16bcddab4d1cafc9d094c0
This commit is contained in:
commit
8a9f77ead1
@ -298,8 +298,6 @@ Gui, printing, widget options:
|
|||||||
-xinput2 ........... Enable XInput2 support [auto]
|
-xinput2 ........... Enable XInput2 support [auto]
|
||||||
-xkbcommon-x11 ..... Select xkbcommon used in combination with xcb
|
-xkbcommon-x11 ..... Select xkbcommon used in combination with xcb
|
||||||
[system/qt/no]
|
[system/qt/no]
|
||||||
-xkb-config-root <dir> ... With -qt-xkbcommon-x11, set default XKB config
|
|
||||||
root <dir> [detect]
|
|
||||||
-xkbcommon-evdev ... Enable X-less xkbcommon in combination with libinput
|
-xkbcommon-evdev ... Enable X-less xkbcommon in combination with libinput
|
||||||
[auto]
|
[auto]
|
||||||
|
|
||||||
|
2
src/3rdparty/xkbcommon.pri
vendored
2
src/3rdparty/xkbcommon.pri
vendored
@ -6,7 +6,7 @@ INCLUDEPATH += $$PWD/xkbcommon \
|
|||||||
|
|
||||||
include($$shadowed($$PWD/../gui/qtgui-config.pri))
|
include($$shadowed($$PWD/../gui/qtgui-config.pri))
|
||||||
|
|
||||||
DEFINES += DFLT_XKB_CONFIG_ROOT='\\"$$QMAKE_XKB_CONFIG_ROOT\\"'
|
DEFINES += DFLT_XKB_CONFIG_ROOT='\\"/usr/share/X11/xkb\\"' # unused, but needs to be set to something
|
||||||
|
|
||||||
### RMLVO names can be overwritten with environmental variables (see libxkbcommon documentation)
|
### RMLVO names can be overwritten with environmental variables (see libxkbcommon documentation)
|
||||||
DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"'
|
DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"'
|
||||||
|
@ -318,7 +318,8 @@ QJsonArray QJsonArray::fromVariantList(const QVariantList &list)
|
|||||||
array.a->tableOffset = currentOffset;
|
array.a->tableOffset = currentOffset;
|
||||||
if (!array.detach2(sizeof(QJsonPrivate::offset)*values.size()))
|
if (!array.detach2(sizeof(QJsonPrivate::offset)*values.size()))
|
||||||
return QJsonArray();
|
return QJsonArray();
|
||||||
memcpy(array.a->table(), values.constData(), values.size()*sizeof(uint));
|
memcpy(static_cast<void *>(array.a->table()),
|
||||||
|
static_cast<const void *>(values.constData()), values.size()*sizeof(uint));
|
||||||
array.a->length = values.size();
|
array.a->length = values.size();
|
||||||
array.a->size = currentOffset + sizeof(QJsonPrivate::offset)*values.size();
|
array.a->size = currentOffset + sizeof(QJsonPrivate::offset)*values.size();
|
||||||
|
|
||||||
|
@ -651,7 +651,8 @@ public:
|
|||||||
inline void reserve(int extraCapacity) {
|
inline void reserve(int extraCapacity) {
|
||||||
if (tos + extraCapacity + 1 > cap) {
|
if (tos + extraCapacity + 1 > cap) {
|
||||||
cap = qMax(tos + extraCapacity + 1, cap << 1 );
|
cap = qMax(tos + extraCapacity + 1, cap << 1 );
|
||||||
data = reinterpret_cast<T *>(realloc(data, cap * sizeof(T)));
|
void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
|
||||||
|
data = reinterpret_cast<T *>(ptr);
|
||||||
Q_CHECK_PTR(data);
|
Q_CHECK_PTR(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -46,7 +46,6 @@
|
|||||||
"xcb-xlib": "boolean",
|
"xcb-xlib": "boolean",
|
||||||
"xinput2": "boolean",
|
"xinput2": "boolean",
|
||||||
"xkb": "boolean",
|
"xkb": "boolean",
|
||||||
"xkb-config-root": "string",
|
|
||||||
"xkbcommon": { "type": "enum", "values": [ "no", "qt", "system" ] },
|
"xkbcommon": { "type": "enum", "values": [ "no", "qt", "system" ] },
|
||||||
"xkbcommon-evdev": "boolean",
|
"xkbcommon-evdev": "boolean",
|
||||||
"xkbcommon-x11": { "type": "enum", "name": "xkbcommon", "values": [ "no", "qt", "system" ] }
|
"xkbcommon-x11": { "type": "enum", "name": "xkbcommon", "values": [ "no", "qt", "system" ] }
|
||||||
@ -624,8 +623,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"testTypeAliases": {
|
"testTypeAliases": {
|
||||||
"files": [ "directX" ],
|
"files": [ "directX" ]
|
||||||
"getPkgConfigVariable": [ "xkbConfigRoot" ]
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"tests": {
|
"tests": {
|
||||||
@ -888,13 +886,6 @@
|
|||||||
"value": "/usr",
|
"value": "/usr",
|
||||||
"log": "value"
|
"log": "value"
|
||||||
},
|
},
|
||||||
"xkbconfigroot": {
|
|
||||||
"label": "XKB config root",
|
|
||||||
"type": "xkbConfigRoot",
|
|
||||||
"pkg-config-args": "xkeyboard-config",
|
|
||||||
"pkg-config-variable": "xkb_base",
|
|
||||||
"log": "value"
|
|
||||||
},
|
|
||||||
"xlib": {
|
"xlib": {
|
||||||
"label": "XLib",
|
"label": "XLib",
|
||||||
"type": "compile",
|
"type": "compile",
|
||||||
@ -1355,12 +1346,6 @@
|
|||||||
"condition": "libs.xkbcommon_x11",
|
"condition": "libs.xkbcommon_x11",
|
||||||
"output": [ "privateFeature" ]
|
"output": [ "privateFeature" ]
|
||||||
},
|
},
|
||||||
"xkb-config-root": {
|
|
||||||
"label": "XKB config root",
|
|
||||||
"emitIf": "features.xcb",
|
|
||||||
"condition": "features.xcb && !features.xkbcommon-system && tests.xkbconfigroot",
|
|
||||||
"output": [ { "type": "varAssign", "name": "QMAKE_XKB_CONFIG_ROOT", "value": "tests.xkbconfigroot.value"} ]
|
|
||||||
},
|
|
||||||
"xlib": {
|
"xlib": {
|
||||||
"label": "XLib",
|
"label": "XLib",
|
||||||
"autoDetect": "!config.darwin || features.xcb",
|
"autoDetect": "!config.darwin || features.xcb",
|
||||||
@ -1579,12 +1564,6 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
"report": [
|
"report": [
|
||||||
{
|
|
||||||
"type": "warning",
|
|
||||||
"condition": "features.xcb && !features.xkbcommon-system && !features.xkb-config-root",
|
|
||||||
"message": "Could not find XKB config root, use -xkb-config-root to set a path to
|
|
||||||
XKB configuration data. This is required for keyboard input support."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "note",
|
"type": "note",
|
||||||
"condition": "features.xcb && config.darwin",
|
"condition": "features.xcb && config.darwin",
|
||||||
|
@ -42,21 +42,6 @@ defineTest(qtConfTest_directX) {
|
|||||||
return(false)
|
return(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
defineTest(qtConfTest_xkbConfigRoot) {
|
|
||||||
qtConfTest_getPkgConfigVariable($${1}): return(true)
|
|
||||||
|
|
||||||
for (dir, $$list("/usr/share/X11/xkb", "/usr/local/share/X11/xkb")) {
|
|
||||||
exists($$dir) {
|
|
||||||
$${1}.value = $$dir
|
|
||||||
export($${1}.value)
|
|
||||||
$${1}.cache += value
|
|
||||||
export($${1}.cache)
|
|
||||||
return(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
defineTest(qtConfTest_qpaDefaultPlatform) {
|
defineTest(qtConfTest_qpaDefaultPlatform) {
|
||||||
name =
|
name =
|
||||||
!isEmpty(config.input.qpa_default_platform): name = $$config.input.qpa_default_platform
|
!isEmpty(config.input.qpa_default_platform): name = $$config.input.qpa_default_platform
|
||||||
|
@ -39,18 +39,17 @@
|
|||||||
#include "qxcbkeyboard.h"
|
#include "qxcbkeyboard.h"
|
||||||
#include "qxcbwindow.h"
|
#include "qxcbwindow.h"
|
||||||
#include "qxcbscreen.h"
|
#include "qxcbscreen.h"
|
||||||
|
#include "qxcbxkbcommon.h"
|
||||||
|
|
||||||
#include <qpa/qwindowsysteminterface.h>
|
#include <qpa/qwindowsysteminterface.h>
|
||||||
#include <qpa/qplatforminputcontext.h>
|
#include <qpa/qplatforminputcontext.h>
|
||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
#include <qpa/qplatformcursor.h>
|
#include <qpa/qplatformcursor.h>
|
||||||
|
|
||||||
#include <QtCore/QTextCodec>
|
#include <QtCore/QMetaEnum>
|
||||||
#include <QtCore/QMetaMethod>
|
|
||||||
#include <QtCore/QDir>
|
|
||||||
#include <private/qguiapplication_p.h>
|
#include <private/qguiapplication_p.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
#if QT_CONFIG(xinput2)
|
#if QT_CONFIG(xinput2)
|
||||||
@ -59,12 +58,6 @@
|
|||||||
#undef KeyRelease
|
#undef KeyRelease
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_CONFIG(xcb_xlib)
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
#undef KeyPress
|
|
||||||
#undef KeyRelease
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef XK_ISO_Left_Tab
|
#ifndef XK_ISO_Left_Tab
|
||||||
#define XK_ISO_Left_Tab 0xFE20
|
#define XK_ISO_Left_Tab 0xFE20
|
||||||
#endif
|
#endif
|
||||||
@ -706,76 +699,6 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbKeyboard::readXKBConfig()
|
|
||||||
{
|
|
||||||
clearXKBConfig();
|
|
||||||
|
|
||||||
xcb_connection_t *c = xcb_connection();
|
|
||||||
xcb_window_t rootWindow = connection()->rootWindow();
|
|
||||||
|
|
||||||
auto config_reply = Q_XCB_REPLY(xcb_get_property, c, 0, rootWindow,
|
|
||||||
atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024);
|
|
||||||
if (!config_reply) {
|
|
||||||
qWarning("Qt: Couldn't interpret the _XKB_RULES_NAMES property");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char *xkb_config = (char *)xcb_get_property_value(config_reply.get());
|
|
||||||
int length = xcb_get_property_value_length(config_reply.get());
|
|
||||||
|
|
||||||
// on old X servers xkb_config can be 0 even if config_reply indicates a succesfull read
|
|
||||||
if (!xkb_config || length == 0)
|
|
||||||
return;
|
|
||||||
// ### TODO some X servers don't set _XKB_RULES_NAMES at all, in these cases it is filled
|
|
||||||
// with gibberish, we would need to do some kind of sanity check
|
|
||||||
|
|
||||||
char *names[5] = { 0, 0, 0, 0, 0 };
|
|
||||||
char *p = xkb_config, *end = p + length;
|
|
||||||
int i = 0;
|
|
||||||
// The result from xcb_get_property_value() is not necessarily \0-terminated,
|
|
||||||
// we need to make sure that too many or missing '\0' symbols are handled safely.
|
|
||||||
do {
|
|
||||||
uint len = qstrnlen(p, length);
|
|
||||||
names[i++] = p;
|
|
||||||
p += len + 1;
|
|
||||||
length -= len + 1;
|
|
||||||
} while (p < end || i < 5);
|
|
||||||
|
|
||||||
xkb_names.rules = qstrdup(names[0]);
|
|
||||||
xkb_names.model = qstrdup(names[1]);
|
|
||||||
xkb_names.layout = qstrdup(names[2]);
|
|
||||||
xkb_names.variant = qstrdup(names[3]);
|
|
||||||
xkb_names.options = qstrdup(names[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QXcbKeyboard::clearXKBConfig()
|
|
||||||
{
|
|
||||||
if (xkb_names.rules)
|
|
||||||
delete[] xkb_names.rules;
|
|
||||||
if (xkb_names.model)
|
|
||||||
delete[] xkb_names.model;
|
|
||||||
if (xkb_names.layout)
|
|
||||||
delete[] xkb_names.layout;
|
|
||||||
if (xkb_names.variant)
|
|
||||||
delete[] xkb_names.variant;
|
|
||||||
if (xkb_names.options)
|
|
||||||
delete[] xkb_names.options;
|
|
||||||
memset(&xkb_names, 0, sizeof(xkb_names));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QXcbKeyboard::printKeymapError(const char *error) const
|
|
||||||
{
|
|
||||||
qWarning() << error;
|
|
||||||
if (xkb_context) {
|
|
||||||
qWarning("Current XKB configuration data search paths are: ");
|
|
||||||
for (unsigned int i = 0; i < xkb_context_num_include_paths(xkb_context); ++i)
|
|
||||||
qWarning() << xkb_context_include_path_get(xkb_context, i);
|
|
||||||
}
|
|
||||||
qWarning("Use QT_XKB_CONFIG_ROOT environmental variable to provide an additional search path, "
|
|
||||||
"add ':' as separator to provide several search paths and/or make sure that XKB configuration data "
|
|
||||||
"directory contains recent enough contents, to update please see http://cgit.freedesktop.org/xkeyboard-config/ .");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if QT_CONFIG(xcb_xlib)
|
|
||||||
/* Look at a pair of unshifted and shifted key symbols.
|
/* Look at a pair of unshifted and shifted key symbols.
|
||||||
* If the 'unshifted' symbol is uppercase and there is no shifted symbol,
|
* If the 'unshifted' symbol is uppercase and there is no shifted symbol,
|
||||||
* return the matching lowercase symbol; otherwise return 0.
|
* return the matching lowercase symbol; otherwise return 0.
|
||||||
@ -787,18 +710,15 @@ static xcb_keysym_t getUnshiftedXKey(xcb_keysym_t unshifted, xcb_keysym_t shifte
|
|||||||
if (shifted != XKB_KEY_NoSymbol) // Has a shifted symbol
|
if (shifted != XKB_KEY_NoSymbol) // Has a shifted symbol
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
KeySym xlower;
|
xcb_keysym_t xlower;
|
||||||
KeySym xupper;
|
xcb_keysym_t xupper;
|
||||||
/* libxkbcommon >= 0.8.0 will have public API functions providing
|
xkbcommon_XConvertCase(unshifted, &xlower, &xupper);
|
||||||
* functionality equivalent to XConvertCase(), use these once the
|
|
||||||
* minimal libxkbcommon version is high enough. After that the
|
|
||||||
* xcb-xlib dependency can be removed */
|
|
||||||
XConvertCase(static_cast<KeySym>(unshifted), &xlower, &xupper);
|
|
||||||
|
|
||||||
if (xlower != xupper // Check if symbol is cased
|
if (xlower != xupper // Check if symbol is cased
|
||||||
&& unshifted == static_cast<xcb_keysym_t>(xupper)) { // Unshifted must be upper case
|
&& unshifted == xupper) { // Unshifted must be upper case
|
||||||
return static_cast<xcb_keysym_t>(xlower);
|
return xlower;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,92 +980,55 @@ struct xkb_keymap *QXcbKeyboard::keymapFromCore()
|
|||||||
|
|
||||||
keymap += "};\n"; // xkb_keymap
|
keymap += "};\n"; // xkb_keymap
|
||||||
|
|
||||||
return xkb_keymap_new_from_buffer(xkb_context,
|
return xkb_keymap_new_from_buffer(m_xkbContext.get(),
|
||||||
keymap.constData(),
|
keymap.constData(),
|
||||||
keymap.size(),
|
keymap.size(),
|
||||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||||
static_cast<xkb_keymap_compile_flags>(0));
|
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void QXcbKeyboard::updateKeymap()
|
void QXcbKeyboard::updateKeymap()
|
||||||
{
|
{
|
||||||
m_config = true;
|
m_config = true;
|
||||||
m_keymap_is_core = false;
|
|
||||||
// set xkb context object
|
if (!m_xkbContext) {
|
||||||
if (!xkb_context) {
|
m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES));
|
||||||
if (qEnvironmentVariableIsSet("QT_XKB_CONFIG_ROOT")) {
|
if (!m_xkbContext) {
|
||||||
xkb_context = xkb_context_new((xkb_context_flags)XKB_CONTEXT_NO_DEFAULT_INCLUDES);
|
qCWarning(lcQpaKeyboard, "failed to create XKB context");
|
||||||
const QList<QByteArray> xkbRootList = QByteArray(qgetenv("QT_XKB_CONFIG_ROOT")).split(':');
|
|
||||||
for (const QByteArray &xkbRoot : xkbRootList)
|
|
||||||
xkb_context_include_path_append(xkb_context, xkbRoot.constData());
|
|
||||||
} else {
|
|
||||||
xkb_context = xkb_context_new((xkb_context_flags)0);
|
|
||||||
}
|
|
||||||
if (!xkb_context) {
|
|
||||||
printKeymapError("Qt: Failed to create XKB context!");
|
|
||||||
m_config = false;
|
m_config = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// log only critical errors, we do our own error logging from printKeymapError()
|
xkb_log_level logLevel = lcQpaKeyboard().isDebugEnabled() ?
|
||||||
xkb_context_set_log_level(xkb_context, (xkb_log_level)XKB_LOG_LEVEL_CRITICAL);
|
XKB_LOG_LEVEL_DEBUG : XKB_LOG_LEVEL_CRITICAL;
|
||||||
|
xkb_context_set_log_level(m_xkbContext.get(), logLevel);
|
||||||
}
|
}
|
||||||
// update xkb keymap object
|
|
||||||
xkb_keymap_unref(xkb_keymap);
|
|
||||||
xkb_keymap = 0;
|
|
||||||
|
|
||||||
struct xkb_state *new_state = 0;
|
|
||||||
#if QT_CONFIG(xkb)
|
#if QT_CONFIG(xkb)
|
||||||
if (connection()->hasXKB()) {
|
if (connection()->hasXKB()) {
|
||||||
xkb_keymap = xkb_x11_keymap_new_from_device(xkb_context, xcb_connection(), core_device_id, (xkb_keymap_compile_flags)0);
|
m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(),
|
||||||
if (xkb_keymap) {
|
core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS));
|
||||||
// Create a new keyboard state object for a keymap
|
if (m_xkbKeymap)
|
||||||
new_state = xkb_x11_state_new_from_device(xkb_keymap, xcb_connection(), core_device_id);
|
m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
|
||||||
}
|
} else {
|
||||||
|
#endif
|
||||||
|
m_xkbKeymap.reset(keymapFromCore());
|
||||||
|
if (m_xkbKeymap)
|
||||||
|
m_xkbState.reset(xkb_state_new(m_xkbKeymap.get()));
|
||||||
|
#if QT_CONFIG(xkb)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!xkb_keymap) {
|
|
||||||
// Read xkb RMLVO (rules, models, layouts, variants and options) names
|
|
||||||
readXKBConfig();
|
|
||||||
#if QT_CONFIG(xcb_xlib)
|
|
||||||
bool rmlvo_is_incomplete = !xkb_names.rules || !(*xkb_names.rules)
|
|
||||||
|| !xkb_names.model || !(*xkb_names.model)
|
|
||||||
|| !xkb_names.layout || !(*xkb_names.layout);
|
|
||||||
if (rmlvo_is_incomplete) {
|
|
||||||
// Try to build xkb map from core mapping information
|
|
||||||
xkb_keymap = keymapFromCore();
|
|
||||||
m_keymap_is_core = xkb_keymap != 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!xkb_keymap) {
|
|
||||||
// Compile a keymap from RMLVO
|
|
||||||
xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names,
|
|
||||||
static_cast<xkb_keymap_compile_flags> (0));
|
|
||||||
}
|
|
||||||
if (!xkb_keymap) {
|
|
||||||
// last fallback is to used hard-coded keymap name, see DEFAULT_XKB_* in xkbcommon.pri
|
|
||||||
qWarning() << "Qt: Could not determine keyboard configuration data"
|
|
||||||
" from X server, will use hard-coded keymap configuration.";
|
|
||||||
clearXKBConfig();
|
|
||||||
xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0);
|
|
||||||
}
|
|
||||||
if (xkb_keymap) {
|
|
||||||
new_state = xkb_state_new(xkb_keymap);
|
|
||||||
} else {
|
|
||||||
printKeymapError("Qt: Failed to compile a keymap!");
|
|
||||||
m_config = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (!m_xkbKeymap) {
|
||||||
if (!new_state) {
|
qCWarning(lcQpaKeyboard, "failed to compile a keymap");
|
||||||
qWarning("Qt: Failed to create xkb state!");
|
|
||||||
m_config = false;
|
m_config = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// update xkb state object
|
if (!m_xkbState) {
|
||||||
xkb_state_unref(xkb_state);
|
qCWarning(lcQpaKeyboard, "failed to create XKB state");
|
||||||
xkb_state = new_state;
|
m_config = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateXKBMods();
|
updateXKBMods();
|
||||||
|
|
||||||
checkForLatinLayout();
|
checkForLatinLayout();
|
||||||
@ -1156,7 +1039,7 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
|
|||||||
{
|
{
|
||||||
if (m_config && connection()->hasXKB()) {
|
if (m_config && connection()->hasXKB()) {
|
||||||
const xkb_state_component newState
|
const xkb_state_component newState
|
||||||
= xkb_state_update_mask(xkb_state,
|
= xkb_state_update_mask(m_xkbState.get(),
|
||||||
state->baseMods,
|
state->baseMods,
|
||||||
state->latchedMods,
|
state->latchedMods,
|
||||||
state->lockedMods,
|
state->lockedMods,
|
||||||
@ -1201,7 +1084,7 @@ void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 s
|
|||||||
void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
|
void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
|
||||||
{
|
{
|
||||||
if (m_config && !connection()->hasXKB()) {
|
if (m_config && !connection()->hasXKB()) {
|
||||||
updateXKBStateFromState(xkb_state, state);
|
updateXKBStateFromState(m_xkbState.get(), state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1211,7 +1094,7 @@ void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
|
|||||||
if (m_config && !connection()->hasXKB()) {
|
if (m_config && !connection()->hasXKB()) {
|
||||||
xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
|
xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
|
||||||
xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
|
xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
|
||||||
const xkb_state_component newState = xkb_state_update_mask(xkb_state,
|
const xkb_state_component newState = xkb_state_update_mask(m_xkbState.get(),
|
||||||
mods->base_mods,
|
mods->base_mods,
|
||||||
mods->latched_mods,
|
mods->latched_mods,
|
||||||
mods->locked_mods,
|
mods->locked_mods,
|
||||||
@ -1252,14 +1135,14 @@ quint32 QXcbKeyboard::xkbModMask(quint16 state)
|
|||||||
|
|
||||||
void QXcbKeyboard::updateXKBMods()
|
void QXcbKeyboard::updateXKBMods()
|
||||||
{
|
{
|
||||||
xkb_mods.shift = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_SHIFT);
|
xkb_mods.shift = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_SHIFT);
|
||||||
xkb_mods.lock = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_CAPS);
|
xkb_mods.lock = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_CAPS);
|
||||||
xkb_mods.control = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_CTRL);
|
xkb_mods.control = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_CTRL);
|
||||||
xkb_mods.mod1 = xkb_keymap_mod_get_index(xkb_keymap, "Mod1");
|
xkb_mods.mod1 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod1");
|
||||||
xkb_mods.mod2 = xkb_keymap_mod_get_index(xkb_keymap, "Mod2");
|
xkb_mods.mod2 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod2");
|
||||||
xkb_mods.mod3 = xkb_keymap_mod_get_index(xkb_keymap, "Mod3");
|
xkb_mods.mod3 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod3");
|
||||||
xkb_mods.mod4 = xkb_keymap_mod_get_index(xkb_keymap, "Mod4");
|
xkb_mods.mod4 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod4");
|
||||||
xkb_mods.mod5 = xkb_keymap_mod_get_index(xkb_keymap, "Mod5");
|
xkb_mods.mod5 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod5");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isLatin(xkb_keysym_t sym)
|
static bool isLatin(xkb_keysym_t sym)
|
||||||
@ -1269,11 +1152,11 @@ static bool isLatin(xkb_keysym_t sym)
|
|||||||
|
|
||||||
void QXcbKeyboard::checkForLatinLayout() const
|
void QXcbKeyboard::checkForLatinLayout() const
|
||||||
{
|
{
|
||||||
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(xkb_keymap);
|
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(m_xkbKeymap.get());
|
||||||
const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
|
const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
|
||||||
const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
|
const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
|
||||||
|
|
||||||
ScopedXKBState state(xkb_state_new(xkb_keymap));
|
ScopedXKBState state(xkb_state_new(m_xkbKeymap.get()));
|
||||||
for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
|
for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
|
||||||
xkb_state_update_mask(state.get(), 0, 0, 0, 0, 0, layout);
|
xkb_state_update_mask(state.get(), 0, 0, 0, 0, 0, layout);
|
||||||
for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
|
for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
|
||||||
@ -1299,16 +1182,16 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
|
|||||||
{
|
{
|
||||||
xkb_layout_index_t layout;
|
xkb_layout_index_t layout;
|
||||||
xkb_keysym_t sym = XKB_KEY_NoSymbol;
|
xkb_keysym_t sym = XKB_KEY_NoSymbol;
|
||||||
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(xkb_keymap, keycode);
|
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(m_xkbKeymap.get(), keycode);
|
||||||
const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(xkb_state, keycode);
|
const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(m_xkbState.get(), keycode);
|
||||||
// Look at user layouts in the order in which they are defined in system
|
// Look at user layouts in the order in which they are defined in system
|
||||||
// settings to find a latin keysym.
|
// settings to find a latin keysym.
|
||||||
for (layout = 0; layout < layoutCount; ++layout) {
|
for (layout = 0; layout < layoutCount; ++layout) {
|
||||||
if (layout == currentLayout)
|
if (layout == currentLayout)
|
||||||
continue;
|
continue;
|
||||||
const xkb_keysym_t *syms;
|
const xkb_keysym_t *syms;
|
||||||
xkb_level_index_t level = xkb_state_key_get_level(xkb_state, keycode, layout);
|
xkb_level_index_t level = xkb_state_key_get_level(m_xkbState.get(), keycode, layout);
|
||||||
if (xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms) != 1)
|
if (xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), keycode, layout, level, &syms) != 1)
|
||||||
continue;
|
continue;
|
||||||
if (isLatin(syms[0])) {
|
if (isLatin(syms[0])) {
|
||||||
sym = syms[0];
|
sym = syms[0];
|
||||||
@ -1319,8 +1202,8 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
|
|||||||
if (sym == XKB_KEY_NoSymbol)
|
if (sym == XKB_KEY_NoSymbol)
|
||||||
return sym;
|
return sym;
|
||||||
|
|
||||||
xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
|
xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
|
||||||
xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
|
xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
|
||||||
|
|
||||||
// Check for uniqueness, consider the following setup:
|
// Check for uniqueness, consider the following setup:
|
||||||
// setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
|
// setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
|
||||||
@ -1332,7 +1215,7 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
|
|||||||
// generate the same shortcut event in this case.
|
// generate the same shortcut event in this case.
|
||||||
const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
|
const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
|
||||||
const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
|
const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
|
||||||
ScopedXKBState state(xkb_state_new(xkb_keymap));
|
ScopedXKBState state(xkb_state_new(m_xkbKeymap.get()));
|
||||||
for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
|
for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
|
||||||
xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
|
xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
|
||||||
for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
|
for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
|
||||||
@ -1347,22 +1230,29 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *qtKeyName(int qtKey)
|
||||||
|
{
|
||||||
|
int keyEnumIndex = qt_getQtMetaObject()->indexOfEnumerator("Key");
|
||||||
|
QMetaEnum keyEnum = qt_getQtMetaObject()->enumerator(keyEnumIndex);
|
||||||
|
return keyEnum.valueToKey(qtKey);
|
||||||
|
}
|
||||||
|
|
||||||
QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
|
QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
|
||||||
{
|
{
|
||||||
// turn off the modifier bits which doesn't participate in shortcuts
|
// turn off the modifier bits which doesn't participate in shortcuts
|
||||||
Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
|
Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
|
||||||
Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded;
|
Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded;
|
||||||
// create a fresh kb state and test against the relevant modifier combinations
|
// create a fresh kb state and test against the relevant modifier combinations
|
||||||
struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
|
struct xkb_state *kb_state = xkb_state_new(m_xkbKeymap.get());
|
||||||
if (!kb_state) {
|
if (!kb_state) {
|
||||||
qWarning("QXcbKeyboard: failed to compile xkb keymap!");
|
qWarning("QXcbKeyboard: failed to compile xkb keymap!");
|
||||||
return QList<int>();
|
return QList<int>();
|
||||||
}
|
}
|
||||||
// get kb state from the master xkb_state and update the temporary kb_state
|
// get kb state from the master xkb_state and update the temporary kb_state
|
||||||
xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LOCKED);
|
xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(m_xkbState.get(), XKB_STATE_LAYOUT_LOCKED);
|
||||||
xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
|
xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
|
||||||
xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
|
xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
|
||||||
xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED);
|
xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_DEPRESSED);
|
||||||
|
|
||||||
xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
|
xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
|
||||||
quint32 keycode = event->nativeScanCode();
|
quint32 keycode = event->nativeScanCode();
|
||||||
@ -1384,14 +1274,14 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
QList<int> result;
|
QList<int> result;
|
||||||
int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, keycode));
|
int baseQtKey = keysymToQtKey(sym, modifiers, kb_state, keycode);
|
||||||
if (baseQtKey)
|
if (baseQtKey)
|
||||||
result += (baseQtKey + modifiers);
|
result += (baseQtKey + modifiers);
|
||||||
|
|
||||||
xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift");
|
xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Shift");
|
||||||
xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt");
|
xkb_mod_index_t altMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Alt");
|
||||||
xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control");
|
xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Control");
|
||||||
xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(xkb_keymap, "Meta");
|
xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Meta");
|
||||||
|
|
||||||
Q_ASSERT(shiftMod < 32);
|
Q_ASSERT(shiftMod < 32);
|
||||||
Q_ASSERT(altMod < 32);
|
Q_ASSERT(altMod < 32);
|
||||||
@ -1425,7 +1315,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
Qt::KeyboardModifiers mods = modifiers & ~neededMods;
|
Qt::KeyboardModifiers mods = modifiers & ~neededMods;
|
||||||
qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, keycode));
|
qtKey = keysymToQtKey(sym, mods, kb_state, keycode);
|
||||||
if (!qtKey || qtKey == baseQtKey)
|
if (!qtKey || qtKey == baseQtKey)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1446,77 +1336,88 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
|
|||||||
}
|
}
|
||||||
xkb_state_unref(kb_state);
|
xkb_state_unref(kb_state);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QXcbKeyboard::keysymToQtKey(xcb_keysym_t key) const
|
int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
|
||||||
|
struct xkb_state *state, xcb_keycode_t code) const
|
||||||
{
|
{
|
||||||
int code = 0;
|
int qtKey = 0;
|
||||||
int i = 0;
|
|
||||||
while (KeyTbl[i]) {
|
// lookup from direct mapping
|
||||||
if (key == KeyTbl[i]) {
|
if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
|
||||||
code = (int)KeyTbl[i+1];
|
// function keys
|
||||||
break;
|
qtKey = Qt::Key_F1 + (keysym - XKB_KEY_F1);
|
||||||
|
} else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
|
||||||
|
// numeric keypad keys
|
||||||
|
qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
|
||||||
|
} else if (isLatin(keysym)) {
|
||||||
|
qtKey = xkbcommon_xkb_keysym_to_upper(keysym);
|
||||||
|
} else {
|
||||||
|
// check if we have a direct mapping
|
||||||
|
int i = 0;
|
||||||
|
while (KeyTbl[i]) {
|
||||||
|
if (keysym == KeyTbl[i]) {
|
||||||
|
qtKey = KeyTbl[i + 1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString text;
|
||||||
|
bool fromUnicode = qtKey == 0;
|
||||||
|
if (fromUnicode) { // lookup from unicode
|
||||||
|
if (modifiers & Qt::ControlModifier) {
|
||||||
|
// Control modifier changes the text to ASCII control character, therefore we
|
||||||
|
// can't use this text to map keysym to a qt key. We can use the same keysym
|
||||||
|
// (it is not affectd by transformation) to obtain untransformed text. For details
|
||||||
|
// see "Appendix A. Default Symbol Transformations" in the XKB specification.
|
||||||
|
text = lookupStringNoKeysymTransformations(keysym);
|
||||||
|
} else {
|
||||||
|
text = lookupString(state, code);
|
||||||
|
}
|
||||||
|
if (!text.isEmpty()) {
|
||||||
|
if (text.unicode()->isDigit()) {
|
||||||
|
// Ensures that also non-latin digits are mapped to corresponding qt keys,
|
||||||
|
// e.g CTRL + ۲ (arabic two), is mapped to CTRL + Qt::Key_2.
|
||||||
|
qtKey = Qt::Key_0 + text.unicode()->digitValue();
|
||||||
|
} else {
|
||||||
|
qtKey = text.unicode()->toUpper().unicode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rmod_masks.meta) {
|
if (rmod_masks.meta) {
|
||||||
// translate Super/Hyper keys to Meta if we're using them as the MetaModifier
|
// translate Super/Hyper keys to Meta if we're using them as the MetaModifier
|
||||||
if (rmod_masks.meta == rmod_masks.super && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) {
|
if (rmod_masks.meta == rmod_masks.super && (qtKey == Qt::Key_Super_L
|
||||||
code = Qt::Key_Meta;
|
|| qtKey == Qt::Key_Super_R)) {
|
||||||
} else if (rmod_masks.meta == rmod_masks.hyper && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
|
qtKey = Qt::Key_Meta;
|
||||||
code = Qt::Key_Meta;
|
} else if (rmod_masks.meta == rmod_masks.hyper && (qtKey == Qt::Key_Hyper_L
|
||||||
|
|| qtKey == Qt::Key_Hyper_R)) {
|
||||||
|
qtKey = Qt::Key_Meta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
if (Q_UNLIKELY(lcQpaKeyboard().isDebugEnabled())) {
|
||||||
}
|
char keysymName[64];
|
||||||
|
xkb_keysym_get_name(keysym, keysymName, sizeof(keysymName));
|
||||||
int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) const
|
QString keysymInHex = QString(QStringLiteral("0x%1")).arg(keysym, 0, 16);
|
||||||
{
|
if (qtKeyName(qtKey)) {
|
||||||
int code = 0;
|
qCDebug(lcQpaKeyboard).nospace() << "keysym: " << keysymName << "("
|
||||||
#ifndef QT_NO_TEXTCODEC
|
<< keysymInHex << ") mapped to Qt::" << qtKeyName(qtKey) << " | text: " << text
|
||||||
QTextCodec *systemCodec = QTextCodec::codecForLocale();
|
<< " | qt key: " << qtKey << " mapped from unicode number: " << fromUnicode;
|
||||||
#endif
|
|
||||||
// Commentary in X11/keysymdef says that X codes match ASCII, so it
|
|
||||||
// is safe to use the locale functions to process X codes in ISO8859-1.
|
|
||||||
// This is mainly for compatibility - applications should not use the
|
|
||||||
// Qt keycodes between 128 and 255 (extended ACSII codes), but should
|
|
||||||
// rather use the QKeyEvent::text().
|
|
||||||
if (keysym < 128 || (keysym < 256
|
|
||||||
#ifndef QT_NO_TEXTCODEC
|
|
||||||
&& systemCodec->mibEnum() == 4
|
|
||||||
#endif
|
|
||||||
)) {
|
|
||||||
// upper-case key, if known
|
|
||||||
code = isprint((int)keysym) ? toupper((int)keysym) : 0;
|
|
||||||
} else if (keysym >= XK_F1 && keysym <= XK_F35) {
|
|
||||||
// function keys
|
|
||||||
code = Qt::Key_F1 + ((int)keysym - XK_F1);
|
|
||||||
} else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) {
|
|
||||||
if (keysym >= XK_KP_0) {
|
|
||||||
// numeric keypad keys
|
|
||||||
code = Qt::Key_0 + ((int)keysym - XK_KP_0);
|
|
||||||
} else {
|
} else {
|
||||||
code = keysymToQtKey(keysym);
|
qCDebug(lcQpaKeyboard).nospace() << "no Qt::Key for keysym: " << keysymName
|
||||||
|
<< "(" << keysymInHex << ") | text: " << text << " | qt key: " << qtKey;
|
||||||
}
|
}
|
||||||
modifiers |= Qt::KeypadModifier;
|
|
||||||
} else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
|
|
||||||
&& text.unicode()->unicode() != 0x7f
|
|
||||||
&& !(keysym >= XK_dead_grave && keysym <= XK_dead_longsolidusoverlay)) {
|
|
||||||
code = text.unicode()->toUpper().unicode();
|
|
||||||
} else {
|
|
||||||
// any other keys
|
|
||||||
code = keysymToQtKey(keysym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
return qtKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
|
QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
|
||||||
: QXcbObject(connection)
|
: QXcbObject(connection)
|
||||||
{
|
{
|
||||||
memset(&xkb_names, 0, sizeof(xkb_names));
|
|
||||||
#if QT_CONFIG(xkb)
|
#if QT_CONFIG(xkb)
|
||||||
core_device_id = 0;
|
core_device_id = 0;
|
||||||
if (connection->hasXKB()) {
|
if (connection->hasXKB()) {
|
||||||
@ -1539,12 +1440,8 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
|
|||||||
|
|
||||||
QXcbKeyboard::~QXcbKeyboard()
|
QXcbKeyboard::~QXcbKeyboard()
|
||||||
{
|
{
|
||||||
xkb_state_unref(xkb_state);
|
|
||||||
xkb_keymap_unref(xkb_keymap);
|
|
||||||
xkb_context_unref(xkb_context);
|
|
||||||
if (!connection()->hasXKB())
|
if (!connection()->hasXKB())
|
||||||
xcb_key_symbols_free(m_key_symbols);
|
xcb_key_symbols_free(m_key_symbols);
|
||||||
clearXKBConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QXcbKeyboard::updateVModMapping()
|
void QXcbKeyboard::updateVModMapping()
|
||||||
@ -1890,24 +1787,36 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
|
|||||||
// this way we allow for synthetic events to have different state
|
// this way we allow for synthetic events to have different state
|
||||||
// from the current state i.e. you can have Alt+Ctrl pressed
|
// from the current state i.e. you can have Alt+Ctrl pressed
|
||||||
// and receive a synthetic key event that has neither Alt nor Ctrl pressed
|
// and receive a synthetic key event that has neither Alt nor Ctrl pressed
|
||||||
struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
|
ScopedXKBState xkbState(xkb_state_new(m_xkbKeymap.get()));
|
||||||
if (!kb_state)
|
if (!xkbState)
|
||||||
return;
|
return;
|
||||||
updateXKBStateFromState(kb_state, state);
|
updateXKBStateFromState(xkbState.get(), state);
|
||||||
|
|
||||||
xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
|
xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState.get(), code);
|
||||||
QString string = lookupString(kb_state, code);
|
QString string = lookupString(xkbState.get(), code);
|
||||||
|
|
||||||
// Ιf control modifier is set we should prefer latin character, this is
|
|
||||||
// used for standard shortcuts in checks like "key == QKeySequence::Copy",
|
|
||||||
// users can still see the actual X11 keysym with QKeyEvent::nativeVirtualKey
|
|
||||||
Qt::KeyboardModifiers modifiers = translateModifiers(state);
|
Qt::KeyboardModifiers modifiers = translateModifiers(state);
|
||||||
xcb_keysym_t translatedSym = XKB_KEY_NoSymbol;
|
if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9)
|
||||||
if (modifiers & Qt::ControlModifier && !isLatin(sym))
|
modifiers |= Qt::KeypadModifier;
|
||||||
translatedSym = lookupLatinKeysym(code);
|
|
||||||
if (translatedSym == XKB_KEY_NoSymbol)
|
// Note 1: All standard key sequences on linux (as defined in platform theme)
|
||||||
translatedSym = sym;
|
// that use a latin character also contain a control modifier, which is why
|
||||||
int qtcode = keysymToQtKey(translatedSym, modifiers, string);
|
// checking for Qt::ControlModifier is sufficient here. It is possible to
|
||||||
|
// override QPlatformTheme::keyBindings() and provide custom sequences for
|
||||||
|
// QKeySequence::StandardKey. Custom sequences probably should respect this
|
||||||
|
// convention (alternatively, we could test against other modifiers here).
|
||||||
|
// Note 2: The possibleKeys() shorcut mechanism is not affected by this value
|
||||||
|
// adjustment and does its own thing.
|
||||||
|
xcb_keysym_t latinKeysym = XKB_KEY_NoSymbol;
|
||||||
|
if (modifiers & Qt::ControlModifier) {
|
||||||
|
// With standard shortcuts we should prefer a latin character, this is
|
||||||
|
// in checks like "event == QKeySequence::Copy".
|
||||||
|
if (!isLatin(sym))
|
||||||
|
latinKeysym = lookupLatinKeysym(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qtcode = keysymToQtKey(latinKeysym != XKB_KEY_NoSymbol ? latinKeysym : sym,
|
||||||
|
modifiers, xkbState.get(), code);
|
||||||
|
|
||||||
bool isAutoRepeat = false;
|
bool isAutoRepeat = false;
|
||||||
if (type == QEvent::KeyPress) {
|
if (type == QEvent::KeyPress) {
|
||||||
@ -1959,7 +1868,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
|
|||||||
QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
|
QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
|
||||||
code, sym, state, string, isAutoRepeat);
|
code, sym, state, string, isAutoRepeat);
|
||||||
}
|
}
|
||||||
xkb_state_unref(kb_state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
|
QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
|
||||||
@ -1973,6 +1881,17 @@ QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code)
|
|||||||
return QString::fromUtf8(chars.constData(), size);
|
return QString::fromUtf8(chars.constData(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QXcbKeyboard::lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const
|
||||||
|
{
|
||||||
|
QVarLengthArray<char, 32> chars(32);
|
||||||
|
const int size = xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
|
||||||
|
if (Q_UNLIKELY(size > chars.size())) {
|
||||||
|
chars.resize(size);
|
||||||
|
xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
|
||||||
|
}
|
||||||
|
return QString::fromUtf8(chars.constData(), size);
|
||||||
|
}
|
||||||
|
|
||||||
void QXcbKeyboard::handleKeyPressEvent(const xcb_key_press_event_t *event)
|
void QXcbKeyboard::handleKeyPressEvent(const xcb_key_press_event_t *event)
|
||||||
{
|
{
|
||||||
handleKeyEvent(event->event, QEvent::KeyPress, event->detail, event->state, event->time);
|
handleKeyEvent(event->event, QEvent::KeyPress, event->detail, event->state, event->time);
|
||||||
|
@ -88,15 +88,12 @@ protected:
|
|||||||
|
|
||||||
void resolveMaskConflicts();
|
void resolveMaskConflicts();
|
||||||
QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;
|
QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;
|
||||||
int keysymToQtKey(xcb_keysym_t keysym) const;
|
QString lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const;
|
||||||
int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) const;
|
int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
|
||||||
void printKeymapError(const char *error) const;
|
struct xkb_state *state, xcb_keycode_t code) const;
|
||||||
|
|
||||||
void readXKBConfig();
|
|
||||||
void clearXKBConfig();
|
|
||||||
#if QT_CONFIG(xcb_xlib)
|
|
||||||
struct xkb_keymap *keymapFromCore();
|
struct xkb_keymap *keymapFromCore();
|
||||||
#endif
|
|
||||||
// when XKEYBOARD not present on the X server
|
// when XKEYBOARD not present on the X server
|
||||||
void updateModifiers();
|
void updateModifiers();
|
||||||
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
|
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
|
||||||
@ -112,14 +109,8 @@ private:
|
|||||||
void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
|
void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
|
||||||
|
|
||||||
bool m_config = false;
|
bool m_config = false;
|
||||||
bool m_keymap_is_core = false;
|
|
||||||
xcb_keycode_t m_autorepeat_code = 0;
|
xcb_keycode_t m_autorepeat_code = 0;
|
||||||
|
|
||||||
struct xkb_context *xkb_context = nullptr;
|
|
||||||
struct xkb_keymap *xkb_keymap = nullptr;
|
|
||||||
struct xkb_state *xkb_state = nullptr;
|
|
||||||
struct xkb_rule_names xkb_names;
|
|
||||||
|
|
||||||
struct _mod_masks {
|
struct _mod_masks {
|
||||||
uint alt;
|
uint alt;
|
||||||
uint altgr;
|
uint altgr;
|
||||||
@ -152,7 +143,19 @@ private:
|
|||||||
struct XKBStateDeleter {
|
struct XKBStateDeleter {
|
||||||
void operator()(struct xkb_state *state) const { return xkb_state_unref(state); }
|
void operator()(struct xkb_state *state) const { return xkb_state_unref(state); }
|
||||||
};
|
};
|
||||||
|
struct XKBKeymapDeleter {
|
||||||
|
void operator()(struct xkb_keymap *keymap) const { return xkb_keymap_unref(keymap); }
|
||||||
|
};
|
||||||
|
struct XKBContextDeleter {
|
||||||
|
void operator()(struct xkb_context *context) const { return xkb_context_unref(context); }
|
||||||
|
};
|
||||||
using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>;
|
using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>;
|
||||||
|
using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>;
|
||||||
|
using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>;
|
||||||
|
|
||||||
|
ScopedXKBState m_xkbState;
|
||||||
|
ScopedXKBKeymap m_xkbKeymap;
|
||||||
|
ScopedXKBContext m_xkbContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
233
src/plugins/platforms/xcb/qxcbxkbcommon.h
Normal file
233
src/plugins/platforms/xcb/qxcbxkbcommon.h
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the plugins of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 3 requirements
|
||||||
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 2.0 or (at your option) the GNU General
|
||||||
|
** Public license version 3 or any later version approved by the KDE Free
|
||||||
|
** Qt Foundation. The licenses are as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||||
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* XConvertCase was copied from src/3rdparty/xkbcommon/src/keysym.c,
|
||||||
|
which contains the following license information:
|
||||||
|
|
||||||
|
Copyright 1985, 1987, 1990, 1998 The Open Group
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the names of the authors or their
|
||||||
|
institutions shall not be used in advertising or otherwise to promote the
|
||||||
|
sale, use or other dealings in this Software without prior written
|
||||||
|
authorization from the authors.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Copyright © 2009 Dan Nicholson
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice (including the next
|
||||||
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following code modifications were applied:
|
||||||
|
|
||||||
|
XConvertCase() was renamed to xkbcommon_XConvertCase(), to not confuse it
|
||||||
|
with Xlib's XConvertCase().
|
||||||
|
|
||||||
|
UCSConvertCase() was renamed to qt_UCSConvertCase() and function's body was
|
||||||
|
replaced to use Qt APIs for doing case conversion, which should give us better
|
||||||
|
results instead of using the less complete version from keysym.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <QtCore/QChar>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
static void qt_UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
|
||||||
|
{
|
||||||
|
*lower = QChar::toLower(code);
|
||||||
|
*upper = QChar::toUpper(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
|
||||||
|
{
|
||||||
|
/* Latin 1 keysym */
|
||||||
|
if (sym < 0x100) {
|
||||||
|
qt_UCSConvertCase(sym, lower, upper);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unicode keysym */
|
||||||
|
if ((sym & 0xff000000) == 0x01000000) {
|
||||||
|
qt_UCSConvertCase((sym & 0x00ffffff), lower, upper);
|
||||||
|
*upper |= 0x01000000;
|
||||||
|
*lower |= 0x01000000;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Legacy keysym */
|
||||||
|
|
||||||
|
*lower = sym;
|
||||||
|
*upper = sym;
|
||||||
|
|
||||||
|
switch (sym >> 8) {
|
||||||
|
case 1: /* Latin 2 */
|
||||||
|
/* Assume the KeySym is a legal value (ignore discontinuities) */
|
||||||
|
if (sym == XKB_KEY_Aogonek)
|
||||||
|
*lower = XKB_KEY_aogonek;
|
||||||
|
else if (sym >= XKB_KEY_Lstroke && sym <= XKB_KEY_Sacute)
|
||||||
|
*lower += (XKB_KEY_lstroke - XKB_KEY_Lstroke);
|
||||||
|
else if (sym >= XKB_KEY_Scaron && sym <= XKB_KEY_Zacute)
|
||||||
|
*lower += (XKB_KEY_scaron - XKB_KEY_Scaron);
|
||||||
|
else if (sym >= XKB_KEY_Zcaron && sym <= XKB_KEY_Zabovedot)
|
||||||
|
*lower += (XKB_KEY_zcaron - XKB_KEY_Zcaron);
|
||||||
|
else if (sym == XKB_KEY_aogonek)
|
||||||
|
*upper = XKB_KEY_Aogonek;
|
||||||
|
else if (sym >= XKB_KEY_lstroke && sym <= XKB_KEY_sacute)
|
||||||
|
*upper -= (XKB_KEY_lstroke - XKB_KEY_Lstroke);
|
||||||
|
else if (sym >= XKB_KEY_scaron && sym <= XKB_KEY_zacute)
|
||||||
|
*upper -= (XKB_KEY_scaron - XKB_KEY_Scaron);
|
||||||
|
else if (sym >= XKB_KEY_zcaron && sym <= XKB_KEY_zabovedot)
|
||||||
|
*upper -= (XKB_KEY_zcaron - XKB_KEY_Zcaron);
|
||||||
|
else if (sym >= XKB_KEY_Racute && sym <= XKB_KEY_Tcedilla)
|
||||||
|
*lower += (XKB_KEY_racute - XKB_KEY_Racute);
|
||||||
|
else if (sym >= XKB_KEY_racute && sym <= XKB_KEY_tcedilla)
|
||||||
|
*upper -= (XKB_KEY_racute - XKB_KEY_Racute);
|
||||||
|
break;
|
||||||
|
case 2: /* Latin 3 */
|
||||||
|
/* Assume the KeySym is a legal value (ignore discontinuities) */
|
||||||
|
if (sym >= XKB_KEY_Hstroke && sym <= XKB_KEY_Hcircumflex)
|
||||||
|
*lower += (XKB_KEY_hstroke - XKB_KEY_Hstroke);
|
||||||
|
else if (sym >= XKB_KEY_Gbreve && sym <= XKB_KEY_Jcircumflex)
|
||||||
|
*lower += (XKB_KEY_gbreve - XKB_KEY_Gbreve);
|
||||||
|
else if (sym >= XKB_KEY_hstroke && sym <= XKB_KEY_hcircumflex)
|
||||||
|
*upper -= (XKB_KEY_hstroke - XKB_KEY_Hstroke);
|
||||||
|
else if (sym >= XKB_KEY_gbreve && sym <= XKB_KEY_jcircumflex)
|
||||||
|
*upper -= (XKB_KEY_gbreve - XKB_KEY_Gbreve);
|
||||||
|
else if (sym >= XKB_KEY_Cabovedot && sym <= XKB_KEY_Scircumflex)
|
||||||
|
*lower += (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
|
||||||
|
else if (sym >= XKB_KEY_cabovedot && sym <= XKB_KEY_scircumflex)
|
||||||
|
*upper -= (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
|
||||||
|
break;
|
||||||
|
case 3: /* Latin 4 */
|
||||||
|
/* Assume the KeySym is a legal value (ignore discontinuities) */
|
||||||
|
if (sym >= XKB_KEY_Rcedilla && sym <= XKB_KEY_Tslash)
|
||||||
|
*lower += (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
|
||||||
|
else if (sym >= XKB_KEY_rcedilla && sym <= XKB_KEY_tslash)
|
||||||
|
*upper -= (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
|
||||||
|
else if (sym == XKB_KEY_ENG)
|
||||||
|
*lower = XKB_KEY_eng;
|
||||||
|
else if (sym == XKB_KEY_eng)
|
||||||
|
*upper = XKB_KEY_ENG;
|
||||||
|
else if (sym >= XKB_KEY_Amacron && sym <= XKB_KEY_Umacron)
|
||||||
|
*lower += (XKB_KEY_amacron - XKB_KEY_Amacron);
|
||||||
|
else if (sym >= XKB_KEY_amacron && sym <= XKB_KEY_umacron)
|
||||||
|
*upper -= (XKB_KEY_amacron - XKB_KEY_Amacron);
|
||||||
|
break;
|
||||||
|
case 6: /* Cyrillic */
|
||||||
|
/* Assume the KeySym is a legal value (ignore discontinuities) */
|
||||||
|
if (sym >= XKB_KEY_Serbian_DJE && sym <= XKB_KEY_Serbian_DZE)
|
||||||
|
*lower -= (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
|
||||||
|
else if (sym >= XKB_KEY_Serbian_dje && sym <= XKB_KEY_Serbian_dze)
|
||||||
|
*upper += (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
|
||||||
|
else if (sym >= XKB_KEY_Cyrillic_YU && sym <= XKB_KEY_Cyrillic_HARDSIGN)
|
||||||
|
*lower -= (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
|
||||||
|
else if (sym >= XKB_KEY_Cyrillic_yu && sym <= XKB_KEY_Cyrillic_hardsign)
|
||||||
|
*upper += (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
|
||||||
|
break;
|
||||||
|
case 7: /* Greek */
|
||||||
|
/* Assume the KeySym is a legal value (ignore discontinuities) */
|
||||||
|
if (sym >= XKB_KEY_Greek_ALPHAaccent && sym <= XKB_KEY_Greek_OMEGAaccent)
|
||||||
|
*lower += (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
|
||||||
|
else if (sym >= XKB_KEY_Greek_alphaaccent && sym <= XKB_KEY_Greek_omegaaccent &&
|
||||||
|
sym != XKB_KEY_Greek_iotaaccentdieresis &&
|
||||||
|
sym != XKB_KEY_Greek_upsilonaccentdieresis)
|
||||||
|
*upper -= (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
|
||||||
|
else if (sym >= XKB_KEY_Greek_ALPHA && sym <= XKB_KEY_Greek_OMEGA)
|
||||||
|
*lower += (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
|
||||||
|
else if (sym >= XKB_KEY_Greek_alpha && sym <= XKB_KEY_Greek_omega &&
|
||||||
|
sym != XKB_KEY_Greek_finalsmallsigma)
|
||||||
|
*upper -= (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
|
||||||
|
break;
|
||||||
|
case 0x13: /* Latin 9 */
|
||||||
|
if (sym == XKB_KEY_OE)
|
||||||
|
*lower = XKB_KEY_oe;
|
||||||
|
else if (sym == XKB_KEY_oe)
|
||||||
|
*upper = XKB_KEY_OE;
|
||||||
|
else if (sym == XKB_KEY_Ydiaeresis)
|
||||||
|
*lower = XKB_KEY_ydiaeresis;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xkb_keysym_t xkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks)
|
||||||
|
{
|
||||||
|
xkb_keysym_t lower, upper;
|
||||||
|
|
||||||
|
xkbcommon_XConvertCase(ks, &lower, &upper);
|
||||||
|
|
||||||
|
return upper;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
@ -46,7 +46,8 @@ HEADERS = \
|
|||||||
qxcbcursor.h \
|
qxcbcursor.h \
|
||||||
qxcbimage.h \
|
qxcbimage.h \
|
||||||
qxcbxsettings.h \
|
qxcbxsettings.h \
|
||||||
qxcbsystemtraytracker.h
|
qxcbsystemtraytracker.h \
|
||||||
|
qxcbxkbcommon.h
|
||||||
|
|
||||||
load(qt_build_paths)
|
load(qt_build_paths)
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ Q_STATIC_ASSERT(!!1);
|
|||||||
static thread_local int gt_var;
|
static thread_local int gt_var;
|
||||||
void thread_local_test()
|
void thread_local_test()
|
||||||
{
|
{
|
||||||
thread_local int t_var;
|
static thread_local int t_var;
|
||||||
t_var = gt_var;
|
t_var = gt_var;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user