|
@@ -1,15 +1,12 @@
|
|
#include <cstring>
|
|
#include <cstring>
|
|
#include <cassert>
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <cstdio>
|
|
-#include <thread>
|
|
|
|
-#include <chrono>
|
|
|
|
|
|
+#include <set>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xlib.h>
|
|
-#include <X11/keysymdef.h>
|
|
|
|
extern "C" {
|
|
extern "C" {
|
|
#include <xdo.h>
|
|
#include <xdo.h>
|
|
}
|
|
}
|
|
|
|
|
|
-// const auto KEY_INTERVAL = std::chrono::seconds(64);
|
|
|
|
const useconds_t KEY_DELAY = 12000; // microseconds
|
|
const useconds_t KEY_DELAY = 12000; // microseconds
|
|
|
|
|
|
void search_windows_by_name(const xdo_t* xdo, const char* name_regex, Window** windowlist_ret, unsigned int* nwindows_ret) {
|
|
void search_windows_by_name(const xdo_t* xdo, const char* name_regex, Window** windowlist_ret, unsigned int* nwindows_ret) {
|
|
@@ -32,35 +29,53 @@ class ToontownKeyboardManager {
|
|
search_windows_by_name(xdo, "Toontown.*", windowlist_ret, nwindows_ret);
|
|
search_windows_by_name(xdo, "Toontown.*", windowlist_ret, nwindows_ret);
|
|
}
|
|
}
|
|
|
|
|
|
- void send_keys(const char* keysequence) {
|
|
|
|
|
|
+ void send_keyseq(const char* keysequence, int type) {
|
|
Window* windows;
|
|
Window* windows;
|
|
unsigned int nwindows;
|
|
unsigned int nwindows;
|
|
search_toontown_windows(&windows, &nwindows);
|
|
search_toontown_windows(&windows, &nwindows);
|
|
for(unsigned int i=0; i<nwindows; i++) {
|
|
for(unsigned int i=0; i<nwindows; i++) {
|
|
// file:///usr/share/doc/libxdo-dev/html/xdo_8h.html
|
|
// file:///usr/share/doc/libxdo-dev/html/xdo_8h.html
|
|
// http://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h
|
|
// http://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h
|
|
- xdo_send_keysequence_window(xdo, windows[i], keysequence, KEY_DELAY);
|
|
|
|
|
|
+ if(type == KeyPress) {
|
|
|
|
+ xdo_send_keysequence_window_down(xdo, windows[i], keysequence, KEY_DELAY);
|
|
|
|
+ } else if(type == KeyRelease) {
|
|
|
|
+ xdo_send_keysequence_window_up(xdo, windows[i], keysequence, KEY_DELAY);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(type == KeyPress) {
|
|
|
|
+ printf("> '%s' down\n", keysequence);
|
|
|
|
+ } else if(type == KeyRelease) {
|
|
|
|
+ printf("> '%s' up\n", keysequence);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ static Bool key_autorepeat_predicate(Display* display, XEvent* event, XPointer arg) {
|
|
|
|
+ XKeyEvent* release_event = (XKeyEvent*)arg;
|
|
|
|
+ return event->type == KeyPress
|
|
|
|
+ && event->xkey.keycode == release_event->keycode
|
|
|
|
+ && event->xkey.time == release_event->time;
|
|
|
|
+ }
|
|
|
|
+
|
|
bool key_event(XKeyEvent* key_event) {
|
|
bool key_event(XKeyEvent* key_event) {
|
|
// https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html#XKeyEvent
|
|
// https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html#XKeyEvent
|
|
// https://tronche.com/gui/x/xlib/utilities/keyboard/XLookupKeysym.html
|
|
// https://tronche.com/gui/x/xlib/utilities/keyboard/XLookupKeysym.html
|
|
KeySym key_symbol = XLookupKeysym(key_event, 0);
|
|
KeySym key_symbol = XLookupKeysym(key_event, 0);
|
|
const char* key_str = XKeysymToString(key_symbol);
|
|
const char* key_str = XKeysymToString(key_symbol);
|
|
- printf(
|
|
|
|
- "%s %d %lu %s %d\n",
|
|
|
|
- (key_event->type == KeyPress) ? "p" : "r",
|
|
|
|
- key_event->keycode,
|
|
|
|
- key_symbol,
|
|
|
|
- key_str,
|
|
|
|
- key_event->state
|
|
|
|
- );
|
|
|
|
|
|
+ // printf(
|
|
|
|
+ // "%s %d %lu %s %d %lu\n",
|
|
|
|
+ // (key_event->type == KeyPress) ? "p" : "r",
|
|
|
|
+ // key_event->keycode,
|
|
|
|
+ // key_symbol,
|
|
|
|
+ // key_str,
|
|
|
|
+ // key_event->state
|
|
|
|
+ // , key_event->time
|
|
|
|
+ // );
|
|
if(key_event->state == ControlMask && key_symbol == XStringToKeysym("c")) {
|
|
if(key_event->state == ControlMask && key_symbol == XStringToKeysym("c")) {
|
|
return false; // Ctrl-c
|
|
return false; // Ctrl-c
|
|
} else {
|
|
} else {
|
|
- if(key_event->type == KeyPress) {
|
|
|
|
- send_keys(key_str);
|
|
|
|
|
|
+ XEvent repeat_event;
|
|
|
|
+ if(!XCheckIfEvent(display, &repeat_event, key_autorepeat_predicate, (XPointer)key_event)) {
|
|
|
|
+ send_keyseq(key_str, key_event->type);
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|