2024-11-07 03:53:04 +00:00
|
|
|
#pragma once
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2024-11-14 11:12:17 +00:00
|
|
|
/// @file
|
2024-11-21 18:03:27 +00:00
|
|
|
/// Handling global hotkeys and some trick
|
|
|
|
/// Part of this header is implemented in
|
|
|
|
/// + `winhotkeywrapper`
|
|
|
|
/// + `machotkeywrapper`
|
|
|
|
/// + `x11hotkeywrapper`
|
2024-11-14 11:12:17 +00:00
|
|
|
|
2023-05-30 06:31:07 +00:00
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QThread>
|
|
|
|
#include "config.hh"
|
|
|
|
#include "ex.hh"
|
|
|
|
#include "qtsingleapplication.h"
|
|
|
|
#include "utils.hh"
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2013-05-31 05:28:36 +00:00
|
|
|
#ifdef HAVE_X11
|
2023-05-30 06:31:07 +00:00
|
|
|
#include <fixx11h.h>
|
|
|
|
#include <set>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/extensions/record.h>
|
|
|
|
#include <X11/Xlibint.h>
|
|
|
|
#undef Bool
|
|
|
|
#undef min
|
|
|
|
#undef max
|
2009-04-19 21:32:18 +00:00
|
|
|
#endif
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2023-05-30 06:31:07 +00:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
#include <QAbstractNativeEventFilter>
|
|
|
|
#endif
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2014-05-12 13:53:13 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2024-11-12 10:19:59 +00:00
|
|
|
#import <Carbon/Carbon.h>
|
2013-04-05 12:25:34 +00:00
|
|
|
#endif
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
struct HotkeyStruct
|
|
|
|
{
|
2024-11-14 11:12:17 +00:00
|
|
|
HotkeyStruct() = default;
|
2009-04-21 21:07:15 +00:00
|
|
|
HotkeyStruct( quint32 key, quint32 key2, quint32 modifier, int handle, int id );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2024-11-14 12:24:46 +00:00
|
|
|
quint32 key = 0;
|
|
|
|
quint32 key2 = 0;
|
|
|
|
quint32 modifier = 0;
|
|
|
|
int handle = 0;
|
|
|
|
int id = 0;
|
2014-05-12 13:53:13 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2024-11-14 11:12:17 +00:00
|
|
|
EventHotKeyRef hkRef = 0;
|
|
|
|
EventHotKeyRef hkRef2 = 0;
|
2013-04-05 12:25:34 +00:00
|
|
|
#endif
|
2009-04-19 21:32:18 +00:00
|
|
|
};
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
class HotkeyWrapper: public QThread // Thread is actually only used on X11
|
2009-04-19 21:32:18 +00:00
|
|
|
{
|
|
|
|
Q_OBJECT
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
friend class QHotkeyApplication;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
public:
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
DEF_EX( exInit, "Hotkey wrapper failed to init", std::exception )
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
HotkeyWrapper( QObject * parent );
|
|
|
|
virtual ~HotkeyWrapper();
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
/// The handle is passed back in hotkeyActivated() to inform which hotkey
|
|
|
|
/// was activated.
|
|
|
|
bool setGlobalKey( int key, int key2, Qt::KeyboardModifiers modifier, int handle );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2022-12-30 02:09:37 +00:00
|
|
|
bool setGlobalKey( QKeySequence const &, int );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 21:07:15 +00:00
|
|
|
/// Unregisters everything
|
|
|
|
void unregister();
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
signals:
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
void hotkeyActivated( int );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
protected slots:
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
void waitKey2();
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2014-05-12 13:53:13 +00:00
|
|
|
#ifndef Q_OS_MAC
|
2009-04-21 18:27:26 +00:00
|
|
|
private slots:
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
bool checkState( quint32 vk, quint32 mod );
|
2013-04-05 12:25:34 +00:00
|
|
|
#endif
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
private:
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
void init();
|
|
|
|
quint32 nativeKey( int key );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
QList< HotkeyStruct > hotkeys;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
bool state2;
|
|
|
|
HotkeyStruct state2waiter;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
#ifdef Q_OS_WIN32
|
2022-02-27 05:17:37 +00:00
|
|
|
virtual bool winEvent( MSG * message, qintptr * result );
|
2009-04-19 21:32:18 +00:00
|
|
|
HWND hwnd;
|
2024-11-14 11:12:17 +00:00
|
|
|
#endif
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2024-11-14 11:12:17 +00:00
|
|
|
#ifdef Q_OS_MAC
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2013-04-05 12:25:34 +00:00
|
|
|
public:
|
|
|
|
void activated( int hkId );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2013-04-05 12:25:34 +00:00
|
|
|
private:
|
|
|
|
void sendCmdC();
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2013-04-05 12:25:34 +00:00
|
|
|
static EventHandlerUPP hotKeyFunction;
|
|
|
|
quint32 keyC;
|
|
|
|
EventHandlerRef handlerRef;
|
2024-11-14 11:12:17 +00:00
|
|
|
#endif
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2024-11-14 11:12:17 +00:00
|
|
|
#ifdef HAVE_X11
|
2009-04-21 18:27:26 +00:00
|
|
|
static void recordEventCallback( XPointer, XRecordInterceptData * );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
/// Called by recordEventCallback()
|
|
|
|
void handleRecordEvent( XRecordInterceptData * );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2024-11-21 18:03:27 +00:00
|
|
|
void run() override; // QThread
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
// We do one-time init of those, translating keysyms to keycodes
|
2009-04-22 15:29:28 +00:00
|
|
|
KeyCode lShiftCode, rShiftCode, lCtrlCode, rCtrlCode, lAltCode, rAltCode, cCode, insertCode, kpInsertCode, lMetaCode,
|
2013-09-24 13:55:58 +00:00
|
|
|
rMetaCode;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
quint32 currentModifiers;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
Display * dataDisplay;
|
|
|
|
XRecordRange * recordRange;
|
|
|
|
XRecordContext recordContext;
|
|
|
|
XRecordClientSpec recordClientSpec;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-22 15:29:28 +00:00
|
|
|
/// Holds all the keys currently grabbed.
|
|
|
|
/// The first value is keycode, the second is modifiers
|
|
|
|
using GrabbedKeys = std::set< std::pair< quint32, quint32 > >;
|
|
|
|
GrabbedKeys grabbedKeys;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-22 15:29:28 +00:00
|
|
|
GrabbedKeys::iterator keyToUngrab; // Used for second stage grabs
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-22 15:29:28 +00:00
|
|
|
/// Returns true if the given key is usually used to copy from clipboard,
|
|
|
|
/// false otherwise.
|
|
|
|
bool isCopyToClipboardKey( quint32 keyCode, quint32 modifiers ) const;
|
|
|
|
/// Returns true if the given key is grabbed, false otherwise
|
|
|
|
bool isKeyGrabbed( quint32 keyCode, quint32 modifiers ) const;
|
|
|
|
/// Grabs the given key, recording the fact in grabbedKeys. If the key's
|
|
|
|
/// already grabbed, does nothing.
|
|
|
|
/// Returns the key's iterator in grabbedKeys.
|
|
|
|
GrabbedKeys::iterator grabKey( quint32 keyCode, quint32 modifiers );
|
|
|
|
/// Ungrabs the given key. erasing it from grabbedKeys. The key's provided
|
|
|
|
/// as an interator inside the grabbedKeys set.
|
|
|
|
void ungrabKey( GrabbedKeys::iterator );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
signals:
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-21 18:27:26 +00:00
|
|
|
/// Emitted from the thread
|
|
|
|
void keyRecorded( quint32 vk, quint32 mod );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
#endif
|
|
|
|
};
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2023-07-20 08:02:22 +00:00
|
|
|
|
|
|
|
|
2023-04-28 16:45:03 +00:00
|
|
|
class QHotkeyApplication: public QtSingleApplication
|
|
|
|
#if defined( Q_OS_WIN )
|
|
|
|
,
|
|
|
|
public QAbstractNativeEventFilter
|
|
|
|
#endif
|
2018-03-27 14:46:03 +00:00
|
|
|
{
|
|
|
|
Q_OBJECT
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
friend class HotkeyWrapper;
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
public:
|
2010-11-20 13:43:55 +00:00
|
|
|
QHotkeyApplication( QString const & id, int & argc, char ** argv );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2024-11-26 05:51:08 +00:00
|
|
|
#ifdef Q_OS_WIN
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
protected:
|
|
|
|
void registerWrapper( HotkeyWrapper * wrapper );
|
|
|
|
void unregisterWrapper( HotkeyWrapper * wrapper );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2022-02-27 05:17:37 +00:00
|
|
|
virtual bool nativeEventFilter( const QByteArray & eventType, void * message, qintptr * result );
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
QList< HotkeyWrapper * > hotkeyWrappers;
|
2024-11-26 05:51:08 +00:00
|
|
|
#endif
|
2009-04-19 21:32:18 +00:00
|
|
|
};
|
2023-07-20 08:02:22 +00:00
|
|
|
|
2009-04-19 21:32:18 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|