diff --git a/qxt/qxtglobalshortcut.cpp b/qxt/qxtglobalshortcut.cpp index 417aacf568..0272c59449 100644 --- a/qxt/qxtglobalshortcut.cpp +++ b/qxt/qxtglobalshortcut.cpp @@ -38,6 +38,7 @@ namespace { int referenceCounter = 0; +std::function layoutChangedCallback; QHash, QxtGlobalShortcut*> shortcuts; @@ -128,6 +129,12 @@ void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativ emit shortcut->activated(shortcut); } +void QxtGlobalShortcutPrivate::onKeyboardLayoutChanged() +{ + if (layoutChangedCallback) + layoutChangedCallback(); +} + /*! \class QxtGlobalShortcut \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey". @@ -306,3 +313,8 @@ void QxtGlobalShortcut::setDisabled(bool disabled) { d_ptr->enabled = !disabled; } + +void QxtGlobalShortcut::setLayoutChangedCallback(LayoutChangedCallback callback) +{ + layoutChangedCallback = std::move(callback); +} diff --git a/qxt/qxtglobalshortcut.h b/qxt/qxtglobalshortcut.h index 628e3cd193..3bc206ce09 100644 --- a/qxt/qxtglobalshortcut.h +++ b/qxt/qxtglobalshortcut.h @@ -31,6 +31,7 @@ #include #include +#include class QxtGlobalShortcutPrivate; @@ -61,6 +62,9 @@ class QxtGlobalShortcut final : public QObject static void notifyRestartNeeded(); + using LayoutChangedCallback = std::function; + static void setLayoutChangedCallback(LayoutChangedCallback callback); + public Q_SLOTS: void setEnabled(bool enabled = true); void setDisabled(bool disabled = true); diff --git a/qxt/qxtglobalshortcut_mac.cpp b/qxt/qxtglobalshortcut_mac.cpp index 8629252274..22ff8f537b 100644 --- a/qxt/qxtglobalshortcut_mac.cpp +++ b/qxt/qxtglobalshortcut_mac.cpp @@ -40,6 +40,12 @@ static QMap keyRefs; static QHash keyIDs; static quint32 hotKeySerial = 0; static bool qxt_mac_handler_installed = false; +static bool qxt_mac_layout_observer_installed = false; + +void qxt_mac_keyboard_layout_changed(CFNotificationCenterRef, void *, CFStringRef, const void *, CFDictionaryRef) +{ + QxtGlobalShortcutPrivate::onKeyboardLayoutChanged(); +} OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) { @@ -57,6 +63,16 @@ OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void QxtGlobalShortcutPrivate::init() { + if (!qxt_mac_layout_observer_installed) { + qxt_mac_layout_observer_installed = true; + CFNotificationCenterAddObserver( + CFNotificationCenterGetDistributedCenter(), + nullptr, + qxt_mac_keyboard_layout_changed, + kTISNotifySelectedKeyboardInputSourceChanged, + nullptr, + CFNotificationSuspensionBehaviorDeliverImmediately); + } } void QxtGlobalShortcutPrivate::destroy() diff --git a/qxt/qxtglobalshortcut_p.h b/qxt/qxtglobalshortcut_p.h index b736861c4b..fba923f4a1 100644 --- a/qxt/qxtglobalshortcut_p.h +++ b/qxt/qxtglobalshortcut_p.h @@ -67,6 +67,7 @@ class QxtGlobalShortcutPrivate const QByteArray &eventType, void *message, NativeEventResult *result) override; static void activateShortcut(quint32 nativeKey, quint32 nativeMods); + static void onKeyboardLayoutChanged(); private: void initFallback(); diff --git a/qxt/qxtglobalshortcut_win.cpp b/qxt/qxtglobalshortcut_win.cpp index 931d89473e..f8eb9a649e 100644 --- a/qxt/qxtglobalshortcut_win.cpp +++ b/qxt/qxtglobalshortcut_win.cpp @@ -57,11 +57,12 @@ bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, Q_UNUSED(eventType) Q_UNUSED(result) MSG* msg = static_cast(message); - if (msg->message == WM_HOTKEY) - { + if (msg->message == WM_HOTKEY) { const quint32 keycode = HIWORD(msg->lParam); const quint32 modifiers = LOWORD(msg->lParam); activateShortcut(keycode, modifiers); + } else if (msg->message == WM_INPUTLANGCHANGE) { + onKeyboardLayoutChanged(); } return false; } diff --git a/src/app/clipboardserver.cpp b/src/app/clipboardserver.cpp index bf8e0648eb..0f8d1e2a19 100644 --- a/src/app/clipboardserver.cpp +++ b/src/app/clipboardserver.cpp @@ -7,6 +7,7 @@ #include "common/clientsocket.h" #include "common/client_server.h" #include "common/commandstatus.h" +#include "common/commandstore.h" #include "common/config.h" #include "common/log.h" #include "common/mimetypes.h" @@ -233,6 +234,12 @@ ClipboardServer::ClipboardServer(QApplication *app, const QString &sessionName) setClipboardMonitorRunning(false); startMonitoring(); +#ifdef COPYQ_GLOBAL_SHORTCUTS + QxtGlobalShortcut::setLayoutChangedCallback([this]() { + onKeyboardLayoutChanged(); + }); +#endif + callback(QStringLiteral("onStart")); } @@ -240,6 +247,9 @@ ClipboardServer::~ClipboardServer() { qApp->setProperty("CopyQ_server", QVariant()); +#ifdef COPYQ_GLOBAL_SHORTCUTS + QxtGlobalShortcut::setLayoutChangedCallback(nullptr); +#endif removeGlobalShortcuts(); delete m_wnd; @@ -303,13 +313,12 @@ void ClipboardServer::removeGlobalShortcuts() m_shortcutActions.clear(); } -void ClipboardServer::onCommandsSaved(const QVector &commands) +void ClipboardServer::addGlobalShortcuts(const QVector &commands) { -#ifdef COPYQ_GLOBAL_SHORTCUTS - removeGlobalShortcuts(); - +#ifndef COPYQ_GLOBAL_SHORTCUTS + Q_UNUSED(commands) +#else QList usedShortcuts; - for (const auto &command : commands) { if (command.type() & CommandType::GlobalShortcut) { for (const auto &shortcutText : command.globalShortcuts) { @@ -322,6 +331,23 @@ void ClipboardServer::onCommandsSaved(const QVector &commands) } } #endif +} + +void ClipboardServer::onKeyboardLayoutChanged() +{ +#ifdef COPYQ_GLOBAL_SHORTCUTS + COPYQ_LOG("Keyboard layout changed, re-registering shortcuts"); + removeGlobalShortcuts(); + addGlobalShortcuts(loadAllCommands()); +#endif +} + +void ClipboardServer::onCommandsSaved(const QVector &commands) +{ +#ifdef COPYQ_GLOBAL_SHORTCUTS + removeGlobalShortcuts(); + addGlobalShortcuts(commands); +#endif const auto hash = monitorCommandStateHash(commands); if ( m_monitor && hash != m_monitorCommandsStateHash ) { diff --git a/src/app/clipboardserver.h b/src/app/clipboardserver.h index b48371e56a..e2ac51d88f 100644 --- a/src/app/clipboardserver.h +++ b/src/app/clipboardserver.h @@ -84,6 +84,8 @@ class ClipboardServer final : public QObject, public App void shortcutActivated(QxtGlobalShortcut *shortcut); void removeGlobalShortcuts(); + void addGlobalShortcuts(const QVector &commands); + void onKeyboardLayoutChanged(); /** Called when new commands are available. */ void onCommandsSaved(const QVector &commands);