Add: add toogle error check and MultiClikck, optimize the code and api

This commit is contained in:
vcaesar 2026-01-18 05:45:38 -08:00
parent dafd29e5ea
commit 4c439be11f
2 changed files with 63 additions and 67 deletions

View file

@ -54,7 +54,6 @@
}
#elif defined(IS_WINDOWS)
DWORD MMMouseUpToMEventF(MMMouseButton button) {
if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTUP; }
if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTUP; }
@ -99,7 +98,6 @@ void moveMouse(MMPointInt32 point){
CGPointFromMMPointInt32(point), kCGMouseButtonLeft);
calculateDeltas(&move, point);
CGEventPost(kCGHIDEventTap, move);
CFRelease(move);
CFRelease(source);
@ -156,7 +154,7 @@ MMPointInt32 location() {
}
/* Press down a button, or release it. */
int toggleMouseErr(bool down, MMMouseButton button) {
int toggleMouse(bool down, MMMouseButton button) {
#if defined(IS_MACOSX)
const CGPoint currentPos = CGPointFromMMPointInt32(location());
const CGEventType mouseType = MMMouseToCGEventType(down, button);
@ -167,20 +165,17 @@ int toggleMouseErr(bool down, MMMouseButton button) {
CFRelease(source);
return (int)kCGErrorCannotComplete;
}
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
CFRelease(source);
return 0;
#elif defined(USE_X11)
Display *display = XGetMainDisplay();
Status status = XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime);
XSync(display, false);
return status ? 0 : 1;
#elif defined(IS_WINDOWS)
// mouse_event(MMMouseToMEventF(down, button), 0, 0, 0, 0);
INPUT mouseInput;
mouseInput.type = INPUT_MOUSE;
@ -195,26 +190,18 @@ int toggleMouseErr(bool down, MMMouseButton button) {
#endif
}
void toggleMouse(bool down, MMMouseButton button) {
toggleMouseErr(down, button);
}
int clickMouseErr(MMMouseButton button){
int err = toggleMouseErr(true, button);
int clickMouse(MMMouseButton button){
int err = toggleMouse(true, button);
if (err != 0) {
return err;
}
microsleep(5.0);
return toggleMouseErr(false, button);
return toggleMouse(false, button);
}
void clickMouse(MMMouseButton button){
clickMouseErr(button);
}
int doubleClickErr(MMMouseButton button){
/* Special function for sending double clicks, needed for MacOS. */
int doubleClick(MMMouseButton button){
#if defined(IS_MACOSX)
/* Double click for Mac. */
const CGPoint currentPos = CGPointFromMMPointInt32(location());
@ -223,7 +210,6 @@ int doubleClickErr(MMMouseButton button){
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef event = CGEventCreateMouseEvent(source, mouseTypeDown, currentPos, kCGMouseButtonLeft);
if (event == NULL) {
CFRelease(source);
return (int)kCGErrorCannotComplete;
@ -238,26 +224,18 @@ int doubleClickErr(MMMouseButton button){
CFRelease(event);
CFRelease(source);
return 0;
#else
/* Double click for everything else. */
int err = clickMouseErr(button);
int err = clickMouse(button);
if (err != 0) {
return err;
}
microsleep(200);
return clickMouseErr(button);
return clickMouse(button);
#endif
}
/* Special function for sending double clicks, needed for MacOS. */
void doubleClick(MMMouseButton button){
doubleClickErr(button);
}
/* Function used to scroll the screen in the required direction. */
void scrollMouseXY(int x, int y) {
#if defined(IS_WINDOWS)
@ -268,7 +246,7 @@ void scrollMouseXY(int x, int y) {
#if defined(IS_MACOSX)
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef event = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitPixel, 2, y, x);
CGEventRef event = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitPixel, 2, y, x);
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
@ -351,10 +329,10 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed)
velo_y /= veloDistance;
pos.x += floor(velo_x + 0.5);
pos.y += floor(velo_y + 0.5);
pos.y += floor(velo_y + 0.5);
/* Make sure we are in the screen boundaries! (Strange things will happen if we are not.) */
// if (pos.x >= screenSize.w || pos.y >= screenSize.h) {
/* Make sure we are in the screen boundaries! */
// if (pos.x >= screenSize.w || pos.y >= screenSize.h) {
// return false;
// }
moveMouse(pos);
@ -363,6 +341,5 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed)
microsleep(DEADBEEF_UNIFORM(lowSpeed, highSpeed));
// microsleep(DEADBEEF_UNIFORM(1.0, 3.0));
}
return true;
}

View file

@ -659,7 +659,7 @@ func Location() (int, int) {
return x, y
}
// Click click the mouse button
// ClickV1 click the mouse button
//
// robotgo.Click(button string, double bool)
//
@ -668,7 +668,7 @@ func Location() (int, int) {
// robotgo.Click() // default is left button
// robotgo.Click("right")
// robotgo.Click("wheelLeft")
func Click(args ...interface{}) {
func ClickV1(args ...interface{}) {
var (
button C.MMMouseButton = C.LEFT_BUTTON
double bool
@ -691,18 +691,19 @@ func Click(args ...interface{}) {
MilliSleep(MouseSleep)
}
// ClickE click the mouse button and return error
// Click click the mouse button and return error
//
// robotgo.ClickE(button string, double bool)
// robotgo.Click(button string, double bool)
//
// Examples:
//
// err := robotgo.ClickE() // default is left button
// err := robotgo.ClickE("right")
func ClickE(args ...interface{}) error {
// err := robotgo.Click() // default is left button
// err := robotgo.Click("right")
func Click(args ...interface{}) error {
var (
button C.MMMouseButton = C.LEFT_BUTTON
double bool
count int
)
if len(args) > 0 {
@ -720,30 +721,46 @@ func ClickE(args ...interface{}) error {
}
double = dbl
}
defer MilliSleep(MouseSleep)
if !double {
if code := C.toggleMouseErr(true, button); code != 0 {
return formatClickError(int(code), button, "down", false)
}
// match clickMouse timing
C.microsleep(C.double(5.0))
if code := C.toggleMouseErr(false, button); code != 0 {
return formatClickError(int(code), button, "up", false)
}
} else {
if code := C.doubleClickErr(button); code != 0 {
return formatClickError(int(code), button, "double", true)
}
if len(args) > 3 {
count = args[3].(int)
}
defer MilliSleep(MouseSleep)
if !double {
if code := C.toggleMouse(true, button); code != 0 {
return formatClickError(int(code), button, "down", count)
}
MilliSleep(5)
if code := C.toggleMouse(false, button); code != 0 {
return formatClickError(int(code), button, "up", count)
}
} else {
if code := C.doubleClick(button); code != 0 {
return formatClickError(int(code), button, "double", 2)
}
}
return nil
}
func formatClickError(code int, button C.MMMouseButton, stage string, double bool) error {
// MultiClick performs multiple clicks and returns error
//
// robotgo.MultiClick(button string, count int)
func MultiClick(button string, count int) error {
if count < 1 {
return nil
}
btn := CheckMouse(button)
defer MilliSleep(MouseSleep)
for i := 0; i < count; i++ {
if err := Click(btn, false, count); err != nil {
return err
}
}
return nil
}
func formatClickError(code int, button C.MMMouseButton, stage string, count int) error {
btnName := MouseButtonString(button)
detail := ""
@ -776,10 +793,9 @@ func formatClickError(code int, button C.MMMouseButton, stage string, double boo
}
if detail != "" {
return fmt.Errorf("click %s failed (%s, double=%v): %s (code=%d)", stage, btnName, double, detail, code)
return fmt.Errorf("click %s failed (%s, count=%d): %s (code=%d)", stage, btnName, count, detail, code)
}
return fmt.Errorf("click %s failed (%s, double=%v), code=%d", stage, btnName, double, code)
return fmt.Errorf("click %s failed (%s, count=%d), code=%d", stage, btnName, count, code)
}
// MoveClick move and click the mouse
@ -824,11 +840,14 @@ func Toggle(key ...interface{}) error {
if len(key) > 1 && key[1].(string) == "up" {
down = false
}
C.toggleMouse(C.bool(down), button)
code := C.toggleMouse(C.bool(down), button)
if code != 0 {
return formatClickError(int(code), button, "down", 1)
}
if len(key) > 2 {
MilliSleep(MouseSleep)
}
return nil
}