diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2017-05-30 02:30:47 +0200 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2017-05-30 02:30:47 +0200 | 
| commit | 5b819219889e78093e0dd32615adb6dcdc66cbcb (patch) | |
| tree | 48dcc16ad34ab19a656ce862d8e4472e7ceb77e1 | |
| parent | a4836eac5872d06d533e0130230c99148aeb4c7e (diff) | |
fix linux hotkeys
Requested-by: @miniskipper and many others
| -rw-r--r-- | cmake/opentrack-platform.cmake | 4 | ||||
| -rw-r--r-- | logic/shortcuts.cpp | 7 | ||||
| -rw-r--r-- | qxt-mini/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | qxt-mini/qxtglobalshortcut.cpp | 36 | ||||
| -rw-r--r-- | qxt-mini/qxtglobalshortcut.h | 4 | ||||
| -rw-r--r-- | qxt-mini/qxtglobalshortcut_mac.cpp | 4 | ||||
| -rw-r--r-- | qxt-mini/qxtglobalshortcut_p.h | 3 | ||||
| -rw-r--r-- | qxt-mini/qxtglobalshortcut_x11.cpp | 221 | ||||
| -rw-r--r-- | qxt-mini/x11-keymap.cpp | 136 | ||||
| -rw-r--r-- | qxt-mini/x11-keymap.hpp | 15 | 
10 files changed, 345 insertions, 87 deletions
| diff --git a/cmake/opentrack-platform.cmake b/cmake/opentrack-platform.cmake index 27d38d88..9d5b1abe 100644 --- a/cmake/opentrack-platform.cmake +++ b/cmake/opentrack-platform.cmake @@ -138,4 +138,8 @@ if(MINGW)      add_definitions(-DMINGW_HAS_SECURE_API)  endif() +if(UNIX AND NOT APPLE) +    include(FindPkgConfig) +endif() +  set(opencv-modules opencv_calib3d opencv_core opencv_features2d opencv_imgcodecs opencv_imgproc opencv_objdetect opencv_videoio) diff --git a/logic/shortcuts.cpp b/logic/shortcuts.cpp index 6d77c3e0..1ffecd3a 100644 --- a/logic/shortcuts.cpp +++ b/logic/shortcuts.cpp @@ -141,8 +141,11 @@ void Shortcuts::reload(const t_keys& keys_)  #ifndef _WIN32          const int idx = keys.size() - 1;          tt& kk_ = keys[idx]; -        auto& fn = std::get<1>(kk_); -        connect(k, &QxtGlobalShortcut::activated, [=]() { fn(true); }); +        auto fn = std::get<1>(kk_); +        connect(k, &QxtGlobalShortcut::activated, [=, fn = std::move(fn)](bool keydown) { +            if (keydown || !held) +                fn(keydown); +        });  #endif      }  } diff --git a/qxt-mini/CMakeLists.txt b/qxt-mini/CMakeLists.txt index a6c2908e..84e66732 100644 --- a/qxt-mini/CMakeLists.txt +++ b/qxt-mini/CMakeLists.txt @@ -1,6 +1,8 @@  if(UNIX OR APPLE)      otr_module(qxt-mini NO-COMPAT BIN)      if(NOT APPLE) +        pkg_check_modules(xprotopkg REQUIRED xproto) +        target_include_directories(opentrack-qxt-mini SYSTEM PRIVATE ${xprotopkg_INCLUDE_DIRS})          target_link_libraries(opentrack-qxt-mini X11)      else()          otr_prop(TARGET opentrack-qxt-mini LINK_FLAGS "-framework Carbon -framework CoreFoundation") diff --git a/qxt-mini/qxtglobalshortcut.cpp b/qxt-mini/qxtglobalshortcut.cpp index 298472b5..fc0984b6 100644 --- a/qxt-mini/qxtglobalshortcut.cpp +++ b/qxt-mini/qxtglobalshortcut.cpp @@ -61,13 +61,13 @@ void QxtGlobalShortcutPrivate::event_filter_installer::ensure_event_filter()  }  QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate(QxtGlobalShortcutPrivate::tag) : -    enabled(false), key(Qt::Key(0)), mods(Qt::NoModifier) +    keystate(false), enabled(false), key(Qt::Key(0)), mods(Qt::NoModifier)  {      qDebug() << "qxt-mini: adding event filter";  }  QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : -    enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) +    keystate(false), enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier)  {      QxtGlobalShortcutPrivate::event_filter_installer::ensure_event_filter();  } @@ -143,25 +143,49 @@ bool QxtGlobalShortcutPrivate::unsetShortcut()      return res;  } -void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) +void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods, bool is_down)  {  #ifndef Q_OS_MAC      using IT = decltype(shortcuts.end());      const auto pair = qMakePair(nativeKey, nativeMods);      IT it = shortcuts.find(pair); +    bool once = false; +      for (; it != shortcuts.end(); it++)      {          if (it.key() != pair) // DO NOT REMOVE              break; +          auto ptr = *it; +        auto& priv = ptr->qxt_d(); + +        if (priv.keystate == is_down) +        { +            continue; +        } + +        if (!once) +        { +            once = true; +            qDebug() << "qxt-mini:" << (is_down ? "keydown" : "keyup") << priv.key << priv.mods; +        } + +        priv.keystate = is_down; +          if (ptr->isEnabled()) -            emit ptr->activated(); +            emit ptr->activated(is_down);      }  #else      QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods)); -    if (shortcut && shortcut->isEnabled()) -        emit shortcut->activated(); + +    if (shortcut) +    { +        shortcut->qxt_d().keystate = false; + +        if (shortcut->isEnabled()) +            emit shortcut->activated(true); +    }  #endif  } diff --git a/qxt-mini/qxtglobalshortcut.h b/qxt-mini/qxtglobalshortcut.h index bf26180f..be62a984 100644 --- a/qxt-mini/qxtglobalshortcut.h +++ b/qxt-mini/qxtglobalshortcut.h @@ -43,6 +43,8 @@ class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject      Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)      Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) +    bool keystate; +  public:      explicit QxtGlobalShortcut(QObject* parent = 0);      explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0); @@ -58,7 +60,7 @@ public Q_SLOTS:      void setDisabled(bool disabled = true);  Q_SIGNALS: -    void activated(); +    void activated(bool keydown = true);  };  #endif // QXTGLOBALSHORTCUT_H diff --git a/qxt-mini/qxtglobalshortcut_mac.cpp b/qxt-mini/qxtglobalshortcut_mac.cpp index c6b20fa2..55684667 100644 --- a/qxt-mini/qxtglobalshortcut_mac.cpp +++ b/qxt-mini/qxtglobalshortcut_mac.cpp @@ -55,7 +55,7 @@ OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event,          GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID);          Identifier id = keyIDs.key(keyID.id);          if(id != Identifier()) -            QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); +            QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first, true);      }      return noErr;  } @@ -76,7 +76,7 @@ quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifier      return native;  } -quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key keys)  {      UTF16Char ch;      // Constants found in NSEvent.h from AppKit.framework diff --git a/qxt-mini/qxtglobalshortcut_p.h b/qxt-mini/qxtglobalshortcut_p.h index 1835f956..7864a7d8 100644 --- a/qxt-mini/qxtglobalshortcut_p.h +++ b/qxt-mini/qxtglobalshortcut_p.h @@ -45,6 +45,7 @@ public:      QxtGlobalShortcutPrivate();      ~QxtGlobalShortcutPrivate() override; +    bool keystate;      bool enabled;      Qt::Key key;      Qt::KeyboardModifiers mods; @@ -56,7 +57,7 @@ public:      static bool eventFilter(void* message);      bool nativeEventFilter(const QByteArray & eventType, void * message, long * result) override; -    static void activateShortcut(quint32 nativeKey, quint32 nativeMods); +    static void activateShortcut(quint32 nativeKey, quint32 nativeMods, bool is_down);  private:      struct event_filter_installer; diff --git a/qxt-mini/qxtglobalshortcut_x11.cpp b/qxt-mini/qxtglobalshortcut_x11.cpp index 0db1ece5..01dfe8df 100644 --- a/qxt-mini/qxtglobalshortcut_x11.cpp +++ b/qxt-mini/qxtglobalshortcut_x11.cpp @@ -32,40 +32,57 @@  #include <QHash>  #include <QMutex> -#include <QMutexLocker>  #include <QDebug> - +#include <QPair> +#include <QKeyEvent>  #include <QApplication> -// include private header for great justice -sh 20131015 +  #include <X11/Xlib.h> +#include <X11/XKBlib.h>  #include <xcb/xcb.h>  #include "qplatformnativeinterface.h"  #include "compat/util.hpp" +#include <iterator> +#include "x11-keymap.hpp" +  static constexpr quint32 AllMods = ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask; +static constexpr quint32 evil_mods[] = { +#if 0 +    LockMask, // caps lock +    Mod3Mask, // scroll lock +#endif +    Mod2Mask, // num lock +    Mod5Mask, // altgr + +    Mod2Mask | Mod5Mask, +}; +  typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event); +using pair = QPair<quint32, quint32>; +  struct keybinding final  { -    quint32 code; +    quint32 code, mods;      int refcnt; -    static QHash<quint32, keybinding> list; +    static QHash<pair, keybinding> list;      static QMutex lock; -    static bool incf(quint32 code); -    static bool decf(quint32 code); +    static bool incf(quint32 code, quint32 mods); +    static bool decf(quint32 code, quint32 mods);      ~keybinding();  private: -    keybinding(quint32 code); +    keybinding(quint32 code, quint32 mods);  };  bool operator==(const keybinding& k1, const keybinding& k2)  { -    return k1.code == k2.code; +    return k1.code == k2.code && k1.mods == k2.mods;  }  inline bool operator!=(const keybinding& k1, const keybinding& k2) @@ -75,15 +92,17 @@ inline bool operator!=(const keybinding& k1, const keybinding& k2)  uint qHash(const keybinding& k)  { -    return qHash(k.code); +    return uint(k.code * 41) ^ qHash(k.mods);  }  uint qHash(const keybinding& k, uint seed)  { -    return qHash(k.code, seed); +    return qHash(uint(k.code * 41) ^ qHash(k.mods), seed);  } -keybinding::keybinding(quint32 code) : code(code), refcnt(0) +keybinding::keybinding(quint32 code, quint32 mods) : +    code(code), mods(mods), +    refcnt(0)  {  } @@ -91,11 +110,11 @@ keybinding::~keybinding()  {  } -bool keybinding::incf(quint32 code) +bool keybinding::incf(quint32 code, quint32 mods)  {      QMutexLocker l(&lock); -    keybinding k = list.value(code, keybinding(code)); +    keybinding k = list.value(pair(code, mods), keybinding(code, mods));      const bool ret = k.refcnt == 0; @@ -105,18 +124,18 @@ bool keybinding::incf(quint32 code)      }      k.refcnt++; -    list.insert(code, k); +    list.insert(pair(code, mods), k);      //qDebug() << "qxt-mini: incf: refcount for" << code << "now" << k.refcnt;      return ret;  } -bool keybinding::decf(quint32 code) +bool keybinding::decf(quint32 code, quint32 mods)  {      QMutexLocker l(&lock); -    auto it = list.find(code); +    auto it = list.find(pair(code, mods));      if (it == list.end())      { @@ -139,7 +158,7 @@ bool keybinding::decf(quint32 code)      return false;  } -QHash<quint32, keybinding> keybinding::list; +QHash<pair, keybinding> keybinding::list;  QMutex keybinding::lock;  class QxtX11ErrorHandler { @@ -206,57 +225,65 @@ public:          return DefaultRootWindow(display());      } -    bool grabKey(quint32 keycode, quint32 modifiers, Window window) +    static constexpr quint32 filter_evil_mods(quint32 mods)      { -        //TODO: search keybinding by code and modifiers, so keys can be assigned multiple times using different modifiers -        if (keybinding::incf(keycode)) +        for (quint32 mod : evil_mods) +            mods &= ~mod; +        return mods; +    } + +    bool grabKey(quint32 code, quint32 mods, Window window) +    { +        // qDebug() << "grabbing key" << code << mods; + +        mods = filter_evil_mods(mods); + +        // qDebug() << "mods now" << mods; + +        if (keybinding::incf(code, mods))          {              QxtX11ErrorHandler errorHandler; -            bool error = false; -            XGrabKey(display(), keycode, modifiers, window, True, -                     GrabModeAsync, GrabModeAsync); -            if (errorHandler.error) { -                error=true; -            } -            //Also grab key with num lock = on -            XGrabKey(display(), keycode, modifiers | Mod2Mask, window, True, -                     GrabModeAsync, GrabModeAsync); -            if (errorHandler.error) { -                error=true; -            } +            XGrabKey(display(), code, mods, window, True, GrabModeAsync, GrabModeAsync); -            //...and with scroll lock = on -            XGrabKey(display(), keycode, modifiers | Mod5Mask, window, True, -                     GrabModeAsync, GrabModeAsync); -            if (errorHandler.error) { -                error=true; -            } +            for (quint32 evil : evil_mods) +            { +                quint32 m = mods | evil; -            //...and with bot = on -            XGrabKey(display(), keycode, modifiers | Mod2Mask | Mod5Mask, window, True, -                     GrabModeAsync, GrabModeAsync); -            if (errorHandler.error) { -                error=true; +                XGrabKey(display(), code, m, window, True, GrabModeAsync, GrabModeAsync);              } -            if(error){ -                ungrabKey(keycode, window); +            if (errorHandler.error) +            { +                qDebug() << "qxt-mini: error while binding to" << code << mods; +                ungrabKey(code, mods, window);                  return false;              } -          }          return true;      } -    bool ungrabKey(quint32 keycode, Window window) +    bool ungrabKey(quint32 code, quint32 mods, Window window)      { -        if (keybinding::decf(keycode)) +        mods = filter_evil_mods(mods); + +        if (keybinding::decf(code, mods))          {              QxtX11ErrorHandler errorHandler; -            XUngrabKey(display(), keycode, AnyModifier, window); -            return !errorHandler.error; +            XUngrabKey(display(), code, mods, window); + +            for (quint32 evil : evil_mods) +            { +                quint32 m = mods | evil; +                XUngrabKey(display(), code, m, window); +            } + +            if (errorHandler.error) +            { +                qDebug() << "qxt-mini: error while unbinding" << code << mods; +                return false; +            }          }          return true;      } @@ -270,14 +297,65 @@ bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,  {      Q_UNUSED(result); +    { +        static bool once_ = false; +        if (!once_) +        { +            QxtX11Data x11; +            if (x11.isValid()) +            { +                once_ = true; +                Bool val; + +                (void) XkbSetDetectableAutoRepeat(x11.display(), True, &val); + +                if (val) +                    qDebug() << "qxt-mini: fixed x11 autorepeat"; +                else +                    qDebug() << "qxt-mini: can't fix x11 autorepeat"; +            } +        } +    } + +    bool is_release = false; +      xcb_key_press_event_t *kev = 0;      if (eventType == "xcb_generic_event_t") {          xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message); -        if ((ev->response_type & 127) == XCB_KEY_PRESS) -            kev = static_cast<xcb_key_press_event_t *>(message); +        switch (ev->response_type & 127) +        { +            case XCB_KEY_RELEASE: +                is_release = true; +                /*FALLTHROUGH*/ +            case XCB_KEY_PRESS: +                kev = static_cast<xcb_key_press_event_t *>(message); +                /*FALLTHROUGH*/ +            default: +                break; +        }      } -    if (kev != 0) { +    if (kev) { +#if 0 +        using event_type = decltype((xcb_key_press_event_t{}).detail); + +        static event_type prev_event = 0; +        static bool prev_is_release = false; + +        if (is_release == prev_is_release && +            prev_event != 0 && +            prev_event == kev->detail) +        { +            // ignore repeated keystrokes +            return false; +        } +        else +        { +            prev_event = kev->detail; +            prev_is_release = is_release; +        } +#endif +          unsigned int keycode = kev->detail;          unsigned int keystate = 0;          if(kev->state & XCB_MOD_MASK_1) // alt @@ -293,14 +371,15 @@ bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,              keystate |= AltGrMask;  #endif -        activateShortcut(keycode, keystate); +        // qDebug() << "qxt-mini:" << (is_release ? "keyup" : "keydown") << keycode << keystate; + +        activateShortcut(keycode, keystate, !is_release);      }      return false;  }  quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)  { -    // XXX TODO make a lookup table      quint32 native = 0;      if (modifiers & Qt::AltModifier)          native |= Mod1Mask; @@ -312,11 +391,8 @@ quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifier          native |= ShiftMask;      if (modifiers & Qt::KeypadModifier)          native |= Mod2Mask; - -#if 0 -    if (modifiers & Qt::MetaModifier) // dunno the native mask +    if (modifiers & Qt::MetaModifier) // Super aka Windows key          native |= Mod4Mask; -#endif      if (modifiers & Qt::KeypadModifier) // numlock          native |= Mod2Mask; @@ -328,31 +404,26 @@ quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifier  quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)  {      QxtX11Data x11; -    if (!x11.isValid()) -        return 0; -    QByteArray tmp(QKeySequence(key).toString().toLatin1()); +    if (x11.isValid()) +        return qt_key_to_x11(x11.display(), key); -    KeySym keysym = XStringToKeysym(tmp.data()); -    if (keysym == NoSymbol) -        keysym = static_cast<ushort>(key); - -    const quint32 ret = XKeysymToKeycode(x11.display(), keysym); - -    //qDebug() << "key is" << key << QKeySequence(key).toString(QKeySequence::PortableText) << ret; - -    return ret; +    return unsigned(-1);  } -bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, unused(quint32, nativeMods)) +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)  {      QxtX11Data x11; +    if (nativeKey == unsigned(-1)) +        return false;      return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow());  } -bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, unused(quint32, nativeMods)) +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)  {      QxtX11Data x11; -    return x11.isValid() && x11.ungrabKey(nativeKey, x11.rootWindow()); +    if (nativeKey == unsigned(-1)) +        return false; +    return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow());  }  #endif diff --git a/qxt-mini/x11-keymap.cpp b/qxt-mini/x11-keymap.cpp new file mode 100644 index 00000000..b4438a3c --- /dev/null +++ b/qxt-mini/x11-keymap.cpp @@ -0,0 +1,136 @@ +#include "x11-keymap.hpp" + +#ifndef __APPLE__ + +#include <tuple> + +#define XK_MISCELLANY +#define XK_LATIN1 +#include <X11/keysymdef.h> + +using tt = std::tuple<Qt::Key, unsigned>; + +static tt keymap[] = +{ +    { Qt::Key_Return, XK_Return }, +    { Qt::Key_Enter, XK_Return }, +    { Qt::Key_Delete, XK_Delete }, +    { Qt::Key_Pause, XK_Pause }, +    { Qt::Key_SysReq, XK_Sys_Req }, +    { Qt::Key_Home, XK_Home }, +    { Qt::Key_End, XK_End }, +    { Qt::Key_Left, XK_Left }, +    { Qt::Key_Up, XK_Up }, +    { Qt::Key_Right, XK_Right }, +    { Qt::Key_Down, XK_Down }, +    { Qt::Key_PageUp, XK_Prior }, +    { Qt::Key_PageDown, XK_Next }, + +    { Qt::Key_F1, XK_F1 }, +    { Qt::Key_F2, XK_F2 }, +    { Qt::Key_F3, XK_F3 }, +    { Qt::Key_F4, XK_F4 }, +    { Qt::Key_F5, XK_F5 }, +    { Qt::Key_F6, XK_F6 }, +    { Qt::Key_F7, XK_F7 }, +    { Qt::Key_F8, XK_F8 }, +    { Qt::Key_F9, XK_F9 }, +    { Qt::Key_F10, XK_F10 }, +    { Qt::Key_F11, XK_F11 }, +    { Qt::Key_F12, XK_F12 }, + +    { Qt::Key_Space, XK_space }, +    { Qt::Key_Exclam, XK_exclam }, +    { Qt::Key_QuoteDbl, XK_quotedbl }, +    { Qt::Key_NumberSign, XK_numbersign }, +    { Qt::Key_Dollar, XK_dollar }, +    { Qt::Key_Percent, XK_percent }, +    { Qt::Key_Ampersand, XK_ampersand }, +    { Qt::Key_Apostrophe, XK_apostrophe }, +    { Qt::Key_ParenLeft, XK_parenleft }, +    { Qt::Key_ParenRight, XK_parenright }, +    { Qt::Key_Asterisk, XK_asterisk }, +    { Qt::Key_Plus, XK_plus }, +    { Qt::Key_Comma, XK_comma }, +    { Qt::Key_Minus, XK_minus }, +    { Qt::Key_Period, XK_period }, +    { Qt::Key_Slash, XK_slash }, + +    { Qt::Key_0, XK_0 }, +    { Qt::Key_1, XK_1}, +    { Qt::Key_2, XK_2 }, +    { Qt::Key_3, XK_3 }, +    { Qt::Key_4, XK_4 }, +    { Qt::Key_5, XK_5 }, +    { Qt::Key_6, XK_6 }, +    { Qt::Key_7, XK_7 }, +    { Qt::Key_8, XK_8 }, +    { Qt::Key_9, XK_9 }, + +    { Qt::Key_Colon, XK_colon }, +    { Qt::Key_Semicolon, XK_semicolon }, +    { Qt::Key_Less, XK_less }, +    { Qt::Key_Equal, XK_equal }, +    { Qt::Key_Greater, XK_greater }, +    { Qt::Key_Question, XK_question }, +    { Qt::Key_At, XK_at }, + +    { Qt::Key_A, XK_a }, +    { Qt::Key_B, XK_b }, +    { Qt::Key_C, XK_c }, +    { Qt::Key_D, XK_d }, +    { Qt::Key_E, XK_e }, +    { Qt::Key_F, XK_f }, +    { Qt::Key_G, XK_g }, +    { Qt::Key_H, XK_h }, +    { Qt::Key_I, XK_i }, +    { Qt::Key_J, XK_j }, +    { Qt::Key_K, XK_k }, +    { Qt::Key_L, XK_l }, +    { Qt::Key_M, XK_m }, +    { Qt::Key_N, XK_n }, +    { Qt::Key_O, XK_o }, +    { Qt::Key_P, XK_p }, +    { Qt::Key_Q, XK_q }, +    { Qt::Key_R, XK_r }, +    { Qt::Key_S, XK_s }, +    { Qt::Key_T, XK_t }, +    { Qt::Key_U, XK_u }, +    { Qt::Key_V, XK_v }, +    { Qt::Key_W, XK_w }, +    { Qt::Key_X, XK_x }, +    { Qt::Key_Y, XK_y }, +    { Qt::Key_Z, XK_z }, + +    { Qt::Key_BracketLeft, XK_bracketleft }, +    { Qt::Key_Backslash, XK_backslash }, +    { Qt::Key_BracketRight, XK_bracketright }, +    { Qt::Key_AsciiCircum, XK_asciicircum }, +    { Qt::Key_Underscore, XK_underscore }, +    { Qt::Key_QuoteLeft, XK_grave }, +}; + +unsigned qt_key_to_x11(Display* disp, Qt::Key k) +{ +    Qt::Key k_; +    unsigned keysym; + +    for (const tt& tuple : keymap) +    { +        std::tie(k_, keysym) = tuple; + +        if (k == k_) +        { +            const unsigned ret = XKeysymToKeycode(disp, keysym); + +            if (ret == 0) +                return unsigned(-1); + +            return ret; +        } +    } + +    qDebug() << "qxt-mini: no keysym for" << k; +    return unsigned(-1); +} +#endif diff --git a/qxt-mini/x11-keymap.hpp b/qxt-mini/x11-keymap.hpp new file mode 100644 index 00000000..b35097bc --- /dev/null +++ b/qxt-mini/x11-keymap.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef BUILD_QXT_MINI +#   error "internal header" +#endif + +#ifndef __APPLE__ + +#include <Qt> +#include <QDebug> +#include <X11/Xlib.h> + +unsigned qt_key_to_x11(Display* disp, Qt::Key k); + +#endif | 
