octalmage / robotjs

Node.js Desktop Automation.
http://robotjs.io
MIT License
12.37k stars 959 forks source link

Keyboard modifiers remain pressed down after calling keyTap or keyToggle #219

Open kalharbi opened 8 years ago

kalharbi commented 8 years ago

Passing a modifier (shift/alt) in keyTap() or keyToggle() results in keeping the modifier down for any subsequent keyboard API call.

Example:

const robot = require('robotjs');
robot.moveMouseSmooth(70, 130);
robot.mouseClick();
robot.keyTap('a', 'shift');
robot.typeString('bc');

Web listener:

<body>
  <input type="text" id= "input-1">
</body>
<script>
  document.getElementById('input-1').onkeydown = function(e) {
    const msg = "Key Pressed: " + e.key + "\n"
    + "SHIFT?: " + e.shiftKey + "\n"
    + "ALT?: " + e.altKey + "\n";
    console.log(msg);
  }
</script>

Output:

Key Pressed: A SHIFT?: true ALT?: false +++++++++++++ Key Pressed: b SHIFT?: true ALT?: false +++++++++++++ Key Pressed: c SHIFT?: true ALT?: false

This was on OSX 10.10, node version 6, robotjs version 0.4.4

octalmage commented 8 years ago

Thanks for the report! This is similar to #208. It should be pretty easy to resolve, I'll look into it!

jonaslund commented 8 years ago

Is there a timeline for this one?

octalmage commented 8 years ago

I've been busy and haven't been able to look into it yet, but you should be able to explicitly "up" the modifier to work around this. I'll try to look into it this weekend.

jonaslund commented 8 years ago

Despite triggering

robot.keyToggle("s", "down", ["shift", "alt"]);

the keys still become 'sticky' even after triggering

robot.keyToggle("s", "up", ["shift", "alt"]);    

so a fix on this issue would be super

octalmage commented 8 years ago

How about triggering shift and alt up like so:

robot.keyToggle("shift", "up");

When I was originally looking into this I thought this would resolve it.

jonaslund commented 8 years ago

Will check and update

waylaidwanderer commented 8 years ago

@octalmage I'm using Windows 10 and am experiencing the same or similar issue. Seems like whatever key I press with either keyTap or keyToggle is held down until I physically press the same key again.

For example, in an application I'm working with, pressing Enter brings up the chat box. Pressing enter again closes it. If I use the following code, this is what happens:

robot.keyTap('enter'); // chat box opens
setTimeout(function() {
    robot.keyTap('enter'); // chat box closes
}, 10);

However if I physically press enter, the chat box will stay closed until I press it one more time.

The application also allows you to draw pictures by holding control and click-dragging your mouse. If I use the following code, this is what happens:

robot.keyTap('enter'); // chat box enters
    setTimeout(function() {
        robot.keyTap('v', 'control'); // text is pasted
        setTimeout(function() {
            robot.keyTap('enter'); // message is sent and chat box is closed
        }, 10);
}, 10);

However this time I am able to draw pictures without holding down control, as if it's still being held down. This is fixed if I physically press the control key. Adding robot.keyToggle('control', up') like you suggested (I tried it with different timeouts) does not fix it.

waylaidwanderer commented 8 years ago

@octalmage Could you please look into this issue?

codycuellar commented 5 years ago

We've been running into this issue lately and seems we need to spam the modifier key after each keyTap with a modifier just for safety. Is there anyone looking into fixing this?

nooikko commented 4 years ago

I seem to be experiencing this issue as well on windows. Any chance we can get this looked at?

Here is my code:

const command = "6";
robot.keyTap(command, ['control']);
L1cardo commented 4 years ago

Same issue here on win10 ! I must physically press the key after robotjs, or it will remaining pressed down!

L1cardo commented 4 years ago

It’s been almost 4 years! Any solution?

lino-levan commented 4 years ago

Hey guys, I know its been 4 years but I have created a makeshift solution. I believe robot.js has been abandoned but the work-around for it is something like this:

let m = ["control"] //put your modifiers in here
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"down");
}
robot.keyToggle(key,"up");//up or down here, you can also use keyTap
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"up");
}

I really hope octalmage comes back to this project.

nooikko commented 4 years ago

Hey guys, I know its been 4 years but I have created a makeshift solution. I believe robot.js has been abandoned but the work-around for it is something like this:

let m = ["control"] //put your modifiers in here
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"down");
}
robot.keyToggle(key,"up");//up or down here, you can also use keyTap
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"up");
}

I really hope octalmage comes back to this project.

I made it into a quick usable function

/**
 * Attempts to fix RobotJS messed up keyTap function
 * @param {Array} modifiers - The modifiers that need to be used during the key tap
 * @param {String} key - The key that should be pressed 
 */
function keyTap(modifiers = [], key = '') {
  modifiers.forEach(mod => robot.keyToggle(mod, 'down'));
  robot.keyToggle(key, 'up');
  modifiers.forEach(mod => robot.keyToggle(mod, 'up'));
}
lino-levan commented 4 years ago

Nice, that is really clean actually. I think that is going to be the solution for a while.

L1cardo commented 4 years ago

Hey guys, I know its been 4 years but I have created a makeshift solution. I believe robot.js has been abandoned but the work-around for it is something like this:


let m = ["control"] //put your modifiers in here

for(let i =0;i<m.length;i++){

    robot.keyToggle(m[i],"down");

}

robot.keyToggle(key,"up");//up or down here, you can also use keyTap

for(let i =0;i<m.length;i++){

    robot.keyToggle(m[i],"up");

}

I really hope octalmage comes back to this project.

Thanks for your solution! You said robotjs has been abandoned, what do you mean? If this has been abandoned, is there any js automation else other than robotjs?

nooikko commented 4 years ago

Thanks for your solution! You said robotjs has been abandoned, what do you mean? If this has been abandoned, is there any js automation else other than robotjs?

There's really nothing better out there. As far as "abandoned", well that update was 2 months ago. Generally if issues have stopped being address and there's no more updates, something is considered abandoned. Depending on the license someone could fork it and try to maintain it, but it's a hell of a code base, and most people use it for other types of automations so there's not really anyone interested in doing that.

L1cardo commented 4 years ago

Hey guys, I know its been 4 years but I have created a makeshift solution. I believe robot.js has been abandoned but the work-around for it is something like this:

let m = ["control"] //put your modifiers in here
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"down");
}
robot.keyToggle(key,"up");//up or down here, you can also use keyTap
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"up");
}

I really hope octalmage comes back to this project.

I made it into a quick usable function

/**
 * Attempts to fix RobotJS messed up keyTap function
 * @param {Array} modifiers - The modifiers that need to be used during the key tap
 * @param {String} key - The key that should be pressed 
 */
function keyTap(modifiers = [], key = '') {
  modifiers.forEach(mod => robot.keyToggle(mod, 'down'));
  robot.keyToggle(key, 'up');
  modifiers.forEach(mod => robot.keyToggle(mod, 'up'));
}

'shift' key still remains pressed in league of legends, I quit :(

michael-mcmasters commented 2 years ago

Hey guys, I know its been 4 years but I have created a makeshift solution. I believe robot.js has been abandoned but the work-around for it is something like this:

let m = ["control"] //put your modifiers in here
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"down");
}
robot.keyToggle(key,"up");//up or down here, you can also use keyTap
for(let i =0;i<m.length;i++){
    robot.keyToggle(m[i],"up");
}

I really hope octalmage comes back to this project.

I made it into a quick usable function

/**
 * Attempts to fix RobotJS messed up keyTap function
 * @param {Array} modifiers - The modifiers that need to be used during the key tap
 * @param {String} key - The key that should be pressed 
 */
function keyTap(modifiers = [], key = '') {
  modifiers.forEach(mod => robot.keyToggle(mod, 'down'));
  robot.keyToggle(key, 'up');
  modifiers.forEach(mod => robot.keyToggle(mod, 'up'));
}

I was still having issues with that implementation, but this change seems to have fixed it.

function keyTap(key = '', modifiers = []) {
  robot.keyToggle(key, 'down', modifiers);
  robot.keyToggle(key, 'up', modifiers);                   // Let up modifier keys in same way they were pressed
  modifiers.forEach(mod => robot.keyToggle(mod, 'up'));    // Double check they are up
}
princefishthrower commented 9 months ago

@michael-mcmasters - another two years later :) amazing bug find here! Someone should really continue on work in this library... it'd be a shame to see it die completely... it might be something I take over for my company's (@fullstackcraftllc) product CodeVideo. I may just fork this and call it something like robotts, and start fixing some of these pesky bugs.