#5592 Post keyboard events to lower level HID client
This commit is contained in:
parent
7c12608f20
commit
e8145aa779
|
@ -23,6 +23,7 @@
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
|
|
||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
|
#include <IOKit/hidsystem/IOHIDLib.h>
|
||||||
|
|
||||||
// Note that some virtual keys codes appear more than once. The
|
// Note that some virtual keys codes appear more than once. The
|
||||||
// first instance of a virtual key code maps to the KeyID that we
|
// first instance of a virtual key code maps to the KeyID that we
|
||||||
|
@ -469,6 +470,105 @@ OSXKeyState::getKeyMap(synergy::KeyMap& keyMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static io_connect_t getEventDriver(void)
|
||||||
|
{
|
||||||
|
static mach_port_t sEventDrvrRef = 0;
|
||||||
|
mach_port_t masterPort, service, iter;
|
||||||
|
kern_return_t kr;
|
||||||
|
|
||||||
|
if (!sEventDrvrRef) {
|
||||||
|
// Get master device port
|
||||||
|
kr = IOMasterPort(bootstrap_port, &masterPort);
|
||||||
|
assert(KERN_SUCCESS == kr);
|
||||||
|
|
||||||
|
kr = IOServiceGetMatchingServices(masterPort,
|
||||||
|
IOServiceMatching(kIOHIDSystemClass), &iter);
|
||||||
|
assert(KERN_SUCCESS == kr);
|
||||||
|
|
||||||
|
service = IOIteratorNext(iter);
|
||||||
|
assert(service);
|
||||||
|
|
||||||
|
kr = IOServiceOpen(service, mach_task_self(),
|
||||||
|
kIOHIDParamConnectType, &sEventDrvrRef);
|
||||||
|
assert(KERN_SUCCESS == kr);
|
||||||
|
|
||||||
|
IOObjectRelease(service);
|
||||||
|
IOObjectRelease(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sEventDrvrRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OSXKeyState::postHIDVirtualKey(const UInt8 virtualKeyCode,
|
||||||
|
const bool postDown)
|
||||||
|
{
|
||||||
|
static UInt32 modifiers = 0;
|
||||||
|
|
||||||
|
NXEventData event;
|
||||||
|
IOGPoint loc = { 0, 0 };
|
||||||
|
UInt32 modifiersDelta = 0;
|
||||||
|
|
||||||
|
bzero(&event, sizeof(NXEventData));
|
||||||
|
|
||||||
|
switch (virtualKeyCode)
|
||||||
|
{
|
||||||
|
case s_shiftVK:
|
||||||
|
case s_superVK:
|
||||||
|
case s_altVK:
|
||||||
|
case s_controlVK:
|
||||||
|
case s_capsLockVK:
|
||||||
|
switch (virtualKeyCode)
|
||||||
|
{
|
||||||
|
case s_shiftVK:
|
||||||
|
modifiersDelta = NX_SHIFTMASK;
|
||||||
|
m_shiftPressed = postDown;
|
||||||
|
break;
|
||||||
|
case s_superVK:
|
||||||
|
modifiersDelta = NX_COMMANDMASK;
|
||||||
|
m_superPressed = postDown;
|
||||||
|
break;
|
||||||
|
case s_altVK:
|
||||||
|
modifiersDelta = NX_ALTERNATEMASK;
|
||||||
|
m_altPressed = postDown;
|
||||||
|
break;
|
||||||
|
case s_controlVK:
|
||||||
|
modifiersDelta = NX_CONTROLMASK;
|
||||||
|
m_controlPressed = postDown;
|
||||||
|
break;
|
||||||
|
case s_capsLockVK:
|
||||||
|
modifiersDelta = NX_ALPHASHIFTMASK;
|
||||||
|
m_capsPressed = postDown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the modifier bit
|
||||||
|
if (postDown) {
|
||||||
|
modifiers |= modifiersDelta;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modifiers &= ~modifiersDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_return_t kr;
|
||||||
|
kr = IOHIDPostEvent(getEventDriver(), NX_FLAGSCHANGED, loc,
|
||||||
|
&event, kNXEventDataVersion, modifiers, true);
|
||||||
|
assert(KERN_SUCCESS == kr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
event.key.repeat = false;
|
||||||
|
event.key.keyCode = virtualKeyCode;
|
||||||
|
event.key.origCharSet = event.key.charSet = NX_ASCIISET;
|
||||||
|
event.key.origCharCode = event.key.charCode = 0;
|
||||||
|
kr = IOHIDPostEvent(getEventDriver(),
|
||||||
|
postDown ? NX_KEYDOWN : NX_KEYUP,
|
||||||
|
loc, &event, kNXEventDataVersion, 0, false);
|
||||||
|
assert(KERN_SUCCESS == kr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OSXKeyState::fakeKey(const Keystroke& keystroke)
|
OSXKeyState::fakeKey(const Keystroke& keystroke)
|
||||||
{
|
{
|
||||||
|
@ -477,76 +577,14 @@ OSXKeyState::fakeKey(const Keystroke& keystroke)
|
||||||
|
|
||||||
KeyButton button = keystroke.m_data.m_button.m_button;
|
KeyButton button = keystroke.m_data.m_button.m_button;
|
||||||
bool keyDown = keystroke.m_data.m_button.m_press;
|
bool keyDown = keystroke.m_data.m_button.m_press;
|
||||||
UInt32 client = keystroke.m_data.m_button.m_client;
|
|
||||||
CGEventSourceRef source = 0;
|
|
||||||
CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button);
|
CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1
|
LOG((CLOG_DEBUG1
|
||||||
" button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x",
|
" button=0x%04x virtualKey=0x%04x keyDown=%s",
|
||||||
button, virtualKey, keyDown ? "down" : "up", client));
|
button, virtualKey, keyDown ? "down" : "up"));
|
||||||
|
|
||||||
CGEventRef ref = CGEventCreateKeyboardEvent(
|
postHIDVirtualKey(virtualKey, keyDown);
|
||||||
source, virtualKey, keyDown);
|
|
||||||
|
|
||||||
if (ref == NULL) {
|
|
||||||
LOG((CLOG_CRIT "unable to create keyboard event for keystroke"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// persist modifier state.
|
|
||||||
if (virtualKey == s_shiftVK) {
|
|
||||||
m_shiftPressed = keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virtualKey == s_controlVK) {
|
|
||||||
m_controlPressed = keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virtualKey == s_altVK) {
|
|
||||||
m_altPressed = keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virtualKey == s_superVK) {
|
|
||||||
m_superPressed = keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virtualKey == s_capsLockVK) {
|
|
||||||
m_capsPressed = keyDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the event flags for special keys
|
|
||||||
// http://tinyurl.com/pxl742y
|
|
||||||
CGEventFlags modifiers = 0;
|
|
||||||
|
|
||||||
if (m_shiftPressed) {
|
|
||||||
modifiers |= kCGEventFlagMaskShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_controlPressed) {
|
|
||||||
modifiers |= kCGEventFlagMaskControl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_altPressed) {
|
|
||||||
modifiers |= kCGEventFlagMaskAlternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_superPressed) {
|
|
||||||
modifiers |= kCGEventFlagMaskCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_capsPressed) {
|
|
||||||
modifiers |= kCGEventFlagMaskAlphaShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGEventSetFlags(ref, modifiers);
|
|
||||||
CGEventPost(kCGHIDEventTap, ref);
|
|
||||||
CFRelease(ref);
|
|
||||||
|
|
||||||
// add a delay if client data isn't zero
|
|
||||||
// FIXME -- why?
|
|
||||||
if (client != 0) {
|
|
||||||
ARCH->sleep(0.01);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,12 @@ private:
|
||||||
static UInt32 mapKeyButtonToVirtualKey(KeyButton keyButton);
|
static UInt32 mapKeyButtonToVirtualKey(KeyButton keyButton);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
// Post a key event to HID manager. It posts an event to HID client, a
|
||||||
|
// much lower level than window manager which's the target from carbon
|
||||||
|
// CGEventPost
|
||||||
|
void postHIDVirtualKey(const UInt8 virtualKeyCode,
|
||||||
|
const bool postDown);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// OS X uses a physical key if 0 for the 'A' key. synergy reserves
|
// OS X uses a physical key if 0 for the 'A' key. synergy reserves
|
||||||
|
|
Loading…
Reference in New Issue