37 KeyboardMapper.KeyProcessingListener, KeyboardView.OnKeyboardActionListener
39 private static final String TAG =
"FreeRDP.SessionInputManager";
41 private static final int SCROLLING_TIMEOUT = 16;
42 private static final int SCROLLING_DISTANCE = 12;
43 private static final int SCROLLING_EDGE_MARGIN = 16;
44 private static final int MAX_DISCARDED_MOVE_EVENTS = 3;
45 private static final int SEND_MOVE_EVENT_TIMEOUT = 150;
47 private static final int MSG_SEND_MOVE_EVENT = 1;
48 private static final int MSG_SCROLLING_REQUESTED = 2;
50 private final Context context;
51 private final KeyboardMapper keyboardMapper;
55 private final KeyboardView keyboardView;
56 private final KeyboardView modifiersKeyboardView;
57 private final PinchZoomListener pinchZoomListener =
new PinchZoomListener();
59 private Keyboard modifiersKeyboard;
60 private Keyboard specialkeysKeyboard;
61 private Keyboard numpadKeyboard;
62 private Keyboard cursorKeyboard;
64 private int safeInsetLeft = 0;
65 private int safeInsetTop = 0;
67 public void setSafeInsets(
int left,
int top)
74 private long instance = 0;
75 private Bitmap bitmap;
76 private int screenWidth;
77 private int screenHeight;
78 private int discardedMoveEvents = 0;
81 private boolean sysKeyboardVisible =
false;
82 private boolean extKeyboardVisible =
false;
84 private final Handler handler;
88 KeyboardView modifiersKeyboardView)
90 this.context = context;
91 this.scrollView = scrollView;
92 this.sessionView = sessionView;
93 this.touchPointerView = touchPointerView;
94 this.keyboardView = keyboardView;
95 this.modifiersKeyboardView = modifiersKeyboardView;
96 this.handler =
new InputHandler();
98 this.keyboardMapper =
new KeyboardMapper();
99 this.keyboardMapper.init(context);
102 keyboardView.setKeyboard(specialkeysKeyboard);
103 modifiersKeyboardView.setKeyboard(modifiersKeyboard);
105 keyboardView.setOnKeyboardActionListener(
this);
106 modifiersKeyboardView.setOnKeyboardActionListener(
this);
109 private void loadKeyboards()
111 Context app = context.getApplicationContext();
112 modifiersKeyboard =
new Keyboard(app, R.xml.modifiers_keyboard);
113 specialkeysKeyboard =
new Keyboard(app, R.xml.specialkeys_keyboard);
114 numpadKeyboard =
new Keyboard(app, R.xml.numpad_keyboard);
115 cursorKeyboard =
new Keyboard(app, R.xml.cursor_keyboard);
119 public void attachSession(
long instance, Bitmap surface)
121 this.instance = instance;
122 this.bitmap = surface;
123 keyboardMapper.reset(
this);
127 public void setBitmap(Bitmap bitmap)
129 this.bitmap = bitmap;
133 public ScaleGestureDetector.OnScaleGestureListener getPinchZoomListener()
135 return pinchZoomListener;
139 public void setScreenSize(
int width,
int height)
141 this.screenWidth = width;
142 this.screenHeight = height;
147 public void reloadKeyboards()
150 keyboardView.setKeyboard(specialkeysKeyboard);
151 modifiersKeyboardView.setKeyboard(modifiersKeyboard);
155 public void toggleSystemKeyboard()
157 showKeyboard(!sysKeyboardVisible,
false);
161 public void toggleExtendedKeyboard()
163 showKeyboard(
false, !extKeyboardVisible);
167 public void hideKeyboards()
169 showKeyboard(
false,
false);
173 public boolean isAnyKeyboardVisible()
175 return sysKeyboardVisible || extKeyboardVisible;
179 private void showKeyboard(
boolean showSystemKeyboard,
boolean showExtendedKeyboard)
181 if (showSystemKeyboard)
184 keyboardView.setVisibility(View.GONE);
186 setSoftInputState(
true);
189 modifiersKeyboardView.setVisibility(View.VISIBLE);
191 else if (showExtendedKeyboard)
194 setSoftInputState(
false);
197 keyboardView.setKeyboard(specialkeysKeyboard);
198 keyboardView.setVisibility(View.VISIBLE);
199 modifiersKeyboardView.setVisibility(View.VISIBLE);
204 setSoftInputState(
false);
205 keyboardView.setVisibility(View.GONE);
206 modifiersKeyboardView.setVisibility(View.GONE);
209 keyboardMapper.clearlAllModifiers();
212 sysKeyboardVisible = showSystemKeyboard;
213 extKeyboardVisible = showExtendedKeyboard;
216 private void setSoftInputState(
boolean state)
218 InputMethodManager mgr =
219 (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
223 sessionView.requestFocus();
224 mgr.showSoftInput(sessionView, InputMethodManager.SHOW_IMPLICIT);
228 mgr.hideSoftInputFromWindow(sessionView.getWindowToken(), 0);
233 public void cancelPendingEvents()
235 handler.removeMessages(MSG_SEND_MOVE_EVENT);
239 public boolean onGenericMotionEvent(MotionEvent e)
243 if (e.getAction() != MotionEvent.ACTION_SCROLL)
246 final float vScroll = e.getAxisValue(MotionEvent.AXIS_VSCROLL);
248 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context,
false));
249 else if (vScroll > 0)
250 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context,
true));
255 public boolean onAndroidKeyEvent(KeyEvent event)
259 return keyboardMapper.processAndroidKeyEvent(event);
264 public boolean onAndroidKeyLongPress(
int keyCode)
268 if (keyCode == KeyEvent.KEYCODE_BACK)
270 LibFreeRDP.disconnect(instance);
277 public boolean handleBackAsAltF4()
283 keyboardMapper.sendAltF4();
288 public void toggleTouchPointer()
290 if (touchPointerView.getVisibility() == View.VISIBLE)
292 touchPointerView.setVisibility(View.INVISIBLE);
293 sessionView.setTouchPointerPadding(0, 0);
297 touchPointerView.setVisibility(View.VISIBLE);
298 sessionView.setTouchPointerPadding(touchPointerView.getPointerWidth(),
299 touchPointerView.getPointerHeight());
306 private void sendDelayedMoveEvent(
int x,
int y)
308 if (handler.hasMessages(MSG_SEND_MOVE_EVENT))
310 handler.removeMessages(MSG_SEND_MOVE_EVENT);
311 discardedMoveEvents++;
314 discardedMoveEvents = 0;
316 if (discardedMoveEvents > MAX_DISCARDED_MOVE_EVENTS)
317 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getMoveEvent());
319 handler.sendMessageDelayed(Message.obtain(
null, MSG_SEND_MOVE_EVENT, x, y),
320 SEND_MOVE_EVENT_TIMEOUT);
323 private void cancelDelayedMoveEvent()
325 handler.removeMessages(MSG_SEND_MOVE_EVENT);
328 private Point mapScreenCoordToSessionCoord(
int x,
int y)
331 scrollView.getWidth() - scrollView.getPaddingLeft() - scrollView.getPaddingRight();
333 scrollView.getHeight() - scrollView.getPaddingTop() - scrollView.getPaddingBottom();
334 int contentW = sessionView.getWidth() - sessionView.getTouchPointerPaddingWidth();
335 int contentH = sessionView.getHeight() - sessionView.getTouchPointerPaddingHeight();
336 int centerOffsetX = Math.max(0, (usableW - contentW) / 2);
337 int centerOffsetY = Math.max(0, (usableH - contentH) / 2);
338 int mappedX = (int)((
float)(x - safeInsetLeft - centerOffsetX + scrollView.getScrollX()) /
339 sessionView.getZoom());
340 int mappedY = (int)((
float)(y - safeInsetTop - centerOffsetY + scrollView.getScrollY()) /
341 sessionView.getZoom());
348 if (mappedX > bitmap.getWidth())
349 mappedX = bitmap.getWidth();
350 if (mappedY > bitmap.getHeight())
351 mappedY = bitmap.getHeight();
353 return new Point(mappedX, mappedY);
356 private void updateModifierKeyStates()
358 List<Keyboard.Key> keys = modifiersKeyboard.getKeys();
359 for (Keyboard.Key curKey : keys)
363 switch (keyboardMapper.getModifierState(curKey.codes[0]))
365 case KeyboardMapper.KEYSTATE_ON:
367 curKey.pressed =
false;
370 case KeyboardMapper.KEYSTATE_OFF:
372 curKey.pressed =
false;
375 case KeyboardMapper.KEYSTATE_LOCKED:
377 curKey.pressed =
true;
382 modifiersKeyboardView.invalidateAllKeys();
388 @Override
public void onSessionViewBeginTouch()
393 @Override
public void onSessionViewEndTouch()
398 @Override
public void onSessionViewLeftTouch(
int x,
int y,
boolean down)
403 cancelDelayedMoveEvent();
404 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getLeftButtonEvent(context, down));
407 @Override
public void onSessionViewMiddleTouch(
int x,
int y,
boolean down)
411 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getMiddleButtonEvent(down));
414 @Override
public void onSessionViewRightTouch(
int x,
int y,
boolean down)
418 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getRightButtonEvent(context, down));
421 @Override
public void onSessionViewMove(
int x,
int y)
425 sendDelayedMoveEvent(x, y);
428 @Override
public void onSessionViewMouseMove(
int x,
int y)
432 LibFreeRDP.sendCursorEvent(instance, x, y, Mouse.getMoveEvent());
435 @Override
public void onSessionViewScroll(
boolean down)
439 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context, down));
442 @Override
public void onSessionViewHScroll(
boolean right)
446 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getHScrollEvent(context, right));
452 @Override
public void onTouchPointerClose()
454 touchPointerView.setVisibility(View.INVISIBLE);
455 sessionView.setTouchPointerPadding(0, 0);
458 @Override
public void onTouchPointerLeftClick(
int x,
int y,
boolean down)
462 Point p = mapScreenCoordToSessionCoord(x, y);
463 LibFreeRDP.sendCursorEvent(instance, p.x, p.y, Mouse.getLeftButtonEvent(context, down));
466 @Override
public void onTouchPointerRightClick(
int x,
int y,
boolean down)
470 Point p = mapScreenCoordToSessionCoord(x, y);
471 LibFreeRDP.sendCursorEvent(instance, p.x, p.y, Mouse.getRightButtonEvent(context, down));
474 @Override
public void onTouchPointerMove(
int x,
int y)
478 Point p = mapScreenCoordToSessionCoord(x, y);
479 LibFreeRDP.sendCursorEvent(instance, p.x, p.y, Mouse.getMoveEvent());
482 !handler.hasMessages(MSG_SCROLLING_REQUESTED))
484 handler.sendEmptyMessageDelayed(MSG_SCROLLING_REQUESTED, SCROLLING_TIMEOUT);
488 @Override
public void onTouchPointerMoveEnd()
490 handler.removeMessages(MSG_SCROLLING_REQUESTED);
493 @Override
public void onTouchPointerScroll(
boolean down)
497 LibFreeRDP.sendCursorEvent(instance, 0, 0, Mouse.getScrollEvent(context, down));
500 @Override
public void onTouchPointerToggleKeyboard()
502 toggleSystemKeyboard();
505 @Override
public void onTouchPointerToggleExtKeyboard()
507 toggleExtendedKeyboard();
510 @Override
public void onTouchPointerResetScrollZoom()
512 sessionView.setZoom(1.0f);
519 @Override
public void processVirtualKey(
int virtualKeyCode,
boolean down)
523 LibFreeRDP.sendKeyEvent(instance, virtualKeyCode, down);
526 @Override
public void processUnicodeKey(
int unicodeKey)
530 if (LibFreeRDP.isUnicodeInputSupported(instance))
532 LibFreeRDP.sendUnicodeKeyEvent(instance, unicodeKey,
true);
533 LibFreeRDP.sendUnicodeKeyEvent(instance, unicodeKey,
false);
536 keyboardMapper.processUnicodeFallback(unicodeKey);
539 @Override
public void switchKeyboard(
int keyboardType)
541 switch (keyboardType)
543 case KeyboardMapper.KEYBOARD_TYPE_FUNCTIONKEYS:
544 keyboardView.setKeyboard(specialkeysKeyboard);
547 case KeyboardMapper.KEYBOARD_TYPE_NUMPAD:
548 keyboardView.setKeyboard(numpadKeyboard);
551 case KeyboardMapper.KEYBOARD_TYPE_CURSOR:
552 keyboardView.setKeyboard(cursorKeyboard);
560 @Override
public void modifiersChanged()
562 updateModifierKeyStates();
568 @Override
public void onKey(
int primaryCode,
int[] keyCodes)
570 keyboardMapper.processCustomKeyEvent(primaryCode);
573 @Override
public void onText(CharSequence text)
577 @Override
public void swipeRight()
581 @Override
public void swipeLeft()
585 @Override
public void swipeDown()
589 @Override
public void swipeUp()
593 @Override
public void onPress(
int primaryCode)
597 @Override
public void onRelease(
int primaryCode)
604 private class InputHandler
extends Handler
608 super(Looper.getMainLooper());
611 @Override
public void handleMessage(Message msg)
615 case MSG_SEND_MOVE_EVENT:
618 LibFreeRDP.sendCursorEvent(instance, msg.arg1, msg.arg2, Mouse.getMoveEvent());
621 case MSG_SCROLLING_REQUESTED:
625 float[] pointerPos = touchPointerView.getPointerPosition();
626 final int ow = touchPointerView.getWidth();
627 final int oh = touchPointerView.getHeight();
628 final int pw = touchPointerView.getPointerWidth();
629 final int ph = touchPointerView.getPointerHeight();
631 if (pointerPos[0] >= ow - pw - SCROLLING_EDGE_MARGIN)
632 scrollX = SCROLLING_DISTANCE;
633 else if (pointerPos[0] <= SCROLLING_EDGE_MARGIN)
634 scrollX = -SCROLLING_DISTANCE;
636 if (pointerPos[1] >= oh - ph - SCROLLING_EDGE_MARGIN)
637 scrollY = SCROLLING_DISTANCE;
638 else if (pointerPos[1] <= SCROLLING_EDGE_MARGIN)
639 scrollY = -SCROLLING_DISTANCE;
641 scrollView.scrollBy(scrollX, scrollY);
643 final int maxX = sessionView.getWidth() - scrollView.getWidth();
644 final int maxY = sessionView.getHeight() - scrollView.getHeight();
645 if ((scrollX < 0 && scrollView.getScrollX() <= 0) ||
646 (scrollX > 0 && scrollView.getScrollX() >= maxX))
648 if ((scrollY < 0 && scrollView.getScrollY() <= 0) ||
649 (scrollY > 0 && scrollView.getScrollY() >= maxY))
652 if (scrollX != 0 || scrollY != 0)
653 handler.sendEmptyMessageDelayed(MSG_SCROLLING_REQUESTED, SCROLLING_TIMEOUT);
663 private class PinchZoomListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener
665 private float scaleFactor = 1.0f;
667 @Override
public boolean onScaleBegin(ScaleGestureDetector detector)
673 @Override
public boolean onScale(ScaleGestureDetector detector)
676 scaleFactor *= detector.getScaleFactor();
677 scaleFactor = Math.max(
SessionView.MIN_SCALE_FACTOR,
678 Math.min(scaleFactor,
SessionView.MAX_SCALE_FACTOR));
679 sessionView.setZoom(scaleFactor);
681 if (!sessionView.isAtMinZoom() && !sessionView.isAtMaxZoom())
684 float transOriginX = scrollView.getScrollX() * detector.getScaleFactor();
685 float transOriginY = scrollView.getScrollY() * detector.getScaleFactor();
689 (scrollView.getScrollX() + detector.getFocusX()) * detector.getScaleFactor();
691 (scrollView.getScrollY() + detector.getFocusY()) * detector.getScaleFactor();
696 scrollView.scrollBy((
int)((transCenterX - transOriginX) - detector.getFocusX()),
697 (
int)((transCenterY - transOriginY) - detector.getFocusY()));
703 @Override
public void onScaleEnd(ScaleGestureDetector de)