37 KeyboardMapper.KeyProcessingListener, KeyboardView.OnKeyboardActionListener
39 private static final String TAG =
"FreeRDP.SessionInputManager";
41 private static final int SCROLLING_TIMEOUT = 50;
42 private static final int SCROLLING_DISTANCE = 20;
43 private static final int MAX_DISCARDED_MOVE_EVENTS = 3;
44 private static final int SEND_MOVE_EVENT_TIMEOUT = 150;
46 private static final int MSG_SEND_MOVE_EVENT = 1;
47 private static final int MSG_SCROLLING_REQUESTED = 2;
49 private final Context context;
50 private final KeyboardMapper keyboardMapper;
54 private final KeyboardView keyboardView;
55 private final KeyboardView modifiersKeyboardView;
56 private final PinchZoomListener pinchZoomListener =
new PinchZoomListener();
58 private Keyboard modifiersKeyboard;
59 private Keyboard specialkeysKeyboard;
60 private Keyboard numpadKeyboard;
61 private Keyboard cursorKeyboard;
63 private int safeInsetLeft = 0;
64 private int safeInsetTop = 0;
66 public void setSafeInsets(
int left,
int top)
73 private long instance = 0;
74 private Bitmap bitmap;
75 private int screenWidth;
76 private int screenHeight;
77 private int discardedMoveEvents = 0;
80 private boolean sysKeyboardVisible =
false;
81 private boolean extKeyboardVisible =
false;
83 private final Handler handler;
87 KeyboardView modifiersKeyboardView)
89 this.context = context;
90 this.scrollView = scrollView;
91 this.sessionView = sessionView;
92 this.touchPointerView = touchPointerView;
93 this.keyboardView = keyboardView;
94 this.modifiersKeyboardView = modifiersKeyboardView;
95 this.handler =
new InputHandler();
97 this.keyboardMapper =
new KeyboardMapper();
98 this.keyboardMapper.init(context);
101 keyboardView.setKeyboard(specialkeysKeyboard);
102 modifiersKeyboardView.setKeyboard(modifiersKeyboard);
104 keyboardView.setOnKeyboardActionListener(
this);
105 modifiersKeyboardView.setOnKeyboardActionListener(
this);
108 private void loadKeyboards()
110 Context app = context.getApplicationContext();
111 modifiersKeyboard =
new Keyboard(app, R.xml.modifiers_keyboard);
112 specialkeysKeyboard =
new Keyboard(app, R.xml.specialkeys_keyboard);
113 numpadKeyboard =
new Keyboard(app, R.xml.numpad_keyboard);
114 cursorKeyboard =
new Keyboard(app, R.xml.cursor_keyboard);
118 public void attachSession(
long instance, Bitmap surface)
120 this.instance = instance;
121 this.bitmap = surface;
122 keyboardMapper.reset(
this);
126 public void setBitmap(Bitmap bitmap)
128 this.bitmap = bitmap;
132 public ScaleGestureDetector.OnScaleGestureListener getPinchZoomListener()
134 return pinchZoomListener;
138 public void setScreenSize(
int width,
int height)
140 this.screenWidth = width;
141 this.screenHeight = height;
146 public void reloadKeyboards()
149 keyboardView.setKeyboard(specialkeysKeyboard);
150 modifiersKeyboardView.setKeyboard(modifiersKeyboard);
154 public void toggleSystemKeyboard()
156 showKeyboard(!sysKeyboardVisible,
false);
160 public void toggleExtendedKeyboard()
162 showKeyboard(
false, !extKeyboardVisible);
166 public void hideKeyboards()
168 showKeyboard(
false,
false);
172 public boolean isAnyKeyboardVisible()
174 return sysKeyboardVisible || extKeyboardVisible;
178 private void showKeyboard(
boolean showSystemKeyboard,
boolean showExtendedKeyboard)
180 if (showSystemKeyboard)
183 keyboardView.setVisibility(View.GONE);
185 setSoftInputState(
true);
188 modifiersKeyboardView.setVisibility(View.VISIBLE);
190 else if (showExtendedKeyboard)
193 setSoftInputState(
false);
196 keyboardView.setKeyboard(specialkeysKeyboard);
197 keyboardView.setVisibility(View.VISIBLE);
198 modifiersKeyboardView.setVisibility(View.VISIBLE);
203 setSoftInputState(
false);
204 keyboardView.setVisibility(View.GONE);
205 modifiersKeyboardView.setVisibility(View.GONE);
208 keyboardMapper.clearlAllModifiers();
211 sysKeyboardVisible = showSystemKeyboard;
212 extKeyboardVisible = showExtendedKeyboard;
215 private void setSoftInputState(
boolean state)
217 InputMethodManager mgr =
218 (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
222 sessionView.requestFocus();
223 mgr.showSoftInput(sessionView, InputMethodManager.SHOW_IMPLICIT);
227 mgr.hideSoftInputFromWindow(sessionView.getWindowToken(), 0);
232 public void cancelPendingEvents()
234 handler.removeMessages(MSG_SEND_MOVE_EVENT);
238 public boolean onGenericMotionEvent(MotionEvent e)
242 if (e.getAction() != MotionEvent.ACTION_SCROLL)
245 final float vScroll = e.getAxisValue(MotionEvent.AXIS_VSCROLL);
247 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context,
false));
248 else if (vScroll > 0)
249 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context,
true));
254 public boolean onAndroidKeyEvent(KeyEvent event)
258 return keyboardMapper.processAndroidKeyEvent(event);
263 public boolean onAndroidKeyLongPress(
int keyCode)
267 if (keyCode == KeyEvent.KEYCODE_BACK)
269 LibFreeRDP.disconnect(instance);
276 public boolean handleBackAsAltF4()
282 keyboardMapper.sendAltF4();
287 public void toggleTouchPointer()
289 if (touchPointerView.getVisibility() == View.VISIBLE)
291 touchPointerView.setVisibility(View.INVISIBLE);
292 sessionView.setTouchPointerPadding(0, 0);
296 touchPointerView.setVisibility(View.VISIBLE);
297 sessionView.setTouchPointerPadding(touchPointerView.getPointerWidth(),
298 touchPointerView.getPointerHeight());
305 private void sendDelayedMoveEvent(
int x,
int y)
307 if (handler.hasMessages(MSG_SEND_MOVE_EVENT))
309 handler.removeMessages(MSG_SEND_MOVE_EVENT);
310 discardedMoveEvents++;
313 discardedMoveEvents = 0;
315 if (discardedMoveEvents > MAX_DISCARDED_MOVE_EVENTS)
316 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getMoveEvent());
318 handler.sendMessageDelayed(Message.obtain(
null, MSG_SEND_MOVE_EVENT, x, y),
319 SEND_MOVE_EVENT_TIMEOUT);
322 private void cancelDelayedMoveEvent()
324 handler.removeMessages(MSG_SEND_MOVE_EVENT);
327 private Point mapScreenCoordToSessionCoord(
int x,
int y)
330 scrollView.getWidth() - scrollView.getPaddingLeft() - scrollView.getPaddingRight();
332 scrollView.getHeight() - scrollView.getPaddingTop() - scrollView.getPaddingBottom();
333 int contentW = sessionView.getWidth() - sessionView.getTouchPointerPaddingWidth();
334 int contentH = sessionView.getHeight() - sessionView.getTouchPointerPaddingHeight();
335 int centerOffsetX = Math.max(0, (usableW - contentW) / 2);
336 int centerOffsetY = Math.max(0, (usableH - contentH) / 2);
337 int mappedX = (int)((
float)(x - safeInsetLeft - centerOffsetX + scrollView.getScrollX()) /
338 sessionView.getZoom());
339 int mappedY = (int)((
float)(y - safeInsetTop - centerOffsetY + scrollView.getScrollY()) /
340 sessionView.getZoom());
347 if (mappedX > bitmap.getWidth())
348 mappedX = bitmap.getWidth();
349 if (mappedY > bitmap.getHeight())
350 mappedY = bitmap.getHeight();
352 return new Point(mappedX, mappedY);
355 private void updateModifierKeyStates()
357 List<Keyboard.Key> keys = modifiersKeyboard.getKeys();
358 for (Keyboard.Key curKey : keys)
362 switch (keyboardMapper.getModifierState(curKey.codes[0]))
364 case KeyboardMapper.KEYSTATE_ON:
366 curKey.pressed =
false;
369 case KeyboardMapper.KEYSTATE_OFF:
371 curKey.pressed =
false;
374 case KeyboardMapper.KEYSTATE_LOCKED:
376 curKey.pressed =
true;
381 modifiersKeyboardView.invalidateAllKeys();
387 @Override
public void onSessionViewBeginTouch()
392 @Override
public void onSessionViewEndTouch()
397 @Override
public void onSessionViewLeftTouch(
int x,
int y,
boolean down)
402 cancelDelayedMoveEvent();
403 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getLeftButtonEvent(context, down));
406 @Override
public void onSessionViewMiddleTouch(
int x,
int y,
boolean down)
410 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getMiddleButtonEvent(down));
413 @Override
public void onSessionViewRightTouch(
int x,
int y,
boolean down)
417 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getRightButtonEvent(context, down));
420 @Override
public void onSessionViewMove(
int x,
int y)
424 sendDelayedMoveEvent(x, y);
427 @Override
public void onSessionViewMouseMove(
int x,
int y)
431 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getMoveEvent());
434 @Override
public void onSessionViewScroll(
boolean down)
438 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context, down));
441 @Override
public void onSessionViewHScroll(
boolean right)
445 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getHScrollEvent(context, right));
451 @Override
public void onTouchPointerClose()
453 touchPointerView.setVisibility(View.INVISIBLE);
454 sessionView.setTouchPointerPadding(0, 0);
457 @Override
public void onTouchPointerLeftClick(
int x,
int y,
boolean down)
461 Point p = mapScreenCoordToSessionCoord(x, y);
462 LibFreeRDP.sendCursorEvent(instance, p.x, p.y, Mouse.getLeftButtonEvent(context, down));
465 @Override
public void onTouchPointerRightClick(
int x,
int y,
boolean down)
469 Point p = mapScreenCoordToSessionCoord(x, y);
470 LibFreeRDP.sendCursorEvent(instance, p.x, p.y, Mouse.getRightButtonEvent(context, down));
473 @Override
public void onTouchPointerMove(
int x,
int y)
477 Point p = mapScreenCoordToSessionCoord(x, y);
478 LibFreeRDP.sendCursorEvent(instance, p.x, p.y, Mouse.getMoveEvent());
481 !handler.hasMessages(MSG_SCROLLING_REQUESTED))
483 Log.v(TAG,
"Starting auto-scroll");
484 handler.sendEmptyMessageDelayed(MSG_SCROLLING_REQUESTED, SCROLLING_TIMEOUT);
488 @Override
public void onTouchPointerScroll(
boolean down)
492 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context, down));
495 @Override
public void onTouchPointerToggleKeyboard()
497 toggleSystemKeyboard();
500 @Override
public void onTouchPointerToggleExtKeyboard()
502 toggleExtendedKeyboard();
505 @Override
public void onTouchPointerResetScrollZoom()
507 sessionView.setZoom(1.0f);
514 @Override
public void processVirtualKey(
int virtualKeyCode,
boolean down)
518 LibFreeRDP.sendKeyEvent(instance, virtualKeyCode, down);
521 @Override
public void processUnicodeKey(
int unicodeKey)
525 if (LibFreeRDP.isUnicodeInputSupported(instance))
527 LibFreeRDP.sendUnicodeKeyEvent(instance, unicodeKey,
true);
528 LibFreeRDP.sendUnicodeKeyEvent(instance, unicodeKey,
false);
531 keyboardMapper.processUnicodeFallback(unicodeKey);
534 @Override
public void switchKeyboard(
int keyboardType)
536 switch (keyboardType)
538 case KeyboardMapper.KEYBOARD_TYPE_FUNCTIONKEYS:
539 keyboardView.setKeyboard(specialkeysKeyboard);
542 case KeyboardMapper.KEYBOARD_TYPE_NUMPAD:
543 keyboardView.setKeyboard(numpadKeyboard);
546 case KeyboardMapper.KEYBOARD_TYPE_CURSOR:
547 keyboardView.setKeyboard(cursorKeyboard);
555 @Override
public void modifiersChanged()
557 updateModifierKeyStates();
563 @Override
public void onKey(
int primaryCode,
int[] keyCodes)
565 keyboardMapper.processCustomKeyEvent(primaryCode);
568 @Override
public void onText(CharSequence text)
572 @Override
public void swipeRight()
576 @Override
public void swipeLeft()
580 @Override
public void swipeDown()
584 @Override
public void swipeUp()
588 @Override
public void onPress(
int primaryCode)
592 @Override
public void onRelease(
int primaryCode)
599 private class InputHandler
extends Handler
603 super(Looper.getMainLooper());
606 @Override
public void handleMessage(Message msg)
610 case MSG_SEND_MOVE_EVENT:
613 LibFreeRDP.sendCursorEvent(instance, msg.arg1, msg.arg2, Mouse.getMoveEvent());
616 case MSG_SCROLLING_REQUESTED:
620 float[] pointerPos = touchPointerView.getPointerPosition();
622 if (pointerPos[0] > (screenWidth - touchPointerView.getPointerWidth()))
623 scrollX = SCROLLING_DISTANCE;
624 else if (pointerPos[0] < 0)
625 scrollX = -SCROLLING_DISTANCE;
627 if (pointerPos[1] > (screenHeight - touchPointerView.getPointerHeight()))
628 scrollY = SCROLLING_DISTANCE;
629 else if (pointerPos[1] < 0)
630 scrollY = -SCROLLING_DISTANCE;
632 scrollView.scrollBy(scrollX, scrollY);
634 if (scrollView.getScrollX() == 0 ||
635 scrollView.getScrollX() == (sessionView.getWidth() - scrollView.getWidth()))
637 if (scrollView.getScrollY() == 0 ||
638 scrollView.getScrollY() ==
639 (sessionView.getHeight() - scrollView.getHeight()))
642 if (scrollX != 0 || scrollY != 0)
643 handler.sendEmptyMessageDelayed(MSG_SCROLLING_REQUESTED, SCROLLING_TIMEOUT);
645 Log.v(TAG,
"Stopping auto-scroll");
655 private class PinchZoomListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener
657 private float scaleFactor = 1.0f;
659 @Override
public boolean onScaleBegin(ScaleGestureDetector detector)
665 @Override
public boolean onScale(ScaleGestureDetector detector)
668 scaleFactor *= detector.getScaleFactor();
669 scaleFactor = Math.max(
SessionView.MIN_SCALE_FACTOR,
670 Math.min(scaleFactor,
SessionView.MAX_SCALE_FACTOR));
671 sessionView.setZoom(scaleFactor);
673 if (!sessionView.isAtMinZoom() && !sessionView.isAtMaxZoom())
676 float transOriginX = scrollView.getScrollX() * detector.getScaleFactor();
677 float transOriginY = scrollView.getScrollY() * detector.getScaleFactor();
681 (scrollView.getScrollX() + detector.getFocusX()) * detector.getScaleFactor();
683 (scrollView.getScrollY() + detector.getFocusY()) * detector.getScaleFactor();
688 scrollView.scrollBy((
int)((transCenterX - transOriginX) - detector.getFocusX()),
689 (
int)((transCenterY - transOriginY) - detector.getFocusY()));
695 @Override
public void onScaleEnd(ScaleGestureDetector de)