From 381c4b65027c62fa87db6038fe6de5f4e46fe990 Mon Sep 17 00:00:00 2001 From: Ryan Hansberry Date: Fri, 9 Oct 2015 14:05:17 -0700 Subject: TerminalView: Move TextView logic that allows text selection into its own class, which allows scrolling selection. --- .../main/java/org/connectbot/ConsoleActivity.java | 21 +- app/src/main/java/org/connectbot/TerminalView.java | 332 ++----------------- .../connectbot/util/TerminalTextViewOverlay.java | 368 +++++++++++++++++++++ app/src/main/res/layout-v11/item_terminal.xml | 47 +++ app/src/main/res/layout/item_terminal.xml | 2 +- 5 files changed, 462 insertions(+), 308 deletions(-) create mode 100644 app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java create mode 100644 app/src/main/res/layout-v11/item_terminal.xml (limited to 'app/src') diff --git a/app/src/main/java/org/connectbot/ConsoleActivity.java b/app/src/main/java/org/connectbot/ConsoleActivity.java index abfbee4..10ae45a 100644 --- a/app/src/main/java/org/connectbot/ConsoleActivity.java +++ b/app/src/main/java/org/connectbot/ConsoleActivity.java @@ -28,6 +28,7 @@ import org.connectbot.service.TerminalBridge; import org.connectbot.service.TerminalKeyListener; import org.connectbot.service.TerminalManager; import org.connectbot.util.PreferenceConstants; +import org.connectbot.util.TerminalTextViewOverlay; import org.connectbot.util.TerminalViewPager; import android.app.AlertDialog; @@ -1148,9 +1149,9 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne * Called whenever the displayed terminal is changed. */ private void onTerminalChanged() { - View overlay = findCurrentView(R.id.terminal_overlay); - if (overlay != null) - overlay.startAnimation(fade_out_delayed); + View terminalNameOverlay = findCurrentView(R.id.terminal_name_overlay); + if (terminalNameOverlay != null) + terminalNameOverlay.startAnimation(fade_out_delayed); updateDefault(); updatePromptVisible(); ActivityCompat.invalidateOptionsMenu(ConsoleActivity.this); @@ -1203,12 +1204,16 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne RelativeLayout view = (RelativeLayout) inflater.inflate( R.layout.item_terminal, container, false); - // set the terminal overlay text - TextView overlay = (TextView) view.findViewById(R.id.terminal_overlay); - overlay.setText(bridge.host.getNickname()); + // set the terminal name overlay text + TextView terminalNameOverlay = (TextView) view.findViewById(R.id.terminal_name_overlay); + terminalNameOverlay.setText(bridge.host.getNickname()); + + TerminalTextViewOverlay terminalTextViewOverlay = + (TerminalTextViewOverlay) view.findViewById(R.id.terminal_text_overlay); // and add our terminal view control, using index to place behind overlay - final TerminalView terminal = new TerminalView(container.getContext(), bridge, pager); + final TerminalView terminal = new TerminalView( + container.getContext(), bridge, terminalTextViewOverlay, pager); terminal.setId(R.id.terminal_view); view.addView(terminal, 0); @@ -1216,7 +1221,7 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne view.setTag(bridge); container.addView(view); - overlay.startAnimation(fade_out_delayed); + terminalNameOverlay.startAnimation(fade_out_delayed); return view; } diff --git a/app/src/main/java/org/connectbot/TerminalView.java b/app/src/main/java/org/connectbot/TerminalView.java index 44b5810..578dcd7 100644 --- a/app/src/main/java/org/connectbot/TerminalView.java +++ b/app/src/main/java/org/connectbot/TerminalView.java @@ -26,6 +26,7 @@ import org.connectbot.service.FontSizeChangedListener; import org.connectbot.service.TerminalBridge; import org.connectbot.service.TerminalKeyListener; import org.connectbot.util.PreferenceConstants; +import org.connectbot.util.TerminalTextViewOverlay; import org.connectbot.util.TerminalViewPager; import android.annotation.TargetApi; @@ -37,25 +38,18 @@ import android.content.SharedPreferences; import android.content.pm.ResolveInfo; import android.database.Cursor; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelXorXfermode; import android.graphics.RectF; -import android.graphics.Typeface; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.preference.PreferenceManager; -import android.support.v4.view.MotionEventCompat; import android.text.ClipboardManager; -import android.view.ActionMode; import android.view.GestureDetector; -import android.view.InputDevice; import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -65,37 +59,29 @@ import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; -import android.widget.TextView; import android.widget.Toast; import de.mud.terminal.VDUBuffer; import de.mud.terminal.vt320; /** - * User interface {@link TextView} for showing a TerminalBridge in an + * User interface {@link View} for showing a TerminalBridge in an * {@link android.app.Activity}. Handles drawing bitmap updates and passing keystrokes down * to terminal. * - * On Honeycomb devices and above (>= APIv11), a TextView with transparent text (which is identical - * to the bitmap) is drawn above the bitmap. This TextView exists to allow the user to - * select and copy text. - * * @author jsharkey */ -public class TerminalView extends TextView implements FontSizeChangedListener { - +public class TerminalView extends View implements FontSizeChangedListener { private final Context context; public final TerminalBridge bridge; - private final TerminalViewPager viewPager; + private TerminalTextViewOverlay terminalTextViewOverlay; + public final TerminalViewPager viewPager; private GestureDetector gestureDetector; private SharedPreferences prefs; - private ClipboardManager clipboard; - private ActionMode selectionActionMode = null; - private String currentSelection = ""; - // These are only used for pre-Honeycomb copying. private int lastTouchedRow, lastTouchedCol; + private final ClipboardManager clipboard; private final Paint paint; private final Paint cursorPaint; @@ -127,11 +113,12 @@ public class TerminalView extends TextView implements FontSizeChangedListener { private static final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService"; private static final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN"; - public TerminalView(Context context, TerminalBridge bridge, TerminalViewPager pager) { + public TerminalView(Context context, TerminalBridge bridge, final TerminalTextViewOverlay terminalTextViewOverlay, TerminalViewPager pager) { super(context); this.context = context; this.bridge = bridge; + this.terminalTextViewOverlay = terminalTextViewOverlay; this.viewPager = pager; setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); @@ -188,6 +175,13 @@ public class TerminalView extends TextView implements FontSizeChangedListener { // connect our view up to the bridge setOnKeyListener(bridge.getKeyHandler()); + if (terminalTextViewOverlay != null) { + terminalTextViewOverlay.parent = this; + + // Once terminalTextViewOverlay is active, allow it to handle key events instead. + terminalTextViewOverlay.setOnKeyListener(bridge.getKeyHandler()); + } + mAccessibilityBuffer = new StringBuffer(); // Enable accessibility features if a screen reader is active. @@ -196,25 +190,19 @@ public class TerminalView extends TextView implements FontSizeChangedListener { clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); prefs = PreferenceManager.getDefaultSharedPreferences(context); - setTextColor(Color.TRANSPARENT); - setTypeface(Typeface.MONOSPACE); onFontSizeChanged(bridge.getFontSize()); - // Allow selection of and copying text for Honeycomb and above devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - setTextIsSelectable(true); - setCustomSelectionActionModeCallback(new TextSelectionActionModeCallback()); - } - gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { + // Only used for pre-Honeycomb devices. private TerminalBridge bridge = TerminalView.this.bridge; private float totalY = 0; @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - // if releasing then reset total scroll - if (e2.getAction() == MotionEvent.ACTION_UP) { - totalY = 0; + // The terminalTextViewOverlay handles scrolling. Only handle scrolling if it + // is not available (i.e. on pre-Honeycomb devices). + if (terminalTextViewOverlay != null) { + return false; } // activate consider if within x tolerance @@ -264,55 +252,18 @@ public class TerminalView extends TextView implements FontSizeChangedListener { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } - @TargetApi(11) - private void closeSelectionActionMode() { - if (selectionActionMode != null) { - selectionActionMode.finish(); - selectionActionMode = null; - } - } - public void copyCurrentSelectionToClipboard() { - ClipboardManager clipboard = - (ClipboardManager) TerminalView.this.context.getSystemService(Context.CLIPBOARD_SERVICE); - if (currentSelection.length() != 0) { - clipboard.setText(currentSelection); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - closeSelectionActionMode(); - } - } - - @Override - protected void onSelectionChanged(int selStart, int selEnd) { - if (selStart <= selEnd) { - currentSelection = getText().toString().substring(selStart, selEnd); - } - super.onSelectionChanged(selStart, selEnd); + terminalTextViewOverlay.copyCurrentSelectionToClipboard(); } @Override public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - // Selection may be beginning. Sync the TextView with the buffer. - refreshTextFromBuffer(); - } - - // Mouse input is treated differently: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && - MotionEventCompat.getSource(event) == InputDevice.SOURCE_MOUSE) { - if (onMouseEvent(event, bridge)) { - return true; - } - viewPager.setPagingEnabled(true); - } else if (gestureDetector != null) { - // The gesture detector should not be called if touch event was from mouse. + if (gestureDetector != null) { gestureDetector.onTouchEvent(event); } // Old version of copying, only for pre-Honeycomb. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + if (terminalTextViewOverlay == null) { // when copying, highlight the area if (bridge.isSelectingForCopy()) { SelectionArea area = bridge.getSelectionArea(); @@ -386,224 +337,6 @@ public class TerminalView extends TextView implements FontSizeChangedListener { return true; } - @TargetApi(11) - private class TextSelectionActionModeCallback implements ActionMode.Callback { - private static final int COPY = 0; - private static final int PASTE = 1; - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return false; - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - TerminalView.this.selectionActionMode = mode; - - menu.clear(); - - menu.add(0, COPY, 0, R.string.console_menu_copy) - .setIcon(R.drawable.ic_action_copy) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT | MenuItem.SHOW_AS_ACTION_IF_ROOM); - menu.add(0, PASTE, 1, R.string.console_menu_paste) - .setIcon(R.drawable.ic_action_paste) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT | MenuItem.SHOW_AS_ACTION_IF_ROOM); - - return true; - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - switch (item.getItemId()) { - case COPY: - copyCurrentSelectionToClipboard(); - return true; - case PASTE: - String clip = ""; - if (clipboard.hasText()) { - clip = clipboard.getText().toString(); - } - TerminalView.this.bridge.injectString(clip); - mode.finish(); - return true; - } - - return false; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - } - } - - /** - * @param event - * @param bridge - * @return True if the event is handled. - */ - @TargetApi(14) - private boolean onMouseEvent(MotionEvent event, TerminalBridge bridge) { - int row = (int) Math.floor(event.getY() / bridge.charHeight); - int col = (int) Math.floor(event.getX() / bridge.charWidth); - int meta = event.getMetaState(); - boolean shiftOn = (meta & KeyEvent.META_SHIFT_ON) != 0; - vt320 vtBuffer = (vt320) bridge.buffer; - boolean mouseReport = vtBuffer.isMouseReportEnabled(); - - // MouseReport can be "defeated" using the shift key. - if (!mouseReport || shiftOn) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (event.getButtonState() == MotionEvent.BUTTON_TERTIARY) { - // Middle click pastes. - String clip = clipboard.getText().toString(); - bridge.injectString(clip); - return true; - } - - // Begin "selection mode" - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - closeSelectionActionMode(); - } - } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - // In the middle of selection. - - if (selectionActionMode == null) { - selectionActionMode = startActionMode(new TextSelectionActionModeCallback()); - } - - int selectionStart = getSelectionStart(); - int selectionEnd = getSelectionEnd(); - - if (selectionStart > selectionEnd) { - int tempStart = selectionStart; - selectionStart = selectionEnd; - selectionEnd = tempStart; - } - - currentSelection = getText().toString().substring(selectionStart, selectionEnd); - } - } else if (event.getAction() == MotionEvent.ACTION_DOWN) { - viewPager.setPagingEnabled(false); - vtBuffer.mousePressed( - col, row, mouseEventToJavaModifiers(event)); - return true; - } else if (event.getAction() == MotionEvent.ACTION_UP) { - viewPager.setPagingEnabled(true); - vtBuffer.mouseReleased(col, row); - return true; - } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - int buttonState = event.getButtonState(); - int button = (buttonState & MotionEvent.BUTTON_PRIMARY) != 0 ? 0 : - (buttonState & MotionEvent.BUTTON_SECONDARY) != 0 ? 1 : - (buttonState & MotionEvent.BUTTON_TERTIARY) != 0 ? 2 : 3; - vtBuffer.mouseMoved( - button, - col, - row, - (meta & KeyEvent.META_CTRL_ON) != 0, - (meta & KeyEvent.META_SHIFT_ON) != 0, - (meta & KeyEvent.META_META_ON) != 0); - return true; - } - - return false; - } - - /** - * Takes an android mouse event and produces a Java InputEvent modifiers int which can be - * passed to vt320. - * @param mouseEvent The {@link MotionEvent} which should be a mouse click or release. - * @return A Java InputEvent modifier int. See - * http://docs.oracle.com/javase/7/docs/api/java/awt/event/InputEvent.html - */ - @TargetApi(14) - private static int mouseEventToJavaModifiers(MotionEvent mouseEvent) { - if (MotionEventCompat.getSource(mouseEvent) != InputDevice.SOURCE_MOUSE) return 0; - - int mods = 0; - - // See http://docs.oracle.com/javase/7/docs/api/constant-values.html - int buttonState = mouseEvent.getButtonState(); - if ((buttonState & MotionEvent.BUTTON_PRIMARY) != 0) - mods |= 16; - if ((buttonState & MotionEvent.BUTTON_SECONDARY) != 0) - mods |= 8; - if ((buttonState & MotionEvent.BUTTON_TERTIARY) != 0) - mods |= 4; - - // Note: Meta and Ctrl are intentionally swapped here to keep logic in vt320 simple. - int meta = mouseEvent.getMetaState(); - if ((meta & KeyEvent.META_META_ON) != 0) - mods |= 2; - if ((meta & KeyEvent.META_SHIFT_ON) != 0) - mods |= 1; - if ((meta & KeyEvent.META_CTRL_ON) != 0) - mods |= 4; - - return mods; - } - - @Override - @TargetApi(12) - public boolean onGenericMotionEvent(MotionEvent event) { - if ((MotionEventCompat.getSource(event) & InputDevice.SOURCE_CLASS_POINTER) != 0) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: - // Process scroll wheel movement: - float yDistance = MotionEventCompat.getAxisValue(event, MotionEvent.AXIS_VSCROLL); - vt320 vtBuffer = (vt320) bridge.buffer; - boolean mouseReport = vtBuffer.isMouseReportEnabled(); - if (mouseReport) { - int row = (int) Math.floor(event.getY() / bridge.charHeight); - int col = (int) Math.floor(event.getX() / bridge.charWidth); - - vtBuffer.mouseWheel( - yDistance > 0, - col, - row, - (event.getMetaState() & KeyEvent.META_CTRL_ON) != 0, - (event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0, - (event.getMetaState() & KeyEvent.META_META_ON) != 0); - return true; - } else if (yDistance != 0) { - int base = bridge.buffer.getWindowBase(); - bridge.buffer.setWindowBase(base - Math.round(yDistance)); - return true; - } - } - } - return super.onGenericMotionEvent(event); - } - - // TODO: cleanup and possibly optimize - private void refreshTextFromBuffer() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - // Do not run this function because the textView is not selectable pre-Honeycomb. - return; - } - - VDUBuffer vb = bridge.getVDUBuffer(); - - String line = ""; - String buffer = ""; - - int windowBase = vb.getWindowBase(); - int rowBegin = vb.getTopMargin(); - int rowEnd = vb.getBottomMargin(); - int numCols = vb.getColumns() - 1; - - for (int r = rowBegin; r <= rowEnd; r++) { - for (int c = 0; c < numCols; c++) { - line += vb.charArray[windowBase + r][c]; - } - buffer += line.replaceAll("\\s+$", "") + "\n"; - line = ""; - } - - setText(buffer); - } - /** * Only intended for pre-Honeycomb devices. */ @@ -639,13 +372,15 @@ public class TerminalView extends TextView implements FontSizeChangedListener { ((Activity) context).runOnUiThread(new Runnable() { @Override public void run() { - setTextSize(size); - - // For the TextView to line up with the bitmap text, lineHeight must be equal to - // the bridge's charHeight. See TextView.getLineHeight(), which has been reversed to - // derive lineSpacingMultiplier. - float lineSpacingMultiplier = (float) bridge.charHeight / getPaint().getFontMetricsInt(null); - setLineSpacing(0.0f, lineSpacingMultiplier); + if (terminalTextViewOverlay != null) { + terminalTextViewOverlay.setTextSize(size); + + // For the TextView to line up with the bitmap text, lineHeight must be equal to + // the bridge's charHeight. See TextView.getLineHeight(), which has been reversed to + // derive lineSpacingMultiplier. + float lineSpacingMultiplier = (float) bridge.charHeight / terminalTextViewOverlay.getPaint().getFontMetricsInt(null); + terminalTextViewOverlay.setLineSpacing(0.0f, lineSpacingMultiplier); + } } }); } @@ -726,8 +461,7 @@ public class TerminalView extends TextView implements FontSizeChangedListener { } // draw any highlighted area - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB && - bridge.isSelectingForCopy()) { + if (terminalTextViewOverlay == null && bridge.isSelectingForCopy()) { SelectionArea area = bridge.getSelectionArea(); canvas.save(Canvas.CLIP_SAVE_FLAG); canvas.clipRect( diff --git a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java new file mode 100644 index 0000000..b64351b --- /dev/null +++ b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java @@ -0,0 +1,368 @@ +/* + * ConnectBot: simple, powerful, open-source SSH client for Android + * Copyright 2015 Kenny Root, Jeffrey Sharkey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.connectbot.util; + +import org.connectbot.R; +import org.connectbot.TerminalView; +import org.connectbot.service.TerminalBridge; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Build; +import android.support.annotation.Nullable; +import android.support.v4.view.MotionEventCompat; +import android.text.ClipboardManager; +import android.util.AttributeSet; +import android.view.ActionMode; +import android.view.InputDevice; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.widget.TextView; +import de.mud.terminal.VDUBuffer; +import de.mud.terminal.vt320; + +/** + * Custom TextView {@link TextView} which is intended to (invisibly) be on top of the TerminalView + * (@link TerminalView) in order to allow the user to select and copy the text of the bitmap below. + * + * @author rhansby + */ +@TargetApi(11) +public class TerminalTextViewOverlay extends TextView { + public TerminalView parent; + private String currentSelection = ""; + private ActionMode selectionActionMode; + private ClipboardManager clipboard; + + private int oldScrollY = -1; + + public TerminalTextViewOverlay(Context context) { + super(context); + init(); + } + + public TerminalTextViewOverlay(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + @TargetApi(21) + public TerminalTextViewOverlay(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + setTextColor(Color.TRANSPARENT); + setTypeface(Typeface.MONOSPACE); + setTextIsSelectable(true); + setCustomSelectionActionModeCallback(new TextSelectionActionModeCallback()); + + clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); + } + + // TODO: optimize: instead of always copying the entire buffer, instead append() as needed. + public void refreshTextFromBuffer() { + VDUBuffer vb = parent.bridge.getVDUBuffer(); + + String line = ""; + String buffer = ""; + + int numRows = vb.getBufferSize(); + int numCols = vb.getColumns() - 1; + + for (int r = 0; r < numRows && vb.charArray[r] != null; r++) { + for (int c = 0; c < numCols; c++) { + line += vb.charArray[r][c]; + } + buffer += line.replaceAll("\\s+$", "") + "\n"; + line = ""; + } + + oldScrollY = vb.getWindowBase() * getLineHeight(); + + setText(buffer); + } + + @Override + public boolean onPreDraw() { + boolean superResult = super.onPreDraw(); + + if (oldScrollY >= 0) { + scrollTo(0, oldScrollY); + oldScrollY = -1; + } + + return superResult; + } + + private void closeSelectionActionMode() { + if (selectionActionMode != null) { + selectionActionMode.finish(); + selectionActionMode = null; + } + } + + public void copyCurrentSelectionToClipboard() { + if (currentSelection.length() != 0) { + clipboard.setText(currentSelection); + } + closeSelectionActionMode(); + } + + @Override + protected void onSelectionChanged(int selStart, int selEnd) { + if (selStart <= selEnd) { + currentSelection = getText().toString().substring(selStart, selEnd); + } + super.onSelectionChanged(selStart, selEnd); + } + + @Override + public void scrollTo(int x, int y) { + int lineMultiple = y / getLineHeight(); + + TerminalBridge bridge = parent.bridge; + bridge.buffer.setWindowBase(lineMultiple); + + super.scrollTo(0, lineMultiple * getLineHeight()); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + // Selection may be beginning. Sync the TextView with the buffer. + refreshTextFromBuffer(); + } + + // Mouse input is treated differently: + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && + MotionEventCompat.getSource(event) == InputDevice.SOURCE_MOUSE) { + if (onMouseEvent(event, parent.bridge)) { + return true; + } + parent.viewPager.setPagingEnabled(true); + } else { + parent.onTouchEvent(event); + } + + super.onTouchEvent(event); + + return true; + } + + @Override + @TargetApi(12) + public boolean onGenericMotionEvent(MotionEvent event) { + if ((MotionEventCompat.getSource(event) & InputDevice.SOURCE_CLASS_POINTER) != 0) { + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: + // Process scroll wheel movement: + float yDistance = MotionEventCompat.getAxisValue(event, MotionEvent.AXIS_VSCROLL); + + vt320 vtBuffer = (vt320) parent.bridge.buffer; + boolean mouseReport = vtBuffer.isMouseReportEnabled(); + if (mouseReport) { + int row = (int) Math.floor(event.getY() / parent.bridge.charHeight); + int col = (int) Math.floor(event.getX() / parent.bridge.charWidth); + + vtBuffer.mouseWheel( + yDistance > 0, + col, + row, + (event.getMetaState() & KeyEvent.META_CTRL_ON) != 0, + (event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0, + (event.getMetaState() & KeyEvent.META_META_ON) != 0); + return true; + } + } + } + + return super.onGenericMotionEvent(event); + } + + /** + * @param event + * @param bridge + * @return True if the event is handled. + */ + @TargetApi(14) + private boolean onMouseEvent(MotionEvent event, TerminalBridge bridge) { + int row = (int) Math.floor(event.getY() / bridge.charHeight); + int col = (int) Math.floor(event.getX() / bridge.charWidth); + int meta = event.getMetaState(); + boolean shiftOn = (meta & KeyEvent.META_SHIFT_ON) != 0; + vt320 vtBuffer = (vt320) bridge.buffer; + boolean mouseReport = vtBuffer.isMouseReportEnabled(); + + // MouseReport can be "defeated" using the shift key. + if (!mouseReport || shiftOn) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (event.getButtonState() == MotionEvent.BUTTON_TERTIARY) { + // Middle click pastes. + String clip = clipboard.getText().toString(); + bridge.injectString(clip); + return true; + } + + // Begin "selection mode" + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + closeSelectionActionMode(); + } + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + // In the middle of selection. + + if (selectionActionMode == null) { + selectionActionMode = startActionMode(new TextSelectionActionModeCallback()); + } + + int selectionStart = getSelectionStart(); + int selectionEnd = getSelectionEnd(); + + if (selectionStart > selectionEnd) { + int tempStart = selectionStart; + selectionStart = selectionEnd; + selectionEnd = tempStart; + } + + currentSelection = getText().toString().substring(selectionStart, selectionEnd); + } + } else if (event.getAction() == MotionEvent.ACTION_DOWN) { + parent.viewPager.setPagingEnabled(false); + vtBuffer.mousePressed( + col, row, mouseEventToJavaModifiers(event)); + return true; + } else if (event.getAction() == MotionEvent.ACTION_UP) { + parent.viewPager.setPagingEnabled(true); + vtBuffer.mouseReleased(col, row); + return true; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + int buttonState = event.getButtonState(); + int button = (buttonState & MotionEvent.BUTTON_PRIMARY) != 0 ? 0 : + (buttonState & MotionEvent.BUTTON_SECONDARY) != 0 ? 1 : + (buttonState & MotionEvent.BUTTON_TERTIARY) != 0 ? 2 : 3; + vtBuffer.mouseMoved( + button, + col, + row, + (meta & KeyEvent.META_CTRL_ON) != 0, + (meta & KeyEvent.META_SHIFT_ON) != 0, + (meta & KeyEvent.META_META_ON) != 0); + return true; + } + + return false; + } + + /** + * Takes an android mouse event and produces a Java InputEvent modifiers int which can be + * passed to vt320. + * @param mouseEvent The {@link MotionEvent} which should be a mouse click or release. + * @return A Java InputEvent modifier int. See + * http://docs.oracle.com/javase/7/docs/api/java/awt/event/InputEvent.html + */ + @TargetApi(14) + private static int mouseEventToJavaModifiers(MotionEvent mouseEvent) { + if (MotionEventCompat.getSource(mouseEvent) != InputDevice.SOURCE_MOUSE) return 0; + + int mods = 0; + + // See http://docs.oracle.com/javase/7/docs/api/constant-values.html + int buttonState = mouseEvent.getButtonState(); + if ((buttonState & MotionEvent.BUTTON_PRIMARY) != 0) + mods |= 16; + if ((buttonState & MotionEvent.BUTTON_SECONDARY) != 0) + mods |= 8; + if ((buttonState & MotionEvent.BUTTON_TERTIARY) != 0) + mods |= 4; + + // Note: Meta and Ctrl are intentionally swapped here to keep logic in vt320 simple. + int meta = mouseEvent.getMetaState(); + if ((meta & KeyEvent.META_META_ON) != 0) + mods |= 2; + if ((meta & KeyEvent.META_SHIFT_ON) != 0) + mods |= 1; + if ((meta & KeyEvent.META_CTRL_ON) != 0) + mods |= 4; + + return mods; + } + + @Override + public boolean onCheckIsTextEditor() { + return true; + } + + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + return parent.onCreateInputConnection(outAttrs); + } + + private class TextSelectionActionModeCallback implements ActionMode.Callback { + private static final int COPY = 0; + private static final int PASTE = 1; + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + TerminalTextViewOverlay.this.selectionActionMode = mode; + + menu.clear(); + + menu.add(0, COPY, 0, R.string.console_menu_copy) + .setIcon(R.drawable.ic_action_copy) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT | MenuItem.SHOW_AS_ACTION_IF_ROOM); + menu.add(0, PASTE, 1, R.string.console_menu_paste) + .setIcon(R.drawable.ic_action_paste) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT | MenuItem.SHOW_AS_ACTION_IF_ROOM); + + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + switch (item.getItemId()) { + case COPY: + copyCurrentSelectionToClipboard(); + return true; + case PASTE: + String clip = clipboard.getText().toString(); + TerminalTextViewOverlay.this.parent.bridge.injectString(clip); + mode.finish(); + return true; + } + + return false; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + } + } +} diff --git a/app/src/main/res/layout-v11/item_terminal.xml b/app/src/main/res/layout-v11/item_terminal.xml new file mode 100644 index 0000000..6817554 --- /dev/null +++ b/app/src/main/res/layout-v11/item_terminal.xml @@ -0,0 +1,47 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/item_terminal.xml b/app/src/main/res/layout/item_terminal.xml index b34c800..e79325d 100644 --- a/app/src/main/res/layout/item_terminal.xml +++ b/app/src/main/res/layout/item_terminal.xml @@ -25,7 +25,7 @@ > Date: Tue, 13 Oct 2015 11:11:12 -0700 Subject: Make text selection scroll up when a new line enters the buffer. --- app/src/main/java/org/connectbot/TerminalView.java | 9 ++++++ .../connectbot/util/TerminalTextViewOverlay.java | 33 +++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/org/connectbot/TerminalView.java b/app/src/main/java/org/connectbot/TerminalView.java index 578dcd7..aec3bc5 100644 --- a/app/src/main/java/org/connectbot/TerminalView.java +++ b/app/src/main/java/org/connectbot/TerminalView.java @@ -557,6 +557,15 @@ public class TerminalView extends View implements FontSizeChangedListener { postDelayed(mEventSender, ACCESSIBILITY_EVENT_THRESHOLD); } } + + ((Activity) context).runOnUiThread(new Runnable() { + @Override + public void run() { + if (terminalTextViewOverlay != null) { + terminalTextViewOverlay.onBufferChanged(); + } + } + }); } private class AccessibilityEventSender implements Runnable { diff --git a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java index b64351b..d814f7f 100644 --- a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java +++ b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java @@ -55,6 +55,7 @@ public class TerminalTextViewOverlay extends TextView { private ActionMode selectionActionMode; private ClipboardManager clipboard; + private int oldBufferHeight = 0; private int oldScrollY = -1; public TerminalTextViewOverlay(Context context) { @@ -82,16 +83,15 @@ public class TerminalTextViewOverlay extends TextView { clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); } - // TODO: optimize: instead of always copying the entire buffer, instead append() as needed. public void refreshTextFromBuffer() { VDUBuffer vb = parent.bridge.getVDUBuffer(); + int numRows = vb.getBufferSize(); + int numCols = vb.getColumns() - 1; + oldBufferHeight = numRows; String line = ""; String buffer = ""; - int numRows = vb.getBufferSize(); - int numCols = vb.getColumns() - 1; - for (int r = 0; r < numRows && vb.charArray[r] != null; r++) { for (int c = 0; c < numCols; c++) { line += vb.charArray[r][c]; @@ -105,6 +105,31 @@ public class TerminalTextViewOverlay extends TextView { setText(buffer); } + /** + * If there is a new line in the buffer, add an empty line + * in this TextView, so that selection seems to move up with the + * rest of the buffer. + */ + public void onBufferChanged() { + VDUBuffer vb = parent.bridge.getVDUBuffer(); + int numRows = vb.getBufferSize(); + int numNewRows = numRows - oldBufferHeight; + + if (numNewRows <= 0) { + return; + } + + String newLines = ""; + for (int i = 0; i < numNewRows; i++) { + newLines += "\n"; + } + + oldScrollY = (vb.getWindowBase() + numNewRows) * getLineHeight(); + oldBufferHeight = numRows; + + append(newLines); + } + @Override public boolean onPreDraw() { boolean superResult = super.onPreDraw(); -- cgit v1.2.3 From 035cba2cf8951a69f89298695d2930ce1b222fb4 Mon Sep 17 00:00:00 2001 From: Ryan Hansberry Date: Tue, 13 Oct 2015 13:18:44 -0700 Subject: Fix lint error. --- app/src/main/res/layout-v11/item_terminal.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/src') diff --git a/app/src/main/res/layout-v11/item_terminal.xml b/app/src/main/res/layout-v11/item_terminal.xml index 6817554..25c3c1c 100644 --- a/app/src/main/res/layout-v11/item_terminal.xml +++ b/app/src/main/res/layout-v11/item_terminal.xml @@ -20,6 +20,7 @@ @@ -42,6 +43,7 @@ android:background="@android:color/transparent" android:isScrollContainer="false" android:ellipsize="end" + tools:ignore="InconsistentLayout" /> -- cgit v1.2.3 From fe52ba2b6b7c46c4d58c485844d85e31882af41f Mon Sep 17 00:00:00 2001 From: Ryan Hansberry Date: Tue, 13 Oct 2015 13:51:32 -0700 Subject: Fix lint error. --- app/src/main/java/org/connectbot/ConsoleActivity.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/org/connectbot/ConsoleActivity.java b/app/src/main/java/org/connectbot/ConsoleActivity.java index 10ae45a..711c89c 100644 --- a/app/src/main/java/org/connectbot/ConsoleActivity.java +++ b/app/src/main/java/org/connectbot/ConsoleActivity.java @@ -31,6 +31,7 @@ import org.connectbot.util.PreferenceConstants; import org.connectbot.util.TerminalTextViewOverlay; import org.connectbot.util.TerminalViewPager; +import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.Dialog; import android.content.ComponentName; @@ -443,6 +444,11 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne hideActionBarIfRequested(); } + @TargetApi(11) + private void requestActionBar() { + supportRequestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); + } + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); @@ -458,8 +464,10 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne prefs = PreferenceManager.getDefaultSharedPreferences(this); titleBarHide = prefs.getBoolean(PreferenceConstants.TITLEBARHIDE, false); - if (titleBarHide) { - supportRequestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); + if (titleBarHide && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + // This is a separate method because Gradle does not uniformly respect the conditional + // Build check. See: https://code.google.com/p/android/issues/detail?id=137195 + requestActionBar(); } this.setContentView(R.layout.act_console); -- cgit v1.2.3 From 1af52a1af5effa89733ddb4925832f4ba14232cd Mon Sep 17 00:00:00 2001 From: Ryan Hansberry Date: Tue, 13 Oct 2015 16:41:45 -0700 Subject: Prevent calling toString on null when pasting to clipboard. --- .../java/org/connectbot/util/TerminalTextViewOverlay.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'app/src') diff --git a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java index d814f7f..be37524 100644 --- a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java +++ b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java @@ -156,6 +156,14 @@ public class TerminalTextViewOverlay extends TextView { closeSelectionActionMode(); } + private void pasteClipboard() { + String clip = ""; + if (clipboard.hasText()) { + clip = clipboard.getText().toString(); + } + parent.bridge.injectString(clip); + } + @Override protected void onSelectionChanged(int selStart, int selEnd) { if (selStart <= selEnd) { @@ -246,8 +254,7 @@ public class TerminalTextViewOverlay extends TextView { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (event.getButtonState() == MotionEvent.BUTTON_TERTIARY) { // Middle click pastes. - String clip = clipboard.getText().toString(); - bridge.injectString(clip); + pasteClipboard(); return true; } @@ -377,8 +384,7 @@ public class TerminalTextViewOverlay extends TextView { copyCurrentSelectionToClipboard(); return true; case PASTE: - String clip = clipboard.getText().toString(); - TerminalTextViewOverlay.this.parent.bridge.injectString(clip); + pasteClipboard(); mode.finish(); return true; } -- cgit v1.2.3 From 0b1de8d696ed7abf64766fefe5700e750cd1f30e Mon Sep 17 00:00:00 2001 From: Ryan Hansberry Date: Wed, 14 Oct 2015 13:34:46 -0700 Subject: Made TerminalTextViewOverlay a child view of TerminalView. --- .../main/java/org/connectbot/ConsoleActivity.java | 7 +--- app/src/main/java/org/connectbot/TerminalView.java | 23 ++++++---- .../connectbot/util/TerminalTextViewOverlay.java | 49 ++++++++-------------- app/src/main/res/layout-v11/item_terminal.xml | 49 ---------------------- 4 files changed, 32 insertions(+), 96 deletions(-) delete mode 100644 app/src/main/res/layout-v11/item_terminal.xml (limited to 'app/src') diff --git a/app/src/main/java/org/connectbot/ConsoleActivity.java b/app/src/main/java/org/connectbot/ConsoleActivity.java index 711c89c..7241e0e 100644 --- a/app/src/main/java/org/connectbot/ConsoleActivity.java +++ b/app/src/main/java/org/connectbot/ConsoleActivity.java @@ -28,7 +28,6 @@ import org.connectbot.service.TerminalBridge; import org.connectbot.service.TerminalKeyListener; import org.connectbot.service.TerminalManager; import org.connectbot.util.PreferenceConstants; -import org.connectbot.util.TerminalTextViewOverlay; import org.connectbot.util.TerminalViewPager; import android.annotation.TargetApi; @@ -1216,12 +1215,8 @@ public class ConsoleActivity extends AppCompatActivity implements BridgeDisconne TextView terminalNameOverlay = (TextView) view.findViewById(R.id.terminal_name_overlay); terminalNameOverlay.setText(bridge.host.getNickname()); - TerminalTextViewOverlay terminalTextViewOverlay = - (TerminalTextViewOverlay) view.findViewById(R.id.terminal_text_overlay); - // and add our terminal view control, using index to place behind overlay - final TerminalView terminal = new TerminalView( - container.getContext(), bridge, terminalTextViewOverlay, pager); + final TerminalView terminal = new TerminalView(container.getContext(), bridge, pager); terminal.setId(R.id.terminal_view); view.addView(terminal, 0); diff --git a/app/src/main/java/org/connectbot/TerminalView.java b/app/src/main/java/org/connectbot/TerminalView.java index aec3bc5..c1e41ea 100644 --- a/app/src/main/java/org/connectbot/TerminalView.java +++ b/app/src/main/java/org/connectbot/TerminalView.java @@ -53,12 +53,13 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; -import android.view.ViewGroup.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; import android.widget.Toast; import de.mud.terminal.VDUBuffer; import de.mud.terminal.vt320; @@ -70,7 +71,7 @@ import de.mud.terminal.vt320; * * @author jsharkey */ -public class TerminalView extends View implements FontSizeChangedListener { +public class TerminalView extends FrameLayout implements FontSizeChangedListener { private final Context context; public final TerminalBridge bridge; @@ -113,12 +114,13 @@ public class TerminalView extends View implements FontSizeChangedListener { private static final String SCREENREADER_INTENT_ACTION = "android.accessibilityservice.AccessibilityService"; private static final String SCREENREADER_INTENT_CATEGORY = "android.accessibilityservice.category.FEEDBACK_SPOKEN"; - public TerminalView(Context context, TerminalBridge bridge, final TerminalTextViewOverlay terminalTextViewOverlay, TerminalViewPager pager) { + public TerminalView(Context context, TerminalBridge bridge, TerminalViewPager pager) { super(context); + setWillNotDraw(false); + this.context = context; this.bridge = bridge; - this.terminalTextViewOverlay = terminalTextViewOverlay; this.viewPager = pager; setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); @@ -175,8 +177,11 @@ public class TerminalView extends View implements FontSizeChangedListener { // connect our view up to the bridge setOnKeyListener(bridge.getKeyHandler()); - if (terminalTextViewOverlay != null) { - terminalTextViewOverlay.parent = this; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + terminalTextViewOverlay = new TerminalTextViewOverlay(context, this); + terminalTextViewOverlay.setLayoutParams( + new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + addView(terminalTextViewOverlay, 0); // Once terminalTextViewOverlay is active, allow it to handle key events instead. terminalTextViewOverlay.setOnKeyListener(bridge.getKeyHandler()); @@ -253,7 +258,9 @@ public class TerminalView extends View implements FontSizeChangedListener { } public void copyCurrentSelectionToClipboard() { - terminalTextViewOverlay.copyCurrentSelectionToClipboard(); + if (terminalTextViewOverlay != null) { + terminalTextViewOverlay.copyCurrentSelectionToClipboard(); + } } @Override @@ -474,8 +481,6 @@ public class TerminalView extends View implements FontSizeChangedListener { canvas.restore(); } } - - super.onDraw(canvas); } public void notifyUser(String message) { diff --git a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java index be37524..a00ab47 100644 --- a/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java +++ b/app/src/main/java/org/connectbot/util/TerminalTextViewOverlay.java @@ -26,10 +26,8 @@ import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; import android.os.Build; -import android.support.annotation.Nullable; import android.support.v4.view.MotionEventCompat; import android.text.ClipboardManager; -import android.util.AttributeSet; import android.view.ActionMode; import android.view.InputDevice; import android.view.KeyEvent; @@ -50,7 +48,7 @@ import de.mud.terminal.vt320; */ @TargetApi(11) public class TerminalTextViewOverlay extends TextView { - public TerminalView parent; + public TerminalView terminalView; // ryan: this name sucks private String currentSelection = ""; private ActionMode selectionActionMode; private ClipboardManager clipboard; @@ -58,33 +56,20 @@ public class TerminalTextViewOverlay extends TextView { private int oldBufferHeight = 0; private int oldScrollY = -1; - public TerminalTextViewOverlay(Context context) { + public TerminalTextViewOverlay(Context context, TerminalView terminalView) { super(context); - init(); - } - - public TerminalTextViewOverlay(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - init(); - } - @TargetApi(21) - public TerminalTextViewOverlay(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } + this.terminalView = terminalView; + clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); - private void init() { setTextColor(Color.TRANSPARENT); setTypeface(Typeface.MONOSPACE); setTextIsSelectable(true); setCustomSelectionActionModeCallback(new TextSelectionActionModeCallback()); - - clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); } public void refreshTextFromBuffer() { - VDUBuffer vb = parent.bridge.getVDUBuffer(); + VDUBuffer vb = terminalView.bridge.getVDUBuffer(); int numRows = vb.getBufferSize(); int numCols = vb.getColumns() - 1; oldBufferHeight = numRows; @@ -111,7 +96,7 @@ public class TerminalTextViewOverlay extends TextView { * rest of the buffer. */ public void onBufferChanged() { - VDUBuffer vb = parent.bridge.getVDUBuffer(); + VDUBuffer vb = terminalView.bridge.getVDUBuffer(); int numRows = vb.getBufferSize(); int numNewRows = numRows - oldBufferHeight; @@ -161,7 +146,7 @@ public class TerminalTextViewOverlay extends TextView { if (clipboard.hasText()) { clip = clipboard.getText().toString(); } - parent.bridge.injectString(clip); + terminalView.bridge.injectString(clip); } @Override @@ -176,7 +161,7 @@ public class TerminalTextViewOverlay extends TextView { public void scrollTo(int x, int y) { int lineMultiple = y / getLineHeight(); - TerminalBridge bridge = parent.bridge; + TerminalBridge bridge = terminalView.bridge; bridge.buffer.setWindowBase(lineMultiple); super.scrollTo(0, lineMultiple * getLineHeight()); @@ -192,12 +177,12 @@ public class TerminalTextViewOverlay extends TextView { // Mouse input is treated differently: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && MotionEventCompat.getSource(event) == InputDevice.SOURCE_MOUSE) { - if (onMouseEvent(event, parent.bridge)) { + if (onMouseEvent(event, terminalView.bridge)) { return true; } - parent.viewPager.setPagingEnabled(true); + terminalView.viewPager.setPagingEnabled(true); } else { - parent.onTouchEvent(event); + terminalView.onTouchEvent(event); } super.onTouchEvent(event); @@ -214,11 +199,11 @@ public class TerminalTextViewOverlay extends TextView { // Process scroll wheel movement: float yDistance = MotionEventCompat.getAxisValue(event, MotionEvent.AXIS_VSCROLL); - vt320 vtBuffer = (vt320) parent.bridge.buffer; + vt320 vtBuffer = (vt320) terminalView.bridge.buffer; boolean mouseReport = vtBuffer.isMouseReportEnabled(); if (mouseReport) { - int row = (int) Math.floor(event.getY() / parent.bridge.charHeight); - int col = (int) Math.floor(event.getX() / parent.bridge.charWidth); + int row = (int) Math.floor(event.getY() / terminalView.bridge.charHeight); + int col = (int) Math.floor(event.getX() / terminalView.bridge.charWidth); vtBuffer.mouseWheel( yDistance > 0, @@ -282,12 +267,12 @@ public class TerminalTextViewOverlay extends TextView { currentSelection = getText().toString().substring(selectionStart, selectionEnd); } } else if (event.getAction() == MotionEvent.ACTION_DOWN) { - parent.viewPager.setPagingEnabled(false); + terminalView.viewPager.setPagingEnabled(false); vtBuffer.mousePressed( col, row, mouseEventToJavaModifiers(event)); return true; } else if (event.getAction() == MotionEvent.ACTION_UP) { - parent.viewPager.setPagingEnabled(true); + terminalView.viewPager.setPagingEnabled(true); vtBuffer.mouseReleased(col, row); return true; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { @@ -349,7 +334,7 @@ public class TerminalTextViewOverlay extends TextView { @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - return parent.onCreateInputConnection(outAttrs); + return terminalView.onCreateInputConnection(outAttrs); } private class TextSelectionActionModeCallback implements ActionMode.Callback { diff --git a/app/src/main/res/layout-v11/item_terminal.xml b/app/src/main/res/layout-v11/item_terminal.xml deleted file mode 100644 index 25c3c1c..0000000 --- a/app/src/main/res/layout-v11/item_terminal.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - -- cgit v1.2.3