From adfa3da65a739e008b0d066ed1b48e47715d14eb Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Wed, 2 Dec 2020 23:20:35 +0330 Subject: [PATCH 1/8] remove qglobalshortcut --- CMakeLists.txt | 2 - src/main.cpp | 14 -- src/qglobalshortcut/qglobalshortcut.cc | 257 ------------------------- src/qglobalshortcut/qglobalshortcut.h | 64 ------ 4 files changed, 337 deletions(-) delete mode 100644 src/qglobalshortcut/qglobalshortcut.cc delete mode 100644 src/qglobalshortcut/qglobalshortcut.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a7e4de6a..4fe59f596 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -386,14 +386,12 @@ if(UNIX) src/unixcapturewindowutility.cpp src/autoprofilewatcher.cpp src/capturedwindowinfodialog.cpp - src/qglobalshortcut/qglobalshortcut.cc ) LIST(APPEND antimicrox_HEADERS src/x11extras.h src/qtx11keymapper.h src/unixcapturewindowutility.h src/autoprofilewatcher.h src/capturedwindowinfodialog.h - src/qglobalshortcut/qglobalshortcut.h ) if(WITH_XTEST) diff --git a/src/main.cpp b/src/main.cpp index 7e5d8e598..07b220fc1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,7 +26,6 @@ #include "joybuttonslot.h" #include "localantimicroserver.h" #include "mainwindow.h" -#include "qglobalshortcut/qglobalshortcut.h" #include "setjoystick.h" #include "simplekeygrabberbutton.h" @@ -850,19 +849,6 @@ int main(int argc, char *argv[]) QObject::connect(&antimicrox, &QApplication::aboutToQuit, &PadderCommon::mouseHelperObj, &MouseHelper::deleteDeskWid, Qt::DirectConnection); -#if defined(WITH_X11) - QString quitComboKeys = settings->value("QuitComboKeys", "").toString(); - - if (quitComboKeys != "") - { - qDebug() << "Loaded quit combo keys: " << quitComboKeys; - QGlobalShortcut *gs = new QGlobalShortcut; - gs->setKey(QKeySequence(quitComboKeys)); - QObject::connect(gs, &QGlobalShortcut::activated, &antimicrox, &QApplication::quit); - - QObject::connect(&antimicrox, &QApplication::aboutToQuit, gs, &QGlobalShortcut::deleteLater); - } -#endif QObject::connect(localServer, &LocalAntiMicroServer::clientdisconnect, mainWindow, &MainWindow::handleInstanceDisconnect); diff --git a/src/qglobalshortcut/qglobalshortcut.cc b/src/qglobalshortcut/qglobalshortcut.cc deleted file mode 100644 index bc3285197..000000000 --- a/src/qglobalshortcut/qglobalshortcut.cc +++ /dev/null @@ -1,257 +0,0 @@ -/* - from https://github.com/mitei/qglobalshortcut - author: mitei -*/ - -#include "qglobalshortcut.h" -#include -#include -#include - -#ifdef WITH_X11 - #include - #include - #include - #include -#endif - -QMultiHash QGlobalShortcut::shortcuts_; -QGlobalShortcut::QGlobalShortcutEventFilter QGlobalShortcut::global_shortcut_event_; - -QGlobalShortcut::QGlobalShortcut(QObject *parent) - : QObject(parent) -{ - initialize(); -} - -QGlobalShortcut::QGlobalShortcut(const QKeySequence &keyseq, QObject *parent) - : QObject(parent) -{ - initialize(); - setKey(keyseq); -} - -void QGlobalShortcut::initialize() -{ - static bool initialized = false; - if (!initialized) - { - qApp->installNativeEventFilter(&global_shortcut_event_); - initialized = true; - } -} - -QGlobalShortcut::~QGlobalShortcut() { unsetKey(); } - -QKeySequence QGlobalShortcut::key() const { return keyseq_; } - -void QGlobalShortcut::setKey(const QKeySequence &keyseq) -{ - if (!keyseq_.isEmpty()) - { - qDebug() << "Key is not empty"; - unsetKey(); - } - - quint32 keyid = calcId(keyseq); - qDebug() << "keyid is: " << keyid; - - if (shortcuts_.count(keyid) == 0) - { - quint32 keycode = toNativeKeycode(getKey(keyseq)); - quint32 mods = toNativeModifiers(getMods(keyseq)); - qDebug() << "keycode is: " << keycode; - qDebug() << "mods is: " << mods; - registerKey(keycode, mods, keyid); - } - - this->keyseq_ = keyseq; - shortcuts_.insert(keyid, this); -} - -void QGlobalShortcut::unsetKey() -{ - quint32 keyid = calcId(keyseq_); - if (shortcuts_.remove(keyid, this) > 0) - { - if (shortcuts_.count(keyid) == 0) - { - quint32 keycode = toNativeKeycode(getKey(keyseq_)); - quint32 mods = toNativeModifiers(getMods(keyseq_)); - unregisterKey(keycode, mods, keyid); - } - } -} - -bool QGlobalShortcut::activate(quint32 id) -{ - if (shortcuts_.contains(id)) - { - foreach (QGlobalShortcut *s, shortcuts_.values(id)) - { - emit s->activated(); - } - return true; - } - return false; -} - -quint32 QGlobalShortcut::calcId(const QKeySequence &keyseq) -{ - quint32 keycode = toNativeKeycode(getKey(keyseq)); - quint32 mods = toNativeModifiers(getMods(keyseq)); - return calcId(keycode, mods); -} - -#ifndef Q_OS_UNIX -quint32 QGlobalShortcut::calcId(quint32 k, quint32 m) { return k | m; } -#endif - -Qt::Key QGlobalShortcut::getKey(const QKeySequence &keyseq) -{ - if (keyseq.isEmpty()) - { - return Qt::Key(0); - } - return Qt::Key(keyseq[0] & ~Qt::KeyboardModifierMask); -} - -Qt::KeyboardModifiers QGlobalShortcut::getMods(const QKeySequence &keyseq) -{ - if (keyseq.isEmpty()) - { - return Qt::KeyboardModifiers(0); - } - return Qt::KeyboardModifiers(keyseq[0] & Qt::KeyboardModifierMask); -} - -#ifdef Q_OS_UNIX - #ifdef WITH_X11 -bool QGlobalShortcut::QGlobalShortcutEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) -{ - xcb_generic_event_t *e = static_cast(message); - if ((e->response_type & ~0x80) == XCB_KEY_PRESS) - { - xcb_key_press_event_t *ke = (xcb_key_press_event_t *)e; - xcb_get_keyboard_mapping_reply_t rep; - xcb_keysym_t *k = xcb_get_keyboard_mapping_keysyms(&rep); - quint32 keycode = ke->detail; - quint32 mods = ke->state & (ShiftMask | ControlMask | Mod1Mask | Mod3Mask); - return activate(calcId(keycode, mods)); - } - return false; -} - -quint32 QGlobalShortcut::calcId(quint32 k, quint32 m) { return k | (m << 16); } - -quint32 QGlobalShortcut::toNativeKeycode(Qt::Key k) -{ - /* keysymdef.h */ - quint32 key = 0; - if (k >= Qt::Key_F1 && k <= Qt::Key_F35) - { - key = XK_F1 + (k - Qt::Key_F1); - } else if (k >= Qt::Key_Space && k <= Qt::Key_QuoteLeft) - { - key = k; - } else if (k >= Qt::Key_BraceLeft && k <= Qt::Key_AsciiTilde) - { - key = k; - } else if (k >= Qt::Key_nobreakspace && k <= Qt::Key_ydiaeresis) - { - key = k; - } else - { - switch (k) - { - case Qt::Key_Escape: - key = XK_Escape; - break; - case Qt::Key_Tab: - case Qt::Key_Backtab: - key = XK_Tab; - break; - case Qt::Key_Backspace: - key = XK_BackSpace; - break; - case Qt::Key_Return: - case Qt::Key_Enter: - key = XK_Return; - break; - case Qt::Key_Insert: - key = XK_Insert; - break; - case Qt::Key_Delete: - key = XK_Delete; - break; - case Qt::Key_Pause: - key = XK_Pause; - break; - case Qt::Key_Print: - key = XK_Print; - break; - case Qt::Key_SysReq: - key = XK_Sys_Req; - break; - case Qt::Key_Clear: - key = XK_Clear; - break; - case Qt::Key_Home: - key = XK_Home; - break; - case Qt::Key_End: - key = XK_End; - break; - case Qt::Key_Left: - key = XK_Left; - break; - case Qt::Key_Up: - key = XK_Up; - break; - case Qt::Key_Right: - key = XK_Right; - break; - case Qt::Key_Down: - key = XK_Down; - break; - case Qt::Key_PageUp: - key = XK_Page_Up; - break; - case Qt::Key_PageDown: - key = XK_Page_Down; - break; - default: - key = 0; - } - } - return XKeysymToKeycode(QX11Info::display(), key); -} - -quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) -{ - quint32 mods = Qt::NoModifier; - if (m & Qt::NoModifier) - mods |= AnyModifier; - if (m & Qt::ShiftModifier) - mods |= ShiftMask; - if (m & Qt::ControlModifier) - mods |= ControlMask; - if (m & Qt::AltModifier) - mods |= Mod1Mask; - if (m & Qt::MetaModifier) - mods |= Mod4Mask; - - return mods; -} - -void QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) -{ - xcb_grab_key(QX11Info::connection(), 1, QX11Info::appRootWindow(), m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); -} - -void QGlobalShortcut::unregisterKey(quint32 k, quint32 m, quint32 id) -{ - xcb_ungrab_key(QX11Info::connection(), k, QX11Info::appRootWindow(), m); -} - #endif -#endif diff --git a/src/qglobalshortcut/qglobalshortcut.h b/src/qglobalshortcut/qglobalshortcut.h deleted file mode 100644 index 7da3c3a34..000000000 --- a/src/qglobalshortcut/qglobalshortcut.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - from https://github.com/mitei/qglobalshortcut - author: mitei -*/ - -#include -#include -#include -#include - -class QGlobalShortcut : public QObject -{ - Q_OBJECT - Q_PROPERTY(QKeySequence key READ key WRITE setKey) - // Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) - private: -#ifdef Q_OS_UNIX - #ifdef WITH_X11 - class QGlobalShortcutEventFilter : public QAbstractNativeEventFilter - { - public: - bool nativeEventFilter(const QByteArray &eventType, void *message, long *result); - }; - #endif -#endif - - public: - explicit QGlobalShortcut(QObject *parent = nullptr); - explicit QGlobalShortcut(const QKeySequence &keyseq, QObject *parent = nullptr); - ~QGlobalShortcut(); - bool nativeEventFilter(const QByteArray &event_type, void *message, long *result); - - QKeySequence key() const; - void setKey(const QKeySequence &keyseq); - // bool isEnabled() const; void setEnabled(bool on); - - signals: - void activated(); - - private: - QKeySequence keyseq_; - void unsetKey(); - void initialize(); - - private: - static QGlobalShortcutEventFilter global_shortcut_event_; - /* quint32 keyid - QGlobalShortcut* shortcut */ - static QMultiHash shortcuts_; - static bool activate(quint32 id); - static inline quint32 calcId(const QKeySequence &keyseq); - static inline Qt::Key getKey(const QKeySequence &keyseq); - static inline Qt::KeyboardModifiers getMods(const QKeySequence &keyseq); - -#ifdef Q_OS_UNIX - #ifdef WITH_X11 - static inline quint32 calcId(quint32 k, quint32 m); - static quint32 toNativeKeycode(Qt::Key k); - static quint32 toNativeModifiers(Qt::KeyboardModifiers m); - static void registerKey(quint32 k, quint32 m, quint32 id); - static void unregisterKey(quint32 k, quint32 m, quint32 id); - #endif -#endif -}; From c6956fa64d10bb94982fc13e067e18859d5a316d Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Wed, 2 Dec 2020 23:40:13 +0330 Subject: [PATCH 2/8] fix formatting --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 07b220fc1..498ea486d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -849,7 +849,6 @@ int main(int argc, char *argv[]) QObject::connect(&antimicrox, &QApplication::aboutToQuit, &PadderCommon::mouseHelperObj, &MouseHelper::deleteDeskWid, Qt::DirectConnection); - QObject::connect(localServer, &LocalAntiMicroServer::clientdisconnect, mainWindow, &MainWindow::handleInstanceDisconnect); QObject::connect(mainWindow, &MainWindow::mappingUpdated, joypad_worker.data(), &InputDaemon::refreshMapping); From cdc52db0722c57649c8fb7c0a34b94c96c2602f7 Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Thu, 3 Dec 2020 01:06:19 +0330 Subject: [PATCH 3/8] hide quit keys layout --- src/mainsettingsdialog.cpp | 2 + src/mainsettingsdialog.ui | 248 +++++++++++++++++++------------------ 2 files changed, 127 insertions(+), 123 deletions(-) diff --git a/src/mainsettingsdialog.cpp b/src/mainsettingsdialog.cpp index 6ebd60cb2..253e24b06 100644 --- a/src/mainsettingsdialog.cpp +++ b/src/mainsettingsdialog.cpp @@ -147,6 +147,8 @@ MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QListlaunchAtWinStartupCheckBox->setVisible(false); ui->keyRepeatGroupBox->setVisible(false); + ui->quitKeysLayout->setVisible(false); + bool useSingleProfileList = settings->value("TrayProfileList", false).toBool(); if (useSingleProfileList) { diff --git a/src/mainsettingsdialog.ui b/src/mainsettingsdialog.ui index 0407fe981..1e81878a9 100644 --- a/src/mainsettingsdialog.ui +++ b/src/mainsettingsdialog.ui @@ -104,7 +104,7 @@ - 3 + 0 @@ -341,133 +341,135 @@ first launches. 20 - 20 + 500 - - - 2 - - - 2 - - - 2 - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 144 - 0 - - - - - 144 - 36 - - - - Combination of keys for quitting app - - - Qt::AlignCenter - - - true - - - 0 - - - - - - - true - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 144 - 36 - - - - Choose keys combination - - - Qt::AlignCenter - - - true - - - - - - - true - - - - - - - - - - 50 - true - false - - - - ! restart is needed after choice of combination - - - - + + + + 2 + + + 2 + + + 2 + + + 2 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 144 + 0 + + + + + 144 + 36 + + + + Combination of keys for quitting app + + + Qt::AlignCenter + + + true + + + 0 + + + + + + + true + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 144 + 36 + + + + Choose keys combination + + + Qt::AlignCenter + + + true + + + + + + + true + + + + + + + + + + 50 + true + false + + + + ! restart is needed after choice of combination + + + + + From 302771c22623644fdbbfce114ac7a987c8ee85b3 Mon Sep 17 00:00:00 2001 From: Gergely Gombos Date: Fri, 4 Dec 2020 11:29:03 +0100 Subject: [PATCH 4/8] remove global quit shortcut functionality --- .github/workflows/main.yml | 4 +- .github/workflows/release.yml | 18 ++--- BUILDING.md | 11 ++- CMakeLists.txt | 7 +- src/mainsettingsdialog.cpp | 137 -------------------------------- src/mainsettingsdialog.h | 3 - src/mainsettingsdialog.ui | 143 +--------------------------------- 7 files changed, 18 insertions(+), 305 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f8f3e1e82..835e9a7f3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,8 +11,8 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext libqt5x11extras5-dev - + run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf6f03745..c3b882d9e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: Release_actions on: release: types: [published] - + jobs: #Build .deb files for debian-based systems. build_deb: @@ -12,8 +12,8 @@ jobs: steps: - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext libqt5x11extras5-dev - + run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 @@ -30,17 +30,17 @@ jobs: with: files: ./build/*.deb repo-token: ${{ secrets.GITHUB_TOKEN }} - + #Build universal and portable AppImage package. build-appimage: # Version of ubuntu building this appimage, it shouldn't be the latest verion of ubuntu to avoid breaking compatibility with older systems runs-on: ubuntu-18.04 needs: build_deb - + steps: - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext libqt5x11extras5-dev qt5-default libsdl2-2.0-0 libqt5x11extras5 zsync - + run: sudo apt-get update && sudo apt-get install g++ cmake extra-cmake-modules qttools5-dev qttools5-dev-tools libsdl2-dev libxi-dev libxtst-dev libx11-dev itstool gettext qt5-default libsdl2-2.0-0 zsync + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 @@ -52,9 +52,9 @@ jobs: MINOR=`echo $VERSION | cut -d " " -f 2` PATCH=`echo $VERSION | cut -d " " -f 3` wget "https://github.com/$GITHUB_REPOSITORY/releases/latest/download/antimicrox-$MAJOR.$MINOR.$PATCH-amd64.deb" - sudo dpkg -i `ls -1 | grep .deb` + sudo dpkg -i `ls -1 | grep .deb` + - - name: Prepare files to create apppimage run: | mkdir build && cd ./build diff --git a/BUILDING.md b/BUILDING.md index 81cd88bf4..74f11ddf3 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -26,7 +26,6 @@ installed on your system in order to build this program: - `libx11-dev` (`libx11` on distros based on Arch Linux) (Needed to compile with Qt5 support) - `itstool` (extracts messages from XML files and outputs PO template files, then merges translations from MO files to create translated XML files) - `gettext` -- `libqt5x11extras5-dev` (`qt5-x11extras` on distros based on Arch Linux) ## Building Under Linux @@ -61,16 +60,16 @@ options and describe their use in the project. -DUPDATE_TRANSLATIONS -Default: OFF. Set updateqm target to call lupdate in order to update +Default: OFF. Set updateqm target to call lupdate in order to update translation files from source. -DTRANS_KEEP_OBSOLETE - -Default: OFF. Do not specify -noobsolete option when calling lupdate + +Default: OFF. Do not specify -noobsolete option when calling lupdate command for qm files. -noobsolete is a method for getting rid of obsolete text entries -DWITH_TESTS - + Default: OFF. Allows for the launch of test sources with unit tests ### Linux Options @@ -110,7 +109,7 @@ mkdir build && cd ./build ``` Download tools used for creating appimages (and make them executable) -```bash +```bash wget https://github.com/linuxdeploy/linuxdeploy/releases/downloacontinuous/linuxdeploy-x86_64.AppImage wget https://github.com/AppImage/AppImageKit/releases/downloacontinuous/appimagetool-x86_64.AppImage wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releasedownload/continuous/linuxdeploy-plugin-qt-x86_64.AppImage diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fe59f596..1f7e0c306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,10 +435,6 @@ if(UNIX) find_package(Qt5Concurrent ${QT_REQUIRED_VERSION} REQUIRED) #find_package(Qt5Test REQUIRED) - if(WITH_X11) - find_package(Qt5X11Extras REQUIRED) - endif() - QT5_WRAP_CPP(antimicrox_HEADERS_MOC ${antimicrox_HEADERS}) QT5_WRAP_UI(antimicrox_FORMS_HEADERS ${antimicrox_FORMS}) QT5_ADD_RESOURCES(antimicrox_RESOURCES_RCC ${antimicrox_RESOURCES}) @@ -460,7 +456,6 @@ if(UNIX) if(WITH_X11) LIST(APPEND X11_LIBS ${X11_X11_LIB}) LIST(APPEND X11_LIBS ${X11_Xi_LIB}) - LIST(APPEND X11_LIBS Qt5::X11Extras) LIST(APPEND X11_LIBS xcb) endif(WITH_X11) @@ -597,7 +592,7 @@ endif() # Building .deb package if(CPACK_GENERATOR STREQUAL "DEB") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "qtbase5-dev (>= ${QT_REQUIRED_VERSION}), libsdl2-2.0-0 (>= ${SDL_REQUIRED_VERSION}), libqt5x11extras5, libc6") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "qtbase5-dev (>= ${QT_REQUIRED_VERSION}), libsdl2-2.0-0 (>= ${SDL_REQUIRED_VERSION}), libc6") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "pktiuk ") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "AntiMicroX is a graphical program used to map gamepad buttons to keyboard, mouse, scripts and macros. diff --git a/src/mainsettingsdialog.cpp b/src/mainsettingsdialog.cpp index 253e24b06..8f03f56be 100644 --- a/src/mainsettingsdialog.cpp +++ b/src/mainsettingsdialog.cpp @@ -20,11 +20,9 @@ #include "addeditautoprofiledialog.h" #include "antimicrosettings.h" -#include "antkeymapper.h" #include "autoprofileinfo.h" #include "common.h" #include "editalldefaultautoprofiledialog.h" -#include "event.h" #include "eventhandlerfactory.h" #include "globalvariables.h" #include "inputdevice.h" @@ -32,13 +30,6 @@ #ifdef WITH_X11 #include "x11extras.h" - #include - #include - #include - #include -#elif WITH_UINPUT - #include - #include #endif #include @@ -74,14 +65,6 @@ MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QListquitCombLineEdit->hide(); - ui->quitComboLabel->hide(); - ui->keysComboBox->hide(); - ui->keysLabel->hide(); - ui->warningComb->hide(); -#endif - ui->profileOpenDirPushButton->setIcon( PadderCommon::loadIcon("document-open", ":/icons/actions/document_open_folder.png")); @@ -96,7 +79,6 @@ MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QListgetLock()->lock(); bool attachedNumKeypad = settings->value("AttachNumKeypad", false).toBool(); - QString quitComboKeys = settings->value("QuitComboKeys", "").toString(); QString defaultProfileDir = settings->value("DefaultProfileDir", "").toString(); int numberRecentProfiles = settings->value("NumberRecentProfiles", 5).toInt(); bool closeToTray = settings->value("CloseToTray", false).toBool(); @@ -147,8 +129,6 @@ MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QListlaunchAtWinStartupCheckBox->setVisible(false); ui->keyRepeatGroupBox->setVisible(false); - ui->quitKeysLayout->setVisible(false); - bool useSingleProfileList = settings->value("TrayProfileList", false).toBool(); if (useSingleProfileList) { @@ -189,10 +169,6 @@ MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QListattachNumKeypadCheckbox->setChecked(true); - initializeKeysList(); - - ui->quitCombLineEdit->setText(quitComboKeys); - bool smoothingEnabled = settings->value("Mouse/Smoothing", false).toBool(); if (smoothingEnabled) { @@ -270,8 +246,6 @@ MainSettingsDialog::MainSettingsDialog(AntiMicroSettings *settings, QListactiveCheckBox, &QCheckBox::toggled, this, &MainSettingsDialog::autoProfileButtonsActiveState); connect(ui->devicesComboBox, static_cast(&QComboBox::activated), this, &MainSettingsDialog::changeDeviceForProfileTable); - connect(ui->keysComboBox, static_cast(&QComboBox::currentTextChanged), this, - &MainSettingsDialog::addKeyToQuitCombination); connect(ui->autoProfileTableWidget, &QTableWidget::itemChanged, this, &MainSettingsDialog::processAutoProfileActiveClick); connect(ui->autoProfileAddPushButton, &QPushButton::clicked, this, &MainSettingsDialog::openAddAutoProfileDialog); @@ -503,10 +477,6 @@ void MainSettingsDialog::saveNewSettings() settings->setValue("AttachNumKeypad", attachNumKeypad ? "1" : "0"); -#if defined(WITH_X11) - settings->setValue("QuitComboKeys", !ui->quitCombLineEdit->text().isEmpty() ? ui->quitCombLineEdit->text() : ""); -#endif - if (oldProfileDir != possibleProfileDir) { if (QFileInfo(possibleProfileDir).exists()) @@ -1056,13 +1026,6 @@ void MainSettingsDialog::changeDeviceForProfileTable(int index) &MainSettingsDialog::processAutoProfileActiveClick); } -void MainSettingsDialog::addKeyToQuitCombination(QString key) -{ - qInstallMessageHandler(MessageHandler::myMessageOutput); - - ui->quitCombLineEdit->setText(key); -} - void MainSettingsDialog::saveAutoProfileSettings() { qInstallMessageHandler(MessageHandler::myMessageOutput); @@ -1985,10 +1948,6 @@ void MainSettingsDialog::resetMouseSett() ui->weightModifierDoubleSpinBox->setValue(0.20); ui->weightModifierDoubleSpinBox->setEnabled(false); -#if defined(WITH_X11) - ui->quitCombLineEdit->clear(); -#endif - int refreshIndex = ui->mouseRefreshRateComboBox->findData(GlobalVariables::JoyButton::mouseRefreshRate); if (refreshIndex >= 0) @@ -2010,102 +1969,6 @@ void MainSettingsDialog::resetAdvancedSett() ui->logLevelComboBox->setCurrentIndex(0); } -void MainSettingsDialog::initializeKeysList() -{ - - QStringList keySysNames = QStringList(); - - // standard shortcuts for Linux - keySysNames.append("F1"); - keySysNames.append("Shift+F1"); - keySysNames.append("Ctrl+O"); - keySysNames.append("Ctrl+W"); - keySysNames.append("Ctrl+S"); - keySysNames.append("Ctrl+Q"); - keySysNames.append("Ctrl+N"); - keySysNames.append("Del"); - keySysNames.append("Ctrl+D"); - keySysNames.append("Ctrl+X"); - keySysNames.append("Shift+Del"); - keySysNames.append("Ctrl+C"); - keySysNames.append("Ctrl+Ins"); - keySysNames.append("Ctrl+V"); - keySysNames.append("Shift+Ins"); - keySysNames.append("Ctrl+Z"); - keySysNames.append("Ctrl+Shift+Z"); - keySysNames.append("Alt+Left"); - keySysNames.append("Alt+Right"); - keySysNames.append("F5"); - keySysNames.append("Ctrl+Plus"); - keySysNames.append("Ctrl+Minus"); - keySysNames.append("Ctrl+Shift+F"); - keySysNames.append("Ctrl+P"); - keySysNames.append("Ctrl+T"); - keySysNames.append("Ctrl+Tab"); - keySysNames.append("Forward"); - keySysNames.append("Ctrl+Shift+Tab"); - keySysNames.append("Back"); - keySysNames.append("Ctrl+F"); - keySysNames.append("F3"); - keySysNames.append("Shift+F3"); - keySysNames.append("Ctrl+A"); - keySysNames.append("Ctrl+Shift+A"); - keySysNames.append("Ctrl+B"); - keySysNames.append("Ctrl+I"); - keySysNames.append("Ctrl+U"); - keySysNames.append("Right"); - keySysNames.append("Left"); - keySysNames.append("Ctrl+Right"); - keySysNames.append("Ctrl+Left"); - keySysNames.append("Down"); - keySysNames.append("Up"); - keySysNames.append("PgDown"); - keySysNames.append("PgUp"); - keySysNames.append("Home"); - keySysNames.append("End"); - keySysNames.append("Ctrl+E"); - keySysNames.append("Ctrl+Home"); - keySysNames.append("Ctrl+End"); - keySysNames.append("Shift+Right"); - keySysNames.append("Shift+Left"); - keySysNames.append("Ctrl+Shift+Right"); - keySysNames.append("Ctrl+Shift+Left"); - keySysNames.append("Shift+Down"); - keySysNames.append("Shift+Up"); - keySysNames.append("Shift+PgDown"); - keySysNames.append("Shift+PgUp"); - keySysNames.append("Shift+Home"); - keySysNames.append("Shift+End"); - keySysNames.append("Ctrl+Shift+Home"); - keySysNames.append("Ctrl+Shift+End"); - keySysNames.append("Ctrl+Backspace"); - keySysNames.append("Ctrl+Del"); - keySysNames.append("Ctrl+K"); - keySysNames.append("Ctrl+U"); - keySysNames.append("Enter"); - keySysNames.append("Shift+Enter"); - keySysNames.append("Escape"); - - if (keysymToKeyString(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_F20)) != tr("[NO KEY]")) - keySysNames.append("F20"); - - if (keysymToKeyString(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_F16)) != tr("[NO KEY]")) - keySysNames.append("F16"); - - if (keysymToKeyString(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_F18)) != tr("[NO KEY]")) - keySysNames.append("F18"); - - if (keysymToKeyString(AntKeyMapper::getInstance()->returnVirtualKey(Qt::Key_F18)) != tr("[NO KEY]")) - keySysNames.append("F14"); - - if (ui->keysComboBox->count() > 0) - ui->keysComboBox->clear(); - - ui->keysComboBox->addItems(keySysNames); - - update(); -} - void MainSettingsDialog::convToUniqueIDAutoProfGroupSett(QSettings *sett, QString guidAutoProfSett, QString uniqueAutoProfSett) { diff --git a/src/mainsettingsdialog.h b/src/mainsettingsdialog.h index 1aa48fae1..716f6df45 100644 --- a/src/mainsettingsdialog.h +++ b/src/mainsettingsdialog.h @@ -56,7 +56,6 @@ class MainSettingsDialog : public QDialog AutoProfileInfo *getAllDefaultProfile() const; QList *getConnectedDevices() const; - QStringList &getChosenQuitComboKeys() const; protected: void fillControllerMappingsTable(); // MainSettingsMapping class @@ -83,7 +82,6 @@ class MainSettingsDialog : public QDialog void selectDefaultProfileDir(); // MainSettingsProfile class void fillGUIDComboBox(); // MainSettingsProfile class void changeDeviceForProfileTable(int index); // MainSettingsProfile class - void addKeyToQuitCombination(QString key); // MainSettingsProfile class void saveAutoProfileSettings(); // MainSettingsProfile class void processAutoProfileActiveClick(QTableWidgetItem *item); // MainSettingsProfile class void openAddAutoProfileDialog(); // MainSettingsProfile class @@ -121,7 +119,6 @@ class MainSettingsDialog : public QDialog void resetAutoProfSett(); void resetMouseSett(); void resetAdvancedSett(); - void initializeKeysList(); }; #endif // MAINSETTINGSDIALOG_H diff --git a/src/mainsettingsdialog.ui b/src/mainsettingsdialog.ui index 1e81878a9..bf66923ed 100644 --- a/src/mainsettingsdialog.ui +++ b/src/mainsettingsdialog.ui @@ -341,148 +341,7 @@ first launches. 20 - 500 - - - - - - - - - 2 - - - 2 - - - 2 - - - 2 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 144 - 0 - - - - - 144 - 36 - - - - Combination of keys for quitting app - - - Qt::AlignCenter - - - true - - - 0 - - - - - - - true - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 144 - 36 - - - - Choose keys combination - - - Qt::AlignCenter - - - true - - - - - - - true - - - - - - - - - - 50 - true - false - - - - ! restart is needed after choice of combination - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 8 + 100 From f7559ba5298246875e92b5610d28056df4aa7fd6 Mon Sep 17 00:00:00 2001 From: Gergely Gombos Date: Fri, 4 Dec 2020 11:38:30 +0100 Subject: [PATCH 5/8] Remove xcb dependency --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f7e0c306..1cbd11f34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -456,7 +456,6 @@ if(UNIX) if(WITH_X11) LIST(APPEND X11_LIBS ${X11_X11_LIB}) LIST(APPEND X11_LIBS ${X11_Xi_LIB}) - LIST(APPEND X11_LIBS xcb) endif(WITH_X11) if(WITH_XTEST) From fae77d54a2891002b2ff91eb1c952ac9b6a67c98 Mon Sep 17 00:00:00 2001 From: Gergely Gombos Date: Sat, 5 Dec 2020 13:39:45 +0100 Subject: [PATCH 6/8] feat: cmake config for windows --- .gitignore | 3 + CMakeLists.txt | 377 ++++++++++++- cmake/FindSDL2.cmake | 202 +++++++ .../winsendinputeventhandler.cpp | 239 +++++++++ src/eventhandlers/winsendinputeventhandler.h | 52 ++ src/eventhandlers/winvmultieventhandler.cpp | 395 ++++++++++++++ src/eventhandlers/winvmultieventhandler.h | 73 +++ src/winextras.cpp | 502 ++++++++++++++++++ src/winextras.h | 49 ++ 9 files changed, 1865 insertions(+), 27 deletions(-) create mode 100644 cmake/FindSDL2.cmake create mode 100644 src/eventhandlers/winsendinputeventhandler.cpp create mode 100644 src/eventhandlers/winsendinputeventhandler.h create mode 100644 src/eventhandlers/winvmultieventhandler.cpp create mode 100644 src/eventhandlers/winvmultieventhandler.h create mode 100644 src/winextras.cpp create mode 100644 src/winextras.h diff --git a/.gitignore b/.gitignore index 606ac26a6..e7841f6b3 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ src/CHANGELOG.md # IDE- related files .vscode +# Windows SDL +SDL2-*/ +CMakeLists.txt.user diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c7e716c9..bbcb145a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,26 +16,28 @@ ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . +# TODO +set(SDL2_DIR "C:/Users/HP/Desktop/prog/antimicrox/SDL2-2.0.12/i686-w64-mingw32") cmake_minimum_required(VERSION 3.6) set(QT_REQUIRED_VERSION 5.8) set(SDL_REQUIRED_VERSION 2.0.6) project(antimicrox) -if(POLICY CMP0071) - cmake_policy(SET CMP0071 NEW) -endif() +# already default? +# if(POLICY CMP0071) +# cmake_policy(SET CMP0071 NEW) +# endif() -if(UNIX) - find_package(ECM REQUIRED NO_MODULE) - set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR}) -endif(UNIX) +# if(UNIX) +# find_package(ECM REQUIRED NO_MODULE) +# set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR}) +# endif(UNIX) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" "${CMAKE_ROOT}/Modules") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") set(CMAKE_INCLUDE_CURRENT_DIR ON) - if(UNIX AND NOT APPLE AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "force cmake prefix to be set for /usr" FORCE) endif(UNIX AND NOT APPLE AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) @@ -49,14 +51,8 @@ endif(UNIX) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) - if(COMPILER_SUPPORTS_CXX11) - if(NOT WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -std=c++11") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") else() message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif(COMPILER_SUPPORTS_CXX11) @@ -85,9 +81,9 @@ option(ATTACH_FAKE_CLASSES "Fake classes can be used in application to tests fun if(UNIX) - find_package(PkgConfig REQUIRED) + # find_package(PkgConfig REQUIRED) - pkg_check_modules(SDL2 REQUIRED sdl2) + # pkg_check_modules(SDL2 REQUIRED sdl2) # find_package(SDL2 REQUIRED) -> will fail on some systems if(WITH_X11) @@ -112,6 +108,38 @@ if(UNIX) endif(NOT WITH_XTEST AND NOT WITH_UINPUT) endif(UNIX) +if(WIN32) + option(PORTABLE_PACKAGE "Create portable Windows package" OFF) + #option(TARGET_ARCH "Choose which version of some libraries to use. (x86, x86_64)" "x86") + # option(WITH_VMULTI "Compile with support for vmulti." OFF) + option(PERFORM_SIGNING "Sign final executable." OFF) + + if(PORTABLE_PACKAGE) + message("Portable package mode build") + + add_definitions(-DWIN_PORTABLE_PACKAGE) + + # Only way to force install target to be dependent on createprofiledir. + add_custom_target(createprofiledir) + add_custom_command(TARGET createprofiledir PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/profiles" + ) + install(CODE "execute_process(COMMAND ${CMAKE_BUILD_TOOL} createprofiledir WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\")") + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/profiles" DESTINATION ${CMAKE_INSTALL_PREFIX}) + endif(PORTABLE_PACKAGE) + + # Find target architecture based on the compiler. + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(TARGET_ARCH "x86_64") + else() + set(TARGET_ARCH "x86") + endif(CMAKE_SIZEOF_VOID_P EQUAL 8) + + # if(WITH_VMULTI) + # add_definitions(-DWITH_VMULTI) + # endif(WITH_VMULTI) +endif(WIN32) + set(antimicrox_MAIN src/main.cpp) set(antimicrox_SOURCES @@ -378,7 +406,10 @@ set(antimicrox_FORMS set(antimicrox_RESOURCES src/resources.qrc) -# Platform dependent files. +############################### +# PLATFORM-DEPENDENT FILES +############################### + if(UNIX) if(WITH_X11) LIST(APPEND antimicrox_SOURCES src/x11extras.cpp @@ -412,8 +443,46 @@ if(UNIX) src/eventhandlers/uinputeventhandler.h ) endif(WITH_UINPUT) + +elseif(WIN32) + LIST(APPEND antimicro_SOURCES + src/winextras.cpp + src/qtwinkeymapper.cpp + # src/winappprofiletimerdialog.cpp + # src/capturedwindowinfodialog.cpp + src/eventhandlers/winsendinputeventhandler.cpp + src/joykeyrepeathelper.cpp + ) + LIST(APPEND antimicro_HEADERS + src/winextras.h + src/qtwinkeymapper.h + # src/winappprofiletimerdialog.h + # src/capturedwindowinfodialog.h + src/eventhandlers/winsendinputeventhandler.h + src/joykeyrepeathelper.h + ) + # LIST(APPEND antimicro_FORMS src/winappprofiletimerdialog.ui) + # Add Windows specific resource file used for application icons. + # LIST(APPEND antimicro_RESOURCES src/resources_windows.qrc) + +# if(WITH_VMULTI) +# list(APPEND antimicro_SOURCES src/qtvmultikeymapper.cpp +# src/eventhandlers/winvmultieventhandler.cpp +# # vmulti/client/client.c +# ) +# list(APPEND antimicro_HEADERS src/qtvmultikeymapper.h +# src/eventhandlers/winvmultieventhandler.h +# ) +# endif(WITH_VMULTI) + endif(UNIX) +############################### +# DEFINITIONS +############################### + +add_definitions(-DUSE_SDL_2) + if(UNIX) if(WITH_X11) add_definitions(-DWITH_X11) @@ -428,6 +497,10 @@ if(UNIX) endif(WITH_UINPUT) endif(UNIX) +############################### +# PACKAGES +############################### + if(UNIX) find_package(Qt5Widgets ${QT_REQUIRED_VERSION} REQUIRED) find_package(Qt5Core ${QT_REQUIRED_VERSION} REQUIRED) @@ -448,10 +521,46 @@ if(UNIX) add_subdirectory("share/antimicrox/translations") set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +elseif(WIN32) + find_package(Qt5Widgets REQUIRED) + find_package(Qt5Core REQUIRED) + find_package(Qt5Gui REQUIRED) + find_package(Qt5Network REQUIRED) + find_package(Qt5LinguistTools REQUIRED) + find_package(Qt5Concurrent ${QT_REQUIRED_VERSION} REQUIRED) + + QT5_WRAP_UI(antimicro_FORMS_HEADERS ${antimicro_FORMS}) + QT5_ADD_RESOURCES(antimicro_RESOURCES_RCC ${antimicro_RESOURCES}) + add_subdirectory("share/antimicrox/translations") + + include_directories(${Qt5Widgets_INCLUDE_DIRS}) + add_definitions(${Qt5Widgets_DEFINITIONS}) + include_directories(${Qt5Core_INCLUDE_DIRS}) + add_definitions(${Qt5Core_DEFINITIONS}) + include_directories(${Qt5Gui_INCLUDE_DIRS}) + add_definitions(${Qt5Gui_DEFINITIONS}) + include_directories(${Qt5Network_INCLUDE_DIRS}) + add_definitions(${Qt5Network_DEFINITIONS}) + + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + + # Add compiler flags for building executables (-fPIE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") + + # LIST(APPEND LIBS ${Qt5Widgets_LIBRARIES} + # ${Qt5Core_LIBRARIES} + # ${Qt5Gui_LIBRARIES} + # ${Qt5Network_LIBRARIES} + # ) endif(UNIX) +find_package(SDL2 REQUIRED) + +############################### +# LINKER LIBRARIES +############################### -# linker libraries LIST(APPEND QT_LIBS Qt5::Core) LIST(APPEND QT_LIBS Qt5::Gui) LIST(APPEND QT_LIBS Qt5::Widgets) @@ -474,44 +583,78 @@ if(UNIX) # if(NOT DEFINED SDL2_LIBRARIES) # set(SDL2_LIBRARIES SDL2::SDL2) # endif() -endif(UNIX) +elseif (WIN32) + # include_directories(${SDL2_INCLUDE_DIRS}) + message("SDL2 include dir: ${SDL2_INCLUDE_DIRS}") + # list(APPEND LIBS ${SDL2_LIBRARIES}) + + add_definitions(-DUNICODE -D_UNICODE) + list(APPEND WIN_LIBS "psapi") + + if(WITH_VMULTI) + include_directories("${PROJECT_SOURCE_DIR}/vmulti/inc") + list(APPEND WIN_LIBS "hid" "setupapi") + endif(WITH_VMULTI) +endif(UNIX) include_directories( ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_BINARY_DIR}/src" ${PROJECT_SOURCE_DIR} "${PROJECT_SOURCE_DIR}/src" + ${SDL2_INCLUDE_DIRS} ) - if(UNIX) # Store executable in a bin subdir. Needed here so translations can be loaded. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") endif(UNIX) +############################### +# COMPILE & LINK +############################### -add_executable(antimicrox +if(UNIX) + add_executable(antimicrox + ${antimicrox_MAIN} + ${antimicrox_HEADERS_MOC} + ${antimicrox_SOURCES} + ${antimicrox_FORMS_HEADERS} + ${antimicrox_RESOURCES_RCC} + ) +elseif(WIN32) + # The WIN32 is required to specify a GUI application. + add_executable(antimicrox WIN32 ${antimicrox_MAIN} ${antimicrox_HEADERS_MOC} ${antimicrox_SOURCES} ${antimicrox_FORMS_HEADERS} ${antimicrox_RESOURCES_RCC} - ) + # TODO create this with windows .ico icon + # src/antimicrox.rc + ) +endif(UNIX) target_link_libraries(antimicrox ${QT_LIBS} ${X11_LIBS} + ${WIN_LIBS} ${SDL2_LIBRARIES} ${EXTRA_LIBS} ) +############################### +# INSTALL +############################### # Specify out directory for final executable. if(UNIX) install(TARGETS antimicrox RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") # install(TARGETS antilib DESTINATION "${CMAKE_INSTALL_LIBDIR}") install(FILES ${antimicrox_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/antimicrox") +elseif(WIN32) + install(TARGETS antimicrox RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) endif(UNIX) if(UNIX) @@ -569,16 +712,196 @@ configure_file( file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/src/) +############################### +# WINDOWS PACKAGING WARNING UNTESTED +############################### + +if(WIN32) + #if(TARGET_ARCH STREQUAL "x86_64") + # # Copy SDL2.dll to find installation directory. + # add_custom_target(copy_sdl_dll + # COMMAND ${CMAKE_COMMAND} -E copy "${SDL2_BASE_DIR}/x86_64-w64-mingw32/bin/SDL2.dll" ${CMAKE_CURRENT_BINARY_DIR} + # ) + #else() + # # Copy SDL2.dll to find installation directory. + # add_custom_target(copy_sdl_dll + # COMMAND ${CMAKE_COMMAND} -E copy "${SDL2_BASE_DIR}/i686-w64-mingw32/bin/SDL2.dll" ${CMAKE_CURRENT_BINARY_DIR} + # ) + #endif(TARGET_ARCH STREQUAL "x86_64") + + add_custom_target(copy_sdl_dll + COMMAND ${CMAKE_COMMAND} -E copy "${SDL2_DLL_LOCATION_DIR}/SDL2.dll" ${CMAKE_CURRENT_BINARY_DIR} + ) + + + # Obtain location of Qt5 DLL files and assign them to a list. + # This list will only be used for Release builds. + get_target_property(QTCORE_DLL_LOCATION Qt5::Core LOCATION) + string(REPLACE "/Qt5Core.dll" "" QTCORE_DLL_LOCATION ${QTCORE_DLL_LOCATION}) + set(EXTRA_QT_DLL_FILES + "${QTCORE_DLL_LOCATION}/Qt5Core.dll" + "${QTCORE_DLL_LOCATION}/Qt5Gui.dll" + "${QTCORE_DLL_LOCATION}/Qt5Network.dll" + "${QTCORE_DLL_LOCATION}/Qt5Widgets.dll" + ) + + find_library(EXTRA_DLLS_PTHREAD NAMES "libwinpthread-1.dll" ) + find_library(EXTRA_DLLS_LIBCPP NAMES "libstdc++-6.dll" ) + + # Don't think find_library will handle versioned DLLS, so we'll try each one until we find something + foreach( ICU_VER 51 52 53 54 55 56 57 58 59 ) + find_library(ICU_DT_DLL NAMES "icudt${ICU_VER}.dll") + find_library(ICU_IN_DLL NAMES "icuin${ICU_VER}.dll") + find_library(ICU_UC_DLL NAMES "icuuc${ICU_VER}.dll") + endforeach( ICU_VER ) + + list(APPEND EXTRA_DLL_FILES + ${EXTRA_QT_DLL_FILES} + ${EXTRA_DLLS_PTHREAD} + ${EXTRA_DLLS_LIBCPP} + ${ICU_DT_DLL} + ${ICU_IN_DLL} + ${ICU_UC_DLL} + ) + + # Copy relevant DLL files depending on the chosen architecture. + if(TARGET_ARCH STREQUAL "x86_64") + find_library( GCC_DLL "libgcc_s_seh-1.dll" ) + + list(APPEND EXTRA_DLL_FILES + ${GCC_DLL} + "${SDL2_BASE_DIR}/x86_64-w64-mingw32/bin/SDL2.dll" + ) + else() + find_library( GCC_DLL "libgcc_s_dw2-1.dll" ) + + list(APPEND EXTRA_DLL_FILES + ${GCC_DLL} + "${SDL2_BASE_DIR}/i686-w64-mingw32/bin/SDL2.dll" + ) + endif(TARGET_ARCH STREQUAL "x86_64") + + # Not a DLL file, but needs to travel with SDL2.DLL + list(APPEND EXTRA_DLL_FILES "${SDL2_BASE_DIR}/README-SDL.txt") + + # Target to copy Qt DLL files. + add_custom_target(install_extra_dlls) + + # Create destination directory if it does not exist. + add_custom_command(TARGET install_extra_dlls PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_INSTALL_PREFIX}/" + ) + + foreach(CURRENT_DLL_FILE ${EXTRA_DLL_FILES}) + add_custom_command(TARGET install_extra_dlls PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CURRENT_DLL_FILE} "${CMAKE_INSTALL_PREFIX}/" + ) + endforeach() + + # Target to copy qwindows.dll platforms file. + add_custom_target(install_platforms_dll) + add_custom_command(TARGET install_platforms_dll PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${QTCORE_DLL_LOCATION}/../plugins/platforms/qwindows.dll" + "${CMAKE_INSTALL_PREFIX}/platforms/qwindows.dll" + ) + + # Combine the two targets into a single target that will be used + # while bundling the program. + add_custom_target(install_dlls) + add_dependencies(install_dlls + install_extra_dlls + install_platforms_dll + ) + + # Copy bundled Qt translation files. + SET(QT_TRANSLATION_PATH "${QTCORE_DLL_LOCATION}/../translations/" ) + file(GLOB QT_TRANSLATION_FILES "${QT_TRANSLATION_PATH}qt_[^help]*.qm") + add_custom_target(copy_qt_translations) + foreach(CURRENT_QM_FILE ${QT_TRANSLATION_FILES}) + set(CURRENT_QM_FILENAME "") + string(REPLACE ${QT_TRANSLATION_PATH} "" CURRENT_QM_FILENAME ${CURRENT_QM_FILE}) + add_custom_command(TARGET copy_qt_translations PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${CURRENT_QM_FILE}" + "${CMAKE_INSTALL_PREFIX}/share/qt/translations/${CURRENT_QM_FILENAME}" + ) + endforeach() + + # Sign final executable + if(PERFORM_SIGNING) + install(CODE "execute_process(COMMAND \"C:/Program Files (x86)/Windows Kits/8.1/bin/x64/signtool.exe\" + sign /v /a /s ROOT /n antimicrox ${CMAKE_INSTALL_PREFIX}/antimicrox.exe)") + endif(PERFORM_SIGNING) + + # Set variables needed for MSI building. + set(MSIFOLDER "${PROJECT_SOURCE_DIR}/windows") + set(WIXENV $ENV{WIX}) + + # Use a different file for each architecture due + # to some DLL differences. + if(TARGET_ARCH STREQUAL "x86_64") + set(WIXWXS "${MSIFOLDER}/antimicro_64.wxs") + else() + set(WIXWXS "${MSIFOLDER}/antimicrox.wxs") + endif(TARGET_ARCH STREQUAL "x86_64") + + set(WIXOBJ "${MSIFOLDER}/antimicrox.wixobj") + + # Use version number in output file name. + set(MSIFILENAME "${ANTIMICRO_MAJOR_VERSION}.${ANTIMICRO_MINOR_VERSION}") + if(ANTIMICRO_PATCH_VERSION AND NOT ANTIMICRO_PATCH_VERSION EQUAL 0) + set(MSIFILENAME "${MSIFILENAME}.${ANTIMICRO_PATCH_VERSION}") + endif(ANTIMICRO_PATCH_VERSION AND NOT ANTIMICRO_PATCH_VERSION EQUAL 0) + + # Change output file depending on the target architecture. + if(TARGET_ARCH STREQUAL "x86_64") + set(WIXMSI "${MSIFOLDER}/antimicrox-${MSIFILENAME}-win64.msi") + else() + set(WIXMSI "${MSIFOLDER}/antimicrox-${MSIFILENAME}-win32.msi") + endif(TARGET_ARCH STREQUAL "x86_64") + + if(NOT WIXENV) + # Display message when WIX is not set up. No extra target will be added. + message("MSI package building not possible: WIX environment variable not defined.") + else() + # Target to build .msi installer file. + add_custom_target(buildmsi) + + # Change arch value passed to candle.exe + set(WIXARCH "") + if(TARGET_ARCH STREQUAL "x86_64") + set(WIXARCH "x64") + else() + set(WIXARCH "x86") + endif(TARGET_ARCH STREQUAL "x86_64") + + add_custom_command(TARGET buildmsi PRE_BUILD + COMMAND "${WIXENV}\\bin\\candle.exe" ${WIXWXS} -out ${WIXOBJ} -sw1113 -arch ${WIXARCH} && + "${WIXENV}\\bin\\light.exe" ${WIXOBJ} -out ${WIXMSI} -sw1076 -spdb + ) + set(WIXFILES ${WIXOBJ} ${WIXMSI}) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${WIXFILES}") + endif(NOT WIXENV) + + # Copy extra files to include in the final archive. + install(FILES gpl.txt Changelog README.md ProfileTips.md + DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif(WIN32) + +############################### +# TESTING +############################### + if(WITH_TESTS) enable_testing() add_subdirectory(tests) endif(WITH_TESTS) +############################### +# CPACK BUILD +############################### -#building package using CPack include(InstallRequiredSystemLibraries) - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Program used to map keyboard keys and mouse controls to a gamepad.") @@ -603,7 +926,7 @@ if(CPACK_GENERATOR STREQUAL "DEB") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "pktiuk ") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "AntiMicroX is a graphical program used to map gamepad buttons to keyboard, mouse, scripts and macros. -It is a new fork of discontinued AntiMicro.") +It is a new fork of discontinued antimicrox.") message("Preparing documentation for DEB package") add_custom_target(package_docummentation ALL) diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake new file mode 100644 index 000000000..795ecff6a --- /dev/null +++ b/cmake/FindSDL2.cmake @@ -0,0 +1,202 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindSDL2 +# ------- +# +# Locate SDL2 library +# +# This module defines +# +# :: +# +# SDL2_LIBRARY, the name of the library to link against +# SDL2_FOUND, if false, do not try to link to SDL +# SDL2_INCLUDE_DIR, where to find SDL.h +# SDL2_VERSION_STRING, human-readable string containing the version of SDL +# +# +# +# This module responds to the flag: +# +# :: +# +# SDL2_BUILDING_LIBRARY +# If this is defined, then no SDL2_main will be linked in because +# only applications need main(). +# Otherwise, it is assumed you are building an application and this +# module will attempt to locate and set the proper link flags +# as part of the returned SDL2_LIBRARY variable. +# +# +# +# Don't forget to include SDLmain.h and SDLmain.m your project for the +# OS X framework based version. (Other versions link to -lSDLmain which +# this module will try to find on your behalf.) Also for OS X, this +# module will automatically add the -framework Cocoa on your behalf. +# +# +# +# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your +# configuration and no SDL2_LIBRARY, it means CMake did not find your SDL +# library (SDL.dll, libsdl.so, SDL.framework, etc). Set +# SDL2_LIBRARY_TEMP to point to your SDL library, and configure again. +# Similarly, if you see an empty SDLMAIN_LIBRARY, you should set this +# value as appropriate. These values are used to generate the final +# SDL2_LIBRARY variable, but when these values are unset, SDL2_LIBRARY +# does not get created. +# +# +# +# $SDL2DIR is an environment variable that would correspond to the +# ./configure --prefix=$SDL2DIR used in building SDL. l.e.galup 9-20-02 +# +# Modified by Eric Wing. Added code to assist with automated building +# by using environmental variables and providing a more +# controlled/consistent search behavior. Added new modifications to +# recognize OS X frameworks and additional Unix paths (FreeBSD, etc). +# Also corrected the header search path to follow "proper" SDL +# guidelines. Added a search for SDLmain which is needed by some +# platforms. Added a search for threads which is needed by some +# platforms. Added needed compile switches for MinGW. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of SDL2_LIBRARY to +# override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. +# +# Note that the header path has changed from SDL/SDL.h to just SDL.h +# This needed to change because "proper" SDL convention is #include +# "SDL.h", not . This is done for portability reasons +# because not all systems place things in SDL/ (see FreeBSD). + +if(NOT SDL2_DIR) + set(SDL2_DIR "" CACHE PATH "SDL2 directory") +endif() + +# modified to SDL2/ prefix +find_path(SDL2_INCLUDE_DIR SDL2/SDL.h + HINTS + ENV SDL2DIR + ${SDL2_DIR} + PATH_SUFFIXES SDL2 + # path suffixes to search inside ENV{SDL2DIR} + include/SDL2 include + REQUIRED +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(VC_LIB_PATH_SUFFIX lib/x64) +else() + set(VC_LIB_PATH_SUFFIX lib/x86) +endif() + +find_library(SDL2_LIBRARY_TEMP + NAMES SDL2 + HINTS + ENV SDL2DIR + ${SDL2_DIR} + PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} +) + +# Hide this cache variable from the user, it's an internal implementation +# detail. The documented library variable for the user is SDL2_LIBRARY +# which is derived from SDL2_LIBRARY_TEMP further below. +set_property(CACHE SDL2_LIBRARY_TEMP PROPERTY TYPE INTERNAL) + +if(NOT SDL2_BUILDING_LIBRARY) + if(NOT SDL2_INCLUDE_DIR MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDLmain for compatibility even though they don't + # necessarily need it. + find_library(SDL2MAIN_LIBRARY + NAMES SDL2main + HINTS + ENV SDL2DIR + ${SDL2_DIR} + PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} + PATHS + /sw + /opt/local + /opt/csw + /opt + ) + endif() +endif() + +# SDL may require threads on your system. +# The Apple build may not need an explicit flag because one of the +# frameworks may already provide it. +# But for non-OSX systems, I will use the CMake Threads package. +if(NOT APPLE) + find_package(Threads) +endif() + +# MinGW needs an additional link flag, -mwindows +# It's total link flags should look like -lmingw32 -lSDLmain -lSDL -mwindows +if(MINGW) + set(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "link flags for MinGW") +endif() + +if(SDL2_LIBRARY_TEMP) + # For SDLmain + if(SDL2MAIN_LIBRARY AND NOT SDL2_BUILDING_LIBRARY) + list(FIND SDL2_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" _SDL2_MAIN_INDEX) + if(_SDL2_MAIN_INDEX EQUAL -1) + set(SDL2_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" ${SDL2_LIBRARY_TEMP}) + endif() + unset(_SDL2_MAIN_INDEX) + endif() + + # For OS X, SDL uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + if(APPLE) + set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") + endif() + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + if(NOT APPLE) + set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + endif() + + # For MinGW library + if(MINGW) + set(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) + endif() + + # Set the final string here so the GUI reflects the final state. + set(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found") +endif() + +if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL2_version.h") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL2_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL2_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}") + set(SDL2_VERSION_STRING ${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH}) + unset(SDL2_VERSION_MAJOR_LINE) + unset(SDL2_VERSION_MINOR_LINE) + unset(SDL2_VERSION_PATCH_LINE) + unset(SDL2_VERSION_MAJOR) + unset(SDL2_VERSION_MINOR) + unset(SDL2_VERSION_PATCH) +endif() + +set(SDL2_LIBRARIES ${SDL2_LIBRARY} ${SDL2MAIN_LIBRARY}) +set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 + REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR + VERSION_VAR SDL2_VERSION_STRING) diff --git a/src/eventhandlers/winsendinputeventhandler.cpp b/src/eventhandlers/winsendinputeventhandler.cpp new file mode 100644 index 000000000..e9fce333c --- /dev/null +++ b/src/eventhandlers/winsendinputeventhandler.cpp @@ -0,0 +1,239 @@ +/* antimicro Gamepad to KB+M event mapper + * Copyright (C) 2015 Travis Nickles + * + * 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 3 of the License, or + * (at your option) any later version. + + * 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 . + */ + +#include +#include + +#include "winsendinputeventhandler.h" +#include +#include + +WinSendInputEventHandler::WinSendInputEventHandler(QObject *parent) : + BaseEventHandler(parent) +{ +} + +bool WinSendInputEventHandler::init() +{ + return true; +} + +bool WinSendInputEventHandler::cleanup() +{ + return true; +} + +void WinSendInputEventHandler::sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) +{ + int code = slot->getSlotCode(); + INPUT temp[1] = {}; + + unsigned int scancode = WinExtras::scancodeFromVirtualKey(code, slot->getSlotCodeAlias()); + int extended = (scancode & WinExtras::EXTENDED_FLAG) != 0; + int tempflags = extended ? KEYEVENTF_EXTENDEDKEY : 0; + + temp[0].type = INPUT_KEYBOARD; + //temp[0].ki.wScan = MapVirtualKey(code, MAPVK_VK_TO_VSC); + temp[0].ki.wScan = scancode; + temp[0].ki.time = 0; + temp[0].ki.dwExtraInfo = 0; + + temp[0].ki.wVk = code; + temp[0].ki.dwFlags = pressed ? tempflags : (tempflags | KEYEVENTF_KEYUP); // 0 for key press + SendInput(1, temp, sizeof(INPUT)); +} + +void WinSendInputEventHandler::sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) +{ + int code = slot->getSlotCode(); + INPUT temp[1] = {}; + + temp[0].type = INPUT_MOUSE; + if (code == 1) + { + temp[0].mi.dwFlags = pressed ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; + } + else if (code == 2) + { + temp[0].mi.dwFlags = pressed ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP; + } + else if (code == 3) + { + temp[0].mi.dwFlags = pressed ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; + } + else if (code == 4) + { + temp[0].mi.dwFlags = MOUSEEVENTF_WHEEL; + temp[0].mi.mouseData = pressed ? WHEEL_DELTA : 0; + } + else if (code == 5) + { + temp[0].mi.dwFlags = MOUSEEVENTF_WHEEL; + temp[0].mi.mouseData = pressed ? -WHEEL_DELTA : 0; + } + else if (code == 6) + { + temp[0].mi.dwFlags = 0x01000; + temp[0].mi.mouseData = pressed ? -WHEEL_DELTA : 0; + } + else if (code == 7) + { + temp[0].mi.dwFlags = 0x01000; + temp[0].mi.mouseData = pressed ? WHEEL_DELTA : 0; + } + else if (code == 8) + { + temp[0].mi.dwFlags = pressed ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; + temp[0].mi.mouseData = XBUTTON1; + } + else if (code == 9) + { + temp[0].mi.dwFlags = pressed ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; + temp[0].mi.mouseData = XBUTTON2; + } + + SendInput(1, temp, sizeof(INPUT)); +} + +void WinSendInputEventHandler::sendMouseEvent(int xDis, int yDis) +{ + INPUT temp[1] = {}; + temp[0].type = INPUT_MOUSE; + temp[0].mi.mouseData = 0; + temp[0].mi.dwFlags = MOUSEEVENTF_MOVE; + temp[0].mi.dx = xDis; + temp[0].mi.dy = yDis; + SendInput(1, temp, sizeof(INPUT)); +} + +QString WinSendInputEventHandler::getName() +{ + return QString("SendInput"); +} + +QString WinSendInputEventHandler::getIdentifier() +{ + return QString("sendinput"); +} + +void WinSendInputEventHandler::sendMouseSpringEvent(unsigned int xDis, unsigned int yDis, + unsigned int width, unsigned int height) +{ + if (width > 0 && height > 0) + { + INPUT temp[1] = {}; + temp[0].type = INPUT_MOUSE; + temp[0].mi.mouseData = 0; + temp[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; + + int fx = ceil(xDis * (65535.0/static_cast(width))); + int fy = ceil(yDis * (65535.0/static_cast(height))); + temp[0].mi.dx = fx; + temp[0].mi.dy = fy; + SendInput(1, temp, sizeof(INPUT)); + } +} + +void WinSendInputEventHandler::sendTextEntryEvent(QString maintext) +{ + AntKeyMapper *mapper = AntKeyMapper::getInstance(); + + if (mapper && mapper->getKeyMapper()) + { + QtWinKeyMapper *keymapper = static_cast(mapper->getKeyMapper()); + + for (int i=0; i < maintext.size(); i++) + { + QtWinKeyMapper::charKeyInformation temp = keymapper->getCharKeyInformation(maintext.at(i)); + QList tempList; + + if (temp.modifiers != Qt::NoModifier) + { + if (temp.modifiers.testFlag(Qt::ShiftModifier)) + { + tempList.append(VK_LSHIFT); + } + + if (temp.modifiers.testFlag(Qt::ControlModifier)) + { + tempList.append(VK_LCONTROL); + } + + if (temp.modifiers.testFlag(Qt::AltModifier)) + { + tempList.append(VK_LMENU); + } + + if (temp.modifiers.testFlag(Qt::MetaModifier)) + { + tempList.append(VK_LWIN); + } + } + + tempList.append(temp.virtualkey); + + if (tempList.size() > 0) + { + INPUT tempBuffer[tempList.size()] = {0}; + + QListIterator tempiter(tempList); + unsigned int j = 0; + while (tempiter.hasNext()) + { + unsigned int tempcode = tempiter.next(); + unsigned int scancode = WinExtras::scancodeFromVirtualKey(tempcode); + int extended = (scancode & WinExtras::EXTENDED_FLAG) != 0; + int tempflags = extended ? KEYEVENTF_EXTENDEDKEY : 0; + + tempBuffer[j].type = INPUT_KEYBOARD; + tempBuffer[j].ki.wScan = scancode; + tempBuffer[j].ki.time = 0; + tempBuffer[j].ki.dwExtraInfo = 0; + + tempBuffer[j].ki.wVk = tempcode; + tempBuffer[j].ki.dwFlags = tempflags; + j++; + } + + SendInput(j, tempBuffer, sizeof(INPUT)); + + tempiter.toBack(); + j = 0; + memset(tempBuffer, 0, sizeof(tempBuffer)); + //INPUT tempBuffer2[tempList.size()] = {0}; + while (tempiter.hasPrevious()) + { + unsigned int tempcode = tempiter.previous(); + unsigned int scancode = WinExtras::scancodeFromVirtualKey(tempcode); + int extended = (scancode & WinExtras::EXTENDED_FLAG) != 0; + int tempflags = extended ? KEYEVENTF_EXTENDEDKEY : 0; + + tempBuffer[j].type = INPUT_KEYBOARD; + tempBuffer[j].ki.wScan = scancode; + tempBuffer[j].ki.time = 0; + tempBuffer[j].ki.dwExtraInfo = 0; + + tempBuffer[j].ki.wVk = tempcode; + tempBuffer[j].ki.dwFlags = tempflags | KEYEVENTF_KEYUP; + j++; + } + + SendInput(j, tempBuffer, sizeof(INPUT)); + } + } + } +} diff --git a/src/eventhandlers/winsendinputeventhandler.h b/src/eventhandlers/winsendinputeventhandler.h new file mode 100644 index 000000000..fcecb3cbc --- /dev/null +++ b/src/eventhandlers/winsendinputeventhandler.h @@ -0,0 +1,52 @@ +/* antimicro Gamepad to KB+M event mapper + * Copyright (C) 2015 Travis Nickles + * + * 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 3 of the License, or + * (at your option) any later version. + + * 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 . + */ + +#ifndef WINSENDINPUTEVENTHANDLER_H +#define WINSENDINPUTEVENTHANDLER_H + +#include + +#include "baseeventhandler.h" + +#include + + +class WinSendInputEventHandler : public BaseEventHandler +{ + Q_OBJECT +public: + explicit WinSendInputEventHandler(QObject *parent = 0); + + virtual bool init(); + virtual bool cleanup(); + virtual void sendKeyboardEvent(JoyButtonSlot *slot, bool pressed); + virtual void sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed); + virtual void sendMouseEvent(int xDis, int yDis); + virtual void sendMouseSpringEvent(unsigned int xDis, unsigned int yDis, + unsigned int width, unsigned int height); + virtual void sendTextEntryEvent(QString maintext); + + virtual QString getName(); + virtual QString getIdentifier(); + +signals: + +public slots: + +}; + +#endif // WINSENDINPUTEVENTHANDLER_H diff --git a/src/eventhandlers/winvmultieventhandler.cpp b/src/eventhandlers/winvmultieventhandler.cpp new file mode 100644 index 000000000..0d1eb3e66 --- /dev/null +++ b/src/eventhandlers/winvmultieventhandler.cpp @@ -0,0 +1,395 @@ +/* antimicro Gamepad to KB+M event mapper + * Copyright (C) 2015 Travis Nickles + * + * 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 3 of the License, or + * (at your option) any later version. + + * 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 . + */ + +//#include +#include +#include +#include + +#include "winvmultieventhandler.h" + +#include + +WinVMultiEventHandler::WinVMultiEventHandler(QObject *parent) : + BaseEventHandler(parent), + sendInputHandler(this) +{ + vmulti = 0; + mouseButtons = 0; + shiftKeys = 0; + multiKeys = 0; + extraKeys = 0; + + keyboardKeys.resize(6); + keyboardKeys.fill(0); + + nativeKeyMapper = 0; +} + +WinVMultiEventHandler::~WinVMultiEventHandler() +{ + cleanup(); +} + +bool WinVMultiEventHandler::init() +{ + bool result = true; + + vmulti = vmulti_alloc(); + + if (vmulti == NULL) + { + result = false; + } + + if (vmulti && !vmulti_connect(vmulti)) + { + vmulti_free(vmulti); + vmulti = 0; + result = false; + } + + if (vmulti) + { + nativeKeyMapper = 0; + if (AntKeyMapper::getInstance("vmulti")->hasNativeKeyMapper()) + { + nativeKeyMapper = AntKeyMapper::getInstance("vmulti")->getNativeKeyMapper(); + } + } + + return result; +} + +bool WinVMultiEventHandler::cleanup() +{ + bool result = true; + + if (vmulti) + { + vmulti_disconnect(vmulti); + vmulti_free(vmulti); + + vmulti = 0; + } + + nativeKeyMapper = 0; + + return result; +} + +void WinVMultiEventHandler::sendKeyboardEvent(JoyButtonSlot *slot, bool pressed) +{ + int code = slot->getSlotCode(); + + BYTE pendingShift = 0x0; + BYTE pendingMultimedia = 0x0; + BYTE pendingExtra = 0x0; + BYTE pendingKey = 0x0; + + JoyButtonSlot tempSendInputSlot(slot); + bool useSendInput = false; + + bool exists = keyboardKeys.contains(code); + + if (code <= 0x65) + { + pendingKey = code; + } + else if (code >= 0xE0 && code <= 0xE7) + { + //pendingShift = 1 << (code - 0xE0); + if (nativeKeyMapper) + { + unsigned int nativeKey = nativeKeyMapper->returnVirtualKey(slot->getSlotCodeAlias()); + if (nativeKey > 0) + { + tempSendInputSlot.setSlotCode(nativeKey); + useSendInput = true; + } + } + } + else if (code > QtVMultiKeyMapper::consumerUsagePagePrefix) + { + if (nativeKeyMapper) + { + unsigned int nativeKey = nativeKeyMapper->returnVirtualKey(slot->getSlotCodeAlias()); + if (nativeKey > 0) + { + tempSendInputSlot.setSlotCode(nativeKey); + useSendInput = true; + } + } + + /*if (code == 0xB5 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingMultimedia = 1 << 0; // (Scan Next Track) + } + else if (code == 0xB6 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingMultimedia = 1 << 1; // (Scan Previous Track) + } + else if (code == 0xB1 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingMultimedia = 1 << 3; // (Play / Pause) + } + else if (code == 0x189 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingMultimedia = 1 << 6; // (WWW Home) + } + + else if (code == 0x194 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 0; // (My Computer) + } + else if (code == 0x192 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 1; // (Calculator) + } + else if (code == 0x22a | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 2; // (WWW fav) + } + else if (code == 0x221 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 3; // (WWW search) + } + else if (code == 0xB7 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 3; // (WWW stop) + } + else if (code == 0x224 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 4; // (WWW back) + } + else if (code == 0x87 | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 5; // (Media Select) + } + else if (code == 0x18a | QtVMultiKeyMapper::consumerUsagePagePrefix) + { + pendingExtra = 1 << 6; // (Mail) + } + */ + + } + else if (code > 0x65) + { + if (nativeKeyMapper) + { + unsigned int nativeKey = nativeKeyMapper->returnVirtualKey(slot->getSlotCodeAlias()); + if (nativeKey > 0) + { + tempSendInputSlot.setSlotCode(nativeKey); + //sendInputHandler.sendKeyboardEvent(tempslot, pressed); + useSendInput = true; + } + } + + /*if (code == 0x78) + { + pendingMultimedia = 1 << 2; // (Stop) + } + else if (code == 0x7F) + { + pendingMultimedia = 1 << 4; // (Mute) + } + else if (code == 0x81) + { + pendingMultimedia = 1 << 5; // (Volume Down) + } + else if (code == 0x80) + { + pendingMultimedia = 1 << 6; // (Volume Up) + } + */ + } + + if (!useSendInput) + { + if (pressed) + { + shiftKeys = shiftKeys | pendingShift; + multiKeys = multiKeys | pendingMultimedia; + extraKeys = extraKeys | pendingExtra; + + if (!exists) + { + // Check for an empty key value + int index = keyboardKeys.indexOf(0); + if (index != -1) + { + keyboardKeys.replace(index, pendingKey); + } + } + } + else + { + shiftKeys = shiftKeys ^ pendingShift; + multiKeys = multiKeys ^ pendingMultimedia; + extraKeys = extraKeys ^ pendingExtra; + + if (exists) + { + int index = keyboardKeys.indexOf(pendingKey); + if (index != -1) + { + keyboardKeys.replace(index, 0); + } + } + } + + BYTE *keykeyArray = keyboardKeys.data(); + /*QStringList trying; + for (int i=0; i < 6; i++) + { + BYTE current = keykeyArray[i]; + trying.append(QString("0x%1").arg(QString::number(current, 16))); + } + */ + + //qDebug() << "CURRENT: " << trying.join(","); + //qDebug() << keykeyArray; + + if (pendingKey > 0x0) + { + vmulti_update_keyboard(vmulti, shiftKeys, keykeyArray); + } + + if (pendingMultimedia > 0 || pendingExtra > 0) + { + //vmulti_update_keyboard_enhanced(vmulti, multiKeys, extraKeys); + } + } + else + { + sendInputHandler.sendKeyboardEvent(&tempSendInputSlot, pressed); + useSendInput = false; + } +} + +void WinVMultiEventHandler::sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed) +{ + BYTE pendingButton = 0; + BYTE pendingWheel = 0; + BYTE pendingHWheel = 0; + + bool useSendInput = false; + + int code = slot->getSlotCode(); + if (code == 1) + { + pendingButton = 0x01; + } + else if (code == 2) + { + pendingButton = 0x04; + } + else if (code == 3) + { + pendingButton = 0x02; + } + else if (code == 4) + { + pendingWheel = pressed ? 1 : 0; + } + else if (code == 5) + { + pendingWheel = pressed ? -1 : 0; + } + else if (code >= 6 && code <= 9) + { + useSendInput = true; + } + /* + else if (code == 6) + { + pendingHWheel = pressed ? -1 : 0; + } + else if (code == 7) + { + pendingHWheel = pressed ? 1 : 0; + } + else if (code == 8) + { + pendingButton = 0x08; + } + else if (code == 9) + { + pendingButton = 0x10; + } + */ + + if (!useSendInput) + { + if (pressed) + { + mouseButtons = mouseButtons | pendingButton; + vmulti_update_relative_mouse(vmulti, mouseButtons, 0, 0, pendingWheel);//, pendingHWheel); + } + else + { + mouseButtons = mouseButtons ^ pendingButton; + vmulti_update_relative_mouse(vmulti, mouseButtons, 0, 0, pendingWheel);//, pendingHWheel); + } + } + else + { + sendInputHandler.sendMouseButtonEvent(slot, pressed); + } +} + +void WinVMultiEventHandler::sendMouseEvent(int xDis, int yDis) +{ + vmulti_update_relative_mouse(vmulti, mouseButtons, xDis, yDis, 0);//, 0); +} + +void WinVMultiEventHandler::sendMouseSpringEvent(unsigned int xDis, unsigned int yDis, + unsigned int width, unsigned int height) +{ + if (width > 0 && height > 0) + { + int fx = ceil(xDis * (32767.0/static_cast(width))); + int fy = ceil(yDis * (32767.0/static_cast(height))); + sendMouseAbsEvent(fx, fy, -1); + } +} + +void WinVMultiEventHandler::sendMouseAbsEvent(int xDis, int yDis, int screen) +{ + Q_UNUSED(screen); + + vmulti_update_mouse(vmulti, mouseButtons, xDis, yDis, 0);//, 0); +} + +/* + * TODO: Implement text event using information from QtWinKeyMapper. + */ +void WinVMultiEventHandler::sendTextEntryEvent(QString maintext) +{ + sendInputHandler.sendTextEntryEvent(maintext); +} + +QString WinVMultiEventHandler::getName() +{ + return QString("Vmulti"); +} + +QString WinVMultiEventHandler::getIdentifier() +{ + return QString("vmulti"); +} diff --git a/src/eventhandlers/winvmultieventhandler.h b/src/eventhandlers/winvmultieventhandler.h new file mode 100644 index 000000000..92acf1c34 --- /dev/null +++ b/src/eventhandlers/winvmultieventhandler.h @@ -0,0 +1,73 @@ +/* antimicro Gamepad to KB+M event mapper + * Copyright (C) 2015 Travis Nickles + * + * 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 3 of the License, or + * (at your option) any later version. + + * 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 . + */ + +#ifndef WINVMULTIEVENTHANDLER_H +#define WINVMULTIEVENTHANDLER_H + +#include +#include + +#include "baseeventhandler.h" + +#include + +#include + +#include +#include "winsendinputeventhandler.h" + + +class WinVMultiEventHandler : public BaseEventHandler +{ + Q_OBJECT +public: + explicit WinVMultiEventHandler(QObject *parent = 0); + ~WinVMultiEventHandler(); + + virtual bool init(); + virtual bool cleanup(); + virtual void sendKeyboardEvent(JoyButtonSlot *slot, bool pressed); + virtual void sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed); + virtual void sendMouseEvent(int xDis, int yDis); + virtual void sendMouseAbsEvent(int xDis, int yDis, int screen); + virtual void sendMouseSpringEvent(unsigned int xDis, unsigned int yDis, + unsigned int width, unsigned int height); + + // TODO: Implement text event using information from QtWinKeyMapper. + virtual void sendTextEntryEvent(QString maintext); + + virtual QString getName(); + virtual QString getIdentifier(); + +protected: + pvmulti_client vmulti; + BYTE mouseButtons; + BYTE shiftKeys; + BYTE multiKeys; + BYTE extraKeys; + QVector keyboardKeys; + WinSendInputEventHandler sendInputHandler; + QtKeyMapperBase *nativeKeyMapper; + + +signals: + +public slots: + +}; + +#endif // WINVMULTIEVENTHANDLER_H diff --git a/src/winextras.cpp b/src/winextras.cpp new file mode 100644 index 000000000..1db50fee1 --- /dev/null +++ b/src/winextras.cpp @@ -0,0 +1,502 @@ +#define _WIN32_WINNT 0x0600 + +#include +#include +//#include +#include +#include +#include +#include + +#include "winextras.h" +#include + +typedef DWORD(WINAPI *MYPROC)(HANDLE, DWORD, LPTSTR, PDWORD); +// Check if QueryFullProcessImageNameW function exists in kernel32.dll. +// Function does not exist in Windows XP. +static MYPROC pQueryFullProcessImageNameW = (MYPROC) GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "QueryFullProcessImageNameW"); + +/*static bool isWindowsVistaOrHigher() +{ + OSVERSIONINFO osvi; + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(osvi); + GetVersionEx(&osvi); + return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 6); +} +*/ + +const unsigned int WinExtras::EXTENDED_FLAG = 0x100; +int WinExtras::originalMouseAccel = 0; + +static const QString ROOTASSOCIATIONKEY("HKEY_CURRENT_USER\\Software\\Classes"); +static const QString FILEASSOCIATIONKEY(QString("%1\\%2").arg(ROOTASSOCIATIONKEY).arg(".amgp")); +static const QString PROGRAMASSOCIATIONKEY(QString("%1\\%2").arg(ROOTASSOCIATIONKEY).arg("AntiMicro.amgp")); + +WinExtras WinExtras::_instance; + +WinExtras::WinExtras(QObject *parent) : + QObject(parent) +{ + populateKnownAliases(); +} + +QString WinExtras::getDisplayString(unsigned int virtualkey) +{ + QString temp; + if (virtualkey <= 0) + { + temp = tr("[NO KEY]"); + } + else if (_instance.knownAliasesVKStrings.contains(virtualkey)) + { + temp = _instance.knownAliasesVKStrings.value(virtualkey); + } + + return temp; +} + +unsigned int WinExtras::getVirtualKey(QString codestring) +{ + int temp = 0; + if (_instance.knownAliasesX11SymVK.contains(codestring)) + { + temp = _instance.knownAliasesX11SymVK.value(codestring); + } + + return temp; +} + +void WinExtras::populateKnownAliases() +{ + // These aliases are needed for xstrings that would + // return empty space characters from XLookupString + if (knownAliasesX11SymVK.isEmpty()) + { + knownAliasesX11SymVK.insert("Escape", VK_ESCAPE); + knownAliasesX11SymVK.insert("Tab", VK_TAB); + knownAliasesX11SymVK.insert("space", VK_SPACE); + knownAliasesX11SymVK.insert("Delete", VK_DELETE); + knownAliasesX11SymVK.insert("Return", VK_RETURN); + knownAliasesX11SymVK.insert("KP_Enter", VK_RETURN); + knownAliasesX11SymVK.insert("BackSpace", VK_BACK); + knownAliasesX11SymVK.insert("F1", VK_F1); + knownAliasesX11SymVK.insert("F2", VK_F2); + knownAliasesX11SymVK.insert("F3", VK_F3); + knownAliasesX11SymVK.insert("F4", VK_F4); + knownAliasesX11SymVK.insert("F5", VK_F5); + knownAliasesX11SymVK.insert("F6", VK_F6); + knownAliasesX11SymVK.insert("F7", VK_F7); + knownAliasesX11SymVK.insert("F8", VK_F8); + knownAliasesX11SymVK.insert("F9", VK_F9); + knownAliasesX11SymVK.insert("F10", VK_F10); + knownAliasesX11SymVK.insert("F11", VK_F11); + knownAliasesX11SymVK.insert("F12", VK_F12); + knownAliasesX11SymVK.insert("Shift_L", VK_LSHIFT); + knownAliasesX11SymVK.insert("Shift_R", VK_RSHIFT); + knownAliasesX11SymVK.insert("Insert", VK_INSERT); + knownAliasesX11SymVK.insert("Pause", VK_PAUSE); + knownAliasesX11SymVK.insert("grave", VK_OEM_3); + knownAliasesX11SymVK.insert("minus", VK_OEM_MINUS); + knownAliasesX11SymVK.insert("equal", VK_OEM_PLUS); + knownAliasesX11SymVK.insert("Caps_Lock", VK_CAPITAL); + knownAliasesX11SymVK.insert("Control_L", VK_CONTROL); + knownAliasesX11SymVK.insert("Control_R", VK_RCONTROL); + knownAliasesX11SymVK.insert("Alt_L", VK_MENU); + knownAliasesX11SymVK.insert("Alt_R", VK_RMENU); + knownAliasesX11SymVK.insert("Super_L", VK_LWIN); + knownAliasesX11SymVK.insert("Menu", VK_APPS); + knownAliasesX11SymVK.insert("Prior", VK_PRIOR); + knownAliasesX11SymVK.insert("Next", VK_NEXT); + knownAliasesX11SymVK.insert("Home", VK_HOME); + knownAliasesX11SymVK.insert("End", VK_END); + knownAliasesX11SymVK.insert("Up", VK_UP); + knownAliasesX11SymVK.insert("Down", VK_DOWN); + knownAliasesX11SymVK.insert("Left", VK_LEFT); + knownAliasesX11SymVK.insert("Right", VK_RIGHT); + knownAliasesX11SymVK.insert("bracketleft", VK_OEM_4); + knownAliasesX11SymVK.insert("bracketright", VK_OEM_6); + knownAliasesX11SymVK.insert("backslash", VK_OEM_5); + knownAliasesX11SymVK.insert("slash", VK_OEM_2); + knownAliasesX11SymVK.insert("semicolon", VK_OEM_1); + knownAliasesX11SymVK.insert("apostrophe", VK_OEM_7); + knownAliasesX11SymVK.insert("comma", VK_OEM_COMMA); + knownAliasesX11SymVK.insert("period", VK_OEM_PERIOD); + knownAliasesX11SymVK.insert("KP_0", VK_NUMPAD0); + knownAliasesX11SymVK.insert("KP_1", VK_NUMPAD1); + knownAliasesX11SymVK.insert("KP_2", VK_NUMPAD2); + knownAliasesX11SymVK.insert("KP_3", VK_NUMPAD3); + knownAliasesX11SymVK.insert("KP_4", VK_NUMPAD4); + knownAliasesX11SymVK.insert("KP_5", VK_NUMPAD5); + knownAliasesX11SymVK.insert("KP_6", VK_NUMPAD6); + knownAliasesX11SymVK.insert("KP_7", VK_NUMPAD7); + knownAliasesX11SymVK.insert("KP_8", VK_NUMPAD8); + knownAliasesX11SymVK.insert("KP_9", VK_NUMPAD9); + knownAliasesX11SymVK.insert("Num_Lock", VK_NUMLOCK); + knownAliasesX11SymVK.insert("KP_Divide", VK_DIVIDE); + knownAliasesX11SymVK.insert("KP_Multiply", VK_MULTIPLY); + knownAliasesX11SymVK.insert("KP_Subtract", VK_SUBTRACT); + knownAliasesX11SymVK.insert("KP_Add", VK_ADD); + knownAliasesX11SymVK.insert("KP_Decimal", VK_DECIMAL); + knownAliasesX11SymVK.insert("Scroll_Lock", VK_SCROLL); + knownAliasesX11SymVK.insert("Print", VK_SNAPSHOT); + knownAliasesX11SymVK.insert("Multi_key", VK_RMENU); + } + + if (knownAliasesVKStrings.isEmpty()) + { + knownAliasesVKStrings.insert(VK_LWIN, QObject::tr("Super")); + knownAliasesVKStrings.insert(VK_APPS, QObject::tr("Menu")); + knownAliasesVKStrings.insert(VK_VOLUME_MUTE, QObject::tr("Mute")); + knownAliasesVKStrings.insert(VK_VOLUME_UP, QObject::tr("Vol+")); + knownAliasesVKStrings.insert(VK_VOLUME_DOWN, QObject::tr("Vol-")); + knownAliasesVKStrings.insert(VK_MEDIA_PLAY_PAUSE, QObject::tr("Play/Pause")); + knownAliasesVKStrings.insert(VK_PLAY, QObject::tr("Play")); + knownAliasesVKStrings.insert(VK_PAUSE, QObject::tr("Pause")); + knownAliasesVKStrings.insert(VK_MEDIA_PREV_TRACK, QObject::tr("Prev")); + knownAliasesVKStrings.insert(VK_MEDIA_NEXT_TRACK, QObject::tr("Next")); + knownAliasesVKStrings.insert(VK_LAUNCH_MAIL, QObject::tr("Mail")); + knownAliasesVKStrings.insert(VK_HOME, QObject::tr("Home")); + knownAliasesVKStrings.insert(VK_LAUNCH_MEDIA_SELECT, QObject::tr("Media")); + knownAliasesVKStrings.insert(VK_BROWSER_SEARCH, QObject::tr("Search")); + } +} + +/** + * @brief Obtain a more specific virtual key (unsigned int) for a key grab event. + * @param Scan code obtained from a key grab event + * @param Virtual key obtained from a key grab event + * @return Corrected virtual key as an unsigned int + */ +unsigned int WinExtras::correctVirtualKey(unsigned int scancode, unsigned int virtualkey) +{ + int mapvirtual = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + int extended = (scancode & EXTENDED_FLAG) != 0; + + int finalvirtual = 0; + switch (virtualkey) + { + case VK_CONTROL: + finalvirtual = extended ? VK_RCONTROL : VK_LCONTROL; + break; + case VK_SHIFT: + finalvirtual = mapvirtual; + break; + case VK_MENU: + finalvirtual = extended ? VK_RMENU : VK_LMENU; + break; + case 0x5E: + // Ignore System Reserved VK + finalvirtual = 0; + break; + default: + finalvirtual = virtualkey; + } + + return finalvirtual; +} + +/** + * @brief Convert a virtual key into the corresponding keyboard scan code. + * @param Windows virtual key + * @param Qt key alias + * @return Keyboard scan code as an unsigned int + */ +unsigned int WinExtras::scancodeFromVirtualKey(unsigned int virtualkey, unsigned int alias) +{ + int scancode = 0; + if (virtualkey == VK_PAUSE) + { + // MapVirtualKey does not work with VK_PAUSE + scancode = 0x45; + } + else + { + scancode = MapVirtualKey(virtualkey, MAPVK_VK_TO_VSC); + } + + switch (virtualkey) + { + case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys + case VK_PRIOR: case VK_NEXT: // page up and page down + case VK_END: case VK_HOME: + case VK_INSERT: case VK_DELETE: + case VK_DIVIDE: // numpad slash + case VK_NUMLOCK: + case VK_RCONTROL: + case VK_RMENU: + { + scancode |= EXTENDED_FLAG; // set extended bit + break; + } + case VK_RETURN: + { + // Remove ambiguity between Enter and Numpad Enter. + // In Windows, VK_RETURN is used for both. + if (alias == Qt::Key_Enter) + { + scancode |= EXTENDED_FLAG; // set extended bit + break; + } + } + } + + return scancode; +} + +/** + * @brief Check foreground window (window in focus) and obtain the + * corresponding exe file path. + * @return File path of executable + */ +QString WinExtras::getForegroundWindowExePath() +{ + QString exePath; + HWND foreground = GetForegroundWindow(); + HANDLE windowProcess = NULL; + if (foreground) + { + DWORD processId; + GetWindowThreadProcessId(foreground, &processId); + windowProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, true, processId); + } + + if (windowProcess != NULL) + { + TCHAR filename[MAX_PATH]; + memset(filename, 0, sizeof(filename)); + //qDebug() << QString::number(sizeof(filename)/sizeof(TCHAR)); + if (pQueryFullProcessImageNameW) + { + // Windows Vista and later + DWORD pathLength = MAX_PATH * sizeof(TCHAR); + pQueryFullProcessImageNameW(windowProcess, 0, filename, &pathLength); + //qDebug() << pathLength; + } + else + { + // Windows XP + GetModuleFileNameEx(windowProcess, NULL, filename, MAX_PATH * sizeof(TCHAR)); + //qDebug() << pathLength; + } + + exePath = QString::fromWCharArray(filename); + //qDebug() << QString::fromWCharArray(filename); + CloseHandle(windowProcess); + } + + return exePath; +} + +bool WinExtras::containsFileAssociationinRegistry() +{ + bool result = false; + + QSettings associationReg(FILEASSOCIATIONKEY, QSettings::NativeFormat); + QString temp = associationReg.value("Default", "").toString(); + if (!temp.isEmpty()) + { + result = true; + } + + return result; +} + +void WinExtras::writeFileAssocationToRegistry() +{ + QSettings fileAssociationReg(FILEASSOCIATIONKEY, QSettings::NativeFormat); + fileAssociationReg.setValue("Default", "AntiMicro.amgp"); + fileAssociationReg.sync(); + + QSettings programAssociationReg(PROGRAMASSOCIATIONKEY, QSettings::NativeFormat); + programAssociationReg.setValue("Default", tr("AntiMicro Profile")); + programAssociationReg.setValue("shell/open/command/Default", QString("\"%1\" \"%2\"").arg(QDir::toNativeSeparators(qApp->applicationFilePath())).arg("%1")); + programAssociationReg.setValue("DefaultIcon/Default", QString("%1,%2").arg(QDir::toNativeSeparators(qApp->applicationFilePath())).arg("0")); + programAssociationReg.sync(); + + // Required to refresh settings used in Windows Explorer + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0); +} + +void WinExtras::removeFileAssociationFromRegistry() +{ + QSettings fileAssociationReg(FILEASSOCIATIONKEY, QSettings::NativeFormat); + QString currentValue = fileAssociationReg.value("Default", "").toString(); + if (currentValue == "AntiMicro.amgp") + { + fileAssociationReg.remove("Default"); + fileAssociationReg.sync(); + } + + QSettings programAssociationReg(PROGRAMASSOCIATIONKEY, QSettings::NativeFormat); + programAssociationReg.remove(""); + programAssociationReg.sync(); + + // Required to refresh settings used in Windows Explorer + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0); +} + +/** + * @brief Attempt to elevate process using runas + * @return Execution status + */ +bool WinExtras::elevateAntiMicro() +{ + QString antiProgramLocation = QDir::toNativeSeparators(qApp->applicationFilePath()); + QByteArray temp = antiProgramLocation.toUtf8(); + SHELLEXECUTEINFO sei = { sizeof(sei) }; + wchar_t tempverb[6]; + wchar_t tempfile[antiProgramLocation.length() + 1]; + QString("runas").toWCharArray(tempverb); + antiProgramLocation.toWCharArray(tempfile); + tempverb[5] = '\0'; + tempfile[antiProgramLocation.length()] = '\0'; + sei.lpVerb = tempverb; + sei.lpFile = tempfile; + sei.hwnd = NULL; + sei.nShow = SW_NORMAL; + BOOL result = ShellExecuteEx(&sei); + return result; +} + +/** + * @brief Check if the application is running with administrative privileges. + * @return Status indicating administrative privileges + */ +bool WinExtras::IsRunningAsAdmin() +{ + BOOL isAdmin = FALSE; + PSID administratorsGroup; + SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; + isAdmin = AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &administratorsGroup); + if (isAdmin) + { + if (!CheckTokenMembership(NULL, administratorsGroup, &isAdmin)) + { + isAdmin = FALSE; + } + FreeSid(administratorsGroup); + } + + return isAdmin; +} + +/** + * @brief Temporarily disable "Enhanced Pointer Precision". + */ +void WinExtras::disablePointerPrecision() +{ + int mouseInfo[3]; + SystemParametersInfo(SPI_GETMOUSE, 0, &mouseInfo, 0); + if (mouseInfo[2] == 1 && mouseInfo[2] == originalMouseAccel) + { + mouseInfo[2] = 0; + SystemParametersInfo(SPI_SETMOUSE, 0, &mouseInfo, 0); + } +} + +/** + * @brief If "Enhanced Pointer Precision" is currently disabled and + * the setting has not been changed explicitly by the user while + * the program has been running, re-enable "Enhanced Pointer Precision". + * Return the mouse behavior to normal. + */ +void WinExtras::enablePointerPrecision() +{ + int mouseInfo[3]; + SystemParametersInfo(SPI_GETMOUSE, 0, &mouseInfo, 0); + if (mouseInfo[2] == 0 && mouseInfo[2] != originalMouseAccel) + { + mouseInfo[2] = originalMouseAccel; + SystemParametersInfo(SPI_SETMOUSE, 0, &mouseInfo, 0); + } +} + +/** + * @brief Used to check if the "Enhance Pointer Precision" Windows + * option is currently enabled. + * @return Status of "Enhanced Pointer Precision" + */ +bool WinExtras::isUsingEnhancedPointerPrecision() +{ + bool result = false; + + int mouseInfo[3]; + SystemParametersInfo(SPI_GETMOUSE, 0, &mouseInfo, 0); + + if (mouseInfo[2] > 0) + { + result = true; + } + + return result; +} + +/** + * @brief Get the value of "Enhanced Pointer Precision" when the program + * first starts. Needed to not override setting if the option has + * been disabled in Windows by the user. + */ +void WinExtras::grabCurrentPointerPrecision() +{ + int mouseInfo[3]; + SystemParametersInfo(SPI_GETMOUSE, 0, &mouseInfo, 0); + originalMouseAccel = mouseInfo[2]; +} + +/** + * @brief Get the window text of the window currently in focus. + * @return Window title of application in focus. + */ +QString WinExtras::getCurrentWindowText() +{ + QString windowText; + + HWND foreground = GetForegroundWindow(); + + if (foreground != NULL) + { + TCHAR foundWindowTitle[256]; + memset(foundWindowTitle, 0, sizeof(foundWindowTitle)); + GetWindowTextW(foreground, foundWindowTitle, 255); + QString temp = QString::fromWCharArray(foundWindowTitle); + if (temp.isEmpty()) + { + memset(foundWindowTitle, 0, sizeof(foundWindowTitle)); + SendMessageA(foreground, WM_GETTEXT, 255, (LPARAM)foundWindowTitle); + temp = QString::fromWCharArray(foundWindowTitle); + } + + if (!temp.isEmpty()) + { + windowText = temp; + } + } + + return windowText; +} + +bool WinExtras::raiseProcessPriority() +{ + bool result = false; + result = SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + /*if (!result) + { + qDebug() << "COULD NOT RAISE PROCESS PRIORITY"; + } + */ + + return result; +} + +QPoint WinExtras::getCursorPos() +{ + POINT cursorPoint; + GetCursorPos(&cursorPoint); + + QPoint temp(cursorPoint.x, cursorPoint.y); + return temp; +} diff --git a/src/winextras.h b/src/winextras.h new file mode 100644 index 000000000..6014cfc4b --- /dev/null +++ b/src/winextras.h @@ -0,0 +1,49 @@ +#ifndef WINEXTRAS_H +#define WINEXTRAS_H + +#include +#include +#include +#include + +class WinExtras : public QObject +{ + Q_OBJECT +public: + static QString getDisplayString(unsigned int virtualkey); + static unsigned int getVirtualKey(QString codestring); + static unsigned int correctVirtualKey(unsigned int scancode, + unsigned int virtualkey); + static unsigned int scancodeFromVirtualKey(unsigned int virtualkey, unsigned int alias=0); + + static const unsigned int EXTENDED_FLAG; + static QString getForegroundWindowExePath(); + static bool containsFileAssociationinRegistry(); + static void writeFileAssocationToRegistry(); + static void removeFileAssociationFromRegistry(); + static bool IsRunningAsAdmin(); + static bool elevateAntiMicro(); + static void disablePointerPrecision(); + static void enablePointerPrecision(); + static bool isUsingEnhancedPointerPrecision(); + static void grabCurrentPointerPrecision(); + static QString getCurrentWindowText(); + static bool raiseProcessPriority(); + static QPoint getCursorPos(); + +protected: + explicit WinExtras(QObject *parent = 0); + void populateKnownAliases(); + + static WinExtras _instance; + QHash knownAliasesX11SymVK; + QHash knownAliasesVKStrings; + static int originalMouseAccel; + +signals: + +public slots: + +}; + +#endif // WINEXTRAS_H From 280745a03741c99b04d3a63e7374bbac20ebdce8 Mon Sep 17 00:00:00 2001 From: Gergely Gombos Date: Sat, 5 Dec 2020 14:23:15 +0100 Subject: [PATCH 7/8] chore: fix builds --- CMakeLists.txt | 26 ++++++++++++------------- src/antkeymapper.h | 18 +++++++++++++----- src/eventhandlerfactory.h | 33 +++++++++++++++++++++++++------- src/main.cpp | 40 ++++++++++++++++++++++++--------------- 4 files changed, 77 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b9c1897e..c792207a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -443,7 +443,7 @@ if(UNIX) endif(WITH_UINPUT) elseif(WIN32) - LIST(APPEND antimicro_SOURCES + LIST(APPEND antimicrox_SOURCES src/winextras.cpp src/qtwinkeymapper.cpp # src/winappprofiletimerdialog.cpp @@ -451,7 +451,7 @@ elseif(WIN32) src/eventhandlers/winsendinputeventhandler.cpp src/joykeyrepeathelper.cpp ) - LIST(APPEND antimicro_HEADERS + LIST(APPEND antimicrox_HEADERS src/winextras.h src/qtwinkeymapper.h # src/winappprofiletimerdialog.h @@ -459,16 +459,16 @@ elseif(WIN32) src/eventhandlers/winsendinputeventhandler.h src/joykeyrepeathelper.h ) - # LIST(APPEND antimicro_FORMS src/winappprofiletimerdialog.ui) + # LIST(APPEND antimicrox_FORMS src/winappprofiletimerdialog.ui) # Add Windows specific resource file used for application icons. - # LIST(APPEND antimicro_RESOURCES src/resources_windows.qrc) + # LIST(APPEND antimicrox_RESOURCES src/resources_windows.qrc) # if(WITH_VMULTI) -# list(APPEND antimicro_SOURCES src/qtvmultikeymapper.cpp +# list(APPEND antimicrox_SOURCES src/qtvmultikeymapper.cpp # src/eventhandlers/winvmultieventhandler.cpp # # vmulti/client/client.c # ) -# list(APPEND antimicro_HEADERS src/qtvmultikeymapper.h +# list(APPEND antimicrox_HEADERS src/qtvmultikeymapper.h # src/eventhandlers/winvmultieventhandler.h # ) # endif(WITH_VMULTI) @@ -524,8 +524,8 @@ elseif(WIN32) find_package(Qt5LinguistTools REQUIRED) find_package(Qt5Concurrent ${QT_REQUIRED_VERSION} REQUIRED) - QT5_WRAP_UI(antimicro_FORMS_HEADERS ${antimicro_FORMS}) - QT5_ADD_RESOURCES(antimicro_RESOURCES_RCC ${antimicro_RESOURCES}) + QT5_WRAP_UI(antimicrox_FORMS_HEADERS ${antimicrox_FORMS}) + QT5_ADD_RESOURCES(antimicrox_RESOURCES_RCC ${antimicrox_RESOURCES}) add_subdirectory("share/antimicrox/translations") include_directories(${Qt5Widgets_INCLUDE_DIRS}) @@ -831,7 +831,7 @@ if(WIN32) # Use a different file for each architecture due # to some DLL differences. if(TARGET_ARCH STREQUAL "x86_64") - set(WIXWXS "${MSIFOLDER}/antimicro_64.wxs") + set(WIXWXS "${MSIFOLDER}/antimicrox_64.wxs") else() set(WIXWXS "${MSIFOLDER}/antimicrox.wxs") endif(TARGET_ARCH STREQUAL "x86_64") @@ -839,10 +839,10 @@ if(WIN32) set(WIXOBJ "${MSIFOLDER}/antimicrox.wixobj") # Use version number in output file name. - set(MSIFILENAME "${ANTIMICRO_MAJOR_VERSION}.${ANTIMICRO_MINOR_VERSION}") - if(ANTIMICRO_PATCH_VERSION AND NOT ANTIMICRO_PATCH_VERSION EQUAL 0) - set(MSIFILENAME "${MSIFILENAME}.${ANTIMICRO_PATCH_VERSION}") - endif(ANTIMICRO_PATCH_VERSION AND NOT ANTIMICRO_PATCH_VERSION EQUAL 0) + set(MSIFILENAME "${ANTIMICROX_MAJOR_VERSION}.${ANTIMICROX_MINOR_VERSION}") + if(ANTIMICROX_PATCH_VERSION AND NOT ANTIMICROX_PATCH_VERSION EQUAL 0) + set(MSIFILENAME "${MSIFILENAME}.${ANTIMICROX_PATCH_VERSION}") + endif(ANTIMICROX_PATCH_VERSION AND NOT ANTIMICROX_PATCH_VERSION EQUAL 0) # Change output file depending on the target architecture. if(TARGET_ARCH STREQUAL "x86_64") diff --git a/src/antkeymapper.h b/src/antkeymapper.h index 51e28044c..52009f28b 100644 --- a/src/antkeymapper.h +++ b/src/antkeymapper.h @@ -21,12 +21,20 @@ #include -#if defined(WITH_XTEST) - #include "qtx11keymapper.h" -#endif +#ifdef Q_OS_WIN + #include "qtwinkeymapper.h" -#if defined(WITH_UINPUT) - #include "qtuinputkeymapper.h" + #ifdef WITH_VMULTI + #include "qtvmultikeymapper.h" + #endif +#else + #ifdef(WITH_XTEST) + #include "qtx11keymapper.h" + #endif + + #ifdef(WITH_UINPUT) + #include "qtuinputkeymapper.h" + #endif #endif class AntKeyMapper : public QObject diff --git a/src/eventhandlerfactory.h b/src/eventhandlerfactory.h index 970f99c25..855420c92 100644 --- a/src/eventhandlerfactory.h +++ b/src/eventhandlerfactory.h @@ -30,19 +30,38 @@ #include "eventhandlers/xtesteventhandler.h" #endif -#ifdef WITH_XTEST - #define ADD_XTEST 1 +#ifdef Q_OS_WIN + #include "eventhandlers/winsendinputeventhandler.h" + + #ifdef WITH_VMULTI + #include "eventhandlers/winvmultieventhandler.h" + #endif +#endif + +#ifdef Q_OS_WIN + #define ADD_SENDINPUT 1 + #ifdef WITH_VMULTI + #define ADD_VMULTI 1 + #else + #define ADD_VMULTI 0 + #endif + + #define NUM_BACKENDS (ADD_SENDINPUT + ADD_VMULTI) #else + #ifdef WITH_XTEST + #define ADD_XTEST 1 + #else #define ADD_XTEST 0 -#endif + #endif -#ifdef WITH_UINPUT + #ifdef WITH_UINPUT #define ADD_UINPUT 1 -#else + #else #define ADD_UINPUT 0 -#endif + #endif -#define NUM_BACKENDS (ADD_XTEST + ADD_UINPUT) + #define NUM_BACKENDS (ADD_XTEST + ADD_UINPUT) +#endif #if (NUM_BACKENDS > 1) #define BACKEND_ELSE_IF else if diff --git a/src/main.cpp b/src/main.cpp index 498ea486d..9886513d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,7 +62,10 @@ #ifdef WITH_X11 #include "x11extras.h" #endif +#endif +#ifdef Q_OS_WIN + #include "winextras.h" #endif static void termSignalTermHandler(int signal) @@ -146,6 +149,27 @@ void importLegacySettingsIfExist() } } +void handleTerminationSignals() +{ +#ifndef Q_OS_WIN + // Have program handle SIGTERM + struct sigaction termaction; + termaction.sa_handler = &termSignalTermHandler; + sigemptyset(&termaction.sa_mask); + termaction.sa_flags = 0; + + sigaction(SIGTERM, &termaction, nullptr); + + // Have program handle SIGINT + struct sigaction termint; + termint.sa_handler = &termSignalIntHandler; + sigemptyset(&termint.sa_mask); + termint.sa_flags = 0; + + sigaction(SIGINT, &termint, nullptr); +#endif +} + int main(int argc, char *argv[]) { qInstallMessageHandler(MessageHandler::myMessageOutput); @@ -637,21 +661,7 @@ int main(int argc, char *argv[]) antimicrox.installTranslator(&myappTranslator); - // Have program handle SIGTERM - struct sigaction termaction; - termaction.sa_handler = &termSignalTermHandler; - sigemptyset(&termaction.sa_mask); - termaction.sa_flags = 0; - - sigaction(SIGTERM, &termaction, nullptr); - - // Have program handle SIGINT - struct sigaction termint; - termint.sa_handler = &termSignalIntHandler; - sigemptyset(&termint.sa_mask); - termint.sa_flags = 0; - - sigaction(SIGINT, &termint, nullptr); + handleTerminationSignals(); if (cmdutility.shouldListControllers()) { From 78ad602383d6b76ee12ca62720c020ac80151755 Mon Sep 17 00:00:00 2001 From: Gergely Gombos Date: Sat, 12 Dec 2020 16:05:32 +0100 Subject: [PATCH 8/8] fix: fix Linux build --- CMakeLists.txt | 18 +- cmake/FindSDL2.cmake | 415 +++++++++++++++++++++++++++++++------------ src/antkeymapper.h | 4 +- 3 files changed, 308 insertions(+), 129 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c792207a5..9cf6cf03a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,15 +24,10 @@ set(QT_REQUIRED_VERSION 5.8) set(SDL_REQUIRED_VERSION 2.0.6) project(antimicrox) -# already default? -# if(POLICY CMP0071) -# cmake_policy(SET CMP0071 NEW) -# endif() - -# if(UNIX) -# find_package(ECM REQUIRED NO_MODULE) -# set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR}) -# endif(UNIX) +if(UNIX) + find_package(ECM REQUIRED NO_MODULE) + set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR}) +endif(UNIX) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") @@ -81,11 +76,6 @@ option(ATTACH_FAKE_CLASSES "Fake classes can be used in application to tests fun if(UNIX) - # find_package(PkgConfig REQUIRED) - - # pkg_check_modules(SDL2 REQUIRED sdl2) -# find_package(SDL2 REQUIRED) -> will fail on some systems - if(WITH_X11) find_package(X11 REQUIRED) endif(WITH_X11) diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake index 795ecff6a..0be1fd6b0 100644 --- a/cmake/FindSDL2.cmake +++ b/cmake/FindSDL2.cmake @@ -1,188 +1,307 @@ +# https://github.com/aminosbh/sdl2-cmake-modules/blob/master/FindSDL2.cmake + # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#.rst: -# FindSDL2 -# ------- -# -# Locate SDL2 library -# -# This module defines -# -# :: -# -# SDL2_LIBRARY, the name of the library to link against -# SDL2_FOUND, if false, do not try to link to SDL -# SDL2_INCLUDE_DIR, where to find SDL.h -# SDL2_VERSION_STRING, human-readable string containing the version of SDL -# -# -# -# This module responds to the flag: -# -# :: -# -# SDL2_BUILDING_LIBRARY -# If this is defined, then no SDL2_main will be linked in because -# only applications need main(). -# Otherwise, it is assumed you are building an application and this -# module will attempt to locate and set the proper link flags -# as part of the returned SDL2_LIBRARY variable. -# -# -# -# Don't forget to include SDLmain.h and SDLmain.m your project for the -# OS X framework based version. (Other versions link to -lSDLmain which -# this module will try to find on your behalf.) Also for OS X, this -# module will automatically add the -framework Cocoa on your behalf. -# -# -# -# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your -# configuration and no SDL2_LIBRARY, it means CMake did not find your SDL -# library (SDL.dll, libsdl.so, SDL.framework, etc). Set -# SDL2_LIBRARY_TEMP to point to your SDL library, and configure again. -# Similarly, if you see an empty SDLMAIN_LIBRARY, you should set this -# value as appropriate. These values are used to generate the final -# SDL2_LIBRARY variable, but when these values are unset, SDL2_LIBRARY -# does not get created. -# -# -# -# $SDL2DIR is an environment variable that would correspond to the -# ./configure --prefix=$SDL2DIR used in building SDL. l.e.galup 9-20-02 -# -# Modified by Eric Wing. Added code to assist with automated building -# by using environmental variables and providing a more -# controlled/consistent search behavior. Added new modifications to -# recognize OS X frameworks and additional Unix paths (FreeBSD, etc). -# Also corrected the header search path to follow "proper" SDL -# guidelines. Added a search for SDLmain which is needed by some -# platforms. Added a search for threads which is needed by some -# platforms. Added needed compile switches for MinGW. -# -# On OSX, this will prefer the Framework version (if found) over others. -# People will have to manually change the cache values of SDL2_LIBRARY to -# override this selection or set the CMake environment -# CMAKE_INCLUDE_PATH to modify the search paths. -# -# Note that the header path has changed from SDL/SDL.h to just SDL.h -# This needed to change because "proper" SDL convention is #include -# "SDL.h", not . This is done for portability reasons -# because not all systems place things in SDL/ (see FreeBSD). - -if(NOT SDL2_DIR) - set(SDL2_DIR "" CACHE PATH "SDL2 directory") +# Copyright 2019 Amine Ben Hassouna +# Copyright 2000-2019 Kitware, Inc. and Contributors +# All rights reserved. + +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: + +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. + +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. + +# * Neither the name of Kitware, Inc. nor the names of Contributors +# may be used to endorse or promote products derived from this +# software without specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#[=======================================================================[.rst: +FindSDL2 +-------- + +Locate SDL2 library + +This module defines the following 'IMPORTED' targets: + +:: + + SDL2::Core + The SDL2 library, if found. + Libraries should link to SDL2::Core + + SDL2::Main + The SDL2main library, if found. + Applications should link to SDL2::Main instead of SDL2::Core + + + +This module will set the following variables in your project: + +:: + + SDL2_LIBRARIES, the name of the library to link against + SDL2_INCLUDE_DIRS, where to find SDL.h + SDL2_FOUND, if false, do not try to link to SDL2 + SDL2MAIN_FOUND, if false, do not try to link to SDL2main + SDL2_VERSION_STRING, human-readable string containing the version of SDL2 + + + +This module responds to the following cache variables: + +:: + + SDL2_PATH + Set a custom SDL2 Library path (default: empty) + + SDL2_NO_DEFAULT_PATH + Disable search SDL2 Library in default path. + If SDL2_PATH (default: ON) + Else (default: OFF) + + SDL2_INCLUDE_DIR + SDL2 headers path. + + SDL2_LIBRARY + SDL2 Library (.dll, .so, .a, etc) path. + + SDL2MAIN_LIBRAY + SDL2main Library (.a) path. + + SDL2_BUILDING_LIBRARY + This flag is useful only when linking to SDL2_LIBRARIES insead of + SDL2::Main. It is required only when building a library that links to + SDL2_LIBRARIES, because only applications need main() (No need to also + link to SDL2main). + If this flag is defined, then no SDL2main will be added to SDL2_LIBRARIES + and no SDL2::Main target will be created. + + +Don't forget to include SDLmain.h and SDLmain.m in your project for the +OS X framework based version. (Other versions link to -lSDL2main which +this module will try to find on your behalf.) Also for OS X, this +module will automatically add the -framework Cocoa on your behalf. + + +Additional Note: If you see an empty SDL2_LIBRARY in your project +configuration, it means CMake did not find your SDL2 library +(SDL2.dll, libsdl2.so, SDL2.framework, etc). Set SDL2_LIBRARY to point +to your SDL2 library, and configure again. Similarly, if you see an +empty SDL2MAIN_LIBRARY, you should set this value as appropriate. These +values are used to generate the final SDL2_LIBRARIES variable and the +SDL2::Core and SDL2::Main targets, but when these values are unset, +SDL2_LIBRARIES, SDL2::Core and SDL2::Main does not get created. + + +$SDL2DIR is an environment variable that would correspond to the +./configure --prefix=$SDL2DIR used in building SDL2. l.e.galup 9-20-02 + + + +Created by Amine Ben Hassouna: + Adapt FindSDL.cmake to SDL2 (FindSDL2.cmake). + Add cache variables for more flexibility: + SDL2_PATH, SDL2_NO_DEFAULT_PATH (for details, see doc above). + Mark 'Threads' as a required dependency for non-OSX systems. + Modernize the FindSDL2.cmake module by creating specific targets: + SDL2::Core and SDL2::Main (for details, see doc above). + + +Original FindSDL.cmake module: + Modified by Eric Wing. Added code to assist with automated building + by using environmental variables and providing a more + controlled/consistent search behavior. Added new modifications to + recognize OS X frameworks and additional Unix paths (FreeBSD, etc). + Also corrected the header search path to follow "proper" SDL + guidelines. Added a search for SDLmain which is needed by some + platforms. Added a search for threads which is needed by some + platforms. Added needed compile switches for MinGW. + +On OSX, this will prefer the Framework version (if found) over others. +People will have to manually change the cache value of SDL2_LIBRARY to +override this selection or set the SDL2_PATH variable or the CMake +environment CMAKE_INCLUDE_PATH to modify the search paths. + +Note that the header path has changed from SDL/SDL.h to just SDL.h +This needed to change because "proper" SDL convention is #include +"SDL.h", not . This is done for portability reasons +because not all systems place things in SDL/ (see FreeBSD). +#]=======================================================================] + +# Define options for searching SDL2 Library in a custom path + +set(SDL2_PATH "" CACHE STRING "Custom SDL2 Library path") + +set(_SDL2_NO_DEFAULT_PATH OFF) +if(SDL2_PATH) + set(_SDL2_NO_DEFAULT_PATH ON) endif() -# modified to SDL2/ prefix +set(SDL2_NO_DEFAULT_PATH ${_SDL2_NO_DEFAULT_PATH} + CACHE BOOL "Disable search SDL2 Library in default path") +unset(_SDL2_NO_DEFAULT_PATH) + +set(SDL2_NO_DEFAULT_PATH_CMD) +if(SDL2_NO_DEFAULT_PATH) + set(SDL2_NO_DEFAULT_PATH_CMD NO_DEFAULT_PATH) +endif() + +# Search for the SDL2 include directory +# Modified to SDL2/SDL.h for antimicroX find_path(SDL2_INCLUDE_DIR SDL2/SDL.h HINTS ENV SDL2DIR - ${SDL2_DIR} + ${SDL2_NO_DEFAULT_PATH_CMD} PATH_SUFFIXES SDL2 # path suffixes to search inside ENV{SDL2DIR} include/SDL2 include - REQUIRED + PATHS ${SDL2_PATH} + DOC "Where the SDL2 headers can be found" ) +set(SDL2_INCLUDE_DIRS "${SDL2_INCLUDE_DIR}") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(VC_LIB_PATH_SUFFIX lib/x64) else() set(VC_LIB_PATH_SUFFIX lib/x86) endif() -find_library(SDL2_LIBRARY_TEMP - NAMES SDL2 +# SDL-2.0 is the name used by FreeBSD ports... +# don't confuse it for the version number. +find_library(SDL2_LIBRARY + NAMES SDL2 SDL-2.0 HINTS ENV SDL2DIR - ${SDL2_DIR} + ${SDL2_NO_DEFAULT_PATH_CMD} PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} + PATHS ${SDL2_PATH} + DOC "Where the SDL2 Library can be found" ) -# Hide this cache variable from the user, it's an internal implementation -# detail. The documented library variable for the user is SDL2_LIBRARY -# which is derived from SDL2_LIBRARY_TEMP further below. -set_property(CACHE SDL2_LIBRARY_TEMP PROPERTY TYPE INTERNAL) +set(SDL2_LIBRARIES "${SDL2_LIBRARY}") if(NOT SDL2_BUILDING_LIBRARY) if(NOT SDL2_INCLUDE_DIR MATCHES ".framework") # Non-OS X framework versions expect you to also dynamically link to - # SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms - # seem to provide SDLmain for compatibility even though they don't + # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2main for compatibility even though they don't # necessarily need it. + + if(SDL2_PATH) + set(SDL2MAIN_LIBRARY_PATHS "${SDL2_PATH}") + endif() + + if(NOT SDL2_NO_DEFAULT_PATH) + set(SDL2MAIN_LIBRARY_PATHS + /sw + /opt/local + /opt/csw + /opt + "${SDL2MAIN_LIBRARY_PATHS}" + ) + endif() + find_library(SDL2MAIN_LIBRARY NAMES SDL2main HINTS ENV SDL2DIR - ${SDL2_DIR} + ${SDL2_NO_DEFAULT_PATH_CMD} PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} - PATHS - /sw - /opt/local - /opt/csw - /opt + PATHS ${SDL2MAIN_LIBRARY_PATHS} + DOC "Where the SDL2main library can be found" ) + unset(SDL2MAIN_LIBRARY_PATHS) endif() endif() -# SDL may require threads on your system. +# SDL2 may require threads on your system. # The Apple build may not need an explicit flag because one of the # frameworks may already provide it. # But for non-OSX systems, I will use the CMake Threads package. if(NOT APPLE) - find_package(Threads) + find_package(Threads QUIET) + if(NOT Threads_FOUND) + set(SDL2_THREADS_NOT_FOUND "Could NOT find Threads (Threads is required by SDL2).") + if(SDL2_FIND_REQUIRED) + message(FATAL_ERROR ${SDL2_THREADS_NOT_FOUND}) + else() + if(NOT SDL2_FIND_QUIETLY) + message(STATUS ${SDL2_THREADS_NOT_FOUND}) + endif() + return() + endif() + unset(SDL2_THREADS_NOT_FOUND) + endif() endif() # MinGW needs an additional link flag, -mwindows -# It's total link flags should look like -lmingw32 -lSDLmain -lSDL -mwindows +# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -mwindows if(MINGW) set(MINGW32_LIBRARY mingw32 "-mwindows" CACHE STRING "link flags for MinGW") endif() -if(SDL2_LIBRARY_TEMP) - # For SDLmain +if(SDL2_LIBRARY) + # For SDL2main if(SDL2MAIN_LIBRARY AND NOT SDL2_BUILDING_LIBRARY) - list(FIND SDL2_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" _SDL2_MAIN_INDEX) + list(FIND SDL2_LIBRARIES "${SDL2MAIN_LIBRARY}" _SDL2_MAIN_INDEX) if(_SDL2_MAIN_INDEX EQUAL -1) - set(SDL2_LIBRARY_TEMP "${SDLMAIN_LIBRARY}" ${SDL2_LIBRARY_TEMP}) + set(SDL2_LIBRARIES "${SDL2MAIN_LIBRARY}" ${SDL2_LIBRARIES}) endif() unset(_SDL2_MAIN_INDEX) endif() - # For OS X, SDL uses Cocoa as a backend so it must link to Cocoa. + # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. # CMake doesn't display the -framework Cocoa string in the UI even # though it actually is there if I modify a pre-used variable. # I think it has something to do with the CACHE STRING. # So I use a temporary variable until the end so I can set the # "real" variable in one-shot. if(APPLE) - set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") + set(SDL2_LIBRARIES ${SDL2_LIBRARIES} -framework Cocoa) endif() # For threads, as mentioned Apple doesn't need this. # In fact, there seems to be a problem if I used the Threads package # and try using this line, so I'm just skipping it entirely for OS X. if(NOT APPLE) - set(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + set(SDL2_LIBRARIES ${SDL2_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) endif() # For MinGW library if(MINGW) - set(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) + set(SDL2_LIBRARIES ${MINGW32_LIBRARY} ${SDL2_LIBRARIES}) endif() - # Set the final string here so the GUI reflects the final state. - set(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found") endif() -if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL2_version.h") - file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL2_MAJOR_VERSION[ \t]+[0-9]+$") - file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL2_MINOR_VERSION[ \t]+[0-9]+$") - file(STRINGS "${SDL2_INCLUDE_DIR}/SDL2_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL2_PATCHLEVEL[ \t]+[0-9]+$") - string(REGEX REPLACE "^#define[ \t]+SDL2_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}") - string(REGEX REPLACE "^#define[ \t]+SDL2_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}") - string(REGEX REPLACE "^#define[ \t]+SDL2_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}") +# Read SDL2 version +if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL_version.h") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$") + file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}") set(SDL2_VERSION_STRING ${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH}) unset(SDL2_VERSION_MAJOR_LINE) unset(SDL2_VERSION_MINOR_LINE) @@ -192,11 +311,81 @@ if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL2_version.h") unset(SDL2_VERSION_PATCH) endif() -set(SDL2_LIBRARIES ${SDL2_LIBRARY} ${SDL2MAIN_LIBRARY}) -set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR}) - include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR VERSION_VAR SDL2_VERSION_STRING) + +if(SDL2MAIN_LIBRARY) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2main + REQUIRED_VARS SDL2MAIN_LIBRARY SDL2_INCLUDE_DIR + VERSION_VAR SDL2_VERSION_STRING) +endif() + + +mark_as_advanced(SDL2_PATH + SDL2_NO_DEFAULT_PATH + SDL2_LIBRARY + SDL2MAIN_LIBRARY + SDL2_INCLUDE_DIR + SDL2_BUILDING_LIBRARY) + + +# SDL2:: targets (SDL2::Core and SDL2::Main) +if(SDL2_FOUND) + + # SDL2::Core target + if(SDL2_LIBRARY AND NOT TARGET SDL2::Core) + add_library(SDL2::Core UNKNOWN IMPORTED) + set_target_properties(SDL2::Core PROPERTIES + IMPORTED_LOCATION "${SDL2_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}") + + if(APPLE) + # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. + # For more details, please see above. + set_property(TARGET SDL2::Core APPEND PROPERTY + INTERFACE_LINK_OPTIONS -framework Cocoa) + else() + # For threads, as mentioned Apple doesn't need this. + # For more details, please see above. + set_property(TARGET SDL2::Core APPEND PROPERTY + INTERFACE_LINK_LIBRARIES Threads::Threads) + endif() + endif() + + # SDL2::Main target + # Applications should link to SDL2::Main instead of SDL2::Core + # For more details, please see above. + if(NOT SDL2_BUILDING_LIBRARY AND NOT TARGET SDL2::Main) + + if(SDL2_INCLUDE_DIR MATCHES ".framework" OR NOT SDL2MAIN_LIBRARY) + add_library(SDL2::Main INTERFACE IMPORTED) + set_property(TARGET SDL2::Main PROPERTY + INTERFACE_LINK_LIBRARIES SDL2::Core) + elseif(SDL2MAIN_LIBRARY) + # MinGW requires that the mingw32 library is specified before the + # libSDL2main.a static library when linking. + # The SDL2::MainInternal target is used internally to make sure that + # CMake respects this condition. + add_library(SDL2::MainInternal UNKNOWN IMPORTED) + set_property(TARGET SDL2::MainInternal PROPERTY + IMPORTED_LOCATION "${SDL2MAIN_LIBRARY}") + set_property(TARGET SDL2::MainInternal PROPERTY + INTERFACE_LINK_LIBRARIES SDL2::Core) + + add_library(SDL2::Main INTERFACE IMPORTED) + + if(MINGW) + # MinGW needs an additional link flag '-mwindows' and link to mingw32 + set_property(TARGET SDL2::Main PROPERTY + INTERFACE_LINK_LIBRARIES "mingw32" "-mwindows") + endif() + + set_property(TARGET SDL2::Main APPEND PROPERTY + INTERFACE_LINK_LIBRARIES SDL2::MainInternal) + endif() + + endif() +endif() diff --git a/src/antkeymapper.h b/src/antkeymapper.h index 52009f28b..e6a81b8d0 100644 --- a/src/antkeymapper.h +++ b/src/antkeymapper.h @@ -28,11 +28,11 @@ #include "qtvmultikeymapper.h" #endif #else - #ifdef(WITH_XTEST) + #ifdef WITH_XTEST #include "qtx11keymapper.h" #endif - #ifdef(WITH_UINPUT) + #ifdef WITH_UINPUT #include "qtuinputkeymapper.h" #endif #endif