AWT keyboard barely working
[nikiroo-utils.git] / src / jexer / io / AWTTerminal.java
CommitLineData
1ac2ccb1
KL
1/**
2 * Jexer - Java Text User Interface
3 *
4 * License: LGPLv3 or later
5 *
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
9 *
10 * Copyright (C) 2015 Kevin Lamonte
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * 02110-1301 USA
27 *
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
29 * @version 1
30 */
31package jexer.io;
32
84614868
KL
33import java.awt.event.KeyListener;
34import java.awt.event.KeyEvent;
35import java.awt.event.MouseListener;
36import java.awt.event.WindowListener;
1ac2ccb1
KL
37import java.util.List;
38import java.util.LinkedList;
39
40import jexer.TKeypress;
41import jexer.bits.Color;
42import jexer.event.TInputEvent;
43import jexer.event.TKeypressEvent;
44import jexer.event.TMouseEvent;
45import jexer.event.TResizeEvent;
46import jexer.session.SessionInfo;
47import jexer.session.TSessionInfo;
48import static jexer.TKeypress.*;
49
50/**
51 * This class reads keystrokes and mouse events from an AWT Frame.
52 */
84614868
KL
53public final class AWTTerminal implements KeyListener {
54
55 /**
56 * The backend Screen.
57 */
58 private AWTScreen screen;
1ac2ccb1
KL
59
60 /**
61 * The session information.
62 */
63 private SessionInfo sessionInfo;
64
65 /**
66 * Getter for sessionInfo.
67 *
68 * @return the SessionInfo
69 */
70 public SessionInfo getSessionInfo() {
71 return sessionInfo;
72 }
73
74 /**
75 * The event queue, filled up by a thread reading on input.
76 */
77 private List<TInputEvent> eventQueue;
78
79 /**
80 * If true, we want the reader thread to exit gracefully.
81 */
82 private boolean stopReaderThread;
83
84 /**
85 * The reader thread.
86 */
87 private Thread readerThread;
88
89 /**
90 * true if mouse1 was down. Used to report mouse1 on the release event.
91 */
92 private boolean mouse1;
93
94 /**
95 * true if mouse2 was down. Used to report mouse2 on the release event.
96 */
97 private boolean mouse2;
98
99 /**
100 * true if mouse3 was down. Used to report mouse3 on the release event.
101 */
102 private boolean mouse3;
103
104 /**
105 * Check if there are events in the queue.
106 *
107 * @return if true, getEvents() has something to return to the backend
108 */
109 public boolean hasEvents() {
110 synchronized (eventQueue) {
111 return (eventQueue.size() > 0);
112 }
113 }
114
115 /**
116 * Constructor sets up state for getEvent().
117 *
84614868 118 * @param screen the top-level AWT frame
1ac2ccb1
KL
119 */
120 public AWTTerminal(final AWTScreen screen) {
84614868 121 this.screen = screen;
1ac2ccb1
KL
122 mouse1 = false;
123 mouse2 = false;
124 mouse3 = false;
125 stopReaderThread = false;
126 sessionInfo = new TSessionInfo();
127 eventQueue = new LinkedList<TInputEvent>();
84614868
KL
128
129 screen.frame.addKeyListener(this);
1ac2ccb1
KL
130 }
131
132 /**
133 * Restore terminal to normal state.
134 */
135 public void shutdown() {
136 // System.err.println("=== shutdown() ==="); System.err.flush();
84614868 137 screen.frame.dispose();
1ac2ccb1
KL
138 }
139
140 /**
141 * Return any events in the IO queue.
142 *
143 * @param queue list to append new events to
144 */
145 public void getEvents(final List<TInputEvent> queue) {
146 synchronized (eventQueue) {
147 if (eventQueue.size() > 0) {
148 synchronized (queue) {
149 queue.addAll(eventQueue);
150 }
151 eventQueue.clear();
152 }
153 }
154 }
155
156 /**
157 * Return any events in the IO queue due to timeout.
158 *
159 * @param queue list to append new events to
160 */
161 public void getIdleEvents(final List<TInputEvent> queue) {
162
163 // Insert any polling action here...
164
165 // Return any events that showed up
166 synchronized (eventQueue) {
167 if (eventQueue.size() > 0) {
168 synchronized (queue) {
169 queue.addAll(eventQueue);
170 }
171 eventQueue.clear();
172 }
173 }
174 }
175
84614868
KL
176 /**
177 * Pass AWT keystrokes into the event queue.
178 *
179 * @param key keystroke received
180 */
181 @Override
182 public void keyReleased(final KeyEvent key) {
183 // Ignore release events
184 }
185
186 /**
187 * Pass AWT keystrokes into the event queue.
188 *
189 * @param key keystroke received
190 */
191 @Override
192 public void keyTyped(final KeyEvent key) {
193 // Ignore typed events
194 }
195
196 /**
197 * Pass AWT keystrokes into the event queue.
198 *
199 * @param key keystroke received
200 */
201 @Override
202 public void keyPressed(final KeyEvent key) {
203 boolean alt = false;
204 boolean shift = false;
205 boolean ctrl = false;
206 char ch = ' ';
207 boolean isKey = false;
208 int fnKey = 0;
209 if (key.isActionKey()) {
210 isKey = true;
211 } else {
212 ch = key.getKeyChar();
213 }
214 alt = key.isAltDown();
215 ctrl = key.isControlDown();
216 shift = key.isShiftDown();
217
218 /*
219 System.err.printf("AWT Key: %s\n", key);
220 System.err.printf(" isKey: %s\n", isKey);
221 System.err.printf(" alt: %s\n", alt);
222 System.err.printf(" ctrl: %s\n", ctrl);
223 System.err.printf(" shift: %s\n", shift);
224 System.err.printf(" ch: %s\n", ch);
225 */
226
227 // Special case: not return the bare modifier presses
228 switch (key.getKeyCode()) {
229 case KeyEvent.VK_ALT:
230 return;
231 case KeyEvent.VK_ALT_GRAPH:
232 return;
233 case KeyEvent.VK_CONTROL:
234 return;
235 case KeyEvent.VK_SHIFT:
236 return;
237 case KeyEvent.VK_META:
238 return;
239 default:
240 break;
241 }
242
243 TKeypress keypress = null;
244 if (isKey) {
245 switch (key.getKeyCode()) {
246 case KeyEvent.VK_F1:
247 keypress = new TKeypress(true, TKeypress.F1, ' ',
248 alt, ctrl, shift);
249 break;
250 case KeyEvent.VK_F2:
251 keypress = new TKeypress(true, TKeypress.F2, ' ',
252 alt, ctrl, shift);
253 break;
254 case KeyEvent.VK_F3:
255 keypress = new TKeypress(true, TKeypress.F3, ' ',
256 alt, ctrl, shift);
257 break;
258 case KeyEvent.VK_F4:
259 keypress = new TKeypress(true, TKeypress.F4, ' ',
260 alt, ctrl, shift);
261 break;
262 case KeyEvent.VK_F5:
263 keypress = new TKeypress(true, TKeypress.F5, ' ',
264 alt, ctrl, shift);
265 break;
266 case KeyEvent.VK_F6:
267 keypress = new TKeypress(true, TKeypress.F6, ' ',
268 alt, ctrl, shift);
269 break;
270 case KeyEvent.VK_F7:
271 keypress = new TKeypress(true, TKeypress.F7, ' ',
272 alt, ctrl, shift);
273 break;
274 case KeyEvent.VK_F8:
275 keypress = new TKeypress(true, TKeypress.F8, ' ',
276 alt, ctrl, shift);
277 break;
278 case KeyEvent.VK_F9:
279 keypress = new TKeypress(true, TKeypress.F9, ' ',
280 alt, ctrl, shift);
281 break;
282 case KeyEvent.VK_F10:
283 keypress = new TKeypress(true, TKeypress.F10, ' ',
284 alt, ctrl, shift);
285 break;
286 case KeyEvent.VK_F11:
287 keypress = new TKeypress(true, TKeypress.F11, ' ',
288 alt, ctrl, shift);
289 break;
290 case KeyEvent.VK_F12:
291 keypress = new TKeypress(true, TKeypress.F12, ' ',
292 alt, ctrl, shift);
293 break;
294 case KeyEvent.VK_HOME:
295 keypress = new TKeypress(true, TKeypress.HOME, ' ',
296 alt, ctrl, shift);
297 break;
298 case KeyEvent.VK_END:
299 keypress = new TKeypress(true, TKeypress.END, ' ',
300 alt, ctrl, shift);
301 break;
302 case KeyEvent.VK_PAGE_UP:
303 keypress = new TKeypress(true, TKeypress.PGUP, ' ',
304 alt, ctrl, shift);
305 break;
306 case KeyEvent.VK_PAGE_DOWN:
307 keypress = new TKeypress(true, TKeypress.PGDN, ' ',
308 alt, ctrl, shift);
309 break;
310 case KeyEvent.VK_INSERT:
311 keypress = new TKeypress(true, TKeypress.INS, ' ',
312 alt, ctrl, shift);
313 break;
314 case KeyEvent.VK_DELETE:
315 keypress = new TKeypress(true, TKeypress.F1, ' ',
316 alt, ctrl, shift);
317 break;
318 case KeyEvent.VK_RIGHT:
319 keypress = new TKeypress(true, TKeypress.RIGHT, ' ',
320 alt, ctrl, shift);
321 break;
322 case KeyEvent.VK_LEFT:
323 keypress = new TKeypress(true, TKeypress.LEFT, ' ',
324 alt, ctrl, shift);
325 break;
326 case KeyEvent.VK_UP:
327 keypress = new TKeypress(true, TKeypress.UP, ' ',
328 alt, ctrl, shift);
329 break;
330 case KeyEvent.VK_DOWN:
331 keypress = new TKeypress(true, TKeypress.DOWN, ' ',
332 alt, ctrl, shift);
333 break;
334 case KeyEvent.VK_TAB:
335 // Special case: distinguish TAB vs BTAB
336 if (shift) {
337 keypress = kbShiftTab;
338 } else {
339 keypress = kbTab;
340 }
341 break;
342 case KeyEvent.VK_ENTER:
343 keypress = new TKeypress(true, TKeypress.ENTER, ' ',
344 alt, ctrl, shift);
345 break;
346 case KeyEvent.VK_ESCAPE:
347 keypress = new TKeypress(true, TKeypress.ESC, ' ',
348 alt, ctrl, shift);
349 break;
350 case KeyEvent.VK_BACK_SPACE:
351 // Special case: return it as kbBackspace (Ctrl-H)
352 keypress = new TKeypress(false, 0, 'H', false, true, false);
353 break;
354 default:
355 // Unsupported, ignore
356 return;
357 }
358 }
359
360 if (keypress == null) {
361 switch (ch) {
362 case 0x08:
363 keypress = kbBackspace;
364 break;
365 case 0x0A:
366 keypress = kbEnter;
367 break;
368 case 0x0D:
369 keypress = kbEnter;
370 break;
371 default:
372 if (!alt && ctrl && !shift) {
373 ch = key.getKeyText(key.getKeyCode()).charAt(0);
374 }
375 // Not a special key, put it together
376 keypress = new TKeypress(false, 0, ch, alt, ctrl, shift);
377 }
378 }
379
380 // Save it and we are done.
381 synchronized (eventQueue) {
382 eventQueue.add(new TKeypressEvent(keypress));
383 }
384 }
1ac2ccb1 385}