#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 <Carbon/Carbon.h>
|
||||
#include <IOKit/hidsystem/IOHIDLib.h>
|
||||
|
||||
// Note that some virtual keys codes appear more than once. The
|
||||
// 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
|
||||
OSXKeyState::fakeKey(const Keystroke& keystroke)
|
||||
{
|
||||
|
@ -477,76 +577,14 @@ OSXKeyState::fakeKey(const Keystroke& keystroke)
|
|||
|
||||
KeyButton button = keystroke.m_data.m_button.m_button;
|
||||
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);
|
||||
|
||||
LOG((CLOG_DEBUG1
|
||||
" button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x",
|
||||
button, virtualKey, keyDown ? "down" : "up", client));
|
||||
" button=0x%04x virtualKey=0x%04x keyDown=%s",
|
||||
button, virtualKey, keyDown ? "down" : "up"));
|
||||
|
||||
CGEventRef ref = CGEventCreateKeyboardEvent(
|
||||
source, virtualKey, keyDown);
|
||||
postHIDVirtualKey(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,6 +150,12 @@ private:
|
|||
|
||||
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:
|
||||
// OS X uses a physical key if 0 for the 'A' key. synergy reserves
|
||||
// KeyButton 0 so we offset all OS X physical key ids by this much
|
||||
|
|
Loading…
Reference in New Issue