// 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 vncclient.adapter; import java.awt.event.KeyEvent; import streamer.BaseElement; import streamer.ByteBuffer; import streamer.Link; import vncclient.vnc.RfbConstants; import common.KeyOrder; public class AwtVncKeyboardAdapter extends BaseElement { protected boolean sh = false; protected boolean caps = false; protected boolean num = false; public AwtVncKeyboardAdapter(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(8); outBuf.writeByte(RfbConstants.CLIENT_KEYBOARD_EVENT); outBuf.writeByte((order.pressed) ? RfbConstants.KEY_DOWN : RfbConstants.KEY_UP); outBuf.writeShort(0); // padding outBuf.writeInt(map_en_us(order)); pushDataToAllOuts(outBuf); } /** * Return key scan code (in lower byte) and extended flags (in second byte). */ private int map_en_us(KeyOrder order) { switch (order.event.getKeyCode()) { // Functional keys case KeyEvent.VK_ESCAPE: return 0xff1b; case KeyEvent.VK_F1: return 0xffbe; case KeyEvent.VK_F2: return 0xffbf; case KeyEvent.VK_F3: return 0xffc0; case KeyEvent.VK_F4: return 0xffc1; case KeyEvent.VK_F5: return 0xffc2; case KeyEvent.VK_F6: return 0xffc3; case KeyEvent.VK_F7: return 0xffc4; case KeyEvent.VK_F8: return 0xffc5; case KeyEvent.VK_F9: return 0xffc6; case KeyEvent.VK_F10: return 0xffc7; case KeyEvent.VK_F11: return 0xffc8; case KeyEvent.VK_F12: return 0xffc9; // Row #1 case KeyEvent.VK_BACK_QUOTE: return (sh) ? '~' : '`'; case KeyEvent.VK_1: return (sh) ? '!' : '1'; case KeyEvent.VK_2: return (sh) ? '@' : '2'; case KeyEvent.VK_3: return (sh) ? '#' : '3'; case KeyEvent.VK_4: return (sh) ? '$' : '4'; case KeyEvent.VK_5: return (sh) ? '%' : '5'; case KeyEvent.VK_6: return (sh) ? '^' : '6'; case KeyEvent.VK_7: return (sh) ? '&' : '7'; case KeyEvent.VK_8: return (sh) ? '*' : '8'; case KeyEvent.VK_9: return (sh) ? '(' : '9'; case KeyEvent.VK_0: return (sh) ? ')' : '0'; case KeyEvent.VK_MINUS: return (sh) ? '_' : '-'; case KeyEvent.VK_EQUALS: return (sh) ? '+' : '='; case KeyEvent.VK_BACK_SPACE: return 0xff08; // Row #2 case KeyEvent.VK_TAB: return 0xff09; case KeyEvent.VK_Q: return (sh ^ caps) ? 'Q' : 'q'; case KeyEvent.VK_W: return (sh ^ caps) ? 'W' : 'w'; case KeyEvent.VK_E: return (sh ^ caps) ? 'E' : 'e'; case KeyEvent.VK_R: return (sh ^ caps) ? 'R' : 'r'; case KeyEvent.VK_T: return (sh ^ caps) ? 'T' : 't'; case KeyEvent.VK_Y: return (sh ^ caps) ? 'Y' : 'y'; case KeyEvent.VK_U: return (sh ^ caps) ? 'U' : 'u'; case KeyEvent.VK_I: return (sh ^ caps) ? 'I' : 'i'; case KeyEvent.VK_O: return (sh ^ caps) ? 'O' : 'o'; case KeyEvent.VK_P: return (sh ^ caps) ? 'P' : 'p'; case KeyEvent.VK_OPEN_BRACKET: return (sh) ? '{' : '['; case KeyEvent.VK_CLOSE_BRACKET: return (sh) ? '{' : ']'; case KeyEvent.VK_ENTER: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_STANDARD: return 0xff0d; case KeyEvent.KEY_LOCATION_NUMPAD: return 0xff8d; } // Row #3 case KeyEvent.VK_CAPS_LOCK: if (order.pressed) caps = !caps; return 0xFFE5; case KeyEvent.VK_A: return (sh ^ caps) ? 'A' : 'a'; case KeyEvent.VK_S: return (sh ^ caps) ? 'S' : 's'; case KeyEvent.VK_D: return (sh ^ caps) ? 'D' : 'd'; case KeyEvent.VK_F: return (sh ^ caps) ? 'F' : 'f'; case KeyEvent.VK_G: return (sh ^ caps) ? 'G' : 'g'; case KeyEvent.VK_H: return (sh ^ caps) ? 'H' : 'h'; case KeyEvent.VK_J: return (sh ^ caps) ? 'J' : 'j'; case KeyEvent.VK_K: return (sh ^ caps) ? 'K' : 'k'; case KeyEvent.VK_L: return (sh ^ caps) ? 'L' : 'l'; case KeyEvent.VK_SEMICOLON: return (sh) ? ':' : ';'; case KeyEvent.VK_QUOTE: return (sh) ? '"' : '\''; // Row #4 case KeyEvent.VK_SHIFT: sh = !sh; switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xffe1; case KeyEvent.KEY_LOCATION_RIGHT: return 0xffe2; } case KeyEvent.VK_BACK_SLASH: return (sh) ? '|' : '\\'; case KeyEvent.VK_Z: return (sh ^ caps) ? 'Z' : 'z'; case KeyEvent.VK_X: return (sh ^ caps) ? 'X' : 'x'; case KeyEvent.VK_C: return (sh ^ caps) ? 'C' : 'c'; case KeyEvent.VK_V: return (sh ^ caps) ? 'V' : 'v'; case KeyEvent.VK_B: return (sh ^ caps) ? 'B' : 'b'; case KeyEvent.VK_N: return (sh ^ caps) ? 'N' : 'n'; case KeyEvent.VK_M: return (sh ^ caps) ? 'M' : 'm'; case KeyEvent.VK_COMMA: return (sh) ? '<' : ','; case KeyEvent.VK_PERIOD: return (sh) ? '>' : '.'; case KeyEvent.VK_SLASH: return (sh) ? '?' : '/'; // // Bottom row case KeyEvent.VK_CONTROL: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xFFE3; case KeyEvent.KEY_LOCATION_RIGHT: return 0xFFE4; } case KeyEvent.VK_WINDOWS: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xFFED; // HyperL case KeyEvent.KEY_LOCATION_RIGHT: return 0xFFEE; // HyperR } case KeyEvent.VK_META: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xFFE7; // MetaL case KeyEvent.KEY_LOCATION_RIGHT: return 0xFFE8; // MetaR } case KeyEvent.VK_ALT: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xFFE9; case KeyEvent.KEY_LOCATION_RIGHT: return 0xFFEA; } case KeyEvent.VK_ALT_GRAPH: return 0xfe03; case KeyEvent.VK_SPACE: return ' '; case KeyEvent.VK_CONTEXT_MENU: return 0xff67; // // Special keys case KeyEvent.VK_PRINTSCREEN: return (sh) ? 0xFF15/* SysRq */: 0xFF61 /* Print */; case KeyEvent.VK_SCROLL_LOCK: return 0xFF14; case KeyEvent.VK_PAUSE: return (sh) ? 0xFF6B/* Break */: 0xFF13/* Pause */; // Text navigation keys case KeyEvent.VK_INSERT: return 0xff63; case KeyEvent.VK_DELETE: return 0xffff; case KeyEvent.VK_HOME: return 0xff50; case KeyEvent.VK_END: return 0xff57; case KeyEvent.VK_PAGE_UP: return 0xff55; case KeyEvent.VK_PAGE_DOWN: return 0xff56; // Cursor keys case KeyEvent.VK_LEFT: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xff51; case KeyEvent.KEY_LOCATION_NUMPAD: return 0xFF96; } case KeyEvent.VK_UP: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xff52; case KeyEvent.KEY_LOCATION_NUMPAD: return 0xFF97; } case KeyEvent.VK_RIGHT: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xff53; case KeyEvent.KEY_LOCATION_NUMPAD: return 0xFF98; } case KeyEvent.VK_DOWN: switch (order.event.getKeyLocation()) { default: case KeyEvent.KEY_LOCATION_LEFT: return 0xff54; case KeyEvent.KEY_LOCATION_NUMPAD: return 0xFF99; } // Keypad case KeyEvent.VK_NUM_LOCK: if (order.pressed) num = !num; return 0xFF6F; case KeyEvent.VK_DIVIDE: return 0xFFAF; case KeyEvent.VK_MULTIPLY: return 0xFFAA; case KeyEvent.VK_SUBTRACT: return 0xFFAD; case KeyEvent.VK_ADD: return 0xFFAB; case KeyEvent.VK_KP_LEFT: return 0xFF96; case KeyEvent.VK_KP_UP: return 0xFF97; case KeyEvent.VK_KP_RIGHT: return 0xFF98; case KeyEvent.VK_KP_DOWN: return 0xFF99; case KeyEvent.VK_NUMPAD0: return 0xFFB0; case KeyEvent.VK_NUMPAD1: return 0xFFB1; case KeyEvent.VK_NUMPAD2: return 0xFFB2; case KeyEvent.VK_NUMPAD3: return 0xFFB3; case KeyEvent.VK_NUMPAD4: return 0xFFB4; case KeyEvent.VK_NUMPAD5: return 0xFFB5; case KeyEvent.VK_NUMPAD6: return 0xFFB6; case KeyEvent.VK_NUMPAD7: return 0xFFB7; case KeyEvent.VK_NUMPAD8: return 0xFFB8; case KeyEvent.VK_NUMPAD9: return 0xFFB9; case KeyEvent.VK_DECIMAL: return 0xFFAE; default: System.err.println("Key is not mapped: " + order + "."); return ' '; // Space } } }