You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2016/09/16 03:05:59 UTC

svn commit: r1760990 - in /openmeetings/application: branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/ branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/ trunk/ope...

Author: solomax
Date: Fri Sep 16 03:05:59 2016
New Revision: 1760990

URL: http://svn.apache.org/viewvc?rev=1760990&view=rev
Log:
[OPENMEETINGS-1468] Linux to Linux and Linux to Mac remote should work as expected

Modified:
    openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java
    openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java
    openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java
    openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java
    openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java
    openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java

Modified: openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java?rev=1760990&r1=1760989&r2=1760990&view=diff
==============================================================================
--- openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java (original)
+++ openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java Fri Sep 16 03:05:59 2016
@@ -19,24 +19,37 @@
 package org.apache.openmeetings.screenshare.job;
 
 import static java.lang.Boolean.TRUE;
+import static org.apache.openmeetings.screenshare.util.Util.getInt;
+import static org.slf4j.LoggerFactory.getLogger;
+import static javax.swing.KeyStroke.getKeyStroke;
+import static java.lang.Character.toUpperCase;
+
 import java.awt.event.KeyEvent;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import org.slf4j.Logger;
+import javax.swing.KeyStroke;
 
-import static org.apache.openmeetings.screenshare.util.Util.getInt;
-import static org.slf4j.LoggerFactory.getLogger;
+import org.apache.commons.lang3.CharUtils;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
 
 public class OmKeyEvent {
 	private static final Logger log = getLogger(OmKeyEvent.class);
 	private static final Map<Integer, Integer> KEY_MAP = new HashMap<>();
+	private static final Map<Character, Integer> CHAR_MAP = new HashMap<>();
+	private static final Set<Character> UNPRINTABLE = Collections.unmodifiableSet(Stream.of('§', 'ö', 'ä', 'ü', 'ß', 'Ö', 'Ä' , 'Ü').collect(Collectors.toSet()));
 	static {
 		KEY_MAP.put(13, KeyEvent.VK_ENTER);
 		KEY_MAP.put(16, 0);
 		KEY_MAP.put(20, KeyEvent.VK_CAPS_LOCK);
+		KEY_MAP.put(43, KeyEvent.VK_ADD); //normal + -> numpad + ????
 		KEY_MAP.put(46, KeyEvent.VK_DELETE);
 		KEY_MAP.put(110, KeyEvent.VK_DECIMAL);
 		KEY_MAP.put(186, KeyEvent.VK_SEMICOLON);
@@ -49,80 +62,86 @@ public class OmKeyEvent {
 		KEY_MAP.put(220, KeyEvent.VK_BACK_SLASH);
 		KEY_MAP.put(221, KeyEvent.VK_CLOSE_BRACKET);
 		KEY_MAP.put(222, KeyEvent.VK_QUOTE);
+		
+		CHAR_MAP.put(Character.valueOf('#'), KeyEvent.VK_NUMBER_SIGN);
+		CHAR_MAP.put(Character.valueOf('<'), KeyEvent.VK_LESS);
+		CHAR_MAP.put(Character.valueOf('.'), KeyEvent.VK_PERIOD);
+		CHAR_MAP.put(Character.valueOf(','), KeyEvent.VK_COMMA);
+		CHAR_MAP.put(Character.valueOf('-'), KeyEvent.VK_MINUS);
+		CHAR_MAP.put(Character.valueOf('='), KeyEvent.VK_EQUALS);
+		CHAR_MAP.put(Character.valueOf('['), KeyEvent.VK_OPEN_BRACKET);
+		CHAR_MAP.put(Character.valueOf(']'), KeyEvent.VK_CLOSE_BRACKET);
+		CHAR_MAP.put(Character.valueOf(';'), KeyEvent.VK_SEMICOLON);
+		CHAR_MAP.put(Character.valueOf('\''), KeyEvent.VK_QUOTE);
+		CHAR_MAP.put(Character.valueOf('\\'), KeyEvent.VK_BACK_SLASH);
+		CHAR_MAP.put(Character.valueOf('`'), KeyEvent.VK_BACK_QUOTE);
+		CHAR_MAP.put(Character.valueOf('/'), KeyEvent.VK_SLASH);
 	}
 	private boolean alt = false;
 	private boolean ctrl = false;
 	private boolean shift = false;
+	private int inKey = 0;
 	private int key = 0;
 	private char ch = 0;
 	
-	public OmKeyEvent(int key) {
-		this(key, false);
-	}
-
-	public OmKeyEvent(int key, boolean shift) {
-		this.key = key;
-		this.shift = shift;
-	}
-
 	public OmKeyEvent(Map<String, Object> obj) {
 		alt = TRUE.equals(obj.get("alt"));
 		ctrl = TRUE.equals(obj.get("ctrl"));
 		shift = TRUE.equals(obj.get("shift"));
 		ch = (char)getInt(obj, "char");
+		key = inKey = getInt(obj, "key");
 		Integer _key = null;
-		int key = getInt(obj, "key");
-		if (key == 0) {
-			if (ch == 61) {
-				this.key = KeyEvent.VK_EQUALS;
+		if (CharUtils.isAsciiPrintable(ch)) {
+			boolean alpha = Character.isAlphabetic(ch);
+			if (alpha) { // can't be combined due to different types
+				key = getKeyStroke(toUpperCase(ch), 0).getKeyCode();
+			} else {
+				key = getKeyStroke(Character.valueOf(ch), 0).getKeyCode();
+			}
+			if (key == 0) {
+				_key = CHAR_MAP.get(ch);
+				if (_key == null) {
+					// fallback
+					key = inKey;
+				}
+			}
+			if (!alpha && _key == null) {
+				_key = KEY_MAP.get(key);
 			}
 		} else {
 			_key = KEY_MAP.get(key);
-			this.key = _key == null ? key : _key;
-		}
-		log.debug("sequence:: shift {}, orig {} -> key {}, _key {}", shift, key, this.key, _key);
-	}
-
-	public int[] sequence() {
-		List<Integer> list = new ArrayList<>();
-		if (alt) {
-			list.add(KeyEvent.VK_ALT);
-		}
-		if (ctrl) {
-			list.add(KeyEvent.VK_CONTROL);
-		}
-		if (shift) {
-			list.add(KeyEvent.VK_SHIFT);
-		}
-		if (key != 0) {
-			list.add(key);
 		}
-		return list.stream().mapToInt(Integer::intValue).toArray();
+		this.key = _key == null ? key : _key;
+		log.debug("sequence:: shift {}, ch {}, orig {} -> key {}({}), map {}", shift, ch == 0 ? ' ' : ch, inKey, key, Integer.toHexString(key), _key);
 	}
 
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + key;
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj) {
-			return true;
-		}
-		if (obj == null) {
-			return false;
-		}
-		if (!(obj instanceof OmKeyEvent)) {
-			return false;
-		}
-		OmKeyEvent other = (OmKeyEvent) obj;
-		if (key != other.key) {
-			return false;
+	public void press(RemoteJob r) throws InterruptedException {
+		if (UNPRINTABLE.contains(ch)) {
+			if (SystemUtils.IS_OS_LINUX) {
+				r.press(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_U);
+				String hex = String.format("%04X", (int)ch);
+				log.debug("sequence:: hex {}", hex);
+				for (int i = 0; i < hex.length(); ++i) {
+					r.press(KeyStroke.getKeyStroke(toUpperCase(hex.charAt(i)), 0).getKeyCode());
+				}
+				r.press(KeyEvent.VK_ENTER);
+			}
+		} else {
+			List<Integer> list = new ArrayList<>();
+			if (shift) {
+				list.add(KeyEvent.VK_SHIFT);
+			}
+			if (alt) {
+				list.add(KeyEvent.VK_ALT);
+			}
+			if (ctrl) {
+				list.add(KeyEvent.VK_CONTROL);
+			}
+			if (key != 0) {
+				list.add(key);
+			}
+			log.debug("sequence:: list {}", list);
+			r.press(list.stream().mapToInt(Integer::intValue).toArray());
 		}
-		return true;
 	}
 }

Modified: openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java?rev=1760990&r1=1760989&r2=1760990&view=diff
==============================================================================
--- openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java (original)
+++ openmeetings/application/branches/3.1.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java Fri Sep 16 03:05:59 2016
@@ -42,6 +42,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.commons.lang3.SystemUtils;
 import org.apache.openmeetings.screenshare.Core;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.Job;
@@ -53,7 +54,6 @@ import org.slf4j.Logger;
 @DisallowConcurrentExecution
 public class RemoteJob implements Job {
 	private static final Logger log = getLogger(RemoteJob.class);
-	private static final boolean isWindows = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1;
 	public static final String CORE_KEY = "core";
 	private Robot robot = null;
 	
@@ -88,10 +88,10 @@ public class RemoteJob implements Job {
 					Point p = getCoordinates(obj);
 					robot.mouseMove(p.x, p.y);
 				} else if (action.equals("keyDown")) {
-					pressSequence(new OmKeyEvent(obj).sequence());
+					new OmKeyEvent(obj).press(this);
 				} else if (action.equals("paste")) {
 					String paste = obj.get("paste").toString();
-					pressSpecialSign(paste);
+					paste(paste);
 				} else if (action.equals("copy")) {
 					String paste = getHighlightedText();
 
@@ -119,7 +119,7 @@ public class RemoteJob implements Job {
 		}
 	}
 
-	private void pressSequence(int... codes) throws InterruptedException {
+	public void press(int... codes) throws InterruptedException {
 		for (int i = 0; i < codes.length; ++i) {
 			robot.keyPress(codes[i]);
 		}
@@ -130,12 +130,12 @@ public class RemoteJob implements Job {
 
 	private String getHighlightedText() {
 		try {
-			if (isWindows) {
-				// pressing STRG+C == copy
-				pressSequence(KeyEvent.VK_CONTROL, KeyEvent.VK_C);
-			} else {
+			if (SystemUtils.IS_OS_MAC) {
 				// Macintosh simulate Copy
-				pressSequence(157, 67);
+				press(157, 67);
+			} else {
+				// pressing CTRL+C == copy
+				press(KeyEvent.VK_CONTROL, KeyEvent.VK_C);
 			}
 			return getClipboardText();
 		} catch (Exception e) {
@@ -165,18 +165,18 @@ public class RemoteJob implements Job {
 		return "";
 	}
 
-	private void pressSpecialSign(String charValue) {
+	private void paste(String charValue) {
 		Clipboard clippy = getDefaultToolkit().getSystemClipboard();
 		try {
 			Transferable transferableText = new StringSelection(charValue);
 			clippy.setContents(transferableText, null);
 
-			if (isWindows) {
-				// pressing STRG+V == insert-mode
-				pressSequence(KeyEvent.VK_CONTROL, KeyEvent.VK_V);
-			} else {
+			if (SystemUtils.IS_OS_MAC) {
 				// Macintosh simulate Insert
-				pressSequence(157, 86);
+				press(157, 86);
+			} else {
+				// pressing CTRL+V == insert-mode
+				press(KeyEvent.VK_CONTROL, KeyEvent.VK_V);
 			}
 		} catch (Exception e) {
 			log.error("Unexpected exception while pressSpecialSign", e);

Modified: openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java?rev=1760990&r1=1760989&r2=1760990&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java Fri Sep 16 03:05:59 2016
@@ -19,24 +19,37 @@
 package org.apache.openmeetings.screenshare.job;
 
 import static java.lang.Boolean.TRUE;
+import static org.apache.openmeetings.screenshare.util.Util.getInt;
+import static org.slf4j.LoggerFactory.getLogger;
+import static javax.swing.KeyStroke.getKeyStroke;
+import static java.lang.Character.toUpperCase;
+
 import java.awt.event.KeyEvent;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import org.slf4j.Logger;
+import javax.swing.KeyStroke;
 
-import static org.apache.openmeetings.screenshare.util.Util.getInt;
-import static org.slf4j.LoggerFactory.getLogger;
+import org.apache.commons.lang3.CharUtils;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
 
 public class OmKeyEvent {
 	private static final Logger log = getLogger(OmKeyEvent.class);
 	private static final Map<Integer, Integer> KEY_MAP = new HashMap<>();
+	private static final Map<Character, Integer> CHAR_MAP = new HashMap<>();
+	private static final Set<Character> UNPRINTABLE = Collections.unmodifiableSet(Stream.of('§', 'ö', 'ä', 'ü', 'ß', 'Ö', 'Ä' , 'Ü').collect(Collectors.toSet()));
 	static {
 		KEY_MAP.put(13, KeyEvent.VK_ENTER);
 		KEY_MAP.put(16, 0);
 		KEY_MAP.put(20, KeyEvent.VK_CAPS_LOCK);
+		KEY_MAP.put(43, KeyEvent.VK_ADD); //normal + -> numpad + ????
 		KEY_MAP.put(46, KeyEvent.VK_DELETE);
 		KEY_MAP.put(110, KeyEvent.VK_DECIMAL);
 		KEY_MAP.put(186, KeyEvent.VK_SEMICOLON);
@@ -49,80 +62,86 @@ public class OmKeyEvent {
 		KEY_MAP.put(220, KeyEvent.VK_BACK_SLASH);
 		KEY_MAP.put(221, KeyEvent.VK_CLOSE_BRACKET);
 		KEY_MAP.put(222, KeyEvent.VK_QUOTE);
+		
+		CHAR_MAP.put(Character.valueOf('#'), KeyEvent.VK_NUMBER_SIGN);
+		CHAR_MAP.put(Character.valueOf('<'), KeyEvent.VK_LESS);
+		CHAR_MAP.put(Character.valueOf('.'), KeyEvent.VK_PERIOD);
+		CHAR_MAP.put(Character.valueOf(','), KeyEvent.VK_COMMA);
+		CHAR_MAP.put(Character.valueOf('-'), KeyEvent.VK_MINUS);
+		CHAR_MAP.put(Character.valueOf('='), KeyEvent.VK_EQUALS);
+		CHAR_MAP.put(Character.valueOf('['), KeyEvent.VK_OPEN_BRACKET);
+		CHAR_MAP.put(Character.valueOf(']'), KeyEvent.VK_CLOSE_BRACKET);
+		CHAR_MAP.put(Character.valueOf(';'), KeyEvent.VK_SEMICOLON);
+		CHAR_MAP.put(Character.valueOf('\''), KeyEvent.VK_QUOTE);
+		CHAR_MAP.put(Character.valueOf('\\'), KeyEvent.VK_BACK_SLASH);
+		CHAR_MAP.put(Character.valueOf('`'), KeyEvent.VK_BACK_QUOTE);
+		CHAR_MAP.put(Character.valueOf('/'), KeyEvent.VK_SLASH);
 	}
 	private boolean alt = false;
 	private boolean ctrl = false;
 	private boolean shift = false;
+	private int inKey = 0;
 	private int key = 0;
 	private char ch = 0;
 	
-	public OmKeyEvent(int key) {
-		this(key, false);
-	}
-
-	public OmKeyEvent(int key, boolean shift) {
-		this.key = key;
-		this.shift = shift;
-	}
-
 	public OmKeyEvent(Map<String, Object> obj) {
 		alt = TRUE.equals(obj.get("alt"));
 		ctrl = TRUE.equals(obj.get("ctrl"));
 		shift = TRUE.equals(obj.get("shift"));
 		ch = (char)getInt(obj, "char");
+		key = inKey = getInt(obj, "key");
 		Integer _key = null;
-		int key = getInt(obj, "key");
-		if (key == 0) {
-			if (ch == 61) {
-				this.key = KeyEvent.VK_EQUALS;
+		if (CharUtils.isAsciiPrintable(ch)) {
+			boolean alpha = Character.isAlphabetic(ch);
+			if (alpha) { // can't be combined due to different types
+				key = getKeyStroke(toUpperCase(ch), 0).getKeyCode();
+			} else {
+				key = getKeyStroke(Character.valueOf(ch), 0).getKeyCode();
+			}
+			if (key == 0) {
+				_key = CHAR_MAP.get(ch);
+				if (_key == null) {
+					// fallback
+					key = inKey;
+				}
+			}
+			if (!alpha && _key == null) {
+				_key = KEY_MAP.get(key);
 			}
 		} else {
 			_key = KEY_MAP.get(key);
-			this.key = _key == null ? key : _key;
-		}
-		log.debug("sequence:: shift {}, orig {} -> key {}, _key {}", shift, key, this.key, _key);
-	}
-
-	public int[] sequence() {
-		List<Integer> list = new ArrayList<>();
-		if (alt) {
-			list.add(KeyEvent.VK_ALT);
-		}
-		if (ctrl) {
-			list.add(KeyEvent.VK_CONTROL);
-		}
-		if (shift) {
-			list.add(KeyEvent.VK_SHIFT);
-		}
-		if (key != 0) {
-			list.add(key);
 		}
-		return list.stream().mapToInt(Integer::intValue).toArray();
+		this.key = _key == null ? key : _key;
+		log.debug("sequence:: shift {}, ch {}, orig {} -> key {}({}), map {}", shift, ch == 0 ? ' ' : ch, inKey, key, Integer.toHexString(key), _key);
 	}
 
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + key;
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj) {
-			return true;
-		}
-		if (obj == null) {
-			return false;
-		}
-		if (!(obj instanceof OmKeyEvent)) {
-			return false;
-		}
-		OmKeyEvent other = (OmKeyEvent) obj;
-		if (key != other.key) {
-			return false;
+	public void press(RemoteJob r) throws InterruptedException {
+		if (UNPRINTABLE.contains(ch)) {
+			if (SystemUtils.IS_OS_LINUX) {
+				r.press(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_U);
+				String hex = String.format("%04X", (int)ch);
+				log.debug("sequence:: hex {}", hex);
+				for (int i = 0; i < hex.length(); ++i) {
+					r.press(KeyStroke.getKeyStroke(toUpperCase(hex.charAt(i)), 0).getKeyCode());
+				}
+				r.press(KeyEvent.VK_ENTER);
+			}
+		} else {
+			List<Integer> list = new ArrayList<>();
+			if (shift) {
+				list.add(KeyEvent.VK_SHIFT);
+			}
+			if (alt) {
+				list.add(KeyEvent.VK_ALT);
+			}
+			if (ctrl) {
+				list.add(KeyEvent.VK_CONTROL);
+			}
+			if (key != 0) {
+				list.add(key);
+			}
+			log.debug("sequence:: list {}", list);
+			r.press(list.stream().mapToInt(Integer::intValue).toArray());
 		}
-		return true;
 	}
 }

Modified: openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java
URL: http://svn.apache.org/viewvc/openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java?rev=1760990&r1=1760989&r2=1760990&view=diff
==============================================================================
--- openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java (original)
+++ openmeetings/application/branches/3.2.x/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java Fri Sep 16 03:05:59 2016
@@ -42,6 +42,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.commons.lang3.SystemUtils;
 import org.apache.openmeetings.screenshare.Core;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.Job;
@@ -53,7 +54,6 @@ import org.slf4j.Logger;
 @DisallowConcurrentExecution
 public class RemoteJob implements Job {
 	private static final Logger log = getLogger(RemoteJob.class);
-	private static final boolean isWindows = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1;
 	public static final String CORE_KEY = "core";
 	private Robot robot = null;
 	
@@ -88,10 +88,10 @@ public class RemoteJob implements Job {
 					Point p = getCoordinates(obj);
 					robot.mouseMove(p.x, p.y);
 				} else if (action.equals("keyDown")) {
-					pressSequence(new OmKeyEvent(obj).sequence());
+					new OmKeyEvent(obj).press(this);
 				} else if (action.equals("paste")) {
 					String paste = obj.get("paste").toString();
-					pressSpecialSign(paste);
+					paste(paste);
 				} else if (action.equals("copy")) {
 					String paste = getHighlightedText();
 
@@ -119,7 +119,7 @@ public class RemoteJob implements Job {
 		}
 	}
 
-	private void pressSequence(int... codes) throws InterruptedException {
+	public void press(int... codes) throws InterruptedException {
 		for (int i = 0; i < codes.length; ++i) {
 			robot.keyPress(codes[i]);
 		}
@@ -130,12 +130,12 @@ public class RemoteJob implements Job {
 
 	private String getHighlightedText() {
 		try {
-			if (isWindows) {
-				// pressing STRG+C == copy
-				pressSequence(KeyEvent.VK_CONTROL, KeyEvent.VK_C);
-			} else {
+			if (SystemUtils.IS_OS_MAC) {
 				// Macintosh simulate Copy
-				pressSequence(157, 67);
+				press(157, 67);
+			} else {
+				// pressing CTRL+C == copy
+				press(KeyEvent.VK_CONTROL, KeyEvent.VK_C);
 			}
 			return getClipboardText();
 		} catch (Exception e) {
@@ -165,18 +165,18 @@ public class RemoteJob implements Job {
 		return "";
 	}
 
-	private void pressSpecialSign(String charValue) {
+	private void paste(String charValue) {
 		Clipboard clippy = getDefaultToolkit().getSystemClipboard();
 		try {
 			Transferable transferableText = new StringSelection(charValue);
 			clippy.setContents(transferableText, null);
 
-			if (isWindows) {
-				// pressing STRG+V == insert-mode
-				pressSequence(KeyEvent.VK_CONTROL, KeyEvent.VK_V);
-			} else {
+			if (SystemUtils.IS_OS_MAC) {
 				// Macintosh simulate Insert
-				pressSequence(157, 86);
+				press(157, 86);
+			} else {
+				// pressing CTRL+V == insert-mode
+				press(KeyEvent.VK_CONTROL, KeyEvent.VK_V);
 			}
 		} catch (Exception e) {
 			log.error("Unexpected exception while pressSpecialSign", e);

Modified: openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java?rev=1760990&r1=1760989&r2=1760990&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java (original)
+++ openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/OmKeyEvent.java Fri Sep 16 03:05:59 2016
@@ -19,24 +19,37 @@
 package org.apache.openmeetings.screenshare.job;
 
 import static java.lang.Boolean.TRUE;
+import static org.apache.openmeetings.screenshare.util.Util.getInt;
+import static org.slf4j.LoggerFactory.getLogger;
+import static javax.swing.KeyStroke.getKeyStroke;
+import static java.lang.Character.toUpperCase;
+
 import java.awt.event.KeyEvent;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import org.slf4j.Logger;
+import javax.swing.KeyStroke;
 
-import static org.apache.openmeetings.screenshare.util.Util.getInt;
-import static org.slf4j.LoggerFactory.getLogger;
+import org.apache.commons.lang3.CharUtils;
+import org.apache.commons.lang3.SystemUtils;
+import org.slf4j.Logger;
 
 public class OmKeyEvent {
 	private static final Logger log = getLogger(OmKeyEvent.class);
 	private static final Map<Integer, Integer> KEY_MAP = new HashMap<>();
+	private static final Map<Character, Integer> CHAR_MAP = new HashMap<>();
+	private static final Set<Character> UNPRINTABLE = Collections.unmodifiableSet(Stream.of('§', 'ö', 'ä', 'ü', 'ß', 'Ö', 'Ä' , 'Ü').collect(Collectors.toSet()));
 	static {
 		KEY_MAP.put(13, KeyEvent.VK_ENTER);
 		KEY_MAP.put(16, 0);
 		KEY_MAP.put(20, KeyEvent.VK_CAPS_LOCK);
+		KEY_MAP.put(43, KeyEvent.VK_ADD); //normal + -> numpad + ????
 		KEY_MAP.put(46, KeyEvent.VK_DELETE);
 		KEY_MAP.put(110, KeyEvent.VK_DECIMAL);
 		KEY_MAP.put(186, KeyEvent.VK_SEMICOLON);
@@ -49,80 +62,86 @@ public class OmKeyEvent {
 		KEY_MAP.put(220, KeyEvent.VK_BACK_SLASH);
 		KEY_MAP.put(221, KeyEvent.VK_CLOSE_BRACKET);
 		KEY_MAP.put(222, KeyEvent.VK_QUOTE);
+		
+		CHAR_MAP.put(Character.valueOf('#'), KeyEvent.VK_NUMBER_SIGN);
+		CHAR_MAP.put(Character.valueOf('<'), KeyEvent.VK_LESS);
+		CHAR_MAP.put(Character.valueOf('.'), KeyEvent.VK_PERIOD);
+		CHAR_MAP.put(Character.valueOf(','), KeyEvent.VK_COMMA);
+		CHAR_MAP.put(Character.valueOf('-'), KeyEvent.VK_MINUS);
+		CHAR_MAP.put(Character.valueOf('='), KeyEvent.VK_EQUALS);
+		CHAR_MAP.put(Character.valueOf('['), KeyEvent.VK_OPEN_BRACKET);
+		CHAR_MAP.put(Character.valueOf(']'), KeyEvent.VK_CLOSE_BRACKET);
+		CHAR_MAP.put(Character.valueOf(';'), KeyEvent.VK_SEMICOLON);
+		CHAR_MAP.put(Character.valueOf('\''), KeyEvent.VK_QUOTE);
+		CHAR_MAP.put(Character.valueOf('\\'), KeyEvent.VK_BACK_SLASH);
+		CHAR_MAP.put(Character.valueOf('`'), KeyEvent.VK_BACK_QUOTE);
+		CHAR_MAP.put(Character.valueOf('/'), KeyEvent.VK_SLASH);
 	}
 	private boolean alt = false;
 	private boolean ctrl = false;
 	private boolean shift = false;
+	private int inKey = 0;
 	private int key = 0;
 	private char ch = 0;
 	
-	public OmKeyEvent(int key) {
-		this(key, false);
-	}
-
-	public OmKeyEvent(int key, boolean shift) {
-		this.key = key;
-		this.shift = shift;
-	}
-
 	public OmKeyEvent(Map<String, Object> obj) {
 		alt = TRUE.equals(obj.get("alt"));
 		ctrl = TRUE.equals(obj.get("ctrl"));
 		shift = TRUE.equals(obj.get("shift"));
 		ch = (char)getInt(obj, "char");
+		key = inKey = getInt(obj, "key");
 		Integer _key = null;
-		int key = getInt(obj, "key");
-		if (key == 0) {
-			if (ch == 61) {
-				this.key = KeyEvent.VK_EQUALS;
+		if (CharUtils.isAsciiPrintable(ch)) {
+			boolean alpha = Character.isAlphabetic(ch);
+			if (alpha) { // can't be combined due to different types
+				key = getKeyStroke(toUpperCase(ch), 0).getKeyCode();
+			} else {
+				key = getKeyStroke(Character.valueOf(ch), 0).getKeyCode();
+			}
+			if (key == 0) {
+				_key = CHAR_MAP.get(ch);
+				if (_key == null) {
+					// fallback
+					key = inKey;
+				}
+			}
+			if (!alpha && _key == null) {
+				_key = KEY_MAP.get(key);
 			}
 		} else {
 			_key = KEY_MAP.get(key);
-			this.key = _key == null ? key : _key;
-		}
-		log.debug("sequence:: shift {}, orig {} -> key {}, _key {}", shift, key, this.key, _key);
-	}
-
-	public int[] sequence() {
-		List<Integer> list = new ArrayList<>();
-		if (alt) {
-			list.add(KeyEvent.VK_ALT);
-		}
-		if (ctrl) {
-			list.add(KeyEvent.VK_CONTROL);
-		}
-		if (shift) {
-			list.add(KeyEvent.VK_SHIFT);
-		}
-		if (key != 0) {
-			list.add(key);
 		}
-		return list.stream().mapToInt(Integer::intValue).toArray();
+		this.key = _key == null ? key : _key;
+		log.debug("sequence:: shift {}, ch {}, orig {} -> key {}({}), map {}", shift, ch == 0 ? ' ' : ch, inKey, key, Integer.toHexString(key), _key);
 	}
 
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + key;
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj) {
-			return true;
-		}
-		if (obj == null) {
-			return false;
-		}
-		if (!(obj instanceof OmKeyEvent)) {
-			return false;
-		}
-		OmKeyEvent other = (OmKeyEvent) obj;
-		if (key != other.key) {
-			return false;
+	public void press(RemoteJob r) throws InterruptedException {
+		if (UNPRINTABLE.contains(ch)) {
+			if (SystemUtils.IS_OS_LINUX) {
+				r.press(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_U);
+				String hex = String.format("%04X", (int)ch);
+				log.debug("sequence:: hex {}", hex);
+				for (int i = 0; i < hex.length(); ++i) {
+					r.press(KeyStroke.getKeyStroke(toUpperCase(hex.charAt(i)), 0).getKeyCode());
+				}
+				r.press(KeyEvent.VK_ENTER);
+			}
+		} else {
+			List<Integer> list = new ArrayList<>();
+			if (shift) {
+				list.add(KeyEvent.VK_SHIFT);
+			}
+			if (alt) {
+				list.add(KeyEvent.VK_ALT);
+			}
+			if (ctrl) {
+				list.add(KeyEvent.VK_CONTROL);
+			}
+			if (key != 0) {
+				list.add(key);
+			}
+			log.debug("sequence:: list {}", list);
+			r.press(list.stream().mapToInt(Integer::intValue).toArray());
 		}
-		return true;
 	}
 }

Modified: openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java
URL: http://svn.apache.org/viewvc/openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java?rev=1760990&r1=1760989&r2=1760990&view=diff
==============================================================================
--- openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java (original)
+++ openmeetings/application/trunk/openmeetings-screenshare/src/main/java/org/apache/openmeetings/screenshare/job/RemoteJob.java Fri Sep 16 03:05:59 2016
@@ -42,6 +42,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.commons.lang3.SystemUtils;
 import org.apache.openmeetings.screenshare.Core;
 import org.quartz.DisallowConcurrentExecution;
 import org.quartz.Job;
@@ -53,7 +54,6 @@ import org.slf4j.Logger;
 @DisallowConcurrentExecution
 public class RemoteJob implements Job {
 	private static final Logger log = getLogger(RemoteJob.class);
-	private static final boolean isWindows = System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") > -1;
 	public static final String CORE_KEY = "core";
 	private Robot robot = null;
 	
@@ -88,10 +88,10 @@ public class RemoteJob implements Job {
 					Point p = getCoordinates(obj);
 					robot.mouseMove(p.x, p.y);
 				} else if (action.equals("keyDown")) {
-					pressSequence(new OmKeyEvent(obj).sequence());
+					new OmKeyEvent(obj).press(this);
 				} else if (action.equals("paste")) {
 					String paste = obj.get("paste").toString();
-					pressSpecialSign(paste);
+					paste(paste);
 				} else if (action.equals("copy")) {
 					String paste = getHighlightedText();
 
@@ -119,7 +119,7 @@ public class RemoteJob implements Job {
 		}
 	}
 
-	private void pressSequence(int... codes) throws InterruptedException {
+	public void press(int... codes) throws InterruptedException {
 		for (int i = 0; i < codes.length; ++i) {
 			robot.keyPress(codes[i]);
 		}
@@ -130,12 +130,12 @@ public class RemoteJob implements Job {
 
 	private String getHighlightedText() {
 		try {
-			if (isWindows) {
-				// pressing STRG+C == copy
-				pressSequence(KeyEvent.VK_CONTROL, KeyEvent.VK_C);
-			} else {
+			if (SystemUtils.IS_OS_MAC) {
 				// Macintosh simulate Copy
-				pressSequence(157, 67);
+				press(157, 67);
+			} else {
+				// pressing CTRL+C == copy
+				press(KeyEvent.VK_CONTROL, KeyEvent.VK_C);
 			}
 			return getClipboardText();
 		} catch (Exception e) {
@@ -165,18 +165,18 @@ public class RemoteJob implements Job {
 		return "";
 	}
 
-	private void pressSpecialSign(String charValue) {
+	private void paste(String charValue) {
 		Clipboard clippy = getDefaultToolkit().getSystemClipboard();
 		try {
 			Transferable transferableText = new StringSelection(charValue);
 			clippy.setContents(transferableText, null);
 
-			if (isWindows) {
-				// pressing STRG+V == insert-mode
-				pressSequence(KeyEvent.VK_CONTROL, KeyEvent.VK_V);
-			} else {
+			if (SystemUtils.IS_OS_MAC) {
 				// Macintosh simulate Insert
-				pressSequence(157, 86);
+				press(157, 86);
+			} else {
+				// pressing CTRL+V == insert-mode
+				press(KeyEvent.VK_CONTROL, KeyEvent.VK_V);
 			}
 		} catch (Exception e) {
 			log.error("Unexpected exception while pressSpecialSign", e);