Skip to content

Commit 8ba3f5a

Browse files
committed
improved handling of keyboard input
1 parent fe809ce commit 8ba3f5a

4 files changed

Lines changed: 209 additions & 132 deletions

File tree

Customer/src/main/java/de/openindex/support/customer/CustomerApplication.java

Lines changed: 17 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,11 @@
3030
import de.openindex.support.core.io.ScreenResponse;
3131
import de.openindex.support.core.io.ScreenTile;
3232
import de.openindex.support.core.io.SocketHandler;
33+
import de.openindex.support.customer.utils.Robot;
3334
import java.awt.AWTException;
3435
import java.awt.Desktop;
3536
import java.awt.GraphicsConfiguration;
3637
import java.awt.GraphicsDevice;
37-
import java.awt.Toolkit;
38-
import java.awt.datatransfer.Clipboard;
39-
import java.awt.datatransfer.DataFlavor;
40-
import java.awt.datatransfer.StringSelection;
4138
import java.awt.event.ActionEvent;
4239
import java.awt.event.ActionListener;
4340
import java.awt.event.KeyEvent;
@@ -63,6 +60,7 @@
6360
import javax.swing.UIManager;
6461
import org.apache.commons.io.FileUtils;
6562
import org.apache.commons.io.IOUtils;
63+
import org.apache.commons.lang3.CharUtils;
6664
import org.apache.commons.lang3.StringUtils;
6765
import org.apache.commons.lang3.SystemUtils;
6866
import org.slf4j.ILoggerFactory;
@@ -410,28 +408,17 @@ public void processReceivedObject(Serializable object) {
410408

411409
if (request.keyCode != KeyEvent.VK_UNDEFINED)
412410
robot.keyPress(request.keyCode);
413-
/*else if (request.keyChar != KeyEvent.CHAR_UNDEFINED) {
411+
else if (request.keyChar != KeyEvent.CHAR_UNDEFINED) {
414412
int code = KeyEvent.getExtendedKeyCodeForChar(request.keyChar);
415-
416-
//LOGGER.debug("special key pressed : " +
417-
request.keyChar + " / " +
418-
code + " / " +
419-
KeyEvent.getKeyText(code) + " / " +
420-
Character.isLetterOrDigit(request.keyChar)
421-
);
422-
423-
try {
424-
if (code != KeyEvent.VK_UNDEFINED) {
425-
//LOGGER.debug("> press");
413+
//LOGGER.debug("key pressed: " + request.keyChar + " / " + code + " / " + CharUtils.isAsciiPrintable(request.keyChar));
414+
if (CharUtils.isAsciiAlphanumeric(request.keyChar) && code != KeyEvent.VK_UNDEFINED) {
415+
try {
426416
robot.keyPress(code);
417+
} catch (IllegalArgumentException ex) {
418+
LOGGER.warn("Can't press key '" + request.keyChar + "' (" + code + "): " + ex.getLocalizedMessage());
427419
}
428-
} catch (IllegalArgumentException ex) {
429-
//LOGGER.debug("Can't press key " +
430-
"(" + request.keyChar + "): " +
431-
ex.getLocalizedMessage() + "!");
432420
}
433-
434-
}*/
421+
}
435422

436423
} else if (object instanceof KeyReleaseRequest) {
437424

@@ -441,29 +428,17 @@ public void processReceivedObject(Serializable object) {
441428
if (request.keyCode != KeyEvent.VK_UNDEFINED)
442429
robot.keyRelease(request.keyCode);
443430
else if (request.keyChar != KeyEvent.CHAR_UNDEFINED) {
444-
/*int code = KeyEvent.getExtendedKeyCodeForChar(request.keyChar);
445-
boolean doPaste = code == KeyEvent.VK_UNDEFINED
446-
|| !CharUtils.isAscii(request.keyChar);
447-
448-
//LOGGER.debug("special key released : " +
449-
request.keyChar + " / " +
450-
code + " / " +
451-
KeyEvent.getKeyText(code) + " / " +
452-
doPaste);
453-
454-
try {
455-
if (code != KeyEvent.VK_UNDEFINED) {
456-
//LOGGER.debug("> release");
431+
int code = KeyEvent.getExtendedKeyCodeForChar(request.keyChar);
432+
//LOGGER.debug("key released: " + request.keyChar + " / " + code + " / " + CharUtils.isAsciiPrintable(request.keyChar));
433+
if (robot.isPressed(code)) {
434+
try {
457435
robot.keyRelease(code);
436+
} catch (IllegalArgumentException ex) {
437+
LOGGER.warn("Can't release key '" + request.keyChar + "' (" + code + "): " + ex.getLocalizedMessage());
458438
}
459-
} catch (IllegalArgumentException ex) {
460-
//LOGGER.debug("Can't release key " +
461-
"(" + request.keyChar + "): " +
462-
ex.getLocalizedMessage() + "!");
463-
doPaste = true;
439+
} else {
440+
robot.printCharacter(request.keyChar);
464441
}
465-
if (doPaste) robot.printSpecialChar(request.keyChar);*/
466-
robot.printSpecialChar(request.keyChar);
467442
}
468443

469444
} else if (object instanceof MouseMoveRequest) {
@@ -515,76 +490,6 @@ public void stop() {
515490
}
516491
}
517492

518-
private static class Robot extends java.awt.Robot {
519-
private Robot(GraphicsDevice screen) throws AWTException {
520-
super(screen);
521-
//setAutoDelay(50);
522-
setAutoWaitForIdle(true);
523-
}
524-
525-
private void pasteText(String text) {
526-
//waitForIdle();
527-
528-
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
529-
String oldClipboardValue;
530-
try {
531-
oldClipboardValue = (String) clipboard.getData(DataFlavor.stringFlavor);
532-
} catch (Exception ex) {
533-
//LOGGER.warn("Can't read clipboard value!", ex);
534-
oldClipboardValue = StringUtils.EMPTY;
535-
}
536-
try {
537-
clipboard.setContents(new StringSelection(text), null);
538-
539-
if (SystemUtils.IS_OS_MAC_OSX)
540-
keyPress(KeyEvent.VK_META);
541-
else
542-
keyPress(KeyEvent.VK_CONTROL);
543-
544-
keyPress(KeyEvent.VK_V);
545-
keyRelease(KeyEvent.VK_V);
546-
547-
if (SystemUtils.IS_OS_MAC_OSX)
548-
keyRelease(KeyEvent.VK_META);
549-
else
550-
keyRelease(KeyEvent.VK_CONTROL);
551-
} finally {
552-
if (oldClipboardValue != null)
553-
clipboard.setContents(new StringSelection(oldClipboardValue), null);
554-
}
555-
}
556-
557-
private void printSpecialChar(char code) {
558-
//waitForIdle();
559-
//LOGGER.debug("printSpecialChar: " + code);
560-
561-
// release modifier keys, that may have been set previously
562-
keyRelease(KeyEvent.VK_SHIFT);
563-
keyRelease(KeyEvent.VK_CONTROL);
564-
keyRelease(KeyEvent.VK_ALT);
565-
keyRelease(KeyEvent.VK_ALT_GRAPH);
566-
if (SystemUtils.IS_OS_MAC_OSX)
567-
keyRelease(KeyEvent.VK_META);
568-
569-
// paste the special character through the system clipboard
570-
pasteText(String.valueOf(code));
571-
572-
// emulate input of special characters
573-
//keyPress(KeyEvent.VK_ALT);
574-
//keyPress(KeyEvent.VK_NUMPAD0);
575-
//keyRelease(KeyEvent.VK_NUMPAD0);
576-
//String altCode = Integer.toString(code);
577-
//for (int i = 0; i < altCode.length(); i++) {
578-
// code = (char) (altCode.charAt(i) + '0');
579-
// //delay(20);//may be needed for certain applications
580-
// keyPress(code);
581-
// //delay(20);//uncomment if necessary
582-
// keyRelease(code);
583-
//}
584-
//keyRelease(KeyEvent.VK_ALT);
585-
}
586-
}
587-
588493
private static class ScreenShooter implements ActionListener, ResponseFactory {
589494
private final ScreenRequest request;
590495
private BufferedImage[] lastSlices = null;
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/*
2+
* Copyright 2015-2018 OpenIndex.de.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package de.openindex.support.customer.utils;
17+
18+
import java.awt.AWTException;
19+
import java.awt.GraphicsDevice;
20+
import java.awt.Toolkit;
21+
import java.awt.datatransfer.Clipboard;
22+
import java.awt.datatransfer.StringSelection;
23+
import java.awt.event.KeyEvent;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
import org.apache.commons.lang3.StringUtils;
27+
import org.apache.commons.lang3.SystemUtils;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
31+
/**
32+
* Extended robot for remote control.
33+
*
34+
* @author Andreas Rudolph
35+
*/
36+
@SuppressWarnings("WeakerAccess")
37+
public class Robot extends java.awt.Robot {
38+
private final static Logger LOGGER = LoggerFactory.getLogger(Robot.class);
39+
private final List<Integer> pressedKeys = new ArrayList<>();
40+
41+
public Robot(GraphicsDevice screen) throws AWTException {
42+
super(screen);
43+
//setAutoDelay(10);
44+
//setAutoWaitForIdle(true);
45+
}
46+
47+
public synchronized boolean isPressed(int code) {
48+
return pressedKeys.contains(code);
49+
}
50+
51+
@Override
52+
public synchronized void keyPress(int code) {
53+
super.keyPress(code);
54+
if (!pressedKeys.contains(code))
55+
pressedKeys.add(code);
56+
}
57+
58+
@Override
59+
public synchronized void keyRelease(int code) {
60+
super.keyRelease(code);
61+
pressedKeys.remove((Integer) code);
62+
}
63+
64+
public synchronized void pasteText(String text) {
65+
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
66+
67+
String oldClipboardValue = StringUtils.EMPTY;
68+
//String oldClipboardValue;
69+
//try {
70+
// oldClipboardValue = (String) clipboard.getData(DataFlavor.stringFlavor);
71+
//} catch (Exception ex) {
72+
// oldClipboardValue = StringUtils.EMPTY;
73+
//}
74+
75+
try {
76+
clipboard.setContents(new StringSelection(text), null);
77+
waitForIdle();
78+
setAutoDelay(25);
79+
80+
if (SystemUtils.IS_OS_MAC_OSX)
81+
keyPress(KeyEvent.VK_META);
82+
else
83+
keyPress(KeyEvent.VK_CONTROL);
84+
85+
keyPress(KeyEvent.VK_V);
86+
keyRelease(KeyEvent.VK_V);
87+
88+
if (SystemUtils.IS_OS_MAC_OSX)
89+
keyRelease(KeyEvent.VK_META);
90+
else
91+
keyRelease(KeyEvent.VK_CONTROL);
92+
} catch (Exception ex) {
93+
LOGGER.warn("Can't paste text!", ex);
94+
} finally {
95+
try {
96+
clipboard.setContents(new StringSelection(oldClipboardValue), null);
97+
} catch (Exception ex) {
98+
LOGGER.warn("Can't clear clipboard!", ex);
99+
}
100+
setAutoDelay(0);
101+
}
102+
}
103+
104+
public synchronized void printCharacter(char character) {
105+
//LOGGER.debug("printCharacter: " + character);
106+
waitForIdle();
107+
108+
// release keys, that may have been set previously
109+
List<Integer> oldPressedKeys = new ArrayList<>(pressedKeys);
110+
releasePressedKeys();
111+
112+
if (SystemUtils.IS_OS_WINDOWS) {
113+
// print character on Windows systems by typing ALT + unicode number
114+
keyPress(KeyEvent.VK_ALT);
115+
keyPress(KeyEvent.VK_NUMPAD0);
116+
keyRelease(KeyEvent.VK_NUMPAD0);
117+
String altCode = Integer.toString(character);
118+
for (int i = 0; i < altCode.length(); i++) {
119+
char code = (char) (altCode.charAt(i) + '0');
120+
//delay(20);//may be needed for certain applications
121+
keyPress(code);
122+
//delay(20);//uncomment if necessary
123+
keyRelease(code);
124+
}
125+
keyRelease(KeyEvent.VK_ALT);
126+
} else {
127+
// paste the character through the system clipboard
128+
pasteText(String.valueOf(character));
129+
}
130+
131+
// reset pressed keys
132+
releasePressedKeys();
133+
for (Integer code : oldPressedKeys) {
134+
keyPress(code);
135+
}
136+
}
137+
138+
public synchronized void releasePressedKeys() {
139+
for (Integer code : pressedKeys) {
140+
try {
141+
super.keyRelease(code);
142+
} catch (Exception ex) {
143+
LOGGER.warn("Can't release previously pressed key (" + code + ")!", ex);
144+
}
145+
}
146+
pressedKeys.clear();
147+
}
148+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2015-2018 OpenIndex.de.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Additional classes of the customer application.
19+
*
20+
* @author Andreas Rudolph
21+
*/
22+
package de.openindex.support.customer.utils;

0 commit comments

Comments
 (0)