#import <Cocoa/Cocoa.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <dispatch/dispatch.h> | |
#include <curl/curl.h> | |
#define MAXLINE 512 | |
CFMachPortRef eventTap; | |
time_t prev_time = 0; | |
int count_key = 0; | |
int count_mouse = 0; | |
size_t curl_write_callback_func(char* ptr, size_t size, size_t nmemb, void* nothing) { | |
return 0; | |
} | |
int post(char *name, int num) { | |
char url[MAXLINE]; | |
sprintf(url, "http://localhost:5126/api/me/log/%s", name); | |
char postdata[MAXLINE]; | |
sprintf(postdata, "number=%d", num); | |
printf("%s: %d\n", name, num); | |
CURL *curl = curl_easy_init(); | |
curl_easy_setopt(curl, CURLOPT_URL, url); | |
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata); | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_callback_func); | |
CURLcode res = curl_easy_perform(curl); | |
curl_easy_cleanup(curl); | |
return res == CURLE_OK; | |
} | |
void postEventsAsync(int num_key, int num_mouse) { | |
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ | |
post("key", num_key); | |
post("mouse", num_mouse); | |
}); | |
} | |
CGEventRef catchEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* nothing) { | |
// http://stackoverflow.com/questions/4727149/application-randomly-stops-receiving-key-presses-cgeventtaps | |
if (type == kCGEventTapDisabledByTimeout) { | |
CGEventTapEnable(eventTap, true); | |
} | |
if (type == kCGEventKeyDown) { /* to listen for key events, run this program as root */ | |
int key = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); | |
printf("%d\n", key); | |
count_key++; | |
} | |
else if (type == kCGEventMouseMoved || type == kCGEventScrollWheel) { | |
count_mouse++; | |
} | |
return event; | |
} | |
void recordCountsCallback(CFRunLoopTimerRef timer, void* nothing) { | |
time_t this_time; | |
struct tm * timeinfo; | |
time(&this_time); | |
timeinfo = localtime(&this_time); | |
timeinfo->tm_sec = 0; | |
this_time = mktime(timeinfo); | |
if (this_time == prev_time) { | |
// within less than 60 sec (do nothing) | |
return; | |
} else if (prev_time == 0) { | |
// first time (set prev_time to this_time) | |
} else if (difftime(this_time, prev_time) >= 120.0) { | |
// come back from sleep (discard) | |
count_key = 0; | |
count_mouse = 0; | |
postEventsAsync(count_key, count_mouse); | |
} else { | |
// more than 60 sec (record) | |
postEventsAsync(count_key, count_mouse); | |
count_key = 0; | |
count_mouse = 0; | |
} | |
prev_time = this_time; | |
} | |
int main() { | |
CFRunLoopSourceRef runLoopSource; | |
eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, kCGEventMaskForAllEvents, catchEventCallback, NULL); | |
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0); | |
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes); | |
CGEventTapEnable(eventTap, true); | |
CFRunLoopTimerRef timer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0, 1.0, 0, 0, recordCountsCallback, NULL); | |
CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); | |
CFRunLoopRun(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment