SYNERGY-1013 Ability to run synergy as a pre-login agent
This commit is contained in:
parent
f9d0dd4879
commit
cf96023aca
3 changed files with 104 additions and 124 deletions
|
|
@ -23,7 +23,6 @@
|
||||||
#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
|
||||||
|
|
@ -476,102 +475,72 @@ OSXKeyState::getKeyMap(synergy::KeyMap& keyMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static io_connect_t getEventDriver(void)
|
CGEventFlags
|
||||||
|
OSXKeyState::getKeyboardEventFlags()
|
||||||
{
|
{
|
||||||
static mach_port_t sEventDrvrRef = 0;
|
// set the event flags for special keys
|
||||||
mach_port_t masterPort, service, iter;
|
// http://tinyurl.com/pxl742y
|
||||||
kern_return_t kr;
|
CGEventFlags modifiers = 0;
|
||||||
|
|
||||||
if (!sEventDrvrRef) {
|
if (m_shiftPressed) {
|
||||||
// Get master device port
|
modifiers |= kCGEventFlagMaskShift;
|
||||||
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;
|
if (m_controlPressed) {
|
||||||
|
modifiers |= kCGEventFlagMaskControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_altPressed) {
|
||||||
|
modifiers |= kCGEventFlagMaskAlternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_superPressed) {
|
||||||
|
modifiers |= kCGEventFlagMaskCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_capsPressed) {
|
||||||
|
modifiers |= kCGEventFlagMaskAlphaShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OSXKeyState::postHIDVirtualKey(const UInt8 virtualKeyCode,
|
OSXKeyState::setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown)
|
||||||
const bool postDown)
|
|
||||||
{
|
{
|
||||||
static UInt32 modifiers = 0;
|
switch(virtualKey) {
|
||||||
|
|
||||||
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:
|
case s_shiftVK:
|
||||||
modifiersDelta = NX_SHIFTMASK;
|
m_shiftPressed = keyDown;
|
||||||
m_shiftPressed = postDown;
|
break;
|
||||||
break;
|
|
||||||
case s_superVK:
|
|
||||||
modifiersDelta = NX_COMMANDMASK;
|
|
||||||
m_superPressed = postDown;
|
|
||||||
break;
|
|
||||||
case s_altVK:
|
|
||||||
modifiersDelta = NX_ALTERNATEMASK;
|
|
||||||
m_altPressed = postDown;
|
|
||||||
break;
|
|
||||||
case s_controlVK:
|
case s_controlVK:
|
||||||
modifiersDelta = NX_CONTROLMASK;
|
m_controlPressed = keyDown;
|
||||||
m_controlPressed = postDown;
|
break;
|
||||||
break;
|
case s_altVK:
|
||||||
|
m_altPressed = keyDown;
|
||||||
|
break;
|
||||||
|
case s_superVK:
|
||||||
|
m_superPressed = keyDown;
|
||||||
|
break;
|
||||||
case s_capsLockVK:
|
case s_capsLockVK:
|
||||||
modifiersDelta = NX_ALPHASHIFTMASK;
|
m_capsPressed = keyDown;
|
||||||
m_capsPressed = postDown;
|
break;
|
||||||
break;
|
default:
|
||||||
}
|
LOG((CLOG_DEBUG1 "The key is not a modifier"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// update the modifier bit
|
void
|
||||||
if (postDown) {
|
OSXKeyState::postKeyboardKey(CGKeyCode virtualKey, bool keyDown)
|
||||||
modifiers |= modifiersDelta;
|
{
|
||||||
}
|
CGEventRef event = CGEventCreateKeyboardEvent(nullptr, virtualKey, keyDown);
|
||||||
else {
|
if (event) {
|
||||||
modifiers &= ~modifiersDelta;
|
CGEventSetFlags(event, getKeyboardEventFlags());
|
||||||
}
|
CGEventPost(kCGHIDEventTap, event);
|
||||||
|
CFRelease(event);
|
||||||
kern_return_t kr;
|
}
|
||||||
kr = IOHIDPostEvent(getEventDriver(), NX_FLAGSCHANGED, loc,
|
else {
|
||||||
&event, kNXEventDataVersion, modifiers, true);
|
LOG((CLOG_CRIT "unable to create keyboard event for keystroke"));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -579,33 +548,33 @@ void
|
||||||
OSXKeyState::fakeKey(const Keystroke& keystroke)
|
OSXKeyState::fakeKey(const Keystroke& keystroke)
|
||||||
{
|
{
|
||||||
switch (keystroke.m_type) {
|
switch (keystroke.m_type) {
|
||||||
case Keystroke::kButton: {
|
case Keystroke::kButton: {
|
||||||
|
bool keyDown = keystroke.m_data.m_button.m_press;
|
||||||
|
UInt32 client = keystroke.m_data.m_button.m_client;
|
||||||
|
KeyButton button = keystroke.m_data.m_button.m_button;
|
||||||
|
CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button);
|
||||||
|
|
||||||
KeyButton button = keystroke.m_data.m_button.m_button;
|
LOG((CLOG_DEBUG1
|
||||||
bool keyDown = keystroke.m_data.m_button.m_press;
|
" button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x",
|
||||||
CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button);
|
button, virtualKey, keyDown ? "down" : "up", client));
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1
|
setKeyboardModifiers(virtualKey, keyDown);
|
||||||
" button=0x%04x virtualKey=0x%04x keyDown=%s",
|
postKeyboardKey(virtualKey, keyDown);
|
||||||
button, virtualKey, keyDown ? "down" : "up"));
|
break;
|
||||||
|
|
||||||
postHIDVirtualKey(virtualKey, keyDown);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Keystroke::kGroup: {
|
|
||||||
SInt32 group = keystroke.m_data.m_group.m_group;
|
|
||||||
if (keystroke.m_data.m_group.m_absolute) {
|
|
||||||
LOG((CLOG_DEBUG1 " group %d", group));
|
|
||||||
setGroup(group);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
LOG((CLOG_DEBUG1 " group %+d", group));
|
case Keystroke::kGroup: {
|
||||||
setGroup(getEffectiveGroup(pollActiveGroup(), group));
|
SInt32 group = keystroke.m_data.m_group.m_group;
|
||||||
|
if (keystroke.m_data.m_group.m_absolute) {
|
||||||
|
LOG((CLOG_DEBUG1 " group %d", group));
|
||||||
|
setGroup(group);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_DEBUG1 " group %+d", group));
|
||||||
|
setGroup(getEffectiveGroup(pollActiveGroup(), group));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,11 +150,12 @@ private:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
// Post a key event to HID manager. It posts an event to HID client, a
|
// Get keyboard event flags accorfing to keyboard modifiers
|
||||||
// much lower level than window manager which's the target from carbon
|
CGEventFlags getKeyboardEventFlags();
|
||||||
// CGEventPost
|
|
||||||
void postHIDVirtualKey(const UInt8 virtualKeyCode,
|
void setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown);
|
||||||
const bool postDown);
|
|
||||||
|
void postKeyboardKey(CGKeyCode virtualKey, bool keyDown);
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,14 @@
|
||||||
#include <AppKit/NSEvent.h>
|
#include <AppKit/NSEvent.h>
|
||||||
#include <libproc.h>
|
#include <libproc.h>
|
||||||
|
|
||||||
|
// The following creates a section that tells Mac OS X
|
||||||
|
// that it is OK to let us inject input in the login screen.
|
||||||
|
// Just the name of the section is important, not its contents.
|
||||||
|
__attribute__((used))
|
||||||
|
__attribute__((section ("__CGPreLoginApp,__cgpreloginapp")))
|
||||||
|
static const char magic_section[] = "";
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// This isn't in any Apple SDK that I know of as of yet.
|
// This isn't in any Apple SDK that I know of as of yet.
|
||||||
enum {
|
enum {
|
||||||
kSynergyEventMouseScroll = 11,
|
kSynergyEventMouseScroll = 11,
|
||||||
|
|
@ -792,16 +800,18 @@ OSXScreen::enable()
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_eventTapPort) {
|
if (m_eventTapPort) {
|
||||||
|
m_eventTapRLSR = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0);
|
||||||
|
if (m_eventTapRLSR) {
|
||||||
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
LOG((CLOG_ERR "failed to create a CFRunLoopSourceRef for the quartz event tap"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
LOG((CLOG_ERR "failed to create quartz event tap"));
|
LOG((CLOG_ERR "failed to create quartz event tap"));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_eventTapRLSR = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0);
|
|
||||||
if (!m_eventTapRLSR) {
|
|
||||||
LOG((CLOG_ERR "failed to create a CFRunLoopSourceRef for the quartz event tap"));
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue