summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-02-24 21:29:47 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-02-24 21:29:47 +0100
commit8a9f77ead179ce88df5113290fa0201872fcd74e (patch)
tree3abf6515ebba2412dc9a36a84d95a9870915e4b2
parentefb46ea7ccf6fe8f89a8228bb5afe34c51901824 (diff)
parent9df6f3367e971d4fad63e59bb42615e2b7a580ce (diff)
Merge remote-tracking branch 'origin/5.11' into dev
-rw-r--r--config_help.txt2
-rw-r--r--src/3rdparty/xkbcommon.pri2
-rw-r--r--src/corelib/serialization/qjsonarray.cpp3
-rw-r--r--src/corelib/serialization/qxmlstream_p.h3
-rw-r--r--src/corelib/xml/qxmlstream_p.h1966
-rw-r--r--src/gui/configure.json23
-rw-r--r--src/gui/configure.pri15
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp433
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h29
-rw-r--r--src/plugins/platforms/xcb/qxcbxkbcommon.h233
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro3
-rw-r--r--tests/auto/corelib/global/qglobal/qglobal.c2
12 files changed, 434 insertions, 2280 deletions
diff --git a/config_help.txt b/config_help.txt
index f61601ec7a..3e2c0c61b0 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -298,8 +298,6 @@ Gui, printing, widget options:
-xinput2 ........... Enable XInput2 support [auto]
-xkbcommon-x11 ..... Select xkbcommon used in combination with xcb
[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
[auto]
diff --git a/src/3rdparty/xkbcommon.pri b/src/3rdparty/xkbcommon.pri
index af71b232d5..1d953d8372 100644
--- a/src/3rdparty/xkbcommon.pri
+++ b/src/3rdparty/xkbcommon.pri
@@ -6,7 +6,7 @@ INCLUDEPATH += $$PWD/xkbcommon \
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)
DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"'
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index c5a5aaf39d..8ee9ce0de7 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -318,7 +318,8 @@ QJsonArray QJsonArray::fromVariantList(const QVariantList &list)
array.a->tableOffset = currentOffset;
if (!array.detach2(sizeof(QJsonPrivate::offset)*values.size()))
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->size = currentOffset + sizeof(QJsonPrivate::offset)*values.size();
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index 5645d812eb..4157fbbd0e 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -651,7 +651,8 @@ public:
inline void reserve(int extraCapacity) {
if (tos + extraCapacity + 1 > cap) {
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);
}
}
diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h
deleted file mode 100644
index e6c89e40cd..0000000000
--- a/src/corelib/xml/qxmlstream_p.h
+++ /dev/null
@@ -1,1966 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module 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$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/private/qglobal_p.h>
-
-// This file was generated by qlalr - DO NOT EDIT!
-#ifndef QXMLSTREAM_P_H
-#define QXMLSTREAM_P_H
-
-#if defined(ERROR)
-# undef ERROR
-#endif
-
-class QXmlStreamReader_Table
-{
-public:
- enum VariousConstants {
- EOF_SYMBOL = 0,
- AMPERSAND = 5,
- ANY = 41,
- ATTLIST = 31,
- BANG = 25,
- CDATA = 47,
- CDATA_START = 28,
- COLON = 17,
- COMMA = 19,
- DASH = 20,
- DBLQUOTE = 8,
- DIGIT = 27,
- DOCTYPE = 29,
- DOT = 23,
- ELEMENT = 30,
- EMPTY = 40,
- ENTITIES = 51,
- ENTITY = 32,
- ENTITY_DONE = 45,
- EQ = 14,
- ERROR = 43,
- FIXED = 39,
- HASH = 6,
- ID = 48,
- IDREF = 49,
- IDREFS = 50,
- IMPLIED = 38,
- LANGLE = 3,
- LBRACK = 9,
- LETTER = 26,
- LPAREN = 11,
- NDATA = 36,
- NMTOKEN = 52,
- NMTOKENS = 53,
- NOTATION = 33,
- NOTOKEN = 1,
- PARSE_ENTITY = 44,
- PCDATA = 42,
- PERCENT = 15,
- PIPE = 13,
- PLUS = 21,
- PUBLIC = 35,
- QUESTIONMARK = 24,
- QUOTE = 7,
- RANGLE = 4,
- RBRACK = 10,
- REQUIRED = 37,
- RPAREN = 12,
- SEMICOLON = 18,
- SHIFT_THERE = 56,
- SLASH = 16,
- SPACE = 2,
- STAR = 22,
- SYSTEM = 34,
- UNRESOLVED_ENTITY = 46,
- VERSION = 55,
- XML = 54,
-
- ACCEPT_STATE = 416,
- RULE_COUNT = 270,
- STATE_COUNT = 427,
- TERMINAL_COUNT = 57,
- NON_TERMINAL_COUNT = 84,
-
- GOTO_INDEX_OFFSET = 427,
- GOTO_INFO_OFFSET = 1017,
- GOTO_CHECK_OFFSET = 1017
- };
-
- static const char *const spell [];
- static const short lhs [];
- static const short rhs [];
- static const short goto_default [];
- static const short action_default [];
- static const short action_index [];
- static const short action_info [];
- static const short action_check [];
-
- static inline int nt_action (int state, int nt)
- {
- const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
- if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
- return goto_default [nt];
-
- return action_info [GOTO_INFO_OFFSET + yyn];
- }
-
- static inline int t_action (int state, int token)
- {
- const int yyn = action_index [state] + token;
-
- if (yyn < 0 || action_check [yyn] != token)
- return - action_default [state];
-
- return action_info [yyn];
- }
-};
-
-
-const char *const QXmlStreamReader_Table::spell [] = {
- "end of file", 0, " ", "<", ">", "&", "#", "\'", "\"", "[",
- "]", "(", ")", "|", "=", "%", "/", ":", ";", ",",
- "-", "+", "*", ".", "?", "!", "[a-zA-Z]", "[0-9]", "[CDATA[", "DOCTYPE",
- "ELEMENT", "ATTLIST", "ENTITY", "NOTATION", "SYSTEM", "PUBLIC", "NDATA", "REQUIRED", "IMPLIED", "FIXED",
- "EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF",
- "IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", 0};
-
-const short QXmlStreamReader_Table::lhs [] = {
- 57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
- 67, 68, 64, 72, 72, 72, 75, 66, 66, 66,
- 66, 79, 78, 80, 80, 80, 80, 80, 80, 80,
- 81, 81, 81, 81, 81, 81, 81, 87, 83, 88,
- 88, 88, 88, 91, 92, 93, 93, 93, 93, 94,
- 94, 96, 96, 96, 97, 97, 98, 98, 99, 99,
- 100, 100, 89, 89, 95, 90, 101, 101, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 104, 105,
- 105, 105, 105, 107, 108, 109, 109, 84, 84, 110,
- 110, 112, 112, 85, 85, 85, 65, 65, 76, 114,
- 63, 115, 116, 86, 86, 86, 117, 117, 117, 117,
- 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
- 117, 117, 117, 117, 117, 117, 117, 117, 117, 118,
- 118, 119, 119, 119, 119, 119, 119, 119, 119, 122,
- 70, 70, 70, 70, 123, 124, 123, 124, 123, 124,
- 123, 124, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 125, 73, 113, 113, 113, 113,
- 127, 128, 127, 128, 127, 128, 127, 128, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 106, 106, 106, 106, 131, 132, 131,
- 132, 131, 131, 132, 132, 133, 133, 133, 133, 135,
- 71, 71, 71, 136, 136, 137, 62, 60, 61, 138,
- 121, 82, 130, 134, 120, 139, 139, 139, 139, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 74,
- 69, 69, 77, 111, 102, 102, 102, 102, 102, 140};
-
-const short QXmlStreamReader_Table::rhs [] = {
- 2, 1, 4, 2, 2, 2, 2, 2, 2, 0,
- 1, 1, 9, 2, 4, 0, 4, 4, 6, 6,
- 4, 1, 3, 1, 1, 1, 2, 2, 2, 0,
- 1, 1, 1, 1, 1, 1, 1, 4, 4, 1,
- 1, 1, 1, 1, 2, 1, 1, 1, 0, 2,
- 2, 2, 6, 6, 1, 5, 1, 5, 3, 5,
- 0, 1, 6, 8, 4, 2, 1, 5, 1, 1,
- 1, 1, 1, 1, 1, 1, 6, 7, 1, 2,
- 2, 1, 4, 3, 3, 1, 2, 5, 6, 4,
- 6, 3, 5, 5, 3, 4, 4, 5, 2, 3,
- 2, 2, 4, 5, 5, 7, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
- 2, 2, 3, 3, 2, 2, 2, 2, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 2, 2, 3, 3,
- 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 2, 2, 3, 3, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 5,
- 0, 1, 3, 1, 3, 2, 4, 3, 5, 1,
- 3, 3, 3, 3, 4, 1, 1, 2, 2, 2,
- 4, 2, 2, 2, 2, 2, 2, 2, 0, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 2};
-
-const short QXmlStreamReader_Table::action_default [] = {
- 10, 259, 0, 2, 1, 0, 125, 117, 119, 120,
- 127, 129, 123, 11, 114, 108, 0, 109, 128, 111,
- 115, 113, 121, 124, 126, 107, 110, 112, 118, 116,
- 131, 122, 240, 12, 254, 136, 250, 253, 0, 130,
- 140, 257, 16, 252, 138, 137, 0, 256, 139, 259,
- 231, 258, 255, 0, 0, 264, 0, 247, 246, 0,
- 249, 248, 245, 241, 99, 263, 0, 236, 0, 0,
- 260, 97, 98, 101, 0, 132, 134, 133, 135, 0,
- 0, 261, 0, 0, 176, 0, 173, 165, 167, 168,
- 142, 154, 171, 162, 156, 157, 153, 159, 163, 161,
- 169, 172, 152, 155, 158, 160, 166, 164, 174, 170,
- 150, 175, 0, 144, 148, 146, 151, 141, 149, 0,
- 147, 143, 145, 0, 15, 14, 262, 0, 22, 21,
- 261, 30, 0, 20, 0, 0, 32, 37, 31, 0,
- 33, 261, 0, 34, 0, 24, 0, 35, 0, 26,
- 36, 25, 0, 242, 41, 40, 261, 43, 49, 261,
- 42, 0, 44, 261, 49, 261, 0, 261, 0, 49,
- 0, 48, 46, 47, 51, 52, 261, 261, 0, 57,
- 261, 54, 261, 0, 58, 0, 55, 261, 53, 261,
- 0, 56, 65, 0, 261, 61, 261, 0, 59, 62,
- 63, 0, 261, 0, 0, 60, 64, 45, 50, 66,
- 0, 39, 0, 0, 261, 0, 94, 95, 0, 0,
- 0, 0, 261, 0, 210, 201, 203, 205, 178, 190,
- 208, 199, 193, 191, 194, 189, 196, 198, 206, 209,
- 188, 192, 195, 197, 202, 200, 204, 207, 211, 213,
- 212, 186, 0, 0, 243, 180, 184, 182, 0, 0,
- 93, 187, 177, 185, 0, 183, 179, 181, 92, 0,
- 96, 0, 0, 0, 0, 0, 261, 86, 261, 0,
- 262, 0, 87, 0, 89, 69, 74, 73, 70, 71,
- 72, 261, 75, 76, 0, 0, 0, 269, 268, 266,
- 267, 265, 67, 261, 0, 261, 0, 0, 68, 77,
- 261, 0, 261, 0, 0, 78, 0, 79, 0, 82,
- 85, 0, 0, 215, 225, 224, 0, 227, 229, 228,
- 226, 0, 244, 217, 221, 219, 223, 214, 222, 0,
- 220, 216, 218, 0, 81, 80, 0, 83, 0, 84,
- 88, 100, 0, 38, 0, 0, 0, 0, 91, 90,
- 0, 103, 23, 27, 29, 28, 0, 0, 261, 262,
- 0, 261, 0, 106, 105, 261, 0, 104, 102, 0,
- 0, 18, 261, 17, 0, 19, 0, 0, 251, 0,
- 261, 0, 239, 0, 232, 238, 0, 237, 234, 261,
- 261, 262, 233, 235, 0, 261, 0, 230, 261, 0,
- 261, 0, 231, 0, 0, 13, 270, 9, 5, 8,
- 4, 0, 7, 259, 6, 0, 3};
-
-const short QXmlStreamReader_Table::goto_default [] = {
- 2, 4, 3, 49, 388, 43, 37, 52, 47, 41,
- 249, 53, 127, 84, 393, 81, 85, 126, 42, 46,
- 169, 130, 131, 146, 145, 149, 138, 136, 140, 147,
- 139, 159, 160, 157, 168, 167, 209, 165, 164, 166,
- 187, 180, 196, 200, 303, 302, 295, 321, 320, 319,
- 279, 277, 278, 142, 56, 141, 222, 38, 34, 148,
- 39, 48, 40, 248, 45, 36, 119, 112, 330, 111,
- 264, 252, 251, 250, 339, 326, 325, 329, 398, 399,
- 50, 51, 59, 0};
-
-const short QXmlStreamReader_Table::action_index [] = {
- -21, -57, 33, 119, 960, 70, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, 105, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, 40, -57,
- 795, -57, 47, -57, -57, -57, 107, -57, -57, -57,
- 84, -57, -57, -38, 80, -57, 12, -57, -57, 97,
- -57, -57, -57, -57, -57, -57, 13, -57, 56, 34,
- -57, -57, -57, -57, 51, -57, -57, -57, -57, 53,
- 57, 84, 300, 255, -57, 84, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, 355, -57, -57, -57, -57, -57, -57, 326,
- -57, -57, -57, 48, -57, -57, -57, 50, -57, -57,
- 84, 155, 32, -57, 38, 22, -57, -57, -57, 115,
- -57, 35, 156, -57, 173, -57, 245, -57, 44, -57,
- -57, -57, 16, -57, -57, -57, 29, -57, 116, 29,
- -57, 133, -57, 29, 129, 84, 15, 29, -22, 121,
- 74, -57, -57, -57, -57, 82, 29, 29, 88, -57,
- 29, 7, 29, 86, -57, 83, -57, 27, 19, 26,
- 94, -57, -57, 106, 29, 3, 29, -8, -57, -57,
- -57, 104, 29, -6, -7, -57, -57, -57, -57, -57,
- 17, -57, -2, 11, 29, 18, -57, -57, 850, 65,
- 465, 67, 84, 135, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -57, 630, 24, -57, -57, -57, -57, 84, 76,
- -57, -57, -57, -57, 740, -57, -57, -57, -57, 39,
- -57, 23, 21, 14, 78, 22, 84, -57, 84, 184,
- 20, 31, -57, 41, -57, -57, -57, -57, -57, -57,
- -57, 84, -57, -57, 36, 126, 162, -57, -57, -57,
- -57, -57, -57, 29, 79, 29, 29, 160, -57, -57,
- 29, 145, 29, 75, 29, -57, 575, -57, 410, -57,
- -57, 110, 64, -57, -57, -57, 685, -57, -57, -57,
- -57, -17, -57, -57, -57, -57, -57, -57, -57, 520,
- -57, -57, -57, 29, -57, -57, 61, -57, 29, -57,
- -57, -57, 29, -57, 29, 29, -15, 29, -57, -57,
- 29, -57, -57, -57, -57, -57, 95, 43, 29, 45,
- 9, 29, 10, -57, -57, 29, 2, -57, -57, -24,
- 190, -57, 29, -57, 1, -57, 905, 150, -57, -26,
- 29, 0, -57, 109, -26, -57, 8, -57, -57, 29,
- 29, -19, -57, -57, -11, 29, 59, -57, 29, -5,
- 29, 103, 29, -16, 6, -57, -57, -57, -57, -57,
- -57, 69, -57, -57, -57, 905, -57,
-
- -84, -84, -84, 204, 75, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, 7, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- 101, -84, -84, -84, -84, -84, -84, -84, -84, 64,
- 54, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, 68, -84, 30, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- 32, -84, -16, -7, -84, 42, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, 45, -84, -84, -84, -84, -84, -84, 44,
- -84, -84, -84, 33, -84, -84, -84, -84, -84, -84,
- 36, 108, -84, -84, -84, 69, -84, -84, -84, 62,
- -84, 63, -84, -84, -84, -84, 118, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -2, -84, -84, -10,
- -84, -84, -84, 25, -21, 11, -84, 20, -84, -25,
- -84, -84, -84, -84, -84, -84, 1, 2, -36, -84,
- -9, -84, 5, -13, -84, -8, -84, 6, -84, 8,
- 12, -84, -84, -84, 23, -84, 4, -1, -84, -84,
- -84, -84, 0, -84, -14, -84, -84, -84, -84, -84,
- -84, -84, 55, -84, 58, -84, -84, -84, -84, 53,
- 47, 123, 67, 66, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -15, -84, -84, -84, -84, -84, 41, 40,
- -84, -84, -84, -84, -46, -84, -84, -84, -84, -84,
- -84, 35, -84, 34, 37, 18, 70, -84, 89, -84,
- 43, -84, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, 48, -84, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, 31, -84, 29, 27, 17, -84, -84,
- 38, 24, 39, -84, 49, -84, 71, -84, 93, -84,
- -84, -84, -12, -84, -84, -84, 94, -84, -84, -84,
- -84, -84, -84, -84, -84, -84, -84, -84, -84, 78,
- -84, -84, -84, 50, -84, -84, 46, -84, 56, -84,
- -84, -84, 60, -84, 61, 59, 51, 57, -84, -84,
- 14, -84, -84, -84, -84, -84, -11, -6, 72, -5,
- -84, -3, -84, -84, -84, 52, -84, -84, -84, -20,
- 77, -84, 21, -84, -84, -84, 76, 16, -84, 19,
- 26, -84, -84, -84, 10, -84, -84, -84, -84, 80,
- 13, 73, -84, -84, -84, 22, -27, -84, 9, -84,
- 28, 15, 82, -84, -84, -84, -84, -84, -84, -84,
- -84, -84, -84, 3, -84, 98, -84};
-
-const short QXmlStreamReader_Table::action_info [] = {
- 65, 332, 65, 405, 392, 385, 377, 65, 414, 410,
- 415, 55, 397, 374, 373, 217, 206, 408, 65, 65,
- 207, 211, 216, 1, 55, 199, 182, 192, 70, 70,
- 63, 70, 189, 416, 153, 350, 133, 70, 72, 55,
- 65, 351, 254, 270, 73, 284, 65, 310, 55, 65,
- 83, 82, 83, 82, 129, 83, 82, 54, 70, 128,
- 83, 82, 66, 64, 83, 82, 318, 316, 318, 316,
- 54, 212, 83, 82, 83, 82, 54, 55, 367, 366,
- 69, 80, 79, 83, 82, 163, 70, 314, 305, 272,
- 55, 306, 305, 354, 163, 177, 55, 163, 379, 163,
- 65, 176, 83, 82, 55, 163, 58, 57, 0, 65,
- 83, 82, 65, 395, 65, 62, 203, 202, 195, 194,
- 65, 417, 16, 61, 60, 396, 156, 272, 0, 66,
- 64, 65, 317, 318, 316, 378, 379, 171, 173, 162,
- 172, 54, 171, 173, 163, 172, 0, 345, 344, 343,
- 171, 173, 0, 172, 0, 155, 154, 70, 134, 65,
- 0, 55, 297, 220, 218, 298, 389, 0, 300, 0,
- 135, 301, 299, 33, 66, 64, 65, 297, 0, 297,
- 298, 0, 298, 300, 0, 300, 301, 299, 301, 299,
- 221, 219, 70, 272, 381, 291, 0, 0, 0, 128,
- 13, 0, 0, 273, 271, 274, 275, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 287, 294, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 285, 288, 289, 290, 286, 292, 293, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 70, 134, 0,
- 0, 0, 0, 0, 0, 362, 0, 108, 0, 103,
- 135, 94, 117, 116, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 0, 94, 102, 90, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 108, 0,
- 103, 0, 94, 121, 120, 95, 104, 97, 105, 99,
- 93, 98, 107, 87, 106, 88, 89, 100, 109, 92,
- 101, 86, 96, 91, 0, 0, 0, 108, 0, 103,
- 0, 94, 114, 113, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 322, 94, 337, 336, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 246, 233, 241,
- 223, 232, 262, 261, 234, 242, 236, 243, 237, 231,
- 0, 245, 225, 244, 226, 227, 238, 247, 230, 239,
- 224, 235, 229, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 108, 0, 103, 322, 94, 341, 340, 95,
- 104, 97, 105, 99, 93, 98, 107, 87, 106, 88,
- 89, 100, 109, 92, 101, 86, 96, 91, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 108, 0, 103,
- 322, 94, 324, 323, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 256, 255, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 108, 0, 103,
- 322, 94, 334, 333, 95, 104, 97, 105, 99, 93,
- 98, 107, 87, 106, 88, 89, 100, 109, 92, 101,
- 86, 96, 91, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 266, 265, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 30, 0, 25,
- 74, 15, 24, 10, 17, 26, 19, 27, 21, 14,
- 20, 29, 7, 28, 8, 9, 22, 31, 12, 23,
- 6, 18, 11, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 246, 233, 241, 223, 232, 240, 228, 234,
- 242, 236, 243, 237, 231, 0, 245, 225, 244, 226,
- 227, 238, 247, 230, 239, 224, 235, 229, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 30, 387, 25,
- 5, 15, 24, 10, 17, 26, 19, 27, 21, 14,
- 20, 29, 7, 28, 8, 9, 22, 31, 12, 23,
- 6, 18, 11, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 13, 32, 0, 0, 0, 0, 0, 0, 0, 33,
- 0, 0, 30, 16, 25, 5, 15, 24, 10, 17,
- 26, 19, 27, 21, 14, 20, 29, 7, 28, 8,
- 9, 22, 31, 12, 23, 6, 18, 11, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 13, 32, 0, 0, 0,
- 0, 0, 0, 0, 33, 0, 0,
-
- 380, 179, 210, 181, 425, 368, 205, 375, 371, 372,
- 161, 208, 204, 178, 185, 174, 201, 183, 188, 198,
- 190, 409, 407, 175, 184, 404, 267, 67, 412, 186,
- 400, 361, 193, 384, 406, 197, 67, 170, 391, 390,
- 411, 307, 331, 304, 309, 125, 124, 71, 132, 191,
- 311, 313, 110, 260, 352, 276, 0, 257, 259, 123,
- 296, 118, 308, 348, 376, 386, 315, 346, 312, 258,
- 215, 394, 360, 349, 358, 213, 359, 353, 356, 269,
- 0, 328, 281, 0, 370, 44, 44, 280, 328, 369,
- 0, 355, 402, 400, 383, 347, 413, 401, 382, 394,
- 158, 283, 426, 328, 328, 357, 280, 0, 44, 214,
- 0, 76, 122, 115, 137, 0, 150, 0, 143, 263,
- 253, 0, 68, 152, 137, 151, 150, 144, 143, 0,
- 0, 0, 0, 0, 327, 365, 268, 144, 35, 35,
- 282, 327, 363, 364, 0, 0, 0, 0, 0, 0,
- 0, 403, 0, 0, 342, 0, 327, 327, 0, 0,
- 0, 35, 78, 0, 75, 77, 0, 0, 0, 338,
- 335, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 423, 0, 420,
- 418, 424, 422, 419, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 421, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0};
-
-const short QXmlStreamReader_Table::action_check [] = {
- 26, 18, 26, 14, 4, 4, 4, 26, 24, 14,
- 4, 26, 4, 4, 4, 4, 22, 55, 26, 26,
- 42, 4, 4, 44, 26, 22, 19, 12, 2, 2,
- 18, 2, 13, 0, 18, 4, 4, 2, 4, 26,
- 26, 20, 18, 4, 4, 4, 26, 11, 26, 26,
- 7, 8, 7, 8, 4, 7, 8, 6, 2, 9,
- 7, 8, 24, 25, 7, 8, 7, 8, 7, 8,
- 6, 36, 7, 8, 7, 8, 6, 26, 34, 35,
- 24, 34, 35, 7, 8, 11, 2, 12, 13, 20,
- 26, 12, 13, 15, 11, 13, 26, 11, 29, 11,
- 26, 19, 7, 8, 26, 11, 26, 27, -1, 26,
- 7, 8, 26, 4, 26, 18, 12, 13, 12, 13,
- 26, 2, 3, 26, 27, 16, 11, 20, -1, 24,
- 25, 26, 6, 7, 8, 28, 29, 21, 22, 6,
- 24, 6, 21, 22, 11, 24, -1, 37, 38, 39,
- 21, 22, -1, 24, -1, 40, 41, 2, 3, 26,
- -1, 26, 17, 7, 8, 20, 16, -1, 23, -1,
- 15, 26, 27, 54, 24, 25, 26, 17, -1, 17,
- 20, -1, 20, 23, -1, 23, 26, 27, 26, 27,
- 34, 35, 2, 20, 4, 11, -1, -1, -1, 9,
- 45, -1, -1, 30, 31, 32, 33, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 32, 33, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 47, 48, 49, 50, 51, 52, 53, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, -1,
- -1, -1, -1, -1, -1, 10, -1, 2, -1, 4,
- 15, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, -1, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, 2, -1,
- 4, -1, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, -1, -1, -1, 2, -1, 4,
- -1, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- -1, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, -1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, -1, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, -1, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 45, 46, -1, -1, -1, -1, -1, -1, -1, 54,
- -1, -1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 45, 46, -1, -1, -1,
- -1, -1, -1, -1, 54, -1, -1,
-
- 20, 37, 12, 12, 1, 16, 20, 13, 13, 12,
- 12, 36, 12, 12, 12, 36, 12, 12, 12, 20,
- 12, 12, 49, 12, 37, 12, 72, 20, 13, 37,
- 20, 17, 12, 12, 12, 12, 20, 12, 12, 20,
- 12, 12, 54, 12, 17, 13, 13, 17, 12, 37,
- 12, 12, 68, 13, 20, 20, -1, 72, 17, 17,
- 12, 68, 45, 20, 12, 1, 17, 17, 44, 16,
- 12, 17, 54, 17, 17, 12, 17, 17, 17, 12,
- -1, 10, 12, -1, 12, 10, 10, 17, 10, 17,
- -1, 54, 12, 20, 17, 49, 14, 17, 21, 17,
- 38, 12, 4, 10, 10, 54, 17, -1, 10, 54,
- -1, 10, 68, 68, 6, -1, 8, -1, 10, 72,
- 54, -1, 54, 54, 6, 17, 8, 19, 10, -1,
- -1, -1, -1, -1, 63, 17, 13, 19, 63, 63,
- 51, 63, 24, 25, -1, -1, -1, -1, -1, -1,
- -1, 78, -1, -1, 76, -1, 63, 63, -1, -1,
- -1, 63, 61, -1, 63, 64, -1, -1, -1, 76,
- 76, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3, -1, 5,
- 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 19, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1};
-
-
-template <typename T> class QXmlStreamSimpleStack {
- T *data;
- int tos, cap;
-public:
- inline QXmlStreamSimpleStack():data(0), tos(-1), cap(0){}
- inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
-
- inline void reserve(int extraCapacity) {
- if (tos + extraCapacity + 1 > cap) {
- cap = qMax(tos + extraCapacity + 1, cap << 1 );
- void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
- data = reinterpret_cast<T *>(ptr);
- Q_CHECK_PTR(data);
- }
- }
-
- inline T &push() { reserve(1); return data[++tos]; }
- inline T &rawPush() { return data[++tos]; }
- inline const T &top() const { return data[tos]; }
- inline T &top() { return data[tos]; }
- inline T &pop() { return data[tos--]; }
- inline T &operator[](int index) { return data[index]; }
- inline const T &at(int index) const { return data[index]; }
- inline int size() const { return tos + 1; }
- inline void resize(int s) { tos = s - 1; }
- inline bool isEmpty() const { return tos < 0; }
- inline void clear() { tos = -1; }
-};
-
-
-class QXmlStream
-{
- Q_DECLARE_TR_FUNCTIONS(QXmlStream)
-};
-
-class QXmlStreamPrivateTagStack {
-public:
- struct NamespaceDeclaration
- {
- QStringRef prefix;
- QStringRef namespaceUri;
- };
-
- struct Tag
- {
- QStringRef name;
- QStringRef qualifiedName;
- NamespaceDeclaration namespaceDeclaration;
- int tagStackStringStorageSize;
- int namespaceDeclarationsSize;
- };
-
-
- QXmlStreamPrivateTagStack();
- QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
- QString tagStackStringStorage;
- int tagStackStringStorageSize;
- int initialTagStackStringStorageSize;
- bool tagsDone;
-
- inline QStringRef addToStringStorage(const QStringRef &s) {
- int pos = tagStackStringStorageSize;
- int sz = s.size();
- if (pos != tagStackStringStorage.size())
- tagStackStringStorage.resize(pos);
- tagStackStringStorage.insert(pos, s.unicode(), sz);
- tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
- }
- inline QStringRef addToStringStorage(const QString &s) {
- int pos = tagStackStringStorageSize;
- int sz = s.size();
- if (pos != tagStackStringStorage.size())
- tagStackStringStorage.resize(pos);
- tagStackStringStorage.insert(pos, s.unicode(), sz);
- tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
- }
-
- QXmlStreamSimpleStack<Tag> tagStack;
-
-
- inline Tag &tagStack_pop() {
- Tag& tag = tagStack.pop();
- tagStackStringStorageSize = tag.tagStackStringStorageSize;
- namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
- tagsDone = tagStack.isEmpty();
- return tag;
- }
- inline Tag &tagStack_push() {
- Tag &tag = tagStack.push();
- tag.tagStackStringStorageSize = tagStackStringStorageSize;
- tag.namespaceDeclarationsSize = namespaceDeclarations.size();
- return tag;
- }
-};
-
-
-class QXmlStreamEntityResolver;
-#ifndef QT_NO_XMLSTREAMREADER
-class QXmlStreamReaderPrivate : public QXmlStreamReader_Table, public QXmlStreamPrivateTagStack{
- QXmlStreamReader *q_ptr;
- Q_DECLARE_PUBLIC(QXmlStreamReader)
-public:
- QXmlStreamReaderPrivate(QXmlStreamReader *q);
- ~QXmlStreamReaderPrivate();
- void init();
-
- QByteArray rawReadBuffer;
- QByteArray dataBuffer;
- uchar firstByte;
- qint64 nbytesread;
- QString readBuffer;
- int readBufferPos;
- QXmlStreamSimpleStack<uint> putStack;
- struct Entity {
- Entity(const QString& str = QString())
- :value(str), external(false), unparsed(false), literal(false),
- hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(const QString &entity)
- { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; }
- QString value;
- uint external : 1;
- uint unparsed : 1;
- uint literal : 1;
- uint hasBeenParsed : 1;
- uint isCurrentlyReferenced : 1;
- };
- QHash<QString, Entity> entityHash;
- QHash<QString, Entity> parameterEntityHash;
- QXmlStreamSimpleStack<Entity *>entityReferenceStack;
- inline bool referenceEntity(Entity &entity) {
- if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
- return false;
- }
- entity.isCurrentlyReferenced = true;
- entityReferenceStack.push() = &entity;
- injectToken(ENTITY_DONE);
- return true;
- }
-
-
- QIODevice *device;
- bool deleteDevice;
-#ifndef QT_NO_TEXTCODEC
- QTextCodec *codec;
- QTextDecoder *decoder;
-#endif
- bool atEnd;
-
- /*!
- \sa setType()
- */
- QXmlStreamReader::TokenType type;
- QXmlStreamReader::Error error;
- QString errorString;
- QString unresolvedEntity;
-
- qint64 lineNumber, lastLineStart, characterOffset;
-
-
- void write(const QString &);
- void write(const char *);
-
-
- QXmlStreamAttributes attributes;
- QStringRef namespaceForPrefix(const QStringRef &prefix);
- void resolveTag();
- void resolvePublicNamespaces();
- void resolveDtd();
- uint resolveCharRef(int symbolIndex);
- bool checkStartDocument();
- void startDocument();
- void parseError();
- void checkPublicLiteral(const QStringRef &publicId);
-
- bool scanDtd;
- QStringRef lastAttributeValue;
- bool lastAttributeIsCData;
- struct DtdAttribute {
- QStringRef tagName;
- QStringRef attributeQualifiedName;
- QStringRef attributePrefix;
- QStringRef attributeName;
- QStringRef defaultValue;
- bool isCDATA;
- bool isNamespaceAttribute;
- };
- QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
- struct NotationDeclaration {
- QStringRef name;
- QStringRef publicId;
- QStringRef systemId;
- };
- QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
- QXmlStreamNotationDeclarations publicNotationDeclarations;
- QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
-
- struct EntityDeclaration {
- QStringRef name;
- QStringRef notationName;
- QStringRef publicId;
- QStringRef systemId;
- QStringRef value;
- bool parameter;
- bool external;
- inline void clear() {
- name.clear();
- notationName.clear();
- publicId.clear();
- systemId.clear();
- value.clear();
- parameter = external = false;
- }
- };
- QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
- QXmlStreamEntityDeclarations publicEntityDeclarations;
-
- QStringRef text;
-
- QStringRef prefix, namespaceUri, qualifiedName, name;
- QStringRef processingInstructionTarget, processingInstructionData;
- QStringRef dtdName, dtdPublicId, dtdSystemId;
- QStringRef documentVersion, documentEncoding;
- uint isEmptyElement : 1;
- uint isWhitespace : 1;
- uint isCDATA : 1;
- uint standalone : 1;
- uint hasCheckedStartDocument : 1;
- uint normalizeLiterals : 1;
- uint hasSeenTag : 1;
- uint inParseEntity : 1;
- uint referenceToUnparsedEntityDetected : 1;
- uint referenceToParameterEntityDetected : 1;
- uint hasExternalDtdSubset : 1;
- uint lockEncoding : 1;
- uint namespaceProcessing : 1;
-
- int resumeReduction;
- void resume(int rule);
-
- inline bool entitiesMustBeDeclared() const {
- return (!inParseEntity
- && (standalone
- || (!referenceToUnparsedEntityDetected
- && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25
- && !hasExternalDtdSubset)));
- }
-
- // qlalr parser
- int tos;
- int stack_size;
- struct Value {
- int pos;
- int len;
- int prefix;
- ushort c;
- };
-
- Value *sym_stack;
- int *state_stack;
- inline void reallocateStack();
- inline Value &sym(int index) const
- { return sym_stack[tos + index - 1]; }
- QString textBuffer;
- inline void clearTextBuffer() {
- if (!scanDtd) {
- textBuffer.resize(0);
- textBuffer.reserve(256);
- }
- }
- struct Attribute {
- Value key;
- Value value;
- };
- QXmlStreamSimpleStack<Attribute> attributeStack;
-
- inline QStringRef symString(int index) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
- }
- inline QStringRef symName(int index) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
- }
- inline QStringRef symString(int index, int offset) {
- const Value &symbol = sym(index);
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
- }
- inline QStringRef symPrefix(int index) {
- const Value &symbol = sym(index);
- if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
- }
- inline QStringRef symString(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
- }
- inline QStringRef symName(const Value &symbol) {
- return QStringRef(&textBuffer, symbol.pos, symbol.len);
- }
- inline QStringRef symPrefix(const Value &symbol) {
- if (symbol.prefix)
- return QStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
- return QStringRef();
- }
-
- inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
-
-
- short token;
- uint token_char;
-
- uint filterCarriageReturn();
- inline uint getChar();
- inline uint peekChar();
- inline void putChar(uint c) { putStack.push() = c; }
- inline void putChar(QChar c) { putStack.push() = c.unicode(); }
- void putString(const QString &s, int from = 0);
- void putStringLiteral(const QString &s);
- void putReplacement(const QString &s);
- void putReplacementInAttributeValue(const QString &s);
- uint getChar_helper();
-
- bool scanUntil(const char *str, short tokenToInject = -1);
- bool scanString(const char *str, short tokenToInject, bool requireSpace = true);
- inline void injectToken(ushort tokenToInject) {
- putChar(int(tokenToInject) << 16);
- }
-
- QString resolveUndeclaredEntity(const QString &name);
- void parseEntity(const QString &value);
- QXmlStreamReaderPrivate *entityParser;
-
- bool scanAfterLangleBang();
- bool scanPublicOrSystem();
- bool scanNData();
- bool scanAfterDefaultDecl();
- bool scanAttType();
-
-
- // scan optimization functions. Not strictly necessary but LALR is
- // not very well suited for scanning fast
- int fastScanLiteralContent();
- int fastScanSpace();
- int fastScanContentCharList();
- int fastScanName(int *prefix = 0);
- inline int fastScanNMTOKEN();
-
-
- bool parse();
- inline void consumeRule(int);
-
- void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
- void raiseWellFormedError(const QString &message);
-
- QXmlStreamEntityResolver *entityResolver;
-
-private:
- /*! \internal
- Never assign to variable type directly. Instead use this function.
-
- This prevents errors from being ignored.
- */
- inline void setType(const QXmlStreamReader::TokenType t)
- {
- if(type != QXmlStreamReader::Invalid)
- type = t;
- }
-};
-
-bool QXmlStreamReaderPrivate::parse()
-{
- // cleanup currently reported token
-
- switch (type) {
- case QXmlStreamReader::StartElement:
- name.clear();
- prefix.clear();
- qualifiedName.clear();
- namespaceUri.clear();
- publicNamespaceDeclarations.clear();
- attributes.clear();
- if (isEmptyElement) {
- setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
- namespaceUri = tag.namespaceDeclaration.namespaceUri;
- name = tag.name;
- qualifiedName = tag.qualifiedName;
- isEmptyElement = false;
- return true;
- }
- clearTextBuffer();
- break;
- case QXmlStreamReader::EndElement:
- name.clear();
- prefix.clear();
- qualifiedName.clear();
- namespaceUri.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::DTD:
- publicNotationDeclarations.clear();
- publicEntityDeclarations.clear();
- dtdName.clear();
- dtdPublicId.clear();
- dtdSystemId.clear();
- Q_FALLTHROUGH();
- case QXmlStreamReader::Comment:
- case QXmlStreamReader::Characters:
- isCDATA = false;
- isWhitespace = true;
- text.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::EntityReference:
- text.clear();
- name.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::ProcessingInstruction:
- processingInstructionTarget.clear();
- processingInstructionData.clear();
- clearTextBuffer();
- break;
- case QXmlStreamReader::NoToken:
- case QXmlStreamReader::Invalid:
- break;
- case QXmlStreamReader::StartDocument:
- lockEncoding = true;
- documentVersion.clear();
- documentEncoding.clear();
-#ifndef QT_NO_TEXTCODEC
- if (decoder && decoder->hasFailure()) {
- raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
- readBuffer.clear();
- return false;
- }
-#endif
- Q_FALLTHROUGH();
- default:
- clearTextBuffer();
- ;
- }
-
- setType(QXmlStreamReader::NoToken);
-
-
- // the main parse loop
- int act, r;
-
- if (resumeReduction) {
- act = state_stack[tos-1];
- r = resumeReduction;
- resumeReduction = 0;
- goto ResumeReduction;
- }
-
- act = state_stack[tos];
-
- forever {
- if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
- uint cu = getChar();
- token = NOTOKEN;
- token_char = cu == ~0U ? cu : ushort(cu);
- if ((cu != ~0U) && (cu & 0xff0000)) {
- token = cu >> 16;
- } else switch (token_char) {
- case 0xfffe:
- case 0xffff:
- token = ERROR;
- break;
- case '\r':
- token = SPACE;
- if (cu == '\r') {
- if ((token_char = filterCarriageReturn())) {
- ++lineNumber;
- lastLineStart = characterOffset + readBufferPos;
- break;
- }
- } else {
- break;
- }
- Q_FALLTHROUGH();
- case ~0U: {
- token = EOF_SYMBOL;
- if (!tagsDone && !inParseEntity) {
- int a = t_action(act, token);
- if (a < 0) {
- raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
- return false;
- }
- }
-
- } break;
- case '\n':
- ++lineNumber;
- lastLineStart = characterOffset + readBufferPos;
- Q_FALLTHROUGH();
- case ' ':
- case '\t':
- token = SPACE;
- break;
- case '&':
- token = AMPERSAND;
- break;
- case '#':
- token = HASH;
- break;
- case '\'':
- token = QUOTE;
- break;
- case '\"':
- token = DBLQUOTE;
- break;
- case '<':
- token = LANGLE;
- break;
- case '>':
- token = RANGLE;
- break;
- case '[':
- token = LBRACK;
- break;
- case ']':
- token = RBRACK;
- break;
- case '(':
- token = LPAREN;
- break;
- case ')':
- token = RPAREN;
- break;
- case '|':
- token = PIPE;
- break;
- case '=':
- token = EQ;
- break;
- case '%':
- token = PERCENT;
- break;
- case '/':
- token = SLASH;
- break;
- case ':':
- token = COLON;
- break;
- case ';':
- token = SEMICOLON;
- break;
- case ',':
- token = COMMA;
- break;
- case '-':
- token = DASH;
- break;
- case '+':
- token = PLUS;
- break;
- case '*':
- token = STAR;
- break;
- case '.':
- token = DOT;
- break;
- case '?':
- token = QUESTIONMARK;
- break;
- case '!':
- token = BANG;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- token = DIGIT;
- break;
- default:
- if (cu < 0x20)
- token = NOTOKEN;
- else
- token = LETTER;
- break;
- }
- }
-
- act = t_action (act, token);
- if (act == ACCEPT_STATE) {
- // reset the parser in case someone resumes (process instructions can follow a valid document)
- tos = 0;
- state_stack[tos++] = 0;
- state_stack[tos] = 0;
- return true;
- } else if (act > 0) {
- if (++tos == stack_size-1)
- reallocateStack();
-
- Value &val = sym_stack[tos];
- val.c = token_char;
- val.pos = textBuffer.size();
- val.prefix = 0;
- val.len = 1;
- if (token_char)
- textBuffer += QChar(token_char);
-
- state_stack[tos] = act;
- token = -1;
-
-
- } else if (act < 0) {
- r = - act - 1;
-
-#if defined (QLALR_DEBUG)
- int ridx = rule_index[r];
- printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]);
- ++ridx;
- for (int i = ridx; i < ridx + rhs[r]; ++i) {
- int symbol = rule_info[i];
- if (const char *name = spell[symbol])
- printf (" %s", name);
- else
- printf (" #%d", symbol);
- }
- printf ("\n");
-#endif
-
- tos -= rhs[r];
- act = state_stack[tos++];
- ResumeReduction:
- switch (r) {
-
- case 0:
- setType(QXmlStreamReader::EndDocument);
- break;
-
- case 1:
- if (type != QXmlStreamReader::Invalid) {
- if (hasSeenTag || inParseEntity) {
- setType(QXmlStreamReader::EndDocument);
- } else {
- raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected."));
- // reset the parser
- tos = 0;
- state_stack[tos++] = 0;
- state_stack[tos] = 0;
- return false;
- }
- }
- break;
-
- case 10:
- entityReferenceStack.pop()->isCurrentlyReferenced = false;
- clearSym();
- break;
-
- case 11:
- if (!scanString(spell[VERSION], VERSION, false) && atEnd) {
- resume(11);
- return false;
- }
- break;
-
- case 12:
- setType(QXmlStreamReader::StartDocument);
- documentVersion = symString(6);
- startDocument();
- break;
-
- case 13:
- hasExternalDtdSubset = true;
- dtdSystemId = symString(2);
- break;
-
- case 14:
- checkPublicLiteral(symString(2));
- dtdPublicId = symString(2);
- dtdSystemId = symString(4);
- hasExternalDtdSubset = true;
- break;
-
- case 16:
- if (!scanPublicOrSystem() && atEnd) {
- resume(16);
- return false;
- }
- dtdName = symString(3);
- break;
-
- case 17:
- case 18:
- dtdName = symString(3);
- Q_FALLTHROUGH();
-
- case 19:
- case 20:
- setType(QXmlStreamReader::DTD);
- text = &textBuffer;
- break;
-
- case 21:
- scanDtd = true;
- break;
-
- case 22:
- scanDtd = false;
- break;
-
- case 37:
- if (!scanString(spell[EMPTY], EMPTY, false)
- && !scanString(spell[ANY], ANY, false)
- && atEnd) {
- resume(37);
- return false;
- }
- break;
-
- case 43:
- if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) {
- resume(43);
- return false;
- }
- break;
-
- case 68: {
- lastAttributeIsCData = true;
- } break;
-
- case 78:
- if (!scanAfterDefaultDecl() && atEnd) {
- resume(78);
- return false;
- }
- break;
-
- case 83:
- sym(1) = sym(2);
- lastAttributeValue.clear();
- lastAttributeIsCData = false;
- if (!scanAttType() && atEnd) {
- resume(83);
- return false;
- }
- break;
-
- case 84: {
- DtdAttribute &dtdAttribute = dtdAttributes.push();
- dtdAttribute.tagName.clear();
- dtdAttribute.isCDATA = lastAttributeIsCData;
- dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1));
- dtdAttribute.attributeName = addToStringStorage(symString(1));
- dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1));
- dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns")
- || (dtdAttribute.attributePrefix.isEmpty()
- && dtdAttribute.attributeName == QLatin1String("xmlns")));
- if (lastAttributeValue.isNull()) {
- dtdAttribute.defaultValue.clear();
- } else {
- if (dtdAttribute.isCDATA)
- dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue);
- else
- dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified());
-
- }
- } break;
-
- case 88: {
- if (referenceToUnparsedEntityDetected && !standalone)
- break;
- int n = dtdAttributes.size();
- QStringRef tagName = addToStringStorage(symName(3));
- while (n--) {
- DtdAttribute &dtdAttribute = dtdAttributes[n];
- if (!dtdAttribute.tagName.isNull())
- break;
- dtdAttribute.tagName = tagName;
- for (int i = 0; i < n; ++i) {
- if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName)
- && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) {
- dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it
- break;
- }
- }
- }
- } break;
-
- case 89: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(89);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.push();
- entityDeclaration.clear();
- entityDeclaration.name = symString(3);
- } break;
-
- case 90: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(90);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.push();
- entityDeclaration.clear();
- entityDeclaration.name = symString(5);
- entityDeclaration.parameter = true;
- } break;
-
- case 91: {
- if (!scanNData() && atEnd) {
- resume(91);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- entityDeclaration.systemId = symString(3);
- entityDeclaration.external = true;
- } break;
-
- case 92: {
- if (!scanNData() && atEnd) {
- resume(92);
- return false;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- checkPublicLiteral((entityDeclaration.publicId = symString(3)));
- entityDeclaration.systemId = symString(5);
- entityDeclaration.external = true;
- } break;
-
- case 93: {
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- entityDeclaration.notationName = symString(3);
- if (entityDeclaration.parameter)
- raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
- }
- Q_FALLTHROUGH();
-
- case 94:
- case 95: {
- if (referenceToUnparsedEntityDetected && !standalone) {
- entityDeclarations.pop();
- break;
- }
- EntityDeclaration &entityDeclaration = entityDeclarations.top();
- if (!entityDeclaration.external)
- entityDeclaration.value = symString(2);
- QString entityName = entityDeclaration.name.toString();
- QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(entityName)) {
- Entity entity(entityDeclaration.value.toString());
- entity.unparsed = (!entityDeclaration.notationName.isNull());
- entity.external = entityDeclaration.external;
- hash.insert(entityName, entity);
- }
- } break;
-
- case 96: {
- setType(QXmlStreamReader::ProcessingInstruction);
- int pos = sym(4).pos + sym(4).len;
- processingInstructionTarget = symString(3);
- if (scanUntil("?>")) {
- processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- const QString piTarget(processingInstructionTarget.toString());
- if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
- raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
- }
- else if(!QXmlUtils::isNCName(piTarget))
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget));
- } else if (type != QXmlStreamReader::Invalid){
- resume(96);
- return false;
- }
- } break;
-
- case 97:
- setType(QXmlStreamReader::ProcessingInstruction);
- processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive))
- raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
- break;
-
- case 98:
- if (!scanAfterLangleBang() && atEnd) {
- resume(98);
- return false;
- }
- break;
-
- case 99:
- if (!scanUntil("--")) {
- resume(99);
- return false;
- }
- break;
-
- case 100: {
- setType(QXmlStreamReader::Comment);
- int pos = sym(1).pos + 4;
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
- } break;
-
- case 101: {
- setType(QXmlStreamReader::Characters);
- isCDATA = true;
- isWhitespace = false;
- int pos = sym(2).pos;
- if (scanUntil("]]>", -1)) {
- text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3);
- } else {
- resume(101);
- return false;
- }
- } break;
-
- case 102: {
- if (!scanPublicOrSystem() && atEnd) {
- resume(102);
- return false;
- }
- NotationDeclaration &notationDeclaration = notationDeclarations.push();
- notationDeclaration.name = symString(3);
- } break;
-
- case 103: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- notationDeclaration.systemId = symString(3);
- notationDeclaration.publicId.clear();
- } break;
-
- case 104: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- notationDeclaration.systemId.clear();
- checkPublicLiteral((notationDeclaration.publicId = symString(3)));
- } break;
-
- case 105: {
- NotationDeclaration &notationDeclaration = notationDeclarations.top();
- checkPublicLiteral((notationDeclaration.publicId = symString(3)));
- notationDeclaration.systemId = symString(5);
- } break;
-
- case 129:
- isWhitespace = false;
- Q_FALLTHROUGH();
-
- case 130:
- sym(1).len += fastScanContentCharList();
- if (atEnd && !inParseEntity) {
- resume(130);
- return false;
- }
- break;
-
- case 139:
- if (!textBuffer.isEmpty()) {
- setType(QXmlStreamReader::Characters);
- text = &textBuffer;
- }
- break;
-
- case 140:
- case 141:
- clearSym();
- break;
-
- case 142:
- case 143:
- sym(1) = sym(2);
- break;
-
- case 144:
- case 145:
- case 146:
- case 147:
- sym(1).len += sym(2).len;
- break;
-
- case 173:
- if (normalizeLiterals)
- textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' ');
- break;
-
- case 174:
- sym(1).len += fastScanLiteralContent();
- if (atEnd) {
- resume(174);
- return false;
- }
- break;
-
- case 175: {
- if (!QXmlUtils::isPublicID(symString(1).toString())) {
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString()));
- resume(175);
- return false;
- }
- } break;
-
- case 176:
- case 177:
- clearSym();
- break;
-
- case 178:
- case 179:
- sym(1) = sym(2);
- break;
-
- case 180:
- case 181:
- case 182:
- case 183:
- sym(1).len += sym(2).len;
- break;
-
- case 213:
- case 214:
- clearSym();
- break;
-
- case 215:
- case 216:
- sym(1) = sym(2);
- lastAttributeValue = symString(1);
- break;
-
- case 217:
- case 218:
- case 219:
- case 220:
- sym(1).len += sym(2).len;
- break;
-
- case 229: {
- QStringRef prefix = symPrefix(1);
- if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- namespaceDeclaration.prefix.clear();
-
- const QStringRef ns(symString(5));
- if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
- ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
- raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
- else
- namespaceDeclaration.namespaceUri = addToStringStorage(ns);
- } else {
- Attribute &attribute = attributeStack.push();
- attribute.key = sym(1);
- attribute.value = sym(5);
-
- QStringRef attributeQualifiedName = symName(1);
- bool normalize = false;
- for (int a = 0; a < dtdAttributes.size(); ++a) {
- DtdAttribute &dtdAttribute = dtdAttributes[a];
- if (!dtdAttribute.isCDATA
- && dtdAttribute.tagName == qualifiedName
- && dtdAttribute.attributeQualifiedName == attributeQualifiedName
- ) {
- normalize = true;
- break;
- }
- }
- if (normalize) {
- // normalize attribute value (simplify and trim)
- int pos = textBuffer.size();
- int n = 0;
- bool wasSpace = true;
- for (int i = 0; i < attribute.value.len; ++i) {
- QChar c = textBuffer.at(attribute.value.pos + i);
- if (c.unicode() == ' ') {
- if (wasSpace)
- continue;
- wasSpace = true;
- } else {
- wasSpace = false;
- }
- textBuffer += textBuffer.at(attribute.value.pos + i);
- ++n;
- }
- if (wasSpace)
- while (n && textBuffer.at(pos + n - 1).unicode() == ' ')
- --n;
- attribute.value.pos = pos;
- attribute.value.len = n;
- }
- if (prefix == QLatin1String("xmlns") && namespaceProcessing) {
- NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- QStringRef namespacePrefix = symString(attribute.key);
- QStringRef namespaceUri = symString(attribute.value);
- attributeStack.pop();
- if (((namespacePrefix == QLatin1String("xml"))
- ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
- || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
- || namespaceUri.isEmpty()
- || namespacePrefix == QLatin1String("xmlns"))
- raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
-
- namespaceDeclaration.prefix = addToStringStorage(namespacePrefix);
- namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
- }
- }
- } break;
-
- case 235: {
- normalizeLiterals = true;
- Tag &tag = tagStack_push();
- prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2));
- name = tag.name = addToStringStorage(symString(2));
- qualifiedName = tag.qualifiedName = addToStringStorage(symName(2));
- if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name))
- raiseWellFormedError(QXmlStream::tr("Invalid XML name."));
- } break;
-
- case 236:
- isEmptyElement = true;
- Q_FALLTHROUGH();
-
- case 237:
- setType(QXmlStreamReader::StartElement);
- resolveTag();
- if (tagStack.size() == 1 && hasSeenTag && !inParseEntity)
- raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
- hasSeenTag = true;
- break;
-
- case 238: {
- setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
-
- namespaceUri = tag.namespaceDeclaration.namespaceUri;
- name = tag.name;
- qualifiedName = tag.qualifiedName;
- if (qualifiedName != symName(3))
- raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch."));
- } break;
-
- case 239:
- if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity));
- break;
- }
- setType(QXmlStreamReader::EntityReference);
- name = &unresolvedEntity;
- break;
-
- case 240: {
- sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
- if (entityHash.contains(reference)) {
- Entity &entity = entityHash[reference];
- if (entity.unparsed) {
- raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference));
- } else {
- if (!entity.hasBeenParsed) {
- parseEntity(entity.value);
- entity.hasBeenParsed = true;
- }
- if (entity.literal)
- putStringLiteral(entity.value);
- else if (referenceEntity(entity))
- putReplacement(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- }
- break;
- }
-
- if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference);
- if (!replacementText.isNull()) {
- putReplacement(replacementText);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
- }
-
- injectToken(UNRESOLVED_ENTITY);
- unresolvedEntity = symString(2).toString();
- textBuffer.chop(2 + sym(2).len);
- clearSym();
-
- } break;
-
- case 241: {
- sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
- if (parameterEntityHash.contains(reference)) {
- referenceToParameterEntityDetected = true;
- Entity &entity = parameterEntityHash[reference];
- if (entity.unparsed || entity.external) {
- referenceToUnparsedEntityDetected = true;
- } else {
- if (referenceEntity(entity))
- putString(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- }
- } else if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString()));
- }
- } break;
-
- case 242:
- sym(1).len += sym(2).len + 1;
- break;
-
- case 243: {
- sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
- if (entityHash.contains(reference)) {
- Entity &entity = entityHash[reference];
- if (entity.unparsed || entity.value.isNull()) {
- raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference));
- break;
- }
- if (!entity.hasBeenParsed) {
- parseEntity(entity.value);
- entity.hasBeenParsed = true;
- }
- if (entity.literal)
- putStringLiteral(entity.value);
- else if (referenceEntity(entity))
- putReplacementInAttributeValue(entity.value);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
-
- if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference);
- if (!replacementText.isNull()) {
- putReplacement(replacementText);
- textBuffer.chop(2 + sym(2).len);
- clearSym();
- break;
- }
- }
- if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference));
- }
- } break;
-
- case 244: {
- if (uint s = resolveCharRef(3)) {
- if (s >= 0xffff)
- putStringLiteral(QString::fromUcs4(&s, 1));
- else
- putChar((LETTER << 16) | s);
-
- textBuffer.chop(3 + sym(3).len);
- clearSym();
- } else {
- raiseWellFormedError(QXmlStream::tr("Invalid character reference."));
- }
- } break;
-
- case 247:
- case 248:
- sym(1).len += sym(2).len;
- break;
-
- case 259:
- sym(1).len += fastScanSpace();
- if (atEnd) {
- resume(259);
- return false;
- }
- break;
-
- case 262: {
- sym(1).len += fastScanName(&sym(1).prefix);
- if (atEnd) {
- resume(262);
- return false;
- }
- } break;
-
- case 263:
- sym(1).len += fastScanName();
- if (atEnd) {
- resume(263);
- return false;
- }
- break;
-
- case 264:
- case 265:
- case 266:
- case 267:
- case 268:
- sym(1).len += fastScanNMTOKEN();
- if (atEnd) {
- resume(268);
- return false;
- }
-
- break;
-
- default:
- ;
- } // switch
- act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT);
- if (type != QXmlStreamReader::NoToken)
- return true;
- } else {
- parseError();
- break;
- }
- }
- return false;
-}
-#endif //QT_NO_XMLSTREAMREADER.xml
-
-
-#endif // QXMLSTREAM_P_H
-
diff --git a/src/gui/configure.json b/src/gui/configure.json
index 27e913877f..220662ea8e 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -46,7 +46,6 @@
"xcb-xlib": "boolean",
"xinput2": "boolean",
"xkb": "boolean",
- "xkb-config-root": "string",
"xkbcommon": { "type": "enum", "values": [ "no", "qt", "system" ] },
"xkbcommon-evdev": "boolean",
"xkbcommon-x11": { "type": "enum", "name": "xkbcommon", "values": [ "no", "qt", "system" ] }
@@ -624,8 +623,7 @@
},
"testTypeAliases": {
- "files": [ "directX" ],
- "getPkgConfigVariable": [ "xkbConfigRoot" ]
+ "files": [ "directX" ]
},
"tests": {
@@ -888,13 +886,6 @@
"value": "/usr",
"log": "value"
},
- "xkbconfigroot": {
- "label": "XKB config root",
- "type": "xkbConfigRoot",
- "pkg-config-args": "xkeyboard-config",
- "pkg-config-variable": "xkb_base",
- "log": "value"
- },
"xlib": {
"label": "XLib",
"type": "compile",
@@ -1355,12 +1346,6 @@
"condition": "libs.xkbcommon_x11",
"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": {
"label": "XLib",
"autoDetect": "!config.darwin || features.xcb",
@@ -1580,12 +1565,6 @@
"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",
"condition": "features.xcb && config.darwin",
"message": "XCB support on macOS is minimal and untested. Some features will
diff --git a/src/gui/configure.pri b/src/gui/configure.pri
index aaffa835dc..fcd2d1f73e 100644
--- a/src/gui/configure.pri
+++ b/src/gui/configure.pri
@@ -42,21 +42,6 @@ defineTest(qtConfTest_directX) {
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) {
name =
!isEmpty(config.input.qpa_default_platform): name = $$config.input.qpa_default_platform
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 20b5fe039a..d00d69586a 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -39,18 +39,17 @@
#include "qxcbkeyboard.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
+#include "qxcbxkbcommon.h"
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontext.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformcursor.h>
-#include <QtCore/QTextCodec>
-#include <QtCore/QMetaMethod>
-#include <QtCore/QDir>
+#include <QtCore/QMetaEnum>
+
#include <private/qguiapplication_p.h>
-#include <stdio.h>
#include <X11/keysym.h>
#if QT_CONFIG(xinput2)
@@ -59,12 +58,6 @@
#undef KeyRelease
#endif
-#if QT_CONFIG(xcb_xlib)
-#include <X11/Xutil.h>
-#undef KeyPress
-#undef KeyRelease
-#endif
-
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
@@ -706,76 +699,6 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
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.
* If the 'unshifted' symbol is uppercase and there is no shifted symbol,
* 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
return 0;
- KeySym xlower;
- KeySym xupper;
- /* libxkbcommon >= 0.8.0 will have public API functions providing
- * 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
- && unshifted == static_cast<xcb_keysym_t>(xupper)) { // Unshifted must be upper case
- return static_cast<xcb_keysym_t>(xlower);
+ xcb_keysym_t xlower;
+ xcb_keysym_t xupper;
+ xkbcommon_XConvertCase(unshifted, &xlower, &xupper);
+
+ if (xlower != xupper // Check if symbol is cased
+ && unshifted == xupper) { // Unshifted must be upper case
+ return xlower;
}
+
return 0;
}
@@ -1060,92 +980,55 @@ struct xkb_keymap *QXcbKeyboard::keymapFromCore()
keymap += "};\n"; // xkb_keymap
- return xkb_keymap_new_from_buffer(xkb_context,
+ return xkb_keymap_new_from_buffer(m_xkbContext.get(),
keymap.constData(),
keymap.size(),
XKB_KEYMAP_FORMAT_TEXT_V1,
- static_cast<xkb_keymap_compile_flags>(0));
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
}
-#endif
void QXcbKeyboard::updateKeymap()
{
m_config = true;
- m_keymap_is_core = false;
- // set xkb context object
- if (!xkb_context) {
- if (qEnvironmentVariableIsSet("QT_XKB_CONFIG_ROOT")) {
- xkb_context = xkb_context_new((xkb_context_flags)XKB_CONTEXT_NO_DEFAULT_INCLUDES);
- 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!");
+
+ if (!m_xkbContext) {
+ m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES));
+ if (!m_xkbContext) {
+ qCWarning(lcQpaKeyboard, "failed to create XKB context");
m_config = false;
return;
}
- // log only critical errors, we do our own error logging from printKeymapError()
- xkb_context_set_log_level(xkb_context, (xkb_log_level)XKB_LOG_LEVEL_CRITICAL);
+ xkb_log_level logLevel = lcQpaKeyboard().isDebugEnabled() ?
+ 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 (connection()->hasXKB()) {
- xkb_keymap = xkb_x11_keymap_new_from_device(xkb_context, xcb_connection(), core_device_id, (xkb_keymap_compile_flags)0);
- if (xkb_keymap) {
- // Create a new keyboard state object for a keymap
- new_state = xkb_x11_state_new_from_device(xkb_keymap, xcb_connection(), core_device_id);
- }
- }
+ m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(),
+ core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ if (m_xkbKeymap)
+ m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
+ } else {
#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;
- }
+ m_xkbKeymap.reset(keymapFromCore());
+ if (m_xkbKeymap)
+ m_xkbState.reset(xkb_state_new(m_xkbKeymap.get()));
+#if QT_CONFIG(xkb)
+ }
#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) {
+ qCWarning(lcQpaKeyboard, "failed to compile a keymap");
+ m_config = false;
+ return;
}
- if (!new_state) {
- qWarning("Qt: Failed to create xkb state!");
+ if (!m_xkbState) {
+ qCWarning(lcQpaKeyboard, "failed to create XKB state");
m_config = false;
return;
}
- // update xkb state object
- xkb_state_unref(xkb_state);
- xkb_state = new_state;
+
updateXKBMods();
checkForLatinLayout();
@@ -1156,7 +1039,7 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
{
if (m_config && connection()->hasXKB()) {
const xkb_state_component newState
- = xkb_state_update_mask(xkb_state,
+ = xkb_state_update_mask(m_xkbState.get(),
state->baseMods,
state->latchedMods,
state->lockedMods,
@@ -1201,7 +1084,7 @@ void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 s
void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
{
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()) {
xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
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->latched_mods,
mods->locked_mods,
@@ -1252,14 +1135,14 @@ quint32 QXcbKeyboard::xkbModMask(quint16 state)
void QXcbKeyboard::updateXKBMods()
{
- xkb_mods.shift = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_SHIFT);
- xkb_mods.lock = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_CAPS);
- xkb_mods.control = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_CTRL);
- xkb_mods.mod1 = xkb_keymap_mod_get_index(xkb_keymap, "Mod1");
- xkb_mods.mod2 = xkb_keymap_mod_get_index(xkb_keymap, "Mod2");
- xkb_mods.mod3 = xkb_keymap_mod_get_index(xkb_keymap, "Mod3");
- xkb_mods.mod4 = xkb_keymap_mod_get_index(xkb_keymap, "Mod4");
- xkb_mods.mod5 = xkb_keymap_mod_get_index(xkb_keymap, "Mod5");
+ xkb_mods.shift = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_SHIFT);
+ xkb_mods.lock = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_CAPS);
+ xkb_mods.control = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_CTRL);
+ xkb_mods.mod1 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod1");
+ xkb_mods.mod2 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod2");
+ xkb_mods.mod3 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod3");
+ xkb_mods.mod4 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod4");
+ xkb_mods.mod5 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod5");
}
static bool isLatin(xkb_keysym_t sym)
@@ -1269,11 +1152,11 @@ static bool isLatin(xkb_keysym_t sym)
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 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) {
xkb_state_update_mask(state.get(), 0, 0, 0, 0, 0, layout);
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_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 currentLayout = xkb_state_key_get_layout(xkb_state, 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(m_xkbState.get(), keycode);
// Look at user layouts in the order in which they are defined in system
// settings to find a latin keysym.
for (layout = 0; layout < layoutCount; ++layout) {
if (layout == currentLayout)
continue;
const xkb_keysym_t *syms;
- xkb_level_index_t level = xkb_state_key_get_level(xkb_state, keycode, layout);
- if (xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms) != 1)
+ xkb_level_index_t level = xkb_state_key_get_level(m_xkbState.get(), keycode, layout);
+ if (xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), keycode, layout, level, &syms) != 1)
continue;
if (isLatin(syms[0])) {
sym = syms[0];
@@ -1319,8 +1202,8 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
if (sym == XKB_KEY_NoSymbol)
return sym;
- xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
- xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
+ 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(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
// Check for uniqueness, consider the following setup:
// 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.
const xcb_keycode_t minKeycode = connection()->setup()->min_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) {
xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
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;
}
+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
{
// turn off the modifier bits which doesn't participate in shortcuts
Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded;
// 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) {
qWarning("QXcbKeyboard: failed to compile xkb keymap!");
return QList<int>();
}
// 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_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
- xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
- xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED);
+ 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(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
+ 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(m_xkbState.get(), XKB_STATE_MODS_DEPRESSED);
xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
quint32 keycode = event->nativeScanCode();
@@ -1384,14 +1274,14 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
}
QList<int> result;
- int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, keycode));
+ int baseQtKey = keysymToQtKey(sym, modifiers, kb_state, keycode);
if (baseQtKey)
result += (baseQtKey + modifiers);
- xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift");
- xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt");
- xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control");
- xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(xkb_keymap, "Meta");
+ xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Shift");
+ xkb_mod_index_t altMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Alt");
+ xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Control");
+ xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Meta");
Q_ASSERT(shiftMod < 32);
Q_ASSERT(altMod < 32);
@@ -1425,7 +1315,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
continue;
Qt::KeyboardModifiers mods = modifiers & ~neededMods;
- qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, keycode));
+ qtKey = keysymToQtKey(sym, mods, kb_state, keycode);
if (!qtKey || qtKey == baseQtKey)
continue;
@@ -1446,77 +1336,88 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
}
xkb_state_unref(kb_state);
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 i = 0;
- while (KeyTbl[i]) {
- if (key == KeyTbl[i]) {
- code = (int)KeyTbl[i+1];
- break;
+ int qtKey = 0;
+
+ // lookup from direct mapping
+ if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
+ // function keys
+ 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) {
// 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)) {
- code = Qt::Key_Meta;
- } else if (rmod_masks.meta == rmod_masks.hyper && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
- code = Qt::Key_Meta;
+ if (rmod_masks.meta == rmod_masks.super && (qtKey == Qt::Key_Super_L
+ || qtKey == Qt::Key_Super_R)) {
+ qtKey = 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;
-}
-
-int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) const
-{
- int code = 0;
-#ifndef QT_NO_TEXTCODEC
- QTextCodec *systemCodec = QTextCodec::codecForLocale();
-#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);
+ if (Q_UNLIKELY(lcQpaKeyboard().isDebugEnabled())) {
+ char keysymName[64];
+ xkb_keysym_get_name(keysym, keysymName, sizeof(keysymName));
+ QString keysymInHex = QString(QStringLiteral("0x%1")).arg(keysym, 0, 16);
+ if (qtKeyName(qtKey)) {
+ qCDebug(lcQpaKeyboard).nospace() << "keysym: " << keysymName << "("
+ << keysymInHex << ") mapped to Qt::" << qtKeyName(qtKey) << " | text: " << text
+ << " | qt key: " << qtKey << " mapped from unicode number: " << fromUnicode;
} 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)
: QXcbObject(connection)
{
- memset(&xkb_names, 0, sizeof(xkb_names));
#if QT_CONFIG(xkb)
core_device_id = 0;
if (connection->hasXKB()) {
@@ -1539,12 +1440,8 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
QXcbKeyboard::~QXcbKeyboard()
{
- xkb_state_unref(xkb_state);
- xkb_keymap_unref(xkb_keymap);
- xkb_context_unref(xkb_context);
if (!connection()->hasXKB())
xcb_key_symbols_free(m_key_symbols);
- clearXKBConfig();
}
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
// 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
- struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
- if (!kb_state)
+ ScopedXKBState xkbState(xkb_state_new(m_xkbKeymap.get()));
+ if (!xkbState)
return;
- updateXKBStateFromState(kb_state, state);
+ updateXKBStateFromState(xkbState.get(), state);
- xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
- QString string = lookupString(kb_state, code);
+ xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState.get(), 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);
- xcb_keysym_t translatedSym = XKB_KEY_NoSymbol;
- if (modifiers & Qt::ControlModifier && !isLatin(sym))
- translatedSym = lookupLatinKeysym(code);
- if (translatedSym == XKB_KEY_NoSymbol)
- translatedSym = sym;
- int qtcode = keysymToQtKey(translatedSym, modifiers, string);
+ if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9)
+ modifiers |= Qt::KeypadModifier;
+
+ // Note 1: All standard key sequences on linux (as defined in platform theme)
+ // that use a latin character also contain a control modifier, which is why
+ // 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;
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,
code, sym, state, string, isAutoRepeat);
}
- xkb_state_unref(kb_state);
}
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);
}
+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)
{
handleKeyEvent(event->event, QEvent::KeyPress, event->detail, event->state, event->time);
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 5cb91ed315..736b32a2fd 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -88,15 +88,12 @@ protected:
void resolveMaskConflicts();
QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;
- int keysymToQtKey(xcb_keysym_t keysym) const;
- int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) const;
- void printKeymapError(const char *error) const;
+ QString lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const;
+ int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ struct xkb_state *state, xcb_keycode_t code) const;
- void readXKBConfig();
- void clearXKBConfig();
-#if QT_CONFIG(xcb_xlib)
struct xkb_keymap *keymapFromCore();
-#endif
+
// when XKEYBOARD not present on the X server
void updateModifiers();
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
@@ -112,14 +109,8 @@ private:
void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
bool m_config = false;
- bool m_keymap_is_core = false;
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 {
uint alt;
uint altgr;
@@ -152,7 +143,19 @@ private:
struct XKBStateDeleter {
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 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
diff --git a/src/plugins/platforms/xcb/qxcbxkbcommon.h b/src/plugins/platforms/xcb/qxcbxkbcommon.h
new file mode 100644
index 0000000000..422c0c0f12
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbxkbcommon.h
@@ -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
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index 00cce13fd0..ffc8a29116 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -46,7 +46,8 @@ HEADERS = \
qxcbcursor.h \
qxcbimage.h \
qxcbxsettings.h \
- qxcbsystemtraytracker.h
+ qxcbsystemtraytracker.h \
+ qxcbxkbcommon.h
load(qt_build_paths)
diff --git a/tests/auto/corelib/global/qglobal/qglobal.c b/tests/auto/corelib/global/qglobal/qglobal.c
index af42efa7f6..0719c4b921 100644
--- a/tests/auto/corelib/global/qglobal/qglobal.c
+++ b/tests/auto/corelib/global/qglobal/qglobal.c
@@ -110,7 +110,7 @@ Q_STATIC_ASSERT(!!1);
static thread_local int gt_var;
void thread_local_test()
{
- thread_local int t_var;
+ static thread_local int t_var;
t_var = gt_var;
}
#endif