Fix the global shortcut grabber on Mac.
This commit is contained in:
parent
3aa1d75163
commit
85e101c8a7
|
@ -698,6 +698,7 @@ if(APPLE)
|
|||
list(APPEND HEADERS widgets/maclineedit.h)
|
||||
list(APPEND SOURCES core/macglobalshortcutbackend.mm)
|
||||
list(APPEND SOURCES devices/macdevicelister.mm)
|
||||
list(APPEND SOURCES ui/globalshortcutgrabber.mm)
|
||||
list(APPEND SOURCES ui/macscreensaver.cpp)
|
||||
list(APPEND SOURCES ui/macsystemtrayicon.mm)
|
||||
list(APPEND SOURCES widgets/maclineedit.mm)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef MAC_STARTUP_H
|
||||
#define MAC_STARTUP_H
|
||||
|
||||
#include <QKeySequence>
|
||||
|
||||
class MacGlobalShortcutBackend;
|
||||
class QObject;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "globalshortcuts.h"
|
||||
#include "mac_delegate.h"
|
||||
#include "mac_startup.h"
|
||||
#include "mac_utilities.h"
|
||||
#include "macglobalshortcutbackend.h"
|
||||
#include "utilities.h"
|
||||
#include "core/logging.h"
|
||||
|
@ -343,4 +344,105 @@ bool MigrateLegacyConfigFiles() {
|
|||
return moved_dir;
|
||||
}
|
||||
|
||||
static int MapFunctionKey(int keycode) {
|
||||
switch (keycode) {
|
||||
// Function keys
|
||||
case NSInsertFunctionKey: return Qt::Key_Insert;
|
||||
case NSDeleteFunctionKey: return Qt::Key_Delete;
|
||||
case NSPauseFunctionKey: return Qt::Key_Pause;
|
||||
case NSPrintFunctionKey: return Qt::Key_Print;
|
||||
case NSSysReqFunctionKey: return Qt::Key_SysReq;
|
||||
case NSHomeFunctionKey: return Qt::Key_Home;
|
||||
case NSEndFunctionKey: return Qt::Key_End;
|
||||
case NSLeftArrowFunctionKey: return Qt::Key_Left;
|
||||
case NSUpArrowFunctionKey: return Qt::Key_Up;
|
||||
case NSRightArrowFunctionKey: return Qt::Key_Right;
|
||||
case NSDownArrowFunctionKey: return Qt::Key_Down;
|
||||
case NSPageUpFunctionKey: return Qt::Key_PageUp;
|
||||
case NSPageDownFunctionKey: return Qt::Key_PageDown;
|
||||
case NSScrollLockFunctionKey: return Qt::Key_ScrollLock;
|
||||
case NSF1FunctionKey: return Qt::Key_F1;
|
||||
case NSF2FunctionKey: return Qt::Key_F2;
|
||||
case NSF3FunctionKey: return Qt::Key_F3;
|
||||
case NSF4FunctionKey: return Qt::Key_F4;
|
||||
case NSF5FunctionKey: return Qt::Key_F5;
|
||||
case NSF6FunctionKey: return Qt::Key_F6;
|
||||
case NSF7FunctionKey: return Qt::Key_F7;
|
||||
case NSF8FunctionKey: return Qt::Key_F8;
|
||||
case NSF9FunctionKey: return Qt::Key_F9;
|
||||
case NSF10FunctionKey: return Qt::Key_F10;
|
||||
case NSF11FunctionKey: return Qt::Key_F11;
|
||||
case NSF12FunctionKey: return Qt::Key_F12;
|
||||
case NSF13FunctionKey: return Qt::Key_F13;
|
||||
case NSF14FunctionKey: return Qt::Key_F14;
|
||||
case NSF15FunctionKey: return Qt::Key_F15;
|
||||
case NSF16FunctionKey: return Qt::Key_F16;
|
||||
case NSF17FunctionKey: return Qt::Key_F17;
|
||||
case NSF18FunctionKey: return Qt::Key_F18;
|
||||
case NSF19FunctionKey: return Qt::Key_F19;
|
||||
case NSF20FunctionKey: return Qt::Key_F20;
|
||||
case NSF21FunctionKey: return Qt::Key_F21;
|
||||
case NSF22FunctionKey: return Qt::Key_F22;
|
||||
case NSF23FunctionKey: return Qt::Key_F23;
|
||||
case NSF24FunctionKey: return Qt::Key_F24;
|
||||
case NSF25FunctionKey: return Qt::Key_F25;
|
||||
case NSF26FunctionKey: return Qt::Key_F26;
|
||||
case NSF27FunctionKey: return Qt::Key_F27;
|
||||
case NSF28FunctionKey: return Qt::Key_F28;
|
||||
case NSF29FunctionKey: return Qt::Key_F29;
|
||||
case NSF30FunctionKey: return Qt::Key_F30;
|
||||
case NSF31FunctionKey: return Qt::Key_F31;
|
||||
case NSF32FunctionKey: return Qt::Key_F32;
|
||||
case NSF33FunctionKey: return Qt::Key_F33;
|
||||
case NSF34FunctionKey: return Qt::Key_F34;
|
||||
case NSF35FunctionKey: return Qt::Key_F35;
|
||||
case NSMenuFunctionKey: return Qt::Key_Menu;
|
||||
case NSHelpFunctionKey: return Qt::Key_Help;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QKeySequence KeySequenceFromNSEvent(NSEvent* event) {
|
||||
NSString* str = [event charactersIgnoringModifiers];
|
||||
NSString* upper = [str uppercaseString];
|
||||
const char* chars = [upper UTF8String];
|
||||
NSUInteger modifiers = [event modifierFlags];
|
||||
int key = 0;
|
||||
unsigned char c = chars[0];
|
||||
switch (c) {
|
||||
case 0x1b: key = Qt::Key_Escape; break;
|
||||
case 0x09: key = Qt::Key_Tab; break;
|
||||
case 0x0d: key = Qt::Key_Return; break;
|
||||
case 0x08: key = Qt::Key_Backspace; break;
|
||||
case 0x03: key = Qt::Key_Enter; break;
|
||||
}
|
||||
|
||||
if (key == 0) {
|
||||
if (c >= 0x20 && c <= 0x7e) { // ASCII from space to ~
|
||||
key = c;
|
||||
} else {
|
||||
key = MapFunctionKey([event keyCode]);
|
||||
if (key == 0) {
|
||||
return QKeySequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiers & NSShiftKeyMask) {
|
||||
key += Qt::SHIFT;
|
||||
}
|
||||
if (modifiers & NSControlKeyMask) {
|
||||
key += Qt::META;
|
||||
}
|
||||
if (modifiers & NSAlternateKeyMask) {
|
||||
key += Qt::ALT;
|
||||
}
|
||||
if (modifiers & NSCommandKeyMask) {
|
||||
key += Qt::CTRL;
|
||||
}
|
||||
|
||||
return QKeySequence(key);
|
||||
}
|
||||
|
||||
} // namespace mac
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Only include this from Objective-C++ files
|
||||
|
||||
#include <QKeySequence>
|
||||
|
||||
@class NSEvent;
|
||||
|
||||
namespace mac {
|
||||
|
||||
QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
#include "config.h"
|
||||
#include "globalshortcuts.h"
|
||||
#include "mac_startup.h"
|
||||
#import "mac_utilities.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
|
@ -67,111 +68,11 @@ class MacGlobalShortcutBackendPrivate : boost::noncopyable {
|
|||
}
|
||||
|
||||
private:
|
||||
static QKeySequence GetSequence(NSEvent* event) {
|
||||
NSString* str = [event charactersIgnoringModifiers];
|
||||
NSString* upper = [str uppercaseString];
|
||||
const char* chars = [upper UTF8String];
|
||||
NSUInteger modifiers = [event modifierFlags];
|
||||
int key = 0;
|
||||
unsigned char c = chars[0];
|
||||
switch (c) {
|
||||
case 0x1b: key = Qt::Key_Escape; break;
|
||||
case 0x09: key = Qt::Key_Tab; break;
|
||||
case 0x0d: key = Qt::Key_Return; break;
|
||||
case 0x08: key = Qt::Key_Backspace; break;
|
||||
case 0x03: key = Qt::Key_Enter; break;
|
||||
}
|
||||
|
||||
if (key == 0) {
|
||||
if (c >= 0x20 && c <= 0x7e) { // ASCII from space to ~
|
||||
key = c;
|
||||
} else {
|
||||
key = MapFunctionKey([event keyCode]);
|
||||
if (key == 0) {
|
||||
return QKeySequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiers & NSShiftKeyMask) {
|
||||
key += Qt::SHIFT;
|
||||
}
|
||||
if (modifiers & NSControlKeyMask) {
|
||||
key += Qt::META;
|
||||
}
|
||||
if (modifiers & NSAlternateKeyMask) {
|
||||
key += Qt::ALT;
|
||||
}
|
||||
if (modifiers & NSCommandKeyMask) {
|
||||
key += Qt::CTRL;
|
||||
}
|
||||
|
||||
return QKeySequence(key);
|
||||
}
|
||||
|
||||
bool HandleKeyEvent(NSEvent* event) {
|
||||
QKeySequence sequence = GetSequence(event);
|
||||
QKeySequence sequence = mac::KeySequenceFromNSEvent(event);
|
||||
return backend_->KeyPressed(sequence);
|
||||
}
|
||||
|
||||
static int MapFunctionKey(int keycode) {
|
||||
switch (keycode) {
|
||||
// Function keys
|
||||
case NSInsertFunctionKey: return Qt::Key_Insert;
|
||||
case NSDeleteFunctionKey: return Qt::Key_Delete;
|
||||
case NSPauseFunctionKey: return Qt::Key_Pause;
|
||||
case NSPrintFunctionKey: return Qt::Key_Print;
|
||||
case NSSysReqFunctionKey: return Qt::Key_SysReq;
|
||||
case NSHomeFunctionKey: return Qt::Key_Home;
|
||||
case NSEndFunctionKey: return Qt::Key_End;
|
||||
case NSLeftArrowFunctionKey: return Qt::Key_Left;
|
||||
case NSUpArrowFunctionKey: return Qt::Key_Up;
|
||||
case NSRightArrowFunctionKey: return Qt::Key_Right;
|
||||
case NSDownArrowFunctionKey: return Qt::Key_Down;
|
||||
case NSPageUpFunctionKey: return Qt::Key_PageUp;
|
||||
case NSPageDownFunctionKey: return Qt::Key_PageDown;
|
||||
case NSScrollLockFunctionKey: return Qt::Key_ScrollLock;
|
||||
case NSF1FunctionKey: return Qt::Key_F1;
|
||||
case NSF2FunctionKey: return Qt::Key_F2;
|
||||
case NSF3FunctionKey: return Qt::Key_F3;
|
||||
case NSF4FunctionKey: return Qt::Key_F4;
|
||||
case NSF5FunctionKey: return Qt::Key_F5;
|
||||
case NSF6FunctionKey: return Qt::Key_F6;
|
||||
case NSF7FunctionKey: return Qt::Key_F7;
|
||||
case NSF8FunctionKey: return Qt::Key_F8;
|
||||
case NSF9FunctionKey: return Qt::Key_F9;
|
||||
case NSF10FunctionKey: return Qt::Key_F10;
|
||||
case NSF11FunctionKey: return Qt::Key_F11;
|
||||
case NSF12FunctionKey: return Qt::Key_F12;
|
||||
case NSF13FunctionKey: return Qt::Key_F13;
|
||||
case NSF14FunctionKey: return Qt::Key_F14;
|
||||
case NSF15FunctionKey: return Qt::Key_F15;
|
||||
case NSF16FunctionKey: return Qt::Key_F16;
|
||||
case NSF17FunctionKey: return Qt::Key_F17;
|
||||
case NSF18FunctionKey: return Qt::Key_F18;
|
||||
case NSF19FunctionKey: return Qt::Key_F19;
|
||||
case NSF20FunctionKey: return Qt::Key_F20;
|
||||
case NSF21FunctionKey: return Qt::Key_F21;
|
||||
case NSF22FunctionKey: return Qt::Key_F22;
|
||||
case NSF23FunctionKey: return Qt::Key_F23;
|
||||
case NSF24FunctionKey: return Qt::Key_F24;
|
||||
case NSF25FunctionKey: return Qt::Key_F25;
|
||||
case NSF26FunctionKey: return Qt::Key_F26;
|
||||
case NSF27FunctionKey: return Qt::Key_F27;
|
||||
case NSF28FunctionKey: return Qt::Key_F28;
|
||||
case NSF29FunctionKey: return Qt::Key_F29;
|
||||
case NSF30FunctionKey: return Qt::Key_F30;
|
||||
case NSF31FunctionKey: return Qt::Key_F31;
|
||||
case NSF32FunctionKey: return Qt::Key_F32;
|
||||
case NSF33FunctionKey: return Qt::Key_F33;
|
||||
case NSF34FunctionKey: return Qt::Key_F34;
|
||||
case NSF35FunctionKey: return Qt::Key_F35;
|
||||
case NSMenuFunctionKey: return Qt::Key_Menu;
|
||||
case NSHelpFunctionKey: return Qt::Key_Help;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
id global_monitor_;
|
||||
id local_monitor_;
|
||||
|
|
|
@ -56,6 +56,20 @@ void GlobalShortcutGrabber::hideEvent(QHideEvent* e) {
|
|||
QDialog::hideEvent(e);
|
||||
}
|
||||
|
||||
void GlobalShortcutGrabber::grabKeyboard() {
|
||||
#ifdef Q_OS_DARWIN
|
||||
SetupMacEventHandler();
|
||||
#endif
|
||||
QDialog::grabKeyboard();
|
||||
}
|
||||
|
||||
void GlobalShortcutGrabber::releaseKeyboard() {
|
||||
#ifdef Q_OS_DARWIN
|
||||
TeardownMacEventHandler();
|
||||
#endif
|
||||
QDialog::releaseKeyboard();
|
||||
}
|
||||
|
||||
bool GlobalShortcutGrabber::event(QEvent* e) {
|
||||
if (e->type() == QEvent::ShortcutOverride) {
|
||||
QKeyEvent* ke = static_cast<QKeyEvent*>(e);
|
||||
|
@ -65,7 +79,7 @@ bool GlobalShortcutGrabber::event(QEvent* e) {
|
|||
else
|
||||
ret_ = QKeySequence(ke->modifiers() | ke->key());
|
||||
|
||||
ui_->combo->setText("<b>" + ret_.toString(QKeySequence::NativeText) + "</b>");
|
||||
UpdateText();
|
||||
|
||||
if (!modifier_keys_.contains(ke->key()))
|
||||
accept();
|
||||
|
@ -74,4 +88,8 @@ bool GlobalShortcutGrabber::event(QEvent* e) {
|
|||
return QDialog::event(e);
|
||||
}
|
||||
|
||||
void GlobalShortcutGrabber::UpdateText() {
|
||||
ui_->combo->setText("<b>" + ret_.toString(QKeySequence::NativeText) + "</b>");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <QDialog>
|
||||
|
||||
class MacMonitorWrapper;
|
||||
class NSEvent;
|
||||
class Ui_GlobalShortcutGrabber;
|
||||
|
||||
class GlobalShortcutGrabber : public QDialog {
|
||||
|
@ -35,12 +37,21 @@ class GlobalShortcutGrabber : public QDialog {
|
|||
bool event(QEvent *);
|
||||
void showEvent(QShowEvent *);
|
||||
void hideEvent(QHideEvent *);
|
||||
void grabKeyboard();
|
||||
void releaseKeyboard();
|
||||
|
||||
private:
|
||||
void UpdateText();
|
||||
void SetupMacEventHandler();
|
||||
void TeardownMacEventHandler();
|
||||
bool HandleMacEvent(NSEvent*);
|
||||
|
||||
Ui_GlobalShortcutGrabber* ui_;
|
||||
QKeySequence ret_;
|
||||
|
||||
QList<int> modifier_keys_;
|
||||
|
||||
MacMonitorWrapper* wrapper_;
|
||||
};
|
||||
|
||||
#endif // GLOBALSHORTCUTGRABBER_H
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#include "globalshortcutgrabber.h"
|
||||
|
||||
#import <AppKit/NSEvent.h>
|
||||
#import <AppKit/NSGraphics.h>
|
||||
#import <AppKit/NSViewController.h>
|
||||
#import <QuartzCore/CALayer.h>
|
||||
|
||||
#include <QKeySequence>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#import "core/mac_utilities.h"
|
||||
|
||||
class MacMonitorWrapper : boost::noncopyable {
|
||||
public:
|
||||
explicit MacMonitorWrapper(id monitor)
|
||||
: local_monitor_(monitor) {
|
||||
}
|
||||
|
||||
~MacMonitorWrapper() {
|
||||
[NSEvent removeMonitor: local_monitor_];
|
||||
}
|
||||
|
||||
private:
|
||||
id local_monitor_;
|
||||
};
|
||||
|
||||
bool GlobalShortcutGrabber::HandleMacEvent(NSEvent* event) {
|
||||
ret_ = mac::KeySequenceFromNSEvent(event);
|
||||
UpdateText();
|
||||
if ([[event charactersIgnoringModifiers] length] != 0) {
|
||||
accept();
|
||||
return true;
|
||||
}
|
||||
return ret_ == QKeySequence(Qt::Key_Escape);
|
||||
}
|
||||
|
||||
void GlobalShortcutGrabber::SetupMacEventHandler() {
|
||||
id monitor = [NSEvent addLocalMonitorForEventsMatchingMask: NSKeyDownMask
|
||||
handler:^(NSEvent* event) {
|
||||
return HandleMacEvent(event) ? event : nil;
|
||||
}];
|
||||
wrapper_ = new MacMonitorWrapper(monitor);
|
||||
}
|
||||
|
||||
void GlobalShortcutGrabber::TeardownMacEventHandler() {
|
||||
delete wrapper_;
|
||||
}
|
Loading…
Reference in New Issue