/* tap-list.c - list every event tap in the current login session. * * Copyright (c) 2026 Lazy Developers * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * Build: cc -framework ApplicationServices -o tap-list tap-list.c * Run: ./tap-list * * CGGetEventTapList is a public Core Graphics API. It reads the list of taps * the window server holds for this session - process id, the mask of event * types the tap subscribed to, its options and whether it is enabled - and * needs no Accessibility, Input Monitoring or Screen Recording permission. * This program only reads; it opens no tap of its own and touches no event. * * The keyboard event types are bits 10, 11 and 12 (key down, key up, modifier * flags changed), together 0x1c00. A tap whose mask has none of them never * receives a keystroke. */ #include #include #include #define KEYBOARD_BITS ((CGEventMask)0x1c00) int main(void) { uint32_t count = 0; CGError err = CGGetEventTapList(0, NULL, &count); if (err != kCGErrorSuccess) { fprintf(stderr, "CGGetEventTapList: error %d\n", (int)err); return 1; } CGEventTapInformation taps[256]; if (count > 256) count = 256; err = CGGetEventTapList(count, taps, &count); if (err != kCGErrorSuccess) { fprintf(stderr, "CGGetEventTapList: error %d\n", (int)err); return 1; } printf("%u event tap(s) in this session\n", (unsigned)count); for (uint32_t i = 0; i < count; i++) { char name[2 * MAXCOMLEN + 1] = "?"; proc_name((int)taps[i].tappingProcess, name, sizeof name); printf("pid=%-6d %-32s mask=0x%-10llx options=%d enabled=%d keyboard=%s\n", (int)taps[i].tappingProcess, name, (unsigned long long)taps[i].eventsOfInterest, (int)taps[i].options, taps[i].enabled ? 1 : 0, (taps[i].eventsOfInterest & KEYBOARD_BITS) ? "YES" : "no"); } return 0; }