| 
					
				 | 
			
			
				@@ -1,12 +1,29 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <cstring> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <cassert> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <cstdio> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <set> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <map> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <X11/Xlib.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define XK_MISCELLANY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define XK_LATIN1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <X11/keysymdef.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern "C" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     #include <xdo.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const std::map<KeySym, const char*> kbd_map = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_w, "Up"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_a, "Left"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_s, "Down"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_d, "Right"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Up, "Up"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Left, "Left"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Down, "Down"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Right, "Right"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Control_L, "Control_L"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Control_R, "Control_R"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    {XK_Delete, "Delete"}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -49,6 +66,27 @@ class ToontownKeyboardManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool handle_key(XKeyEvent* key_event) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // https://tronche.com/gui/x/xlib/utilities/keyboard/XLookupKeysym.html 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        KeySym key_symbol = XLookupKeysym(key_event, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(key_event->state == ControlMask && key_symbol == XK_c) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; // Ctrl-c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            auto kbd_map_it = kbd_map.find(key_symbol); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(kbd_map_it != kbd_map.end()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                send_keyseq(kbd_map_it->second, key_event->type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else if(key_event->type == KeyPress) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                printf( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    "no mapping for '%s' (%#lx)\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    XKeysymToString(key_symbol), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    key_symbol 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     static Bool key_autorepeat_predicate(Display* display, XEvent* event, XPointer arg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         XKeyEvent* release_event = (XKeyEvent*)arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return event->type == KeyPress 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -58,25 +96,12 @@ class ToontownKeyboardManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const char* key_str = XKeysymToString(key_symbol); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // 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")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return false; // Ctrl-c 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        XEvent repeat_event; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!XCheckIfEvent(display, &repeat_event, key_autorepeat_predicate, (XPointer)key_event)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return handle_key(key_event); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            XEvent repeat_event;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(!XCheckIfEvent(display, &repeat_event, key_autorepeat_predicate, (XPointer)key_event)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                send_keyseq(key_str, key_event->type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // ignore auto release event 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // xcheckifevent() removed the associated auto press event 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 |