Kennwortmanager KeePassX Weiterentwicklung der Version 1
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
keepassx1/src/lib/HelperMacX.cpp

238 lines
9.3 KiB

/***************************************************************************
* Copyright (C) 2009 by Jeff Gibbons *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "lib/HelperMacX.h"
#include <map>
static pid_t keepassxPID;
#ifdef GLOBAL_AUTOTYPE
#include "lib/AutoTypeGlobalMacX.h"
uint HelperMacX::getShortcutModifierMask(const Shortcut& s){
AutoTypeGlobalMacX* autoTypeGlobal = static_cast<AutoTypeGlobalMacX*>(autoType);
uint mod = 0;
if (s.ctrl) mod |= autoTypeGlobal->maskCtrl();
if (s.shift) mod |= autoTypeGlobal->maskShift();
if (s.alt) mod |= autoTypeGlobal->maskAlt();
if (s.altgr) mod |= autoTypeGlobal->maskAltGr();
if (s.win) mod |= autoTypeGlobal->maskMeta();
return mod;
}
Boolean HelperMacX::isFrontProcess(pid_t pid){
Boolean result;
ProcessSerialNumber pidPSN;
ProcessSerialNumber frontPSN;
OSStatus status = GetProcessForPID(pid, &pidPSN);
if (noErr != status) {
qWarning("HelperMacX::isFrontProcess: GetProcessForPID error for pid %d: %d", pid, (int)status);
return false;
}
GetFrontProcess(&frontPSN);
SameProcess(&pidPSN, &frontPSN, &result);
return result;
}
#endif
pid_t HelperMacX::getKeepassxPID(){
if (0 == keepassxPID) {
ProcessSerialNumber processSerialNumber;
GetCurrentProcess(&processSerialNumber);
GetProcessPID(&processSerialNumber, &keepassxPID);
}
return keepassxPID;
}
Boolean HelperMacX::getTargetWindowInfo(pid_t *pidPtr, int *windowNumberPtr,
char* windowName, int maxWindowNameSize){
char windowNameBuffer[256];
if (NULL == windowName) {
windowName = windowNameBuffer;
maxWindowNameSize = sizeof(windowNameBuffer);
}
// get info for on screen windows (excluding desktop elements) in top to bottom order
CFArrayRef windowInfo = CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
CFIndex windowCount = CFArrayGetCount(windowInfo);
for (CFIndex i = 0; i < windowCount; i++){
CFDictionaryRef window = (CFDictionaryRef)CFArrayGetValueAtIndex(windowInfo, i);
// only want windows in layer 0
CFNumberRef windowLayerRef = (CFNumberRef)CFDictionaryGetValue(window, kCGWindowLayer);
int windowLayer = -1;
CFNumberGetValue(windowLayerRef, kCFNumberIntType, &windowLayer);
if (0 != windowLayer) continue;
// get the pid owning this window
CFNumberRef pidRef = (CFNumberRef)CFDictionaryGetValue(window, kCGWindowOwnerPID);
pid_t pid = -1;
CFNumberGetValue(pidRef, kCFNumberIntType, &pid);
// skip KeePassX windows
if (getKeepassxPID() == pid) continue;
// get window name; continue if no name
CFStringRef windowNameRef = (CFStringRef)CFDictionaryGetValue(window, kCGWindowName);
if (!windowNameRef) continue;
windowName[0] = 0;
if (!CFStringGetCString(windowNameRef, windowName, maxWindowNameSize, kCFStringEncodingUTF8) ||
(0 == windowName[0]))
continue;
if (NULL != pidPtr) *pidPtr = pid;
if (NULL != windowNumberPtr) {
CFNumberRef windowNumberRef = (CFNumberRef)CFDictionaryGetValue(window, kCGWindowNumber);
CFNumberGetValue(windowNumberRef, kCGWindowIDCFNumberType, windowNumberPtr);
}
CFRelease(windowInfo);
return true;
}
CFRelease(windowInfo);
return false;
}
OSType HelperMacX::getProcessSignature(pid_t pid){
OSErr err;
ProcessSerialNumber processSerialNumber;
ProcessInfoRec processInfoRec;
memset(&processInfoRec, 0, sizeof(processInfoRec));
processInfoRec.processInfoLength = sizeof(processInfoRec);
err = GetProcessForPID(pid, &processSerialNumber);
if (noErr != err) {
qWarning("HelperMacX::getProcessSignature: GetProcessForPID error for pid %d: %d", pid, err);
return 0;
}
err = GetProcessInformation(&processSerialNumber, &processInfoRec);
if (noErr != err) {
qWarning("HelperMacX::getProcessSignature: GetProcessInformation error for pid %d: %d\n", pid, err);
return 0;
}
return processInfoRec.processSignature;
}
static uint orderedModifiers[] = {
0,
( shiftKey ) >> 8,
(controlKey ) >> 8,
( optionKey ) >> 8,
( cmdKey ) >> 8,
( shiftKey | controlKey ) >> 8,
( shiftKey | optionKey ) >> 8,
( shiftKey | cmdKey ) >> 8,
(controlKey | optionKey ) >> 8,
(controlKey | cmdKey ) >> 8,
( optionKey | cmdKey ) >> 8,
( shiftKey | controlKey | optionKey ) >> 8,
( shiftKey | controlKey | cmdKey ) >> 8,
( shiftKey | optionKey | cmdKey ) >> 8,
(controlKey | optionKey | cmdKey ) >> 8,
( shiftKey | controlKey | optionKey | cmdKey ) >> 8
};
static std::map<uint,KeycodeWithMods> unicodeToKeycodeWithModsMap;
void HelperMacX::initUnicodeToKeycodeWithModsMap(){
unicodeToKeycodeWithModsMap.clear();
TISInputSourceRef inputSourceRef = TISCopyCurrentKeyboardInputSource();
if (NULL == inputSourceRef) {
qWarning("HelperMacX::initUnicodeToKeycodeWithModsMap: inputSourceRef is NULL");
return;
}
CFDataRef unicodeKeyLayoutDataRef = (CFDataRef)TISGetInputSourceProperty(inputSourceRef,
kTISPropertyUnicodeKeyLayoutData);
if (NULL == unicodeKeyLayoutDataRef) {
qWarning("HelperMacX::initUnicodeToKeycodeWithModsMap: unicodeKeyLayoutDataRef is NULL");
return;
}
UCKeyboardLayout *unicodeKeyLayoutDataPtr = (UCKeyboardLayout*)CFDataGetBytePtr(unicodeKeyLayoutDataRef);
UInt32 deadKeyState;
UniChar unicodeString[8];
UniCharCount len;
for (int m = 0; m < 16; m++) {
uint mods = orderedModifiers[m];
for (uint keycode = 0; keycode < 0x80; keycode++) {
deadKeyState = 0;
len = 0;
OSStatus status = UCKeyTranslate(unicodeKeyLayoutDataPtr, keycode, kUCKeyActionDown,
mods, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask,
&deadKeyState, sizeof(unicodeString), &len, unicodeString);
if (noErr != status) {
qWarning("HelperMacX::initUnicodeToKeycodeWithModsMap: UCKeyTranslate error: %d keycode 0x%02X modifiers 0x%02X",
(int)status, keycode, mods);
continue;
}
// store if only one char and not already in store
if ((1 != len) || (0 < unicodeToKeycodeWithModsMap.count(unicodeString[0]))) continue;
unicodeToKeycodeWithModsMap[unicodeString[0]] = (KeycodeWithMods){ keycode, mods };
}
}
}
KeySym HelperMacX::keycodeToKeysym(uint keycode){
TISInputSourceRef inputSourceRef = TISCopyCurrentKeyboardInputSource();
if (NULL == inputSourceRef) {
qWarning("HelperMacX::keycodeToKeysym: inputSourceRef is NULL");
return NoSymbol;
}
CFDataRef unicodeKeyLayoutDataRef = (CFDataRef)TISGetInputSourceProperty(inputSourceRef,
kTISPropertyUnicodeKeyLayoutData);
if (NULL == unicodeKeyLayoutDataRef) {
CFRelease(inputSourceRef);
qWarning("HelperMacX::keycodeToKeysym: unicodeKeyLayoutDataRef is NULL");
return NoSymbol;
}
UCKeyboardLayout *unicodeKeyLayoutDataPtr = (UCKeyboardLayout*)CFDataGetBytePtr(unicodeKeyLayoutDataRef);
UInt32 deadKeyState = 0;
UniChar unicodeString[8];
UniCharCount len = 0;
OSStatus status = UCKeyTranslate(unicodeKeyLayoutDataPtr, keycode, kUCKeyActionDown,
0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask,
&deadKeyState, sizeof(unicodeString), &len, unicodeString);
CFRelease(inputSourceRef);
if (noErr != status) {
qWarning("HelperMacX::keycodeToKeysym: UCKeyTranslate error: %d", (int)status);
return NoSymbol;
}
return 1 != len ? NoSymbol : unicodeString[0];
}
uint HelperMacX::keysymToKeycode(KeySym keysym){
return keysymToKeycodeWithMods(keysym).keycode;
}
static const KeycodeWithMods NoKeycodeWithMods = (KeycodeWithMods){ NoKeycode, 0 };
KeycodeWithMods HelperMacX::keysymToKeycodeWithMods(KeySym keysym){
return 0 == unicodeToKeycodeWithModsMap.count(keysym)
? NoKeycodeWithMods : unicodeToKeycodeWithModsMap[keysym];
}
void HelperMacX::processToFront(pid_t pid){
OSStatus status;
ProcessSerialNumber processSerialNumber;
status = GetProcessForPID(pid, &processSerialNumber);
if (noErr != status) {
qWarning("HelperMacX::processToFront: GetProcessForPID error for pid %d: %d", pid, (int)status);
return;
}
status = SetFrontProcessWithOptions(&processSerialNumber, kSetFrontProcessFrontWindowOnly);
if (noErr != status) {
qWarning("HelperMacX::processToFront: SetFrontProcessWithOptions for pid %d: %d", pid, (int)status);
return;
}
}