64 implements LibFreeRDP.UIEventListener, ClipboardManagerProxy.OnClipboardChangedListener
66 public static final String PARAM_CONNECTION_REFERENCE =
"conRef";
67 public static final String PARAM_INSTANCE =
"instance";
68 private static final String TAG =
"FreeRDP.SessionActivity";
69 private Bitmap bitmap;
70 private SessionState session;
74 private static final int REFRESH_SESSIONVIEW = 1;
75 private static final int DISPLAY_TOAST = 2;
76 private static final int GRAPHICS_CHANGED = 6;
78 private final Handler uiHandler =
new Handler(Looper.getMainLooper()) {
79 @Override
public void handleMessage(Message msg)
83 case GRAPHICS_CHANGED:
85 sessionView.onSurfaceChange(session);
86 scrollView.requestLayout();
89 case REFRESH_SESSIONVIEW:
91 sessionView.invalidateRegion();
96 Toast errorToast = Toast.makeText(getApplicationContext(), msg.obj.toString(),
105 private int screen_width;
106 private int screen_height;
108 private boolean connectCancelledByUser =
false;
109 private boolean sessionRunning =
false;
110 private long backPressedTime = 0;
114 private ClipboardManagerProxy mClipboardManager;
118 private void hideSystemBars()
125 if (getSupportActionBar() !=
null)
128 getSupportActionBar().hide();
130 getSupportActionBar().show();
133 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
135 WindowInsetsControllerCompat controller =
136 WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView());
139 toHide |= WindowInsetsCompat.Type.statusBars();
141 toHide |= WindowInsetsCompat.Type.navigationBars();
145 controller.hide(toHide);
146 controller.setSystemBarsBehavior(
147 WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
151 controller.show(WindowInsetsCompat.Type.systemBars());
159 flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
161 flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
163 flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
165 getWindow().getDecorView().setSystemUiVisibility(flags);
169 @Override
public void onCreate(Bundle savedInstanceState)
171 super.onCreate(savedInstanceState);
175 this.setContentView(R.layout.session);
177 Log.v(TAG,
"Session.onCreate");
186 final View activityRootView = findViewById(R.id.session_root_view);
187 activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
188 new OnGlobalLayoutListener() {
189 @Override
public void onGlobalLayout()
191 screen_width = activityRootView.getWidth();
192 screen_height = activityRootView.getHeight();
195 if (!sessionRunning && getIntent() !=
null)
197 processIntent(getIntent());
198 sessionRunning =
true;
203 sessionView = findViewById(R.id.sessionView);
204 sessionView.requestFocus();
206 touchPointerView = findViewById(R.id.touchPointerView);
208 KeyboardView keyboardView = findViewById(R.id.extended_keyboard);
209 KeyboardView modifiersKeyboardView = findViewById(R.id.extended_keyboard_header);
211 scrollView = findViewById(R.id.sessionScrollView);
213 sessionViewModel.getState().observe(
this, this::onConnectionStateChanged);
216 @Override public void onUserCancel()
218 connectCancelledByUser = true;
224 keyboardView, modifiersKeyboardView);
225 sessionView.setSessionViewListener(inputManager);
226 touchPointerView.setTouchPointerListener(inputManager);
227 sessionView.setScaleGestureDetector(
228 new ScaleGestureDetector(
this, inputManager.getPinchZoomListener()));
230 mClipboardManager = ClipboardManagerProxy.getClipboardManager(
this);
231 mClipboardManager.addClipboardChangedListener(
this);
233 getOnBackPressedDispatcher().addCallback(
this,
new OnBackPressedCallback(
true) {
234 @Override
public void handleOnBackPressed()
243 @Override
public void onWindowFocusChanged(
boolean hasFocus)
245 super.onWindowFocusChanged(hasFocus);
248 mClipboardManager.getPrimaryClipManually();
251 @Override
protected void onStart()
254 Log.v(TAG,
"Session.onStart");
257 @Override
protected void onRestart()
260 Log.v(TAG,
"Session.onRestart");
263 @Override
protected void onResume()
266 Log.v(TAG,
"Session.onResume");
269 @Override
protected void onPause()
272 Log.v(TAG,
"Session.onPause");
275 inputManager.hideKeyboards();
278 @Override
protected void onStop()
281 Log.v(TAG,
"Session.onStop");
284 @Override
protected void onDestroy()
286 if (connectThread !=
null)
288 connectThread.interrupt();
291 Log.v(TAG,
"Session.onDestroy");
294 GlobalApp.cancelDisconnectTimer();
297 Collection<SessionState> sessions = GlobalApp.getSessions();
298 for (SessionState session : sessions)
299 LibFreeRDP.disconnect(session.getInstance());
302 sessionViewModel.unregister();
305 mClipboardManager.removeClipboardboardChangedListener(
this);
308 GlobalApp.freeSession(session.getInstance());
313 @Override
public void onConfigurationChanged(Configuration newConfig)
315 super.onConfigurationChanged(newConfig);
318 inputManager.reloadKeyboards();
323 private void processIntent(Intent intent)
326 Bundle bundle = intent.getExtras();
327 Uri openUri = intent.getData();
334 else if (bundle.containsKey(PARAM_INSTANCE))
336 int inst = bundle.getInt(PARAM_INSTANCE);
337 session = GlobalApp.getSession(inst);
338 bitmap = session.getSurface().getBitmap();
341 else if (bundle.containsKey(PARAM_CONNECTION_REFERENCE))
343 String refStr = bundle.getString(PARAM_CONNECTION_REFERENCE);
344 if (ConnectionReference.isHostnameReference(refStr))
346 BookmarkBase bookmark =
new BookmarkBase();
347 bookmark.setHostname(ConnectionReference.getHostname(refStr));
350 else if (ConnectionReference.isBookmarkReference(refStr))
352 sessionViewModel.loadBookmarkById(ConnectionReference.getBookmarkId(refStr),
354 if (bookmark != null)
357 closeSessionActivity(RESULT_CANCELED);
362 closeSessionActivity(RESULT_CANCELED);
368 closeSessionActivity(RESULT_CANCELED);
372 private void connect(BookmarkBase bookmark)
374 session = GlobalApp.createSession(bookmark, getApplicationContext());
376 BookmarkBase.ScreenSettings screenSettings =
377 session.getBookmark().getActiveScreenSettings();
378 Log.v(TAG,
"Screen Resolution: " + screenSettings.getResolutionString());
379 if (screenSettings.isAutomatic())
381 if ((getResources().getConfiguration().screenLayout &
382 Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE)
385 screenSettings.setHeight(screen_height);
386 screenSettings.setWidth(screen_width);
393 int screenMax = Math.max(screen_width, screen_height);
394 screenSettings.setHeight(screenMax);
395 screenSettings.setWidth((
int)((
float)screenMax * 1.6f));
398 if (screenSettings.isFitScreen())
400 screenSettings.setHeight(screen_height);
401 screenSettings.setWidth(screen_width);
404 connectWithTitle(bookmark.getLabel());
407 private void connect(Uri openUri)
409 session = GlobalApp.createSession(openUri, getApplicationContext());
411 connectWithTitle(openUri.getAuthority());
414 static class ConnectThread
extends Thread
416 private final SessionState runnableSession;
417 private final Context context;
419 public ConnectThread(@NonNull Context context, @NonNull SessionState session)
421 this.context = context;
422 runnableSession = session;
427 runnableSession.connect(context.getApplicationContext());
431 private ConnectThread connectThread =
null;
433 private void connectWithTitle(String title)
435 session.setUIEventListener(
this);
437 sessionViewModel.register(session.getInstance());
439 dialogs.showProgress(title, () -> {
440 connectCancelledByUser =
true;
441 LibFreeRDP.cancelConnection(session.getInstance());
444 connectThread =
new ConnectThread(getApplicationContext(), session);
445 connectThread.start();
450 private void bindSession()
452 Log.v(TAG,
"bindSession called");
453 session.setUIEventListener(
this);
454 sessionView.onSurfaceChange(session);
455 scrollView.requestLayout();
457 Bitmap surface = session.getSurface() !=
null ? session.getSurface().getBitmap() :
null;
458 inputManager.attachSession(session.getInstance(), surface);
459 inputManager.setScreenSize(screen_width, screen_height);
463 private void closeSessionActivity(
int resultCode)
466 setResult(resultCode, getIntent());
470 @Override
public boolean onCreateOptionsMenu(Menu menu)
472 getMenuInflater().inflate(R.menu.session_menu, menu);
476 @Override
public boolean onOptionsItemSelected(MenuItem item)
480 int itemId = item.getItemId();
482 if (itemId == R.id.session_touch_pointer)
484 inputManager.toggleTouchPointer();
486 else if (itemId == R.id.session_sys_keyboard)
488 inputManager.toggleSystemKeyboard();
490 else if (itemId == R.id.session_ext_keyboard)
492 inputManager.toggleExtendedKeyboard();
494 else if (itemId == R.id.session_disconnect)
496 inputManager.hideKeyboards();
497 LibFreeRDP.disconnect(session.getInstance());
503 public void handleBackPressed()
506 if (inputManager.isAnyKeyboardVisible())
508 inputManager.hideKeyboards();
511 if (inputManager.handleBackAsAltF4())
515 if (System.currentTimeMillis() - backPressedTime < 2000)
517 LibFreeRDP.disconnect(session.getInstance());
521 backPressedTime = System.currentTimeMillis();
522 Toast.makeText(
this, R.string.session_double_back_to_exit, Toast.LENGTH_SHORT).show();
526 @Override
public boolean onKeyLongPress(
int keyCode, KeyEvent event)
528 if (inputManager.onAndroidKeyLongPress(keyCode))
530 return super.onKeyLongPress(keyCode, event);
539 @Override
public boolean onKeyDown(
int keycode, KeyEvent event)
541 if (keycode == KeyEvent.KEYCODE_BACK)
542 return super.onKeyDown(keycode, event);
543 return inputManager.onAndroidKeyEvent(event);
546 @Override
public boolean onKeyUp(
int keycode, KeyEvent event)
548 if (keycode == KeyEvent.KEYCODE_BACK)
549 return super.onKeyUp(keycode, event);
550 return inputManager.onAndroidKeyEvent(event);
555 @Override
public boolean onKeyMultiple(
int keyCode,
int repeatCount, KeyEvent event)
557 return inputManager.onAndroidKeyEvent(event);
565 @Override
public void OnSettingsChanged(
int width,
int height,
int bpp)
569 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
571 bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
573 session.setSurface(
new BitmapDrawable(getResources(), bitmap));
575 if (inputManager !=
null)
576 inputManager.setBitmap(bitmap);
578 if (session.getBookmark() ==
null)
588 BookmarkBase.ScreenSettings settings = session.getBookmark().getActiveScreenSettings();
589 if ((settings.getWidth() != width && settings.getWidth() != width + 1) ||
590 settings.getHeight() != height || settings.getColors() != bpp)
591 uiHandler.sendMessage(Message.obtain(
592 null, DISPLAY_TOAST, getResources().getText(R.string.info_capabilities_changed)));
595 @Override
public void OnGraphicsUpdate(
int x,
int y,
int width,
int height)
597 LibFreeRDP.updateGraphics(session.getInstance(), bitmap, x, y, width, height);
599 sessionView.addInvalidRegion(
new Rect(x, y, x + width, y + height));
606 uiHandler.sendEmptyMessage(REFRESH_SESSIONVIEW);
609 @Override
public void OnGraphicsResize(
int width,
int height,
int bpp)
613 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
615 bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
616 session.setSurface(
new BitmapDrawable(getResources(), bitmap));
618 if (inputManager !=
null)
619 inputManager.setBitmap(bitmap);
625 uiHandler.sendEmptyMessage(GRAPHICS_CHANGED);
629 public boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
630 StringBuilder password)
632 return dialogs.promptCredentials(username, domain, password);
636 public boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
637 StringBuilder password)
639 return dialogs.promptCredentials(username, domain, password);
643 public int OnVerifiyCertificateEx(String host,
long port, String commonName, String subject,
644 String issuer, String fingerprint,
long flags)
646 if (ApplicationSettingsActivity.getAcceptAllCertificates(
this))
648 return dialogs.verifyCertificate(host, port, subject, issuer, fingerprint, flags);
652 public int OnVerifyChangedCertificateEx(String host,
long port, String commonName,
653 String subject, String issuer, String fingerprint,
654 String oldSubject, String oldIssuer,
655 String oldFingerprint,
long flags)
657 if (ApplicationSettingsActivity.getAcceptAllCertificates(
this))
659 return dialogs.verifyChangedCertificate(host, port, subject, issuer, fingerprint, flags);
662 @Override
public void OnRemoteClipboardChanged(String data)
664 Log.v(TAG,
"OnRemoteClipboardChanged: " + data);
665 mClipboardManager.setClipboardData(data);
672 @Override
public boolean onGenericMotionEvent(MotionEvent e)
674 super.onGenericMotionEvent(e);
675 return inputManager !=
null && inputManager.onGenericMotionEvent(e);
680 @Override
public void onClipboardChanged(String data)
682 Log.v(TAG,
"onClipboardChanged: " + data);
683 LibFreeRDP.sendClipboardData(session.getInstance(), data);
686 private void onConnectionStateChanged(SessionViewModel.ConnectionState state)
693 onSessionConnected();
699 onSessionDisconnected();
706 private void onSessionConnected()
708 Log.v(TAG,
"onSessionConnected");
710 if (connectCancelledByUser)
712 LibFreeRDP.disconnect(session.getInstance());
713 closeSessionActivity(RESULT_CANCELED);
720 if (ApplicationSettingsActivity.getKeepScreenOnWhenConnected(
this))
722 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
725 dialogs.dismissProgress();
727 if (session.getBookmark() ==
null)
734 Bundle bundle = getIntent().getExtras();
735 if (bundle !=
null && bundle.containsKey(PARAM_CONNECTION_REFERENCE))
737 if (ConnectionReference.isHostnameReference(
738 bundle.getString(PARAM_CONNECTION_REFERENCE)))
740 assert session.getBookmark().getType() == BookmarkBase.TYPE_MANUAL;
741 sessionViewModel.recordQuickConnectHistory(session.getBookmark().getHostname());
746 private void onSessionFailed()
748 Log.v(TAG,
"onSessionFailed");
751 if (inputManager !=
null)
752 inputManager.cancelPendingEvents();
754 dialogs.dismissProgress();
757 if (!connectCancelledByUser)
758 uiHandler.sendMessage(Message.obtain(
759 null, DISPLAY_TOAST, getResources().getText(R.string.error_connection_failure)));
761 closeSessionActivity(RESULT_CANCELED);
764 private void onSessionDisconnected()
766 Log.v(TAG,
"onSessionDisconnected");
769 if (inputManager !=
null)
770 inputManager.cancelPendingEvents();
772 if (ApplicationSettingsActivity.getKeepScreenOnWhenConnected(
this))
774 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
777 dialogs.dismissProgress();
779 session.setUIEventListener(
null);
780 closeSessionActivity(RESULT_OK);