| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| package rdpclient.adapter; |
| |
| import java.awt.event.KeyEvent; |
| |
| import streamer.BaseElement; |
| import streamer.ByteBuffer; |
| import streamer.Link; |
| import common.KeyOrder; |
| |
| public class AwtRdpKeyboardAdapter extends BaseElement { |
| |
| /** |
| * Absence of this flag indicates a key-down event, while its presence |
| * indicates a key-release event. |
| */ |
| public static final int FASTPATH_INPUT_KBDFLAGS_RELEASE = 0x01; |
| |
| /** |
| * Keystroke message contains an extended scancode. For enhanced 101-key and |
| * 102-key keyboards, extended keys include the right ALT and right CTRL keys |
| * on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE |
| * DOWN and ARROW keys in the clusters to the left of the numeric keypad; and |
| * the Divide ("/") and ENTER keys in the numeric keypad. |
| */ |
| public static final int FASTPATH_INPUT_KBDFLAGS_EXTENDED = 0x02; |
| |
| public static final int FASTPATH_INPUT_EVENT_SCANCODE = 0; |
| |
| public AwtRdpKeyboardAdapter(String id) { |
| super(id); |
| } |
| |
| @Override |
| public void handleData(ByteBuffer buf, Link link) { |
| if (verbose) |
| System.out.println("[" + this + "] INFO: Data received: " + buf + "."); |
| |
| KeyOrder order = (KeyOrder)buf.getOrder(); |
| buf.unref(); |
| |
| ByteBuffer outBuf = new ByteBuffer(2, true); |
| |
| int scanCode = map_en_us(order.event); |
| |
| // eventHeader (1 byte): An 8-bit, unsigned integer. The format of this |
| // field is the same as the eventHeader byte field described in section |
| // 2.2.8.1.2.2. The eventCode bitfield (3 bits in size) MUST be set to |
| // FASTPATH_INPUT_EVENT_SCANCODE (0). The eventFlags bitfield (5 bits in |
| // size) contains flags describing the keyboard event. |
| outBuf.writeByte((scanCode >> 8) | (FASTPATH_INPUT_EVENT_SCANCODE << 5) | ((order.pressed) ? 0 : FASTPATH_INPUT_KBDFLAGS_RELEASE)); |
| |
| // keyCode (1 byte): An 8-bit, unsigned integer. The scancode of the key |
| // which triggered the event. |
| outBuf.writeByte(scanCode); |
| |
| // Push buffer to one pad only, so it can be modified without copying of |
| // data |
| pushDataToPad(STDOUT, outBuf); |
| } |
| |
| /** |
| * Return key scan code (in lower byte) and extended flags (in second byte). |
| */ |
| private int map_en_us(KeyEvent event) { |
| // Also set extended key flag when necessary. |
| // For enhanced 101-key and 102-key keyboards, extended keys include the |
| // right ALT and right CTRL keys on the main section of the keyboard; the |
| // INS, DEL, HOME, END, PAGE UP, PAGE DOWN and ARROW keys in the clusters to |
| // the left of the numeric keypad; and the Divide ("/") and ENTER keys in |
| // the numeric keypad. |
| |
| switch (event.getKeyCode()) { |
| // Functional keys |
| case KeyEvent.VK_ESCAPE: |
| return 1; |
| case KeyEvent.VK_F1: |
| return 59; |
| case KeyEvent.VK_F2: |
| return 60; |
| case KeyEvent.VK_F3: |
| return 61; |
| case KeyEvent.VK_F4: |
| return 62; |
| case KeyEvent.VK_F5: |
| return 63; |
| case KeyEvent.VK_F6: |
| return 64; |
| case KeyEvent.VK_F7: |
| return 65; |
| case KeyEvent.VK_F8: |
| return 66; |
| case KeyEvent.VK_F9: |
| return 67; |
| case KeyEvent.VK_F10: |
| return 68; |
| case KeyEvent.VK_F11: |
| return 87; |
| case KeyEvent.VK_F12: |
| return 88; |
| |
| // Row #1 |
| case KeyEvent.VK_BACK_QUOTE: |
| return 41; |
| case KeyEvent.VK_1: |
| return 2; |
| case KeyEvent.VK_2: |
| return 3; |
| case KeyEvent.VK_3: |
| return 4; |
| case KeyEvent.VK_4: |
| return 5; |
| case KeyEvent.VK_5: |
| return 6; |
| case KeyEvent.VK_6: |
| return 7; |
| case KeyEvent.VK_7: |
| return 8; |
| case KeyEvent.VK_8: |
| return 9; |
| case KeyEvent.VK_9: |
| return 10; |
| case KeyEvent.VK_0: |
| return 11; |
| case KeyEvent.VK_MINUS: |
| return 12; |
| case KeyEvent.VK_EQUALS: |
| return 13; |
| case KeyEvent.VK_BACK_SPACE: |
| return 14; |
| |
| // Row #2 |
| case KeyEvent.VK_TAB: |
| return 15; |
| case KeyEvent.VK_Q: |
| return 16; |
| case KeyEvent.VK_W: |
| return 17; |
| case KeyEvent.VK_E: |
| return 18; |
| case KeyEvent.VK_R: |
| return 19; |
| case KeyEvent.VK_T: |
| return 20; |
| case KeyEvent.VK_Y: |
| return 21; |
| case KeyEvent.VK_U: |
| return 22; |
| case KeyEvent.VK_I: |
| return 23; |
| case KeyEvent.VK_O: |
| return 24; |
| case KeyEvent.VK_P: |
| return 25; |
| case KeyEvent.VK_OPEN_BRACKET: |
| return 26; |
| case KeyEvent.VK_CLOSE_BRACKET: |
| return 27; |
| case KeyEvent.VK_ENTER: |
| switch (event.getKeyLocation()) { |
| default: |
| case KeyEvent.KEY_LOCATION_STANDARD: |
| return 28; |
| case KeyEvent.KEY_LOCATION_NUMPAD: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 28; |
| } |
| |
| // Row #3 |
| case KeyEvent.VK_CAPS_LOCK: |
| return 58; |
| case KeyEvent.VK_A: |
| return 30; |
| case KeyEvent.VK_S: |
| return 31; |
| case KeyEvent.VK_D: |
| return 32; |
| case KeyEvent.VK_F: |
| return 33; |
| case KeyEvent.VK_G: |
| return 34; |
| case KeyEvent.VK_H: |
| return 35; |
| case KeyEvent.VK_J: |
| return 36; |
| case KeyEvent.VK_K: |
| return 37; |
| case KeyEvent.VK_L: |
| return 38; |
| case KeyEvent.VK_SEMICOLON: |
| return 39; |
| case KeyEvent.VK_QUOTE: |
| return 40; |
| |
| // Row #4 |
| case KeyEvent.VK_SHIFT: |
| switch (event.getKeyLocation()) { |
| default: |
| case KeyEvent.KEY_LOCATION_LEFT: |
| return 42; |
| case KeyEvent.KEY_LOCATION_RIGHT: |
| return 54; |
| } |
| case KeyEvent.VK_BACK_SLASH: |
| return 43; |
| case KeyEvent.VK_Z: |
| return 44; |
| case KeyEvent.VK_X: |
| return 45; |
| case KeyEvent.VK_C: |
| return 46; |
| case KeyEvent.VK_V: |
| return 47; |
| case KeyEvent.VK_B: |
| return 48; |
| case KeyEvent.VK_N: |
| return 49; |
| case KeyEvent.VK_M: |
| return 50; |
| case KeyEvent.VK_COMMA: |
| return 51; |
| case KeyEvent.VK_PERIOD: |
| return 52; |
| case KeyEvent.VK_SLASH: |
| return 53; |
| |
| // |
| // Bottom row |
| case KeyEvent.VK_CONTROL: |
| switch (event.getKeyLocation()) { |
| default: |
| case KeyEvent.KEY_LOCATION_LEFT: |
| return 29; |
| case KeyEvent.KEY_LOCATION_RIGHT: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 29; |
| } |
| case KeyEvent.VK_WINDOWS: |
| switch (event.getKeyLocation()) { |
| default: |
| case KeyEvent.KEY_LOCATION_LEFT: |
| return 91; |
| case KeyEvent.KEY_LOCATION_RIGHT: |
| return 92; |
| } |
| case KeyEvent.VK_ALT: |
| switch (event.getKeyLocation()) { |
| default: |
| case KeyEvent.KEY_LOCATION_LEFT: |
| return 56; |
| case KeyEvent.KEY_LOCATION_RIGHT: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 56; |
| } |
| case KeyEvent.VK_ALT_GRAPH: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 56; |
| |
| case KeyEvent.VK_SPACE: |
| return 57; |
| |
| case KeyEvent.VK_CONTEXT_MENU: |
| return 93; |
| |
| // |
| // Special keys |
| case KeyEvent.VK_PRINTSCREEN: |
| return 55; |
| case KeyEvent.VK_SCROLL_LOCK: |
| return 70; |
| case KeyEvent.VK_PAUSE: |
| return 29; |
| |
| // Text navigation keys |
| case KeyEvent.VK_INSERT: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 82; |
| case KeyEvent.VK_HOME: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 71; |
| case KeyEvent.VK_PAGE_UP: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 73; |
| case KeyEvent.VK_DELETE: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 83; |
| case KeyEvent.VK_END: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 79; |
| case KeyEvent.VK_PAGE_DOWN: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 81; |
| |
| // Cursor keys |
| case KeyEvent.VK_UP: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 72; |
| case KeyEvent.VK_LEFT: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 75; |
| case KeyEvent.VK_DOWN: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 80; |
| case KeyEvent.VK_RIGHT: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 77; |
| |
| // Keypad |
| case KeyEvent.VK_NUM_LOCK: |
| return 69; |
| case KeyEvent.VK_DIVIDE: |
| return (FASTPATH_INPUT_KBDFLAGS_EXTENDED << 8) | 53; |
| case KeyEvent.VK_MULTIPLY: |
| return 55; |
| case KeyEvent.VK_SUBTRACT: |
| return 74; |
| case KeyEvent.VK_ADD: |
| return 78; |
| |
| case KeyEvent.VK_NUMPAD7: |
| return 71; |
| case KeyEvent.VK_NUMPAD8: |
| return 72; |
| case KeyEvent.VK_NUMPAD9: |
| return 73; |
| case KeyEvent.VK_NUMPAD4: |
| return 75; |
| case KeyEvent.VK_NUMPAD5: |
| return 76; |
| case KeyEvent.VK_NUMPAD6: |
| return 77; |
| case KeyEvent.VK_NUMPAD1: |
| return 79; |
| case KeyEvent.VK_NUMPAD2: |
| return 80; |
| case KeyEvent.VK_NUMPAD3: |
| return 81; |
| case KeyEvent.VK_NUMPAD0: |
| return 82; |
| case KeyEvent.VK_DECIMAL: |
| return 83; |
| |
| default: |
| System.err.println("Key is not mapped: " + event + "."); |
| return event.getKeyCode(); |
| } |
| } |
| |
| } |