diff options
Diffstat (limited to 'app/src/main/java/org/connectbot/ConsoleActivity.java')
-rw-r--r-- | app/src/main/java/org/connectbot/ConsoleActivity.java | 306 |
1 files changed, 261 insertions, 45 deletions
diff --git a/app/src/main/java/org/connectbot/ConsoleActivity.java b/app/src/main/java/org/connectbot/ConsoleActivity.java index 72fd2fd..4051a45 100644 --- a/app/src/main/java/org/connectbot/ConsoleActivity.java +++ b/app/src/main/java/org/connectbot/ConsoleActivity.java @@ -85,6 +85,7 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; +import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; @@ -100,7 +101,10 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne private static final int CLICK_TIME = 400; private static final float MAX_CLICK_DISTANCE = 25f; - private static final int KEYBOARD_DISPLAY_TIME = 1500; + private static final int KEYBOARD_DISPLAY_TIME = 3000; + private static final int KEYBOARD_REPEAT_INITIAL = 500; + private static final int KEYBOARD_REPEAT = 100; + private static final String STATE_SELECTED_URI = "selectedUri"; protected ViewPager pager = null; protected TabLayout tabs = null; @@ -217,38 +221,143 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne } }; + protected Handler keyRepeatHandler = new Handler(); + + + /** + * Handle repeatable virtual keys and touch events + */ + public class KeyRepeater implements Runnable, OnTouchListener { + private View mView; + private Handler mHandler; + private boolean mDown; + + public KeyRepeater(Handler handler, View view) { + mView = view; + mHandler = handler; + mView.setOnTouchListener(this); + mDown = false; + } + + @Override + public void run() { + mDown = true; + mHandler.removeCallbacks(this); + mHandler.postDelayed(this, KEYBOARD_REPEAT); + onEmulatedKeyClicked(mView); + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (BuildConfig.DEBUG) { + Log.d(TAG, "KeyRepeater.onTouch(" + v.getId() + ", " + + event.getAction() + ", " + + event.getActionIndex() + ", " + + event.getActionMasked() + ");"); + } + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mDown = false; + mHandler.postDelayed(this, KEYBOARD_REPEAT_INITIAL); + return (true); + + case MotionEvent.ACTION_CANCEL: + mHandler.removeCallbacks(this); + return (true); + + case MotionEvent.ACTION_UP: + mHandler.removeCallbacks(this); + if (!mDown) { + onEmulatedKeyClicked(mView); + } + return (true); + } + return false; + } + } + private void onEmulatedKeyClicked(View v) { TerminalView terminal = adapter.getCurrentTerminalView(); if (terminal == null) return; TerminalKeyListener handler = terminal.bridge.getKeyHandler(); - boolean hideKeys = true; + boolean hideKeys = false; - switch (v.getId()) { + switch (v.getId()) { case R.id.button_ctrl: handler.metaPress(TerminalKeyListener.OUR_CTRL_ON, true); + hideKeys = true; break; case R.id.button_esc: handler.sendEscape(); + hideKeys = true; break; case R.id.button_tab: handler.sendTab(); + hideKeys = true; break; + case R.id.button_up: handler.sendPressedKey(vt320.KEY_UP); - hideKeys = false; break; case R.id.button_down: handler.sendPressedKey(vt320.KEY_DOWN); - hideKeys = false; break; case R.id.button_left: handler.sendPressedKey(vt320.KEY_LEFT); - hideKeys = false; break; case R.id.button_right: handler.sendPressedKey(vt320.KEY_RIGHT); - hideKeys = false; + break; + + case R.id.button_home: + handler.sendPressedKey(vt320.KEY_HOME); + break; + case R.id.button_end: + handler.sendPressedKey(vt320.KEY_END); + break; + case R.id.button_pgup: + handler.sendPressedKey(vt320.KEY_PAGE_UP); + break; + case R.id.button_pgdn: + handler.sendPressedKey(vt320.KEY_PAGE_DOWN); + break; + + case R.id.button_f1: + handler.sendPressedKey(vt320.KEY_F1); + break; + case R.id.button_f2: + handler.sendPressedKey(vt320.KEY_F2); + break; + case R.id.button_f3: + handler.sendPressedKey(vt320.KEY_F3); + break; + case R.id.button_f4: + handler.sendPressedKey(vt320.KEY_F4); + break; + case R.id.button_f5: + handler.sendPressedKey(vt320.KEY_F5); + break; + case R.id.button_f6: + handler.sendPressedKey(vt320.KEY_F6); + break; + case R.id.button_f7: + handler.sendPressedKey(vt320.KEY_F7); + break; + case R.id.button_f8: + handler.sendPressedKey(vt320.KEY_F8); + break; + case R.id.button_f9: + handler.sendPressedKey(vt320.KEY_F9); + break; + case R.id.button_f10: + handler.sendPressedKey(vt320.KEY_F10); + break; + case R.id.button_f11: + handler.sendPressedKey(vt320.KEY_F11); + break; + case R.id.button_f12: + handler.sendPressedKey(vt320.KEY_F12); break; } @@ -258,6 +367,9 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne autoHideEmulatedKeys(); terminal.bridge.tryKeyVibrate(); + if (titleBarHide) { + actionBar.hide(); + } } /** @@ -292,10 +404,12 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne booleanPromptGroup.setVisibility(View.GONE); } - private void showEmulatedKeys() { + private void showEmulatedKeys(boolean showActionBar) { keyboardGroup.startAnimation(keyboard_fade_in); keyboardGroup.setVisibility(View.VISIBLE); - actionBar.show(); + if (showActionBar) { + actionBar.show(); + } autoHideEmulatedKeys(); } @@ -358,7 +472,11 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne setVolumeControlStream(AudioManager.STREAM_MUSIC); // handle requested console from incoming intent - requested = getIntent().getData(); + if (icicle == null) { + requested = getIntent().getData(); + } else { + requested = Uri.parse(icicle.getString(STATE_SELECTED_URI)); + } inflater = LayoutInflater.from(this); @@ -448,10 +566,29 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne findViewById(R.id.button_ctrl).setOnClickListener(emulatedKeysListener); findViewById(R.id.button_esc).setOnClickListener(emulatedKeysListener); findViewById(R.id.button_tab).setOnClickListener(emulatedKeysListener); - findViewById(R.id.button_up).setOnClickListener(emulatedKeysListener); - findViewById(R.id.button_down).setOnClickListener(emulatedKeysListener); - findViewById(R.id.button_left).setOnClickListener(emulatedKeysListener); - findViewById(R.id.button_right).setOnClickListener(emulatedKeysListener); + + new KeyRepeater(keyRepeatHandler, findViewById(R.id.button_up)); + new KeyRepeater(keyRepeatHandler, findViewById(R.id.button_down)); + new KeyRepeater(keyRepeatHandler, findViewById(R.id.button_left)); + new KeyRepeater(keyRepeatHandler, findViewById(R.id.button_right)); + + findViewById(R.id.button_home).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_end).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_pgup).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_pgdn).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f1).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f2).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f3).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f4).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f5).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f6).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f7).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f8).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f9).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f10).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f11).setOnClickListener(emulatedKeysListener); + findViewById(R.id.button_f12).setOnClickListener(emulatedKeysListener); + actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); @@ -467,9 +604,50 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne } }); + final HorizontalScrollView keyboardScroll = (HorizontalScrollView) findViewById(R.id.keyboard_hscroll); + if (!hardKeyboard) { + // Show virtual keyboard and scroll back and forth + showEmulatedKeys(false); + keyboardScroll.postDelayed(new Runnable() { + @Override + public void run() { + final int xscroll = findViewById(R.id.button_f12).getRight(); + if (BuildConfig.DEBUG) { + Log.d(TAG, "smoothScrollBy(toEnd[" + xscroll + "])"); + } + keyboardScroll.smoothScrollBy(xscroll, 0); + keyboardScroll.postDelayed(new Runnable() { + @Override + public void run() { + if (BuildConfig.DEBUG) { + Log.d(TAG, "smoothScrollBy(toStart[" + (-xscroll) + "])"); + } + keyboardScroll.smoothScrollBy(-xscroll, 0); + } + }, 500); + } + }, 500); + } + + // Reset keyboard auto-hide timer when scrolling + keyboardScroll.setOnTouchListener( + new OnTouchListener() { + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE: + autoHideEmulatedKeys(); + break; + case MotionEvent.ACTION_UP: + v.performClick(); + return (true); + } + return (false); + } + }); + tabs = (TabLayout) findViewById(R.id.tabs); if (tabs != null) - tabs.setupWithViewPager(pager); + setupTabLayoutWithViewPager(); // detect fling gestures to switch between terminals final GestureDetector detect = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { @@ -634,7 +812,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne && event.getEventTime() - event.getDownTime() < CLICK_TIME && Math.abs(event.getX() - lastX) < MAX_CLICK_DISTANCE && Math.abs(event.getY() - lastY) < MAX_CLICK_DISTANCE) { - showEmulatedKeys(); + showEmulatedKeys(true); } // pass any touch events back to detector @@ -645,6 +823,32 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne } /** + * Ties the {@link TabLayout} to the {@link ViewPager}. + * + * <p>This method will: + * <ul> + * <li>Add a {@link ViewPager.OnPageChangeListener} that will forward events to + * this TabLayout.</li> + * <li>Populate the TabLayout's tabs from the ViewPager's {@link PagerAdapter}.</li> + * <li>Set our {@link TabLayout.OnTabSelectedListener} which will forward + * selected events to the ViewPager</li> + * </ul> + * </p> + */ + public void setupTabLayoutWithViewPager() { + tabs.setTabsFromPagerAdapter(adapter); + pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabs)); + tabs.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager)); + + if (adapter.getCount() > 0) { + final int curItem = pager.getCurrentItem(); + if (tabs.getSelectedTabPosition() != curItem) { + tabs.getTabAt(curItem).select(); + } + } + } + + /** * */ private void configureOrientation() { @@ -790,26 +994,26 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne final View resizeView = inflater.inflate(R.layout.dia_resize, null, false); new AlertDialog.Builder(ConsoleActivity.this) - .setView(resizeView) - .setPositiveButton(R.string.button_resize, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - int width, height; - try { - width = Integer.parseInt(((EditText) resizeView - .findViewById(R.id.width)) - .getText().toString()); - height = Integer.parseInt(((EditText) resizeView - .findViewById(R.id.height)) - .getText().toString()); - } catch (NumberFormatException nfe) { - // TODO change this to a real dialog where we can - // make the input boxes turn red to indicate an error. - return; + .setView(resizeView) + .setPositiveButton(R.string.button_resize, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + int width, height; + try { + width = Integer.parseInt(((EditText) resizeView + .findViewById(R.id.width)) + .getText().toString()); + height = Integer.parseInt(((EditText) resizeView + .findViewById(R.id.height)) + .getText().toString()); + } catch (NumberFormatException nfe) { + // TODO change this to a real dialog where we can + // make the input boxes turn red to indicate an error. + return; + } + + terminalView.forceSize(width, height); } - - terminalView.forceSize(width, height); - } - }).setNegativeButton(android.R.string.cancel, null).create().show(); + }).setNegativeButton(android.R.string.cancel, null).create().show(); return true; } @@ -854,13 +1058,13 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case android.R.id.home: - Intent intent = new Intent(this, HostListActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - return true; - default: - return super.onOptionsItemSelected(item); + case android.R.id.home: + Intent intent = new Intent(this, HostListActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + return true; + default: + return super.onOptionsItemSelected(item); } } @@ -994,6 +1198,18 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne unbindService(connection); } + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + // Maintain selected host if connected. + if (adapter.getCurrentTerminalView() != null + && !adapter.getCurrentTerminalView().bridge.isDisconnected()) { + Uri uri = adapter.getCurrentTerminalView().bridge.host.getUri(); + savedInstanceState.putString(STATE_SELECTED_URI, uri.toString()); + } + + super.onSaveInstanceState(savedInstanceState); + } + private void startCopyMode() { // mark as copying and reset any previous bounds TerminalView terminalView = (TerminalView) adapter.getCurrentTerminalView(); @@ -1179,7 +1395,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne // and add our terminal view control, using index to place behind overlay final TerminalView terminal = new TerminalView(container.getContext(), bridge); - terminal.setId(R.id.console_flip); + terminal.setId(R.id.terminal_view); view.addView(terminal, 0); // Tag the view with its bridge so it can be retrieved later. @@ -1204,7 +1420,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne } View view = (View) object; - TerminalView terminal = (TerminalView) view.findViewById(R.id.console_flip); + TerminalView terminal = (TerminalView) view.findViewById(R.id.terminal_view); HostBean host = terminal.bridge.host; int itemIndex = POSITION_NONE; @@ -1257,7 +1473,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne public TerminalView getCurrentTerminalView() { View currentView = pager.findViewWithTag(getBridgeAtPosition(pager.getCurrentItem())); if (currentView == null) return null; - return (TerminalView) currentView.findViewById(R.id.console_flip); + return (TerminalView) currentView.findViewById(R.id.terminal_view); } } } |