ultimatepp/bazaar/SysInfo/MouseKey.cpp
koldo 36dcb65a30 SysInfo: Solved CLANG warnings in Linux
git-svn-id: svn://ultimatepp.org/upp/trunk@14587 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2020-06-13 13:16:52 +00:00

477 lines
12 KiB
C++

#include "SysInfo_in.h"
namespace Upp {
struct KeyCodes {
String key;
int code;
};
#if defined(PLATFORM_WIN32) || defined (PLATFORM_WIN64)
Array <String> GetWinRegSubkeys(const String& key, HKEY base) {
HKEY hkey;
Array <String> 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(int xMove, int yMove, int64 windowId) {
int 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(int &x, int &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 */
"", 0
};
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(static_cast<BYTE>(keyVK), static_cast<BYTE>(nScan), nExtended, 0);
if (!hold)
keybd_event(static_cast<BYTE>(keyVK), static_cast<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(static_cast<BYTE>(nVK), static_cast<BYTE>(nScan), 0, 0);
if (!hold)
keybd_event(static_cast<BYTE>(nVK), static_cast<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);
}
}
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(int &x, int &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(int x, int y, int64 windowId) {
SetSysInfoX11ErrorHandler();
_XDisplay *dpy = XOpenDisplay (NULL);
if (!dpy) {
SetX11ErrorHandler();
return false;
}
int 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;
}
#endif
// libxtst-dev
#if defined(PLATFORM_POSIX) && !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);
}
}
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},
{"",0}
};
#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 <wchar> 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
}