Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Carbon from Mac Auto-Type #3347

Merged
merged 4 commits into from
Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
605 changes: 307 additions & 298 deletions src/autotype/mac/AutoTypeMac.cpp

Large diffs are not rendered by default.

19 changes: 9 additions & 10 deletions src/autotype/mac/AutoTypeMac.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
#ifndef KEEPASSX_AUTOTYPEMAC_H
#define KEEPASSX_AUTOTYPEMAC_H

#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
#include <QtPlugin>
#include <memory>

#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h"
#include "autotype/AutoTypePlatformPlugin.h"

class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface
{
Expand All @@ -48,20 +48,19 @@ class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface
bool raiseOwnWindow() override;

void sendChar(const QChar& ch, bool isKeyDown);
void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers);
void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers = 0);

signals:
void globalShortcutTriggered();

private:
EventHotKeyRef m_hotkeyRef;
EventHotKeyID m_hotkeyId;

static uint16 qtToNativeKeyCode(Qt::Key key);
static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native);
static void hotkeyHandler(void* userData);
static CGKeyCode qtToNativeKeyCode(Qt::Key key);
static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers);
static int windowLayer(CFDictionaryRef window);
static QString windowTitle(CFDictionaryRef window);
static OSStatus hotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData);

void* m_globalMonitor;
};

class AutoTypeExecutorMac : public AutoTypeExecutor
Expand All @@ -77,4 +76,4 @@ class AutoTypeExecutorMac : public AutoTypeExecutor
AutoTypePlatformMac* const m_platform;
};

#endif // KEEPASSX_AUTOTYPEMAC_H
#endif // KEEPASSX_AUTOTYPEMAC_H
160 changes: 160 additions & 0 deletions src/autotype/mac/AutoTypeMacKeyCodes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
//
// Taken from HIToolbox/Events.h
//

/*
* Summary:
* Virtual keycodes
*
* Discussion:
* These constants are the virtual keycodes defined originally in
* Inside Mac Volume V, pg. V-191. They identify physical keys on a
* keyboard. Those constants with "ANSI" in the name are labeled
* according to the key position on an ANSI-standard US keyboard.
* For example, kVK_ANSI_A indicates the virtual keycode for the key
* with the letter 'A' in the US keyboard layout. Other keyboard
* layouts may have the 'A' key label on a different physical key;
* in this case, pressing 'A' will generate a different virtual
* keycode.
*/

#ifndef KEEPASSXC_AUTOTYPEMAC_KEYCODES_H
#define KEEPASSXC_AUTOTYPEMAC_KEYCODES_H

// clang-format off
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
kVK_ANSI_G = 0x05,
kVK_ANSI_Z = 0x06,
kVK_ANSI_X = 0x07,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_B = 0x0B,
kVK_ANSI_Q = 0x0C,
kVK_ANSI_W = 0x0D,
kVK_ANSI_E = 0x0E,
kVK_ANSI_R = 0x0F,
kVK_ANSI_Y = 0x10,
kVK_ANSI_T = 0x11,
kVK_ANSI_1 = 0x12,
kVK_ANSI_2 = 0x13,
kVK_ANSI_3 = 0x14,
kVK_ANSI_4 = 0x15,
kVK_ANSI_6 = 0x16,
kVK_ANSI_5 = 0x17,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_9 = 0x19,
kVK_ANSI_7 = 0x1A,
kVK_ANSI_Minus = 0x1B,
kVK_ANSI_8 = 0x1C,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_RightBracket = 0x1E,
kVK_ANSI_O = 0x1F,
kVK_ANSI_U = 0x20,
kVK_ANSI_LeftBracket = 0x21,
kVK_ANSI_I = 0x22,
kVK_ANSI_P = 0x23,
kVK_ANSI_L = 0x25,
kVK_ANSI_J = 0x26,
kVK_ANSI_Quote = 0x27,
kVK_ANSI_K = 0x28,
kVK_ANSI_Semicolon = 0x29,
kVK_ANSI_Backslash = 0x2A,
kVK_ANSI_Comma = 0x2B,
kVK_ANSI_Slash = 0x2C,
kVK_ANSI_N = 0x2D,
kVK_ANSI_M = 0x2E,
kVK_ANSI_Period = 0x2F,
kVK_ANSI_Grave = 0x32,
kVK_ANSI_KeypadDecimal = 0x41,
kVK_ANSI_KeypadMultiply = 0x43,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadClear = 0x47,
kVK_ANSI_KeypadDivide = 0x4B,
kVK_ANSI_KeypadEnter = 0x4C,
kVK_ANSI_KeypadMinus = 0x4E,
kVK_ANSI_KeypadEquals = 0x51,
kVK_ANSI_Keypad0 = 0x52,
kVK_ANSI_Keypad1 = 0x53,
kVK_ANSI_Keypad2 = 0x54,
kVK_ANSI_Keypad3 = 0x55,
kVK_ANSI_Keypad4 = 0x56,
kVK_ANSI_Keypad5 = 0x57,
kVK_ANSI_Keypad6 = 0x58,
kVK_ANSI_Keypad7 = 0x59,
kVK_ANSI_Keypad8 = 0x5B,
kVK_ANSI_Keypad9 = 0x5C
};

/* keycodes for keys that are independent of keyboard layout*/
enum {
kVK_Return = 0x24,
kVK_Tab = 0x30,
kVK_Space = 0x31,
kVK_Delete = 0x33,
kVK_Escape = 0x35,
kVK_Command = 0x37,
kVK_Shift = 0x38,
kVK_CapsLock = 0x39,
kVK_Option = 0x3A,
kVK_Control = 0x3B,
kVK_RightCommand = 0x36,
kVK_RightShift = 0x3C,
kVK_RightOption = 0x3D,
kVK_RightControl = 0x3E,
kVK_Function = 0x3F,
kVK_F17 = 0x40,
kVK_VolumeUp = 0x48,
kVK_VolumeDown = 0x49,
kVK_Mute = 0x4A,
kVK_F18 = 0x4F,
kVK_F19 = 0x50,
kVK_F20 = 0x5A,
kVK_F5 = 0x60,
kVK_F6 = 0x61,
kVK_F7 = 0x62,
kVK_F3 = 0x63,
kVK_F8 = 0x64,
kVK_F9 = 0x65,
kVK_F11 = 0x67,
kVK_F13 = 0x69,
kVK_F16 = 0x6A,
kVK_F14 = 0x6B,
kVK_F10 = 0x6D,
kVK_F12 = 0x6F,
kVK_F15 = 0x71,
kVK_Help = 0x72,
kVK_Home = 0x73,
kVK_PageUp = 0x74,
kVK_ForwardDelete = 0x75,
kVK_F4 = 0x76,
kVK_End = 0x77,
kVK_F2 = 0x78,
kVK_PageDown = 0x79,
kVK_F1 = 0x7A,
kVK_LeftArrow = 0x7B,
kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D,
kVK_UpArrow = 0x7E
};

/* ISO keyboards only*/
enum {
kVK_ISO_Section = 0x0A
};

/* JIS keyboards only*/
enum {
kVK_JIS_Yen = 0x5D,
kVK_JIS_Underscore = 0x5E,
kVK_JIS_KeypadComma = 0x5F,
kVK_JIS_Eisu = 0x66,
kVK_JIS_Kana = 0x68
};
// clang-format on

#endif
2 changes: 1 addition & 1 deletion src/autotype/mac/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set(autotype_mac_SOURCES AutoTypeMac.cpp)

add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES})
set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon")
set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit")
target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets)

if(WITH_APP_BUNDLE)
Expand Down
7 changes: 5 additions & 2 deletions src/gui/macutils/AppKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#define KEEPASSX_APPKIT_H

#include <QObject>
#include <unistd.h>
#include <CoreGraphics/CGEvent.h>

class AppKit : public QObject
{
Expand All @@ -37,12 +37,15 @@ class AppKit : public QObject
bool hideProcess(pid_t pid);
bool isHidden(pid_t pid);
bool isDarkMode();
void* addGlobalMonitor(CGKeyCode keycode, CGEventFlags modifier, void* userData, void (*handler)(void*));
void removeGlobalMonitor(void* monitor);
bool enableAccessibility();

signals:
void lockDatabases();

private:
void *self;
void* self;
};

#endif // KEEPASSX_APPKIT_H
8 changes: 6 additions & 2 deletions src/gui/macutils/AppKitImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
#import "AppKit.h"

#import <Foundation/Foundation.h>
#import <AppKit/NSEvent.h>
#import <AppKit/NSRunningApplication.h>

@interface AppKitImpl : NSObject
{
AppKit *m_appkit;
AppKit* m_appkit;
}
- (id) initWithObject:(AppKit *)appkit;
- (id) initWithObject:(AppKit*)appkit;

@property (strong) NSRunningApplication *lastActiveApplication;

Expand All @@ -36,5 +37,8 @@
- (bool) isHidden:(pid_t) pid;
- (bool) isDarkMode;
- (void) userSwitchHandler:(NSNotification*) notification;
- (id) addGlobalMonitor:(NSEventMask) mask handler:(void (^)(NSEvent*)) handler;
- (void) removeGlobalMonitor:(id) monitor;
- (bool) enableAccessibility;

@end
60 changes: 52 additions & 8 deletions src/gui/macutils/AppKitImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

@implementation AppKitImpl

- (id) initWithObject:(AppKit *)appkit
- (id) initWithObject:(AppKit*)appkit
{
self = [super init];
if (self) {
Expand All @@ -43,10 +43,10 @@ - (id) initWithObject:(AppKit *)appkit
//
// Update last active application property
//
- (void) didDeactivateApplicationObserver:(NSNotification *) notification
- (void) didDeactivateApplicationObserver:(NSNotification*) notification
{
NSDictionary *userInfo = notification.userInfo;
NSRunningApplication *app = userInfo[NSWorkspaceApplicationKey];
NSDictionary* userInfo = notification.userInfo;
NSRunningApplication* app = userInfo[NSWorkspaceApplicationKey];

if (app.processIdentifier != [self ownProcessId]) {
self.lastActiveApplication = app;
Expand Down Expand Up @@ -74,7 +74,7 @@ - (pid_t) ownProcessId
//
- (bool) activateProcess:(pid_t) pid
{
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
return [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
}

Expand All @@ -83,7 +83,7 @@ - (bool) activateProcess:(pid_t) pid
//
- (bool) hideProcess:(pid_t) pid
{
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
return [app hide];
}

Expand All @@ -92,7 +92,7 @@ - (bool) hideProcess:(pid_t) pid
//
- (bool) isHidden:(pid_t) pid
{
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
return [app isHidden];
}

Expand All @@ -101,7 +101,7 @@ - (bool) isHidden:(pid_t) pid
//
- (bool) isDarkMode
{
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
NSDictionary* dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
id style = [dict objectForKey:@"AppleInterfaceStyle"];
return ( style && [style isKindOfClass:[NSString class]]
&& NSOrderedSame == [style caseInsensitiveCompare:@"dark"] );
Expand All @@ -118,6 +118,31 @@ - (void) userSwitchHandler:(NSNotification*) notification
}
}

//
// Add global event monitor
//
- (id) addGlobalMonitor:(NSEventMask) mask handler:(void (^)(NSEvent*)) handler
{
return [NSEvent addGlobalMonitorForEventsMatchingMask:mask handler:handler];
}

//
// Remove global event monitor
//
- (void) removeGlobalMonitor:(id) monitor
{
[NSEvent removeMonitor:monitor];
}

//
// Check if accessibility is enabled, may show an popup asking for permissions
//
- (bool) enableAccessibility
{
NSDictionary* opts = @{static_cast<id>(kAXTrustedCheckOptionPrompt): @YES};
return AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef>(opts));
}

@end

//
Expand Down Expand Up @@ -169,3 +194,22 @@ - (void) userSwitchHandler:(NSNotification*) notification
{
return [static_cast<id>(self) isDarkMode];
}

void* AppKit::addGlobalMonitor(CGKeyCode keycode, CGEventFlags modifier, void* userData, void (*handler)(void*))
{
return [static_cast<id>(self) addGlobalMonitor:NSEventMaskKeyDown handler:^(NSEvent* event) {
if (event.keyCode == keycode && (event.modifierFlags & modifier) == modifier) {
handler(userData);
}
}];
}

void AppKit::removeGlobalMonitor(void* monitor)
{
[static_cast<id>(self) removeGlobalMonitor:static_cast<id>(monitor)];
}

bool AppKit::enableAccessibility()
{
return [static_cast<id>(self) enableAccessibility];
}
Loading