diff --git a/bazaar/SysInfo/MouseKey_.cpp b/bazaar/SysInfo/MouseKey_.cpp new file mode 100644 index 000000000..79f0e4a7a --- /dev/null +++ b/bazaar/SysInfo/MouseKey_.cpp @@ -0,0 +1,535 @@ +#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 + #ifndef MAPVK_VK_TO_CHAR + #define MAPVK_VK_TO_CHAR 2 + #endif +// #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; +} + +// libxtst-dev +#if !defined(flagNO_XTEST) + +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); + } +} + +#endif + +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; +} + +#if !defined(flagNO_XTEST) + +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, + "" +}; +#endif + +#endif + +#if defined(PLATFORM_WIN32) || !defined(flagNO_XTEST) + +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 + +END_UPP_NAMESPACE \ No newline at end of file