#include "kext.cpp" #include #include #include #include #include #include #include int debug = 0; int vflag = 0; // the -v command line flag // Defined in // Reported for page == 0xFF for some reaosn /* AppleVendor Keyboard Page (0xff01) */ enum { kHIDUsage_AppleVendorKeyboard_Spotlight = 0x0001, kHIDUsage_AppleVendorKeyboard_Dashboard = 0x0002, kHIDUsage_AppleVendorKeyboard_Function = 0x0003, kHIDUsage_AppleVendorKeyboard_Launchpad = 0x0004, kHIDUsage_AppleVendorKeyboard_Reserved = 0x000a, kHIDUsage_AppleVendorKeyboard_CapsLockDelayEnable = 0x000b, kHIDUsage_AppleVendorKeyboard_PowerState = 0x000c, kHIDUsage_AppleVendorKeyboard_Expose_All = 0x0010, kHIDUsage_AppleVendorKeyboard_Expose_Desktop = 0x0011, kHIDUsage_AppleVendorKeyboard_Brightness_Up = 0x0020, kHIDUsage_AppleVendorKeyboard_Brightness_Down = 0x0021, kHIDUsage_AppleVendorKeyboard_Language = 0x0030 }; #if 0 struct KeyEvent { uint64_t type; uint32_t page; uint32_t usage; }; extern "C" int release_kb(); extern "C" int grab_kb(char *product); extern "C" int monitor_kb (char *product); extern "C" int wait_key (struct KeyEvent *); extern "C" int send_key (struct KeyEvent *); #endif // #define send_key my_send_key int send_key (struct KeyEvent *); // Our cooked state of modifiers for key translation dispatch. int meta_down = 0; int shift_down = 0; int control_down = 0; int alt_down = 0; int gui_down = 0; int fn_down = 0; // Current non-modifier key depressed. We need that for auto repeat. struct KeyEvent current_key; // Forward const char *usage_name (struct KeyEvent e); void send_make (KeyEvent e); void send_break (KeyEvent e); // -------------------------------------------------------------------------------------------- #define REPEAT_CPS 30 // character per second #define REPEAT_DELAY 200 // [ms] delay #define META_KEY kHIDUsage_KeyboardLeftAlt // Don't ask why #define KBD(u) ((struct KeyEvent){ .page = 7, .usage = kHIDUsage_Keyboard##u }) #define APPLE(u) ((struct KeyEvent){ .page = 0xFF, .usage = kHIDUsage_AppleVendorKeyboard_##u }) // Our own page #define PRIVATE_PAGE 0x1000CAFE #define PRIVATE_USAGE_Meta 0x00000001 #define PRIVATE(u) ((struct KeyEvent){ .page = PRIVATE_PAGE, .usage = PRIVATE_USAGE_##u }) #define NO_KEY ((struct KeyEvent){ 0, 0, 0 }) int event_eq (struct KeyEvent a, struct KeyEvent b) { return (a.page == b.page) && (a.usage == b.usage); } // -------------------------------------------------------------------------------------------- // We must keep track of both incoming and outgoing modifiers being // depressed or not at any given time. struct modifier_mapping { struct KeyEvent from; struct KeyEvent to; }; #define N_MODBITS ((int)(sizeof(modifiers)/sizeof(modifiers[0]))) struct modifier_mapping modifiers[] = { { KBD(CapsLock), KBD(LeftControl) }, { KBD(LeftControl), KBD(LeftControl) }, { KBD(LeftShift), KBD(LeftShift) }, { KBD(LeftAlt), KBD(LeftGUI) }, { KBD(LeftGUI), PRIVATE(Meta) }, // <--- { KBD(RightControl), KBD(RightControl) }, { KBD(RightShift), KBD(RightShift) }, { KBD(RightAlt), KBD(RightGUI) }, { KBD(RightGUI), KBD(RightAlt) }, { APPLE(Function), APPLE(Function) }, { KBD(NonUSBackslash), KBD(LeftAlt) } }; struct modifier_state { // q[i].type tells whether that modifier is depressed. // // We count upon that page 0x00 is undefined with USB. Also there cannot // really be more "bits" in here than there are modifiers listed with // `modbits'. // struct KeyEvent q[N_MODBITS]; }; // The modifier state that the keyboard actually has. struct modifier_state incoming_modifier_state; // The modifier state that _should_ be seen by the OS. struct modifier_state outgoing_modifier_state; // The modifier state that the OS has seen. struct modifier_state old_outgoing_modifier_state; struct modifier_state empty_modifier_state; void put_modifier (struct modifier_state *state, struct KeyEvent key, int depressed) { int i; for (i = 0; i < N_MODBITS; i++) { if (event_eq (state->q[i], key) || (state->q[i].page == 0 && state->q[i].usage == 0)) { state->q[i] = key; state->q[i].type = depressed; goto done; } } abort(); done:; } int modifier_depressed_p (struct modifier_state *state, struct KeyEvent key) { for (int i = 0; i < N_MODBITS; i++) if (event_eq (state->q[i], key)) return state->q[i].type; return 0; } void print_modifier_state (FILE *out, struct modifier_state *state) { int k = 0; fprintf(out,"["); for (int i = 0; i < N_MODBITS; i++) if (state->q[i].type) { if (k++) fprintf(out, ", "); fprintf(out, "%s", usage_name(state->q[i])); } fprintf(out,"]"); } void ensure_modifier_state (struct modifier_state *state) // Ensures that the OS sees the modifier_state as mentioned with `state'. { int i; // Clear all modifiers that were send, but that are not wanted for (i = 0; i < N_MODBITS; i++) { struct KeyEvent key = old_outgoing_modifier_state.q[i]; if (key.type) if (!modifier_depressed_p (state, key)) send_break (key); } // Then make any which are needed for (i = 0; i < N_MODBITS; i++) { struct KeyEvent key = state->q[i]; if (key.type) if (!modifier_depressed_p (&old_outgoing_modifier_state, key)) send_make (key); } memcpy (&old_outgoing_modifier_state, state, sizeof (struct modifier_state)); } // -------------------------------------------------------------------------------------------- const char *usage_name (struct KeyEvent e) { switch (e.page) { case 0: switch (e.usage) { case 0: return "NIL"; } break; case 7: #define Q(x) case (x) : return #x + strlen("kHIDUsage_Keyboard"); break; switch (e.usage) { Q(kHIDUsage_KeyboardErrorRollOver); Q(kHIDUsage_KeyboardPOSTFail); Q(kHIDUsage_KeyboardErrorUndefined); Q(kHIDUsage_KeyboardA); Q(kHIDUsage_KeyboardB); Q(kHIDUsage_KeyboardC); Q(kHIDUsage_KeyboardD); Q(kHIDUsage_KeyboardE); Q(kHIDUsage_KeyboardF); Q(kHIDUsage_KeyboardG); Q(kHIDUsage_KeyboardH); Q(kHIDUsage_KeyboardI); Q(kHIDUsage_KeyboardJ); Q(kHIDUsage_KeyboardK); Q(kHIDUsage_KeyboardL); Q(kHIDUsage_KeyboardM); Q(kHIDUsage_KeyboardN); Q(kHIDUsage_KeyboardO); Q(kHIDUsage_KeyboardP); Q(kHIDUsage_KeyboardQ); Q(kHIDUsage_KeyboardR); Q(kHIDUsage_KeyboardS); Q(kHIDUsage_KeyboardT); Q(kHIDUsage_KeyboardU); Q(kHIDUsage_KeyboardV); Q(kHIDUsage_KeyboardW); Q(kHIDUsage_KeyboardX); Q(kHIDUsage_KeyboardY); Q(kHIDUsage_KeyboardZ); Q(kHIDUsage_Keyboard1); Q(kHIDUsage_Keyboard2); Q(kHIDUsage_Keyboard3); Q(kHIDUsage_Keyboard4); Q(kHIDUsage_Keyboard5); Q(kHIDUsage_Keyboard6); Q(kHIDUsage_Keyboard7); Q(kHIDUsage_Keyboard8); Q(kHIDUsage_Keyboard9); Q(kHIDUsage_Keyboard0); Q(kHIDUsage_KeyboardReturnOrEnter); Q(kHIDUsage_KeyboardEscape); Q(kHIDUsage_KeyboardDeleteOrBackspace); Q(kHIDUsage_KeyboardTab); Q(kHIDUsage_KeyboardSpacebar); Q(kHIDUsage_KeyboardHyphen); Q(kHIDUsage_KeyboardEqualSign); Q(kHIDUsage_KeyboardOpenBracket); Q(kHIDUsage_KeyboardCloseBracket); Q(kHIDUsage_KeyboardBackslash); Q(kHIDUsage_KeyboardNonUSPound); Q(kHIDUsage_KeyboardSemicolon); Q(kHIDUsage_KeyboardQuote); Q(kHIDUsage_KeyboardGraveAccentAndTilde); Q(kHIDUsage_KeyboardComma); Q(kHIDUsage_KeyboardPeriod); Q(kHIDUsage_KeyboardSlash); Q(kHIDUsage_KeyboardCapsLock); Q(kHIDUsage_KeyboardF1); Q(kHIDUsage_KeyboardF2); Q(kHIDUsage_KeyboardF3); Q(kHIDUsage_KeyboardF4); Q(kHIDUsage_KeyboardF5); Q(kHIDUsage_KeyboardF6); Q(kHIDUsage_KeyboardF7); Q(kHIDUsage_KeyboardF8); Q(kHIDUsage_KeyboardF9); Q(kHIDUsage_KeyboardF10); Q(kHIDUsage_KeyboardF11); Q(kHIDUsage_KeyboardF12); Q(kHIDUsage_KeyboardPrintScreen); Q(kHIDUsage_KeyboardScrollLock); Q(kHIDUsage_KeyboardPause); Q(kHIDUsage_KeyboardInsert); Q(kHIDUsage_KeyboardHome); Q(kHIDUsage_KeyboardPageUp); Q(kHIDUsage_KeyboardDeleteForward); Q(kHIDUsage_KeyboardEnd); Q(kHIDUsage_KeyboardPageDown); Q(kHIDUsage_KeyboardRightArrow); Q(kHIDUsage_KeyboardLeftArrow); Q(kHIDUsage_KeyboardDownArrow); Q(kHIDUsage_KeyboardUpArrow); Q(kHIDUsage_KeypadNumLock); Q(kHIDUsage_KeypadSlash); Q(kHIDUsage_KeypadAsterisk); Q(kHIDUsage_KeypadHyphen); Q(kHIDUsage_KeypadPlus); Q(kHIDUsage_KeypadEnter); Q(kHIDUsage_Keypad1); Q(kHIDUsage_Keypad2); Q(kHIDUsage_Keypad3); Q(kHIDUsage_Keypad4); Q(kHIDUsage_Keypad5); Q(kHIDUsage_Keypad6); Q(kHIDUsage_Keypad7); Q(kHIDUsage_Keypad8); Q(kHIDUsage_Keypad9); Q(kHIDUsage_Keypad0); Q(kHIDUsage_KeypadPeriod); Q(kHIDUsage_KeyboardNonUSBackslash); Q(kHIDUsage_KeyboardApplication); Q(kHIDUsage_KeyboardPower); Q(kHIDUsage_KeypadEqualSign); Q(kHIDUsage_KeyboardF13); Q(kHIDUsage_KeyboardF14); Q(kHIDUsage_KeyboardF15); Q(kHIDUsage_KeyboardF16); Q(kHIDUsage_KeyboardF17); Q(kHIDUsage_KeyboardF18); Q(kHIDUsage_KeyboardF19); Q(kHIDUsage_KeyboardF20); Q(kHIDUsage_KeyboardF21); Q(kHIDUsage_KeyboardF22); Q(kHIDUsage_KeyboardF23); Q(kHIDUsage_KeyboardF24); Q(kHIDUsage_KeyboardExecute); Q(kHIDUsage_KeyboardHelp); Q(kHIDUsage_KeyboardMenu); Q(kHIDUsage_KeyboardSelect); Q(kHIDUsage_KeyboardStop); Q(kHIDUsage_KeyboardAgain); Q(kHIDUsage_KeyboardUndo); Q(kHIDUsage_KeyboardCut); Q(kHIDUsage_KeyboardCopy); Q(kHIDUsage_KeyboardPaste); Q(kHIDUsage_KeyboardFind); Q(kHIDUsage_KeyboardMute); Q(kHIDUsage_KeyboardVolumeUp); Q(kHIDUsage_KeyboardVolumeDown); Q(kHIDUsage_KeyboardLockingCapsLock); Q(kHIDUsage_KeyboardLockingNumLock); Q(kHIDUsage_KeyboardLockingScrollLock); Q(kHIDUsage_KeypadComma); Q(kHIDUsage_KeypadEqualSignAS400); Q(kHIDUsage_KeyboardInternational1); Q(kHIDUsage_KeyboardInternational2); Q(kHIDUsage_KeyboardInternational3); Q(kHIDUsage_KeyboardInternational4); Q(kHIDUsage_KeyboardInternational5); Q(kHIDUsage_KeyboardInternational6); Q(kHIDUsage_KeyboardInternational7); Q(kHIDUsage_KeyboardInternational8); Q(kHIDUsage_KeyboardInternational9); Q(kHIDUsage_KeyboardLANG1); Q(kHIDUsage_KeyboardLANG2); Q(kHIDUsage_KeyboardLANG3); Q(kHIDUsage_KeyboardLANG4); Q(kHIDUsage_KeyboardLANG5); Q(kHIDUsage_KeyboardLANG6); Q(kHIDUsage_KeyboardLANG7); Q(kHIDUsage_KeyboardLANG8); Q(kHIDUsage_KeyboardLANG9); Q(kHIDUsage_KeyboardAlternateErase); Q(kHIDUsage_KeyboardSysReqOrAttention); Q(kHIDUsage_KeyboardCancel); Q(kHIDUsage_KeyboardClear); Q(kHIDUsage_KeyboardPrior); Q(kHIDUsage_KeyboardReturn); Q(kHIDUsage_KeyboardSeparator); Q(kHIDUsage_KeyboardOut); Q(kHIDUsage_KeyboardOper); Q(kHIDUsage_KeyboardClearOrAgain); Q(kHIDUsage_KeyboardCrSelOrProps); Q(kHIDUsage_KeyboardExSel); Q(kHIDUsage_KeyboardLeftControl); Q(kHIDUsage_KeyboardLeftShift); Q(kHIDUsage_KeyboardLeftAlt); Q(kHIDUsage_KeyboardLeftGUI); Q(kHIDUsage_KeyboardRightControl); Q(kHIDUsage_KeyboardRightShift); Q(kHIDUsage_KeyboardRightAlt); Q(kHIDUsage_KeyboardRightGUI); } break; #undef Q #define Q(x) case (x) : return #x + strlen("kHIDUsage_AppleVendorKeyboard_"); break; case 0xFF: switch (e.usage) { Q(kHIDUsage_AppleVendorKeyboard_Spotlight); Q(kHIDUsage_AppleVendorKeyboard_Dashboard); Q(kHIDUsage_AppleVendorKeyboard_Function); Q(kHIDUsage_AppleVendorKeyboard_Launchpad); Q(kHIDUsage_AppleVendorKeyboard_Reserved); Q(kHIDUsage_AppleVendorKeyboard_CapsLockDelayEnable); Q(kHIDUsage_AppleVendorKeyboard_PowerState); Q(kHIDUsage_AppleVendorKeyboard_Expose_All); Q(kHIDUsage_AppleVendorKeyboard_Expose_Desktop); Q(kHIDUsage_AppleVendorKeyboard_Brightness_Up); Q(kHIDUsage_AppleVendorKeyboard_Brightness_Down); Q(kHIDUsage_AppleVendorKeyboard_Language); } break; #undef Q #define Q(x) case (x) : return #x + strlen("PRIVATE_USAGE_"); break; case PRIVATE_PAGE: switch (e.usage) { Q(PRIVATE_USAGE_Meta); } break; #undef Q } { char *buf = 0; asprintf (&buf, "Unknown page/usage: 0x%x/0x%x\n", e.page, e.usage); return buf; } } // 64-bit suffice to represent us since epoch. int64_t tv_to_usec (struct timeval tv) { return (tv.tv_sec * (uint64_t)1000000) + tv.tv_usec; } struct timeval usec_to_tv (int64_t us) { return (struct timeval) { .tv_sec = (time_t)(us / 1000000), .tv_usec = (suseconds_t)(us % 1000000) }; } int64_t now_usec (void) { struct timeval tv; gettimeofday (&tv, NULL); return tv_to_usec (tv); } void send_make (KeyEvent e) { if ((e.page != PRIVATE_PAGE) && (e.page != 0)) { if (vflag) fprintf(stderr, "\033[31m=> make %s\033[0m\n", usage_name(e)); e.type = 1; send_key (&e); } } void send_break (KeyEvent e) { if ((e.page != PRIVATE_PAGE) && (e.page != 0)) { if (vflag) fprintf(stderr, "\033[31m=> break %s\033[0m\n", usage_name(e)); e.type = 0; send_key (&e); } } void send_hit (struct KeyEvent e, int down) { ensure_modifier_state(&outgoing_modifier_state); if (down) send_make(e); else send_break(e); } void ensure_shift (int depressed) { put_modifier(&outgoing_modifier_state, KBD(LeftShift), depressed); put_modifier(&outgoing_modifier_state, KBD(RightShift), 0); } void send_stroke (KeyEvent e, int down) { if(0){} // Some remappings else if (event_eq(e, KBD(OpenBracket)) && !shift_down) { ensure_shift(1); send_hit(KBD(9), down); } else if (event_eq(e, KBD(CloseBracket)) && !shift_down) { ensure_shift(1); send_hit(KBD(0), down); } else if (event_eq(e, KBD(9)) && shift_down) { ensure_shift(0); send_hit(KBD(OpenBracket), down); } else if (event_eq(e, KBD(0)) && shift_down) { ensure_shift(0); send_hit(KBD(CloseBracket), down); } else if (event_eq(e, KBD(Slash)) && !shift_down) { send_hit(KBD(Hyphen), down); } else if (event_eq(e, KBD(Hyphen)) && !shift_down) { send_hit(KBD(Slash), down); } // c-space => c-@ which is more reliable else if (event_eq(e, KBD(Spacebar)) && control_down) { ensure_shift(1); send_hit(KBD(2), down); } // Those funny keys else if (event_eq(e, KBD(F10))) { send_hit(KBD(Mute), down); } else if (event_eq(e, KBD(F11))) { send_hit(KBD(VolumeDown), down); } else if (event_eq(e, KBD(F12))) { send_hit(KBD(VolumeUp), down); } // Some short cuts else if (event_eq (e, KBD(T)) && gui_down && !shift_down) { if(down) system("osascript -e 'tell application \"Terminal\" to activate'"); } else if (event_eq (e, KBD(E)) && gui_down && !shift_down) { if(down) system("osascript -e 'tell application \"Emacs\" to activate'"); } else if (event_eq (e, KBD(T)) && gui_down && shift_down) { if(down) system("open -a Terminal ~"); } // Default else send_hit (e, down); } void recompute_outgoing_modifiers (void) { int i; memset (&outgoing_modifier_state, 0, sizeof (outgoing_modifier_state)); for (i = 0; i < N_MODBITS; i++) if (modifier_depressed_p(&incoming_modifier_state, modifiers[i].from)) put_modifier(&outgoing_modifier_state, modifiers[i].to, 1); } // -------------------------------------------------------------------------------------------- #if 0 void send_escape (void) { ensure_modifier_state(&empty_modifier_state); send_make(KBD(Escape)); send_break(KBD(Escape)); } #else void send_escape (void) { struct modifier_state m = empty_modifier_state; put_modifier(&m, KBD(LeftControl), 1); ensure_modifier_state(&m); send_make(KBD(OpenBracket)); send_break(KBD(OpenBracket)); } #endif // // We reconstruct this a bit. This keyboard stuff needs to run as root, but // we don't and don't need to. // // What we rather would like to have is just two pipes to a child process, // which runs as root, sending (struct KeyEvent) back and forth. // int old_main (void); int main_to_kbd[2], kbd_to_main[2]; #define fatala(msg, ...) do{ \ fprintf(stderr, "%s:%d: " msg ": %s\n", __FILE__, __LINE__, __VA_ARGS__, strerror(errno)); \ abort(); \ }while(0) #define fatal(msg) { \ fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, strerror(errno)); \ abort(); \ }while(0) int send_key (struct KeyEvent *e) { int ret; again: errno = 0; ret = write(main_to_kbd[1], e, sizeof(*e)); if ((ret < 0) && (errno == EAGAIN)) goto again; if ((ret < 0) && (errno == EINTR)) goto again; if (ret != sizeof(*e)) fatal("write"); return 1; } void usage (const char *name) { fprintf(stderr, "Usage: %s [-v]\n", name); fprintf(stderr, " -v Be verbose. Both incoming and outgoing make/break events\n"); fprintf(stderr, " are logged\n"); fprintf(stderr,"\n"); } int main (int argc, char **argv) { int ret; // Grok command line arguments { int ch; while ((ch = getopt(argc, argv, "v")) != -1) { switch (ch) { case 'v': vflag = 1; break; case '?': default: usage(argv[0]); exit(1); } } } argc -= optind; argv += optind; ret = pipe(main_to_kbd); if (ret != 0) fatal("pipe"); ret = pipe(kbd_to_main); if (ret != 0) fatal("pipe"); ret = fork(); if (ret < 0) fatal("fork"); if (ret == 0) { // child close(main_to_kbd[1]); close(kbd_to_main[0]); sleep(1); ret = grab_kb(NULL); if(ret) { fprintf(stderr, "Can't grab keyboard it seems.\n"); abort(); } fprintf(stderr, "Ready to go, we apparently have the keyboard\n"); // Kludge fd[1] = kbd_to_main[1]; // for(;;) { struct KeyEvent e; again: errno = 0; ret = read(main_to_kbd[0], &e, sizeof(e)); if (ret < 0 && errno == EAGAIN) goto again; if (ret < 0 && errno == EINTR) goto again; if (ret == 0) break; if (ret < 0) fatal("read"); if (ret != sizeof(e)) fatala("short read, wanted %zu, got %d", sizeof(e), ret); #undef send_key send_key (&e); #define send_key my_send_key } fprintf(stderr, "Good bye!\n"); release_kb(); } else { // Parent close(main_to_kbd[0]); close(kbd_to_main[1]); // Get rid of root priviledges ret = setgid(getgid()); if (ret != 0) { fprintf(stderr,"getgid(2): %s\n", strerror(errno)); abort(); } ret = setuid(getuid()); if (ret != 0) { fprintf(stderr,"getgid(2): %s\n", strerror(errno)); abort(); } // Kludge fd[0] = kbd_to_main[0]; old_main (); } } int old_main (void) { int serial = 0; int ret; struct KeyEvent e, repeat_key; int64_t repeat_due = 0; #if 0 // Sleep a little just in case to let keyup events to occur, when // we're started interactively. sleep (1); fprintf(stderr, "Ready to go, about to grab the keyboard\n"); ret = grab_kb(NULL); fprintf(stderr, "Ready to go, we apparently have the keyboard\n"); if (0 == fork()) { ret = setgid(getgid()); if (ret != 0) { fprintf(stderr,"getgid(2): %s\n", strerror(errno)); abort(); } ret = setuid(getuid()); if (ret != 0) { fprintf(stderr,"getgid(2): %s\n", strerror(errno)); abort(); } system("id"); exit(0); } #endif int64_t exit_due = now_usec() + 60 * 1000 * 1000; while (!debug || now_usec() < exit_due) { fd_set rfds; int maxfd = 0; struct timeval to; FD_ZERO(&rfds); FD_SET(fd[0], &rfds); if (fd[0] > maxfd) maxfd = fd[0]; if (repeat_due) { int64_t dt = repeat_due - now_usec (); if (dt < 0) dt = 0; to = usec_to_tv(dt); } else to = usec_to_tv (1000 * 1000); ret = select(maxfd+1, &rfds, NULL, NULL, &to); if (ret == -1) { fprintf (stderr, "select(2): %s\n", strerror (errno)); goto take_care; } // fprintf(stderr, "#"); if (ret && FD_ISSET(fd[0], &rfds)) { again: errno = 0; ret = read (fd[0], &e, sizeof(e)); if (ret == 0) goto take_care; if (ret < 0 && errno == EAGAIN) goto again; if (ret < 0 && errno == EINTR) goto again; if (ret < 0) fatal("read(2)"); if (ret != sizeof(struct KeyEvent)) fatala("read(2), wanted %zu got %d", sizeof(e), ret); int is_modifier = 0; // Update the incoming modifier bits { int i; for (i = 0; i < N_MODBITS; i++) { if (event_eq (modifiers[i].from, e)) { put_modifier(&incoming_modifier_state, e, e.type == 1); is_modifier = 1; break; } } } // Recompute our own modifiers. For consistency we always do a // complete remap. recompute_outgoing_modifiers (); meta_down = modifier_depressed_p(&outgoing_modifier_state, PRIVATE(Meta)); shift_down = (modifier_depressed_p(&outgoing_modifier_state, KBD(LeftShift)) || modifier_depressed_p(&outgoing_modifier_state, KBD(RightShift))); control_down = (modifier_depressed_p(&outgoing_modifier_state, KBD(LeftControl)) || modifier_depressed_p(&outgoing_modifier_state, KBD(RightControl))); alt_down = (modifier_depressed_p(&outgoing_modifier_state, KBD(LeftAlt)) || modifier_depressed_p(&outgoing_modifier_state, KBD(RightAlt))); gui_down = (modifier_depressed_p(&outgoing_modifier_state, KBD(LeftGUI)) || modifier_depressed_p(&outgoing_modifier_state, KBD(RightGUI))); fn_down = modifier_depressed_p(&outgoing_modifier_state, APPLE(Function)); if (!(e.usage == -1 || // No idea where these come from e.usage == 0 || // Not here // Hmm, I guess there is no point on relaying these. (e.page == 7 && (e.usage == kHIDUsage_KeyboardErrorRollOver || e.usage == kHIDUsage_KeyboardErrorUndefined)))) { if (vflag) switch (e.type) { case 0: fprintf (stdout, "\033[32m<= break %s\033[0m\n", usage_name(e)); break; case 1: fprintf (stdout, "\033[32m<= make %s\033[0m\n", usage_name(e)); break; default: fprintf (stderr, "[%6d] ret = %d, type = %.16llx page = %.8x usage = %.8x (%s)\n", serial++, ret, e.type, e.page, e.usage, usage_name(e) ); } if ((e.page == 7 || e.page == 0xFF) && (e.type == 0 || e.type == 1)) { // ensure_modifier_state (&outgoing_modifier_state); if (is_modifier) ; else if (e.type == 1) { repeat_due = now_usec() + REPEAT_DELAY * 1000; if (meta_down) send_escape(); ensure_modifier_state (&outgoing_modifier_state); send_stroke (e, 1); repeat_key = e; } else { send_stroke (e, 0); if (event_eq (repeat_key, e)) { repeat_due = 0; repeat_key = NO_KEY; } } } else { // Don't know what this is. Pass it along. ret = send_key(&e); } } } if (repeat_due && (now_usec () > repeat_due)) { send_stroke(repeat_key, 0); if (meta_down) send_escape(); ensure_modifier_state (&outgoing_modifier_state); send_stroke (repeat_key, 1); repeat_due = now_usec() + 1000000 / REPEAT_CPS; } // No matter what sync the modifier state again recompute_outgoing_modifiers (); ensure_modifier_state (&outgoing_modifier_state); } take_care: fprintf (stderr, "Take care.\n"); close (main_to_kbd[1]); sleep(1); return 0; } // -- TODO ------------------------------------------------------------------------------------ // I don't like how auto-repeat is handledd. Maybe we make this before we do // other translatioons? My trouble is with '[' => sh-9 // at the moment we do // make shift-left // make 9 // break shift-left // make shift-left // break 9 // break shift-left // Which is non-sense. // Have an option to return to the previous key repeat logic. It'll break // games, but it perhaps is more reliable. // Have an option to send as C-[ // Perhaps the 'shift' should stick somehow? Yes, it should. This would need // some change in our infrastructure, as we need to keep track of chords to // present. // For I want that make/break does indeed appear for the key. // Make the prefix like: make make make . // This could be a secret trick to make Free-CLIM tell about an ESC prefix. // Hmm. // At times we face some glitches.