From 48c30a3d75d18e87e39c18cb52961bb37ab6055e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Fri, 30 Oct 2015 10:07:42 +0100 Subject: qxt: fix unix build --- qxt-mini/plat/qxtglobalshortcut_mac.cpp | 268 ------------------------------- qxt-mini/plat/qxtglobalshortcut_x11.cpp | 235 --------------------------- qxt-mini/qxtglobal.h | 4 +- qxt-mini/qxtglobalshortcut.cpp | 1 + qxt-mini/qxtglobalshortcut_mac.cpp | 271 ++++++++++++++++++++++++++++++++ qxt-mini/qxtglobalshortcut_x11.cpp | 238 ++++++++++++++++++++++++++++ 6 files changed, 511 insertions(+), 506 deletions(-) delete mode 100644 qxt-mini/plat/qxtglobalshortcut_mac.cpp delete mode 100644 qxt-mini/plat/qxtglobalshortcut_x11.cpp create mode 100644 qxt-mini/qxtglobalshortcut_mac.cpp create mode 100644 qxt-mini/qxtglobalshortcut_x11.cpp (limited to 'qxt-mini') diff --git a/qxt-mini/plat/qxtglobalshortcut_mac.cpp b/qxt-mini/plat/qxtglobalshortcut_mac.cpp deleted file mode 100644 index 1181b293..00000000 --- a/qxt-mini/plat/qxtglobalshortcut_mac.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include -/**************************************************************************** -** Copyright (c) 2006 - 2011, the LibQxt project. -** See the Qxt AUTHORS file for a list of authors and copyright holders. -** 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 the LibQxt project nor the -** names of its 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 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. -** -** -*****************************************************************************/ - -#pragma GCC diagnostic ignored "-Wfour-char-constants" -#pragma GCC diagnostic ignored "-Wunused-parameter" - -#include "qxtglobalshortcut_p.h" -#include -#include -#include -#include - -typedef QPair Identifier; -static QMap keyRefs; -static QHash keyIDs; -static quint32 hotKeySerial = 0; -static bool qxt_mac_handler_installed = false; - -OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) -{ - Q_UNUSED(nextHandler); - Q_UNUSED(data); - if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) - { - EventHotKeyID keyID; - GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); - Identifier id = keyIDs.key(keyID.id); - if(id != Identifier()) - QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); - } - return noErr; -} - -quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) -{ - quint32 native = 0; - if (modifiers & Qt::ShiftModifier) - native |= shiftKey; - if (modifiers & Qt::ControlModifier) - native |= cmdKey; - if (modifiers & Qt::AltModifier) - native |= optionKey; - if (modifiers & Qt::MetaModifier) - native |= controlKey; - if (modifiers & Qt::KeypadModifier) - native |= kEventKeyModifierNumLockMask; - return native; -} - -quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) -{ - UTF16Char ch; - // Constants found in NSEvent.h from AppKit.framework - switch (key) - { - case Qt::Key_Return: - return kVK_Return; - case Qt::Key_Enter: - return kVK_ANSI_KeypadEnter; - case Qt::Key_Tab: - return kVK_Tab; - case Qt::Key_Space: - return kVK_Space; - case Qt::Key_Backspace: - return kVK_Delete; - case Qt::Key_Control: - return kVK_Command; - case Qt::Key_Shift: - return kVK_Shift; - case Qt::Key_CapsLock: - return kVK_CapsLock; - case Qt::Key_Option: - return kVK_Option; - case Qt::Key_Meta: - return kVK_Control; - case Qt::Key_F17: - return kVK_F17; - case Qt::Key_VolumeUp: - return kVK_VolumeUp; - case Qt::Key_VolumeDown: - return kVK_VolumeDown; - case Qt::Key_F18: - return kVK_F18; - case Qt::Key_F19: - return kVK_F19; - case Qt::Key_F20: - return kVK_F20; - case Qt::Key_F5: - return kVK_F5; - case Qt::Key_F6: - return kVK_F6; - case Qt::Key_F7: - return kVK_F7; - case Qt::Key_F3: - return kVK_F3; - case Qt::Key_F8: - return kVK_F8; - case Qt::Key_F9: - return kVK_F9; - case Qt::Key_F11: - return kVK_F11; - case Qt::Key_F13: - return kVK_F13; - case Qt::Key_F16: - return kVK_F16; - case Qt::Key_F14: - return kVK_F14; - case Qt::Key_F10: - return kVK_F10; - case Qt::Key_F12: - return kVK_F12; - case Qt::Key_F15: - return kVK_F15; - case Qt::Key_Help: - return kVK_Help; - case Qt::Key_Home: - return kVK_Home; - case Qt::Key_PageUp: - return kVK_PageUp; - case Qt::Key_Delete: - return kVK_ForwardDelete; - case Qt::Key_F4: - return kVK_F4; - case Qt::Key_End: - return kVK_End; - case Qt::Key_F2: - return kVK_F2; - case Qt::Key_PageDown: - return kVK_PageDown; - case Qt::Key_F1: - return kVK_F1; - case Qt::Key_Left: - return kVK_LeftArrow; - case Qt::Key_Right: - return kVK_RightArrow; - case Qt::Key_Down: - return kVK_DownArrow; - case Qt::Key_Up: - return kVK_UpArrow; - default: - ; - } - - if (key == Qt::Key_Escape) ch = 27; - else if (key == Qt::Key_Return) ch = 13; - else if (key == Qt::Key_Enter) ch = 3; - else if (key == Qt::Key_Tab) ch = 9; - else ch = key; - - CFDataRef currentLayoutData; - TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); - - if (currentKeyboard == NULL) - return 0; - - currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); - CFRelease(currentKeyboard); - if (currentLayoutData == NULL) - return 0; - - UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData); - UCKeyboardTypeHeader* table = header->keyboardTypeList; - - uint8_t *data = (uint8_t*)header; - // God, would a little documentation for this shit kill you... - for (quint32 i=0; i < header->keyboardTypeCount; i++) - { - UCKeyStateRecordsIndex* stateRec = 0; - if (table[i].keyStateRecordsIndexOffset != 0) - { - stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); - if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; - } - - UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); - if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; - - for (quint32 j=0; j < charTable->keyToCharTableCount; j++) - { - UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); - for (quint32 k=0; k < charTable->keyToCharTableSize; k++) - { - if (keyToChar[k] & kUCKeyOutputTestForIndexMask) - { - long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; - if (stateRec && idx < stateRec->keyStateRecordCount) - { - UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); - if (rec->stateZeroCharData == ch) return k; - } - } - else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) - { - if (keyToChar[k] == ch) return k; - } - } // for k - } // for j - } // for i - return 0; -} - -bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) -{ - if (!qxt_mac_handler_installed) - { - qxt_mac_handler_installed = true; - EventTypeSpec t; - t.eventClass = kEventClassKeyboard; - t.eventKind = kEventHotKeyPressed; - InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); - } - - EventHotKeyID keyID; - keyID.signature = 'cute'; - keyID.id = ++hotKeySerial; - - EventHotKeyRef ref = 0; - bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); - if (rv) - { - keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); - keyRefs.insert(keyID.id, ref); - } - return rv; -} - -bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) -{ - Identifier id(nativeMods, nativeKey); - if (!keyIDs.contains(id)) return false; - - EventHotKeyRef ref = keyRefs.take(keyIDs[id]); - keyIDs.remove(id); - return !UnregisterEventHotKey(ref); -} -bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, - void *message, long *result) -{ - return false; -} diff --git a/qxt-mini/plat/qxtglobalshortcut_x11.cpp b/qxt-mini/plat/qxtglobalshortcut_x11.cpp deleted file mode 100644 index f18f86db..00000000 --- a/qxt-mini/plat/qxtglobalshortcut_x11.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include "../qxtglobalshortcut_p.h" -/**************************************************************************** -** Copyright (c) 2006 - 2011, the LibQxt project. -** See the Qxt AUTHORS file for a list of authors and copyright holders. -** 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 the LibQxt project nor the -** names of its 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 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. -** -** -*****************************************************************************/ - -#include -#include -// include private header for great justice -sh 20131015 -#include -#include -#include "qplatformnativeinterface.h" - -namespace { - -const QVector maskModifiers = QVector() - << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask); - -typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event); - -class QxtX11ErrorHandler { -public: - static bool error; - - static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) - { - Q_UNUSED(display); - switch (event->error_code) - { - case BadAccess: - case BadValue: - case BadWindow: - if (event->request_code == 33 /* X_GrabKey */ || - event->request_code == 34 /* X_UngrabKey */) - { - error = true; - //TODO: - //char errstr[256]; - //XGetErrorText(dpy, err->error_code, errstr, 256); - } - } - return 0; - } - - QxtX11ErrorHandler() - { - error = false; - m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler); - } - - ~QxtX11ErrorHandler() - { - XSetErrorHandler(m_previousErrorHandler); - } - -private: - X11ErrorHandler m_previousErrorHandler; -}; - -bool QxtX11ErrorHandler::error = false; - -class QxtX11Data { -public: - QxtX11Data() - { -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) - m_display = QX11Info::display(); -#else - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - void *display = native->nativeResourceForScreen(QByteArray("display"), - QGuiApplication::primaryScreen()); - m_display = reinterpret_cast(display); -#endif - } - - bool isValid() - { - return m_display != 0; - } - - Display *display() - { - Q_ASSERT(isValid()); - return m_display; - } - - Window rootWindow() - { - return DefaultRootWindow(display()); - } - - bool grabKey(quint32 keycode, quint32 modifiers, Window window) - { - QxtX11ErrorHandler errorHandler; - - for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) { - XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, - GrabModeAsync, GrabModeAsync); - } - - if (errorHandler.error) { - ungrabKey(keycode, modifiers, window); - return false; - } - - return true; - } - - bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) - { - QxtX11ErrorHandler errorHandler; - - foreach (quint32 maskMods, maskModifiers) { - XUngrabKey(display(), keycode, modifiers | maskMods, window); - } - - return !errorHandler.error; - } - -private: - Display *m_display; -}; - -} // namespace - -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) -bool QxtGlobalShortcutPrivate::eventFilter(void *message) -{ - XEvent *event = static_cast(message); - if (event->type == KeyPress) - { - XKeyEvent *key = reinterpret_cast(event); - unsigned int keycode = key->keycode; - unsigned int keystate = key->state; -#else -bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, - void *message, long *result) -{ - Q_UNUSED(result); - - xcb_key_press_event_t *kev = 0; - if (eventType == "xcb_generic_event_t") { - xcb_generic_event_t *ev = static_cast(message); - if ((ev->response_type & 127) == XCB_KEY_PRESS) - kev = static_cast(message); - } - - if (kev != 0) { - unsigned int keycode = kev->detail; - unsigned int keystate = 0; - if(kev->state & XCB_MOD_MASK_1) - keystate |= Mod1Mask; - if(kev->state & XCB_MOD_MASK_CONTROL) - keystate |= ControlMask; - if(kev->state & XCB_MOD_MASK_4) - keystate |= Mod4Mask; - if(kev->state & XCB_MOD_MASK_SHIFT) - keystate |= ShiftMask; -#endif - activateShortcut(keycode, - // Mod1Mask == Alt, Mod4Mask == Meta - keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); - } - return false; -} - -quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) -{ - // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask - quint32 native = 0; - if (modifiers & Qt::ShiftModifier) - native |= ShiftMask; - if (modifiers & Qt::ControlModifier) - native |= ControlMask; - if (modifiers & Qt::AltModifier) - native |= Mod1Mask; - if (modifiers & Qt::MetaModifier) - native |= Mod4Mask; - - // TODO: resolve these? - //if (modifiers & Qt::MetaModifier) - //if (modifiers & Qt::KeypadModifier) - //if (modifiers & Qt::GroupSwitchModifier) - return native; -} - -quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) -{ - QxtX11Data x11; - if (!x11.isValid()) - return 0; - - KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); - if (keysym == NoSymbol) - keysym = static_cast(key); - - return XKeysymToKeycode(x11.display(), keysym); -} - -bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) -{ - QxtX11Data x11; - return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow()); -} - -bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) -{ - QxtX11Data x11; - return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow()); -} diff --git a/qxt-mini/qxtglobal.h b/qxt-mini/qxtglobal.h index fa592181..574482ae 100644 --- a/qxt-mini/qxtglobal.h +++ b/qxt-mini/qxtglobal.h @@ -51,9 +51,7 @@ #define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE -#define QXT_STATIC - -#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) +#ifdef QXT_BUILD # if defined(BUILD_QXT_CORE) # define QXT_CORE_EXPORT Q_DECL_EXPORT # else diff --git a/qxt-mini/qxtglobalshortcut.cpp b/qxt-mini/qxtglobalshortcut.cpp index 45576d37..4b400a72 100644 --- a/qxt-mini/qxtglobalshortcut.cpp +++ b/qxt-mini/qxtglobalshortcut.cpp @@ -1,3 +1,4 @@ +#define QXT_BUILD #include "qxtglobalshortcut.h" /**************************************************************************** ** Copyright (c) 2006 - 2011, the LibQxt project. diff --git a/qxt-mini/qxtglobalshortcut_mac.cpp b/qxt-mini/qxtglobalshortcut_mac.cpp new file mode 100644 index 00000000..34de694e --- /dev/null +++ b/qxt-mini/qxtglobalshortcut_mac.cpp @@ -0,0 +1,271 @@ +#ifdef __APPLE__ +#define QXT_BUILD +#include +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** 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 the LibQxt project nor the +** names of its 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 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. +** +** +*****************************************************************************/ + +#pragma GCC diagnostic ignored "-Wfour-char-constants" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +#include "qxtglobalshortcut_p.h" +#include +#include +#include +#include + +typedef QPair Identifier; +static QMap keyRefs; +static QHash keyIDs; +static quint32 hotKeySerial = 0; +static bool qxt_mac_handler_installed = false; + +OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) +{ + Q_UNUSED(nextHandler); + Q_UNUSED(data); + if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) + { + EventHotKeyID keyID; + GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); + Identifier id = keyIDs.key(keyID.id); + if(id != Identifier()) + QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); + } + return noErr; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= shiftKey; + if (modifiers & Qt::ControlModifier) + native |= cmdKey; + if (modifiers & Qt::AltModifier) + native |= optionKey; + if (modifiers & Qt::MetaModifier) + native |= controlKey; + if (modifiers & Qt::KeypadModifier) + native |= kEventKeyModifierNumLockMask; + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + UTF16Char ch; + // Constants found in NSEvent.h from AppKit.framework + switch (key) + { + case Qt::Key_Return: + return kVK_Return; + case Qt::Key_Enter: + return kVK_ANSI_KeypadEnter; + case Qt::Key_Tab: + return kVK_Tab; + case Qt::Key_Space: + return kVK_Space; + case Qt::Key_Backspace: + return kVK_Delete; + case Qt::Key_Control: + return kVK_Command; + case Qt::Key_Shift: + return kVK_Shift; + case Qt::Key_CapsLock: + return kVK_CapsLock; + case Qt::Key_Option: + return kVK_Option; + case Qt::Key_Meta: + return kVK_Control; + case Qt::Key_F17: + return kVK_F17; + case Qt::Key_VolumeUp: + return kVK_VolumeUp; + case Qt::Key_VolumeDown: + return kVK_VolumeDown; + case Qt::Key_F18: + return kVK_F18; + case Qt::Key_F19: + return kVK_F19; + case Qt::Key_F20: + return kVK_F20; + case Qt::Key_F5: + return kVK_F5; + case Qt::Key_F6: + return kVK_F6; + case Qt::Key_F7: + return kVK_F7; + case Qt::Key_F3: + return kVK_F3; + case Qt::Key_F8: + return kVK_F8; + case Qt::Key_F9: + return kVK_F9; + case Qt::Key_F11: + return kVK_F11; + case Qt::Key_F13: + return kVK_F13; + case Qt::Key_F16: + return kVK_F16; + case Qt::Key_F14: + return kVK_F14; + case Qt::Key_F10: + return kVK_F10; + case Qt::Key_F12: + return kVK_F12; + case Qt::Key_F15: + return kVK_F15; + case Qt::Key_Help: + return kVK_Help; + case Qt::Key_Home: + return kVK_Home; + case Qt::Key_PageUp: + return kVK_PageUp; + case Qt::Key_Delete: + return kVK_ForwardDelete; + case Qt::Key_F4: + return kVK_F4; + case Qt::Key_End: + return kVK_End; + case Qt::Key_F2: + return kVK_F2; + case Qt::Key_PageDown: + return kVK_PageDown; + case Qt::Key_F1: + return kVK_F1; + case Qt::Key_Left: + return kVK_LeftArrow; + case Qt::Key_Right: + return kVK_RightArrow; + case Qt::Key_Down: + return kVK_DownArrow; + case Qt::Key_Up: + return kVK_UpArrow; + default: + ; + } + + if (key == Qt::Key_Escape) ch = 27; + else if (key == Qt::Key_Return) ch = 13; + else if (key == Qt::Key_Enter) ch = 3; + else if (key == Qt::Key_Tab) ch = 9; + else ch = key; + + CFDataRef currentLayoutData; + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + + if (currentKeyboard == NULL) + return 0; + + currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + CFRelease(currentKeyboard); + if (currentLayoutData == NULL) + return 0; + + UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData); + UCKeyboardTypeHeader* table = header->keyboardTypeList; + + uint8_t *data = (uint8_t*)header; + // God, would a little documentation for this shit kill you... + for (quint32 i=0; i < header->keyboardTypeCount; i++) + { + UCKeyStateRecordsIndex* stateRec = 0; + if (table[i].keyStateRecordsIndexOffset != 0) + { + stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); + if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; + } + + UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); + if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; + + for (quint32 j=0; j < charTable->keyToCharTableCount; j++) + { + UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); + for (quint32 k=0; k < charTable->keyToCharTableSize; k++) + { + if (keyToChar[k] & kUCKeyOutputTestForIndexMask) + { + long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; + if (stateRec && idx < stateRec->keyStateRecordCount) + { + UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); + if (rec->stateZeroCharData == ch) return k; + } + } + else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) + { + if (keyToChar[k] == ch) return k; + } + } // for k + } // for j + } // for i + return 0; +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + if (!qxt_mac_handler_installed) + { + qxt_mac_handler_installed = true; + EventTypeSpec t; + t.eventClass = kEventClassKeyboard; + t.eventKind = kEventHotKeyPressed; + InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); + } + + EventHotKeyID keyID; + keyID.signature = 'cute'; + keyID.id = ++hotKeySerial; + + EventHotKeyRef ref = 0; + bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); + if (rv) + { + keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); + keyRefs.insert(keyID.id, ref); + } + return rv; +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + Identifier id(nativeMods, nativeKey); + if (!keyIDs.contains(id)) return false; + + EventHotKeyRef ref = keyRefs.take(keyIDs[id]); + keyIDs.remove(id); + return !UnregisterEventHotKey(ref); +} +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void *message, long *result) +{ + return false; +} +#endif diff --git a/qxt-mini/qxtglobalshortcut_x11.cpp b/qxt-mini/qxtglobalshortcut_x11.cpp new file mode 100644 index 00000000..b13770a2 --- /dev/null +++ b/qxt-mini/qxtglobalshortcut_x11.cpp @@ -0,0 +1,238 @@ +#ifndef __APPLE_ +#define QXT_BUILD +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** 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 the LibQxt project nor the +** names of its 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 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. +** +** +*****************************************************************************/ + +#include +#include +// include private header for great justice -sh 20131015 +#include +#include +#include "qplatformnativeinterface.h" + +namespace { + +const QVector maskModifiers = QVector() + << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask); + +typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event); + +class QxtX11ErrorHandler { +public: + static bool error; + + static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) + { + Q_UNUSED(display); + switch (event->error_code) + { + case BadAccess: + case BadValue: + case BadWindow: + if (event->request_code == 33 /* X_GrabKey */ || + event->request_code == 34 /* X_UngrabKey */) + { + error = true; + //TODO: + //char errstr[256]; + //XGetErrorText(dpy, err->error_code, errstr, 256); + } + } + return 0; + } + + QxtX11ErrorHandler() + { + error = false; + m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler); + } + + ~QxtX11ErrorHandler() + { + XSetErrorHandler(m_previousErrorHandler); + } + +private: + X11ErrorHandler m_previousErrorHandler; +}; + +bool QxtX11ErrorHandler::error = false; + +class QxtX11Data { +public: + QxtX11Data() + { +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + m_display = QX11Info::display(); +#else + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + void *display = native->nativeResourceForScreen(QByteArray("display"), + QGuiApplication::primaryScreen()); + m_display = reinterpret_cast(display); +#endif + } + + bool isValid() + { + return m_display != 0; + } + + Display *display() + { + Q_ASSERT(isValid()); + return m_display; + } + + Window rootWindow() + { + return DefaultRootWindow(display()); + } + + bool grabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) { + XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, + GrabModeAsync, GrabModeAsync); + } + + if (errorHandler.error) { + ungrabKey(keycode, modifiers, window); + return false; + } + + return true; + } + + bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + foreach (quint32 maskMods, maskModifiers) { + XUngrabKey(display(), keycode, modifiers | maskMods, window); + } + + return !errorHandler.error; + } + +private: + Display *m_display; +}; + +} // namespace + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +bool QxtGlobalShortcutPrivate::eventFilter(void *message) +{ + XEvent *event = static_cast(message); + if (event->type == KeyPress) + { + XKeyEvent *key = reinterpret_cast(event); + unsigned int keycode = key->keycode; + unsigned int keystate = key->state; +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void *message, long *result) +{ + Q_UNUSED(result); + + xcb_key_press_event_t *kev = 0; + if (eventType == "xcb_generic_event_t") { + xcb_generic_event_t *ev = static_cast(message); + if ((ev->response_type & 127) == XCB_KEY_PRESS) + kev = static_cast(message); + } + + if (kev != 0) { + unsigned int keycode = kev->detail; + unsigned int keystate = 0; + if(kev->state & XCB_MOD_MASK_1) + keystate |= Mod1Mask; + if(kev->state & XCB_MOD_MASK_CONTROL) + keystate |= ControlMask; + if(kev->state & XCB_MOD_MASK_4) + keystate |= Mod4Mask; + if(kev->state & XCB_MOD_MASK_SHIFT) + keystate |= ShiftMask; +#endif + activateShortcut(keycode, + // Mod1Mask == Alt, Mod4Mask == Meta + keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); + } + return false; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= ShiftMask; + if (modifiers & Qt::ControlModifier) + native |= ControlMask; + if (modifiers & Qt::AltModifier) + native |= Mod1Mask; + if (modifiers & Qt::MetaModifier) + native |= Mod4Mask; + + // TODO: resolve these? + //if (modifiers & Qt::MetaModifier) + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + QxtX11Data x11; + if (!x11.isValid()) + return 0; + + KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); + if (keysym == NoSymbol) + keysym = static_cast(key); + + return XKeysymToKeycode(x11.display(), keysym); +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow()); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow()); +} +#endif -- cgit v1.2.3