#include "SysInfo_in.h" NAMESPACE_UPP struct KeyCodes { String key; int code; }; #if defined(PLATFORM_WIN32) || defined (PLATFORM_WIN64) Array GetWinRegSubkeys(const String& key, HKEY base) { HKEY hkey; Array subkeys; if(RegOpenKeyEx(base, key, 0, KEY_READ, &hkey) != ERROR_SUCCESS) return subkeys; char temp[_MAX_PATH]; dword len; for(dword dw = 0; len = sizeof(temp), RegEnumKeyEx(hkey, dw, temp, &len, 0, 0, 0, 0) == ERROR_SUCCESS; dw++) subkeys.Add(temp); RegCloseKey(hkey); return subkeys; } void Mouse_LeftDown() {mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);} void Mouse_LeftUp() {mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);} void Mouse_MiddleDown() {mouse_event(MOUSEEVENTF_MIDDLEDOWN, 0, 0, 0, 0);} void Mouse_MiddleUp() {mouse_event(MOUSEEVENTF_MIDDLEUP, 0, 0, 0, 0);} void Mouse_RightDown() {mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);} void Mouse_RightUp() {mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);} bool Mouse_SetPos(long xMove, long yMove, int64 windowId) { long left, top, right, bottom; if (windowId != 0) { Window_GetRect(windowId, left, top, right, bottom); xMove = xMove + left; yMove = yMove + top; } SetCursorPos(xMove, yMove); return true; } bool Mouse_GetPos(long &x, long &y) { POINT p; GetCursorPos (&p); x = p.x; y = p.y; return true; } KeyCodes keyCodes[60] = { "NUMPAD7", VK_NUMPAD7, "BACK", VK_BACK, "NUMPAD8", VK_NUMPAD8, "TAB", VK_TAB, "NUMPAD9", VK_NUMPAD9, "RETURN", VK_RETURN, "MULTIPLY", VK_MULTIPLY, "SHIFT", VK_SHIFT, "ADD", VK_ADD, "CONTROL", VK_CONTROL, "SEPARATOR", VK_SEPARATOR, "MENU", VK_MENU, "SUBTRACT", VK_SUBTRACT, "PAUSE", VK_PAUSE, "DECIMAL", VK_DECIMAL, "CAPITAL", VK_CAPITAL, "DIVIDE", VK_DIVIDE, "ESCAPE", VK_ESCAPE, "F1", VK_F1, "SPACE", VK_SPACE, "F2", VK_F2, "END", VK_END, "F3", VK_F3, "HOME", VK_HOME, "F4", VK_F4, "LEFT", VK_LEFT, "F5", VK_F5, "UP", VK_UP, "F6", VK_F6, "RIGHT", VK_RIGHT, "F7", VK_F7, "DOWN", VK_DOWN, "F8", VK_F8, "PRINT", VK_PRINT, "F9", VK_F9, "SNAPSHOT", VK_SNAPSHOT, "F10", VK_F10, "INSERT", VK_INSERT, "F11", VK_F11, "DELETE", VK_DELETE, "F12", VK_F12, "LWIN", VK_LWIN, "NUMLOCK", VK_NUMLOCK, "RWIN", VK_RWIN, "SCROLL", VK_SCROLL, "NUMPAD0", VK_NUMPAD0, "LSHIFT", VK_LSHIFT, "NUMPAD1", VK_NUMPAD1, "RSHIFT", VK_RSHIFT, "NUMPAD2", VK_NUMPAD2, "LCONTROL", VK_LCONTROL, "NUMPAD3", VK_NUMPAD3, "RCONTROL", VK_RCONTROL, "NUMPAD4", VK_NUMPAD4, "LMENU", VK_LMENU, "NUMPAD5", VK_NUMPAD5, "RMENU", VK_RMENU, "NUMPAD6", VK_NUMPAD6, /*"PGUP", XK_Page_Up, "PGDOWN", XK_Page_Down "CAPSLOCK", XK_Caps_Lock, "BACKSPACE",XK_BackSpace */ "" }; void PressKeyVK(int keyVK, bool hold = false, bool release = false, bool compatible = false) { long nScan, nExtended; nScan = MapVirtualKey(keyVK, 2); nExtended = 0; if (nScan == 0) nExtended = KEYEVENTF_EXTENDEDKEY; nScan = MapVirtualKey(keyVK, 0); if (compatible) nExtended = 0; if (!release) keybd_event((BYTE)keyVK, (BYTE)nScan, nExtended, 0); if (!hold) keybd_event((BYTE)keyVK, (BYTE)nScan, KEYEVENTF_KEYUP | nExtended, 0); } #if defined(__MINGW32__) #define MAPVK_VK_TO_VSC 0 #define MAPVK_VSC_TO_VK 1 #define MAPVK_VK_TO_CHAR 2 #define MAPVK_VSC_TO_VK_EX 3 #endif #define MAPVK_VK_TO_VSC_EX 4 // This is less nice but more compatible for Notepad and MSWord for example void PressKey(wchar key, bool hold = false, bool release = false) { if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9')) { HKL hKeyboardLayout = ::GetKeyboardLayout(0); SHORT nVK = VkKeyScanExW(key, hKeyboardLayout); UINT nScan = MapVirtualKeyExW(nVK, MAPVK_VK_TO_CHAR, hKeyboardLayout); if (!release) keybd_event((BYTE)nVK, (BYTE)nScan, 0, 0); if (!hold) keybd_event((BYTE)nVK, (BYTE)nScan, KEYEVENTF_KEYUP, 0); } else { String numStr = FormatIntDec(key, 5, '0'); PressKeyVK(VK_LMENU, true); PressKeyVK(VK_NUMPAD0 + numStr[0] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[1] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[2] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[3] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[4] - '0'); PressKeyVK(VK_LMENU, false, true); } } /* void PressKey(wchar key, bool hold = false, bool release = false) { bool caps, num, scroll; if (IsLetter(key)) { GetKeyLockStatus(caps, num, scroll); if (caps) SetKeyLockStatus(false, num, scroll); } HKL hKeyboardLayout = ::GetKeyboardLayout(0); if (hKeyboardLayout) { // Last resource !! String numStr = FormatIntDec(key, 4, '0'); PressKeyVK(VK_LMENU, true); PressKeyVK(VK_NUMPAD0 + numStr[0] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[1] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[2] - '0'); PressKeyVK(VK_NUMPAD0 + numStr[3] - '0'); PressKeyVK(VK_LMENU, false, true); return; } UINT nScan = MapVirtualKeyExW(nVK, MAPVK_VK_TO_CHAR, hKeyboardLayout); long nExtended = 0; if (nScan == 0) nExtended = KEYEVENTF_EXTENDEDKEY; nScan = MapVirtualKeyExW(nVK, MAPVK_VK_TO_VSC, hKeyboardLayout); bool shift, ctrl, alt; shift = nVK & 0x100; ctrl = nVK & 0x200; alt = nVK & 0x400; nVK = nVK & 0xFF; if (!release) { if (shift) keybd_event (VK_SHIFT, 0, 0, 0); if (ctrl) keybd_event (VK_CONTROL, 0, 0, 0); if (alt) keybd_event (VK_MENU, 0, 0, 0); keybd_event ((BYTE)nVK, (BYTE)nScan, nExtended, 0); } if (!hold) { keybd_event ((BYTE)nVK, (BYTE)nScan, KEYEVENTF_KEYUP | nExtended, 0); if (shift) keybd_event (VK_SHIFT, 0, KEYEVENTF_KEYUP, 0); if (ctrl) keybd_event (VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); if (alt) keybd_event (VK_MENU, 0, KEYEVENTF_KEYUP, 0); } if (IsLetter(key) && caps) SetKeyLockStatus(true, num, scroll); } */ bool GetKeyLockStatus(bool &caps, bool &num, bool &scroll) { caps = GetKeyState(VK_CAPITAL); num = GetKeyState(VK_NUMLOCK); scroll = GetKeyState(VK_SCROLL); return true; } bool SetKeyLockStatus(bool caps, bool num, bool scroll) { bool capsnow, numnow, scrollnow; GetKeyLockStatus(capsnow, numnow, scrollnow); if (capsnow != caps) PressKeyVK(VK_CAPITAL); if (numnow != num) PressKeyVK(VK_NUMLOCK); if (scrollnow != scroll) PressKeyVK(VK_SCROLL); return true; } #endif #ifdef PLATFORM_POSIX bool Mouse_GetPos(long &x, long &y) { SetSysInfoX11ErrorHandler(); _XDisplay *dpy = XOpenDisplay (NULL); if (!dpy) { SetX11ErrorHandler(); return false; } bool ret = false; Window root, child; Window r = DefaultRootWindow(dpy); int retx, rety; int wx, wy; unsigned int keys_buttons; if (XQueryPointer(dpy, r, &root, &child, &retx, &rety, &wx, &wy, &keys_buttons)) { x = wx; y = wy; ret = true; } else x = y = -1; XCloseDisplay (dpy); SetX11ErrorHandler(); return ret; } bool Mouse_SetPos(long x, long y, int64 windowId) { SetSysInfoX11ErrorHandler(); _XDisplay *dpy = XOpenDisplay (NULL); if (!dpy) { SetX11ErrorHandler(); return false; } long left, top, right, bottom; Window r = DefaultRootWindow(dpy); if (windowId != 0) { Window_GetRect(windowId, left, top, right, bottom); x = x + left; y = y + top; } XWarpPointer(dpy, None, r, 0, 0, 0, 0, x, y); XCloseDisplay (dpy); SetX11ErrorHandler(); return true; } #ifdef flagXTEST // libxtst-dev void Mouse_FakeClick(int button, int press) { _XDisplay *dpy = XOpenDisplay(NULL); XTestFakeButtonEvent(dpy, button, press, CurrentTime); XFlush(dpy); XCloseDisplay(dpy); } void Mouse_LeftDown() {Mouse_FakeClick(1, True);} void Mouse_LeftUp() {Mouse_FakeClick(1, False);} void Mouse_MiddleDown() {Mouse_FakeClick(2, True);} void Mouse_MiddleUp() {Mouse_FakeClick(2, False);} void Mouse_RightDown() {Mouse_FakeClick(3, True);} void Mouse_RightUp() {Mouse_FakeClick(3, False);} void PressKeyVK(int key, _XDisplay *dpy = NULL) { bool local = false; if (!dpy) { if (!(dpy = XOpenDisplay(NULL))) return; local = true; } XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, key), True, CurrentTime); XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, key), False, CurrentTime); if (local) { XFlush(dpy); XCloseDisplay(dpy); } } void PressKey(wchar key, _XDisplay *dpy = NULL) { bool local = false; if (!dpy) { if (!(dpy = XOpenDisplay(NULL))) return; local = true; } wchar k = key; if (key > 0x00ff) key = key | 0x01000000; bool shift = false; KeyCode code = XKeysymToKeycode(dpy, key); if (code != 0) { if (XkbKeycodeToKeysym(dpy, code, 0, 0) != key) { if (XkbKeycodeToKeysym(dpy, code, 1, 0) == key) shift = true; else code = 0; } } else { int firstKeycode, maxKeycode; int keysymsPerKeycode; XDisplayKeycodes(dpy, &firstKeycode, &maxKeycode); KeySym *keysyms = XGetKeyboardMapping(dpy, firstKeycode, maxKeycode - firstKeycode + 1, &keysymsPerKeycode); int indx = (maxKeycode - firstKeycode - 1)*keysymsPerKeycode; keysyms[indx] = key; XChangeKeyboardMapping(dpy, firstKeycode, keysymsPerKeycode, keysyms, maxKeycode-firstKeycode); XSync(dpy, False); code = maxKeycode-1; if (XkbKeycodeToKeysym(dpy, code, 0, 0) != key) { if (XkbKeycodeToKeysym(dpy, code, 1, 0) == key) shift = true; } } if (code != 0) { if (shift) XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, XK_Shift_L), True, CurrentTime); XTestFakeKeyEvent(dpy, code, True, CurrentTime); XTestFakeKeyEvent(dpy, code, False, CurrentTime); if (shift) XTestFakeKeyEvent(dpy, XKeysymToKeycode(dpy, XK_Shift_L), False, CurrentTime); } if (local) { XFlush(dpy); XCloseDisplay(dpy); } } bool GetKeyLockStatus0(bool &caps, bool &num, bool &scroll, _XDisplay *dpy) { int x, y, xx, yy; Window dm1, dm2; unsigned int sKbdState; if(!XQueryPointer(dpy, DefaultRootWindow(dpy), &dm1, &dm2, &x, &y, &xx, &yy, &sKbdState)) return false; caps = sKbdState & LockMask; num = sKbdState & Mod2Mask; scroll = sKbdState & Mod5Mask; return true; } bool GetKeyLockStatus(bool &caps, bool &num, bool &scroll) { _XDisplay *dpy; if (!(dpy = XOpenDisplay(NULL))) return false; if (!GetKeyLockStatus0(caps, num, scroll, dpy)) { XCloseDisplay(dpy); return false; } XFlush(dpy); XCloseDisplay(dpy); return true; } bool SetKeyLockStatus(bool caps, bool num, bool scroll) { _XDisplay *dpy; if (!(dpy = XOpenDisplay(NULL))) return false; bool oldcaps, oldnum, oldscroll; if (!GetKeyLockStatus0(oldcaps, oldnum, oldscroll, dpy)) { XCloseDisplay(dpy); return false; } if (caps != oldcaps) PressKeyVK(XK_Caps_Lock, dpy); if (num != oldnum) PressKeyVK(XK_Num_Lock, dpy); if (scroll != oldscroll) PressKeyVK(XK_Scroll_Lock, dpy); XFlush(dpy); XCloseDisplay(dpy); return true; } KeyCodes keyCodes[] = { "NUMPAD7", XK_KP_7, "BACK", XK_BackSpace, "NUMPAD8", XK_KP_8, "TAB", XK_Tab, "NUMPAD9", XK_KP_9, "RETURN", XK_Return, "MULTIPLY", XK_KP_Multiply, "SHIFT", XK_Shift_Lock, "ADD", XK_KP_Add, "CONTROL", XK_Control_L, "SEPARATOR", XK_KP_Separator,"MENU", XK_Super_L, "SUBTRACT", XK_KP_Subtract, "PAUSE", XK_Pause, "DECIMAL", XK_KP_Decimal, /*"CAPITAL", VK_CAPITAL,*/ "DIVIDE", XK_KP_Divide, "ESCAPE", XK_Escape, "F1", XK_F1, "SPACE", XK_KP_Space, "F2", XK_F2, "END", XK_End, "F3", XK_F3, "HOME", XK_Home, "F4", XK_F4, "LEFT", XK_Left, "F5", XK_F5, "UP", XK_Up, "F6", XK_F6, "RIGHT", XK_Right, "F7", XK_F7, "DOWN", XK_Down, "F8", XK_F8, "PRINT", XK_Sys_Req, "F9", XK_F9, /*"SNAPSHOT", VK_SNAPSHOT,*/ "F10", XK_F10, "INSERT", XK_Insert, "F11", XK_F11, "DELETE", XK_Delete, "F12", XK_F12, "LWIN", XK_Meta_L, "NUMLOCK", XK_Num_Lock, "RWIN", XK_Meta_R, "SCROLL", XK_Scroll_Lock, "NUMPAD0", XK_KP_0, "LSHIFT", XK_Shift_L, "NUMPAD1", XK_KP_1, "RSHIFT", XK_Shift_R, "NUMPAD2", XK_KP_2, "LCONTROL", XK_Control_L, "NUMPAD3", XK_KP_3, "RCONTROL", XK_Control_R, "NUMPAD4", XK_KP_4, "LMENU", XK_Super_L, "NUMPAD5", XK_KP_5, "RMENU", XK_Super_R, "NUMPAD6", XK_KP_6, "PGUP", XK_Page_Up, "PGDOWN", XK_Page_Down, "CAPSLOCK", XK_Caps_Lock, "BACKSPACE",XK_BackSpace, "" }; void Mouse_LeftClick() { Mouse_LeftDown(); Mouse_LeftUp(); } void Mouse_RightClick() { Mouse_RightDown(); Mouse_RightUp(); } void Mouse_MiddleClick() { Mouse_MiddleDown(); Mouse_MiddleUp(); } void Mouse_LeftDblClick() { Mouse_LeftClick(); Mouse_LeftClick(); } void Mouse_MiddleDblClick() { Mouse_MiddleClick(); Mouse_MiddleClick(); } void Mouse_RightDblClick() { Mouse_RightClick(); Mouse_RightClick(); } int GetKeyCode(String key) { for (int i = 0; keyCodes[i].code != 0; ++i) if (keyCodes[i].key == key) return keyCodes[i].code; return 0; } void Keyb_SendKeys(String text, long finalDelay, long delayBetweenKeys) { Array virt; bool inKey = false; String key = ""; WString wtext(text); for (int i = 0; i < wtext.GetCount(); ++i) { bool vk = false; Sleep(delayBetweenKeys); wchar c = wtext[i]; if (c == '{') inKey = true; else if (c == '}') { if (key == "{") c = '{'; else { c = GetKeyCode(key); vk = true; } inKey = false; key = ""; } else if (inKey == 1) key.Cat(c); else if (c == '\n') { c = GetKeyCode("RETURN"); vk = true; } if (inKey == false) { if (!vk) PressKey(c); #if defined(PLATFORM_WIN32) || defined (PLATFORM_WIN64) else { PressKeyVK(c, true); virt.Add(c); } #endif } } #if defined(PLATFORM_WIN32) || defined (PLATFORM_WIN64) for (int i = 0; i < virt.GetCount(); ++i) PressKeyVK(virt[i], false, true); #endif Sleep(finalDelay); } #endif #endif END_UPP_NAMESPACE