kern_return_t IOHIDSetMouseLocation( io_connect_t connect, int x, int y ) { NXEventData event; IOGPoint location = {x,y}; memset(&event, 0, sizeof(event)); return IOHIDPostEvent(connect, NX_NULLEVENT, location, &event, 2, -1, kIOHIDSetCursorPosition); }
void HIDPostSysDefinedKey(const UInt8 sysKeyCode ) { NXEventData event; kern_return_t kr; IOGPoint loc = { 0, 0 }; bzero(&event, sizeof(NXEventData)); event.compound.subType = sysKeyCode; kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE ); check( KERN_SUCCESS == kr ); }
void HIDPostAuxKey(const UInt8 auxKeyCode ) { NXEventData event; kern_return_t kr; IOGPoint loc = { 0, 0 }; bzero(&event, sizeof(NXEventData)); event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; event.compound.misc.S[0] = auxKeyCode; event.compound.misc.C[2] = NX_KEYDOWN; kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE ); check( KERN_SUCCESS == kr ); }
// Event helpers static void postevent(io_connect_t event, UInt32 type, NXEventData* ev, IOOptionBits flags, IOOptionBits options, int silence_errors){ // Hack #1: IOHIDPostEvent will fail with kIOReturnNotPrivileged if the event doesn't originate from the UID that owns /dev/console // You'd think being root would be good enough. You'd be wrong. ckb-daemon needs to run as root for other reasons though // (namely, being able to seize the physical IOHIDDevices) so what we do instead is change our EUID to the appropriate owner, // post the event, and then change it right back. // Yeah... uid_t uid = 0; gid_t gid = 0; struct stat file; if(!stat("/dev/console", &file)){ uid = file.st_uid; gid = file.st_gid; } euid_guard_start; if(uid != 0) seteuid(uid); if(gid != 0) setegid(gid); IOGPoint location = {0, 0}; if((options & kIOHIDSetRelativeCursorPosition) && type != NX_MOUSEMOVED){ // Hack #2: IOHIDPostEvent will not accept relative mouse coordinates for any event other than NX_MOUSEMOVED // So we need to get the current absolute coordinates from CoreGraphics and then modify those... CGEventRef cge = CGEventCreate(nil); CGPoint loc = CGEventGetLocation(cge); CFRelease(cge); location.x = floor(loc.x + ev->mouseMove.dx); location.y = floor(loc.y + ev->mouseMove.dy); options = (options & ~kIOHIDSetRelativeCursorPosition) | kIOHIDSetCursorPosition; } kern_return_t res = IOHIDPostEvent(event, type, location, ev, kNXEventDataVersion, flags | NX_NONCOALSESCEDMASK, options); if(res != kIOReturnSuccess && !silence_errors) ckb_warn("Post event failed: %x\n", res); if(uid != 0) seteuid(0); if(gid != 0) setegid(0); euid_guard_stop; }