Java tutorial
/* Android Session Activity Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.freerdp.freerdpcore.presentation; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.ScaleGestureDetector; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.Toast; import android.widget.ZoomControls; import com.freerdp.freerdpcore.domain.BookmarkBase; import com.freerdp.freerdpcore.domain.ConnectionReference; import com.freerdp.freerdpcore.domain.JzManualBoolmark; import com.freerdp.freerdpcore.domain.ManualBookmark; import com.freerdp.freerdpcore.services.LibFreeRDP; import com.freerdp.freerdpcore.utils.ClipboardManagerProxy; import com.freerdp.freerdpcore.utils.KeyboardMapper; import com.freerdp.freerdpcore.utils.Mouse; import com.jz.vdistack.R; import com.jz.vdistack.application.GlobalApp; import com.jz.vdistack.application.GlobalSettings; import com.jz.vdistack.application.SessionState; import com.jz.vdistack.network.WcNetWorkUtils; public class SessionActivity extends BaseActivity implements LibFreeRDP.UIEventListener, KeyboardView.OnKeyboardActionListener, ScrollView2D.ScrollView2DListener, KeyboardMapper.KeyProcessingListener, SessionView.SessionViewListener, TouchPointerView.TouchPointerListener, ClipboardManagerProxy.OnClipboardChangedListener, Runnable { private class UIHandler extends Handler { public static final int REFRESH_SESSIONVIEW = 1; public static final int DISPLAY_TOAST = 2; public static final int HIDE_ZOOMCONTROLS = 3; public static final int SEND_MOVE_EVENT = 4; public static final int SHOW_DIALOG = 5; public static final int GRAPHICS_CHANGED = 6; public static final int SCROLLING_REQUESTED = 7; UIHandler() { super(); } @Override public void handleMessage(Message msg) { switch (msg.what) { case GRAPHICS_CHANGED: { sessionView.onSurfaceChange(session); scrollView.requestLayout(); break; } case REFRESH_SESSIONVIEW: { sessionView.invalidateRegion(); break; } case DISPLAY_TOAST: { Toast errorToast = Toast.makeText(getApplicationContext(), msg.obj.toString(), Toast.LENGTH_LONG); errorToast.show(); break; } case HIDE_ZOOMCONTROLS: { zoomControls.hide(); break; } case SEND_MOVE_EVENT: { LibFreeRDP.sendCursorEvent(session.getInstance(), msg.arg1, msg.arg2, Mouse.getMoveEvent()); break; } case SHOW_DIALOG: { // create and show the dialog ((Dialog) msg.obj).show(); break; } case SCROLLING_REQUESTED: { int scrollX = 0; int scrollY = 0; float[] pointerPos = touchPointerView.getPointerPosition(); if (pointerPos[0] > (screen_width - touchPointerView.getPointerWidth())) scrollX = SCROLLING_DISTANCE; else if (pointerPos[0] < 0) scrollX = -SCROLLING_DISTANCE; if (pointerPos[1] > (screen_height - touchPointerView.getPointerHeight())) scrollY = SCROLLING_DISTANCE; else if (pointerPos[1] < 0) scrollY = -SCROLLING_DISTANCE; scrollView.scrollBy(scrollX, scrollY); // see if we reached the min/max scroll positions if (scrollView.getScrollX() == 0 || scrollView.getScrollX() == (sessionView.getWidth() - scrollView.getWidth())) scrollX = 0; if (scrollView.getScrollY() == 0 || scrollView.getScrollY() == (sessionView.getHeight() - scrollView.getHeight())) scrollY = 0; if (scrollX != 0 || scrollY != 0) uiHandler.sendEmptyMessageDelayed(SCROLLING_REQUESTED, SCROLLING_TIMEOUT); else Log.v(TAG, "Stopping auto-scroll"); break; } } } } private class PinchZoomListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { private float scaleFactor = 1.0f; @Override public boolean onScaleBegin(ScaleGestureDetector detector) { scrollView.setScrollEnabled(false); return true; } @Override public boolean onScale(ScaleGestureDetector detector) { // calc scale factor scaleFactor *= detector.getScaleFactor(); scaleFactor = Math.max(SessionView.MIN_SCALE_FACTOR, Math.min(scaleFactor, SessionView.MAX_SCALE_FACTOR)); sessionView.setZoom(scaleFactor); if (!sessionView.isAtMinZoom() && !sessionView.isAtMaxZoom()) { // transform scroll origin to the new zoom space float transOriginX = scrollView.getScrollX() * detector.getScaleFactor(); float transOriginY = scrollView.getScrollY() * detector.getScaleFactor(); // transform center point to the zoomed space float transCenterX = (scrollView.getScrollX() + detector.getFocusX()) * detector.getScaleFactor(); float transCenterY = (scrollView.getScrollY() + detector.getFocusY()) * detector.getScaleFactor(); // scroll by the difference between the distance of the transformed center/origin point and their old distance (focusX/Y) scrollView.scrollBy((int) ((transCenterX - transOriginX) - detector.getFocusX()), (int) ((transCenterY - transOriginY) - detector.getFocusY())); } return true; } @Override public void onScaleEnd(ScaleGestureDetector de) { scrollView.setScrollEnabled(true); } } private class LibFreeRDPBroadcastReceiver extends BroadcastReceiver { private boolean is = false; @Override public void onReceive(Context context, Intent intent) { // still got a valid session? if (session == null) return; // is this event for the current session? if (session.getInstance() != intent.getExtras().getInt(GlobalApp.EVENT_PARAM, -1)) return; switch (intent.getExtras().getInt(GlobalApp.EVENT_TYPE, -1)) { case GlobalApp.FREERDP_EVENT_CONNECTION_SUCCESS: OnConnectionSuccess(context); break; case GlobalApp.FREERDP_EVENT_CONNECTION_FAILURE: OnConnectionFailure(context); break; case GlobalApp.FREERDP_EVENT_DISCONNECTED: OnDisconnected(context); break; } } private void OnConnectionSuccess(final Context context) { bindSession(); rladvertising.setVisibility(View.GONE); //JzVDIHomeActivity.jzVDIHomeActivity.finish(); Bundle bundle = getIntent().getExtras(); if (bundle != null && bundle.containsKey(PARAM_CONNECTION_REFERENCE)) { if (ConnectionReference.isHostnameReference(bundle.getString(PARAM_CONNECTION_REFERENCE))) { assert session.getBookmark().getType() == BookmarkBase.TYPE_MANUAL; String item = session.getBookmark().<ManualBookmark>get().getHostname(); if (!GlobalApp.getQuickConnectHistoryGateway().historyItemExists(item)) GlobalApp.getQuickConnectHistoryGateway().addHistoryItem(item); } } } private void OnConnectionFailure(Context context) { uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT); if (!connectCancelledByUser) uiHandler.sendMessage(Message.obtain(null, UIHandler.DISPLAY_TOAST, getResources().getText(R.string.error_connection_failure))); closeSessionActivity(RESULT_CANCELED); } private void OnDisconnected(final Context context) { if (!is) { new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub List<NameValuePair> l = new ArrayList<NameValuePair>(); l.add(new BasicNameValuePair("mac", WcNetWorkUtils.getMacInfo(context))); l.add(new BasicNameValuePair("type", "0")); String s = WcNetWorkUtils.getResultPost("http://180.153.152.42:3000/connection", l); } }).start(); is = true; } uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT); session.setUIEventListener(null); closeSessionActivity(RESULT_OK); } } public static final String PARAM_CONNECTION_REFERENCE = "conRef"; public static final String PARAM_INSTANCE = "instance"; private static final float ZOOMING_STEP = 0.5f; private static final int ZOOMCONTROLS_AUTOHIDE_TIMEOUT = 4000; // timeout between subsequent scrolling requests when the touch-pointer is at the edge of the session view private static final int SCROLLING_TIMEOUT = 50; private static final int SCROLLING_DISTANCE = 20; private Bitmap bitmap; private SessionState session; private SessionView sessionView; private TouchPointerView touchPointerView; //private ProgressDialog progressDialog; private KeyboardView keyboardView; private KeyboardView modifiersKeyboardView; private ZoomControls zoomControls; private KeyboardMapper keyboardMapper; private Keyboard specialkeysKeyboard; private Keyboard numpadKeyboard; private Keyboard cursorKeyboard; private Keyboard modifiersKeyboard; private AlertDialog dlgVerifyCertificate; private AlertDialog dlgUserCredentials; private View userCredView; private UIHandler uiHandler; private int screen_width; private int screen_height; private boolean autoScrollTouchPointer = GlobalSettings.getAutoScrollTouchPointer(); private boolean connectCancelledByUser = false; private boolean sessionRunning = false; private boolean toggleMouseButtons = false; private LibFreeRDPBroadcastReceiver libFreeRDPBroadcastReceiver; private static final String TAG = "FreeRDP.SessionActivity"; private ScrollView2D scrollView; // keyboard visibility flags private boolean sysKeyboardVisible = false; private boolean extKeyboardVisible = false; // variables for delayed move event sending private static final int MAX_DISCARDED_MOVE_EVENTS = 3; private static final int SEND_MOVE_EVENT_TIMEOUT = 150; private int discardedMoveEvents = 0; public static int x = 0; public static int y = 0; private ClipboardManagerProxy mClipboardManager; private AdvertisingView rladvertising; private Thread thread; private static final String URLHTTP = "180.153.152.42:3000/"; private void createDialogs() { // build verify certificate dialog dlgVerifyCertificate = new AlertDialog.Builder(this).setTitle(R.string.dlg_title_verify_certificate) .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { callbackDialogResult = true; synchronized (dialog) { dialog.notify(); } } }).setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { callbackDialogResult = false; connectCancelledByUser = true; synchronized (dialog) { dialog.notify(); } } }).setCancelable(false).create(); // build the dialog userCredView = getLayoutInflater().inflate(R.layout.credentials, null, true); dlgUserCredentials = new AlertDialog.Builder(this).setView(userCredView) .setTitle(R.string.dlg_title_credentials) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { callbackDialogResult = true; synchronized (dialog) { dialog.notify(); } } }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { callbackDialogResult = false; connectCancelledByUser = true; synchronized (dialog) { dialog.notify(); } } }).setCancelable(false).create(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // show status bar or make fullscreen? if (GlobalSettings.getHideStatusBar()) getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.setContentView(R.layout.session); rladvertising = (AdvertisingView) findViewById(R.id.advertising); rladvertising.startImagePlay(); final View activityRootView = findViewById(R.id.session_root_view); // activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { screen_width = activityRootView.getWidth(); screen_height = activityRootView.getHeight(); if (!sessionRunning && getIntent() != null) { thread = new Thread(SessionActivity.this); thread.start(); sessionRunning = true; } } }); sessionView = (SessionView) findViewById(R.id.sessionView); sessionView.setScaleGestureDetector(new ScaleGestureDetector(this, new PinchZoomListener())); sessionView.setSessionViewListener(this); sessionView.requestFocus(); touchPointerView = (TouchPointerView) findViewById(R.id.touchPointerView); touchPointerView.setTouchPointerListener(this); keyboardMapper = new KeyboardMapper(); keyboardMapper.init(this); keyboardMapper.reset(this); modifiersKeyboard = new Keyboard(getApplicationContext(), R.xml.modifiers_keyboard); specialkeysKeyboard = new Keyboard(getApplicationContext(), R.xml.specialkeys_keyboard); numpadKeyboard = new Keyboard(getApplicationContext(), R.xml.numpad_keyboard); cursorKeyboard = new Keyboard(getApplicationContext(), R.xml.cursor_keyboard); // hide keyboard below the sessionView keyboardView = (KeyboardView) findViewById(R.id.extended_keyboard); keyboardView.setKeyboard(specialkeysKeyboard); keyboardView.setOnKeyboardActionListener(this); modifiersKeyboardView = (KeyboardView) findViewById(R.id.extended_keyboard_header); modifiersKeyboardView.setKeyboard(modifiersKeyboard); modifiersKeyboardView.setOnKeyboardActionListener(this); scrollView = (ScrollView2D) findViewById(R.id.sessionScrollView); scrollView.setScrollViewListener(this); uiHandler = new UIHandler(); libFreeRDPBroadcastReceiver = new LibFreeRDPBroadcastReceiver(); zoomControls = (ZoomControls) findViewById(R.id.zoomControls); zoomControls.hide(); zoomControls.setOnZoomInClickListener(new View.OnClickListener() { @Override public void onClick(View v) { resetZoomControlsAutoHideTimeout(); zoomControls.setIsZoomInEnabled(sessionView.zoomIn(ZOOMING_STEP)); zoomControls.setIsZoomOutEnabled(true); } }); zoomControls.setOnZoomOutClickListener(new View.OnClickListener() { @Override public void onClick(View v) { resetZoomControlsAutoHideTimeout(); zoomControls.setIsZoomOutEnabled(sessionView.zoomOut(ZOOMING_STEP)); zoomControls.setIsZoomInEnabled(true); } }); toggleMouseButtons = false; createDialogs(); // register freerdp events broadcast receiver IntentFilter filter = new IntentFilter(); filter.addAction(GlobalApp.ACTION_EVENT_FREERDP); registerReceiver(libFreeRDPBroadcastReceiver, filter); mClipboardManager = ClipboardManagerProxy.getClipboardManager(this); mClipboardManager.addClipboardChangedListener(this); } @Override protected void onStart() { super.onStart(); Log.v(TAG, "Session.onStart"); } @Override protected void onRestart() { super.onRestart(); Log.v(TAG, "Session.onRestart"); } @Override protected void onResume() { super.onResume(); Log.v(TAG, "Session.onResume"); } @Override protected void onPause() { super.onPause(); Log.v(TAG, "Session.onPause"); // hide any visible keyboards showKeyboard(false, false); } @Override protected void onStop() { super.onStop(); Log.v(TAG, "Session.onStop"); } @Override protected void onDestroy() { super.onDestroy(); Log.v(TAG, "Session.onDestroy"); // Cancel running disconnect timers. GlobalApp.cancelDisconnectTimer(); // Disconnect all remaining sessions. Collection<SessionState> sessions = GlobalApp.getSessions(); for (SessionState session : sessions) LibFreeRDP.disconnect(session.getInstance()); unregisterReceiver(libFreeRDPBroadcastReceiver); mClipboardManager.removeClipboardboardChangedListener(this); // free session try { GlobalApp.freeSession(session.getInstance()); } catch (Exception exception) { exception.printStackTrace(); } session = null; } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // reload keyboard resources (changed from landscape) modifiersKeyboard = new Keyboard(getApplicationContext(), R.xml.modifiers_keyboard); specialkeysKeyboard = new Keyboard(getApplicationContext(), R.xml.specialkeys_keyboard); numpadKeyboard = new Keyboard(getApplicationContext(), R.xml.numpad_keyboard); cursorKeyboard = new Keyboard(getApplicationContext(), R.xml.cursor_keyboard); keyboardView.setKeyboard(specialkeysKeyboard); modifiersKeyboardView.setKeyboard(modifiersKeyboard); } private void processIntent(Intent intent, String str) { JzManualBoolmark jzManualBoolmark; try { jzManualBoolmark = new JzManualBoolmark(str, this); connect(jzManualBoolmark.getManualBookmark()); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub List<NameValuePair> ll = new ArrayList<NameValuePair>(); ll.add(new BasicNameValuePair("mac", WcNetWorkUtils.getMacInfo(SessionActivity.this))); ll.add(new BasicNameValuePair("type", "1")); String s = WcNetWorkUtils.getResultPost("http://180.153.152.42:3000/connection", ll); } }).start(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); closeSessionActivity(RESULT_CANCELED); } } private void connect(BookmarkBase bookmark) { session = GlobalApp.createSession(bookmark); session.setUIEventListener(this); // set writeable data directory LibFreeRDP.setDataDirectory(session.getInstance(), getFilesDir().toString()); BookmarkBase.ScreenSettings screenSettings = session.getBookmark().getActiveScreenSettings(); Log.v(TAG, "Screen Resolution: " + screenSettings.getResolutionString()); if (screenSettings.isAutomatic()) { if ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE) { screenSettings.setHeight(screen_height); screenSettings.setWidth(screen_width); } else { // small screen device i.e. phone: // Automatic uses the largest side length of the screen and makes a 16:10 resolution setting out of it int screenMax = (screen_width > screen_height) ? screen_width : screen_height; // screenSettings.setHeight(screenMax); // screenSettings.setWidth((int)((float)screenMax * 1.6f)); screenSettings.setHeight(screen_height); screenSettings.setWidth(screen_width); } } if (screenSettings.isFitScreen()) { screenSettings.setHeight(screen_height); screenSettings.setWidth(screen_width); } session.connect(); } // binds the current session to the activity by wiring it up with the sessionView and updating all internal objects accordingly private void bindSession() { Log.v("SessionActivity", "bindSession called"); session.setUIEventListener(this); sessionView.onSurfaceChange(session); scrollView.requestLayout(); keyboardMapper.reset(this); } // displays either the system or the extended keyboard or non of them private void showKeyboard(boolean showSystemKeyboard, boolean showExtendedKeyboard) { // no matter what we are doing ... hide the zoom controls // TODO: this is not working correctly as hiding the keyboard issues a onScrollChange notification showing the control again ... uiHandler.removeMessages(UIHandler.HIDE_ZOOMCONTROLS); if (zoomControls.getVisibility() == View.VISIBLE) zoomControls.hide(); InputMethodManager mgr; if (showSystemKeyboard) { // hide extended keyboard keyboardView.setVisibility(View.GONE); // show system keyboard mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (!mgr.isActive(sessionView)) Log.e(TAG, "Failed to show system keyboard: SessionView is not the active view!"); mgr.showSoftInput(sessionView, 0); // show modifiers keyboard modifiersKeyboardView.setVisibility(View.VISIBLE); } else if (showExtendedKeyboard) { // hide system keyboard mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(sessionView.getWindowToken(), 0); // show extended keyboard keyboardView.setKeyboard(specialkeysKeyboard); keyboardView.setVisibility(View.VISIBLE); modifiersKeyboardView.setVisibility(View.VISIBLE); } else { // hide both mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(sessionView.getWindowToken(), 0); keyboardView.setVisibility(View.GONE); modifiersKeyboardView.setVisibility(View.GONE); // clear any active key modifiers) keyboardMapper.clearlAllModifiers(); } sysKeyboardVisible = showSystemKeyboard; extKeyboardVisible = showExtendedKeyboard; } private void closeSessionActivity(int resultCode) { // Go back to home activity (and send intent data back to home) setResult(resultCode, getIntent()); finish(); } // update the state of our modifier keys private void updateModifierKeyStates() { // check if any key is in the keycodes list List<Keyboard.Key> keys = modifiersKeyboard.getKeys(); for (Iterator<Keyboard.Key> it = keys.iterator(); it.hasNext();) { // if the key is a sticky key - just set it to off Keyboard.Key curKey = it.next(); if (curKey.sticky) { switch (keyboardMapper.getModifierState(curKey.codes[0])) { case KeyboardMapper.KEYSTATE_ON: curKey.on = true; curKey.pressed = false; break; case KeyboardMapper.KEYSTATE_OFF: curKey.on = false; curKey.pressed = false; break; case KeyboardMapper.KEYSTATE_LOCKED: curKey.on = true; curKey.pressed = true; break; } } } // refresh image modifiersKeyboardView.invalidateAllKeys(); } private void sendDelayedMoveEvent(int x, int y) { if (uiHandler.hasMessages(UIHandler.SEND_MOVE_EVENT)) { uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT); discardedMoveEvents++; } else discardedMoveEvents = 0; if (discardedMoveEvents > MAX_DISCARDED_MOVE_EVENTS) LibFreeRDP.sendCursorEvent(session.getInstance(), x, y, Mouse.getMoveEvent()); else uiHandler.sendMessageDelayed(Message.obtain(null, UIHandler.SEND_MOVE_EVENT, x, y), SEND_MOVE_EVENT_TIMEOUT); } private void cancelDelayedMoveEvent() { uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT); } @Override public boolean onCreateOptionsMenu(Menu menu) { if (rladvertising.getVisibility() == View.VISIBLE) { return false; } getMenuInflater().inflate(R.menu.session_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // refer to http://tools.android.com/tips/non-constant-fields why we can't use switch/case here .. int itemId = item.getItemId(); if (itemId == R.id.session_touch_pointer) { // toggle touch pointer if (touchPointerView.getVisibility() == View.VISIBLE) { touchPointerView.setVisibility(View.INVISIBLE); sessionView.setTouchPointerPadding(0, 0); } else { touchPointerView.setVisibility(View.VISIBLE); sessionView.setTouchPointerPadding(touchPointerView.getPointerWidth(), touchPointerView.getPointerHeight()); } } else if (itemId == R.id.session_sys_keyboard) { showKeyboard(!sysKeyboardVisible, false); } else if (itemId == R.id.session_ext_keyboard) { showKeyboard(false, !extKeyboardVisible); } else if (itemId == R.id.session_disconnect) { showKeyboard(false, false); LibFreeRDP.disconnect(session.getInstance()); } return true; } @Override public void onBackPressed() { // hide keyboards (if any visible) or send alt+f4 to the session if (sysKeyboardVisible || extKeyboardVisible) showKeyboard(false, false); else { keyboardMapper.sendAltF4(); } } // android keyboard input handling // We always use the unicode value to process input from the android keyboard except if key modifiers // (like Win, Alt, Ctrl) are activated. In this case we will send the virtual key code to allow key // combinations (like Win + E to open the explorer). @Override public boolean onKeyDown(int keycode, KeyEvent event) { if (keycode == KeyEvent.KEYCODE_BACK && rladvertising.getVisibility() == View.VISIBLE) { try { connectCancelledByUser = true; rladvertising.stopPlay(); rladvertising.getLock().notifyAll(); LibFreeRDP.cancelConnection(session.getInstance()); } catch (Exception e) { } finish(); return false; } if (event.getRepeatCount() == 0 && keycode == KeyEvent.KEYCODE_BACK) { event.startTracking(); return true; } return keyboardMapper.processAndroidKeyEvent(event); } @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { // TODO Auto-generated method stub keyboardMapper.sendAltF4(); return super.onKeyLongPress(keyCode, event); } @Override public boolean onKeyUp(int keycode, KeyEvent event) { return keyboardMapper.processAndroidKeyEvent(event); } // onKeyMultiple is called for input of some special characters like umlauts and some symbol characters @Override public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { return keyboardMapper.processAndroidKeyEvent(event); } // **************************************************************************** // KeyboardView.KeyboardActionEventListener @Override public void onKey(int primaryCode, int[] keyCodes) { Log.v("WC", "onKey" + primaryCode); keyboardMapper.processCustomKeyEvent(primaryCode); } @Override public void onText(CharSequence text) { } @Override public void swipeRight() { } @Override public void swipeLeft() { } @Override public void swipeDown() { } @Override public void swipeUp() { } @Override public void onPress(int primaryCode) { } @Override public void onRelease(int primaryCode) { } // **************************************************************************** // KeyboardMapper.KeyProcessingListener implementation @Override public void processVirtualKey(int virtualKeyCode, boolean down) { Log.v("WC", "processVirtualKey" + virtualKeyCode + down); LibFreeRDP.sendKeyEvent(session.getInstance(), virtualKeyCode, down); } @Override public void processUnicodeKey(int unicodeKey) { LibFreeRDP.sendUnicodeKeyEvent(session.getInstance(), unicodeKey); } @Override public void switchKeyboard(int keyboardType) { switch (keyboardType) { case KeyboardMapper.KEYBOARD_TYPE_FUNCTIONKEYS: keyboardView.setKeyboard(specialkeysKeyboard); break; case KeyboardMapper.KEYBOARD_TYPE_NUMPAD: keyboardView.setKeyboard(numpadKeyboard); break; case KeyboardMapper.KEYBOARD_TYPE_CURSOR: keyboardView.setKeyboard(cursorKeyboard); break; default: break; } } @Override public void modifiersChanged() { updateModifierKeyStates(); } // **************************************************************************** // LibFreeRDP UI event listener implementation @Override public void OnSettingsChanged(int width, int height, int bpp) { if (bpp > 16) bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); else bitmap = Bitmap.createBitmap(width, height, Config.RGB_565); session.setSurface(new BitmapDrawable(bitmap)); // check this settings and initial settings - if they are not equal the server doesn't support our settings // FIXME: the additional check (settings.getWidth() != width + 1) is for the RDVH bug fix to avoid accidental notifications // (refer to android_freerdp.c for more info on this problem) BookmarkBase.ScreenSettings settings = session.getBookmark().getActiveScreenSettings(); if ((settings.getWidth() != width && settings.getWidth() != width + 1) || settings.getHeight() != height || settings.getColors() != bpp) uiHandler.sendMessage(Message.obtain(null, UIHandler.DISPLAY_TOAST, getResources().getText(R.string.info_capabilities_changed))); } @Override public void OnGraphicsUpdate(int x, int y, int width, int height) { LibFreeRDP.updateGraphics(session.getInstance(), bitmap, x, y, width, height); sessionView.addInvalidRegion(new Rect(x, y, x + width, y + height)); /* since sessionView can only be modified from the UI thread * any modifications to it need to be scheduled */ uiHandler.sendEmptyMessage(UIHandler.REFRESH_SESSIONVIEW); } @Override public void OnGraphicsResize(int width, int height, int bpp) { // replace bitmap if (bpp > 16) bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); else bitmap = Bitmap.createBitmap(width, height, Config.RGB_565); session.setSurface(new BitmapDrawable(bitmap)); /* since sessionView can only be modified from the UI thread * any modifications to it need to be scheduled */ uiHandler.sendEmptyMessage(UIHandler.GRAPHICS_CHANGED); } private boolean callbackDialogResult; @Override public boolean OnAuthenticate(StringBuilder username, StringBuilder domain, StringBuilder password) { // this is where the return code of our dialog will be stored callbackDialogResult = false; // set text fields ((EditText) userCredView.findViewById(R.id.editTextUsername)).setText(username); ((EditText) userCredView.findViewById(R.id.editTextDomain)).setText(domain); ((EditText) userCredView.findViewById(R.id.editTextPassword)).setText(password); // start dialog in UI thread uiHandler.sendMessage(Message.obtain(null, UIHandler.SHOW_DIALOG, dlgUserCredentials)); // wait for result try { synchronized (dlgUserCredentials) { dlgUserCredentials.wait(); } } catch (InterruptedException e) { } // clear buffers username.setLength(0); domain.setLength(0); password.setLength(0); // read back user credentials username.append(((EditText) userCredView.findViewById(R.id.editTextUsername)).getText().toString()); domain.append(((EditText) userCredView.findViewById(R.id.editTextDomain)).getText().toString()); password.append(((EditText) userCredView.findViewById(R.id.editTextPassword)).getText().toString()); return callbackDialogResult; } @Override public boolean OnVerifiyCertificate(String subject, String issuer, String fingerprint) { // see if global settings says accept all if (GlobalSettings.getAcceptAllCertificates()) return true; // this is where the return code of our dialog will be stored callbackDialogResult = false; // set message String msg = getResources().getString(R.string.dlg_msg_verify_certificate); msg = msg + "\n\nSubject: " + subject + "\nIssuer: " + issuer + "\nFingerprint: " + fingerprint; dlgVerifyCertificate.setMessage(msg); // start dialog in UI thread uiHandler.sendMessage(Message.obtain(null, UIHandler.SHOW_DIALOG, dlgVerifyCertificate)); // wait for result try { synchronized (dlgVerifyCertificate) { dlgVerifyCertificate.wait(); } } catch (InterruptedException e) { } return callbackDialogResult; } @Override public void OnRemoteClipboardChanged(String data) { Log.v(TAG, "OnRemoteClipboardChanged: " + data); mClipboardManager.setClipboardData(data); } // **************************************************************************** // ScrollView2DListener implementation private void resetZoomControlsAutoHideTimeout() { uiHandler.removeMessages(UIHandler.HIDE_ZOOMCONTROLS); uiHandler.sendEmptyMessageDelayed(UIHandler.HIDE_ZOOMCONTROLS, ZOOMCONTROLS_AUTOHIDE_TIMEOUT); } @Override public void onScrollChanged(ScrollView2D scrollView, int x, int y, int oldx, int oldy) { zoomControls.setIsZoomInEnabled(!sessionView.isAtMaxZoom()); zoomControls.setIsZoomOutEnabled(!sessionView.isAtMinZoom()); if (!GlobalSettings.getHideZoomControls() && zoomControls.getVisibility() != View.VISIBLE) zoomControls.show(); resetZoomControlsAutoHideTimeout(); } // **************************************************************************** // SessionView.SessionViewListener @Override public void onSessionViewBeginTouch() { scrollView.setScrollEnabled(false); } @Override public void onSessionViewEndTouch() { scrollView.setScrollEnabled(true); } @Override public void onSessionViewLeftTouch(int x, int y, boolean down) { if (!down) cancelDelayedMoveEvent(); LibFreeRDP.sendCursorEvent(session.getInstance(), x, y, toggleMouseButtons ? Mouse.getRightButtonEvent(down) : Mouse.getLeftButtonEvent(down)); if (!down) toggleMouseButtons = false; } public void onSessionViewRightTouch(int x, int y, boolean down) { if (!down) toggleMouseButtons = !toggleMouseButtons; } @Override public void onSessionViewMove(int x, int y) { sendDelayedMoveEvent(x, y); } @Override public void onSessionViewScroll(boolean down) { LibFreeRDP.sendCursorEvent(session.getInstance(), 0, 0, Mouse.getScrollEvent(down)); } // **************************************************************************** // TouchPointerView.TouchPointerListener @Override public void onTouchPointerClose() { touchPointerView.setVisibility(View.INVISIBLE); sessionView.setTouchPointerPadding(0, 0); } private Point mapScreenCoordToSessionCoord(int x, int y) { int mappedX = (int) ((float) (x + scrollView.getScrollX()) / sessionView.getZoom()); int mappedY = (int) ((float) (y + scrollView.getScrollY()) / sessionView.getZoom()); if (mappedX > bitmap.getWidth()) mappedX = bitmap.getWidth(); if (mappedY > bitmap.getHeight()) mappedY = bitmap.getHeight(); return new Point(mappedX, mappedY); } @Override public void onTouchPointerLeftClick(int x, int y, boolean down) { Point p = mapScreenCoordToSessionCoord(x, y); LibFreeRDP.sendCursorEvent(session.getInstance(), p.x, p.y, Mouse.getLeftButtonEvent(down)); } @Override public void onTouchPointerRightClick(int x, int y, boolean down) { Point p = mapScreenCoordToSessionCoord(x, y); LibFreeRDP.sendCursorEvent(session.getInstance(), p.x, p.y, Mouse.getRightButtonEvent(down)); } @Override public void onTouchPointerMove(int x, int y) { Point p = mapScreenCoordToSessionCoord(x, y); LibFreeRDP.sendCursorEvent(session.getInstance(), p.x, p.y, Mouse.getMoveEvent()); if (autoScrollTouchPointer && !uiHandler.hasMessages(UIHandler.SCROLLING_REQUESTED)) { Log.v(TAG, "Starting auto-scroll"); uiHandler.sendEmptyMessageDelayed(UIHandler.SCROLLING_REQUESTED, SCROLLING_TIMEOUT); } } @Override public void onTouchPointerScroll(boolean down) { LibFreeRDP.sendCursorEvent(session.getInstance(), 0, 0, Mouse.getScrollEvent(down)); } @Override public void onTouchPointerToggleKeyboard() { showKeyboard(!sysKeyboardVisible, false); } @Override public void onTouchPointerToggleExtKeyboard() { showKeyboard(false, !extKeyboardVisible); } @Override public void onTouchPointerResetScrollZoom() { sessionView.setZoom(1.0f); scrollView.scrollTo(0, 0); } // **************************************************************************** // ClipboardManagerProxy.OnClipboardChangedListener @Override public void onClipboardChanged(String data) { Log.v(TAG, "onClipboardChanged: " + data); LibFreeRDP.sendClipboardData(session.getInstance(), data); } // @Override public void run() { // TODO Auto-generated method stub try { String str = WcNetWorkUtils.getHttpClientString("http://180.153.152.42:3000/desktop/?mac=" + WcNetWorkUtils.getMacInfo(getApplicationContext())); synchronized (rladvertising.getLock()) { if (rladvertising.isrun()) { processIntent(getIntent(), str); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }