1

I'm creating an application on UNIX which uses the command xdotool to fake mouse/keyboard actions. The command works as expected, and the example line:

xdotool mousemove 20 50 && xdotool mousedown 1 && xdotool mouseup 1

moves the mouse and performs a simple click as expected.

However, when trying to implement a call to this command from a C program requires to split the command and insert a delay between both of them (mousemove, then wait, then mousedown && mouseup).

These are the relevant pieces of code involved:

Generation of the command:

button = button + 1;

std::string moveCommand = 
  "xdotool mousemove " 
  + std::to_string(realPosX) 
  + " " 
  + std::to_string(realPosY);

std::string btnStr = std::to_string(button);
std::string clickCommand = 
  "xdotool mousedown " 
  + btnStr 
  + " && xdotool mouseup " 
  + btnStr;

exec(moveCommand + " && " + clickCommand);
//std::this_thread::sleep_for(std::chrono::duration<double>(0.1));
//exec(clickCommand);

exec function:

std::string exec(const char * cmd) 
{
    /*
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);

    if (!pipe)
        {
            throw std::runtime_error("popen() failed!");
        }

    while (fgets(buffer.data(), 128, pipe.get()) != nullptr) 
        {
        result += buffer.data();
    }
    return result;
    */

    std::cout << cmd << std::endl;
    int retValue = system(cmd);

    if(retValue != 0)
    {
        std::cerr << "Command \"" << cmd << "\" exited with value " << retValue << std::endl;
    }

    return "";
}


std::string exec(const std::string & st)
{
    return exec(st.c_str());
}

So far I have tried:

  • Executing the commands separately using popen

  • Executing the commands together joined by && using popen

  • The same as previous, using system since I read it makes a blocking call to the command (Thinking that it could be the problem).

The only way it has work until now is by splitting the commands and putting a delay between both calls (as can be seen in the generation of command).

Without the delay, the mouse is moved, but the click has no effect. No error is returned from the execution.

As you can see in the exec() function, I print the command to screen, and then I run it manually to make sure the command is well-formed. The command run as expected on the shell.

I dont know if I am missing something when calling the popen()/system() functions that is causing this behaviour

Nadir
  • 1,799
  • 12
  • 20
  • 2
    On Linux, there is a `sleep` command which can be used with floating point values for sub-second times. I.e. `sleep 0.1` sleeps for a minimum of 100 ms. (Found it here: [Bash sleep in milliseconds](https://stackoverflow.com/a/32213322/7478597)) On other *ix systems, `sleep` may accept integer numbers as arguments only: [sleep (command)](https://en.wikipedia.org/wiki/Sleep_(command)). An alternative might be to split your commands and use [`std::this_thread::sleep_for()`](https://en.cppreference.com/w/cpp/thread/sleep_for). – Scheff's Cat Oct 18 '18 at 09:25
  • @Scheff Thanks for the advice. Im trying to be able to run the command without having to put any delay (as If I would type it in the shell). If in the end that cannot be solved, ill take a look into these functions. – Nadir Oct 18 '18 at 09:28
  • 1
    Sorry, I'm afraid I got you wrong. So, your actual question is Why do you have to make a delay between mouse move and mouse button press/release to become properly effective? May be, this might have to do with how X11 processes the generated events... – Scheff's Cat Oct 18 '18 at 10:33
  • @Scheff but why if I execute the commands altogether from the shelf it works and when I launch it from the program I created it requires to be split and a delay? – Nadir Oct 18 '18 at 10:51
  • I've thought about this too but with less result. My only idea: calling commands from interactive `bash` results in a different timing than calling them with `system()`. In other words: It works accidentally in `bash`. ;-) (I've no better excuse...) – Scheff's Cat Oct 18 '18 at 10:53

0 Answers0