Skip to content

Commit 3e2c016

Browse files
titusfortnerpujaganidiemol
authored
[java] allow setting a different keyboard or pointer for actions on input devices (#10213)
Co-authored-by: Puja Jagani <[email protected]> Co-authored-by: Diego Molina <[email protected]>
1 parent 1181c1c commit 3e2c016

6 files changed

Lines changed: 152 additions & 193 deletions

File tree

java/src/org/openqa/selenium/interactions/Actions.java

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.HashSet;
3636
import java.util.LinkedHashMap;
3737
import java.util.Map;
38+
import java.util.Objects;
3839
import java.util.Set;
3940
import java.util.function.IntConsumer;
4041
import java.util.logging.Logger;
@@ -55,8 +56,8 @@ public class Actions {
5556

5657
// W3C
5758
private final Map<InputSource, Sequence> sequences = new HashMap<>();
58-
private final PointerInput defaultMouse = new PointerInput(MOUSE, "default mouse");
59-
private final KeyInput defaultKeyboard = new KeyInput("default keyboard");
59+
private PointerInput activePointer;
60+
private KeyInput activeKeyboard;
6061

6162
// JSON-wire protocol
6263
private final Keyboard jsonKeyboard;
@@ -90,7 +91,7 @@ public Actions keyDown(CharSequence key) {
9091
if (isBuildingActions()) {
9192
action.addAction(new KeyDownAction(jsonKeyboard, jsonMouse, asKeys(key)));
9293
}
93-
return addKeyAction(key, codePoint -> tick(defaultKeyboard.createKeyDown(codePoint)));
94+
return addKeyAction(key, codePoint -> tick(getActiveKeyboard().createKeyDown(codePoint)));
9495
}
9596

9697
/**
@@ -108,7 +109,7 @@ public Actions keyDown(WebElement target, CharSequence key) {
108109
action.addAction(new KeyDownAction(jsonKeyboard, jsonMouse, (Locatable) target, asKeys(key)));
109110
}
110111
return focusInTicks(target)
111-
.addKeyAction(key, codepoint -> tick(defaultKeyboard.createKeyDown(codepoint)));
112+
.addKeyAction(key, codepoint -> tick(getActiveKeyboard().createKeyDown(codepoint)));
112113
}
113114

114115
/**
@@ -123,7 +124,7 @@ public Actions keyUp(CharSequence key) {
123124
action.addAction(new KeyUpAction(jsonKeyboard, jsonMouse, asKeys(key)));
124125
}
125126

126-
return addKeyAction(key, codePoint -> tick(defaultKeyboard.createKeyUp(codePoint)));
127+
return addKeyAction(key, codePoint -> tick(getActiveKeyboard().createKeyUp(codePoint)));
127128
}
128129

129130
/**
@@ -141,7 +142,7 @@ public Actions keyUp(WebElement target, CharSequence key) {
141142
}
142143

143144
return focusInTicks(target)
144-
.addKeyAction(key, codePoint -> tick(defaultKeyboard.createKeyUp(codePoint)));
145+
.addKeyAction(key, codePoint -> tick(getActiveKeyboard().createKeyUp(codePoint)));
145146
}
146147

147148
/**
@@ -205,8 +206,8 @@ private Actions sendKeysInTicks(CharSequence... keys) {
205206
}
206207
for (CharSequence key : keys) {
207208
key.codePoints().forEach(codePoint -> {
208-
tick(defaultKeyboard.createKeyDown(codePoint));
209-
tick(defaultKeyboard.createKeyUp(codePoint));
209+
tick(getActiveKeyboard().createKeyDown(codePoint));
210+
tick(getActiveKeyboard().createKeyUp(codePoint));
210211
});
211212
}
212213
return this;
@@ -236,7 +237,7 @@ public Actions clickAndHold(WebElement target) {
236237
action.addAction(new ClickAndHoldAction(jsonMouse, (Locatable) target));
237238
}
238239
return moveInTicks(target, 0, 0)
239-
.tick(defaultMouse.createPointerDown(LEFT.asArg()));
240+
.tick(getActivePointer().createPointerDown(LEFT.asArg()));
240241
}
241242

242243
/**
@@ -248,7 +249,7 @@ public Actions clickAndHold() {
248249
action.addAction(new ClickAndHoldAction(jsonMouse, null));
249250
}
250251

251-
return tick(defaultMouse.createPointerDown(LEFT.asArg()));
252+
return tick(getActivePointer().createPointerDown(LEFT.asArg()));
252253
}
253254

254255
/**
@@ -267,7 +268,7 @@ public Actions release(WebElement target) {
267268
action.addAction(new ButtonReleaseAction(jsonMouse, (Locatable) target));
268269
}
269270

270-
return moveInTicks(target, 0, 0).tick(defaultMouse.createPointerUp(LEFT.asArg()));
271+
return moveInTicks(target, 0, 0).tick(getActivePointer().createPointerUp(LEFT.asArg()));
271272
}
272273

273274
/**
@@ -280,7 +281,7 @@ public Actions release() {
280281
action.addAction(new ButtonReleaseAction(jsonMouse, null));
281282
}
282283

283-
return tick(defaultMouse.createPointerUp(Button.LEFT.asArg()));
284+
return tick(getActivePointer().createPointerUp(Button.LEFT.asArg()));
284285
}
285286

286287
/**
@@ -313,8 +314,8 @@ public Actions click() {
313314
}
314315

315316
private Actions clickInTicks(PointerInput.MouseButton button) {
316-
tick(defaultMouse.createPointerDown(button.asArg()));
317-
tick(defaultMouse.createPointerUp(button.asArg()));
317+
tick(getActivePointer().createPointerDown(button.asArg()));
318+
tick(getActivePointer().createPointerUp(button.asArg()));
318319
return this;
319320
}
320321

@@ -386,7 +387,7 @@ public Actions moveToElement(WebElement target, int xOffset, int yOffset) {
386387
}
387388

388389
private Actions moveInTicks(WebElement target, int xOffset, int yOffset) {
389-
return tick(defaultMouse.createPointerMove(
390+
return tick(getActivePointer().createPointerMove(
390391
Duration.ofMillis(100),
391392
Origin.fromElement(target),
392393
xOffset,
@@ -409,7 +410,7 @@ public Actions moveByOffset(int xOffset, int yOffset) {
409410
}
410411

411412
return tick(
412-
defaultMouse.createPointerMove(Duration.ofMillis(200), Origin.pointer(), xOffset, yOffset));
413+
getActivePointer().createPointerMove(Duration.ofMillis(200), Origin.pointer(), xOffset, yOffset));
413414
}
414415

415416
/**
@@ -454,9 +455,9 @@ public Actions dragAndDrop(WebElement source, WebElement target) {
454455
}
455456

456457
return moveInTicks(source, 0, 0)
457-
.tick(defaultMouse.createPointerDown(LEFT.asArg()))
458+
.tick(getActivePointer().createPointerDown(LEFT.asArg()))
458459
.moveInTicks(target, 0, 0)
459-
.tick(defaultMouse.createPointerUp(LEFT.asArg()));
460+
.tick(getActivePointer().createPointerUp(LEFT.asArg()));
460461
}
461462

462463
/**
@@ -476,9 +477,9 @@ public Actions dragAndDropBy(WebElement source, int xOffset, int yOffset) {
476477
}
477478

478479
return moveInTicks(source, 0, 0)
479-
.tick(defaultMouse.createPointerDown(LEFT.asArg()))
480-
.tick(defaultMouse.createPointerMove(Duration.ofMillis(250), Origin.pointer(), xOffset, yOffset))
481-
.tick(defaultMouse.createPointerUp(LEFT.asArg()));
480+
.tick(getActivePointer().createPointerDown(LEFT.asArg()))
481+
.tick(getActivePointer().createPointerMove(Duration.ofMillis(250), Origin.pointer(), xOffset, yOffset))
482+
.tick(getActivePointer().createPointerUp(LEFT.asArg()));
482483
}
483484

484485
/**
@@ -492,7 +493,7 @@ public Actions pause(long pause) {
492493
action.addAction(new PauseAction(pause));
493494
}
494495

495-
return tick(new Pause(defaultMouse, Duration.ofMillis(pause)));
496+
return tick(new Pause(getActivePointer(), Duration.ofMillis(pause)));
496497
}
497498

498499
public Actions pause(Duration duration) {
@@ -501,7 +502,7 @@ public Actions pause(Duration duration) {
501502
action.addAction(new PauseAction(duration.toMillis()));
502503
}
503504

504-
return tick(new Pause(defaultMouse, duration));
505+
return tick(new Pause(getActivePointer(), duration));
505506
}
506507

507508
public Actions tick(Interaction... actions) {
@@ -538,7 +539,7 @@ public Actions tick(Action action) {
538539
}
539540

540541
for (Interaction interaction :
541-
((IsInteraction) action).asInteractions(defaultMouse, defaultKeyboard)) {
542+
((IsInteraction) action).asInteractions(getActivePointer(), getActiveKeyboard())) {
542543
tick(interaction);
543544
}
544545

@@ -549,6 +550,44 @@ public Actions tick(Action action) {
549550
return this;
550551
}
551552

553+
public Actions setActiveKeyboard(String name) {
554+
InputSource inputSource = sequences.keySet().stream().filter(input -> Objects.equals(input.getName(), name)).findFirst().orElse(null);
555+
556+
if (inputSource == null) {
557+
this.activeKeyboard = new KeyInput(name);
558+
} else {
559+
this.activeKeyboard = (KeyInput) inputSource;
560+
}
561+
562+
return this;
563+
}
564+
565+
public Actions setActivePointer(PointerInput.Kind kind, String name) {
566+
InputSource inputSource = sequences.keySet().stream().filter(input -> Objects.equals(input.getName(), name)).findFirst().orElse(null);
567+
568+
if (inputSource == null) {
569+
this.activePointer = new PointerInput(kind, name);
570+
} else {
571+
this.activePointer = (PointerInput) inputSource;
572+
}
573+
574+
return this;
575+
}
576+
577+
public KeyInput getActiveKeyboard() {
578+
if (this.activeKeyboard == null) {
579+
setActiveKeyboard("default keyboard");
580+
}
581+
return this.activeKeyboard;
582+
}
583+
584+
public PointerInput getActivePointer() {
585+
if (this.activePointer == null) {
586+
setActivePointer(PointerInput.Kind.MOUSE, "default mouse");
587+
}
588+
return this.activePointer;
589+
}
590+
552591
/**
553592
* Generates a composite action containing all actions so far, ready to be performed (and
554593
* resets the internal builder state, so subsequent calls to this method will contain fresh

java/src/org/openqa/selenium/interactions/InputSource.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@
2323
*/
2424
public interface InputSource {
2525
SourceType getInputType();
26+
String getName();
2627
}

java/src/org/openqa/selenium/interactions/KeyInput.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public KeyInput(String name) {
3333
this.name = Optional.ofNullable(name).orElse(UUID.randomUUID().toString());
3434
}
3535

36+
@Override
37+
public String getName() {
38+
return this.name;
39+
}
40+
3641
@Override
3742
public SourceType getInputType() {
3843
return SourceType.KEY;

java/src/org/openqa/selenium/interactions/PointerInput.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public PointerInput(Kind kind, String name) {
4343
this.name = Optional.ofNullable(name).orElse(UUID.randomUUID().toString());
4444
}
4545

46+
@Override
47+
public String getName() {
48+
return this.name;
49+
}
50+
4651
@Override
4752
public SourceType getInputType() {
4853
return SourceType.POINTER;

java/test/org/openqa/selenium/interactions/CombinedInputActionsTest.java

Lines changed: 23 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,11 @@
4343
import org.openqa.selenium.Point;
4444
import org.openqa.selenium.WaitingConditions;
4545
import org.openqa.selenium.WebElement;
46-
import org.openqa.selenium.remote.RemoteWebDriver;
4746
import org.openqa.selenium.testing.Ignore;
4847
import org.openqa.selenium.testing.JUnit4TestBase;
4948
import org.openqa.selenium.testing.NotYetImplemented;
5049
import org.openqa.selenium.testing.SwitchToTopAfterTest;
5150

52-
import java.time.Duration;
53-
import java.util.Arrays;
5451
import java.util.List;
5552

5653
/**
@@ -119,40 +116,16 @@ public void testMultipleInputs() {
119116

120117
List<WebElement> options = driver.findElements(By.tagName("option"));
121118

122-
PointerInput defaultPen = new PointerInput(PointerInput.Kind.PEN, "default pen");
123-
Sequence actionListPen = new Sequence(defaultPen, 0)
124-
.addAction(defaultPen.createPointerMove(Duration.ZERO, PointerInput.Origin.fromElement(options.get(1)), 0, 0))
125-
.addAction(defaultPen.createPointerDown(0))
126-
.addAction(defaultPen.createPointerUp(0))
127-
.addAction(new Pause(defaultPen, Duration.ZERO))
128-
.addAction(new Pause(defaultPen, Duration.ZERO))
129-
.addAction(new Pause(defaultPen, Duration.ZERO))
130-
.addAction(new Pause(defaultPen, Duration.ZERO))
131-
.addAction(new Pause(defaultPen, Duration.ZERO));
132-
133-
PointerInput defaultMouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse");
134-
Sequence actionListMouse = new Sequence(defaultMouse, 0)
135-
.addAction(new Pause(defaultPen, Duration.ZERO))
136-
.addAction(new Pause(defaultPen, Duration.ZERO))
137-
.addAction(new Pause(defaultPen, Duration.ZERO))
138-
.addAction(new Pause(defaultMouse, Duration.ZERO))
139-
.addAction(defaultMouse.createPointerMove(Duration.ZERO, PointerInput.Origin.fromElement(options.get(3)), 0, 0))
140-
.addAction(defaultMouse.createPointerDown(0))
141-
.addAction(defaultMouse.createPointerUp(0))
142-
.addAction(new Pause(defaultMouse, Duration.ZERO));
143-
144-
KeyInput defaultKeyboard = new KeyInput("default keyboard");
145-
Sequence actionListKeyboard = new Sequence(defaultKeyboard, 0)
146-
.addAction(new Pause(defaultPen, Duration.ZERO))
147-
.addAction(new Pause(defaultPen, Duration.ZERO))
148-
.addAction(new Pause(defaultPen, Duration.ZERO))
149-
.addAction(defaultKeyboard.createKeyDown(Keys.SHIFT.getCodePoint()))
150-
.addAction(new Pause(defaultPen, Duration.ZERO))
151-
.addAction(new Pause(defaultPen, Duration.ZERO))
152-
.addAction(new Pause(defaultPen, Duration.ZERO))
153-
.addAction(defaultKeyboard.createKeyUp(Keys.SHIFT.getCodePoint()));
154-
155-
((RemoteWebDriver) driver).perform(Arrays.asList(actionListKeyboard, actionListPen, actionListMouse));
119+
Actions actions = new Actions(driver);
120+
Action selectThreeOptions = actions.setActivePointer(PointerInput.Kind.PEN, "default pen")
121+
.keyDown(Keys.SHIFT)
122+
.click(options.get(1))
123+
.setActivePointer(PointerInput.Kind.MOUSE, "default mouse")
124+
.click(options.get(3))
125+
.keyUp(Keys.SHIFT)
126+
.build();
127+
128+
selectThreeOptions.perform();
156129

157130
WebElement showButton = driver.findElement(By.name("showselected"));
158131
showButton.click();
@@ -236,49 +209,19 @@ public void testControlClickingWithMultiplePointers() {
236209

237210
List<WebElement> listItems = driver.findElements(By.tagName("li"));
238211

239-
PointerInput defaultPen = new PointerInput(PointerInput.Kind.PEN, "default pen");
240-
Sequence actionListPen = new Sequence(defaultPen, 0)
241-
.addAction(new Pause(defaultPen, Duration.ZERO))
242-
.addAction(defaultPen.createPointerMove(Duration.ZERO, PointerInput.Origin.fromElement(listItems.get(1)), 0, 0))
243-
.addAction(defaultPen.createPointerDown(0))
244-
.addAction(defaultPen.createPointerUp(0))
245-
.addAction(new Pause(defaultPen, Duration.ZERO))
246-
.addAction(new Pause(defaultPen, Duration.ZERO))
247-
.addAction(new Pause(defaultPen, Duration.ZERO))
248-
.addAction(defaultPen.createPointerMove(Duration.ZERO, PointerInput.Origin.fromElement(listItems.get(3)), 0, 0))
249-
.addAction(defaultPen.createPointerDown(0))
250-
.addAction(defaultPen.createPointerUp(0))
251-
.addAction(new Pause(defaultPen, Duration.ZERO));
252-
253-
PointerInput defaultMouse = new PointerInput(PointerInput.Kind.MOUSE, "default mouse");
254-
Sequence actionListMouse = new Sequence(defaultMouse, 0)
255-
.addAction(new Pause(defaultMouse, Duration.ZERO))
256-
.addAction(new Pause(defaultMouse, Duration.ZERO))
257-
.addAction(new Pause(defaultMouse, Duration.ZERO))
258-
.addAction(new Pause(defaultMouse, Duration.ZERO))
259-
.addAction(defaultMouse.createPointerMove(Duration.ZERO, PointerInput.Origin.fromElement(listItems.get(5)), 0, 0))
260-
.addAction(defaultMouse.createPointerDown(0))
261-
.addAction(defaultMouse.createPointerUp(0))
262-
.addAction(new Pause(defaultMouse, Duration.ZERO))
263-
.addAction(new Pause(defaultMouse, Duration.ZERO))
264-
.addAction(new Pause(defaultMouse, Duration.ZERO))
265-
.addAction(new Pause(defaultMouse, Duration.ZERO));
266-
267-
KeyInput defaultKeyboard = new KeyInput("default keyboard");
268-
Sequence actionListKeyboard = new Sequence(defaultKeyboard, 0)
269-
.addAction(defaultKeyboard.createKeyDown(key.getCodePoint()))
270-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
271-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
272-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
273-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
274-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
275-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
276-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
277-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
278-
.addAction(new Pause(defaultKeyboard, Duration.ZERO))
279-
.addAction(defaultKeyboard.createKeyUp(key.getCodePoint()));
280-
281-
((RemoteWebDriver) driver).perform(Arrays.asList(actionListKeyboard, actionListPen, actionListMouse));
212+
Actions actions = new Actions(driver);
213+
Action selectThreeItems = actions
214+
.keyDown(key)
215+
.setActivePointer(PointerInput.Kind.PEN, "default pen")
216+
.click(listItems.get(1))
217+
.setActivePointer(PointerInput.Kind.MOUSE, "default mouse")
218+
.click(listItems.get(3))
219+
.setActivePointer(PointerInput.Kind.PEN, "default pen")
220+
.click(listItems.get(5))
221+
.keyUp(key)
222+
.build();
223+
224+
selectThreeItems.perform();
282225

283226
assertThat(reportingElement.getText()).isEqualTo("#item2 #item4 #item6");
284227
}

0 commit comments

Comments
 (0)