[packages/keepassx] - restore git.patch and qt5 support (the freezez with qt4 are still there) - rel 2
baggins
baggins at pld-linux.org
Wed Apr 20 20:07:22 CEST 2016
commit 6a4b7e5574a9da380dea7179ab1d87cb43c5713d
Author: Jan Rękorajski <baggins at pld-linux.org>
Date: Wed Apr 20 20:06:38 2016 +0200
- restore git.patch and qt5 support (the freezez with qt4 are still there)
- rel 2
git.patch | 12915 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
keepassx.spec | 6 +-
2 files changed, 12919 insertions(+), 2 deletions(-)
---
diff --git a/keepassx.spec b/keepassx.spec
index e02a43f..212610b 100644
--- a/keepassx.spec
+++ b/keepassx.spec
@@ -2,11 +2,12 @@ Summary: KeePassX - Cross Platform Password Manager
Summary(pl.UTF-8): KeePassX - Wieloplatformowy zarządca haseł
Name: keepassx
Version: 2.0.2
-Release: 1
+Release: 2
License: GPL v2+
Group: X11/Applications
Source0: http://www.keepassx.org/releases/%{version}/keepassx-%{version}.tar.gz
# Source0-md5: 65d098dff663768911847a1e92d0f01d
+Patch0: git.patch
URL: https://www.keepassx.org/
BuildRequires: Qt5Concurrent-devel >= 5.2.0
BuildRequires: Qt5Core-devel >= 5.2.0
@@ -51,6 +52,7 @@ szyfrowania jakie są do tej pory znane (AES i TwoFish).
%prep
%setup -q
+%patch0 -p1
%build
install -d build
@@ -93,7 +95,7 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/keepassx/icons
%dir %{_datadir}/keepassx/translations
%dir %{_libdir}/keepassx
-%attr(755,root,root) %{_libdir}/keepassx/libkeepassx-autotype-x11.so
+%attr(755,root,root) %{_libdir}/keepassx/libkeepassx-autotype-xcb.so
%{_iconsdir}/hicolor/*x*/apps/keepassx.png
%{_iconsdir}/hicolor/*x*/mimetypes/application-x-keepassx.png
%{_iconsdir}/hicolor/scalable/apps/keepassx.svgz
diff --git a/git.patch b/git.patch
new file mode 100644
index 0000000..6be8810
--- /dev/null
+++ b/git.patch
@@ -0,0 +1,12915 @@
+diff --git a/.travis.yml b/.travis.yml
+index fa33cf0..550518a 100644
+--- a/.travis.yml
++++ b/.travis.yml
+@@ -5,16 +5,20 @@ compiler:
+ - gcc
+ - clang
+ language: cpp
++sudo: required
++dist: trusty
+ install:
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update; fi
+- - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libqt4-dev libgcrypt11-dev zlib1g-dev libxtst-dev; fi
++ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev libxtst-dev xvfb; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq cmake || brew install cmake; fi
+- - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt || brew install qt; fi
++ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt5 || brew install qt5; fi
+ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq libgcrypt || brew install libgcrypt; fi
+-before_script: mkdir build && pushd build
++before_script:
++ - if [ "$TRAVIS_OS_NAME" = "osx" ]; then CMAKE_ARGS="-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5"; fi
++ - mkdir build && pushd build
+ script:
+- - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON ..
++ - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON $CMAKE_ARGS ..
+ - make
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then make test ARGS+="-E testgui --output-on-failure"; fi
+ - if [ "$TRAVIS_OS_NAME" = "linux" ]; then xvfb-run -a --server-args="-screen 0 800x600x24" make test ARGS+="-R testgui --output-on-failure"; fi
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 6df5503..21c46fa 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -21,7 +21,7 @@ endif()
+
+ project(KeePassX)
+
+-cmake_minimum_required(VERSION 2.6.4)
++cmake_minimum_required(VERSION 2.8.12)
+
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+@@ -31,7 +31,7 @@ include(CheckCXXSourceCompiles)
+
+ option(WITH_TESTS "Enable building of unit tests" ON)
+ option(WITH_GUI_TESTS "Enable building of GUI tests" OFF)
+-option(WITH_CXX11 "Build with the C++ 11 standard" ON)
++option(WITH_DEV_BUILD "Use only for development. Disables/warns about deprecated methods." OFF)
+
+ set(KEEPASSX_VERSION "2.0.2")
+ set(KEEPASSX_VERSION_NUM "2.0.2")
+@@ -61,7 +61,7 @@ macro(add_gcc_compiler_flags FLAGS)
+ add_gcc_compiler_cflags("${FLAGS}")
+ endmacro(add_gcc_compiler_flags)
+
+-add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
++add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
+
+ add_gcc_compiler_flags("-fno-common -fstack-protector --param=ssp-buffer-size=4")
+ add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long")
+@@ -100,14 +100,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro")
+ endif()
+
+-if (WITH_CXX11)
+- add_gcc_compiler_cxxflags("-std=c++0x")
+- add_gcc_compiler_cflags("-ansi")
+- if(APPLE)
+- add_gcc_compiler_cxxflags("-stdlib=libc++")
+- endif()
+-else()
+- add_gcc_compiler_flags("-ansi")
++add_gcc_compiler_cxxflags("-std=c++11")
++
++if(APPLE)
++ add_gcc_compiler_cxxflags("-stdlib=libc++")
++endif()
++
++add_gcc_compiler_cflags("-ansi")
++
++if(WITH_DEV_BUILD)
++ add_definitions(-DQT_DEPRECATED_WARNINGS -DGCRYPT_NO_DEPRECATED)
+ endif()
+
+ if(MINGW)
+@@ -146,19 +148,18 @@ if(WITH_TESTS)
+ enable_testing()
+ endif(WITH_TESTS)
+
+-set(QT_REQUIRED_MODULES QtCore QtGui QtTest)
++find_package(Qt5Core 5.2 REQUIRED)
++find_package(Qt5Concurrent 5.2 REQUIRED)
++find_package(Qt5Widgets 5.2 REQUIRED)
++find_package(Qt5Test 5.2 REQUIRED)
++find_package(Qt5LinguistTools 5.2 REQUIRED)
++set(CMAKE_AUTOMOC ON)
+
+-find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES})
+-include(${QT_USE_FILE})
+ # Debian sets the the build type to None for package builds.
+ # Make sure we don't enable asserts there.
+ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
+
+-find_package(Gcrypt REQUIRED)
+-if(NOT (${GCRYPT_VERSION_STRING} VERSION_LESS "1.6.0"))
+- message(STATUS "Gcrypt ${GCRYPT_VERSION_STRING} supports the SALSA20 cipher")
+- set(GCRYPT_HAS_SALSA20 1)
+-endif()
++find_package(Gcrypt 1.6.0 REQUIRED)
+
+ find_package(ZLIB REQUIRED)
+
+@@ -199,10 +200,7 @@ endif()
+
+ include_directories(SYSTEM ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
+
+-if(NOT (${CMAKE_VERSION} VERSION_LESS 2.8.3))
+- set(PRINT_SUMMARY ON)
+- include(FeatureSummary)
+-endif()
++include(FeatureSummary)
+
+ add_subdirectory(src)
+ add_subdirectory(share)
+diff --git a/README.md b/README.md
+index 326bd4a..0c18ff3 100644
+--- a/README.md
++++ b/README.md
+@@ -49,20 +49,20 @@ Once downloaded, double click on the file to execute the installer.
+ The following tools must exist within your PATH:
+
+ * make
+-* cmake (>= 2.6.4)
+-* g++ or clang++
++* cmake (>= 2.8.12)
++* g++ (>= 4.7) or clang++ (>= 3.0)
+
+ The following libraries are required:
+
+-* Qt 4 (>= 4.6)
+-* libgcrypt
++* Qt 5 (>= 5.2): qtbase and qttools5
++* libgcrypt (>= 1.6)
+ * zlib
+-* libxtst (optional for auto-type on X11)
++* libxtst, qtx11extras (optional for auto-type on X11)
+
+ On Debian you can install them with:
+
+ ```bash
+-sudo apt-get install build-essential cmake libqt4-dev libgcrypt11-dev zlib1g-dev
++sudo apt-get install build-essential cmake qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev
+ ```
+
+ #### Build Steps
+diff --git a/share/translations/CMakeLists.txt b/share/translations/CMakeLists.txt
+index b1aa878..7380750 100644
+--- a/share/translations/CMakeLists.txt
++++ b/share/translations/CMakeLists.txt
+@@ -17,9 +17,9 @@ file(GLOB TRANSLATION_FILES *.ts)
+ get_filename_component(TRANSLATION_EN_ABS keepassx_en.ts ABSOLUTE)
+ list(REMOVE_ITEM TRANSLATION_FILES keepassx_en.ts)
+ list(REMOVE_ITEM TRANSLATION_FILES ${TRANSLATION_EN_ABS})
+-message(STATUS ${TRANSLATION_FILES})
++message(STATUS "${TRANSLATION_FILES}")
+
+-qt4_add_translation(QM_FILES ${TRANSLATION_FILES})
++qt5_add_translation(QM_FILES ${TRANSLATION_FILES})
+
+ install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations)
+ add_custom_target(translations DEPENDS ${QM_FILES})
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index da8b9ec..da35651 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -54,9 +54,6 @@ set(keepassx_SOURCES
+ core/ListDeleter.h
+ core/Metadata.cpp
+ core/PasswordGenerator.cpp
+- core/qlockfile.cpp
+- core/qsavefile.cpp
+- core/qsavefile_p.h
+ core/SignalMultiplexer.cpp
+ core/TimeDelta.cpp
+ core/TimeInfo.cpp
+@@ -64,8 +61,6 @@ set(keepassx_SOURCES
+ core/Tools.cpp
+ core/Translator.cpp
+ core/Uuid.cpp
+- core/qcommandlineoption.cpp
+- core/qcommandlineparser.cpp
+ crypto/Crypto.cpp
+ crypto/CryptoHash.cpp
+ crypto/Random.cpp
+@@ -133,94 +128,10 @@ set(keepassx_SOURCES
+ streams/SymmetricCipherStream.cpp
+ )
+
+-if(NOT GCRYPT_HAS_SALSA20)
+- set(keepassx_SOURCES
+- ${keepassx_SOURCES}
+- crypto/salsa20/ecrypt-config.h
+- crypto/salsa20/ecrypt-machine.h
+- crypto/salsa20/ecrypt-portable.h
+- crypto/salsa20/ecrypt-sync.h
+- crypto/salsa20/salsa20.c
+- crypto/SymmetricCipherSalsa20.cpp
+- )
+-endif()
+-
+-if(UNIX)
+- set(keepassx_SOURCES
+- ${keepassx_SOURCES}
+- core/qlockfile_unix.cpp
+- )
+-elseif(MINGW)
+- set(keepassx_SOURCES
+- ${keepassx_SOURCES}
+- core/qlockfile_win.cpp
+- )
+-endif()
+-
+ set(keepassx_SOURCES_MAINEXE
+ main.cpp
+ )
+
+-set(keepassx_MOC
+- autotype/AutoType.h
+- autotype/AutoTypeSelectDialog.h
+- autotype/AutoTypeSelectView.h
+- autotype/ShortcutWidget.h
+- autotype/WindowSelectComboBox.h
+- core/AutoTypeAssociations.h
+- core/Config.h
+- core/Database.h
+- core/Entry.h
+- core/EntryAttachments.h
+- core/EntryAttributes.h
+- core/Group.h
+- core/InactivityTimer.h
+- core/Metadata.h
+- core/qsavefile.h
+- gui/AboutDialog.h
+- gui/Application.h
+- gui/ChangeMasterKeyWidget.h
+- gui/Clipboard.h
+- gui/DatabaseOpenWidget.h
+- gui/DatabaseRepairWidget.h
+- gui/DatabaseSettingsWidget.h
+- gui/DatabaseTabWidget.h
+- gui/DatabaseWidget.h
+- gui/DatabaseWidgetStateSync.h
+- gui/DialogyWidget.h
+- gui/DragTabBar.h
+- gui/EditWidget.h
+- gui/EditWidgetIcons.h
+- gui/EditWidgetProperties.h
+- gui/IconModels.h
+- gui/KeePass1OpenWidget.h
+- gui/LineEdit.h
+- gui/MainWindow.h
+- gui/PasswordEdit.h
+- gui/PasswordGeneratorWidget.h
+- gui/PasswordComboBox.h
+- gui/SettingsWidget.h
+- gui/SortFilterHideProxyModel.h
+- gui/UnlockDatabaseWidget.h
+- gui/WelcomeWidget.h
+- gui/entry/AutoTypeAssociationsModel.h
+- gui/entry/EditEntryWidget.h
+- gui/entry/EntryAttachmentsModel.h
+- gui/entry/EntryAttributesModel.h
+- gui/entry/EntryHistoryModel.h
+- gui/entry/EntryModel.h
+- gui/entry/EntryView.h
+- gui/group/EditGroupWidget.h
+- gui/group/GroupModel.h
+- gui/group/GroupView.h
+- keys/CompositeKey_p.h
+- streams/HashedBlockStream.h
+- streams/LayeredStream.h
+- streams/qtiocompressor.h
+- streams/StoreDataStream.h
+- streams/SymmetricCipherStream.h
+-)
+-
+ set(keepassx_FORMS
+ gui/AboutDialog.ui
+ gui/ChangeMasterKeyWidget.ui
+@@ -248,17 +159,18 @@ if(MINGW)
+ ${CMAKE_SOURCE_DIR}/share/windows/icon.rc)
+ endif()
+
+-qt4_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
+-qt4_wrap_cpp(keepassx_SOURCES ${keepassx_MOC})
++qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
+
+ add_library(keepassx_core STATIC ${keepassx_SOURCES})
+ set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE)
++target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets)
+
+ add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE})
+ target_link_libraries(${PROGNAME}
+ keepassx_core
+- ${QT_QTCORE_LIBRARY}
+- ${QT_QTGUI_LIBRARY}
++ Qt5::Core
++ Qt5::Concurrent
++ Qt5::Widgets
+ ${GCRYPT_LIBRARIES}
+ ${ZLIB_LIBRARIES})
+
+@@ -276,7 +188,7 @@ install(TARGETS ${PROGNAME}
+
+ add_subdirectory(autotype)
+
+-if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
++if(APPLE)
+ if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib")
+ install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib"
+ DESTINATION "${DATA_INSTALL_DIR}")
+@@ -294,7 +206,7 @@ if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
+ install_qt4_executable(${PROGNAME}.app "qjpeg;qgif;qico;qtaccessiblewidgets")
+ endif()
+
+-if(MINGW AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
++if(MINGW )
+ set(CPACK_GENERATOR "ZIP")
+ set(CPACK_STRIP_FILES ON)
+ set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSX_VERSION_NUM}")
+diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp
+index f1b7e3e..15185b2 100644
+--- a/src/autotype/AutoType.cpp
++++ b/src/autotype/AutoType.cpp
+@@ -32,7 +32,7 @@
+ #include "core/Tools.h"
+ #include "gui/MessageBox.h"
+
+-AutoType* AutoType::m_instance = Q_NULLPTR;
++AutoType* AutoType::m_instance = nullptr;
+
+ AutoType::AutoType(QObject* parent, bool test)
+ : QObject(parent)
+@@ -40,8 +40,8 @@ AutoType::AutoType(QObject* parent, bool test)
+ , m_currentGlobalKey(static_cast<Qt::Key>(0))
+ , m_currentGlobalModifiers(0)
+ , m_pluginLoader(new QPluginLoader(this))
+- , m_plugin(Q_NULLPTR)
+- , m_executor(Q_NULLPTR)
++ , m_plugin(nullptr)
++ , m_executor(nullptr)
+ , m_windowFromGlobal(0)
+ {
+ // prevent crash when the plugin has unresolved symbols
+@@ -49,7 +49,7 @@ AutoType::AutoType(QObject* parent, bool test)
+
+ QString pluginName = "keepassx-autotype-";
+ if (!test) {
+- pluginName += Tools::platform();
++ pluginName += QApplication::platformName();
+ }
+ else {
+ pluginName += "test";
+@@ -68,7 +68,7 @@ AutoType::~AutoType()
+ {
+ if (m_executor) {
+ delete m_executor;
+- m_executor = Q_NULLPTR;
++ m_executor = nullptr;
+ }
+ }
+
+@@ -79,7 +79,7 @@ void AutoType::loadPlugin(const QString& pluginPath)
+ QObject* pluginInstance = m_pluginLoader->instance();
+ if (pluginInstance) {
+ m_plugin = qobject_cast<AutoTypePlatformInterface*>(pluginInstance);
+- m_executor = Q_NULLPTR;
++ m_executor = nullptr;
+
+ if (m_plugin) {
+ if (m_plugin->isAvailable()) {
+@@ -202,11 +202,11 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
+ QString message = tr("Couldn't find an entry that matches the window title:");
+ message.append("\n\n");
+ message.append(windowTitle);
+- MessageBox::information(Q_NULLPTR, tr("Auto-Type - KeePassX"), message);
++ MessageBox::information(nullptr, tr("Auto-Type - KeePassX"), message);
+ }
+ else if ((entryList.size() == 1) && !config()->get("security/autotypeask").toBool()) {
+ m_inAutoType = false;
+- performAutoType(entryList.first(), Q_NULLPTR, sequenceHash[entryList.first()]);
++ performAutoType(entryList.first(), nullptr, sequenceHash[entryList.first()]);
+ }
+ else {
+ m_windowFromGlobal = m_plugin->activeWindow();
+@@ -228,7 +228,7 @@ void AutoType::performAutoTypeFromGlobal(Entry* entry, const QString& sequence)
+ m_plugin->raiseWindow(m_windowFromGlobal);
+
+ m_inAutoType = false;
+- performAutoType(entry, Q_NULLPTR, sequence, m_windowFromGlobal);
++ performAutoType(entry, nullptr, sequence, m_windowFromGlobal);
+ }
+
+ void AutoType::resetInAutoType()
+@@ -242,12 +242,12 @@ void AutoType::unloadPlugin()
+ {
+ if (m_executor) {
+ delete m_executor;
+- m_executor = Q_NULLPTR;
++ m_executor = nullptr;
+ }
+
+ if (m_plugin) {
+ m_plugin->unload();
+- m_plugin = Q_NULLPTR;
++ m_plugin = nullptr;
+ }
+ }
+
+diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h
+index f3d626c..d1c8817 100644
+--- a/src/autotype/AutoType.h
++++ b/src/autotype/AutoType.h
+@@ -22,8 +22,6 @@
+ #include <QStringList>
+ #include <QWidget>
+
+-#include "core/Global.h"
+-
+ class AutoTypeAction;
+ class AutoTypeExecutor;
+ class AutoTypePlatformInterface;
+@@ -37,7 +35,7 @@ class AutoType : public QObject
+
+ public:
+ QStringList windowTitles();
+- void performAutoType(const Entry* entry, QWidget* hideWindow = Q_NULLPTR,
++ void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr,
+ const QString& customSequence = QString(), WId window = 0);
+ bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
+ void unregisterGlobalShortcut();
+@@ -62,7 +60,7 @@ private Q_SLOTS:
+ void unloadPlugin();
+
+ private:
+- explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false);
++ explicit AutoType(QObject* parent = nullptr, bool test = false);
+ ~AutoType();
+ void loadPlugin(const QString& pluginPath);
+ bool parseActions(const QString& sequence, const Entry* entry, QList<AutoTypeAction*>& actions);
+diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h
+index 07e050b..490f0d8 100644
+--- a/src/autotype/AutoTypeAction.h
++++ b/src/autotype/AutoTypeAction.h
+@@ -66,7 +66,7 @@ public:
+ class KEEPASSX_EXPORT AutoTypeClearField : public AutoTypeAction
+ {
+ public:
+- explicit AutoTypeClearField();
++ AutoTypeClearField();
+ AutoTypeAction* clone();
+ void accept(AutoTypeExecutor* executor);
+ };
+diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h
+index 4f455c7..c0dbfe4 100644
+--- a/src/autotype/AutoTypeSelectDialog.h
++++ b/src/autotype/AutoTypeSelectDialog.h
+@@ -22,8 +22,6 @@
+ #include <QDialog>
+ #include <QHash>
+
+-#include "core/Global.h"
+-
+ class AutoTypeSelectView;
+ class Entry;
+
+@@ -32,7 +30,7 @@ class AutoTypeSelectDialog : public QDialog
+ Q_OBJECT
+
+ public:
+- explicit AutoTypeSelectDialog(QWidget* parent = Q_NULLPTR);
++ explicit AutoTypeSelectDialog(QWidget* parent = nullptr);
+ void setEntries(const QList<Entry*>& entries, const QHash<Entry*, QString>& sequences);
+
+ Q_SIGNALS:
+diff --git a/src/autotype/AutoTypeSelectView.h b/src/autotype/AutoTypeSelectView.h
+index bcbb262..749f6a9 100644
+--- a/src/autotype/AutoTypeSelectView.h
++++ b/src/autotype/AutoTypeSelectView.h
+@@ -18,7 +18,6 @@
+ #ifndef KEEPASSX_AUTOTYPESELECTVIEW_H
+ #define KEEPASSX_AUTOTYPESELECTVIEW_H
+
+-#include "core/Global.h"
+ #include "gui/entry/EntryView.h"
+
+ class Entry;
+@@ -28,10 +27,10 @@ class AutoTypeSelectView : public EntryView
+ Q_OBJECT
+
+ public:
+- explicit AutoTypeSelectView(QWidget* parent = Q_NULLPTR);
++ explicit AutoTypeSelectView(QWidget* parent = nullptr);
+
+ protected:
+- void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
++ void mouseMoveEvent(QMouseEvent* event) override;
+
+ private Q_SLOTS:
+ void selectFirstEntry();
+diff --git a/src/autotype/CMakeLists.txt b/src/autotype/CMakeLists.txt
+index a0f7877..707edf9 100644
+--- a/src/autotype/CMakeLists.txt
++++ b/src/autotype/CMakeLists.txt
+@@ -1,12 +1,12 @@
+-if(Q_WS_X11)
++if(UNIX AND NOT APPLE)
+ find_package(X11)
+- if(PRINT_SUMMARY)
+- add_feature_info(libXi X11_Xi_FOUND "The X11 Xi Protocol library is required for auto-type")
+- add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
+- endif()
++ find_package(Qt5X11Extras 5.2)
++ add_feature_info(libXi X11_Xi_FOUND "The X11 Xi Protocol library is required for auto-type")
++ add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
++ add_feature_info(Qt5X11Extras Qt5X11Extras_FOUND "The Qt5X11Extras library is required for auto-type")
+
+- if(X11_FOUND AND X11_Xi_FOUND AND X11_XTest_FOUND)
+- add_subdirectory(x11)
++ if(X11_FOUND AND X11_Xi_FOUND AND X11_XTest_FOUND AND Qt5X11Extras_FOUND)
++ add_subdirectory(xcb)
+ endif()
+ endif()
+
+diff --git a/src/autotype/ShortcutWidget.h b/src/autotype/ShortcutWidget.h
+index 5ff306c..60898ab 100644
+--- a/src/autotype/ShortcutWidget.h
++++ b/src/autotype/ShortcutWidget.h
+@@ -20,21 +20,19 @@
+
+ #include <QLineEdit>
+
+-#include "core/Global.h"
+-
+ class ShortcutWidget : public QLineEdit
+ {
+ Q_OBJECT
+
+ public:
+- explicit ShortcutWidget(QWidget* parent = Q_NULLPTR);
++ explicit ShortcutWidget(QWidget* parent = nullptr);
+ Qt::Key key() const;
+ Qt::KeyboardModifiers modifiers() const;
+ void setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
+
+ protected:
+- void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
+- void keyReleaseEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
++ void keyPressEvent(QKeyEvent* event) override;
++ void keyReleaseEvent(QKeyEvent* event) override;
+
+ private:
+ void keyEvent(QKeyEvent* event);
+diff --git a/src/autotype/WindowSelectComboBox.h b/src/autotype/WindowSelectComboBox.h
+index 661bc84..244119a 100644
+--- a/src/autotype/WindowSelectComboBox.h
++++ b/src/autotype/WindowSelectComboBox.h
+@@ -20,19 +20,17 @@
+
+ #include <QComboBox>
+
+-#include "core/Global.h"
+-
+ class WindowSelectComboBox : public QComboBox
+ {
+ Q_OBJECT
+
+ public:
+- explicit WindowSelectComboBox(QWidget* parent = Q_NULLPTR);
++ explicit WindowSelectComboBox(QWidget* parent = nullptr);
+ void refreshWindowList();
+
+- void showPopup() Q_DECL_OVERRIDE;
+- QSize sizeHint() const Q_DECL_OVERRIDE;
+- QSize minimumSizeHint() const Q_DECL_OVERRIDE;
++ void showPopup() override;
++ QSize sizeHint() const override;
++ QSize minimumSizeHint() const override;
+ };
+
+ #endif // KEEPASSX_WINDOWSELECTCOMBOBOX_H
+diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp
+index a8bcc71..979af8b 100644
+--- a/src/autotype/test/AutoTypeTest.cpp
++++ b/src/autotype/test/AutoTypeTest.cpp
+@@ -129,5 +129,3 @@ void AutoTypeExecturorTest::execKey(AutoTypeKey* action)
+ {
+ m_platform->addActionKey(action);
+ }
+-
+-Q_EXPORT_PLUGIN2(keepassx-autotype-test, AutoTypePlatformTest)
+diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h
+index c791c15..8c6e524 100644
+--- a/src/autotype/test/AutoTypeTest.h
++++ b/src/autotype/test/AutoTypeTest.h
+@@ -23,34 +23,34 @@
+ #include "autotype/AutoTypePlatformPlugin.h"
+ #include "autotype/AutoTypeAction.h"
+ #include "autotype/test/AutoTypeTestInterface.h"
+-#include "core/Global.h"
+
+ class AutoTypePlatformTest : public QObject,
+ public AutoTypePlatformInterface,
+ public AutoTypeTestInterface
+ {
+ Q_OBJECT
++ Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface")
+ Q_INTERFACES(AutoTypePlatformInterface AutoTypeTestInterface)
+
+ public:
+- QString keyToString(Qt::Key key) Q_DECL_OVERRIDE;
++ QString keyToString(Qt::Key key) override;
+
+- bool isAvailable() Q_DECL_OVERRIDE;
+- QStringList windowTitles() Q_DECL_OVERRIDE;
+- WId activeWindow() Q_DECL_OVERRIDE;
+- QString activeWindowTitle() Q_DECL_OVERRIDE;
+- bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- int platformEventFilter(void* event) Q_DECL_OVERRIDE;
+- int initialTimeout() Q_DECL_OVERRIDE;
+- bool raiseWindow(WId window) Q_DECL_OVERRIDE;
+- AutoTypeExecutor* createExecutor() Q_DECL_OVERRIDE;
++ bool isAvailable() override;
++ QStringList windowTitles() override;
++ WId activeWindow() override;
++ QString activeWindowTitle() override;
++ bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ int platformEventFilter(void* event) override;
++ int initialTimeout() override;
++ bool raiseWindow(WId window) override;
++ AutoTypeExecutor* createExecutor() override;
+
+- void setActiveWindowTitle(const QString& title) Q_DECL_OVERRIDE;
++ void setActiveWindowTitle(const QString& title) override;
+
+- QString actionChars() Q_DECL_OVERRIDE;
+- int actionCount() Q_DECL_OVERRIDE;
+- void clearActions() Q_DECL_OVERRIDE;
++ QString actionChars() override;
++ int actionCount() override;
++ void clearActions() override;
+
+ void addActionChar(AutoTypeChar* action);
+ void addActionKey(AutoTypeKey* action);
+@@ -69,8 +69,8 @@ class AutoTypeExecturorTest : public AutoTypeExecutor
+ public:
+ explicit AutoTypeExecturorTest(AutoTypePlatformTest* platform);
+
+- void execChar(AutoTypeChar* action) Q_DECL_OVERRIDE;
+- void execKey(AutoTypeKey* action) Q_DECL_OVERRIDE;
++ void execChar(AutoTypeChar* action) override;
++ void execKey(AutoTypeKey* action) override;
+
+ private:
+ AutoTypePlatformTest* const m_platform;
+diff --git a/src/autotype/test/CMakeLists.txt b/src/autotype/test/CMakeLists.txt
+index 749f7d5..9b3dbd4 100644
+--- a/src/autotype/test/CMakeLists.txt
++++ b/src/autotype/test/CMakeLists.txt
+@@ -2,11 +2,5 @@ set(autotype_test_SOURCES
+ AutoTypeTest.cpp
+ )
+
+-set(autotype_test_MOC
+- AutoTypeTest.h
+-)
+-
+-qt4_wrap_cpp(autotype_test_SOURCES ${autotype_test_MOC})
+-
+ add_library(keepassx-autotype-test MODULE ${autotype_test_SOURCES})
+-target_link_libraries(keepassx-autotype-test testautotype ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
++target_link_libraries(keepassx-autotype-test testautotype Qt5::Core Qt5::Widgets)
+diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/x11/AutoTypeX11.cpp
+deleted file mode 100644
+index 6a20a88..0000000
+--- a/src/autotype/x11/AutoTypeX11.cpp
++++ /dev/null
+@@ -1,850 +0,0 @@
+-/*
+- * Copyright (C) 2012 Felix Geyer <debfx at fobos.de>
+- * Copyright (C) 2000-2008 Tom Sato <VEF00200 at nifty.ne.jp>
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation, either version 2 or (at your option)
+- * version 3 of the License.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+- */
+-
+-#include "AutoTypeX11.h"
+-#include "KeySymMap.h"
+-
+-#include <time.h>
+-
+-bool AutoTypePlatformX11::m_catchXErrors = false;
+-bool AutoTypePlatformX11::m_xErrorOccured = false;
+-int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = Q_NULLPTR;
+-
+-AutoTypePlatformX11::AutoTypePlatformX11()
+-{
+- m_dpy = QX11Info::display();
+- m_rootWindow = QX11Info::appRootWindow();
+-
+- m_atomWmState = XInternAtom(m_dpy, "WM_STATE", True);
+- m_atomWmName = XInternAtom(m_dpy, "WM_NAME", True);
+- m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", True);
+- m_atomString = XInternAtom(m_dpy, "STRING", True);
+- m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
+- m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
+-
+- m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
+- m_classBlacklist << "kdesktop" << "kicker"; // KDE 3
+- m_classBlacklist << "Plasma"; // KDE 4
+- m_classBlacklist << "plasmashell"; // KDE 5
+- m_classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
+-
+- m_currentGlobalKey = static_cast<Qt::Key>(0);
+- m_currentGlobalModifiers = 0;
+-
+- m_keysymTable = Q_NULLPTR;
+- m_xkb = Q_NULLPTR;
+- m_remapKeycode = 0;
+- m_currentRemapKeysym = NoSymbol;
+- m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
+-
+- m_loaded = true;
+-
+- updateKeymap();
+-}
+-
+-bool AutoTypePlatformX11::isAvailable()
+-{
+- int ignore;
+-
+- if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) {
+- return false;
+- }
+-
+- if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) {
+- return false;
+- }
+-
+- if (!m_xkb) {
+- XkbDescPtr kbd = getKeyboard();
+-
+- if (!kbd) {
+- return false;
+- }
+-
+- XkbFreeKeyboard(kbd, XkbAllComponentsMask, True);
+- }
+-
+- return true;
+-}
+-
+-void AutoTypePlatformX11::unload()
+-{
+- // Restore the KeyboardMapping to its original state.
+- if (m_currentRemapKeysym != NoSymbol) {
+- AddKeysym(NoSymbol);
+- }
+-
+- if (m_keysymTable) {
+- XFree(m_keysymTable);
+- }
+-
+- if (m_xkb) {
+- XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
+- }
+-
+- m_loaded = false;
+-}
+-
+-QStringList AutoTypePlatformX11::windowTitles()
+-{
+- return windowTitlesRecursive(m_rootWindow);
+-}
+-
+-WId AutoTypePlatformX11::activeWindow()
+-{
+- Window window;
+- int revert_to_return;
+- XGetInputFocus(m_dpy, &window, &revert_to_return);
+-
+- int tree;
+- do {
+- if (isTopLevelWindow(window)) {
+- break;
+- }
+-
+- Window root;
+- Window parent;
+- Window* children = Q_NULLPTR;
+- unsigned int numChildren;
+- tree = XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren);
+- window = parent;
+- if (children) {
+- XFree(children);
+- }
+- } while (tree && window);
+-
+- return window;
+-}
+-
+-QString AutoTypePlatformX11::activeWindowTitle()
+-{
+- return windowTitle(activeWindow(), true);
+-}
+-
+-bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
+-{
+- int keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
+- uint nativeModifiers = qtToNativeModifiers(modifiers);
+-
+- startCatchXErrors();
+- XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
+- XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync,
+- GrabModeAsync);
+- XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync,
+- GrabModeAsync);
+- XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
+- GrabModeAsync, GrabModeAsync);
+- stopCatchXErrors();
+-
+- if (!m_xErrorOccured) {
+- m_currentGlobalKey = key;
+- m_currentGlobalModifiers = modifiers;
+- m_currentGlobalKeycode = keycode;
+- m_currentGlobalNativeModifiers = nativeModifiers;
+- return true;
+- }
+- else {
+- unregisterGlobalShortcut(key, modifiers);
+- return false;
+- }
+-}
+-
+-uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
+-{
+- uint nativeModifiers = 0;
+-
+- if (modifiers & Qt::ShiftModifier) {
+- nativeModifiers |= ShiftMask;
+- }
+- if (modifiers & Qt::ControlModifier) {
+- nativeModifiers |= ControlMask;
+- }
+- if (modifiers & Qt::AltModifier) {
+- nativeModifiers |= Mod1Mask;
+- }
+- if (modifiers & Qt::MetaModifier) {
+- nativeModifiers |= Mod4Mask;
+- }
+-
+- return nativeModifiers;
+-}
+-
+-void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
+-{
+- KeyCode keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
+- uint nativeModifiers = qtToNativeModifiers(modifiers);
+-
+- XUngrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow);
+- XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow);
+- XUngrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow);
+- XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow);
+-
+- m_currentGlobalKey = static_cast<Qt::Key>(0);
+- m_currentGlobalModifiers = 0;
+- m_currentGlobalKeycode = 0;
+- m_currentGlobalNativeModifiers = 0;
+-}
+-
+-int AutoTypePlatformX11::platformEventFilter(void* event)
+-{
+- XEvent* xevent = static_cast<XEvent*>(event);
+-
+- if ((xevent->type == KeyPress || xevent->type == KeyRelease)
+- && m_currentGlobalKey
+- && xevent->xkey.keycode == m_currentGlobalKeycode
+- && (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers
+- && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
+- && m_loaded) {
+- if (xevent->type == KeyPress) {
+- Q_EMIT globalShortcutTriggered();
+- }
+- return 1;
+- }
+- if (xevent->type == MappingNotify && m_loaded) {
+- XRefreshKeyboardMapping(reinterpret_cast<XMappingEvent*>(xevent));
+- updateKeymap();
+- }
+-
+- return -1;
+-}
+-
+-AutoTypeExecutor* AutoTypePlatformX11::createExecutor()
+-{
+- return new AutoTypeExecturorX11(this);
+-}
+-
+-QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
+-{
+- QString title;
+-
+- Atom type;
+- int format;
+- unsigned long nitems;
+- unsigned long after;
+- unsigned char* data = Q_NULLPTR;
+-
+- // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME
+-
+- int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String,
+- &type, &format, &nitems, &after, &data);
+-
+- if ((retVal == 0) && data) {
+- title = QString::fromUtf8(reinterpret_cast<char*>(data));
+- }
+- else {
+- XTextProperty textProp;
+- retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
+- if ((retVal != 0) && textProp.value) {
+- char** textList = Q_NULLPTR;
+- int count;
+-
+- if (textProp.encoding == m_atomUtf8String) {
+- title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
+- }
+- else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0)
+- && textList && (count > 0)) {
+- title = QString::fromLocal8Bit(textList[0]);
+- }
+- else if (textProp.encoding == m_atomString) {
+- title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
+- }
+-
+- if (textList) {
+- XFreeStringList(textList);
+- }
+- }
+-
+- if (textProp.value) {
+- XFree(textProp.value);
+- }
+- }
+-
+- if (data) {
+- XFree(data);
+- }
+-
+- if (useBlacklist && !title.isEmpty()) {
+- if (window == m_rootWindow) {
+- return QString();
+- }
+-
+- QString className = windowClassName(window);
+- if (m_classBlacklist.contains(className)) {
+- return QString();
+- }
+-
+- QList<Window> keepassxWindows = widgetsToX11Windows(QApplication::topLevelWidgets());
+- if (keepassxWindows.contains(window)) {
+- return QString();
+- }
+- }
+-
+- return title;
+-}
+-
+-QString AutoTypePlatformX11::windowClassName(Window window)
+-{
+- QString className;
+-
+- XClassHint wmClass;
+- wmClass.res_name = Q_NULLPTR;
+- wmClass.res_class = Q_NULLPTR;
+-
+- if (XGetClassHint(m_dpy, window, &wmClass) && wmClass.res_name) {
+- className = QString::fromLocal8Bit(wmClass.res_name);
+- }
+- if (wmClass.res_name) {
+- XFree(wmClass.res_name);
+- }
+- if (wmClass.res_class) {
+- XFree(wmClass.res_class);
+- }
+-
+- return className;
+-}
+-
+-QList<Window> AutoTypePlatformX11::widgetsToX11Windows(const QWidgetList& widgetList)
+-{
+- QList<Window> windows;
+-
+- Q_FOREACH (const QWidget* widget, widgetList) {
+- windows.append(widget->effectiveWinId());
+- }
+-
+- return windows;
+-}
+-
+-QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window)
+-{
+- QStringList titles;
+-
+- if (isTopLevelWindow(window)) {
+- QString title = windowTitle(window, true);
+- if (!title.isEmpty()) {
+- titles.append(title);
+- }
+- }
+-
+- Window root;
+- Window parent;
+- Window* children = Q_NULLPTR;
+- unsigned int numChildren;
+- if (XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren) && children) {
+- for (uint i = 0; i < numChildren; i++) {
+- titles.append(windowTitlesRecursive(children[i]));
+- }
+- }
+- if (children) {
+- XFree(children);
+- }
+-
+- return titles;
+-}
+-
+-bool AutoTypePlatformX11::isTopLevelWindow(Window window)
+-{
+- Atom type = None;
+- int format;
+- unsigned long nitems;
+- unsigned long after;
+- unsigned char* data = Q_NULLPTR;
+- int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, False, AnyPropertyType, &type, &format,
+- &nitems, &after, &data);
+- if (data) {
+- XFree(data);
+- }
+-
+- return (retVal == 0) && type;
+-}
+-
+-KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
+-{
+- ushort unicode = ch.unicode();
+-
+- /* first check for Latin-1 characters (1:1 mapping) */
+- if ((unicode >= 0x0020 && unicode <= 0x007e)
+- || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
+- return unicode;
+- }
+-
+- /* mapping table generated from keysymdef.h */
+- const uint* match = qBinaryFind(m_unicodeToKeysymKeys,
+- m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
+- unicode);
+- int index = match - m_unicodeToKeysymKeys;
+- if (index != m_unicodeToKeysymLen) {
+- return m_unicodeToKeysymValues[index];
+- }
+-
+- if (unicode >= 0x0100) {
+- return unicode | 0x01000000;
+- }
+-
+- return NoSymbol;
+-}
+-
+-KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
+-{
+- switch (key) {
+- case Qt::Key_Tab:
+- return XK_Tab;
+- case Qt::Key_Enter:
+- return XK_Return;
+- case Qt::Key_Up:
+- return XK_Up;
+- case Qt::Key_Down:
+- return XK_Down;
+- case Qt::Key_Left:
+- return XK_Left;
+- case Qt::Key_Right:
+- return XK_Right;
+- case Qt::Key_Insert:
+- return XK_Insert;
+- case Qt::Key_Delete:
+- return XK_Delete;
+- case Qt::Key_Home:
+- return XK_Home;
+- case Qt::Key_End:
+- return XK_End;
+- case Qt::Key_PageUp:
+- return XK_Page_Up;
+- case Qt::Key_PageDown:
+- return XK_Page_Down;
+- case Qt::Key_Backspace:
+- return XK_BackSpace;
+- case Qt::Key_Pause:
+- return XK_Break;
+- case Qt::Key_CapsLock:
+- return XK_Caps_Lock;
+- case Qt::Key_Escape:
+- return XK_Escape;
+- case Qt::Key_Help:
+- return XK_Help;
+- case Qt::Key_NumLock:
+- return XK_Num_Lock;
+- case Qt::Key_Print:
+- return XK_Print;
+- case Qt::Key_ScrollLock:
+- return XK_Scroll_Lock;
+- default:
+- if (key >= Qt::Key_F1 && key <= Qt::Key_F16) {
+- return XK_F1 + (key - Qt::Key_F1);
+- }
+- else {
+- return NoSymbol;
+- }
+- }
+-}
+-
+-/*
+- * Update the keyboard and modifier mapping.
+- * We need the KeyboardMapping for AddKeysym.
+- * Modifier mapping is required for clearing the modifiers.
+- */
+-void AutoTypePlatformX11::updateKeymap()
+-{
+- int keycode, inx;
+- int mod_index, mod_key;
+- XModifierKeymap *modifiers;
+-
+- if (m_xkb) {
+- XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
+- }
+- m_xkb = getKeyboard();
+-
+- XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
+- if (m_keysymTable != NULL) XFree(m_keysymTable);
+- m_keysymTable = XGetKeyboardMapping(m_dpy,
+- m_minKeycode, m_maxKeycode - m_minKeycode + 1,
+- &m_keysymPerKeycode);
+-
+- /* determine the keycode to use for remapped keys */
+- inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
+- if (m_remapKeycode == 0 || !isRemapKeycodeValid()) {
+- for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
+- inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
+- if (m_keysymTable[inx] == NoSymbol) {
+- m_remapKeycode = keycode;
+- m_currentRemapKeysym = NoSymbol;
+- break;
+- }
+- }
+- }
+-
+- /* determine the keycode to use for modifiers */
+- modifiers = XGetModifierMapping(m_dpy);
+- for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
+- m_modifier_keycode[mod_index] = 0;
+- for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
+- keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
+- if (keycode) {
+- m_modifier_keycode[mod_index] = keycode;
+- break;
+- }
+- }
+- }
+- XFreeModifiermap(modifiers);
+-
+- /* Xlib needs some time until the mapping is distributed to
+- all clients */
+- // TODO: we should probably only sleep while in the middle of typing something
+- timespec ts;
+- ts.tv_sec = 0;
+- ts.tv_nsec = 30 * 1000 * 1000;
+- nanosleep(&ts, Q_NULLPTR);
+-}
+-
+-bool AutoTypePlatformX11::isRemapKeycodeValid()
+-{
+- int baseKeycode = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
+- for (int i = 0; i < m_keysymPerKeycode; i++) {
+- if (m_keysymTable[baseKeycode + i] == m_currentRemapKeysym) {
+- return true;
+- }
+- }
+-
+- return false;
+-}
+-
+-void AutoTypePlatformX11::startCatchXErrors()
+-{
+- Q_ASSERT(!m_catchXErrors);
+-
+- m_catchXErrors = true;
+- m_xErrorOccured = false;
+- m_oldXErrorHandler = XSetErrorHandler(x11ErrorHandler);
+-}
+-
+-void AutoTypePlatformX11::stopCatchXErrors()
+-{
+- Q_ASSERT(m_catchXErrors);
+-
+- XSync(m_dpy, False);
+- XSetErrorHandler(m_oldXErrorHandler);
+- m_catchXErrors = false;
+-}
+-
+-int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
+-{
+- Q_UNUSED(display)
+- Q_UNUSED(error)
+-
+- if (m_catchXErrors) {
+- m_xErrorOccured = true;
+- }
+-
+- return 1;
+-}
+-
+-XkbDescPtr AutoTypePlatformX11::getKeyboard()
+-{
+- int num_devices;
+- XID keyboard_id = XkbUseCoreKbd;
+- XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices);
+- if (!devices) {
+- return Q_NULLPTR;
+- }
+-
+- for (int i = 0; i < num_devices; i++) {
+- if (QString(devices[i].name) == "Virtual core XTEST keyboard") {
+- keyboard_id = devices[i].id;
+- break;
+- }
+- }
+-
+- XFreeDeviceList(devices);
+-
+- return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id);
+-}
+-
+-// --------------------------------------------------------------------------
+-// The following code is taken from xvkbd 3.0 and has been slightly modified.
+-// --------------------------------------------------------------------------
+-
+-/*
+- * Insert a specified keysym on the dedicated position in the keymap
+- * table.
+- */
+-int AutoTypePlatformX11::AddKeysym(KeySym keysym)
+-{
+- if (m_remapKeycode == 0) {
+- return 0;
+- }
+-
+- int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
+- m_keysymTable[inx] = keysym;
+- m_currentRemapKeysym = keysym;
+-
+- XChangeKeyboardMapping(m_dpy, m_remapKeycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
+- XFlush(m_dpy);
+- updateKeymap();
+-
+- return m_remapKeycode;
+-}
+-
+-/*
+- * Send event to the focused window.
+- * If input focus is specified explicitly, select the window
+- * before send event to the window.
+- */
+-void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
+-{
+- XSync(event->display, False);
+- int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
+-
+- event->type = event_type;
+- Bool press;
+- if (event->type == KeyPress) {
+- press = True;
+- }
+- else {
+- press = False;
+- }
+- XTestFakeKeyEvent(event->display, event->keycode, press, 0);
+- XFlush(event->display);
+-
+- XSetErrorHandler(oldHandler);
+-}
+-
+-/*
+- * Send a modifier press/release event for all modifiers
+- * which are set in the mask variable.
+- */
+-void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
+-{
+- int mod_index;
+- for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
+- if (mask & (1 << mod_index)) {
+- event->keycode = m_modifier_keycode[mod_index];
+- SendEvent(event, event_type);
+- if (event_type == KeyPress)
+- event->state |= (1 << mod_index);
+- else
+- event->state &= (1 << mod_index);
+- }
+- }
+-}
+-
+-/*
+- * Determines the keycode and modifier mask for the given
+- * keysym.
+- */
+-int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
+-{
+- int keycode = XKeysymToKeycode(m_dpy, keysym);
+-
+- if (keycode && keysymModifiers(keysym, keycode, mask)) {
+- return keycode;
+- }
+-
+- /* no modifier matches => resort to remapping */
+- keycode = AddKeysym(keysym);
+- if (keycode && keysymModifiers(keysym, keycode, mask)) {
+- return keycode;
+- }
+-
+- *mask = 0;
+- return 0;
+-}
+-
+-bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
+-{
+- int shift, mod;
+- unsigned int mods_rtrn;
+-
+- /* determine whether there is a combination of the modifiers
+- (Mod1-Mod5) with or without shift which returns keysym */
+- for (shift = 0; shift < 2; shift ++) {
+- for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
+- KeySym keysym_rtrn;
+- *mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
+- XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
+- if (keysym_rtrn == keysym) {
+- return true;
+- }
+- }
+- }
+-
+- return false;
+-}
+-
+-
+-
+-/*
+- * Send sequence of KeyPressed/KeyReleased events to the focused
+- * window to simulate keyboard. If modifiers (shift, control, etc)
+- * are set ON, many events will be sent.
+- */
+-void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
+-{
+- Window cur_focus;
+- int revert_to;
+- XKeyEvent event;
+- int keycode;
+-
+- if (keysym == NoSymbol) {
+- qWarning("No such key: keysym=0x%lX", keysym);
+- return;
+- }
+-
+- XGetInputFocus(m_dpy, &cur_focus, &revert_to);
+-
+- event.display = m_dpy;
+- event.window = cur_focus;
+- event.root = m_rootWindow;
+- event.subwindow = None;
+- event.time = CurrentTime;
+- event.x = 1;
+- event.y = 1;
+- event.x_root = 1;
+- event.y_root = 1;
+- event.same_screen = TRUE;
+-
+- Window root, child;
+- int root_x, root_y, x, y;
+- unsigned int wanted_mask = 0;
+- unsigned int original_mask;
+-
+- XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &original_mask);
+-
+- /* determine keycode and mask for the given keysym */
+- keycode = GetKeycode(keysym, &wanted_mask);
+- if (keycode < 8 || keycode > 255) {
+- qWarning("Unable to get valid keycode for key: keysym=0x%lX", keysym);
+- return;
+- }
+-
+- event.state = original_mask;
+-
+- // modifiers that need to be pressed but aren't
+- unsigned int press_mask = wanted_mask & ~original_mask;
+-
+- // modifiers that are pressed but maybe shouldn't
+- unsigned int release_check_mask = original_mask & ~wanted_mask;
+-
+- // modifiers we need to release before sending the keycode
+- unsigned int release_mask = 0;
+-
+- // check every release_check_mask individually if it affects the keysym we would generate
+- // if it doesn't we probably don't need to release it
+- for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
+- if (release_check_mask & (1 << mod_index)) {
+- unsigned int mods_rtrn;
+- KeySym keysym_rtrn;
+- XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (1 << mod_index), &mods_rtrn, &keysym_rtrn);
+-
+- if (keysym_rtrn != keysym) {
+- release_mask |= (1 << mod_index);
+- }
+- }
+- }
+-
+- // finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
+- unsigned int mods_rtrn;
+- KeySym keysym_rtrn;
+- XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
+- if (keysym_rtrn != keysym) {
+- // oh well, release all the modifiers we don't want
+- release_mask = release_check_mask;
+- }
+-
+- /* release all modifiers */
+- SendModifier(&event, release_mask, KeyRelease);
+-
+- SendModifier(&event, press_mask, KeyPress);
+-
+- /* press and release key */
+- event.keycode = keycode;
+- SendEvent(&event, KeyPress);
+- SendEvent(&event, KeyRelease);
+-
+- /* release the modifiers */
+- SendModifier(&event, press_mask, KeyRelease);
+-
+- /* restore the old keyboard mask */
+- SendModifier(&event, release_mask, KeyPress);
+-}
+-
+-int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
+-{
+- char msg[200];
+-
+- if (event->error_code == BadWindow) {
+- return 0;
+- }
+- XGetErrorText(my_dpy, event->error_code, msg, sizeof(msg) - 1);
+- qWarning("X error trapped: %s, request-code=%d\n", msg, event->request_code);
+- return 0;
+-}
+-
+-
+-AutoTypeExecturorX11::AutoTypeExecturorX11(AutoTypePlatformX11* platform)
+- : m_platform(platform)
+-{
+-}
+-
+-void AutoTypeExecturorX11::execChar(AutoTypeChar* action)
+-{
+- m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
+-}
+-
+-void AutoTypeExecturorX11::execKey(AutoTypeKey* action)
+-{
+- m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
+-}
+-
+-int AutoTypePlatformX11::initialTimeout()
+-{
+- return 500;
+-}
+-
+-bool AutoTypePlatformX11::raiseWindow(WId window)
+-{
+- if (m_atomNetActiveWindow == None) {
+- return false;
+- }
+-
+- XRaiseWindow(m_dpy, window);
+-
+- XEvent event;
+- event.xclient.type = ClientMessage;
+- event.xclient.serial = 0;
+- event.xclient.send_event = True;
+- event.xclient.window = window;
+- event.xclient.message_type = m_atomNetActiveWindow;
+- event.xclient.format = 32;
+- event.xclient.data.l[0] = 1; // FromApplication
+- event.xclient.data.l[1] = QX11Info::appUserTime();
+- QWidget* activeWindow = QApplication::activeWindow();
+- if (activeWindow) {
+- event.xclient.data.l[2] = activeWindow->internalWinId();
+- }
+- else {
+- event.xclient.data.l[2] = 0;
+- }
+- event.xclient.data.l[3] = 0;
+- event.xclient.data.l[4] = 0;
+- XSendEvent(m_dpy, m_rootWindow, False,
+- SubstructureRedirectMask | SubstructureNotifyMask,
+- &event);
+- XFlush(m_dpy);
+-
+- return true;
+-}
+-
+-Q_EXPORT_PLUGIN2(keepassx-autotype-x11, AutoTypePlatformX11)
+diff --git a/src/autotype/x11/AutoTypeX11.h b/src/autotype/x11/AutoTypeX11.h
+deleted file mode 100644
+index 99abb23..0000000
+--- a/src/autotype/x11/AutoTypeX11.h
++++ /dev/null
+@@ -1,134 +0,0 @@
+-/*
+- * Copyright (C) 2012 Felix Geyer <debfx at fobos.de>
+- * Copyright (C) 2000-2008 Tom Sato <VEF00200 at nifty.ne.jp>
+- *
+- * This program is free software: you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation, either version 2 or (at your option)
+- * version 3 of the License.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+- */
+-
+-#ifndef KEEPASSX_AUTOTYPEX11_H
+-#define KEEPASSX_AUTOTYPEX11_H
+-
+-#include <QApplication>
+-#include <QSet>
+-#include <QtPlugin>
+-#include <QWidget>
+-#include <QX11Info>
+-
+-#include <X11/Xutil.h>
+-#include <X11/extensions/XTest.h>
+-#include <X11/XKBlib.h>
+-
+-#include "autotype/AutoTypePlatformPlugin.h"
+-#include "autotype/AutoTypeAction.h"
+-#include "core/Global.h"
+-
+-#define N_MOD_INDICES (Mod5MapIndex + 1)
+-
+-class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
+-{
+- Q_OBJECT
+- Q_INTERFACES(AutoTypePlatformInterface)
+-
+-public:
+- AutoTypePlatformX11();
+- bool isAvailable() Q_DECL_OVERRIDE;
+- void unload() Q_DECL_OVERRIDE;
+- QStringList windowTitles() Q_DECL_OVERRIDE;
+- WId activeWindow() Q_DECL_OVERRIDE;
+- QString activeWindowTitle() Q_DECL_OVERRIDE;
+- bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
+- int platformEventFilter(void* event) Q_DECL_OVERRIDE;
+- int initialTimeout() Q_DECL_OVERRIDE;
+- bool raiseWindow(WId window) Q_DECL_OVERRIDE;
+- AutoTypeExecutor* createExecutor() Q_DECL_OVERRIDE;
+-
+- KeySym charToKeySym(const QChar& ch);
+- KeySym keyToKeySym(Qt::Key key);
+-
+- void SendKeyPressedEvent(KeySym keysym);
+-
+-Q_SIGNALS:
+- void globalShortcutTriggered();
+-
+-private:
+- QString windowTitle(Window window, bool useBlacklist);
+- QStringList windowTitlesRecursive(Window window);
+- QString windowClassName(Window window);
+- QList<Window> widgetsToX11Windows(const QWidgetList& widgetList);
+- bool isTopLevelWindow(Window window);
+- uint qtToNativeModifiers(Qt::KeyboardModifiers modifiers);
+- void startCatchXErrors();
+- void stopCatchXErrors();
+- static int x11ErrorHandler(Display* display, XErrorEvent* error);
+-
+- XkbDescPtr getKeyboard();
+- void updateKeymap();
+- bool isRemapKeycodeValid();
+- int AddKeysym(KeySym keysym);
+- void AddModifier(KeySym keysym);
+- void SendEvent(XKeyEvent* event, int event_type);
+- void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
+- int GetKeycode(KeySym keysym, unsigned int *mask);
+- bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
+-
+- static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
+-
+- Display* m_dpy;
+- Window m_rootWindow;
+- Atom m_atomWmState;
+- Atom m_atomWmName;
+- Atom m_atomNetWmName;
+- Atom m_atomString;
+- Atom m_atomUtf8String;
+- Atom m_atomNetActiveWindow;
+- QSet<QString> m_classBlacklist;
+- Qt::Key m_currentGlobalKey;
+- Qt::KeyboardModifiers m_currentGlobalModifiers;
+- uint m_currentGlobalKeycode;
+- uint m_currentGlobalNativeModifiers;
+- int m_modifierMask;
+- static bool m_catchXErrors;
+- static bool m_xErrorOccured;
+- static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
+-
+- static const int m_unicodeToKeysymLen;
+- static const uint m_unicodeToKeysymKeys[];
+- static const uint m_unicodeToKeysymValues[];
+-
+- XkbDescPtr m_xkb;
+- KeySym* m_keysymTable;
+- int m_minKeycode;
+- int m_maxKeycode;
+- int m_keysymPerKeycode;
+- /* dedicated keycode for remapped keys */
+- unsigned int m_remapKeycode;
+- KeySym m_currentRemapKeysym;
+- KeyCode m_modifier_keycode[N_MOD_INDICES];
+- bool m_loaded;
+-};
+-
+-class AutoTypeExecturorX11 : public AutoTypeExecutor
+-{
+-public:
+- explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform);
+-
+- void execChar(AutoTypeChar* action) Q_DECL_OVERRIDE;
+- void execKey(AutoTypeKey* action) Q_DECL_OVERRIDE;
+-
+-private:
+- AutoTypePlatformX11* const m_platform;
+-};
+-
+-#endif // KEEPASSX_AUTOTYPEX11_H
+diff --git a/src/autotype/x11/CMakeLists.txt b/src/autotype/x11/CMakeLists.txt
+deleted file mode 100644
+index cc401f7..0000000
+--- a/src/autotype/x11/CMakeLists.txt
++++ /dev/null
+@@ -1,17 +0,0 @@
+-include_directories(SYSTEM ${X11_X11_INCLUDE_PATH})
+-
+-set(autotype_X11_SOURCES
+- AutoTypeX11.cpp
+-)
+-
+-set(autotype_X11_MOC
+- AutoTypeX11.h
+-)
+-
+-qt4_wrap_cpp(autotype_X11_SOURCES ${autotype_X11_MOC})
+-
+-add_library(keepassx-autotype-x11 MODULE ${autotype_X11_SOURCES})
+-target_link_libraries(keepassx-autotype-x11 ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB})
+-install(TARGETS keepassx-autotype-x11
+- BUNDLE DESTINATION . COMPONENT Runtime
+- LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime)
+diff --git a/src/autotype/x11/KeySymMap.h b/src/autotype/x11/KeySymMap.h
+deleted file mode 100644
+index 55022fe..0000000
+--- a/src/autotype/x11/KeySymMap.h
++++ /dev/null
+@@ -1,169 +0,0 @@
+-/*
+- * Automatically generated by keysymmap.py from parsing keysymdef.h.
+- */
+-
+-const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
+-
+-const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
+- 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
+- 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
+- 0x0110, 0x0111, 0x0112, 0x0113, 0x0116, 0x0117, 0x0118, 0x0119,
+- 0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121,
+- 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
+- 0x012a, 0x012b, 0x012e, 0x012f, 0x0130, 0x0131, 0x0134, 0x0135,
+- 0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
+- 0x013e, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
+- 0x0148, 0x014a, 0x014b, 0x014c, 0x014d, 0x0150, 0x0151, 0x0152,
+- 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015a,
+- 0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162,
+- 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016a,
+- 0x016b, 0x016c, 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0172,
+- 0x0173, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 0x017e,
+- 0x0192, 0x02c7, 0x02d8, 0x02d9, 0x02db, 0x02dd, 0x0385, 0x0386,
+- 0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391,
+- 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
+- 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1,
+- 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa,
+- 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2,
+- 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
+- 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c2,
+- 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca,
+- 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404,
+- 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
+- 0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
+- 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
+- 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
+- 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
+- 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
+- 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
+- 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
+- 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
+- 0x044e, 0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456,
+- 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f,
+- 0x0490, 0x0491, 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5,
+- 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd,
+- 0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
+- 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x060c, 0x061b, 0x061f,
+- 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
+- 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, 0x0630,
+- 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638,
+- 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645,
+- 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d,
+- 0x064e, 0x064f, 0x0650, 0x0651, 0x0652, 0x0e01, 0x0e02, 0x0e03,
+- 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b,
+- 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, 0x0e10, 0x0e11, 0x0e12, 0x0e13,
+- 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b,
+- 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, 0x0e20, 0x0e21, 0x0e22, 0x0e23,
+- 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b,
+- 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e32, 0x0e33,
+- 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0e3f,
+- 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
+- 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e50, 0x0e51,
+- 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59,
+- 0x2002, 0x2003, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, 0x200a,
+- 0x2012, 0x2013, 0x2014, 0x2015, 0x2017, 0x2018, 0x2019, 0x201a,
+- 0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2025, 0x2026, 0x2030,
+- 0x2032, 0x2033, 0x2038, 0x203e, 0x20ac, 0x2105, 0x2116, 0x2117,
+- 0x211e, 0x2122, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158,
+- 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x2190, 0x2191,
+- 0x2192, 0x2193, 0x21d2, 0x21d4, 0x2202, 0x2207, 0x2218, 0x221a,
+- 0x221d, 0x221e, 0x2227, 0x2228, 0x2229, 0x222a, 0x222b, 0x2234,
+- 0x223c, 0x2243, 0x2260, 0x2261, 0x2264, 0x2265, 0x2282, 0x2283,
+- 0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x2308, 0x230a, 0x2315, 0x2320,
+- 0x2321, 0x2395, 0x239b, 0x239d, 0x239e, 0x23a0, 0x23a1, 0x23a3,
+- 0x23a4, 0x23a6, 0x23a8, 0x23ac, 0x23b7, 0x23ba, 0x23bb, 0x23bc,
+- 0x23bd, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x2424, 0x2500,
+- 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c,
+- 0x2534, 0x253c, 0x2592, 0x25c6, 0x25cb, 0x260e, 0x2640, 0x2642,
+- 0x2663, 0x2665, 0x2666, 0x266d, 0x266f, 0x2713, 0x2717, 0x271d,
+- 0x2720, 0x3001, 0x3002, 0x300c, 0x300d, 0x309b, 0x309c, 0x30a1,
+- 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
+- 0x30aa, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
+- 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3, 0x30c4, 0x30c6,
+- 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d2,
+- 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2,
+- 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea,
+- 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f2, 0x30f3, 0x30fb, 0x30fc
+-};
+-
+-const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
+- 0x03c0, 0x03e0, 0x01c3, 0x01e3, 0x01a1, 0x01b1, 0x01c6, 0x01e6,
+- 0x02c6, 0x02e6, 0x02c5, 0x02e5, 0x01c8, 0x01e8, 0x01cf, 0x01ef,
+- 0x01d0, 0x01f0, 0x03aa, 0x03ba, 0x03cc, 0x03ec, 0x01ca, 0x01ea,
+- 0x01cc, 0x01ec, 0x02d8, 0x02f8, 0x02ab, 0x02bb, 0x02d5, 0x02f5,
+- 0x03ab, 0x03bb, 0x02a6, 0x02b6, 0x02a1, 0x02b1, 0x03a5, 0x03b5,
+- 0x03cf, 0x03ef, 0x03c7, 0x03e7, 0x02a9, 0x02b9, 0x02ac, 0x02bc,
+- 0x03d3, 0x03f3, 0x03a2, 0x01c5, 0x01e5, 0x03a6, 0x03b6, 0x01a5,
+- 0x01b5, 0x01a3, 0x01b3, 0x01d1, 0x01f1, 0x03d1, 0x03f1, 0x01d2,
+- 0x01f2, 0x03bd, 0x03bf, 0x03d2, 0x03f2, 0x01d5, 0x01f5, 0x13bc,
+- 0x13bd, 0x01c0, 0x01e0, 0x03a3, 0x03b3, 0x01d8, 0x01f8, 0x01a6,
+- 0x01b6, 0x02de, 0x02fe, 0x01aa, 0x01ba, 0x01a9, 0x01b9, 0x01de,
+- 0x01fe, 0x01ab, 0x01bb, 0x03ac, 0x03bc, 0x03dd, 0x03fd, 0x03de,
+- 0x03fe, 0x02dd, 0x02fd, 0x01d9, 0x01f9, 0x01db, 0x01fb, 0x03d9,
+- 0x03f9, 0x13be, 0x01ac, 0x01bc, 0x01af, 0x01bf, 0x01ae, 0x01be,
+- 0x08f6, 0x01b7, 0x01a2, 0x01ff, 0x01b2, 0x01bd, 0x07ae, 0x07a1,
+- 0x07a2, 0x07a3, 0x07a4, 0x07a7, 0x07a8, 0x07ab, 0x07b6, 0x07c1,
+- 0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7, 0x07c8, 0x07c9,
+- 0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf, 0x07d0, 0x07d1,
+- 0x07d2, 0x07d4, 0x07d5, 0x07d6, 0x07d7, 0x07d8, 0x07d9, 0x07a5,
+- 0x07a9, 0x07b1, 0x07b2, 0x07b3, 0x07b4, 0x07ba, 0x07e1, 0x07e2,
+- 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9, 0x07ea,
+- 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
+- 0x07f2, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, 0x07f9, 0x07b5,
+- 0x07b9, 0x07b7, 0x07b8, 0x07bb, 0x06b3, 0x06b1, 0x06b2, 0x06b4,
+- 0x06b5, 0x06b6, 0x06b7, 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc,
+- 0x06be, 0x06bf, 0x06e1, 0x06e2, 0x06f7, 0x06e7, 0x06e4, 0x06e5,
+- 0x06f6, 0x06fa, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee,
+- 0x06ef, 0x06f0, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06e6, 0x06e8,
+- 0x06e3, 0x06fe, 0x06fb, 0x06fd, 0x06ff, 0x06f9, 0x06f8, 0x06fc,
+- 0x06e0, 0x06f1, 0x06c1, 0x06c2, 0x06d7, 0x06c7, 0x06c4, 0x06c5,
+- 0x06d6, 0x06da, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce,
+- 0x06cf, 0x06d0, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06c6, 0x06c8,
+- 0x06c3, 0x06de, 0x06db, 0x06dd, 0x06df, 0x06d9, 0x06d8, 0x06dc,
+- 0x06c0, 0x06d1, 0x06a3, 0x06a1, 0x06a2, 0x06a4, 0x06a5, 0x06a6,
+- 0x06a7, 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af,
+- 0x06bd, 0x06ad, 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5,
+- 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced,
+- 0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf2, 0x0cf3, 0x0cf4, 0x0cf5,
+- 0x0cf6, 0x0cf7, 0x0cf8, 0x0cf9, 0x0cfa, 0x05ac, 0x05bb, 0x05bf,
+- 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, 0x05c8,
+- 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, 0x05d0,
+- 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8,
+- 0x05d9, 0x05da, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
+- 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed,
+- 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f2, 0x0da1, 0x0da2, 0x0da3,
+- 0x0da4, 0x0da5, 0x0da6, 0x0da7, 0x0da8, 0x0da9, 0x0daa, 0x0dab,
+- 0x0dac, 0x0dad, 0x0dae, 0x0daf, 0x0db0, 0x0db1, 0x0db2, 0x0db3,
+- 0x0db4, 0x0db5, 0x0db6, 0x0db7, 0x0db8, 0x0db9, 0x0dba, 0x0dbb,
+- 0x0dbc, 0x0dbd, 0x0dbe, 0x0dbf, 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3,
+- 0x0dc4, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9, 0x0dca, 0x0dcb,
+- 0x0dcc, 0x0dcd, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3,
+- 0x0dd4, 0x0dd5, 0x0dd6, 0x0dd7, 0x0dd8, 0x0dd9, 0x0dda, 0x0ddf,
+- 0x0de0, 0x0de1, 0x0de2, 0x0de3, 0x0de4, 0x0de5, 0x0de6, 0x0de7,
+- 0x0de8, 0x0de9, 0x0dea, 0x0deb, 0x0dec, 0x0ded, 0x0df0, 0x0df1,
+- 0x0df2, 0x0df3, 0x0df4, 0x0df5, 0x0df6, 0x0df7, 0x0df8, 0x0df9,
+- 0x0aa2, 0x0aa1, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8,
+- 0x0abb, 0x0aaa, 0x0aa9, 0x07af, 0x0cdf, 0x0ad0, 0x0ad1, 0x0afd,
+- 0x0ad2, 0x0ad3, 0x0afe, 0x0af1, 0x0af2, 0x0aaf, 0x0aae, 0x0ad5,
+- 0x0ad6, 0x0ad7, 0x0afc, 0x047e, 0x20ac, 0x0ab8, 0x06b0, 0x0afb,
+- 0x0ad4, 0x0ac9, 0x0ab0, 0x0ab1, 0x0ab2, 0x0ab3, 0x0ab4, 0x0ab5,
+- 0x0ab6, 0x0ab7, 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac6, 0x08fb, 0x08fc,
+- 0x08fd, 0x08fe, 0x08ce, 0x08cd, 0x08ef, 0x08c5, 0x0bca, 0x08d6,
+- 0x08c1, 0x08c2, 0x08de, 0x08df, 0x08dc, 0x08dd, 0x08bf, 0x08c0,
+- 0x08c8, 0x08c9, 0x08bd, 0x08cf, 0x08bc, 0x08be, 0x08da, 0x08db,
+- 0x0bfc, 0x0bdc, 0x0bc2, 0x0bce, 0x0bd3, 0x0bc4, 0x0afa, 0x08a4,
+- 0x08a5, 0x0bcc, 0x08ab, 0x08ac, 0x08ad, 0x08ae, 0x08a7, 0x08a8,
+- 0x08a9, 0x08aa, 0x08af, 0x08b0, 0x08a1, 0x09ef, 0x09f0, 0x09f2,
+- 0x09f3, 0x09e2, 0x09e5, 0x09e9, 0x09e3, 0x09e4, 0x09e8, 0x09f1,
+- 0x09f8, 0x09ec, 0x09eb, 0x09ed, 0x09ea, 0x09f4, 0x09f5, 0x09f7,
+- 0x09f6, 0x09ee, 0x09e1, 0x09e0, 0x0bcf, 0x0af9, 0x0af8, 0x0af7,
+- 0x0aec, 0x0aee, 0x0aed, 0x0af6, 0x0af5, 0x0af3, 0x0af4, 0x0ad9,
+- 0x0af0, 0x04a4, 0x04a1, 0x04a2, 0x04a3, 0x04de, 0x04df, 0x04a7,
+- 0x04b1, 0x04a8, 0x04b2, 0x04a9, 0x04b3, 0x04aa, 0x04b4, 0x04ab,
+- 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc,
+- 0x04bd, 0x04be, 0x04bf, 0x04c0, 0x04c1, 0x04af, 0x04c2, 0x04c3,
+- 0x04c4, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9, 0x04ca, 0x04cb,
+- 0x04cc, 0x04cd, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d2, 0x04d3,
+- 0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
+- 0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
+-};
+diff --git a/src/autotype/x11/keysymmap.py b/src/autotype/x11/keysymmap.py
+deleted file mode 100755
+index a359710..0000000
+--- a/src/autotype/x11/keysymmap.py
++++ /dev/null
+@@ -1,107 +0,0 @@
+-#!/usr/bin/python3
+-
+-#
+-# Copyright (C) 2013 Felix Geyer <debfx at fobos.de>
+-#
+-# This program is free software: you can redistribute it and/or modify
+-# it under the terms of the GNU General Public License as published by
+-# the Free Software Foundation, either version 2 or (at your option)
+-# version 3 of the License.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public License
+-# along with this program. If not, see <http://www.gnu.org/licenses/>.
+-#
+-
+-#
+-# Parses keysymdef.h to construct a unicode symbol -> keysym mapping table.
+-#
+-# The lines that are parsed look like this:
+-# #define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
+-#
+-# This would create a 0x0104 -> 0x01a1 mapping.
+-#
+-
+-import sys
+-import re
+-import collections
+-
+-cols = 8
+-
+-if len(sys.argv) >= 2:
+- keysymdef = sys.argv[1]
+-else:
+- keysymdef = "/usr/include/X11/keysymdef.h"
+-
+-keysymMap = {}
+-
+-f = open(keysymdef, "r")
+-for line in f:
+- match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line)
+- if match:
+- keysym = int(match.group(1), 16)
+- unicodeVal = int(match.group(2), 16)
+-
+- # ignore 1:1 mappings
+- if keysym >= 0x0020 and keysym <= 0x007e:
+- continue
+- if keysym >= 0x00a0 and keysym <= 0x00ff:
+- continue
+- # ignore unicode | 0x01000000 mappings
+- if keysym >= 0x1000000:
+- continue
+-
+- keysymMap[unicodeVal] = keysym
+-
+-keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0]))
+-
+-print("""/*
+- * Automatically generated by keysymmap.py from parsing keysymdef.h.
+- */
+-""")
+-
+-print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";")
+-
+-print()
+-
+-print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {")
+-keys = keysymMap.keys()
+-keyLen = len(keys)
+-i = 1
+-for val in keys:
+- hexVal = "{0:#0{1}x}".format(val, 6)
+-
+- if i == keyLen:
+- print(hexVal)
+- elif (i % cols) == 0:
+- print(hexVal + ",")
+- elif ((i - 1) % cols) == 0:
+- print(" " + hexVal + ", ", end="")
+- else:
+- print(hexVal + ", ", end="")
+- i += 1
+-print("};")
+-
+-print()
+-
+-print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {")
+-values = keysymMap.values()
+-valuesLen = len(values)
+-i = 1
+-for val in values:
+- hexVal = "{0:#0{1}x}".format(val, 6)
+-
+- if i == valuesLen:
+- print(hexVal)
+- elif (i % cols) == 0:
+- print(hexVal + ",")
+- elif ((i - 1) % cols) == 0:
+- print(" " + hexVal + ", ", end="")
+- else:
+- print(hexVal + ", ", end="")
+- i += 1
+-print("};")
+diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp
+new file mode 100644
+index 0000000..40acaf6
+--- /dev/null
++++ b/src/autotype/xcb/AutoTypeXCB.cpp
+@@ -0,0 +1,870 @@
++/*
++ * Copyright (C) 2012 Felix Geyer <debfx at fobos.de>
++ * Copyright (C) 2000-2008 Tom Sato <VEF00200 at nifty.ne.jp>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 2 or (at your option)
++ * version 3 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "AutoTypeXCB.h"
++#include "KeySymMap.h"
++#include "core/Tools.h"
++
++#include <time.h>
++#include <xcb/xcb.h>
++
++bool AutoTypePlatformX11::m_catchXErrors = false;
++bool AutoTypePlatformX11::m_xErrorOccured = false;
++int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = nullptr;
++
++AutoTypePlatformX11::AutoTypePlatformX11()
++{
++ m_dpy = QX11Info::display();
++ m_rootWindow = QX11Info::appRootWindow();
++
++ m_atomWmState = XInternAtom(m_dpy, "WM_STATE", True);
++ m_atomWmName = XInternAtom(m_dpy, "WM_NAME", True);
++ m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", True);
++ m_atomString = XInternAtom(m_dpy, "STRING", True);
++ m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
++ m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
++
++ m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
++ m_classBlacklist << "kdesktop" << "kicker"; // KDE 3
++ m_classBlacklist << "Plasma"; // KDE 4
++ m_classBlacklist << "plasmashell"; // KDE 5
++ m_classBlacklist << "xfdesktop" << "xfce4-panel"; // Xfce 4
++
++ m_currentGlobalKey = static_cast<Qt::Key>(0);
++ m_currentGlobalModifiers = 0;
++
++ m_keysymTable = nullptr;
++ m_xkb = nullptr;
++ m_remapKeycode = 0;
++ m_currentRemapKeysym = NoSymbol;
++ m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
++
++ m_loaded = true;
++
++ updateKeymap();
++}
++
++bool AutoTypePlatformX11::isAvailable()
++{
++ int ignore;
++
++ if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) {
++ return false;
++ }
++
++ if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) {
++ return false;
++ }
++
++ if (!m_xkb) {
++ XkbDescPtr kbd = getKeyboard();
++
++ if (!kbd) {
++ return false;
++ }
++
++ XkbFreeKeyboard(kbd, XkbAllComponentsMask, True);
++ }
++
++ return true;
++}
++
++void AutoTypePlatformX11::unload()
++{
++ // Restore the KeyboardMapping to its original state.
++ if (m_currentRemapKeysym != NoSymbol) {
++ AddKeysym(NoSymbol);
++ }
++
++ if (m_keysymTable) {
++ XFree(m_keysymTable);
++ }
++
++ if (m_xkb) {
++ XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
++ }
++
++ m_loaded = false;
++}
++
++QStringList AutoTypePlatformX11::windowTitles()
++{
++ return windowTitlesRecursive(m_rootWindow);
++}
++
++WId AutoTypePlatformX11::activeWindow()
++{
++ Window window;
++ int revert_to_return;
++ XGetInputFocus(m_dpy, &window, &revert_to_return);
++
++ int tree;
++ do {
++ if (isTopLevelWindow(window)) {
++ break;
++ }
++
++ Window root;
++ Window parent;
++ Window* children = nullptr;
++ unsigned int numChildren;
++ tree = XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren);
++ window = parent;
++ if (children) {
++ XFree(children);
++ }
++ } while (tree && window);
++
++ return window;
++}
++
++QString AutoTypePlatformX11::activeWindowTitle()
++{
++ return windowTitle(activeWindow(), true);
++}
++
++bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
++{
++ int keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
++ uint nativeModifiers = qtToNativeModifiers(modifiers);
++
++ startCatchXErrors();
++ XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
++ XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync,
++ GrabModeAsync);
++ XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync,
++ GrabModeAsync);
++ XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
++ GrabModeAsync, GrabModeAsync);
++ stopCatchXErrors();
++
++ if (!m_xErrorOccured) {
++ m_currentGlobalKey = key;
++ m_currentGlobalModifiers = modifiers;
++ m_currentGlobalKeycode = keycode;
++ m_currentGlobalNativeModifiers = nativeModifiers;
++ return true;
++ }
++ else {
++ unregisterGlobalShortcut(key, modifiers);
++ return false;
++ }
++}
++
++uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
++{
++ uint nativeModifiers = 0;
++
++ if (modifiers & Qt::ShiftModifier) {
++ nativeModifiers |= ShiftMask;
++ }
++ if (modifiers & Qt::ControlModifier) {
++ nativeModifiers |= ControlMask;
++ }
++ if (modifiers & Qt::AltModifier) {
++ nativeModifiers |= Mod1Mask;
++ }
++ if (modifiers & Qt::MetaModifier) {
++ nativeModifiers |= Mod4Mask;
++ }
++
++ return nativeModifiers;
++}
++
++void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
++{
++ KeyCode keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
++ uint nativeModifiers = qtToNativeModifiers(modifiers);
++
++ XUngrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow);
++ XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow);
++ XUngrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow);
++ XUngrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow);
++
++ m_currentGlobalKey = static_cast<Qt::Key>(0);
++ m_currentGlobalModifiers = 0;
++ m_currentGlobalKeycode = 0;
++ m_currentGlobalNativeModifiers = 0;
++}
++
++int AutoTypePlatformX11::platformEventFilter(void* event)
++{
++ xcb_generic_event_t* genericEvent = static_cast<xcb_generic_event_t*>(event);
++ quint8 type = genericEvent->response_type & 0x7f;
++
++ if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) {
++ xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event);
++ if (keyPressEvent->detail == m_currentGlobalKeycode
++ && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
++ && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
++ && m_loaded) {
++ if (type == XCB_KEY_PRESS) {
++ Q_EMIT globalShortcutTriggered();
++ }
++
++ return 1;
++ }
++ }
++ else if (type == XCB_MAPPING_NOTIFY) {
++ xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast<xcb_mapping_notify_event_t*>(event);
++ if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD
++ || mappingNotifyEvent->request == XCB_MAPPING_MODIFIER)
++ {
++ XMappingEvent xMappingEvent;
++ memset(&xMappingEvent, 0, sizeof(xMappingEvent));
++ xMappingEvent.type = MappingNotify;
++ xMappingEvent.display = m_dpy;
++ if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) {
++ xMappingEvent.request = MappingKeyboard;
++ }
++ else {
++ xMappingEvent.request = MappingModifier;
++ }
++ xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode;
++ xMappingEvent.count = mappingNotifyEvent->count;
++ XRefreshKeyboardMapping(&xMappingEvent);
++ updateKeymap();
++ }
++ }
++
++ return -1;
++}
++
++AutoTypeExecutor* AutoTypePlatformX11::createExecutor()
++{
++ return new AutoTypeExecturorX11(this);
++}
++
++QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
++{
++ QString title;
++
++ Atom type;
++ int format;
++ unsigned long nitems;
++ unsigned long after;
++ unsigned char* data = nullptr;
++
++ // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME
++
++ int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String,
++ &type, &format, &nitems, &after, &data);
++
++ if ((retVal == 0) && data) {
++ title = QString::fromUtf8(reinterpret_cast<char*>(data));
++ }
++ else {
++ XTextProperty textProp;
++ retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
++ if ((retVal != 0) && textProp.value) {
++ char** textList = nullptr;
++ int count;
++
++ if (textProp.encoding == m_atomUtf8String) {
++ title = QString::fromUtf8(reinterpret_cast<char*>(textProp.value));
++ }
++ else if ((XmbTextPropertyToTextList(m_dpy, &textProp, &textList, &count) == 0)
++ && textList && (count > 0)) {
++ title = QString::fromLocal8Bit(textList[0]);
++ }
++ else if (textProp.encoding == m_atomString) {
++ title = QString::fromLocal8Bit(reinterpret_cast<char*>(textProp.value));
++ }
++
++ if (textList) {
++ XFreeStringList(textList);
++ }
++ }
++
++ if (textProp.value) {
++ XFree(textProp.value);
++ }
++ }
++
++ if (data) {
++ XFree(data);
++ }
++
++ if (useBlacklist && !title.isEmpty()) {
++ if (window == m_rootWindow) {
++ return QString();
++ }
++
++ QString className = windowClassName(window);
++ if (m_classBlacklist.contains(className)) {
++ return QString();
++ }
++
++ QList<Window> keepassxWindows = widgetsToX11Windows(QApplication::topLevelWidgets());
++ if (keepassxWindows.contains(window)) {
++ return QString();
++ }
++ }
++
++ return title;
++}
++
++QString AutoTypePlatformX11::windowClassName(Window window)
++{
++ QString className;
++
++ XClassHint wmClass;
++ wmClass.res_name = nullptr;
++ wmClass.res_class = nullptr;
++
++ if (XGetClassHint(m_dpy, window, &wmClass) && wmClass.res_name) {
++ className = QString::fromLocal8Bit(wmClass.res_name);
++ }
++ if (wmClass.res_name) {
++ XFree(wmClass.res_name);
++ }
++ if (wmClass.res_class) {
++ XFree(wmClass.res_class);
++ }
++
++ return className;
++}
++
++QList<Window> AutoTypePlatformX11::widgetsToX11Windows(const QWidgetList& widgetList)
++{
++ QList<Window> windows;
++
++ Q_FOREACH (const QWidget* widget, widgetList) {
++ windows.append(widget->effectiveWinId());
++ }
++
++ return windows;
++}
++
++QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window)
++{
++ QStringList titles;
++
++ if (isTopLevelWindow(window)) {
++ QString title = windowTitle(window, true);
++ if (!title.isEmpty()) {
++ titles.append(title);
++ }
++ }
++
++ Window root;
++ Window parent;
++ Window* children = nullptr;
++ unsigned int numChildren;
++ if (XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren) && children) {
++ for (uint i = 0; i < numChildren; i++) {
++ titles.append(windowTitlesRecursive(children[i]));
++ }
++ }
++ if (children) {
++ XFree(children);
++ }
++
++ return titles;
++}
++
++bool AutoTypePlatformX11::isTopLevelWindow(Window window)
++{
++ Atom type = None;
++ int format;
++ unsigned long nitems;
++ unsigned long after;
++ unsigned char* data = nullptr;
++ int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, False, AnyPropertyType, &type, &format,
++ &nitems, &after, &data);
++ if (data) {
++ XFree(data);
++ }
++
++ return (retVal == 0) && type;
++}
++
++KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
++{
++ ushort unicode = ch.unicode();
++
++ /* first check for Latin-1 characters (1:1 mapping) */
++ if ((unicode >= 0x0020 && unicode <= 0x007e)
++ || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
++ return unicode;
++ }
++
++ /* mapping table generated from keysymdef.h */
++ const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys,
++ m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
++ unicode);
++ int index = match - m_unicodeToKeysymKeys;
++ if (index != m_unicodeToKeysymLen) {
++ return m_unicodeToKeysymValues[index];
++ }
++
++ if (unicode >= 0x0100) {
++ return unicode | 0x01000000;
++ }
++
++ return NoSymbol;
++}
++
++KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
++{
++ switch (key) {
++ case Qt::Key_Tab:
++ return XK_Tab;
++ case Qt::Key_Enter:
++ return XK_Return;
++ case Qt::Key_Up:
++ return XK_Up;
++ case Qt::Key_Down:
++ return XK_Down;
++ case Qt::Key_Left:
++ return XK_Left;
++ case Qt::Key_Right:
++ return XK_Right;
++ case Qt::Key_Insert:
++ return XK_Insert;
++ case Qt::Key_Delete:
++ return XK_Delete;
++ case Qt::Key_Home:
++ return XK_Home;
++ case Qt::Key_End:
++ return XK_End;
++ case Qt::Key_PageUp:
++ return XK_Page_Up;
++ case Qt::Key_PageDown:
++ return XK_Page_Down;
++ case Qt::Key_Backspace:
++ return XK_BackSpace;
++ case Qt::Key_Pause:
++ return XK_Break;
++ case Qt::Key_CapsLock:
++ return XK_Caps_Lock;
++ case Qt::Key_Escape:
++ return XK_Escape;
++ case Qt::Key_Help:
++ return XK_Help;
++ case Qt::Key_NumLock:
++ return XK_Num_Lock;
++ case Qt::Key_Print:
++ return XK_Print;
++ case Qt::Key_ScrollLock:
++ return XK_Scroll_Lock;
++ default:
++ if (key >= Qt::Key_F1 && key <= Qt::Key_F16) {
++ return XK_F1 + (key - Qt::Key_F1);
++ }
++ else {
++ return NoSymbol;
++ }
++ }
++}
++
++/*
++ * Update the keyboard and modifier mapping.
++ * We need the KeyboardMapping for AddKeysym.
++ * Modifier mapping is required for clearing the modifiers.
++ */
++void AutoTypePlatformX11::updateKeymap()
++{
++ int keycode, inx;
++ int mod_index, mod_key;
++ XModifierKeymap *modifiers;
++
++ if (m_xkb) {
++ XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
++ }
++ m_xkb = getKeyboard();
++
++ XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
++ if (m_keysymTable != NULL) XFree(m_keysymTable);
++ m_keysymTable = XGetKeyboardMapping(m_dpy,
++ m_minKeycode, m_maxKeycode - m_minKeycode + 1,
++ &m_keysymPerKeycode);
++
++ /* determine the keycode to use for remapped keys */
++ inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
++ if (m_remapKeycode == 0 || !isRemapKeycodeValid()) {
++ for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
++ inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
++ if (m_keysymTable[inx] == NoSymbol) {
++ m_remapKeycode = keycode;
++ m_currentRemapKeysym = NoSymbol;
++ break;
++ }
++ }
++ }
++
++ /* determine the keycode to use for modifiers */
++ modifiers = XGetModifierMapping(m_dpy);
++ for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
++ m_modifier_keycode[mod_index] = 0;
++ for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
++ keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
++ if (keycode) {
++ m_modifier_keycode[mod_index] = keycode;
++ break;
++ }
++ }
++ }
++ XFreeModifiermap(modifiers);
++
++ /* Xlib needs some time until the mapping is distributed to
++ all clients */
++ // TODO: we should probably only sleep while in the middle of typing something
++ timespec ts;
++ ts.tv_sec = 0;
++ ts.tv_nsec = 30 * 1000 * 1000;
++ nanosleep(&ts, nullptr);
++}
++
++bool AutoTypePlatformX11::isRemapKeycodeValid()
++{
++ int baseKeycode = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
++ for (int i = 0; i < m_keysymPerKeycode; i++) {
++ if (m_keysymTable[baseKeycode + i] == m_currentRemapKeysym) {
++ return true;
++ }
++ }
++
++ return false;
++}
++
++void AutoTypePlatformX11::startCatchXErrors()
++{
++ Q_ASSERT(!m_catchXErrors);
++
++ m_catchXErrors = true;
++ m_xErrorOccured = false;
++ m_oldXErrorHandler = XSetErrorHandler(x11ErrorHandler);
++}
++
++void AutoTypePlatformX11::stopCatchXErrors()
++{
++ Q_ASSERT(m_catchXErrors);
++
++ XSync(m_dpy, False);
++ XSetErrorHandler(m_oldXErrorHandler);
++ m_catchXErrors = false;
++}
++
++int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
++{
++ Q_UNUSED(display)
++ Q_UNUSED(error)
++
++ if (m_catchXErrors) {
++ m_xErrorOccured = true;
++ }
++
++ return 1;
++}
++
++XkbDescPtr AutoTypePlatformX11::getKeyboard()
++{
++ int num_devices;
++ XID keyboard_id = XkbUseCoreKbd;
++ XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices);
++ if (!devices) {
++ return nullptr;
++ }
++
++ for (int i = 0; i < num_devices; i++) {
++ if (QString(devices[i].name) == "Virtual core XTEST keyboard") {
++ keyboard_id = devices[i].id;
++ break;
++ }
++ }
++
++ XFreeDeviceList(devices);
++
++ return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id);
++}
++
++// --------------------------------------------------------------------------
++// The following code is taken from xvkbd 3.0 and has been slightly modified.
++// --------------------------------------------------------------------------
++
++/*
++ * Insert a specified keysym on the dedicated position in the keymap
++ * table.
++ */
++int AutoTypePlatformX11::AddKeysym(KeySym keysym)
++{
++ if (m_remapKeycode == 0) {
++ return 0;
++ }
++
++ int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
++ m_keysymTable[inx] = keysym;
++ m_currentRemapKeysym = keysym;
++
++ XChangeKeyboardMapping(m_dpy, m_remapKeycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
++ XFlush(m_dpy);
++ updateKeymap();
++
++ return m_remapKeycode;
++}
++
++/*
++ * Send event to the focused window.
++ * If input focus is specified explicitly, select the window
++ * before send event to the window.
++ */
++void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
++{
++ XSync(event->display, False);
++ int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
++
++ event->type = event_type;
++ Bool press;
++ if (event->type == KeyPress) {
++ press = True;
++ }
++ else {
++ press = False;
++ }
++ XTestFakeKeyEvent(event->display, event->keycode, press, 0);
++ XFlush(event->display);
++
++ XSetErrorHandler(oldHandler);
++}
++
++/*
++ * Send a modifier press/release event for all modifiers
++ * which are set in the mask variable.
++ */
++void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
++{
++ int mod_index;
++ for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
++ if (mask & (1 << mod_index)) {
++ event->keycode = m_modifier_keycode[mod_index];
++ SendEvent(event, event_type);
++ if (event_type == KeyPress)
++ event->state |= (1 << mod_index);
++ else
++ event->state &= (1 << mod_index);
++ }
++ }
++}
++
++/*
++ * Determines the keycode and modifier mask for the given
++ * keysym.
++ */
++int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
++{
++ int keycode = XKeysymToKeycode(m_dpy, keysym);
++
++ if (keycode && keysymModifiers(keysym, keycode, mask)) {
++ return keycode;
++ }
++
++ /* no modifier matches => resort to remapping */
++ keycode = AddKeysym(keysym);
++ if (keycode && keysymModifiers(keysym, keycode, mask)) {
++ return keycode;
++ }
++
++ *mask = 0;
++ return 0;
++}
++
++bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
++{
++ int shift, mod;
++ unsigned int mods_rtrn;
++
++ /* determine whether there is a combination of the modifiers
++ (Mod1-Mod5) with or without shift which returns keysym */
++ for (shift = 0; shift < 2; shift ++) {
++ for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
++ KeySym keysym_rtrn;
++ *mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
++ XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
++ if (keysym_rtrn == keysym) {
++ return true;
++ }
++ }
++ }
++
++ return false;
++}
++
++
++
++/*
++ * Send sequence of KeyPressed/KeyReleased events to the focused
++ * window to simulate keyboard. If modifiers (shift, control, etc)
++ * are set ON, many events will be sent.
++ */
++void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
++{
++ Window cur_focus;
++ int revert_to;
++ XKeyEvent event;
++ int keycode;
++
++ if (keysym == NoSymbol) {
++ qWarning("No such key: keysym=0x%lX", keysym);
++ return;
++ }
++
++ XGetInputFocus(m_dpy, &cur_focus, &revert_to);
++
++ event.display = m_dpy;
++ event.window = cur_focus;
++ event.root = m_rootWindow;
++ event.subwindow = None;
++ event.time = CurrentTime;
++ event.x = 1;
++ event.y = 1;
++ event.x_root = 1;
++ event.y_root = 1;
++ event.same_screen = True;
++
++ Window root, child;
++ int root_x, root_y, x, y;
++ unsigned int wanted_mask = 0;
++ unsigned int original_mask;
++
++ XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &original_mask);
++
++ /* determine keycode and mask for the given keysym */
++ keycode = GetKeycode(keysym, &wanted_mask);
++ if (keycode < 8 || keycode > 255) {
++ qWarning("Unable to get valid keycode for key: keysym=0x%lX", keysym);
++ return;
++ }
++
++ event.state = original_mask;
++
++ // modifiers that need to be pressed but aren't
++ unsigned int press_mask = wanted_mask & ~original_mask;
++
++ // modifiers that are pressed but maybe shouldn't
++ unsigned int release_check_mask = original_mask & ~wanted_mask;
++
++ // modifiers we need to release before sending the keycode
++ unsigned int release_mask = 0;
++
++ // check every release_check_mask individually if it affects the keysym we would generate
++ // if it doesn't we probably don't need to release it
++ for (int mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
++ if (release_check_mask & (1 << mod_index)) {
++ unsigned int mods_rtrn;
++ KeySym keysym_rtrn;
++ XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (1 << mod_index), &mods_rtrn, &keysym_rtrn);
++
++ if (keysym_rtrn != keysym) {
++ release_mask |= (1 << mod_index);
++ }
++ }
++ }
++
++ // finally check if the combination of pressed modifiers that we chose to ignore affects the keysym
++ unsigned int mods_rtrn;
++ KeySym keysym_rtrn;
++ XkbTranslateKeyCode(m_xkb, keycode, wanted_mask | (release_check_mask & ~release_mask), &mods_rtrn, &keysym_rtrn);
++ if (keysym_rtrn != keysym) {
++ // oh well, release all the modifiers we don't want
++ release_mask = release_check_mask;
++ }
++
++ /* release all modifiers */
++ SendModifier(&event, release_mask, KeyRelease);
++
++ SendModifier(&event, press_mask, KeyPress);
++
++ /* press and release key */
++ event.keycode = keycode;
++ SendEvent(&event, KeyPress);
++ SendEvent(&event, KeyRelease);
++
++ /* release the modifiers */
++ SendModifier(&event, press_mask, KeyRelease);
++
++ /* restore the old keyboard mask */
++ SendModifier(&event, release_mask, KeyPress);
++}
++
++int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
++{
++ char msg[200];
++
++ if (event->error_code == BadWindow) {
++ return 0;
++ }
++ XGetErrorText(my_dpy, event->error_code, msg, sizeof(msg) - 1);
++ qWarning("X error trapped: %s, request-code=%d\n", msg, event->request_code);
++ return 0;
++}
++
++
++AutoTypeExecturorX11::AutoTypeExecturorX11(AutoTypePlatformX11* platform)
++ : m_platform(platform)
++{
++}
++
++void AutoTypeExecturorX11::execChar(AutoTypeChar* action)
++{
++ m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
++}
++
++void AutoTypeExecturorX11::execKey(AutoTypeKey* action)
++{
++ m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
++}
++
++int AutoTypePlatformX11::initialTimeout()
++{
++ return 500;
++}
++
++bool AutoTypePlatformX11::raiseWindow(WId window)
++{
++ if (m_atomNetActiveWindow == None) {
++ return false;
++ }
++
++ XRaiseWindow(m_dpy, window);
++
++ XEvent event;
++ event.xclient.type = ClientMessage;
++ event.xclient.serial = 0;
++ event.xclient.send_event = True;
++ event.xclient.window = window;
++ event.xclient.message_type = m_atomNetActiveWindow;
++ event.xclient.format = 32;
++ event.xclient.data.l[0] = 1; // FromApplication
++ event.xclient.data.l[1] = QX11Info::appUserTime();
++ QWidget* activeWindow = QApplication::activeWindow();
++ if (activeWindow) {
++ event.xclient.data.l[2] = activeWindow->internalWinId();
++ }
++ else {
++ event.xclient.data.l[2] = 0;
++ }
++ event.xclient.data.l[3] = 0;
++ event.xclient.data.l[4] = 0;
++ XSendEvent(m_dpy, m_rootWindow, False,
++ SubstructureRedirectMask | SubstructureNotifyMask,
++ &event);
++ XFlush(m_dpy);
++
++ return true;
++}
+diff --git a/src/autotype/xcb/AutoTypeXCB.h b/src/autotype/xcb/AutoTypeXCB.h
+new file mode 100644
+index 0000000..8adee77
+--- /dev/null
++++ b/src/autotype/xcb/AutoTypeXCB.h
+@@ -0,0 +1,134 @@
++/*
++ * Copyright (C) 2012 Felix Geyer <debfx at fobos.de>
++ * Copyright (C) 2000-2008 Tom Sato <VEF00200 at nifty.ne.jp>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation, either version 2 or (at your option)
++ * version 3 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef KEEPASSX_AUTOTYPEXCB_H
++#define KEEPASSX_AUTOTYPEXCB_H
++
++#include <QApplication>
++#include <QSet>
++#include <QtPlugin>
++#include <QWidget>
++#include <QX11Info>
++
++#include <X11/Xutil.h>
++#include <X11/extensions/XTest.h>
++#include <X11/XKBlib.h>
++
++#include "autotype/AutoTypePlatformPlugin.h"
++#include "autotype/AutoTypeAction.h"
++
++#define N_MOD_INDICES (Mod5MapIndex + 1)
++
++class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
++{
++ Q_OBJECT
++ Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformX11")
++ Q_INTERFACES(AutoTypePlatformInterface)
++
++public:
++ AutoTypePlatformX11();
++ bool isAvailable() override;
++ void unload() override;
++ QStringList windowTitles() override;
++ WId activeWindow() override;
++ QString activeWindowTitle() override;
++ bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
++ int platformEventFilter(void* event) override;
++ int initialTimeout() override;
++ bool raiseWindow(WId window) override;
++ AutoTypeExecutor* createExecutor() override;
++
++ KeySym charToKeySym(const QChar& ch);
++ KeySym keyToKeySym(Qt::Key key);
++
++ void SendKeyPressedEvent(KeySym keysym);
++
++Q_SIGNALS:
++ void globalShortcutTriggered();
++
++private:
++ QString windowTitle(Window window, bool useBlacklist);
++ QStringList windowTitlesRecursive(Window window);
++ QString windowClassName(Window window);
++ QList<Window> widgetsToX11Windows(const QWidgetList& widgetList);
++ bool isTopLevelWindow(Window window);
++ uint qtToNativeModifiers(Qt::KeyboardModifiers modifiers);
++ void startCatchXErrors();
++ void stopCatchXErrors();
++ static int x11ErrorHandler(Display* display, XErrorEvent* error);
++
++ XkbDescPtr getKeyboard();
++ void updateKeymap();
++ bool isRemapKeycodeValid();
++ int AddKeysym(KeySym keysym);
++ void AddModifier(KeySym keysym);
++ void SendEvent(XKeyEvent* event, int event_type);
++ void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
++ int GetKeycode(KeySym keysym, unsigned int *mask);
++ bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
++
++ static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
++
++ Display* m_dpy;
++ Window m_rootWindow;
++ Atom m_atomWmState;
++ Atom m_atomWmName;
++ Atom m_atomNetWmName;
++ Atom m_atomString;
++ Atom m_atomUtf8String;
++ Atom m_atomNetActiveWindow;
++ QSet<QString> m_classBlacklist;
++ Qt::Key m_currentGlobalKey;
++ Qt::KeyboardModifiers m_currentGlobalModifiers;
++ uint m_currentGlobalKeycode;
++ uint m_currentGlobalNativeModifiers;
++ int m_modifierMask;
++ static bool m_catchXErrors;
++ static bool m_xErrorOccured;
++ static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
++
++ static const int m_unicodeToKeysymLen;
++ static const uint m_unicodeToKeysymKeys[];
++ static const uint m_unicodeToKeysymValues[];
++
++ XkbDescPtr m_xkb;
++ KeySym* m_keysymTable;
++ int m_minKeycode;
++ int m_maxKeycode;
++ int m_keysymPerKeycode;
++ /* dedicated keycode for remapped keys */
++ unsigned int m_remapKeycode;
++ KeySym m_currentRemapKeysym;
++ KeyCode m_modifier_keycode[N_MOD_INDICES];
++ bool m_loaded;
++};
++
++class AutoTypeExecturorX11 : public AutoTypeExecutor
++{
++public:
++ explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform);
++
++ void execChar(AutoTypeChar* action) override;
++ void execKey(AutoTypeKey* action) override;
++
++private:
++ AutoTypePlatformX11* const m_platform;
++};
++
++#endif // KEEPASSX_AUTOTYPEXCB_H
+diff --git a/src/autotype/xcb/CMakeLists.txt b/src/autotype/xcb/CMakeLists.txt
+new file mode 100644
+index 0000000..3b56b31
+--- /dev/null
++++ b/src/autotype/xcb/CMakeLists.txt
+@@ -0,0 +1,11 @@
++include_directories(SYSTEM ${X11_X11_INCLUDE_PATH})
++
++set(autotype_XCB_SOURCES
++ AutoTypeXCB.cpp
++)
++
++add_library(keepassx-autotype-xcb MODULE ${autotype_XCB_SOURCES})
++target_link_libraries(keepassx-autotype-xcb Qt5::Core Qt5::Widgets Qt5::X11Extras ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB})
++install(TARGETS keepassx-autotype-xcb
++ BUNDLE DESTINATION . COMPONENT Runtime
++ LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime)
+diff --git a/src/autotype/xcb/KeySymMap.h b/src/autotype/xcb/KeySymMap.h
+new file mode 100644
+index 0000000..55022fe
+--- /dev/null
++++ b/src/autotype/xcb/KeySymMap.h
+@@ -0,0 +1,169 @@
++/*
++ * Automatically generated by keysymmap.py from parsing keysymdef.h.
++ */
++
++const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
++
++const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
++ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
++ 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
++ 0x0110, 0x0111, 0x0112, 0x0113, 0x0116, 0x0117, 0x0118, 0x0119,
++ 0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121,
++ 0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
++ 0x012a, 0x012b, 0x012e, 0x012f, 0x0130, 0x0131, 0x0134, 0x0135,
++ 0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
++ 0x013e, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
++ 0x0148, 0x014a, 0x014b, 0x014c, 0x014d, 0x0150, 0x0151, 0x0152,
++ 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015a,
++ 0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162,
++ 0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016a,
++ 0x016b, 0x016c, 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0172,
++ 0x0173, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 0x017e,
++ 0x0192, 0x02c7, 0x02d8, 0x02d9, 0x02db, 0x02dd, 0x0385, 0x0386,
++ 0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391,
++ 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
++ 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1,
++ 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa,
++ 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2,
++ 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
++ 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c2,
++ 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca,
++ 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404,
++ 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
++ 0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
++ 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
++ 0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
++ 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
++ 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
++ 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
++ 0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
++ 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
++ 0x044e, 0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456,
++ 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f,
++ 0x0490, 0x0491, 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5,
++ 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd,
++ 0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
++ 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x060c, 0x061b, 0x061f,
++ 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
++ 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, 0x0630,
++ 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638,
++ 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645,
++ 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d,
++ 0x064e, 0x064f, 0x0650, 0x0651, 0x0652, 0x0e01, 0x0e02, 0x0e03,
++ 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b,
++ 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, 0x0e10, 0x0e11, 0x0e12, 0x0e13,
++ 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b,
++ 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, 0x0e20, 0x0e21, 0x0e22, 0x0e23,
++ 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b,
++ 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e32, 0x0e33,
++ 0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0e3f,
++ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
++ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e50, 0x0e51,
++ 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59,
++ 0x2002, 0x2003, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, 0x200a,
++ 0x2012, 0x2013, 0x2014, 0x2015, 0x2017, 0x2018, 0x2019, 0x201a,
++ 0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2025, 0x2026, 0x2030,
++ 0x2032, 0x2033, 0x2038, 0x203e, 0x20ac, 0x2105, 0x2116, 0x2117,
++ 0x211e, 0x2122, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158,
++ 0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x2190, 0x2191,
++ 0x2192, 0x2193, 0x21d2, 0x21d4, 0x2202, 0x2207, 0x2218, 0x221a,
++ 0x221d, 0x221e, 0x2227, 0x2228, 0x2229, 0x222a, 0x222b, 0x2234,
++ 0x223c, 0x2243, 0x2260, 0x2261, 0x2264, 0x2265, 0x2282, 0x2283,
++ 0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x2308, 0x230a, 0x2315, 0x2320,
++ 0x2321, 0x2395, 0x239b, 0x239d, 0x239e, 0x23a0, 0x23a1, 0x23a3,
++ 0x23a4, 0x23a6, 0x23a8, 0x23ac, 0x23b7, 0x23ba, 0x23bb, 0x23bc,
++ 0x23bd, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x2424, 0x2500,
++ 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c,
++ 0x2534, 0x253c, 0x2592, 0x25c6, 0x25cb, 0x260e, 0x2640, 0x2642,
++ 0x2663, 0x2665, 0x2666, 0x266d, 0x266f, 0x2713, 0x2717, 0x271d,
++ 0x2720, 0x3001, 0x3002, 0x300c, 0x300d, 0x309b, 0x309c, 0x30a1,
++ 0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
++ 0x30aa, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
++ 0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3, 0x30c4, 0x30c6,
++ 0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d2,
++ 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2,
++ 0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea,
++ 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f2, 0x30f3, 0x30fb, 0x30fc
++};
++
++const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
++ 0x03c0, 0x03e0, 0x01c3, 0x01e3, 0x01a1, 0x01b1, 0x01c6, 0x01e6,
++ 0x02c6, 0x02e6, 0x02c5, 0x02e5, 0x01c8, 0x01e8, 0x01cf, 0x01ef,
++ 0x01d0, 0x01f0, 0x03aa, 0x03ba, 0x03cc, 0x03ec, 0x01ca, 0x01ea,
++ 0x01cc, 0x01ec, 0x02d8, 0x02f8, 0x02ab, 0x02bb, 0x02d5, 0x02f5,
++ 0x03ab, 0x03bb, 0x02a6, 0x02b6, 0x02a1, 0x02b1, 0x03a5, 0x03b5,
++ 0x03cf, 0x03ef, 0x03c7, 0x03e7, 0x02a9, 0x02b9, 0x02ac, 0x02bc,
++ 0x03d3, 0x03f3, 0x03a2, 0x01c5, 0x01e5, 0x03a6, 0x03b6, 0x01a5,
++ 0x01b5, 0x01a3, 0x01b3, 0x01d1, 0x01f1, 0x03d1, 0x03f1, 0x01d2,
++ 0x01f2, 0x03bd, 0x03bf, 0x03d2, 0x03f2, 0x01d5, 0x01f5, 0x13bc,
++ 0x13bd, 0x01c0, 0x01e0, 0x03a3, 0x03b3, 0x01d8, 0x01f8, 0x01a6,
++ 0x01b6, 0x02de, 0x02fe, 0x01aa, 0x01ba, 0x01a9, 0x01b9, 0x01de,
++ 0x01fe, 0x01ab, 0x01bb, 0x03ac, 0x03bc, 0x03dd, 0x03fd, 0x03de,
++ 0x03fe, 0x02dd, 0x02fd, 0x01d9, 0x01f9, 0x01db, 0x01fb, 0x03d9,
++ 0x03f9, 0x13be, 0x01ac, 0x01bc, 0x01af, 0x01bf, 0x01ae, 0x01be,
++ 0x08f6, 0x01b7, 0x01a2, 0x01ff, 0x01b2, 0x01bd, 0x07ae, 0x07a1,
++ 0x07a2, 0x07a3, 0x07a4, 0x07a7, 0x07a8, 0x07ab, 0x07b6, 0x07c1,
++ 0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7, 0x07c8, 0x07c9,
++ 0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf, 0x07d0, 0x07d1,
++ 0x07d2, 0x07d4, 0x07d5, 0x07d6, 0x07d7, 0x07d8, 0x07d9, 0x07a5,
++ 0x07a9, 0x07b1, 0x07b2, 0x07b3, 0x07b4, 0x07ba, 0x07e1, 0x07e2,
++ 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9, 0x07ea,
++ 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
++ 0x07f2, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, 0x07f9, 0x07b5,
++ 0x07b9, 0x07b7, 0x07b8, 0x07bb, 0x06b3, 0x06b1, 0x06b2, 0x06b4,
++ 0x06b5, 0x06b6, 0x06b7, 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc,
++ 0x06be, 0x06bf, 0x06e1, 0x06e2, 0x06f7, 0x06e7, 0x06e4, 0x06e5,
++ 0x06f6, 0x06fa, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee,
++ 0x06ef, 0x06f0, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06e6, 0x06e8,
++ 0x06e3, 0x06fe, 0x06fb, 0x06fd, 0x06ff, 0x06f9, 0x06f8, 0x06fc,
++ 0x06e0, 0x06f1, 0x06c1, 0x06c2, 0x06d7, 0x06c7, 0x06c4, 0x06c5,
++ 0x06d6, 0x06da, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce,
++ 0x06cf, 0x06d0, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06c6, 0x06c8,
++ 0x06c3, 0x06de, 0x06db, 0x06dd, 0x06df, 0x06d9, 0x06d8, 0x06dc,
++ 0x06c0, 0x06d1, 0x06a3, 0x06a1, 0x06a2, 0x06a4, 0x06a5, 0x06a6,
++ 0x06a7, 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af,
++ 0x06bd, 0x06ad, 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5,
++ 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced,
++ 0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf2, 0x0cf3, 0x0cf4, 0x0cf5,
++ 0x0cf6, 0x0cf7, 0x0cf8, 0x0cf9, 0x0cfa, 0x05ac, 0x05bb, 0x05bf,
++ 0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, 0x05c8,
++ 0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, 0x05d0,
++ 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8,
++ 0x05d9, 0x05da, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
++ 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed,
++ 0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f2, 0x0da1, 0x0da2, 0x0da3,
++ 0x0da4, 0x0da5, 0x0da6, 0x0da7, 0x0da8, 0x0da9, 0x0daa, 0x0dab,
++ 0x0dac, 0x0dad, 0x0dae, 0x0daf, 0x0db0, 0x0db1, 0x0db2, 0x0db3,
++ 0x0db4, 0x0db5, 0x0db6, 0x0db7, 0x0db8, 0x0db9, 0x0dba, 0x0dbb,
++ 0x0dbc, 0x0dbd, 0x0dbe, 0x0dbf, 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3,
++ 0x0dc4, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9, 0x0dca, 0x0dcb,
++ 0x0dcc, 0x0dcd, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3,
++ 0x0dd4, 0x0dd5, 0x0dd6, 0x0dd7, 0x0dd8, 0x0dd9, 0x0dda, 0x0ddf,
++ 0x0de0, 0x0de1, 0x0de2, 0x0de3, 0x0de4, 0x0de5, 0x0de6, 0x0de7,
++ 0x0de8, 0x0de9, 0x0dea, 0x0deb, 0x0dec, 0x0ded, 0x0df0, 0x0df1,
++ 0x0df2, 0x0df3, 0x0df4, 0x0df5, 0x0df6, 0x0df7, 0x0df8, 0x0df9,
++ 0x0aa2, 0x0aa1, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8,
++ 0x0abb, 0x0aaa, 0x0aa9, 0x07af, 0x0cdf, 0x0ad0, 0x0ad1, 0x0afd,
++ 0x0ad2, 0x0ad3, 0x0afe, 0x0af1, 0x0af2, 0x0aaf, 0x0aae, 0x0ad5,
++ 0x0ad6, 0x0ad7, 0x0afc, 0x047e, 0x20ac, 0x0ab8, 0x06b0, 0x0afb,
++ 0x0ad4, 0x0ac9, 0x0ab0, 0x0ab1, 0x0ab2, 0x0ab3, 0x0ab4, 0x0ab5,
++ 0x0ab6, 0x0ab7, 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac6, 0x08fb, 0x08fc,
++ 0x08fd, 0x08fe, 0x08ce, 0x08cd, 0x08ef, 0x08c5, 0x0bca, 0x08d6,
++ 0x08c1, 0x08c2, 0x08de, 0x08df, 0x08dc, 0x08dd, 0x08bf, 0x08c0,
++ 0x08c8, 0x08c9, 0x08bd, 0x08cf, 0x08bc, 0x08be, 0x08da, 0x08db,
++ 0x0bfc, 0x0bdc, 0x0bc2, 0x0bce, 0x0bd3, 0x0bc4, 0x0afa, 0x08a4,
++ 0x08a5, 0x0bcc, 0x08ab, 0x08ac, 0x08ad, 0x08ae, 0x08a7, 0x08a8,
++ 0x08a9, 0x08aa, 0x08af, 0x08b0, 0x08a1, 0x09ef, 0x09f0, 0x09f2,
++ 0x09f3, 0x09e2, 0x09e5, 0x09e9, 0x09e3, 0x09e4, 0x09e8, 0x09f1,
++ 0x09f8, 0x09ec, 0x09eb, 0x09ed, 0x09ea, 0x09f4, 0x09f5, 0x09f7,
++ 0x09f6, 0x09ee, 0x09e1, 0x09e0, 0x0bcf, 0x0af9, 0x0af8, 0x0af7,
++ 0x0aec, 0x0aee, 0x0aed, 0x0af6, 0x0af5, 0x0af3, 0x0af4, 0x0ad9,
++ 0x0af0, 0x04a4, 0x04a1, 0x04a2, 0x04a3, 0x04de, 0x04df, 0x04a7,
++ 0x04b1, 0x04a8, 0x04b2, 0x04a9, 0x04b3, 0x04aa, 0x04b4, 0x04ab,
++ 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc,
++ 0x04bd, 0x04be, 0x04bf, 0x04c0, 0x04c1, 0x04af, 0x04c2, 0x04c3,
++ 0x04c4, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9, 0x04ca, 0x04cb,
++ 0x04cc, 0x04cd, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d2, 0x04d3,
++ 0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
++ 0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
++};
+diff --git a/src/autotype/xcb/keysymmap.py b/src/autotype/xcb/keysymmap.py
+new file mode 100755
+index 0000000..a359710
+--- /dev/null
++++ b/src/autotype/xcb/keysymmap.py
+@@ -0,0 +1,107 @@
++#!/usr/bin/python3
++
++#
++# Copyright (C) 2013 Felix Geyer <debfx at fobos.de>
++#
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 2 or (at your option)
++# version 3 of the License.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
++#
++
++#
++# Parses keysymdef.h to construct a unicode symbol -> keysym mapping table.
++#
++# The lines that are parsed look like this:
++# #define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
++#
++# This would create a 0x0104 -> 0x01a1 mapping.
++#
++
++import sys
++import re
++import collections
++
++cols = 8
++
++if len(sys.argv) >= 2:
++ keysymdef = sys.argv[1]
++else:
++ keysymdef = "/usr/include/X11/keysymdef.h"
++
++keysymMap = {}
++
++f = open(keysymdef, "r")
++for line in f:
++ match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line)
++ if match:
++ keysym = int(match.group(1), 16)
++ unicodeVal = int(match.group(2), 16)
++
++ # ignore 1:1 mappings
++ if keysym >= 0x0020 and keysym <= 0x007e:
++ continue
++ if keysym >= 0x00a0 and keysym <= 0x00ff:
++ continue
++ # ignore unicode | 0x01000000 mappings
++ if keysym >= 0x1000000:
++ continue
++
++ keysymMap[unicodeVal] = keysym
++
++keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0]))
++
++print("""/*
++ * Automatically generated by keysymmap.py from parsing keysymdef.h.
++ */
++""")
++
++print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";")
++
++print()
++
++print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {")
++keys = keysymMap.keys()
++keyLen = len(keys)
++i = 1
++for val in keys:
++ hexVal = "{0:#0{1}x}".format(val, 6)
++
++ if i == keyLen:
++ print(hexVal)
++ elif (i % cols) == 0:
++ print(hexVal + ",")
++ elif ((i - 1) % cols) == 0:
++ print(" " + hexVal + ", ", end="")
++ else:
++ print(hexVal + ", ", end="")
++ i += 1
++print("};")
++
++print()
++
++print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {")
++values = keysymMap.values()
++valuesLen = len(values)
++i = 1
++for val in values:
++ hexVal = "{0:#0{1}x}".format(val, 6)
++
++ if i == valuesLen:
++ print(hexVal)
++ elif (i % cols) == 0:
++ print(hexVal + ",")
++ elif ((i - 1) % cols) == 0:
++ print(" " + hexVal + ", ", end="")
++ else:
++ print(hexVal + ", ", end="")
++ i += 1
++print("};")
+diff --git a/src/config-keepassx.h.cmake b/src/config-keepassx.h.cmake
+index 197c0d3..dc418b6 100644
+--- a/src/config-keepassx.h.cmake
++++ b/src/config-keepassx.h.cmake
+@@ -16,6 +16,4 @@
+ #cmakedefine HAVE_RLIMIT_CORE 1
+ #cmakedefine HAVE_PT_DENY_ATTACH 1
+
+-#cmakedefine GCRYPT_HAS_SALSA20
+-
+ #endif // KEEPASSX_CONFIG_KEEPASSX_H
+diff --git a/src/core/AutoTypeAssociations.h b/src/core/AutoTypeAssociations.h
+index 1b5871b..491a5db 100644
+--- a/src/core/AutoTypeAssociations.h
++++ b/src/core/AutoTypeAssociations.h
+@@ -20,8 +20,6 @@
+
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class AutoTypeAssociations : public QObject
+ {
+ Q_OBJECT
+@@ -36,7 +34,7 @@ public:
+ bool operator!=(const AutoTypeAssociations::Association& other) const;
+ };
+
+- explicit AutoTypeAssociations(QObject* parent = Q_NULLPTR);
++ explicit AutoTypeAssociations(QObject* parent = nullptr);
+ void copyDataFrom(const AutoTypeAssociations* other);
+ void add(const AutoTypeAssociations::Association& association);
+ void remove(int index);
+diff --git a/src/core/Config.cpp b/src/core/Config.cpp
+index 046a0fe..5b06c22 100644
+--- a/src/core/Config.cpp
++++ b/src/core/Config.cpp
+@@ -18,12 +18,12 @@
+ #include "Config.h"
+
+ #include <QCoreApplication>
+-#include <QDesktopServices>
+ #include <QDir>
+ #include <QSettings>
++#include <QStandardPaths>
+ #include <QTemporaryFile>
+
+-Config* Config::m_instance(Q_NULLPTR);
++Config* Config::m_instance(nullptr);
+
+ QVariant Config::get(const QString& key)
+ {
+@@ -53,7 +53,7 @@ Config::Config(QObject* parent)
+ QString homePath = QDir::homePath();
+
+ #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+- // we can't use QDesktopServices on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
++ // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
+ QByteArray env = qgetenv("XDG_CONFIG_HOME");
+ if (env.isEmpty()) {
+ userPath = homePath;
+@@ -70,7 +70,7 @@ Config::Config(QObject* parent)
+
+ userPath += "/keepassx/";
+ #else
+- userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
++ userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
+ // storageLocation() appends the application name ("/keepassx") to the end
+ userPath += "/";
+ #endif
+diff --git a/src/core/Config.h b/src/core/Config.h
+index ca0f74c..09aa02f 100644
+--- a/src/core/Config.h
++++ b/src/core/Config.h
+@@ -21,8 +21,6 @@
+ #include <QScopedPointer>
+ #include <QVariant>
+
+-#include "core/Global.h"
+-
+ class QSettings;
+
+ class Config : public QObject
+diff --git a/src/core/Database.cpp b/src/core/Database.cpp
+index 098cc06..6f94235 100644
+--- a/src/core/Database.cpp
++++ b/src/core/Database.cpp
+@@ -23,7 +23,6 @@
+
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+-#include "core/Tools.h"
+ #include "crypto/Random.h"
+ #include "format/KeePass2.h"
+
+@@ -105,7 +104,7 @@ Entry* Database::recFindEntry(const Uuid& uuid, Group* group)
+ }
+ }
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ Group* Database::resolveGroup(const Uuid& uuid)
+@@ -126,7 +125,7 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group)
+ }
+ }
+
+- return Q_NULLPTR;
++ return nullptr;
+ }
+
+ QList<DeletedObject> Database::deletedObjects()
+@@ -143,7 +142,7 @@ void Database::addDeletedObject(const DeletedObject& delObj)
+ void Database::addDeletedObject(const Uuid& uuid)
+ {
+ DeletedObject delObj;
+- delObj.deletionTime = Tools::currentDateTimeUtc();
++ delObj.deletionTime = QDateTime::currentDateTimeUtc();
+ delObj.uuid = uuid;
+
+ addDeletedObject(delObj);
+@@ -223,7 +222,7 @@ bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed,
+ m_data.transformedMasterKey = transformedMasterKey;
+ m_data.hasKey = true;
+ if (updateChangedTime) {
+- m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
++ m_metadata->setMasterKeyChanged(QDateTime::currentDateTimeUtc());
+ }
+ Q_EMIT modifiedImmediate();
+
+diff --git a/src/core/Database.h b/src/core/Database.h
+index 97ccad2..6fde3c6 100644
+--- a/src/core/Database.h
++++ b/src/core/Database.h
+@@ -20,6 +20,7 @@
+
+ #include <QDateTime>
+ #include <QHash>
++#include <QObject>
+
+ #include "core/Uuid.h"
+ #include "keys/CompositeKey.h"
+diff --git a/src/core/DatabaseIcons.cpp b/src/core/DatabaseIcons.cpp
+index d6e816f..4e62f79 100644
+--- a/src/core/DatabaseIcons.cpp
++++ b/src/core/DatabaseIcons.cpp
+@@ -19,7 +19,7 @@
+
+ #include "core/FilePath.h"
+
+-DatabaseIcons* DatabaseIcons::m_instance(Q_NULLPTR);
++DatabaseIcons* DatabaseIcons::m_instance(nullptr);
+ const int DatabaseIcons::IconCount(69);
+ const int DatabaseIcons::ExpiredIconIndex(45);
+ const char* const DatabaseIcons::m_indexToName[] = {
+diff --git a/src/core/DatabaseIcons.h b/src/core/DatabaseIcons.h
+index 68d1e0c..a1d9480 100644
+--- a/src/core/DatabaseIcons.h
++++ b/src/core/DatabaseIcons.h
+@@ -23,8 +23,6 @@
+ #include <QPixmapCache>
+ #include <QVector>
+
+-#include "core/Global.h"
+-
+ class DatabaseIcons
+ {
+ public:
+diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp
+index 784b489..2fd52d0 100644
+--- a/src/core/Entry.cpp
++++ b/src/core/Entry.cpp
+@@ -21,7 +21,6 @@
+ #include "core/DatabaseIcons.h"
+ #include "core/Group.h"
+ #include "core/Metadata.h"
+-#include "core/Tools.h"
+
+ const int Entry::DefaultIconNumber = 0;
+
+@@ -29,7 +28,7 @@ Entry::Entry()
+ : m_attributes(new EntryAttributes(this))
+ , m_attachments(new EntryAttachments(this))
+ , m_autoTypeAssociations(new AutoTypeAssociations(this))
+- , m_tmpHistoryItem(Q_NULLPTR)
++ , m_tmpHistoryItem(nullptr)
+ , m_modifiedSinceBegin(false)
+ , m_updateTimeinfo(true)
+ {
+@@ -74,8 +73,8 @@ template <class T> inline bool Entry::set(T& property, const T& value)
+ void Entry::updateTimeinfo()
+ {
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
+- m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc());
++ m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc());
+ }
+ }
+
+@@ -223,7 +222,7 @@ QString Entry::notes() const
+
+ bool Entry::isExpired() const
+ {
+- return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
++ return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
+ }
+
+ EntryAttributes* Entry::attributes()
+@@ -474,7 +473,7 @@ Entry* Entry::clone(CloneFlags flags) const
+ entry->setUpdateTimeinfo(true);
+
+ if (flags & CloneResetTimeInfo) {
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ entry->m_data.timeInfo.setCreationTime(now);
+ entry->m_data.timeInfo.setLastModificationTime(now);
+ entry->m_data.timeInfo.setLastAccessTime(now);
+@@ -522,7 +521,7 @@ void Entry::endUpdate()
+ delete m_tmpHistoryItem;
+ }
+
+- m_tmpHistoryItem = Q_NULLPTR;
++ m_tmpHistoryItem = nullptr;
+ }
+
+ void Entry::updateModifiedSinceBegin()
+@@ -568,7 +567,7 @@ void Entry::setGroup(Group* group)
+ QObject::setParent(group);
+
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc());
+ }
+ }
+
+@@ -583,7 +582,7 @@ const Database* Entry::database() const
+ return m_group->database();
+ }
+ else {
+- return Q_NULLPTR;
++ return nullptr;
+ }
+ }
+
+diff --git a/src/core/Entry.h b/src/core/Entry.h
+index 3044dc8..cd7c7b7 100644
+--- a/src/core/Entry.h
++++ b/src/core/Entry.h
+@@ -29,7 +29,6 @@
+ #include "core/AutoTypeAssociations.h"
+ #include "core/EntryAttachments.h"
+ #include "core/EntryAttributes.h"
+-#include "core/Global.h"
+ #include "core/TimeInfo.h"
+ #include "core/Uuid.h"
+
+diff --git a/src/core/EntryAttachments.h b/src/core/EntryAttachments.h
+index 3446b31..903ca10 100644
+--- a/src/core/EntryAttachments.h
++++ b/src/core/EntryAttachments.h
+@@ -21,14 +21,12 @@
+ #include <QMap>
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class EntryAttachments : public QObject
+ {
+ Q_OBJECT
+
+ public:
+- explicit EntryAttachments(QObject* parent = Q_NULLPTR);
++ explicit EntryAttachments(QObject* parent = nullptr);
+ QList<QString> keys() const;
+ bool hasKey(const QString& key) const;
+ QList<QByteArray> values() const;
+diff --git a/src/core/EntryAttributes.h b/src/core/EntryAttributes.h
+index 334eb0a..c6bbf29 100644
+--- a/src/core/EntryAttributes.h
++++ b/src/core/EntryAttributes.h
+@@ -23,14 +23,12 @@
+ #include <QSet>
+ #include <QStringList>
+
+-#include "core/Global.h"
+-
+ class EntryAttributes : public QObject
+ {
+ Q_OBJECT
+
+ public:
+- explicit EntryAttributes(QObject* parent = Q_NULLPTR);
++ explicit EntryAttributes(QObject* parent = nullptr);
+ QList<QString> keys() const;
+ bool hasKey(const QString& key) const;
+ QList<QString> customKeys();
+diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp
+index 82a553e..05c4c58 100644
+--- a/src/core/EntrySearcher.cpp
++++ b/src/core/EntrySearcher.cpp
+@@ -19,7 +19,8 @@
+
+ #include "core/Group.h"
+
+-QList<Entry*> EntrySearcher::search(const QString &searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
++QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group,
++ Qt::CaseSensitivity caseSensitivity)
+ {
+ if (!group->resolveSearchingEnabled()) {
+ return QList<Entry*>();
+@@ -28,7 +29,8 @@ QList<Entry*> EntrySearcher::search(const QString &searchTerm, const Group* grou
+ return searchEntries(searchTerm, group, caseSensitivity);
+ }
+
+-QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
++QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group,
++ Qt::CaseSensitivity caseSensitivity)
+ {
+ QList<Entry*> searchResult;
+
+@@ -44,7 +46,8 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
+ return searchResult;
+ }
+
+-QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity)
++QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
++ Qt::CaseSensitivity caseSensitivity)
+ {
+ QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
+ Q_FOREACH (const QString& word, wordList) {
+diff --git a/src/core/EntrySearcher.h b/src/core/EntrySearcher.h
+index 246538c..c7075dc 100644
+--- a/src/core/EntrySearcher.h
++++ b/src/core/EntrySearcher.h
+@@ -28,10 +28,11 @@ class EntrySearcher
+ {
+ public:
+ QList<Entry*> search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
++
+ private:
+ QList<Entry*> searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
+ QList<Entry*> matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity);
+- bool wordMatch(const QString &word, Entry *entry, Qt::CaseSensitivity caseSensitivity);
++ bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity);
+ };
+
+ #endif // KEEPASSX_ENTRYSEARCHER_H
+diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp
+index f7c4075..497568a 100644
+--- a/src/core/FilePath.cpp
++++ b/src/core/FilePath.cpp
+@@ -23,7 +23,7 @@
+
+ #include "config-keepassx.h"
+
+-FilePath* FilePath::m_instance(Q_NULLPTR);
++FilePath* FilePath::m_instance(nullptr);
+
+ QString FilePath::dataPath(const QString& name)
+ {
+diff --git a/src/core/FilePath.h b/src/core/FilePath.h
+index 9e98d3e..c37a908 100644
+--- a/src/core/FilePath.h
++++ b/src/core/FilePath.h
+@@ -22,8 +22,6 @@
+ #include <QIcon>
+ #include <QString>
+
+-#include "core/Global.h"
+-
+ class FilePath
+ {
+ public:
+diff --git a/src/core/Global.h b/src/core/Global.h
+index 914c7b4..14281ee 100644
+--- a/src/core/Global.h
++++ b/src/core/Global.h
+@@ -20,104 +20,8 @@
+ #ifndef KEEPASSX_GLOBAL_H
+ #define KEEPASSX_GLOBAL_H
+
+-// mostly copied from qcompilerdetection.h which is part of Qt 5
+-
+ #include <QtGlobal>
+
+-#ifdef Q_CC_CLANG
+-# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+-# if __has_feature(cxx_strong_enums)
+-# define COMPILER_CLASS_ENUM
+-# endif
+-# if __has_feature(cxx_constexpr)
+-# define COMPILER_CONSTEXPR
+-# endif
+-# if __has_feature(cxx_decltype) /* && __has_feature(cxx_decltype_incomplete_return_types) */
+-# define COMPILER_DECLTYPE
+-# endif
+-# if __has_feature(cxx_override_control)
+-# define COMPILER_EXPLICIT_OVERRIDES
+-# endif
+-# if __has_feature(cxx_nullptr)
+-# define COMPILER_NULLPTR
+-# endif
+-# if __has_feature(cxx_static_assert)
+-# define COMPILER_STATIC_ASSERT
+-# endif
+-# endif
+-#endif // Q_CC_CLANG
+-
+-#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+-# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
+-# define COMPILER_DECLTYPE
+-# define COMPILER_STATIC_ASSERT
+-# endif
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404
+-# define COMPILER_CLASS_ENUM
+-# endif
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+-# define COMPILER_CONSTEXPR
+-# define COMPILER_NULLPTR
+-# endif
+-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
+-# define COMPILER_EXPLICIT_OVERRIDES
+-# endif
+-# endif
+-#endif
+-
+-/*
+- * C++11 keywords and expressions
+- */
+-#if !defined(Q_NULLPTR)
+-# ifdef COMPILER_NULLPTR
+-# define Q_NULLPTR nullptr
+-# else
+-# define Q_NULLPTR 0
+-# endif
+-#endif
+-
+-#if !defined(Q_DECL_CONSTEXPR)
+-# ifdef COMPILER_CONSTEXPR
+-# define Q_DECL_CONSTEXPR constexpr
+-# else
+-# define Q_DECL_CONSTEXPR
+-# endif
+-#endif
+-
+-#if !defined(Q_DECL_OVERRIDE) && !defined(Q_DECL_FINAL) && !defined(Q_DECL_FINAL_CLASS)
+-# ifdef COMPILER_EXPLICIT_OVERRIDES
+-# define Q_DECL_OVERRIDE override
+-# define Q_DECL_FINAL final
+-# ifdef COMPILER_DECLTYPE
+-# define Q_DECL_FINAL_CLASS final
+-# else
+-# define Q_DECL_FINAL_CLASS
+-# endif
+-# else
+-# define Q_DECL_OVERRIDE
+-# define Q_DECL_FINAL
+-# define Q_DECL_FINAL_CLASS
+-# endif
+-#endif
+-
+-#if !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X)
+-#ifdef COMPILER_STATIC_ASSERT
+-#define Q_STATIC_ASSERT(Condition) static_assert(static_cast<bool>(Condition), #Condition)
+-#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(static_cast<bool>(Condition), Message)
+-#else
+-// Intentionally undefined
+-template <bool Test> class QStaticAssertFailure;
+-template <> class QStaticAssertFailure<true> {};
+-
+-#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
+-#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
+-#define Q_STATIC_ASSERT(Condition) \
+- enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure<!!(Condition)>)}
+-#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
+-#endif // COMPILER_STATIC_ASSERT
+-#endif // !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X)
+-
+ #if defined(Q_OS_WIN)
+ # if defined(KEEPASSX_BUILDING_CORE)
+ # define KEEPASSX_EXPORT Q_DECL_EXPORT
+diff --git a/src/core/Group.cpp b/src/core/Group.cpp
+index 371f3e4..2b9e9bc 100644
+--- a/src/core/Group.cpp
++++ b/src/core/Group.cpp
+@@ -20,7 +20,6 @@
+ #include "core/Config.h"
+ #include "core/DatabaseIcons.h"
+ #include "core/Metadata.h"
+-#include "core/Tools.h"
+
+ const int Group::DefaultIconNumber = 48;
+ const int Group::RecycleBinIconNumber = 43;
+@@ -50,7 +49,7 @@ Group::~Group()
+
+ if (m_db && m_parent) {
+ DeletedObject delGroup;
+- delGroup.deletionTime = Tools::currentDateTimeUtc();
++ delGroup.deletionTime = QDateTime::currentDateTimeUtc();
+ delGroup.uuid = m_uuid;
+ m_db->addDeletedObject(delGroup);
+ }
+@@ -84,8 +83,8 @@ template <class P, class V> inline bool Group::set(P& property, const V& value)
+ void Group::updateTimeinfo()
+ {
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
+- m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc());
++ m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc());
+ }
+ }
+
+@@ -203,7 +202,7 @@ Entry* Group::lastTopVisibleEntry() const
+
+ bool Group::isExpired() const
+ {
+- return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
++ return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
+ }
+
+ void Group::setUuid(const Uuid& uuid)
+@@ -365,7 +364,7 @@ void Group::setParent(Group* parent, int index)
+ }
+
+ if (m_updateTimeinfo) {
+- m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
++ m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc());
+ }
+
+ Q_EMIT modified();
+@@ -385,7 +384,7 @@ void Group::setParent(Database* db)
+
+ cleanupParent();
+
+- m_parent = Q_NULLPTR;
++ m_parent = nullptr;
+ recSetDatabase(db);
+
+ QObject::setParent(db);
+@@ -510,7 +509,7 @@ Group* Group::clone(Entry::CloneFlags entryFlags) const
+
+ clonedGroup->setUpdateTimeinfo(true);
+
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ clonedGroup->m_data.timeInfo.setCreationTime(now);
+ clonedGroup->m_data.timeInfo.setLastModificationTime(now);
+ clonedGroup->m_data.timeInfo.setLastAccessTime(now);
+diff --git a/src/core/InactivityTimer.h b/src/core/InactivityTimer.h
+index e0a21e0..ba571a5 100644
+--- a/src/core/InactivityTimer.h
++++ b/src/core/InactivityTimer.h
+@@ -21,8 +21,6 @@
+ #include <QMutex>
+ #include <QObject>
+
+-#include "core/Global.h"
+-
+ class QTimer;
+
+ class InactivityTimer : public QObject
+@@ -30,7 +28,7 @@ class InactivityTimer : public QObject
+ Q_OBJECT
+
+ public:
+- explicit InactivityTimer(QObject* parent = Q_NULLPTR);
++ explicit InactivityTimer(QObject* parent = nullptr);
+ void setInactivityTimeout(int inactivityTimeout);
+ void activate();
+ void deactivate();
+diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp
+index 0c67bba..a50c6ef 100644
+--- a/src/core/Metadata.cpp
++++ b/src/core/Metadata.cpp
+@@ -42,7 +42,7 @@ Metadata::Metadata(QObject* parent)
+ m_data.protectNotes = false;
+ // m_data.autoEnableVisualHiding = false;
+
+- QDateTime now = Tools::currentDateTimeUtc();
++ QDateTime now = QDateTime::currentDateTimeUtc();
+ m_data.nameChanged = now;
+ m_data.descriptionChanged = now;
+ m_data.defaultUserNameChanged = now;
+@@ -67,7 +67,7 @@ template <class P, class V> bool Metadata::set(P& property, const V& value, QDat
+ if (property != value) {
+ property = value;
+ if (m_updateDatetime) {
+- dateTime = Tools::currentDateTimeUtc();
++ dateTime = QDateTime::currentDateTimeUtc();
+ }
+ Q_EMIT modified();
+ return true;
+diff --git a/src/core/Metadata.h b/src/core/Metadata.h
+index 062e552..c35aed3 100644
+--- a/src/core/Metadata.h
++++ b/src/core/Metadata.h
+@@ -26,7 +26,6 @@
+ #include <QPixmapCache>
+ #include <QPointer>
+
+-#include "core/Global.h"
+ #include "core/Uuid.h"
+
+ class Database;
+@@ -37,7 +36,7 @@ class Metadata : public QObject
+ Q_OBJECT
+
+ public:
+- explicit Metadata(QObject* parent = Q_NULLPTR);
++ explicit Metadata(QObject* parent = nullptr);
+
+ struct MetadataData
+ {
+diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h
+index 6a9d212..cc8196f 100644
+--- a/src/core/PasswordGenerator.h
<Skipped 8982 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/keepassx.git/commitdiff/6a4b7e5574a9da380dea7179ab1d87cb43c5713d
More information about the pld-cvs-commit
mailing list