From e00499dacde23ecd82298071eb708046771cfe53 Mon Sep 17 00:00:00 2001 From: Foone Debonte Date: Sat, 29 May 2010 02:32:57 +0300 Subject: [PATCH] Variable keyboard layouts support Support reading keyboard layout data from file and add few new layouts. --- Changelog.utf8 | 1 + assemble.jpcrrinit | 2 +- classic.keyboard | 111 ++++++++ org/jpc/plugins/VirtualKeyboard.java | 508 ++++++++++++++++++++++++----------- thinkpad.keyboard | 98 +++++++ updated.keyboard | 111 ++++++++ 6 files changed, 676 insertions(+), 155 deletions(-) create mode 100644 classic.keyboard create mode 100644 thinkpad.keyboard create mode 100644 updated.keyboard diff --git a/Changelog.utf8 b/Changelog.utf8 index 7d5a773..c5fa8a9 100644 --- a/Changelog.utf8 +++ b/Changelog.utf8 @@ -9,6 +9,7 @@ Changes since JPC-RR Release 10.8: - Implement INT3_O16 and INTO_O16 in pmode. - Clean up Misc.parseString(). - Clean up ConstantTableLayout. +- Keyboard layouts support and new default layout. Changes from JPC-RR Release 10.7 to JPC-RR Release 10.8: ======================================================== diff --git a/assemble.jpcrrinit b/assemble.jpcrrinit index 93fc5bc..16e62ac 100644 --- a/assemble.jpcrrinit +++ b/assemble.jpcrrinit @@ -1,6 +1,6 @@ library disklibrary load org.jpc.plugins.PCMonitor -load org.jpc.plugins.VirtualKeyboard +load org.jpc.plugins.VirtualKeyboard(keyboard=updated.keyboard) load org.jpc.plugins.TimeDisplay load org.jpc.plugins.LuaPlugin(kernel=luakernel.lua,luapath=lua) load org.jpc.plugins.PCControl(extramenu=extramenu) diff --git a/classic.keyboard b/classic.keyboard new file mode 100644 index 0000000..1a961a5 --- /dev/null +++ b/classic.keyboard @@ -0,0 +1,111 @@ +(Code X Y W H Size Name Shifted) +001 0 0 3 2 C Esc +059 4 - 2 2 C F1 +060 - - 2 2 C F2 +061 - - 2 2 C F3 +062 - - 2 2 C F4 +063 13 - 2 2 C F5 +064 - - 2 2 C F6 +065 - - 2 2 C F7 +066 - - 2 2 C F8 +067 22 - 2 2 C F9 +068 - - 2 2 C FA +087 - - 2 2 C FB +088 - - 2 2 C FC +183 31 - 2 2 C PS +070 - - 2 2 C SL +255 - - 2 2 C PA + +002 2 4 2 2 C 1 +003 - - 2 2 C 2 +004 - - 2 2 C 3 +005 - - 2 2 C 4 +006 - - 2 2 C 5 +007 - - 2 2 C 6 +008 - - 2 2 C 7 +009 - - 2 2 C 8 +010 - - 2 2 C 9 +011 - - 2 2 C 0 +012 - - 2 2 C - +013 - - 2 2 C = +014 - - 4 2 C BS +210 31 - 2 2 C I +199 - - 2 2 C H +201 - - 2 2 C PU +069 38 - 2 2 C NL +181 - - 2 2 C / +055 - - 2 2 C * +074 - - 2 2 C - + +NumLock 38 0 2 2 C N +CapsLock - - 2 2 C C +ScrollLock - - 2 2 C S + +015 0 6 3 2 C Tab +016 - - 2 2 C Q +017 - - 2 2 C W +018 - - 2 2 C E +019 - - 2 2 C R +020 - - 2 2 C T +021 - - 2 2 C Y +022 - - 2 2 C U +023 - - 2 2 C I +024 - - 2 2 C O +025 - - 2 2 C P +026 - - 2 2 C [ +027 - - 2 2 C ] +028 28 - 2 4 C EN +211 31 - 2 2 C D +207 - - 2 2 C E +209 - - 2 2 C PD +071 38 - 2 2 C 7 +072 - - 2 2 C 8 +073 - - 2 2 C 9 +078 - - 2 4 C + + +058 0 8 4 2 C CL +030 - - 2 2 C A +031 - - 2 2 C S +032 - - 2 2 C D +033 - - 2 2 C F +034 - - 2 2 C G +035 - - 2 2 C H +036 - - 2 2 C J +037 - - 2 2 C K +038 - - 2 2 C L +039 - - 2 2 C ; +040 - - 2 2 C ' +041 - - 2 2 C ` +075 38 - 2 2 C 4 +076 - - 2 2 C 5 +077 - - 2 2 C 6 + +042 0 10 3 2 C SH +043 - - 2 2 C \\ +044 - - 2 2 C Z +045 - - 2 2 C X +046 - - 2 2 C C +047 - - 2 2 C V +048 - - 2 2 C B +049 - - 2 2 C N +050 - - 2 2 C M +051 - - 2 2 C , +052 - - 2 2 C . +053 - - 2 2 C / +054 - - 5 2 C SH +200 33 - 2 2 C ^ +079 38 - 2 2 C 1 +080 - - 2 2 C 2 +081 - - 2 2 C 3 +156 - - 2 4 C EN + +029 0 12 3 2 C CT +056 5 - 3 2 C AL +057 - - 14 2 C SP +184 - - 3 2 C AL +157 27 - 3 2 C CT +203 31 - 2 2 C < +208 - - 2 2 C v +205 - - 2 2 C > +082 38 - 4 2 C 0 +083 - - 2 2 C . diff --git a/org/jpc/plugins/VirtualKeyboard.java b/org/jpc/plugins/VirtualKeyboard.java index 122f99b..51bb1be 100644 --- a/org/jpc/plugins/VirtualKeyboard.java +++ b/org/jpc/plugins/VirtualKeyboard.java @@ -4,6 +4,7 @@ Copyright (C) 2007-2009 Isis Innovation Limited Copyright (C) 2009-2010 H. Ilari Liusvaara + Copyright (C) 2010 Foone Debonte This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by @@ -29,18 +30,25 @@ package org.jpc.plugins; +import org.jpc.Misc; import org.jpc.emulator.peripheral.Keyboard; import org.jpc.emulator.KeyboardStatusListener; +import org.jpc.jrsr.UTFInputLineStream; import org.jpc.pluginsbase.Plugins; import org.jpc.pluginsbase.Plugin; import org.jpc.pluginsaux.ConstantTableLayout; import static org.jpc.Misc.errorDialog; import static org.jpc.Misc.moveWindow; +import static org.jpc.Misc.parseStringToComponents; +import java.io.*; import javax.swing.*; +import javax.swing.border.*; import java.util.*; import java.awt.event.*; import java.awt.*; +import javax.swing.plaf.basic.*; +import javax.swing.plaf.*; public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusListener { @@ -51,31 +59,159 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi private JToggleButton capsLock; private JToggleButton numLock; private JToggleButton scrollLock; + private Font keyFont; + private Font smallKeyFont; + private Border keyBorder, smallKeyBorder, classicBorder; + private boolean nativeButtons; + private org.jpc.emulator.peripheral.Keyboard keyboard; private int keyNo; private boolean[] cachedState; private Plugins pluginManager; private int nativeWidth, nativeHeight; - public void addKey(String name, int scanCode, int x, int y, int w, int h) + private static String[][] DEFAULT_KEYBOARD_DATA = new String[][] { + new String[]{"001", "0", "0", "3", "2", "C", "Esc"}, + new String[]{"059", "4", "-", "2", "2", "C", "F1"}, + new String[]{"060", "-", "-", "2", "2", "C", "F2"}, + new String[]{"061", "-", "-", "2", "2", "C", "F3"}, + new String[]{"062", "-", "-", "2", "2", "C", "F4"}, + new String[]{"063", "13", "-", "2", "2", "C", "F5"}, + new String[]{"064", "-", "-", "2", "2", "C", "F6"}, + new String[]{"065", "-", "-", "2", "2", "C", "F7"}, + new String[]{"066", "-", "-", "2", "2", "C", "F8"}, + new String[]{"067", "22", "-", "2", "2", "C", "F9"}, + new String[]{"068", "-", "-", "2", "2", "C", "FA"}, + new String[]{"087", "-", "-", "2", "2", "C", "FB"}, + new String[]{"088", "-", "-", "2", "2", "C", "FC"}, + new String[]{"183", "31", "-", "2", "2", "C", "PS"}, + new String[]{"070", "-", "-", "2", "2", "C", "SL"}, + new String[]{"255", "-", "-", "2", "2", "C", "PA"}, + new String[]{"002", "2", "4", "2", "2", "C", "1"}, + new String[]{"003", "-", "-", "2", "2", "C", "2"}, + new String[]{"004", "-", "-", "2", "2", "C", "3"}, + new String[]{"005", "-", "-", "2", "2", "C", "4"}, + new String[]{"006", "-", "-", "2", "2", "C", "5"}, + new String[]{"007", "-", "-", "2", "2", "C", "6"}, + new String[]{"008", "-", "-", "2", "2", "C", "7"}, + new String[]{"009", "-", "-", "2", "2", "C", "8"}, + new String[]{"010", "-", "-", "2", "2", "C", "9"}, + new String[]{"011", "-", "-", "2", "2", "C", "0"}, + new String[]{"012", "-", "-", "2", "2", "C", "-"}, + new String[]{"013", "-", "-", "2", "2", "C", "="}, + new String[]{"014", "-", "-", "4", "2", "C", "BS"}, + new String[]{"210", "31", "-", "2", "2", "C", "I"}, + new String[]{"199", "-", "-", "2", "2", "C", "H"}, + new String[]{"201", "-", "-", "2", "2", "C", "PU"}, + new String[]{"069", "38", "-", "2", "2", "C", "NL"}, + new String[]{"181", "-", "-", "2", "2", "C", "/"}, + new String[]{"055", "-", "-", "2", "2", "C", "*"}, + new String[]{"074", "-", "-", "2", "2", "C", "-"}, + new String[]{"NumLock", "38", "0", "2", "2", "C", "N"}, + new String[]{"CapsLock", "-", "-", "2", "2", "C", "C"}, + new String[]{"ScrollLock", "-", "-", "2", "2", "C", "S"}, + new String[]{"015", "0", "6", "3", "2", "C", "Tab"}, + new String[]{"016", "-", "-", "2", "2", "C", "Q"}, + new String[]{"017", "-", "-", "2", "2", "C", "W"}, + new String[]{"018", "-", "-", "2", "2", "C", "E"}, + new String[]{"019", "-", "-", "2", "2", "C", "R"}, + new String[]{"020", "-", "-", "2", "2", "C", "T"}, + new String[]{"021", "-", "-", "2", "2", "C", "Y"}, + new String[]{"022", "-", "-", "2", "2", "C", "U"}, + new String[]{"023", "-", "-", "2", "2", "C", "I"}, + new String[]{"024", "-", "-", "2", "2", "C", "O"}, + new String[]{"025", "-", "-", "2", "2", "C", "P"}, + new String[]{"026", "-", "-", "2", "2", "C", "["}, + new String[]{"027", "-", "-", "2", "2", "C", "]"}, + new String[]{"028", "28", "-", "2", "4", "C", "EN"}, + new String[]{"211", "31", "-", "2", "2", "C", "D"}, + new String[]{"207", "-", "-", "2", "2", "C", "E"}, + new String[]{"209", "-", "-", "2", "2", "C", "PD"}, + new String[]{"071", "38", "-", "2", "2", "C", "7"}, + new String[]{"072", "-", "-", "2", "2", "C", "8"}, + new String[]{"073", "-", "-", "2", "2", "C", "9"}, + new String[]{"078", "-", "-", "2", "4", "C", "+"}, + new String[]{"058", "0", "8", "4", "2", "C", "CL"}, + new String[]{"030", "-", "-", "2", "2", "C", "A"}, + new String[]{"031", "-", "-", "2", "2", "C", "S"}, + new String[]{"032", "-", "-", "2", "2", "C", "D"}, + new String[]{"033", "-", "-", "2", "2", "C", "F"}, + new String[]{"034", "-", "-", "2", "2", "C", "G"}, + new String[]{"035", "-", "-", "2", "2", "C", "H"}, + new String[]{"036", "-", "-", "2", "2", "C", "J"}, + new String[]{"037", "-", "-", "2", "2", "C", "K"}, + new String[]{"038", "-", "-", "2", "2", "C", "L"}, + new String[]{"039", "-", "-", "2", "2", "C", ";"}, + new String[]{"040", "-", "-", "2", "2", "C", "'"}, + new String[]{"041", "-", "-", "2", "2", "C", "`"}, + new String[]{"075", "38", "-", "2", "2", "C", "4"}, + new String[]{"076", "-", "-", "2", "2", "C", "5"}, + new String[]{"077", "-", "-", "2", "2", "C", "6"}, + new String[]{"042", "0", "10", "3", "2", "C", "SH"}, + new String[]{"043", "-", "-", "2", "2", "C", "\\"}, + new String[]{"044", "-", "-", "2", "2", "C", "Z"}, + new String[]{"045", "-", "-", "2", "2", "C", "X"}, + new String[]{"046", "-", "-", "2", "2", "C", "C"}, + new String[]{"047", "-", "-", "2", "2", "C", "V"}, + new String[]{"048", "-", "-", "2", "2", "C", "B"}, + new String[]{"049", "-", "-", "2", "2", "C", "N"}, + new String[]{"050", "-", "-", "2", "2", "C", "M"}, + new String[]{"051", "-", "-", "2", "2", "C", ","}, + new String[]{"052", "-", "-", "2", "2", "C", "."}, + new String[]{"053", "-", "-", "2", "2", "C", "/"}, + new String[]{"054", "-", "-", "5", "2", "C", "SH"}, + new String[]{"200", "33", "-", "2", "2", "C", "^"}, + new String[]{"079", "38", "-", "2", "2", "C", "1"}, + new String[]{"080", "-", "-", "2", "2", "C", "2"}, + new String[]{"081", "-", "-", "2", "2", "C", "3"}, + new String[]{"156", "-", "-", "2", "4", "C", "EN"}, + new String[]{"029", "0", "12", "3", "2", "C", "CT"}, + new String[]{"056", "5", "-", "3", "2", "C", "AL"}, + new String[]{"057", "-", "-", "14", "2", "C", "SP"}, + new String[]{"184", "-", "-", "3", "2", "C", "AL"}, + new String[]{"157", "27", "-", "3", "2", "C", "CT"}, + new String[]{"203", "31", "-", "2", "2", "C", "<"}, + new String[]{"208", "-", "-", "2", "2", "C", "v"}, + new String[]{"205", "-", "-", "2", "2", "C", ">"}, + new String[]{"082", "38", "-", "4", "2", "C", "0"}, + new String[]{"083", "-", "-", "2", "2", "C", "."}, + }; + + public JToggleButton addKey(String name, String topKey, int scanCode, int x, int y, int w, int h, char sizeCode, + boolean special) { String cmdName = name + "-" + (keyNo++); - JToggleButton button = new JToggleButton(name, false); - commandToKey.put(cmdName, new Integer(scanCode)); - commandToButton.put(cmdName, button); - ConstantTableLayout.Placement c = new ConstantTableLayout.Placement(x, y, w, h); - panel.add(button, c); - button.setActionCommand(cmdName); - button.addActionListener(this); - } + String label = name; + if(topKey != null) { + label = "" + topKey + "
" + name + ""; + } else if(label.indexOf('&') >= 0) { + label = "" + name + ""; + } + JToggleButton button = new JToggleButton(label, false); + if(sizeCode == 'N') { + button.setFont(keyFont); + button.setBorder(keyBorder); + } else if(sizeCode == 'S') { + button.setFont(smallKeyFont); + button.setBorder(smallKeyBorder); + } else if(sizeCode == 'C' && !nativeButtons) { + button.setBorder(classicBorder); + } - public JToggleButton addSpecial(String name, String text, int x, int y, int w, int h) - { - ConstantTableLayout.Placement c = new ConstantTableLayout.Placement(x, y, w, h); - JToggleButton button = new JToggleButton(text, false); - panel.add(button, c); - button.setEnabled(false); - button.setVisible(false); + button.setRolloverEnabled(false); + if(special) { + button.setEnabled(false); + button.setVisible(false); + } else { + commandToKey.put(cmdName, new Integer(scanCode)); + commandToButton.put(cmdName, button); + button.setActionCommand(cmdName); + button.addActionListener(this); + } + + if(!nativeButtons) button.setUI(new KeyboardButtonUI()); + + panel.add(button, new ConstantTableLayout.Placement(x, y, w, h)); return button; } @@ -84,139 +220,115 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi moveWindow(window, x.intValue(), y.intValue(), nativeWidth, nativeHeight); } + public VirtualKeyboard(Plugins _pluginManager) throws IOException + { + this(_pluginManager, ""); + } - public VirtualKeyboard(Plugins _pluginManager) + public VirtualKeyboard(Plugins _pluginManager, String args) throws IOException { - pluginManager = _pluginManager; - keyNo = 0; - keyboard = null; - commandToKey = new HashMap(); - commandToButton = new HashMap(); - window = new JFrame("Virtual Keyboard"); - ConstantTableLayout layout = new ConstantTableLayout(); - cachedState = new boolean[256]; - panel = new JPanel(layout); - window.add(panel); - addKey("Esc", 1, 0, 0, 3, 2); //Hack: W should be 2, but we use 3 to make keyboard narrower. - addKey("F1", 59, 4, 0, 2, 2); - addKey("F2", 60, 6, 0, 2, 2); - addKey("F3", 61, 8, 0, 2, 2); - addKey("F4", 62, 10, 0, 2, 2); - addKey("F5", 63, 13, 0, 2, 2); - addKey("F6", 64, 15, 0, 2, 2); - addKey("F7", 65, 17, 0, 2, 2); - addKey("F8", 66, 19, 0, 2, 2); - addKey("F9", 67, 22, 0, 2, 2); - addKey("FA", 68, 24, 0, 2, 2); - addKey("FB", 87, 26, 0, 2, 2); - addKey("FC", 88, 28, 0, 2, 2); - addKey("PS", 128 + 55, 31, 0, 2, 2); - addKey("SL", 70, 33, 0, 2, 2); - addKey("PA", 255, 35, 0, 2, 2); - - numLock = addSpecial("NumLock", "N", 38, 0, 2, 2); - capsLock = addSpecial("CapsLock", "C", 40, 0, 2, 2); - scrollLock = addSpecial("ScrollLock", "S", 42, 0, 2, 2); - - addKey("1", 2, 2, 4, 2, 2); - addKey("2", 3, 4, 4, 2, 2); - addKey("3", 4, 6, 4, 2, 2); - addKey("4", 5, 8, 4, 2, 2); - addKey("5", 6, 10, 4, 2, 2); - addKey("6", 7, 12, 4, 2, 2); - addKey("7", 8, 14, 4, 2, 2); - addKey("8", 9, 16, 4, 2, 2); - addKey("9", 10, 18, 4, 2, 2); - addKey("0", 11, 20, 4, 2, 2); - addKey("-", 12, 22, 4, 2, 2); - addKey("=", 13, 24, 4, 2, 2); - addKey("BS", 14, 26, 4, 4, 2); - addKey("I", 128 + 82, 31, 4, 2, 2); - addKey("H", 128 + 71, 33, 4, 2, 2); - addKey("PU", 128 + 73, 35, 4, 2, 2); - addKey("NL", 69, 38, 4, 2, 2); - addKey("/", 128 + 53, 40, 4, 2, 2); - addKey("*", 55, 42, 4, 2, 2); - addKey("-", 74, 44, 4, 2, 2); - - addKey("Tab", 15, 0, 6, 3, 2); - addKey("Q", 16, 3, 6, 2, 2); - addKey("W", 17, 5, 6, 2, 2); - addKey("E", 18, 7, 6, 2, 2); - addKey("R", 19, 9, 6, 2, 2); - addKey("T", 20, 11, 6, 2, 2); - addKey("Y", 21, 13, 6, 2, 2); - addKey("U", 22, 15, 6, 2, 2); - addKey("I", 23, 17, 6, 2, 2); - addKey("O", 24, 19, 6, 2, 2); - addKey("P", 25, 21, 6, 2, 2); - addKey("[", 26, 23, 6, 2, 2); - addKey("]", 27, 25, 6, 2, 2); - addKey("EN", 28, 28, 6, 2, 4); - addKey("D", 128 + 83, 31, 6, 2, 2); - addKey("E", 128 + 79, 33, 6, 2, 2); - addKey("PD", 128 + 81, 35, 6, 2, 2); - addKey("7", 71, 38, 6, 2, 2); - addKey("8", 72, 40, 6, 2, 2); - addKey("9", 73, 42, 6, 2, 2); - addKey("+", 78, 44, 6, 2, 4); - - addKey("CL", 58, 0, 8, 4, 2); - addKey("A", 30, 4, 8, 2, 2); - addKey("S", 31, 6, 8, 2, 2); - addKey("D", 32, 8, 8, 2, 2); - addKey("F", 33, 10, 8, 2, 2); - addKey("G", 34, 12, 8, 2, 2); - addKey("H", 35, 14, 8, 2, 2); - addKey("J", 36, 16, 8, 2, 2); - addKey("K", 37, 18, 8, 2, 2); - addKey("L", 38, 20, 8, 2, 2); - addKey(";", 39, 22, 8, 2, 2); - addKey("'", 40, 24, 8, 2, 2); - addKey("`", 41, 26, 8, 2, 2); - addKey("4", 75, 38, 8, 2, 2); - addKey("5", 76, 40, 8, 2, 2); - addKey("6", 77, 42, 8, 2, 2); - - addKey("SH", 42, 0, 10, 3, 2); - addKey("\\", 43, 3, 10, 2, 2); - addKey("Z", 44, 5, 10, 2, 2); - addKey("X", 45, 7, 10, 2, 2); - addKey("C", 46, 9, 10, 2, 2); - addKey("V", 47, 11, 10, 2, 2); - addKey("B", 48, 13, 10, 2, 2); - addKey("N", 49, 15, 10, 2, 2); - addKey("M", 50, 17, 10, 2, 2); - addKey(",", 51, 19, 10, 2, 2); - addKey(".", 52, 21, 10, 2, 2); - addKey("/", 53, 23, 10, 2, 2); - addKey("SH", 54, 25, 10, 5, 2); - addKey("^", 128 + 72, 33, 10, 2, 2); - addKey("1", 79, 38, 10, 2, 2); - addKey("2", 80, 40, 10, 2, 2); - addKey("3", 81, 42, 10, 2, 2); - addKey("EN", 128 + 28, 44, 10, 2, 4); - - addKey("CT", 29, 0, 12, 3, 2); - addKey("AL", 56, 5, 12, 3, 2); - addKey("SP", 57, 8, 12, 14, 2); - addKey("AL", 128 + 56, 22, 12, 3, 2); - addKey("CT", 128 + 29, 27, 12, 3, 2); - addKey("<", 128 + 75, 31, 12, 2, 2); - addKey("v", 128 + 80, 33, 12, 2, 2 ); - addKey(">", 128 + 77, 35, 12, 2, 2 ); - addKey("0", 82, 38, 12, 4, 2); - addKey(".", 83, 42, 12, 2, 2); - - window.pack(); - window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - Dimension d = window.getSize(); - nativeWidth = d.width; - nativeHeight = d.height; - window.setVisible(true); + pluginManager = _pluginManager; + Map params = parseStringToComponents(args); + String keyboardPath = params.get("keyboard"); + + nativeButtons = "native".equalsIgnoreCase(params.get("style")) || keyboardPath == null; + + keyNo = 0; + keyboard = null; + commandToKey = new HashMap(); + commandToButton = new HashMap(); + window = new JFrame("Virtual Keyboard"); + ConstantTableLayout layout = new ConstantTableLayout(); + cachedState = new boolean[256]; + panel = new JPanel(layout); + keyFont = new Font("SanSerif", Font.PLAIN, 11); + smallKeyFont = keyFont.deriveFont(9.0f); + + if(nativeButtons) { + keyBorder = new EmptyBorder(0, 5, 0, 5); + smallKeyBorder = new EmptyBorder(0, 1, 0, 1); + // classicBorder isn't used with native buttons + } else { + Border outerBorder = new CompoundBorder(new EmptyBorder(1, 1, 0, 0), new SimpleButtonBorder(false)); + keyBorder = new CompoundBorder(outerBorder, new EmptyBorder(0, 3, 0, 3)); + smallKeyBorder = new CompoundBorder(outerBorder, new EmptyBorder(0, 1, 0, 1)); + classicBorder = new SimpleButtonBorder(true); + } + + window.add(panel); + + parseKeyboardFile(keyboardPath); + + window.pack(); + window.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + Dimension d = window.getSize(); + nativeWidth = d.width; + nativeHeight = d.height; + window.setVisible(true); + } + + private static int parseCoord(String value, int next) + { + if("-".equals(value)) + return next; + else + return Integer.valueOf(value); + } + + private void handleKeyboardData(String[][] array) throws IOException + { + int nextX = 0, nextY = 0; + for(String[] line : array) { + if(line.length == 7 || line.length == 8) { + int x = parseCoord(line[1], nextX), y = parseCoord(line[2], nextY); + int w = Integer.parseInt(line[3]), h = Integer.parseInt(line[4]); + char sizeCode = line[5].charAt(0); + String name = line[6], shifted = null; + if(line.length == 8) + shifted = line[7]; + + try { + int scanCode = Integer.parseInt(line[0]); + addKey(name, shifted, scanCode, x, y, w, h, sizeCode, false); + } catch(NumberFormatException nfe) { // The scanCode wasn't a number, so this must be a special key + String scanName = line[0]; + JToggleButton specialButton = addKey(name, null, 0, x, y, w, h, sizeCode, true); + if(scanName.equalsIgnoreCase("numlock")) + numLock=specialButton; + else if(scanName.equalsIgnoreCase("capslock")) + capsLock=specialButton; + else if(scanName.equalsIgnoreCase("scrolllock")) + scrollLock=specialButton; + + } + nextX = x + w; + nextY = y; + } else + throw new IOException("Invalid line in keyboard layout: " + line.toString()); + } + } + + private void parseKeyboardFile(String filename) throws IOException + { + if(filename == null) { + handleKeyboardData(DEFAULT_KEYBOARD_DATA); + return; + } + + UTFInputLineStream keyboardFile = new UTFInputLineStream(new FileInputStream(filename)); + String[] line; + ArrayList data = new ArrayList(); + + while((line = Misc.nextParseLine(keyboardFile)) != null) + if(line.length <= 1) + continue; + else + data.add(line); + + handleKeyboardData((String[][])data.toArray(new String[data.size()][])); } - //-1 if unknonw, bit 2 is capslock, bit 1 is numlock, bit 0 is scrollock. + //-1 if unknown, bit 2 is capslock, bit 1 is numlock, bit 0 is scrollock. private void updateLEDs(int status) { if(status < 0) { @@ -227,12 +339,9 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi scrollLock.setVisible(false); scrollLock.setSelected(false); } else { - numLock.setVisible(true); - capsLock.setVisible(true); - scrollLock.setVisible(true); - numLock.setSelected((status & 2) != 0); - capsLock.setSelected((status & 4) != 0); - scrollLock.setSelected((status & 1) != 0); + numLock.setVisible((status & 2) != 0); + capsLock.setVisible((status & 4) != 0); + scrollLock.setVisible((status & 1) != 0); } } @@ -276,7 +385,8 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi try { final int _scancode = scancode; final boolean _pressed = pressed; - SwingUtilities.invokeLater(new Thread() { public void run() { VirtualKeyboard.this.keyStatusChangeEventThread(_scancode, _pressed); }}); + SwingUtilities.invokeLater(new Thread() { public void run() { + VirtualKeyboard.this.keyStatusChangeEventThread(_scancode, _pressed); }}); } catch(Exception e) { } else @@ -299,7 +409,8 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi if(!SwingUtilities.isEventDispatchThread()) try { final int _newstatus = newstatus; - SwingUtilities.invokeLater(new Thread() { public void run() { VirtualKeyboard.this.updateLEDs(_newstatus); }}); + SwingUtilities.invokeLater(new Thread() { public void run() { + VirtualKeyboard.this.updateLEDs(_newstatus); }}); } catch(Exception e) { } else @@ -375,7 +486,6 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi if(keyboard == null) return; - String command = evt.getActionCommand(); JToggleButton button = commandToButton.get(command); int scan = commandToKey.get(command).intValue(); @@ -402,4 +512,94 @@ public class VirtualKeyboard implements ActionListener, Plugin, KeyboardStatusLi cachedState[scan] = !cachedState[scan]; button.setSelected(cachedState[scan]); } + + protected static class KeyboardButtonUI extends BasicToggleButtonUI + { + protected static Color highlightColor = new Color(200, 200, 200); + protected static Color backgroundColor = new Color(220, 220, 220); + + protected void simplePaint(Graphics g, JComponent c, Color color) + { + Rectangle viewRect = new Rectangle(c.getSize()); + Insets margin; + try { + /* We want to ignore the inner margins while calculating the background size, so we have to + * pull the outside border out of the compound border */ + CompoundBorder border = (CompoundBorder)c.getBorder(); + margin = border.getOutsideBorder().getBorderInsets(c); + } catch(ClassCastException cce) { + // We were called on a button without our elaborate triple-border, so default to the whole inset + margin = c.getBorder().getBorderInsets(c); + } + + g.setColor(color); + + g.fillRect(viewRect.x + margin.left, viewRect.y + margin.top, + viewRect.width - (margin.left + margin.right), + viewRect.height - (margin.top + margin.bottom)); + } + + protected void paintButtonPressed(Graphics g, AbstractButton b) + { + simplePaint(g, b, highlightColor); + } + + public void paint(Graphics g, JComponent c) + { + simplePaint(g, c, backgroundColor); + super.paint(g, c); + } + } + + protected static class SimpleButtonBorder extends LineBorder + { + private static final long serialVersionUID = 1L; + + protected static Color nwColor=new Color(240, 240, 240); + protected static Color seColor=new Color(130, 130, 130); + protected static Color pressedColor=new Color(160, 160, 160); + protected boolean thin; + public SimpleButtonBorder(boolean thin) + { + super(Color.BLACK, 1, true); + this.thin = thin; + } + + public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, + final int height) + { + Color oldColor = g.getColor(); + JToggleButton button = (JToggleButton)c; + ButtonModel model = button.getModel(); + int adjust = thin ? 0 : 1; + + // Draw inner highlights + if(model.isSelected() || model.isPressed()) { + // Draw the north-west highlight, but in the south-east color + g.setColor(seColor); + g.drawRect(x + 1, y + 1, width - 2, 0); + g.drawRect(x + 1, y + 1, 0, height - 2); + } else { + // Draw the north-west highlight + g.setColor(nwColor); + g.drawRect(x + 1, y + 1, width - 2, adjust); + g.drawRect(x + 1, y + 1, adjust, height - 2); + // Draw the south-east highlight + g.setColor(seColor); + g.drawRect(x + 1, y + height - 2, width - 2, 0); + g.drawRect(x + width - 2, y + 1, 0, height - 2); + if(!thin) { // Draw inner line of shadow + g.drawRect(x + 2, y + height - 3, width - 3, 0); + g.drawRect(x + width - 3, y + 2, 0, height - 3); + } + } + + // Draw actual border + g.setColor(model.isPressed() ? pressedColor : lineColor); + g.drawRoundRect(x, y, width - 1, height - 1, 2, 2); + + // Restore color state + g.setColor(oldColor); + } + } } diff --git a/thinkpad.keyboard b/thinkpad.keyboard new file mode 100644 index 0000000..19094cf --- /dev/null +++ b/thinkpad.keyboard @@ -0,0 +1,98 @@ +(Code X Y W H Size Name Shifted) +001 0 0 8 4 S Esc +183 71 - 7 4 S PrtSc +070 - - 7 4 S ScrLk +255 - - 7 4 S Pause +210 99 - 7 4 S Ins +199 - - 7 4 S Home +201 - - 7 4 S PgUp + +NumLock 39 0 4 3 N N +CapsLock 43 - 4 3 N C +ScrollLock 47 - 4 3 N S + +059 0 4 7 4 S F1 +060 - - 7 4 S F2 +061 - - 7 4 S F3 +062 - - 7 4 S F4 +063 32 - 7 4 S F5 +064 - - 7 4 S F6 +065 - - 7 4 S F7 +066 - - 7 4 S F8 +067 64 - 7 4 S F9 +068 - - 7 4 S F10 +087 - - 7 4 S F11 +088 - - 7 4 S F12 +211 99 - 7 4 S Del +207 106 - 7 4 S End +209 113 - 7 4 S PgDn + +041 0 8 8 6 N ` ~ +002 - - 8 6 N 1 ! +003 - - 8 6 N 2 @ +004 - - 8 6 N 3 # +005 - - 8 6 N 4 $ +006 - - 8 6 N 5 % +007 - - 8 6 N 6 ^ +008 - - 8 6 N 7 & +009 - - 8 6 N 8 * +010 - - 8 6 N 9 \( +011 - - 8 6 N 0 \) +012 - - 8 6 N - _ +013 - - 8 6 N = + +014 - - 16 6 S (← Backspace) + + +015 0 14 12 6 N Tab +016 - - 8 6 N Q +017 - - 8 6 N W +018 - - 8 6 N E +019 - - 8 6 N R +020 - - 8 6 N T +021 - - 8 6 N Y +022 - - 8 6 N U +023 - - 8 6 N I +024 - - 8 6 N O +025 - - 8 6 N P +026 - - 8 6 N [ { +027 - - 8 6 N ] } +043 - - 12 6 N \\ | + +058 0 20 16 6 N Caps +030 - - 8 6 N A +031 - - 8 6 N S +032 - - 8 6 N D +033 - - 8 6 N F +034 - - 8 6 N G +035 - - 8 6 N H +036 - - 8 6 N J +037 - - 8 6 N K +038 - - 8 6 N L +039 - - 8 6 N ; : +040 - - 8 6 N ' " +028 - - 16 6 N (↲ Enter) + +042 0 26 20 6 N (⇧ Shift) +044 - - 8 6 N Z +045 - - 8 6 N X +046 - - 8 6 N C +047 - - 8 6 N V +048 - - 8 6 N B +049 - - 8 6 N N +050 - - 8 6 N M +051 - - 8 6 N , < +052 - - 8 6 N . > +053 - - 8 6 N / ? +054 - - 20 6 N (⇧ Shift) + +029 12 32 8 6 N Ctrl +056 26 32 8 6 N Alt +057 - 32 42 6 N ( ) +184 - 32 8 6 N Alt +157 92 32 8 6 N Ctrl + +200 107 32 6 4 N ↑ + +203 101 36 6 4 N ← +208 - - 6 4 N ↓ +205 - - 6 4 N → diff --git a/updated.keyboard b/updated.keyboard new file mode 100644 index 0000000..fbdf5be --- /dev/null +++ b/updated.keyboard @@ -0,0 +1,111 @@ +(Code X Y W H Size Name Shifted) +001 0 0 2 2 S Esc +059 4 - 2 2 S F1 +060 - - 2 2 S F2 +061 - - 2 2 S F3 +062 - - 2 2 S F4 +063 13 - 2 2 S F5 +064 - - 2 2 S F6 +065 - - 2 2 S F7 +066 - - 2 2 S F8 +067 22 - 2 2 S F9 +068 - - 2 2 S F10 +087 - - 2 2 S F11 +088 - - 2 2 S F12 +183 31 - 3 2 S SysRq PrtScn +070 - - 3 2 S ScrLk +255 - - 3 2 S Break Pause + +NumLock 43 0 1 1 N N +CapsLock 44 0 1 1 N C +ScrollLock 45 0 1 1 N S + +041 0 4 2 2 N ` ~ +002 - - 2 2 N 1 ! +003 - - 2 2 N 2 @ +004 - - 2 2 N 3 # +005 - - 2 2 N 4 $ +006 - - 2 2 N 5 % +007 - - 2 2 N 6 ^ +008 - - 2 2 N 7 & +009 - - 2 2 N 8 * +010 - - 2 2 N 9 \( +011 - - 2 2 N 0 \) +012 - - 2 2 N - _ +013 - - 2 2 N = + +014 - - 4 2 S Backspace +210 31 - 2 2 S Ins +199 - - 2 2 S Home +201 - - 2 2 S PgUp +069 38 - 2 2 S Num +181 - - 2 2 N / +055 - - 2 2 N * +074 - - 2 2 N - + +015 0 6 3 2 N Tab +016 - - 2 2 N Q +017 - - 2 2 N W +018 - - 2 2 N E +019 - - 2 2 N R +020 - - 2 2 N T +021 - - 2 2 N Y +022 - - 2 2 N U +023 - - 2 2 N I +024 - - 2 2 N O +025 - - 2 2 N P +026 - - 2 2 N [ { +027 - - 2 2 N ] } +043 - - 3 2 N \\ | +211 31 - 2 2 S Del +207 - - 2 2 S End +209 - - 2 2 S PgDn +071 38 - 2 2 S Home 7 +072 - - 2 2 S ↑ - +073 - - 2 2 S PgUp 9 +078 - - 2 4 N + + +058 0 8 4 2 N Caps +030 - - 2 2 N A +031 - - 2 2 N S +032 - - 2 2 N D +033 - - 2 2 N F +034 - - 2 2 N G +035 - - 2 2 N H +036 - - 2 2 N J +037 - - 2 2 N K +038 - - 2 2 N L +039 - - 2 2 N ; : +040 - - 2 2 N ' " +028 - - 4 2 N Enter +075 38 - 2 2 S ← 4 +076 - - 2 2 S   5 +077 - - 2 2 S → 6 + +042 0 10 5 2 N Shift +044 - - 2 2 N Z +045 - - 2 2 N X +046 - - 2 2 N C +047 - - 2 2 N V +048 - - 2 2 N B +049 - - 2 2 N N +050 - - 2 2 N M +051 - - 2 2 N , < +052 - - 2 2 N . > +053 - - 2 2 N / ? +054 - - 5 2 N Shift +200 33 - 2 2 N ↑ +079 38 - 2 2 S End 1 +080 - - 2 2 S ↓ 2 +081 - - 2 2 S PgDn 3 +156 - - 2 4 S Enter + +029 0 12 3 2 N Ctrl +056 - - 3 2 N Alt +057 - - 14 2 N ( ) +184 - - 3 2 N Alt +157 27 - 3 2 N Ctrl +203 31 - 2 2 N ← +208 - - 2 2 N ↓ +205 - - 2 2 N → +082 38 - 4 2 N Ins 0 +083 - - 2 2 N Del . -- 2.11.4.GIT