INLINE MMPoint getMousePos() { #if defined(IS_MACOSX) CGEventRef event = CGEventCreate(NULL); CGPoint point = CGEventGetLocation(event); CFRelease(event); return MMPointFromCGPoint(point); #elif defined(USE_X11) int x, y; /* This is all we care about. Seriously. */ Window garb1, garb2; /* Why you can't specify NULL as a parameter */ int garb_x, garb_y; /* is beyond me. */ unsigned int more_garbage; Display *display = XGetMainDisplay(); XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2, &x, &y, &garb_x, &garb_y, &more_garbage); return MMPointMake(x, y); #elif defined(IS_WINDOWS) POINT point; GetCursorPos(&point); return MMPointFromPOINT(point); #endif }
/** * Move the mouse to a specific point. * @param point The coordinates to move the mouse to (x, y). */ void moveMouse(MMPoint point) { #if defined(IS_MACOSX) CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, CGPointFromMMPoint(point), kCGMouseButtonLeft); calculateDeltas(&move, point); CGEventPost(kCGSessionEventTap, move); CFRelease(move); #elif defined(USE_X11) Display *display = XGetMainDisplay(); XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y); XSync(display, false); #elif defined(IS_WINDOWS) //Mouse motion is now done using SendInput with MOUSEINPUT. We use Absolute mouse positioning #define MOUSE_COORD_TO_ABS(coord, width_or_height) (((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) point.x = MOUSE_COORD_TO_ABS(point.x, GetSystemMetrics(SM_CXSCREEN)); point.y = MOUSE_COORD_TO_ABS(point.y, GetSystemMetrics(SM_CYSCREEN)); INPUT mouseInput; mouseInput.type = INPUT_MOUSE; mouseInput.mi.dx = point.x; mouseInput.mi.dy = point.y; mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; mouseInput.mi.time = 0; //System will provide the timestamp mouseInput.mi.dwExtraInfo = 0; mouseInput.mi.mouseData = 0; SendInput(1, &mouseInput, sizeof(mouseInput)); #endif }
void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { #if defined(IS_MACOSX) CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, down); assert(keyEvent != NULL); CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp); CGEventSetFlags(keyEvent, flags); CGEventPost(kCGSessionEventTap, keyEvent); CFRelease(keyEvent); #elif defined(IS_WINDOWS) const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP; /* Parse modifier keys. */ if (flags & MOD_META) WIN32_KEY_EVENT_WAIT(K_META, dwFlags); if (flags & MOD_ALT) WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags); if (flags & MOD_CONTROL) WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags); if (flags & MOD_SHIFT) WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags); win32KeyEvent(code, dwFlags); #elif defined(USE_X11) Display *display = XGetMainDisplay(); const Bool is_press = down ? True : False; /* Just to be safe. */ /* Parse modifier keys. */ if (flags & MOD_META) X_KEY_EVENT_WAIT(display, K_META, is_press); if (flags & MOD_ALT) X_KEY_EVENT_WAIT(display, K_ALT, is_press); if (flags & MOD_CONTROL) X_KEY_EVENT_WAIT(display, K_CONTROL, is_press); if (flags & MOD_SHIFT) X_KEY_EVENT_WAIT(display, K_SHIFT, is_press); X_KEY_EVENT(display, code, is_press); #endif }
/** * Function used to scroll the screen in the required direction. * This uses the magnitude to scroll the required amount in the direction. * TODO Requires further fine tuning based on the requirements. */ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection) { /* Direction should only be considered based on the scrollDirection. This * Should not interfere. */ int cleanScrollMagnitude = abs(scrollMagnitude); if (!(scrollDirection == DIRECTION_UP || scrollDirection == DIRECTION_DOWN)) { return; } /* Set up the OS specific solution */ #if defined(__APPLE__) CGWheelCount wheel = 1; CGEventRef event; /* Make scroll magnitude negative if we're scrolling down. */ cleanScrollMagnitude = cleanScrollMagnitude * scrollDirection; event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine, wheel, cleanScrollMagnitude, 0); CGEventPost(kCGHIDEventTap, event); #elif defined(USE_X11) int x; int dir = 4; /* Button 4 is up, 5 is down. */ Display *display = XGetMainDisplay(); if (scrollDirection == DIRECTION_DOWN) { dir = 5; } for (x = 0; x < cleanScrollMagnitude; x++) { XTestFakeButtonEvent(display, dir, 1, CurrentTime); XTestFakeButtonEvent(display, dir, 0, CurrentTime); } XFlush(display); #elif defined(IS_WINDOWS) //FIXME: Need to figure out why this code doesn't work on Windows XP. /*INPUT mouseScrollInput; mouseScrollInput.type = INPUT_MOUSE; mouseScrollInput.mi.dx = 0; mouseScrollInput.mi.dy = 0; mouseScrollInput.mi.dwFlags = MOUSEEVENTF_WHEEL; mouseScrollInput.mi.time = 0; mouseScrollInput.mi.dwExtraInfo = 0; mouseScrollInput.mi.mouseData = WHEEL_DELTA * scrollDirection * cleanScrollMagnitude; SendInput(1, &mouseScrollInput, sizeof(mouseScrollInput));*/ #endif }
INLINE void toggleMouse(bool down, MMMouseButton button) { #if defined(IS_MACOSX) const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); const CGEventType mouseType = MMMouseToCGEventType(down, button); CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType, currentPos, (CGMouseButton)button); CGEventPost(kCGSessionEventTap, event); CFRelease(event); #elif defined(USE_X11) Display *display = XGetMainDisplay(); XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime); XFlush(display); #elif defined(IS_WINDOWS) mouse_event(MMMouseToMEventF(down, button), 0, 0, 0, 0); #endif }
INLINE void moveMouse(MMPoint point) { #if defined(IS_MACOSX) CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, CGPointFromMMPoint(point), 0); CGEventPost(kCGSessionEventTap, move); CFRelease(move); #elif defined(USE_X11) Display *display = XGetMainDisplay(); XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y); XFlush(display); #elif defined(IS_WINDOWS) point.x *= 0xFFFF / GetSystemMetrics(SM_CXSCREEN); point.y *= 0xFFFF / GetSystemMetrics(SM_CYSCREEN); mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, point.x, point.y, 0, 0); #endif }
/** * Move the mouse to a specific point. * @param point The coordinates to move the mouse to (x, y). */ void moveMouse(MMPoint point) { #if defined(IS_MACOSX) CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, CGPointFromMMPoint(point), 0); CGEventPost(kCGSessionEventTap, move); CFRelease(move); #elif defined(USE_X11) Display *display = XGetMainDisplay(); XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y); XFlush(display); #elif defined(IS_WINDOWS) #define MOUSE_COORD_TO_ABS(coord, width_or_height) (((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) point.x = MOUSE_COORD_TO_ABS(point.x, GetSystemMetrics(SM_CXSCREEN)); point.y = MOUSE_COORD_TO_ABS(point.y, GetSystemMetrics(SM_CYSCREEN)); mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, (DWORD)point.x, (DWORD)point.y, 0, 0); #endif }
void scrollMouse(int x, int y) { #if defined(IS_WINDOWS) // Fix for #97 https://github.com/octalmage/robotjs/issues/97, // C89 needs variables declared on top of functions (mouseScrollInput) INPUT mouseScrollInputH; INPUT mouseScrollInputV; #endif /* Direction should only be considered based on the scrollDirection. This * Should not interfere. */ /* Set up the OS specific solution */ #if defined(__APPLE__) CGEventRef event; event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x); CGEventPost(kCGHIDEventTap, event); CFRelease(event); #elif defined(USE_X11) /* X11 Mouse Button Numbering 1 = left button 2 = middle button (pressing the scroll wheel) 3 = right button 4 = turn scroll wheel up 5 = turn scroll wheel down 6 = push scroll wheel left 7 = push scroll wheel right 8 = 4th button (aka browser backward button) 9 = 5th button (aka browser forward button) */ int ydir = 4; // Button 4 is up, 5 is down. int xdir = 6; // Button 6 is left, 7 is right. Display *display = XGetMainDisplay(); if (y < 0){ ydir = 5; } if (x < 0){ xdir = 7; } int xi; int yi; for (xi = 0; xi < abs(x); xi++) { XTestFakeButtonEvent(display, xdir, 1, CurrentTime); XTestFakeButtonEvent(display, xdir, 0, CurrentTime); } for (yi = 0; yi < abs(y); yi++) { XTestFakeButtonEvent(display, ydir, 1, CurrentTime); XTestFakeButtonEvent(display, ydir, 0, CurrentTime); } XSync(display, false); #elif defined(IS_WINDOWS) mouseScrollInputH.type = INPUT_MOUSE; mouseScrollInputH.mi.dx = 0; mouseScrollInputH.mi.dy = 0; mouseScrollInputH.mi.dwFlags = MOUSEEVENTF_HWHEEL; mouseScrollInputH.mi.time = 0; mouseScrollInputH.mi.dwExtraInfo = 0; // Flip x to match other platforms. mouseScrollInputH.mi.mouseData = -x; mouseScrollInputV.type = INPUT_MOUSE; mouseScrollInputV.mi.dx = 0; mouseScrollInputV.mi.dy = 0; mouseScrollInputV.mi.dwFlags = MOUSEEVENTF_WHEEL; mouseScrollInputV.mi.time = 0; mouseScrollInputV.mi.dwExtraInfo = 0; mouseScrollInputV.mi.mouseData = y; SendInput(1, &mouseScrollInputH, sizeof(mouseScrollInputH)); SendInput(1, &mouseScrollInputV, sizeof(mouseScrollInputV)); #endif }