SYNERGY-1013 Ability to run synergy as a pre-login agent

This commit is contained in:
Serhii Hadzhilov 2021-08-17 16:40:36 +03:00
parent f9d0dd4879
commit cf96023aca
3 changed files with 104 additions and 124 deletions

View file

@ -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) {
// 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); if (m_shiftPressed) {
IOObjectRelease(iter); modifiers |= kCGEventFlagMaskShift;
} }
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 }
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: void
event.key.repeat = false; OSXKeyState::postKeyboardKey(CGKeyCode virtualKey, bool keyDown)
event.key.keyCode = virtualKeyCode; {
event.key.origCharSet = event.key.charSet = NX_ASCIISET; CGEventRef event = CGEventCreateKeyboardEvent(nullptr, virtualKey, keyDown);
event.key.origCharCode = event.key.charCode = 0; if (event) {
kr = IOHIDPostEvent(getEventDriver(), CGEventSetFlags(event, getKeyboardEventFlags());
postDown ? NX_KEYDOWN : NX_KEYUP, CGEventPost(kCGHIDEventTap, event);
loc, &event, kNXEventDataVersion, 0, false); CFRelease(event);
assert(KERN_SUCCESS == kr); }
break; else {
LOG((CLOG_CRIT "unable to create keyboard event for keystroke"));
} }
} }
@ -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;
KeyButton button = keystroke.m_data.m_button.m_button; UInt32 client = keystroke.m_data.m_button.m_client;
bool keyDown = keystroke.m_data.m_button.m_press; KeyButton button = keystroke.m_data.m_button.m_button;
CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button); CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button);
LOG((CLOG_DEBUG1
" button=0x%04x virtualKey=0x%04x keyDown=%s",
button, virtualKey, keyDown ? "down" : "up"));
postHIDVirtualKey(virtualKey, keyDown); LOG((CLOG_DEBUG1
" button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x",
button, virtualKey, keyDown ? "down" : "up", client));
break; setKeyboardModifiers(virtualKey, keyDown);
} postKeyboardKey(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;
}
} }
} }

View file

@ -149,12 +149,13 @@ 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 // 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

View file

@ -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