11 package com.freerdp.freerdpcore.presentation;
13 import android.app.AlertDialog;
14 import android.app.Dialog;
15 import android.app.ProgressDialog;
16 import android.app.UiModeManager;
17 import android.content.BroadcastReceiver;
18 import android.content.Context;
19 import android.content.DialogInterface;
20 import android.content.Intent;
21 import android.content.IntentFilter;
22 import android.content.SharedPreferences;
23 import android.content.res.Configuration;
24 import android.graphics.Bitmap;
25 import android.graphics.Bitmap.Config;
26 import android.graphics.Point;
27 import android.graphics.Rect;
28 import android.graphics.drawable.BitmapDrawable;
29 import android.inputmethodservice.Keyboard;
30 import android.inputmethodservice.KeyboardView;
31 import android.net.Uri;
32 import android.os.Build;
33 import android.os.Bundle;
34 import android.os.Handler;
35 import android.os.Message;
37 import androidx.annotation.NonNull;
38 import androidx.appcompat.app.AppCompatActivity;
40 import android.text.InputType;
41 import android.util.Log;
42 import android.view.KeyEvent;
43 import android.view.Menu;
44 import android.view.MenuItem;
45 import android.view.MotionEvent;
46 import android.view.ScaleGestureDetector;
47 import android.view.View;
48 import android.view.ViewConfiguration;
49 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
50 import android.view.WindowManager;
51 import android.view.inputmethod.InputMethodManager;
52 import android.view.inputmethod.InputMethodSubtype;
53 import android.widget.EditText;
54 import android.widget.Toast;
55 import android.widget.ZoomControls;
57 import com.freerdp.freerdpcore.R;
58 import com.freerdp.freerdpcore.application.GlobalApp;
59 import com.freerdp.freerdpcore.application.SessionState;
60 import com.freerdp.freerdpcore.domain.BookmarkBase;
61 import com.freerdp.freerdpcore.domain.ConnectionReference;
62 import com.freerdp.freerdpcore.domain.ManualBookmark;
63 import com.freerdp.freerdpcore.services.LibFreeRDP;
64 import com.freerdp.freerdpcore.utils.ClipboardManagerProxy;
65 import com.freerdp.freerdpcore.utils.KeyboardMapper;
66 import com.freerdp.freerdpcore.utils.Mouse;
68 import java.util.Collection;
69 import java.util.Iterator;
70 import java.util.List;
73 implements
LibFreeRDP.UIEventListener, KeyboardView.OnKeyboardActionListener,
78 public static final String PARAM_CONNECTION_REFERENCE =
"conRef";
79 public static final String PARAM_INSTANCE =
"instance";
80 private static final float ZOOMING_STEP = 0.5f;
81 private static final int ZOOMCONTROLS_AUTOHIDE_TIMEOUT = 4000;
84 private static final int SCROLLING_TIMEOUT = 50;
85 private static final int SCROLLING_DISTANCE = 20;
86 private static final String TAG =
"FreeRDP.SessionActivity";
88 private static final int MAX_DISCARDED_MOVE_EVENTS = 3;
89 private static final int SEND_MOVE_EVENT_TIMEOUT = 150;
90 private Bitmap bitmap;
94 private ProgressDialog progressDialog;
95 private KeyboardView keyboardView;
96 private KeyboardView modifiersKeyboardView;
97 private ZoomControls zoomControls;
100 private Keyboard specialkeysKeyboard;
101 private Keyboard numpadKeyboard;
102 private Keyboard cursorKeyboard;
103 private Keyboard modifiersKeyboard;
105 private AlertDialog dlgVerifyCertificate;
106 private AlertDialog dlgUserCredentials;
107 private View userCredView;
109 private UIHandler uiHandler;
111 private int screen_width;
112 private int screen_height;
114 private boolean connectCancelledByUser =
false;
115 private boolean sessionRunning =
false;
116 private boolean toggleMouseButtons =
false;
118 private LibFreeRDPBroadcastReceiver libFreeRDPBroadcastReceiver;
121 private boolean sysKeyboardVisible =
false;
122 private boolean extKeyboardVisible =
false;
123 private int discardedMoveEvents = 0;
125 private boolean callbackDialogResult;
128 private void createDialogs()
131 dlgVerifyCertificate =
132 new AlertDialog.Builder(
this)
133 .setTitle(R.string.dlg_title_verify_certificate)
134 .setPositiveButton(android.R.string.yes,
135 new DialogInterface.OnClickListener() {
137 public void onClick(DialogInterface dialog, int which)
139 callbackDialogResult = true;
140 synchronized (dialog)
146 .setNegativeButton(android.R.string.no,
147 new DialogInterface.OnClickListener() {
149 public void onClick(DialogInterface dialog, int which)
151 callbackDialogResult = false;
152 connectCancelledByUser = true;
153 synchronized (dialog)
159 .setCancelable(
false)
163 userCredView = getLayoutInflater().inflate(R.layout.credentials,
null,
true);
165 new AlertDialog.Builder(
this)
166 .setView(userCredView)
167 .setTitle(R.string.dlg_title_credentials)
168 .setPositiveButton(android.R.string.ok,
169 new DialogInterface.OnClickListener() {
171 public void onClick(DialogInterface dialog, int which)
173 callbackDialogResult = true;
174 synchronized (dialog)
180 .setNegativeButton(android.R.string.cancel,
181 new DialogInterface.OnClickListener() {
183 public void onClick(DialogInterface dialog, int which)
185 callbackDialogResult = false;
186 connectCancelledByUser = true;
187 synchronized (dialog)
193 .setCancelable(
false)
197 private boolean hasHardwareMenuButton()
199 if (Build.VERSION.SDK_INT <= 10)
202 if (Build.VERSION.SDK_INT >= 14)
205 final ViewConfiguration cfg = ViewConfiguration.get(
this);
207 return cfg.hasPermanentMenuKey();
213 @Override
public void onCreate(Bundle savedInstanceState)
215 super.onCreate(savedInstanceState);
218 if (ApplicationSettingsActivity.getHideStatusBar(
this))
220 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
221 WindowManager.LayoutParams.FLAG_FULLSCREEN);
224 this.setContentView(R.layout.session);
225 if (hasHardwareMenuButton() || ApplicationSettingsActivity.getHideActionBar(
this))
227 this.getSupportActionBar().hide();
230 this.getSupportActionBar().show();
232 Log.v(TAG,
"Session.onCreate");
241 final View activityRootView = findViewById(R.id.session_root_view);
242 activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
243 new OnGlobalLayoutListener() {
244 @Override
public void onGlobalLayout()
246 screen_width = activityRootView.getWidth();
247 screen_height = activityRootView.getHeight();
250 if (!sessionRunning && getIntent() !=
null)
252 processIntent(getIntent());
253 sessionRunning =
true;
258 sessionView = (SessionView)findViewById(R.id.sessionView);
259 sessionView.setScaleGestureDetector(
260 new ScaleGestureDetector(
this,
new PinchZoomListener()));
261 sessionView.setSessionViewListener(
this);
262 sessionView.requestFocus();
265 touchPointerView.setTouchPointerListener(
this);
267 keyboardMapper =
new KeyboardMapper();
268 keyboardMapper.init(
this);
269 keyboardMapper.reset(
this);
271 modifiersKeyboard =
new Keyboard(getApplicationContext(), R.xml.modifiers_keyboard);
272 specialkeysKeyboard =
new Keyboard(getApplicationContext(), R.xml.specialkeys_keyboard);
273 numpadKeyboard =
new Keyboard(getApplicationContext(), R.xml.numpad_keyboard);
274 cursorKeyboard =
new Keyboard(getApplicationContext(), R.xml.cursor_keyboard);
277 keyboardView = (KeyboardView)findViewById(R.id.extended_keyboard);
278 keyboardView.setKeyboard(specialkeysKeyboard);
279 keyboardView.setOnKeyboardActionListener(
this);
281 modifiersKeyboardView = (KeyboardView)findViewById(R.id.extended_keyboard_header);
282 modifiersKeyboardView.setKeyboard(modifiersKeyboard);
283 modifiersKeyboardView.setOnKeyboardActionListener(
this);
285 scrollView = (ScrollView2D)findViewById(R.id.sessionScrollView);
286 scrollView.setScrollViewListener(
this);
287 uiHandler =
new UIHandler();
288 libFreeRDPBroadcastReceiver =
new LibFreeRDPBroadcastReceiver();
290 zoomControls = (ZoomControls)findViewById(R.id.zoomControls);
292 zoomControls.setOnZoomInClickListener(
new View.OnClickListener() {
293 @Override
public void onClick(View v)
295 resetZoomControlsAutoHideTimeout();
296 zoomControls.setIsZoomInEnabled(sessionView.zoomIn(ZOOMING_STEP));
297 zoomControls.setIsZoomOutEnabled(
true);
300 zoomControls.setOnZoomOutClickListener(
new View.OnClickListener() {
301 @Override
public void onClick(View v)
303 resetZoomControlsAutoHideTimeout();
304 zoomControls.setIsZoomOutEnabled(sessionView.zoomOut(ZOOMING_STEP));
305 zoomControls.setIsZoomInEnabled(
true);
309 toggleMouseButtons =
false;
314 IntentFilter filter =
new IntentFilter();
315 filter.addAction(GlobalApp.ACTION_EVENT_FREERDP);
316 registerReceiver(libFreeRDPBroadcastReceiver, filter);
318 mClipboardManager = ClipboardManagerProxy.getClipboardManager(
this);
319 mClipboardManager.addClipboardChangedListener(
this);
321 mDecor = getWindow().getDecorView();
322 mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
323 View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
326 @Override
public void onWindowFocusChanged(
boolean hasFocus)
328 super.onWindowFocusChanged(hasFocus);
329 mClipboardManager.getPrimaryClipManually();
332 @Override
protected void onStart()
335 Log.v(TAG,
"Session.onStart");
338 @Override
protected void onRestart()
341 Log.v(TAG,
"Session.onRestart");
344 @Override
protected void onResume()
347 Log.v(TAG,
"Session.onResume");
350 @Override
protected void onPause()
353 Log.v(TAG,
"Session.onPause");
356 showKeyboard(
false,
false);
359 @Override
protected void onStop()
362 Log.v(TAG,
"Session.onStop");
365 @Override
protected void onDestroy()
367 if (connectThread !=
null)
369 connectThread.interrupt();
372 Log.v(TAG,
"Session.onDestroy");
375 GlobalApp.cancelDisconnectTimer();
378 Collection<SessionState> sessions = GlobalApp.getSessions();
379 for (SessionState session : sessions)
380 LibFreeRDP.disconnect(session.getInstance());
383 unregisterReceiver(libFreeRDPBroadcastReceiver);
386 mClipboardManager.removeClipboardboardChangedListener(
this);
389 GlobalApp.freeSession(session.getInstance());
394 @Override
public void onConfigurationChanged(Configuration newConfig)
396 super.onConfigurationChanged(newConfig);
399 modifiersKeyboard =
new Keyboard(getApplicationContext(), R.xml.modifiers_keyboard);
400 specialkeysKeyboard =
new Keyboard(getApplicationContext(), R.xml.specialkeys_keyboard);
401 numpadKeyboard =
new Keyboard(getApplicationContext(), R.xml.numpad_keyboard);
402 cursorKeyboard =
new Keyboard(getApplicationContext(), R.xml.cursor_keyboard);
405 keyboardView.setKeyboard(specialkeysKeyboard);
406 modifiersKeyboardView.setKeyboard(modifiersKeyboard);
408 mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
409 View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
412 private void processIntent(Intent intent)
415 Bundle bundle = intent.getExtras();
416 Uri openUri = intent.getData();
423 else if (bundle.containsKey(PARAM_INSTANCE))
425 int inst = bundle.getInt(PARAM_INSTANCE);
426 session = GlobalApp.getSession(inst);
427 bitmap = session.getSurface().getBitmap();
430 else if (bundle.containsKey(PARAM_CONNECTION_REFERENCE))
432 BookmarkBase bookmark =
null;
433 String refStr = bundle.getString(PARAM_CONNECTION_REFERENCE);
434 if (ConnectionReference.isHostnameReference(refStr))
436 bookmark =
new ManualBookmark();
437 bookmark.<ManualBookmark>
get().setHostname(ConnectionReference.getHostname(refStr));
439 else if (ConnectionReference.isBookmarkReference(refStr))
441 if (ConnectionReference.isManualBookmarkReference(refStr))
442 bookmark = GlobalApp.getManualBookmarkGateway().findById(
443 ConnectionReference.getManualBookmarkId(refStr));
448 if (bookmark !=
null)
451 closeSessionActivity(RESULT_CANCELED);
456 closeSessionActivity(RESULT_CANCELED);
460 private void connect(BookmarkBase bookmark)
462 session = GlobalApp.createSession(bookmark, getApplicationContext());
464 BookmarkBase.ScreenSettings screenSettings =
465 session.getBookmark().getActiveScreenSettings();
466 Log.v(TAG,
"Screen Resolution: " + screenSettings.getResolutionString());
467 if (screenSettings.isAutomatic())
469 if ((getResources().getConfiguration().screenLayout &
470 Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE)
473 screenSettings.setHeight(screen_height);
474 screenSettings.setWidth(screen_width);
481 int screenMax = Math.max(screen_width, screen_height);
482 screenSettings.setHeight(screenMax);
483 screenSettings.setWidth((
int)((
float)screenMax * 1.6f));
486 if (screenSettings.isFitScreen())
488 screenSettings.setHeight(screen_height);
489 screenSettings.setWidth(screen_width);
492 connectWithTitle(bookmark.getLabel());
495 private void connect(Uri openUri)
497 session = GlobalApp.createSession(openUri, getApplicationContext());
499 connectWithTitle(openUri.getAuthority());
502 static class ConnectThread
extends Thread
504 private SessionState runnableSession;
505 private Context context;
507 public ConnectThread(@NonNull Context context, @NonNull SessionState session)
509 this.context = context;
510 runnableSession = session;
515 runnableSession.connect(context.getApplicationContext());
519 private ConnectThread connectThread =
null;
521 private void connectWithTitle(String title)
523 session.setUIEventListener(
this);
525 progressDialog =
new ProgressDialog(
this);
526 progressDialog.setTitle(title);
527 progressDialog.setMessage(getResources().getText(R.string.dlg_msg_connecting));
528 progressDialog.setButton(
529 ProgressDialog.BUTTON_NEGATIVE,
"Cancel",
new DialogInterface.OnClickListener() {
530 @Override public void onClick(DialogInterface dialog, int which)
532 connectCancelledByUser = true;
533 LibFreeRDP.cancelConnection(session.getInstance());
536 progressDialog.setCancelable(
false);
537 progressDialog.show();
539 connectThread =
new ConnectThread(getApplicationContext(), session);
540 connectThread.start();
545 private void bindSession()
547 Log.v(TAG,
"bindSession called");
548 session.setUIEventListener(
this);
549 sessionView.onSurfaceChange(session);
550 scrollView.requestLayout();
551 keyboardMapper.reset(
this);
552 mDecor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
553 View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
556 private void setSoftInputState(
boolean state)
558 InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
562 mgr.showSoftInput(sessionView, InputMethodManager.SHOW_FORCED);
566 mgr.hideSoftInputFromWindow(sessionView.getWindowToken(), 0);
571 private void showKeyboard(
final boolean showSystemKeyboard,
final boolean showExtendedKeyboard)
576 uiHandler.removeMessages(UIHandler.SHOW_ZOOMCONTROLS);
577 uiHandler.sendEmptyMessage(UIHandler.HIDE_ZOOMCONTROLS);
579 InputMethodManager mgr = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
581 if (showSystemKeyboard)
584 keyboardView.setVisibility(View.GONE);
586 setSoftInputState(
true);
589 modifiersKeyboardView.setVisibility(View.VISIBLE);
591 else if (showExtendedKeyboard)
594 setSoftInputState(
false);
597 keyboardView.setKeyboard(specialkeysKeyboard);
598 keyboardView.setVisibility(View.VISIBLE);
599 modifiersKeyboardView.setVisibility(View.VISIBLE);
604 setSoftInputState(
false);
605 keyboardView.setVisibility(View.GONE);
606 modifiersKeyboardView.setVisibility(View.GONE);
609 keyboardMapper.clearlAllModifiers();
612 sysKeyboardVisible = showSystemKeyboard;
613 extKeyboardVisible = showExtendedKeyboard;
616 private void closeSessionActivity(
int resultCode)
619 setResult(resultCode, getIntent());
624 private void updateModifierKeyStates()
628 List<Keyboard.Key> keys = modifiersKeyboard.getKeys();
629 for (Keyboard.Key curKey : keys)
634 switch (keyboardMapper.getModifierState(curKey.codes[0]))
636 case KeyboardMapper.KEYSTATE_ON:
638 curKey.pressed =
false;
641 case KeyboardMapper.KEYSTATE_OFF:
643 curKey.pressed =
false;
646 case KeyboardMapper.KEYSTATE_LOCKED:
648 curKey.pressed =
true;
655 modifiersKeyboardView.invalidateAllKeys();
658 private void sendDelayedMoveEvent(
int x,
int y)
660 if (uiHandler.hasMessages(UIHandler.SEND_MOVE_EVENT))
662 uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
663 discardedMoveEvents++;
666 discardedMoveEvents = 0;
668 if (discardedMoveEvents > MAX_DISCARDED_MOVE_EVENTS)
669 LibFreeRDP.sendCursorEvent(session.getInstance(), x, y, Mouse.getMoveEvent());
671 uiHandler.sendMessageDelayed(Message.obtain(
null, UIHandler.SEND_MOVE_EVENT, x, y),
672 SEND_MOVE_EVENT_TIMEOUT);
675 private void cancelDelayedMoveEvent()
677 uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
680 @Override
public boolean onCreateOptionsMenu(Menu menu)
682 getMenuInflater().inflate(R.menu.session_menu, menu);
686 @Override
public boolean onOptionsItemSelected(MenuItem item)
690 int itemId = item.getItemId();
692 if (itemId == R.id.session_touch_pointer)
695 if (touchPointerView.getVisibility() == View.VISIBLE)
697 touchPointerView.setVisibility(View.INVISIBLE);
698 sessionView.setTouchPointerPadding(0, 0);
702 touchPointerView.setVisibility(View.VISIBLE);
703 sessionView.setTouchPointerPadding(touchPointerView.getPointerWidth(),
704 touchPointerView.getPointerHeight());
707 else if (itemId == R.id.session_sys_keyboard)
709 showKeyboard(!sysKeyboardVisible,
false);
711 else if (itemId == R.id.session_ext_keyboard)
713 showKeyboard(
false, !extKeyboardVisible);
715 else if (itemId == R.id.session_disconnect)
717 showKeyboard(
false,
false);
718 LibFreeRDP.disconnect(session.getInstance());
724 @Override
public void onBackPressed()
727 if (sysKeyboardVisible || extKeyboardVisible)
728 showKeyboard(
false,
false);
729 else if (ApplicationSettingsActivity.getUseBackAsAltf4(
this))
731 keyboardMapper.sendAltF4();
735 @Override
public boolean onKeyLongPress(
int keyCode, KeyEvent event)
737 if (keyCode == KeyEvent.KEYCODE_BACK)
739 LibFreeRDP.disconnect(session.getInstance());
742 return super.onKeyLongPress(keyCode, event);
751 @Override
public boolean onKeyDown(
int keycode, KeyEvent event)
753 return keyboardMapper.processAndroidKeyEvent(event);
756 @Override
public boolean onKeyUp(
int keycode, KeyEvent event)
758 return keyboardMapper.processAndroidKeyEvent(event);
763 @Override
public boolean onKeyMultiple(
int keyCode,
int repeatCount, KeyEvent event)
765 return keyboardMapper.processAndroidKeyEvent(event);
770 @Override
public void onKey(
int primaryCode,
int[] keyCodes)
772 keyboardMapper.processCustomKeyEvent(primaryCode);
775 @Override
public void onText(CharSequence text)
779 @Override
public void swipeRight()
783 @Override
public void swipeLeft()
787 @Override
public void swipeDown()
791 @Override
public void swipeUp()
795 @Override
public void onPress(
int primaryCode)
799 @Override
public void onRelease(
int primaryCode)
805 @Override
public void processVirtualKey(
int virtualKeyCode,
boolean down)
807 LibFreeRDP.sendKeyEvent(session.getInstance(), virtualKeyCode, down);
810 @Override
public void processUnicodeKey(
int unicodeKey)
812 LibFreeRDP.sendUnicodeKeyEvent(session.getInstance(), unicodeKey,
true);
813 LibFreeRDP.sendUnicodeKeyEvent(session.getInstance(), unicodeKey,
false);
816 @Override
public void switchKeyboard(
int keyboardType)
818 switch (keyboardType)
820 case KeyboardMapper.KEYBOARD_TYPE_FUNCTIONKEYS:
821 keyboardView.setKeyboard(specialkeysKeyboard);
824 case KeyboardMapper.KEYBOARD_TYPE_NUMPAD:
825 keyboardView.setKeyboard(numpadKeyboard);
828 case KeyboardMapper.KEYBOARD_TYPE_CURSOR:
829 keyboardView.setKeyboard(cursorKeyboard);
837 @Override
public void modifiersChanged()
839 updateModifierKeyStates();
844 @Override
public void OnSettingsChanged(
int width,
int height,
int bpp)
848 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
850 bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
852 session.setSurface(
new BitmapDrawable(getResources(), bitmap));
854 if (session.getBookmark() ==
null)
865 BookmarkBase.ScreenSettings settings = session.getBookmark().getActiveScreenSettings();
866 if ((settings.getWidth() != width && settings.getWidth() != width + 1) ||
867 settings.getHeight() != height || settings.getColors() != bpp)
868 uiHandler.sendMessage(
869 Message.obtain(
null, UIHandler.DISPLAY_TOAST,
870 getResources().getText(R.string.info_capabilities_changed)));
873 @Override
public void OnGraphicsUpdate(
int x,
int y,
int width,
int height)
875 LibFreeRDP.updateGraphics(session.getInstance(), bitmap, x, y, width, height);
877 sessionView.addInvalidRegion(
new Rect(x, y, x + width, y + height));
884 uiHandler.sendEmptyMessage(UIHandler.REFRESH_SESSIONVIEW);
887 @Override
public void OnGraphicsResize(
int width,
int height,
int bpp)
891 bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
893 bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
894 session.setSurface(
new BitmapDrawable(getResources(), bitmap));
900 uiHandler.sendEmptyMessage(UIHandler.GRAPHICS_CHANGED);
904 public boolean OnAuthenticate(StringBuilder username, StringBuilder domain,
905 StringBuilder password)
908 callbackDialogResult =
false;
911 ((EditText)userCredView.findViewById(R.id.editTextUsername)).setText(username);
912 ((EditText)userCredView.findViewById(R.id.editTextDomain)).setText(domain);
913 ((EditText)userCredView.findViewById(R.id.editTextPassword)).setText(password);
916 uiHandler.sendMessage(Message.obtain(
null, UIHandler.SHOW_DIALOG, dlgUserCredentials));
921 synchronized (dlgUserCredentials)
923 dlgUserCredentials.wait();
926 catch (InterruptedException e)
931 username.setLength(0);
933 password.setLength(0);
937 ((EditText)userCredView.findViewById(R.id.editTextUsername)).getText().toString());
939 ((EditText)userCredView.findViewById(R.id.editTextDomain)).getText().toString());
941 ((EditText)userCredView.findViewById(R.id.editTextPassword)).getText().toString());
943 return callbackDialogResult;
947 public boolean OnGatewayAuthenticate(StringBuilder username, StringBuilder domain,
948 StringBuilder password)
951 callbackDialogResult =
false;
954 ((EditText)userCredView.findViewById(R.id.editTextUsername)).setText(username);
955 ((EditText)userCredView.findViewById(R.id.editTextDomain)).setText(domain);
956 ((EditText)userCredView.findViewById(R.id.editTextPassword)).setText(password);
959 uiHandler.sendMessage(Message.obtain(
null, UIHandler.SHOW_DIALOG, dlgUserCredentials));
964 synchronized (dlgUserCredentials)
966 dlgUserCredentials.wait();
969 catch (InterruptedException e)
974 username.setLength(0);
976 password.setLength(0);
980 ((EditText)userCredView.findViewById(R.id.editTextUsername)).getText().toString());
982 ((EditText)userCredView.findViewById(R.id.editTextDomain)).getText().toString());
984 ((EditText)userCredView.findViewById(R.id.editTextPassword)).getText().toString());
986 return callbackDialogResult;
990 public int OnVerifiyCertificateEx(String host,
long port, String commonName, String subject,
991 String issuer, String fingerprint,
long flags)
994 if (ApplicationSettingsActivity.getAcceptAllCertificates(
this))
998 callbackDialogResult =
false;
1001 String msg = getResources().getString(R.string.dlg_msg_verify_certificate);
1002 String type =
"RDP-Server";
1003 if ((flags & LibFreeRDP.VERIFY_CERT_FLAG_GATEWAY) != 0)
1004 type =
"RDP-Gateway";
1005 if ((flags & LibFreeRDP.VERIFY_CERT_FLAG_REDIRECT) != 0)
1006 type =
"RDP-Redirect";
1007 msg +=
"\n\n" + type +
": " + host +
":" + port;
1009 msg +=
"\n\nSubject: " + subject +
"\nIssuer: " + issuer;
1011 if ((flags & LibFreeRDP.VERIFY_CERT_FLAG_FP_IS_PEM) != 0)
1012 msg +=
"\nCertificate: " + fingerprint;
1014 msg +=
"\nFingerprint: " + fingerprint;
1015 dlgVerifyCertificate.setMessage(msg);
1018 uiHandler.sendMessage(Message.obtain(
null, UIHandler.SHOW_DIALOG, dlgVerifyCertificate));
1023 synchronized (dlgVerifyCertificate)
1025 dlgVerifyCertificate.wait();
1028 catch (InterruptedException e)
1032 return callbackDialogResult ? 1 : 0;
1036 public int OnVerifyChangedCertificateEx(String host,
long port, String commonName,
1037 String subject, String issuer, String fingerprint,
1038 String oldSubject, String oldIssuer,
1039 String oldFingerprint,
long flags)
1042 if (ApplicationSettingsActivity.getAcceptAllCertificates(
this))
1046 callbackDialogResult =
false;
1049 String msg = getResources().getString(R.string.dlg_msg_verify_certificate);
1050 String type =
"RDP-Server";
1051 if ((flags & LibFreeRDP.VERIFY_CERT_FLAG_GATEWAY) != 0)
1052 type =
"RDP-Gateway";
1053 if ((flags & LibFreeRDP.VERIFY_CERT_FLAG_REDIRECT) != 0)
1054 type =
"RDP-Redirect";
1055 msg +=
"\n\n" + type +
": " + host +
":" + port;
1056 msg +=
"\n\nSubject: " + subject +
"\nIssuer: " + issuer;
1057 if ((flags & LibFreeRDP.VERIFY_CERT_FLAG_FP_IS_PEM) != 0)
1058 msg +=
"\nCertificate: " + fingerprint;
1060 msg +=
"\nFingerprint: " + fingerprint;
1061 dlgVerifyCertificate.setMessage(msg);
1064 uiHandler.sendMessage(Message.obtain(
null, UIHandler.SHOW_DIALOG, dlgVerifyCertificate));
1069 synchronized (dlgVerifyCertificate)
1071 dlgVerifyCertificate.wait();
1074 catch (InterruptedException e)
1078 return callbackDialogResult ? 1 : 0;
1081 @Override
public void OnRemoteClipboardChanged(String data)
1083 Log.v(TAG,
"OnRemoteClipboardChanged: " + data);
1084 mClipboardManager.setClipboardData(data);
1089 private void resetZoomControlsAutoHideTimeout()
1091 uiHandler.removeMessages(UIHandler.HIDE_ZOOMCONTROLS);
1092 uiHandler.sendEmptyMessageDelayed(UIHandler.HIDE_ZOOMCONTROLS,
1093 ZOOMCONTROLS_AUTOHIDE_TIMEOUT);
1096 @Override
public void onScrollChanged(ScrollView2D scrollView,
int x,
int y,
int oldx,
int oldy)
1098 zoomControls.setIsZoomInEnabled(!sessionView.isAtMaxZoom());
1099 zoomControls.setIsZoomOutEnabled(!sessionView.isAtMinZoom());
1101 if (sysKeyboardVisible || extKeyboardVisible)
1104 if (!ApplicationSettingsActivity.getHideZoomControls(
this))
1106 uiHandler.sendEmptyMessage(UIHandler.SHOW_ZOOMCONTROLS);
1107 resetZoomControlsAutoHideTimeout();
1113 @Override
public void onSessionViewBeginTouch()
1115 scrollView.setScrollEnabled(
false);
1118 @Override
public void onSessionViewEndTouch()
1120 scrollView.setScrollEnabled(
true);
1123 @Override
public void onSessionViewLeftTouch(
int x,
int y,
boolean down)
1126 cancelDelayedMoveEvent();
1128 LibFreeRDP.sendCursorEvent(session.getInstance(), x, y,
1129 toggleMouseButtons ? Mouse.getRightButtonEvent(
this, down)
1130 : Mouse.getLeftButtonEvent(
this, down));
1133 toggleMouseButtons =
false;
1136 public void onSessionViewRightTouch(
int x,
int y,
boolean down)
1139 toggleMouseButtons = !toggleMouseButtons;
1142 @Override
public void onSessionViewMove(
int x,
int y)
1144 sendDelayedMoveEvent(x, y);
1147 @Override
public void onSessionViewScroll(
boolean down)
1149 LibFreeRDP.sendCursorEvent(session.getInstance(), 0, 0, Mouse.getScrollEvent(
this, down));
1154 @Override
public void onTouchPointerClose()
1156 touchPointerView.setVisibility(View.INVISIBLE);
1157 sessionView.setTouchPointerPadding(0, 0);
1160 private Point mapScreenCoordToSessionCoord(
int x,
int y)
1162 int mappedX = (int)((
float)(x + scrollView.getScrollX()) / sessionView.getZoom());
1163 int mappedY = (int)((
float)(y + scrollView.getScrollY()) / sessionView.getZoom());
1164 if (mappedX > bitmap.getWidth())
1165 mappedX = bitmap.getWidth();
1166 if (mappedY > bitmap.getHeight())
1167 mappedY = bitmap.getHeight();
1168 return new Point(mappedX, mappedY);
1171 @Override
public void onTouchPointerLeftClick(
int x,
int y,
boolean down)
1173 Point p = mapScreenCoordToSessionCoord(x, y);
1174 LibFreeRDP.sendCursorEvent(session.getInstance(), p.x, p.y,
1175 Mouse.getLeftButtonEvent(
this, down));
1178 @Override
public void onTouchPointerRightClick(
int x,
int y,
boolean down)
1180 Point p = mapScreenCoordToSessionCoord(x, y);
1181 LibFreeRDP.sendCursorEvent(session.getInstance(), p.x, p.y,
1182 Mouse.getRightButtonEvent(
this, down));
1185 @Override
public void onTouchPointerMove(
int x,
int y)
1187 Point p = mapScreenCoordToSessionCoord(x, y);
1188 LibFreeRDP.sendCursorEvent(session.getInstance(), p.x, p.y, Mouse.getMoveEvent());
1190 if (ApplicationSettingsActivity.getAutoScrollTouchPointer(
this) &&
1191 !uiHandler.hasMessages(UIHandler.SCROLLING_REQUESTED))
1193 Log.v(TAG,
"Starting auto-scroll");
1194 uiHandler.sendEmptyMessageDelayed(UIHandler.SCROLLING_REQUESTED, SCROLLING_TIMEOUT);
1198 @Override
public void onTouchPointerScroll(
boolean down)
1200 LibFreeRDP.sendCursorEvent(session.getInstance(), 0, 0, Mouse.getScrollEvent(
this, down));
1203 @Override
public void onTouchPointerToggleKeyboard()
1205 showKeyboard(!sysKeyboardVisible,
false);
1208 @Override
public void onTouchPointerToggleExtKeyboard()
1210 showKeyboard(
false, !extKeyboardVisible);
1213 @Override
public void onTouchPointerResetScrollZoom()
1215 sessionView.setZoom(1.0f);
1216 scrollView.scrollTo(0, 0);
1219 @Override
public boolean onGenericMotionEvent(MotionEvent e)
1221 super.onGenericMotionEvent(e);
1222 switch (e.getAction())
1224 case MotionEvent.ACTION_SCROLL:
1225 final float vScroll = e.getAxisValue(MotionEvent.AXIS_VSCROLL);
1228 LibFreeRDP.sendCursorEvent(session.getInstance(), 0, 0,
1229 Mouse.getScrollEvent(
this,
false));
1233 LibFreeRDP.sendCursorEvent(session.getInstance(), 0, 0,
1234 Mouse.getScrollEvent(
this,
true));
1243 @Override
public void onClipboardChanged(String data)
1245 Log.v(TAG,
"onClipboardChanged: " + data);
1246 LibFreeRDP.sendClipboardData(session.getInstance(), data);
1249 private class UIHandler
extends Handler
1252 public static final int REFRESH_SESSIONVIEW = 1;
1253 public static final int DISPLAY_TOAST = 2;
1254 public static final int HIDE_ZOOMCONTROLS = 3;
1255 public static final int SEND_MOVE_EVENT = 4;
1256 public static final int SHOW_DIALOG = 5;
1257 public static final int GRAPHICS_CHANGED = 6;
1258 public static final int SCROLLING_REQUESTED = 7;
1259 public static final int SHOW_ZOOMCONTROLS = 8;
1266 @Override
public void handleMessage(Message msg)
1270 case GRAPHICS_CHANGED:
1272 sessionView.onSurfaceChange(session);
1273 scrollView.requestLayout();
1276 case REFRESH_SESSIONVIEW:
1278 sessionView.invalidateRegion();
1283 Toast errorToast = Toast.makeText(getApplicationContext(), msg.obj.toString(),
1288 case HIDE_ZOOMCONTROLS:
1290 if (zoomControls.isShown())
1291 zoomControls.hide();
1294 case SHOW_ZOOMCONTROLS:
1296 if (!zoomControls.isShown())
1297 zoomControls.show();
1301 case SEND_MOVE_EVENT:
1303 LibFreeRDP.sendCursorEvent(session.getInstance(), msg.arg1, msg.arg2,
1304 Mouse.getMoveEvent());
1310 ((Dialog)msg.obj).show();
1313 case SCROLLING_REQUESTED:
1317 float[] pointerPos = touchPointerView.getPointerPosition();
1319 if (pointerPos[0] > (screen_width - touchPointerView.getPointerWidth()))
1320 scrollX = SCROLLING_DISTANCE;
1321 else if (pointerPos[0] < 0)
1322 scrollX = -SCROLLING_DISTANCE;
1324 if (pointerPos[1] > (screen_height - touchPointerView.getPointerHeight()))
1325 scrollY = SCROLLING_DISTANCE;
1326 else if (pointerPos[1] < 0)
1327 scrollY = -SCROLLING_DISTANCE;
1329 scrollView.scrollBy(scrollX, scrollY);
1332 if (scrollView.getScrollX() == 0 ||
1333 scrollView.getScrollX() == (sessionView.getWidth() - scrollView.getWidth()))
1335 if (scrollView.getScrollY() == 0 ||
1336 scrollView.getScrollY() ==
1337 (sessionView.getHeight() - scrollView.getHeight()))
1340 if (scrollX != 0 || scrollY != 0)
1341 uiHandler.sendEmptyMessageDelayed(SCROLLING_REQUESTED, SCROLLING_TIMEOUT);
1343 Log.v(TAG,
"Stopping auto-scroll");
1350 private class PinchZoomListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener
1352 private float scaleFactor = 1.0f;
1354 @Override
public boolean onScaleBegin(ScaleGestureDetector detector)
1356 scrollView.setScrollEnabled(
false);
1360 @Override
public boolean onScale(ScaleGestureDetector detector)
1364 scaleFactor *= detector.getScaleFactor();
1365 scaleFactor = Math.max(SessionView.MIN_SCALE_FACTOR,
1366 Math.min(scaleFactor, SessionView.MAX_SCALE_FACTOR));
1367 sessionView.setZoom(scaleFactor);
1369 if (!sessionView.isAtMinZoom() && !sessionView.isAtMaxZoom())
1372 float transOriginX = scrollView.getScrollX() * detector.getScaleFactor();
1373 float transOriginY = scrollView.getScrollY() * detector.getScaleFactor();
1376 float transCenterX =
1377 (scrollView.getScrollX() + detector.getFocusX()) * detector.getScaleFactor();
1378 float transCenterY =
1379 (scrollView.getScrollY() + detector.getFocusY()) * detector.getScaleFactor();
1384 scrollView.scrollBy((
int)((transCenterX - transOriginX) - detector.getFocusX()),
1385 (
int)((transCenterY - transOriginY) - detector.getFocusY()));
1391 @Override
public void onScaleEnd(ScaleGestureDetector de)
1393 scrollView.setScrollEnabled(
true);
1397 private class LibFreeRDPBroadcastReceiver
extends BroadcastReceiver
1399 @Override
public void onReceive(Context context, Intent intent)
1402 if (session ==
null)
1406 if (session.getInstance() != intent.getExtras().getLong(GlobalApp.EVENT_PARAM, -1))
1409 switch (intent.getExtras().getInt(GlobalApp.EVENT_TYPE, -1))
1411 case GlobalApp.FREERDP_EVENT_CONNECTION_SUCCESS:
1412 OnConnectionSuccess(context);
1415 case GlobalApp.FREERDP_EVENT_CONNECTION_FAILURE:
1416 OnConnectionFailure(context);
1418 case GlobalApp.FREERDP_EVENT_DISCONNECTED:
1419 OnDisconnected(context);
1424 private void OnConnectionSuccess(Context context)
1426 Log.v(TAG,
"OnConnectionSuccess");
1431 if (progressDialog !=
null)
1433 progressDialog.dismiss();
1434 progressDialog =
null;
1437 if (session.getBookmark() ==
null)
1444 Bundle bundle = getIntent().getExtras();
1445 if (bundle !=
null && bundle.containsKey(PARAM_CONNECTION_REFERENCE))
1447 if (ConnectionReference.isHostnameReference(
1448 bundle.getString(PARAM_CONNECTION_REFERENCE)))
1450 assert session.getBookmark().getType() == BookmarkBase.TYPE_MANUAL;
1451 String item = session.getBookmark().<ManualBookmark>
get().getHostname();
1452 if (!GlobalApp.getQuickConnectHistoryGateway().historyItemExists(item))
1453 GlobalApp.getQuickConnectHistoryGateway().addHistoryItem(item);
1458 private void OnConnectionFailure(Context context)
1460 Log.v(TAG,
"OnConnectionFailure");
1463 uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
1465 if (progressDialog !=
null)
1467 progressDialog.dismiss();
1468 progressDialog =
null;
1472 if (!connectCancelledByUser)
1473 uiHandler.sendMessage(
1474 Message.obtain(
null, UIHandler.DISPLAY_TOAST,
1475 getResources().getText(R.string.error_connection_failure)));
1477 closeSessionActivity(RESULT_CANCELED);
1480 private void OnDisconnected(Context context)
1482 Log.v(TAG,
"OnDisconnected");
1485 uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
1487 if (progressDialog !=
null)
1489 progressDialog.dismiss();
1490 progressDialog =
null;
1493 session.setUIEventListener(
null);
1494 closeSessionActivity(RESULT_OK);