001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: ///////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp;
022:
023: import java.awt.event.*;
024: import java.util.Vector;
025: import org.rdesktop.server.rdp.keymapping.*;
026:
027: public abstract class RdpAbstractInput {
028: protected static final int KBD_FLAG_RIGHT = 0x0001;
029: protected static final int KBD_FLAG_EXT = 0x0100;
030:
031: protected static final int KBD_FLAG_QUIET = 0x200;
032: protected static final int KBD_FLAG_DOWN = 0x4000;
033: protected static final int KBD_FLAG_UP = 0x8000;
034:
035: protected static final int RDP_KEYPRESS = 0;
036: protected static final int RDP_KEYRELEASE = KBD_FLAG_DOWN
037: | KBD_FLAG_UP;
038: protected static final int MOUSE_FLAG_MOVE = 0x0800;
039:
040: protected static final int MOUSE_FLAG_BUTTON1 = 0x1000;
041: protected static final int MOUSE_FLAG_BUTTON2 = 0x2000;
042: protected static final int MOUSE_FLAG_BUTTON3 = 0x4000;
043: protected static final int MOUSE_FLAG_BUTTON4 = 0x0280; // wheel up -
044: protected static final int MOUSE_FLAG_BUTTON5 = 0x0380; // wheel down -
045: protected static final int MOUSE_FLAG_DOWN = 0x8000;
046:
047: protected static final int RDP_INPUT_SYNCHRONIZE = 0;
048: protected static final int RDP_INPUT_CODEPOINT = 1;
049: protected static final int RDP_INPUT_VIRTKEY = 2;
050: protected static final int RDP_INPUT_SCANCODE = 4;
051: protected static final int RDP_INPUT_MOUSE = 0x8001;
052:
053: private static int m_time = 0;
054:
055: private KeyCode m_keys = null;
056: private KeyCode_FileBased m_newKeyMapper = null;
057:
058: protected boolean m_capsLockOn = false;
059: protected boolean m_numLockOn = false;
060: protected boolean m_scrollLockOn = false;
061: protected boolean m_serverAltDown = false;
062: protected boolean m_altDown = false;
063: protected boolean m_ctrlDown = false;
064:
065: protected Vector m_pressedKeys;
066: protected KeyEvent m_lastKeyEvent = null;
067: protected boolean m_modifiersValid = false;
068: protected boolean m_keyDownWindows = false;
069:
070: protected RdpProto m_rdp = null;
071: protected RdpAbstractDesktopCanvas m_canvas = null;
072:
073: public RdpAbstractInput(RdpProto rdp,
074: RdpAbstractDesktopCanvas canvas, KeyCode_FileBased keyMapper) {
075: m_rdp = rdp;
076: m_canvas = canvas;
077: m_newKeyMapper = keyMapper;
078:
079: m_pressedKeys = new Vector();
080:
081: addInputListeners();
082: }
083:
084: public RdpAbstractInput(RdpProto rdp,
085: RdpAbstractDesktopCanvas canvas, String keymapFile) {
086: try {
087: m_newKeyMapper = new RdpKeyCodeFileBased(keymapFile);
088: } catch (KeyMapException e) {
089: System.err.println(e.getMessage());
090: }
091:
092: m_rdp = rdp;
093: m_canvas = canvas;
094:
095: m_pressedKeys = new Vector();
096:
097: addInputListeners();
098: }
099:
100: protected void doLockKeys() {
101: }
102:
103: protected void middleButtonPressed(MouseEvent e) {
104: m_rdp.sendInput(m_time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3
105: | MOUSE_FLAG_DOWN, e.getX(), e.getY());
106: }
107:
108: protected void middleButtonReleased(MouseEvent e) {
109: m_rdp.sendInput(m_time, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e
110: .getX(), e.getY());
111: }
112:
113: public void addInputListeners() {
114: m_canvas.addMouseListener(new RdpDesktopMouseAdapter());
115: m_canvas
116: .addMouseMotionListener(new RdpDesktopMouseMotionAdapter());
117: m_canvas.addKeyListener(new RdpDesktopKeyAdapter());
118: }
119:
120: public void sendKeyPresses(String pressSequence) {
121: try {
122: for (int i = 0; i < pressSequence.length(); i += 2) {
123: int scancode = (int) pressSequence.charAt(i);
124: int action = (int) pressSequence.charAt(i + 1);
125: int flags = 0;
126:
127: if (action == KeyCode_FileBased.UP) {
128: flags = RDP_KEYRELEASE;
129: } else if (action == KeyCode_FileBased.DOWN) {
130: flags = RDP_KEYPRESS;
131: } else if (action == KeyCode_FileBased.QUIETUP) {
132: flags = RDP_KEYRELEASE | KBD_FLAG_QUIET;
133: } else if (action == KeyCode_FileBased.QUIETDOWN) {
134: flags = RDP_KEYPRESS | KBD_FLAG_QUIET;
135: }
136:
137: long t = getTime();
138: sendScancode(t, flags, scancode);
139: }
140: } catch (Exception ex) {
141: }
142: }
143:
144: public static int getTime() {
145: m_time++;
146:
147: if (m_time == Integer.MAX_VALUE) {
148: m_time = 1;
149: }
150:
151: return m_time;
152: }
153:
154: public void lostFocus() {
155: clearKeys();
156: m_modifiersValid = false;
157: }
158:
159: public void gainedFocus() {
160: doLockKeys();
161: }
162:
163: public void sendScancode(long time, int flags, int scancode) {
164: if (scancode == 0x38) // be careful with alt
165: {
166: if ((flags & RDP_KEYRELEASE) != 0) {
167: m_serverAltDown = false;
168: }
169:
170: if ((flags == RDP_KEYPRESS)) {
171: m_serverAltDown = true;
172: }
173: }
174:
175: if ((scancode & KeyCode.SCANCODE_EXTENDED) != 0) {
176: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE, flags
177: | KBD_FLAG_EXT, scancode
178: & ~KeyCode.SCANCODE_EXTENDED, 0);
179: } else {
180: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE, flags,
181: scancode, 0);
182: }
183: }
184:
185: public void clearKeys() {
186: if (m_modifiersValid == false) {
187: return;
188: }
189:
190: m_altDown = false;
191: m_ctrlDown = false;
192:
193: if (m_lastKeyEvent == null) {
194: return;
195: }
196:
197: if (m_lastKeyEvent.isShiftDown() == true) {
198: sendScancode(getTime(), RDP_KEYRELEASE, 0x2a); // shift
199: }
200:
201: if ((m_lastKeyEvent.isAltDown() == true)
202: || (m_serverAltDown == true)) {
203: sendScancode(getTime(), RDP_KEYRELEASE, 0x38); // ALT
204: sendScancode(getTime(), RDP_KEYPRESS | KBD_FLAG_QUIET, 0x38); // ALT
205: sendScancode(getTime(), RDP_KEYRELEASE | KBD_FLAG_QUIET,
206: 0x38); // l.alt
207: }
208:
209: if (m_lastKeyEvent.isControlDown()) {
210: sendScancode(getTime(), RDP_KEYRELEASE, 0x1d); // l.ctrl
211: //sendScancode(getTime(), RDP_KEYPRESS | KBD_FLAG_QUIET, 0x1d); // Ctrl
212: //sendScancode(getTime(), RDP_KEYRELEASE | KBD_FLAG_QUIET, 0x1d); // ctrl
213: }
214: }
215:
216: public void setKeys() {
217: if (m_modifiersValid == false) {
218: return;
219: }
220:
221: if (m_lastKeyEvent == null) {
222: return;
223: }
224:
225: if (m_lastKeyEvent.isShiftDown()) {
226: sendScancode(getTime(), RDP_KEYPRESS, 0x2a); // shift
227: }
228:
229: if (m_lastKeyEvent.isAltDown()) {
230: sendScancode(getTime(), RDP_KEYPRESS, 0x38); // l.alt
231: }
232:
233: if (m_lastKeyEvent.isControlDown()) {
234: sendScancode(getTime(), RDP_KEYPRESS, 0x1d); // l.ctrl
235: }
236: }
237:
238: public boolean handleShortcutKeys(long time, KeyEvent e,
239: boolean pressed) {
240: if (e.isAltDown() == false) {
241: return false;
242: }
243:
244: if (m_altDown == false) {
245: return false; // all of the below have ALT on
246: }
247:
248: switch (e.getKeyCode()) {
249: case KeyEvent.VK_ENTER: {
250: sendScancode(time, RDP_KEYRELEASE, 0x38);
251: m_altDown = false;
252: break;
253: }
254: case KeyEvent.VK_TAB: // Alt+Tab received, quiet combination
255: {
256: sendScancode(time,
257: (pressed ? RDP_KEYPRESS : RDP_KEYRELEASE)
258: | KBD_FLAG_QUIET, 0x0f);
259: if (pressed == false) {
260: sendScancode(time, RDP_KEYRELEASE | KBD_FLAG_QUIET,
261: 0x38); // Release Alt
262: }
263:
264: break;
265: }
266: case KeyEvent.VK_PAGE_UP: // Alt + PgUp = Alt-Tab
267: {
268: sendScancode(time, pressed ? RDP_KEYPRESS : RDP_KEYRELEASE,
269: 0x0f); // TAB
270: break;
271: }
272: case KeyEvent.VK_PAGE_DOWN: // Alt + PgDown = Alt-Shift-Tab
273: {
274: if (pressed == false) {
275: sendScancode(time, RDP_KEYPRESS, 0x2a); // Shift
276: sendScancode(time, RDP_KEYPRESS, 0x0f); // TAB
277: } else {
278: sendScancode(time, RDP_KEYRELEASE, 0x0f); // TAB
279: sendScancode(time, RDP_KEYRELEASE, 0x2a); // Shift
280: }
281:
282: break;
283: }
284: case KeyEvent.VK_INSERT: // Alt + Insert = Alt + Esc
285: {
286: sendScancode(time, pressed ? RDP_KEYPRESS : RDP_KEYRELEASE,
287: 0x01); // ESC
288: break;
289: }
290: case KeyEvent.VK_HOME: // Alt + Home = Ctrl + Esc (Start)
291: {
292: if (pressed == true) {
293: sendScancode(time, RDP_KEYRELEASE, 0x38); // ALT
294: sendScancode(time, RDP_KEYPRESS, 0x1d); // left Ctrl
295: sendScancode(time, RDP_KEYPRESS, 0x01); // Esc
296: } else {
297: sendScancode(time, RDP_KEYRELEASE, 0x01); // escape
298: sendScancode(time, RDP_KEYRELEASE, 0x1d); // left ctrl
299: // sendScancode(time,RDP_KEYPRESS,0x38); // ALT
300: }
301:
302: break;
303: }
304: case KeyEvent.VK_END: // Ctrl+Alt+End = Ctrl+Alt+Del
305: {
306: if (m_ctrlDown == true) {
307: sendScancode(time, pressed ? RDP_KEYPRESS
308: : RDP_KEYRELEASE,
309: 0x53 | KeyCode.SCANCODE_EXTENDED); // DEL
310: }
311:
312: break;
313: }
314: case KeyEvent.VK_DELETE: // Alt + Delete = Menu
315: {
316: if (pressed == true) {
317: sendScancode(time, RDP_KEYRELEASE, 0x38); // ALT
318: sendScancode(time, RDP_KEYPRESS, 0x38); // ALT
319: sendScancode(time, RDP_KEYRELEASE, 0x38); // ALT
320: sendScancode(time, RDP_KEYPRESS,
321: 0x5d | KeyCode.SCANCODE_EXTENDED); // Menu
322: } else {
323: sendScancode(time, RDP_KEYRELEASE,
324: 0x5d | KeyCode.SCANCODE_EXTENDED); // Menu
325: // sendScancode(time,RDP_KEYPRESS,0x38); // ALT
326: }
327:
328: break;
329: }
330: case KeyEvent.VK_SUBTRACT: // Ctrl + Alt + Minus (on NUM KEYPAD) = Alt+PrtSc
331: {
332: if (m_ctrlDown == true) {
333: if (pressed == true) {
334: sendScancode(time, RDP_KEYRELEASE, 0x1d); // Ctrl
335: sendScancode(time, RDP_KEYPRESS,
336: 0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
337: } else {
338: sendScancode(time, RDP_KEYRELEASE,
339: 0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
340: sendScancode(time, RDP_KEYPRESS, 0x1d); // Ctrl
341: }
342: }
343:
344: break;
345: }
346: case KeyEvent.VK_ADD: // Ctrl + ALt + Plus (on NUM KEYPAD) = PrtSc
347: case KeyEvent.VK_EQUALS: // for laptops that can't do Ctrl-Alt+Plus
348: {
349: if (m_ctrlDown == true) {
350: if (pressed == true) {
351: sendScancode(time, RDP_KEYRELEASE, 0x38); // Alt
352: sendScancode(time, RDP_KEYRELEASE, 0x1d); // Ctrl
353: sendScancode(time, RDP_KEYPRESS,
354: 0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
355: } else {
356: sendScancode(time, RDP_KEYRELEASE,
357: 0x37 | KeyCode.SCANCODE_EXTENDED); // PrtSc
358: sendScancode(time, RDP_KEYPRESS, 0x1d); // Ctrl
359: sendScancode(time, RDP_KEYPRESS, 0x38); // Alt
360: }
361: }
362:
363: break;
364: }
365: default: {
366: return false;
367: }
368: }
369:
370: return true;
371: }
372:
373: public boolean handleSpecialKeys(long time, KeyEvent e,
374: boolean pressed) {
375: if (handleShortcutKeys(time, e, pressed) == true) {
376: return true;
377: }
378:
379: switch (e.getKeyCode()) {
380: case KeyEvent.VK_CONTROL: {
381: m_ctrlDown = pressed;
382: return false;
383: }
384: case KeyEvent.VK_ALT: {
385: m_altDown = pressed;
386: return false;
387: }
388: case KeyEvent.VK_CAPS_LOCK: {
389: if ((pressed == true)
390: && (RdpOptions.caps_sends_up_and_down == true)) {
391: m_capsLockOn = !m_capsLockOn;
392: }
393:
394: if (RdpOptions.caps_sends_up_and_down == false) {
395: if (pressed == true) {
396: m_capsLockOn = true;
397: } else {
398: m_capsLockOn = false;
399: }
400: }
401:
402: return false;
403: }
404: case KeyEvent.VK_NUM_LOCK: {
405: if (pressed == true) {
406: m_numLockOn = !m_numLockOn;
407: }
408:
409: return false;
410: }
411: case KeyEvent.VK_SCROLL_LOCK: {
412: if (pressed == true) {
413: m_scrollLockOn = !m_scrollLockOn;
414: }
415:
416: return false;
417: }
418: case KeyEvent.VK_PAUSE: // untested
419: {
420: if (pressed == true) // E1 1D 45 E1 9D C5
421: {
422: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
423: RDP_KEYPRESS, 0xe1, 0);
424: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
425: RDP_KEYPRESS, 0x1d, 0);
426: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
427: RDP_KEYPRESS, 0x45, 0);
428: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
429: RDP_KEYPRESS, 0xe1, 0);
430: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
431: RDP_KEYPRESS, 0x9d, 0);
432: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
433: RDP_KEYPRESS, 0xc5, 0);
434: } else // release left ctrl
435: {
436: m_rdp.sendInput((int) time, RDP_INPUT_SCANCODE,
437: RDP_KEYRELEASE, 0x1d, 0);
438: }
439:
440: break;
441: }
442: default: {
443: return false; // not handled - use sendScancode instead
444: }
445: }
446:
447: return true; // handled - no need to use sendScancode
448: }
449:
450: public void triggerReadyToSend() {
451: m_capsLockOn = false;
452: m_numLockOn = false;
453: m_scrollLockOn = false;
454: doLockKeys();
455: }
456:
457: class RdpDesktopKeyAdapter extends KeyAdapter {
458: public RdpDesktopKeyAdapter() {
459: super ();
460: }
461:
462: public void keyPressed(KeyEvent e) {
463: m_lastKeyEvent = e;
464: m_modifiersValid = true;
465: long time = getTime();
466:
467: m_pressedKeys.addElement(new Integer(e.getKeyCode()));
468:
469: if (m_rdp != null) {
470: if (handleSpecialKeys(time, e, true) == false) {
471: sendKeyPresses(m_newKeyMapper.getKeyStrokes(e));
472: }
473: // sendScancode(time, RDP_KEYPRESS, m_keys.getScancode(e));
474: }
475: }
476:
477: public void keyTyped(KeyEvent e) {
478: m_lastKeyEvent = e;
479: m_modifiersValid = true;
480: long time = getTime();
481:
482: m_pressedKeys.addElement(new Integer(e.getKeyCode()));
483:
484: if (m_rdp != null) {
485: if (handleSpecialKeys(time, e, true) == false) {
486: sendKeyPresses(m_newKeyMapper.getKeyStrokes(e));
487: }
488: // sendScancode(time, RDP_KEYPRESS, m_keys.getScancode(e));
489: }
490: }
491:
492: public void keyReleased(KeyEvent e) {
493: Integer keycode = new Integer(e.getKeyCode());
494: if (m_pressedKeys.contains(keycode) == false) {
495: this .keyPressed(e);
496: }
497:
498: m_pressedKeys.removeElement(keycode);
499:
500: m_lastKeyEvent = e;
501: m_modifiersValid = true;
502: long time = getTime();
503:
504: if (m_rdp != null) {
505: if (handleSpecialKeys(time, e, false) == false) {
506: sendKeyPresses(m_newKeyMapper.getKeyStrokes(e));
507: }
508: // sendScancode(time, RDP_KEYRELEASE, m_keys.getScancode(e));
509: }
510: }
511: }
512:
513: class RdpDesktopMouseAdapter extends MouseAdapter {
514: public RdpDesktopMouseAdapter() {
515: super ();
516: }
517:
518: public void mousePressed(MouseEvent e) {
519: int time = getTime();
520: if (m_rdp != null) {
521: if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
522: m_rdp.sendInput(time, RDP_INPUT_MOUSE,
523: MOUSE_FLAG_BUTTON1 | MOUSE_FLAG_DOWN, e
524: .getX(), e.getY());
525: } else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
526: m_rdp.sendInput(time, RDP_INPUT_MOUSE,
527: MOUSE_FLAG_BUTTON2 | MOUSE_FLAG_DOWN, e
528: .getX(), e.getY());
529: } else if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
530: middleButtonPressed(e);
531: }
532: }
533: }
534:
535: public void mouseReleased(MouseEvent e) {
536: int time = getTime();
537: if (m_rdp != null) {
538: if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
539: m_rdp.sendInput(time, RDP_INPUT_MOUSE,
540: MOUSE_FLAG_BUTTON1, e.getX(), e.getY());
541: } else if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) {
542: m_rdp.sendInput(time, RDP_INPUT_MOUSE,
543: MOUSE_FLAG_BUTTON2, e.getX(), e.getY());
544: } else if ((e.getModifiers() & InputEvent.BUTTON2_MASK) == InputEvent.BUTTON2_MASK) {
545: middleButtonReleased(e);
546: }
547: }
548: }
549: }
550:
551: class RdpDesktopMouseMotionAdapter extends MouseMotionAdapter {
552: public RdpDesktopMouseMotionAdapter() {
553: super ();
554: }
555:
556: public void mouseMoved(MouseEvent e) {
557: int time = getTime();
558: if (m_rdp != null) {
559: m_rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
560: e.getX(), e.getY());
561: }
562: }
563:
564: public void mouseDragged(MouseEvent e) {
565: int time = getTime();
566: if (m_rdp != null) {
567: m_rdp.sendInput(time, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
568: e.getX(), e.getY());
569: }
570: }
571: }
572: }
|