|
@@ -1,12 +1,15 @@
|
|
#include <cstring>
|
|
#include <cstring>
|
|
#include <cassert>
|
|
#include <cassert>
|
|
|
|
+#include <cstdio>
|
|
#include <thread>
|
|
#include <thread>
|
|
#include <chrono>
|
|
#include <chrono>
|
|
|
|
+#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 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) {
|
|
@@ -28,17 +31,81 @@ void send_keysequence(const xdo_t* xdo) {
|
|
unsigned int nwindows;
|
|
unsigned int nwindows;
|
|
search_toontown_windows(xdo, &windows, &nwindows);
|
|
search_toontown_windows(xdo, &windows, &nwindows);
|
|
for(unsigned int i=0; i<nwindows; i++) {
|
|
for(unsigned int i=0; i<nwindows; i++) {
|
|
|
|
+ // http://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h
|
|
xdo_send_keysequence_window(xdo, windows[i], "Left", KEY_DELAY);
|
|
xdo_send_keysequence_window(xdo, windows[i], "Left", KEY_DELAY);
|
|
xdo_send_keysequence_window(xdo, windows[i], "Right", KEY_DELAY);
|
|
xdo_send_keysequence_window(xdo, windows[i], "Right", KEY_DELAY);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-int main() {
|
|
|
|
- xdo_t* xdo = xdo_new(NULL);
|
|
|
|
- assert(xdo);
|
|
|
|
- while(true) {
|
|
|
|
- send_keysequence(xdo);
|
|
|
|
- std::this_thread::sleep_for(KEY_INTERVAL);
|
|
|
|
|
|
+class ToontownKeyboardManager {
|
|
|
|
+ Display* display;
|
|
|
|
+ int screen;
|
|
|
|
+ Window main_window;
|
|
|
|
+ xdo_t* xdo;
|
|
|
|
+
|
|
|
|
+ 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/utilities/keyboard/XLookupKeysym.html
|
|
|
|
+ KeySym key_symbol = XLookupKeysym(key_event, 0);
|
|
|
|
+ printf(
|
|
|
|
+ "%s %d %d\n",
|
|
|
|
+ (key_event->type == KeyPress) ? "p" : "r",
|
|
|
|
+ key_event->keycode,
|
|
|
|
+ key_event->state
|
|
|
|
+ );
|
|
|
|
+ //if(key_event.state == ControlMask) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bool window_event(XEvent* event) {
|
|
|
|
+ if(event->type == KeyPress || event->type == KeyRelease) {
|
|
|
|
+ return key_event(&event->xkey);
|
|
|
|
+ } else {
|
|
|
|
+ printf("window event %d", event->type);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+public:
|
|
|
|
+ ToontownKeyboardManager() {
|
|
|
|
+ display = XOpenDisplay(NULL);
|
|
|
|
+ assert(display);
|
|
|
|
+ screen = XDefaultScreen(display);
|
|
|
|
+ xdo = xdo_new(NULL);
|
|
|
|
+ assert(xdo);
|
|
|
|
+
|
|
|
|
+ // https://tronche.com/gui/x/xlib/window/XCreateWindow.html
|
|
|
|
+ main_window = XCreateSimpleWindow(
|
|
|
|
+ display,
|
|
|
|
+ RootWindow(display, screen), // parent
|
|
|
|
+ 0, // x
|
|
|
|
+ 0, // y
|
|
|
|
+ 50, // width
|
|
|
|
+ 50, // height
|
|
|
|
+ 1, // border width
|
|
|
|
+ 0, // border
|
|
|
|
+ 0 // background
|
|
|
|
+ );
|
|
|
|
+ XSelectInput(display, main_window, KeyPressMask | KeyReleaseMask);
|
|
|
|
+ XMapWindow(display, main_window);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ void loop() {
|
|
|
|
+ XEvent event;
|
|
|
|
+ do {
|
|
|
|
+ XNextEvent(display, &event);
|
|
|
|
+ } while(window_event(&event));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ~ToontownKeyboardManager() {
|
|
|
|
+ XCloseDisplay(display);
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+int main() {
|
|
|
|
+ // http://stackoverflow.com/questions/2100654/ignore-auto-repeat-in-x11-applications
|
|
|
|
+ // XAutoRepeatOn(display);
|
|
|
|
+ ToontownKeyboardManager app;
|
|
|
|
+ app.loop();
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|