From: Kevin Lamonte Date: Mon, 16 Mar 2015 15:45:46 +0000 (-0400) Subject: AWT keyboard barely working X-Git-Url: http://git.nikiroo.be/?a=commitdiff_plain;h=84614868e6bcbe374c0c1ba248ad046ff25ccb2b;p=fanfix.git AWT keyboard barely working --- diff --git a/build.xml b/build.xml index 35aee17..f47d041 100644 --- a/build.xml +++ b/build.xml @@ -30,10 +30,11 @@ - - - - + + + + + @@ -49,6 +50,7 @@ + diff --git a/resources/terminus-ttf-4.39/COPYING b/resources/terminus-ttf-4.39/COPYING new file mode 100644 index 0000000..c964194 --- /dev/null +++ b/resources/terminus-ttf-4.39/COPYING @@ -0,0 +1,97 @@ +Copyright (c) 2010 Dimitar Toshkov Zhekov, +with Reserved Font Name "Terminus Font". + +Copyright (c) 2011 Tilman Blumenbach, +with Reserved Font Name "Terminus (TTF)". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/resources/terminus-ttf-4.39/TerminusTTF-4.39.ttf b/resources/terminus-ttf-4.39/TerminusTTF-4.39.ttf new file mode 100644 index 0000000..f4bb6b2 Binary files /dev/null and b/resources/terminus-ttf-4.39/TerminusTTF-4.39.ttf differ diff --git a/resources/terminus-ttf-4.39/TerminusTTF-Bold-4.39.ttf b/resources/terminus-ttf-4.39/TerminusTTF-Bold-4.39.ttf new file mode 100644 index 0000000..06700de Binary files /dev/null and b/resources/terminus-ttf-4.39/TerminusTTF-Bold-4.39.ttf differ diff --git a/resources/terminus-ttf-4.39/TerminusTTF-Italic-4.39.ttf b/resources/terminus-ttf-4.39/TerminusTTF-Italic-4.39.ttf new file mode 100644 index 0000000..e80d0c0 Binary files /dev/null and b/resources/terminus-ttf-4.39/TerminusTTF-Italic-4.39.ttf differ diff --git a/src/jexer/io/AWTScreen.java b/src/jexer/io/AWTScreen.java index e10e0ec..2b913f1 100644 --- a/src/jexer/io/AWTScreen.java +++ b/src/jexer/io/AWTScreen.java @@ -39,18 +39,72 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Frame; import java.awt.Graphics; +import java.awt.Insets; import java.awt.geom.Rectangle2D; +import java.io.InputStream; /** * This Screen implementation draws to a Java AWT Frame. */ public final class AWTScreen extends Screen { + private static Color MYBLACK; + private static Color MYRED; + private static Color MYGREEN; + private static Color MYYELLOW; + private static Color MYBLUE; + private static Color MYMAGENTA; + private static Color MYCYAN; + private static Color MYWHITE; + + private static Color MYBOLD_BLACK; + private static Color MYBOLD_RED; + private static Color MYBOLD_GREEN; + private static Color MYBOLD_YELLOW; + private static Color MYBOLD_BLUE; + private static Color MYBOLD_MAGENTA; + private static Color MYBOLD_CYAN; + private static Color MYBOLD_WHITE; + + private static boolean dosColors = false; + + /** + * Setup AWT colors to match DOS color palette. + */ + private static void setDOSColors() { + if (dosColors) { + return; + } + MYBLACK = new Color(0x00, 0x00, 0x00); + MYRED = new Color(0xa8, 0x00, 0x00); + MYGREEN = new Color(0x00, 0xa8, 0x00); + MYYELLOW = new Color(0xa8, 0x54, 0x00); + MYBLUE = new Color(0x00, 0x00, 0xa8); + MYMAGENTA = new Color(0xa8, 0x00, 0xa8); + MYCYAN = new Color(0x00, 0xa8, 0xa8); + MYWHITE = new Color(0xa8, 0xa8, 0xa8); + MYBOLD_BLACK = new Color(0x54, 0x54, 0x54); + MYBOLD_RED = new Color(0xfc, 0x54, 0x54); + MYBOLD_GREEN = new Color(0x54, 0xfc, 0x54); + MYBOLD_YELLOW = new Color(0xfc, 0xfc, 0x54); + MYBOLD_BLUE = new Color(0x54, 0x54, 0xfc); + MYBOLD_MAGENTA = new Color(0xfc, 0x54, 0xfc); + MYBOLD_CYAN = new Color(0x54, 0xfc, 0xfc); + MYBOLD_WHITE = new Color(0xfc, 0xfc, 0xfc); + + dosColors = true; + } + /** * AWTFrame is our top-level hook into the AWT system. */ class AWTFrame extends Frame { + /** + * The terminus font resource filename. + */ + private static final String FONTFILE = "terminus-ttf-4.39/TerminusTTF-Bold-4.39.ttf"; + /** * The TUI Screen data. */ @@ -66,41 +120,165 @@ public final class AWTScreen extends Screen { */ private int textHeight = 1; + /** + * Descent of a character cell. + */ + private int maxDescent = 0; + /** * Top pixel value. */ private int top = 30; - + /** * Left pixel value. */ private int left = 30; - + + /** + * Convert a CellAttributes foreground color to an AWT Color. + * + * @param attr the text attributes + * @return the AWT Color + */ + private Color attrToForegroundColor(final CellAttributes attr) { + /* + * TODO: + * reverse + * blink + * underline + */ + if (attr.getBold()) { + if (attr.getForeColor().equals(jexer.bits.Color.BLACK)) { + return MYBOLD_BLACK; + } else if (attr.getForeColor().equals(jexer.bits.Color.RED)) { + return MYBOLD_RED; + } else if (attr.getForeColor().equals(jexer.bits.Color.BLUE)) { + return MYBOLD_BLUE; + } else if (attr.getForeColor().equals(jexer.bits.Color.GREEN)) { + return MYBOLD_GREEN; + } else if (attr.getForeColor().equals(jexer.bits.Color.YELLOW)) { + return MYBOLD_YELLOW; + } else if (attr.getForeColor().equals(jexer.bits.Color.CYAN)) { + return MYBOLD_CYAN; + } else if (attr.getForeColor().equals(jexer.bits.Color.MAGENTA)) { + return MYBOLD_MAGENTA; + } else if (attr.getForeColor().equals(jexer.bits.Color.WHITE)) { + return MYBOLD_WHITE; + } + } else { + if (attr.getForeColor().equals(jexer.bits.Color.BLACK)) { + return MYBLACK; + } else if (attr.getForeColor().equals(jexer.bits.Color.RED)) { + return MYRED; + } else if (attr.getForeColor().equals(jexer.bits.Color.BLUE)) { + return MYBLUE; + } else if (attr.getForeColor().equals(jexer.bits.Color.GREEN)) { + return MYGREEN; + } else if (attr.getForeColor().equals(jexer.bits.Color.YELLOW)) { + return MYYELLOW; + } else if (attr.getForeColor().equals(jexer.bits.Color.CYAN)) { + return MYCYAN; + } else if (attr.getForeColor().equals(jexer.bits.Color.MAGENTA)) { + return MYMAGENTA; + } else if (attr.getForeColor().equals(jexer.bits.Color.WHITE)) { + return MYWHITE; + } + } + throw new IllegalArgumentException("Invalid color: " + attr.getForeColor().getValue()); + } + + /** + * Convert a CellAttributes background color to an AWT Color. + * + * @param attr the text attributes + * @return the AWT Color + */ + private Color attrToBackgroundColor(final CellAttributes attr) { + /* + * TODO: + * reverse + * blink + * underline + */ + if (attr.getBackColor().equals(jexer.bits.Color.BLACK)) { + return MYBLACK; + } else if (attr.getBackColor().equals(jexer.bits.Color.RED)) { + return MYRED; + } else if (attr.getBackColor().equals(jexer.bits.Color.BLUE)) { + return MYBLUE; + } else if (attr.getBackColor().equals(jexer.bits.Color.GREEN)) { + return MYGREEN; + } else if (attr.getBackColor().equals(jexer.bits.Color.YELLOW)) { + return MYYELLOW; + } else if (attr.getBackColor().equals(jexer.bits.Color.CYAN)) { + return MYCYAN; + } else if (attr.getBackColor().equals(jexer.bits.Color.MAGENTA)) { + return MYMAGENTA; + } else if (attr.getBackColor().equals(jexer.bits.Color.WHITE)) { + return MYWHITE; + } + throw new IllegalArgumentException("Invalid color: " + attr.getBackColor().getValue()); + } + /** * Public constructor. + * + * @param screen the Screen that Backend talks to */ - public AWTFrame() { + public AWTFrame(final AWTScreen screen) { + this.screen = screen; + setDOSColors(); + setTitle("Jexer Application"); setBackground(java.awt.Color.black); setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); - setFont(new Font("Liberation Mono", Font.BOLD, 16)); + // setFont(new Font("Liberation Mono", Font.BOLD, 16)); // setFont(new Font(Font.MONOSPACED, Font.PLAIN, 16)); - setSize(100, 100); + + try { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + InputStream in = loader.getResourceAsStream(FONTFILE); + Font terminusRoot = Font.createFont(Font.TRUETYPE_FONT, in); + Font terminus = terminusRoot.deriveFont(Font.PLAIN, 22); + setFont(terminus); + } catch (Exception e) { + e.printStackTrace(); + // setFont(new Font("Liberation Mono", Font.PLAIN, 24)); + setFont(new Font(Font.MONOSPACED, Font.PLAIN, 24)); + } setVisible(true); + resizeToScreen(); } /** * Resize to font dimensions. */ public void resizeToScreen() { - Graphics gr = getGraphics(); - FontMetrics fm = gr.getFontMetrics(); - textWidth = fm.charWidth('m'); - textHeight = fm.getHeight(); - setSize((textWidth + 1) * screen.width + (2 * left), - (textHeight + 1) * screen.height + (2 * top)); - - System.err.printf("W: %d H: %d\n", textWidth, textHeight); + Graphics gr = getGraphics(); + FontMetrics fm = gr.getFontMetrics(); + maxDescent = fm.getMaxDescent(); + Rectangle2D bounds = fm.getMaxCharBounds(gr); + int leading = fm.getLeading(); + textWidth = (int)Math.round(bounds.getWidth()); + textHeight = (int)Math.round(bounds.getHeight()) - maxDescent; + // This also produces the same number, but works better for ugly + // monospace. + textHeight = fm.getMaxAscent() + maxDescent - leading; + + // Figure out the thickness of borders and use that to set the + // final size. + Insets insets = getInsets(); + left = insets.left; + top = insets.top; + + setSize(textWidth * screen.width + insets.left + insets.right, + textHeight * screen.height + insets.top + insets.bottom); + + /* + System.err.printf("W: %d H: %d MD: %d L: %d\n", textWidth, + textHeight, maxDescent, leading); + */ } /** @@ -109,60 +287,27 @@ public final class AWTScreen extends Screen { * @param gr the AWT Graphics context */ @Override - public void paint(Graphics gr) { + public void paint(final Graphics gr) { for (int y = 0; y < screen.height; y++) { for (int x = 0; x < screen.width; x++) { Cell lCell = screen.logical[x][y]; Cell pCell = screen.physical[x][y]; - int xPixel = x * (textWidth + 1) + left; - int yPixel = y * (textHeight + 1) + top - y; + int xPixel = x * textWidth + left; + int yPixel = y * textHeight + top; if (!lCell.equals(pCell)) { + // Draw the background rectangle, then the foreground // character. - if (lCell.getBackColor().equals(jexer.bits.Color.BLACK)) { - gr.setColor(Color.black); - } else if (lCell.getBackColor().equals(jexer.bits.Color.RED)) { - gr.setColor(Color.red); - } else if (lCell.getBackColor().equals(jexer.bits.Color.BLUE)) { - gr.setColor(Color.blue); - } else if (lCell.getBackColor().equals(jexer.bits.Color.GREEN)) { - gr.setColor(Color.green); - } else if (lCell.getBackColor().equals(jexer.bits.Color.YELLOW)) { - gr.setColor(Color.yellow); - } else if (lCell.getBackColor().equals(jexer.bits.Color.CYAN)) { - gr.setColor(Color.cyan); - } else if (lCell.getBackColor().equals(jexer.bits.Color.MAGENTA)) { - gr.setColor(Color.magenta); - } else if (lCell.getBackColor().equals(jexer.bits.Color.WHITE)) { - gr.setColor(Color.white); - } - gr.fillRect(xPixel, yPixel, textWidth + 1, - textHeight + 2); - - if (lCell.getForeColor().equals(jexer.bits.Color.BLACK)) { - gr.setColor(Color.black); - } else if (lCell.getForeColor().equals(jexer.bits.Color.RED)) { - gr.setColor(Color.red); - } else if (lCell.getForeColor().equals(jexer.bits.Color.BLUE)) { - gr.setColor(Color.blue); - } else if (lCell.getForeColor().equals(jexer.bits.Color.GREEN)) { - gr.setColor(Color.green); - } else if (lCell.getForeColor().equals(jexer.bits.Color.YELLOW)) { - gr.setColor(Color.yellow); - } else if (lCell.getForeColor().equals(jexer.bits.Color.CYAN)) { - gr.setColor(Color.cyan); - } else if (lCell.getForeColor().equals(jexer.bits.Color.MAGENTA)) { - gr.setColor(Color.magenta); - } else if (lCell.getForeColor().equals(jexer.bits.Color.WHITE)) { - gr.setColor(Color.white); - } + gr.setColor(attrToBackgroundColor(lCell)); + gr.fillRect(xPixel, yPixel, textWidth, textHeight); + gr.setColor(attrToForegroundColor(lCell)); char [] chars = new char[1]; chars[0] = lCell.getChar(); gr.drawChars(chars, 0, 1, xPixel, - yPixel + textHeight - 2); + yPixel + textHeight - maxDescent); // Physical is always updated physical[x][y].setTo(lCell); @@ -173,17 +318,15 @@ public final class AWTScreen extends Screen { } /** - * The raw AWT Frame. + * The raw AWT Frame. Note package private access. */ - private AWTFrame frame; + AWTFrame frame; /** * Public constructor. */ public AWTScreen() { - frame = new AWTFrame(); - frame.screen = this; - frame.resizeToScreen(); + frame = new AWTFrame(this); } /** diff --git a/src/jexer/io/AWTTerminal.java b/src/jexer/io/AWTTerminal.java index c9ddc13..fd03487 100644 --- a/src/jexer/io/AWTTerminal.java +++ b/src/jexer/io/AWTTerminal.java @@ -30,6 +30,10 @@ */ package jexer.io; +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowListener; import java.util.List; import java.util.LinkedList; @@ -46,7 +50,12 @@ import static jexer.TKeypress.*; /** * This class reads keystrokes and mouse events from an AWT Frame. */ -public final class AWTTerminal { +public final class AWTTerminal implements KeyListener { + + /** + * The backend Screen. + */ + private AWTScreen screen; /** * The session information. @@ -106,15 +115,18 @@ public final class AWTTerminal { /** * Constructor sets up state for getEvent(). * - * @param screen the top-level AWT frame + * @param screen the top-level AWT frame */ public AWTTerminal(final AWTScreen screen) { + this.screen = screen; mouse1 = false; mouse2 = false; mouse3 = false; stopReaderThread = false; sessionInfo = new TSessionInfo(); eventQueue = new LinkedList(); + + screen.frame.addKeyListener(this); } /** @@ -122,6 +134,7 @@ public final class AWTTerminal { */ public void shutdown() { // System.err.println("=== shutdown() ==="); System.err.flush(); + screen.frame.dispose(); } /** @@ -160,4 +173,213 @@ public final class AWTTerminal { } } + /** + * Pass AWT keystrokes into the event queue. + * + * @param key keystroke received + */ + @Override + public void keyReleased(final KeyEvent key) { + // Ignore release events + } + + /** + * Pass AWT keystrokes into the event queue. + * + * @param key keystroke received + */ + @Override + public void keyTyped(final KeyEvent key) { + // Ignore typed events + } + + /** + * Pass AWT keystrokes into the event queue. + * + * @param key keystroke received + */ + @Override + public void keyPressed(final KeyEvent key) { + boolean alt = false; + boolean shift = false; + boolean ctrl = false; + char ch = ' '; + boolean isKey = false; + int fnKey = 0; + if (key.isActionKey()) { + isKey = true; + } else { + ch = key.getKeyChar(); + } + alt = key.isAltDown(); + ctrl = key.isControlDown(); + shift = key.isShiftDown(); + + /* + System.err.printf("AWT Key: %s\n", key); + System.err.printf(" isKey: %s\n", isKey); + System.err.printf(" alt: %s\n", alt); + System.err.printf(" ctrl: %s\n", ctrl); + System.err.printf(" shift: %s\n", shift); + System.err.printf(" ch: %s\n", ch); + */ + + // Special case: not return the bare modifier presses + switch (key.getKeyCode()) { + case KeyEvent.VK_ALT: + return; + case KeyEvent.VK_ALT_GRAPH: + return; + case KeyEvent.VK_CONTROL: + return; + case KeyEvent.VK_SHIFT: + return; + case KeyEvent.VK_META: + return; + default: + break; + } + + TKeypress keypress = null; + if (isKey) { + switch (key.getKeyCode()) { + case KeyEvent.VK_F1: + keypress = new TKeypress(true, TKeypress.F1, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F2: + keypress = new TKeypress(true, TKeypress.F2, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F3: + keypress = new TKeypress(true, TKeypress.F3, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F4: + keypress = new TKeypress(true, TKeypress.F4, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F5: + keypress = new TKeypress(true, TKeypress.F5, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F6: + keypress = new TKeypress(true, TKeypress.F6, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F7: + keypress = new TKeypress(true, TKeypress.F7, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F8: + keypress = new TKeypress(true, TKeypress.F8, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F9: + keypress = new TKeypress(true, TKeypress.F9, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F10: + keypress = new TKeypress(true, TKeypress.F10, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F11: + keypress = new TKeypress(true, TKeypress.F11, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_F12: + keypress = new TKeypress(true, TKeypress.F12, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_HOME: + keypress = new TKeypress(true, TKeypress.HOME, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_END: + keypress = new TKeypress(true, TKeypress.END, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_PAGE_UP: + keypress = new TKeypress(true, TKeypress.PGUP, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_PAGE_DOWN: + keypress = new TKeypress(true, TKeypress.PGDN, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_INSERT: + keypress = new TKeypress(true, TKeypress.INS, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_DELETE: + keypress = new TKeypress(true, TKeypress.F1, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_RIGHT: + keypress = new TKeypress(true, TKeypress.RIGHT, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_LEFT: + keypress = new TKeypress(true, TKeypress.LEFT, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_UP: + keypress = new TKeypress(true, TKeypress.UP, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_DOWN: + keypress = new TKeypress(true, TKeypress.DOWN, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_TAB: + // Special case: distinguish TAB vs BTAB + if (shift) { + keypress = kbShiftTab; + } else { + keypress = kbTab; + } + break; + case KeyEvent.VK_ENTER: + keypress = new TKeypress(true, TKeypress.ENTER, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_ESCAPE: + keypress = new TKeypress(true, TKeypress.ESC, ' ', + alt, ctrl, shift); + break; + case KeyEvent.VK_BACK_SPACE: + // Special case: return it as kbBackspace (Ctrl-H) + keypress = new TKeypress(false, 0, 'H', false, true, false); + break; + default: + // Unsupported, ignore + return; + } + } + + if (keypress == null) { + switch (ch) { + case 0x08: + keypress = kbBackspace; + break; + case 0x0A: + keypress = kbEnter; + break; + case 0x0D: + keypress = kbEnter; + break; + default: + if (!alt && ctrl && !shift) { + ch = key.getKeyText(key.getKeyCode()).charAt(0); + } + // Not a special key, put it together + keypress = new TKeypress(false, 0, ch, alt, ctrl, shift); + } + } + + // Save it and we are done. + synchronized (eventQueue) { + eventQueue.add(new TKeypressEvent(keypress)); + } + } }