summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2013-02-19 23:10:46 -0800
committerJeff Sharkey <jsharkey@android.com>2013-02-19 23:11:58 -0800
commit410e0da343fd581f3112037deb475db9fb0da850 (patch)
treeb5abeb9de4fb1818c26b2be19aa842e65576d789 /src
parent5d4b3955da5952d8ec2cb45e3aa5406294560798 (diff)
downloadandroid_packages_apps_Terminal-410e0da343fd581f3112037deb475db9fb0da850.tar.gz
android_packages_apps_Terminal-410e0da343fd581f3112037deb475db9fb0da850.tar.bz2
android_packages_apps_Terminal-410e0da343fd581f3112037deb475db9fb0da850.zip
TerminalView to draw session contents.
View sets terminal dimensions to match screen, and handles any draw requests for dirty regions. damage() calls from below are translated into normal View invalidates. For now makes separate getCell() calls for each cell while drawing across screen. This currently costs about 130ms for a 38x59 shell. Change-Id: I2d106a8aeb18e9d6993f30cfb02438e85ee63c65
Diffstat (limited to 'src')
-rw-r--r--src/com/android/terminal/Terminal.java68
-rw-r--r--src/com/android/terminal/TerminalActivity.java8
-rw-r--r--src/com/android/terminal/TerminalView.java167
3 files changed, 236 insertions, 7 deletions
diff --git a/src/com/android/terminal/Terminal.java b/src/com/android/terminal/Terminal.java
index 9f3016b..8067b9a 100644
--- a/src/com/android/terminal/Terminal.java
+++ b/src/com/android/terminal/Terminal.java
@@ -16,30 +16,88 @@
package com.android.terminal;
-public class Terminal {
- private TerminalCallbacks mCallbacks;
+import android.graphics.Color;
+/**
+ * Single terminal session backed by a pseudo terminal on the local device.
+ */
+public class Terminal {
static {
System.loadLibrary("jni_terminal");
}
+ public static class Cell {
+ char[] chars = new char[2];
+ int width = 1;
+
+ boolean bold;
+ int underline;
+ boolean blink;
+ boolean reverse;
+ boolean strike;
+ int font;
+
+ int fgColor = Color.RED;
+ int bgColor = Color.BLUE;
+ }
+
+ public interface TerminalClient {
+ public void damage(int startRow, int endRow, int startCol, int endCol);
+ public void bell();
+ }
+
private final int mNativePtr;
+ private TerminalClient mClient;
+
+ private final TerminalCallbacks mCallbacks = new TerminalCallbacks() {
+ @Override
+ public int damage(int startRow, int endRow, int startCol, int endCol) {
+ if (mClient != null) {
+ mClient.damage(startRow, endRow, startCol, endCol);
+ }
+ return 1;
+ }
+
+ @Override
+ public int bell() {
+ if (mClient != null) {
+ mClient.bell();
+ }
+ return 1;
+ }
+ };
public Terminal() {
- mCallbacks = new TerminalCallbacks() {
- };
mNativePtr = nativeInit(mCallbacks, 25, 80);
}
+ public void setClient(TerminalClient client) {
+ mClient = client;
+ }
+
public void resize(int rows, int cols) {
- nativeResize(mNativePtr, rows, cols);
+ if (nativeResize(mNativePtr, rows, cols) != 0) {
+ throw new IllegalStateException("resize failed");
+ }
}
public int getRows() {
return nativeGetRows(mNativePtr);
}
+ public int getCols() {
+ return nativeGetCols(mNativePtr);
+ }
+
+ public void getCell(int row, int col, Cell cell) {
+ if (nativeGetCell(mNativePtr, row, col, cell) != 0) {
+ throw new IllegalStateException("getCell failed");
+ }
+ }
+
private static native int nativeInit(TerminalCallbacks callbacks, int rows, int cols);
private static native int nativeResize(int ptr, int rows, int cols);
+ private static native int nativeGetCell(int ptr, int row, int col, Cell cell);
private static native int nativeGetRows(int ptr);
+ private static native int nativeGetCols(int ptr);
}
diff --git a/src/com/android/terminal/TerminalActivity.java b/src/com/android/terminal/TerminalActivity.java
index 0bb73ff..601fd98 100644
--- a/src/com/android/terminal/TerminalActivity.java
+++ b/src/com/android/terminal/TerminalActivity.java
@@ -27,7 +27,11 @@ public class TerminalActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Terminal t = new Terminal();
- Log.d(TAG, "Rows: " + t.getRows());
+ final Terminal term = new Terminal();
+ final TerminalView view = new TerminalView(this, term);
+
+ setContentView(view);
+
+ Log.d(TAG, "Rows: " + term.getRows());
}
}
diff --git a/src/com/android/terminal/TerminalView.java b/src/com/android/terminal/TerminalView.java
new file mode 100644
index 0000000..adbb0a7
--- /dev/null
+++ b/src/com/android/terminal/TerminalView.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 com.android.terminal;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.FontMetrics;
+import android.graphics.Rect;
+import android.view.View;
+
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.terminal.Terminal.TerminalClient;
+
+/**
+ * Rendered contents of a {@link Terminal} session.
+ */
+public class TerminalView extends View {
+ private static final String TAG = "Terminal";
+
+ private final Context mContext;
+ private final Terminal mTerm;
+
+ private final Paint mBgPaint = new Paint();
+ private final Paint mTextPaint = new Paint();
+
+ private int mCharTop;
+ private int mCharWidth;
+ private int mCharHeight;
+
+ private TerminalClient mClient = new TerminalClient() {
+ @Override
+ public void damage(int startRow, int endRow, int startCol, int endCol) {
+ final int top = startRow * mCharHeight;
+ final int bottom = (endRow + 1) * mCharHeight;
+ final int left = startCol * mCharWidth;
+ final int right = (endCol + 1) * mCharWidth;
+
+ // Invalidate region on screen
+ postInvalidate(left, top, right, bottom);
+ }
+
+ @Override
+ public void bell() {
+ Log.i(TAG, "DING!");
+ }
+ };
+
+ public TerminalView(Context context, Terminal term) {
+ super(context);
+ mContext = context;
+ mTerm = term;
+
+ setBackgroundColor(Color.BLACK);
+ setTextSize(20);
+
+ // TODO: remove this test code that triggers invalidates
+ setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ v.invalidate();
+ }
+ });
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mTerm.setClient(mClient);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mTerm.setClient(null);
+ }
+
+ public void setTextSize(float textSize) {
+ mTextPaint.setTextSize(textSize);
+
+ // Read metrics to get exact pixel dimensions
+ final FontMetrics fm = mTextPaint.getFontMetrics();
+ mCharTop = (int) Math.ceil(fm.top);
+
+ final float[] widths = new float[1];
+ mTextPaint.getTextWidths("X", widths);
+ mCharWidth = (int) Math.ceil(widths[0]);
+ mCharHeight = (int) Math.ceil(fm.descent - fm.top);
+
+ updateTerminalSize();
+ }
+
+ /**
+ * Determine terminal dimensions based on current dimensions and font size,
+ * and request that {@link Terminal} change to that size.
+ */
+ public void updateTerminalSize() {
+ if (getWidth() > 0 && getHeight() > 0) {
+ final int rows = getHeight() / mCharHeight;
+ final int cols = getWidth() / mCharWidth;
+ mTerm.resize(rows, cols);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ updateTerminalSize();
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ final long start = SystemClock.elapsedRealtime();
+
+ // Only draw dirty region of console
+ final Rect dirty = canvas.getClipBounds();
+
+ final int startRow = dirty.top / mCharHeight;
+ final int endRow = dirty.bottom / mCharHeight;
+ final int startCol = dirty.left / mCharWidth;
+ final int endCol = dirty.right / mCharWidth;
+
+ final Terminal.Cell cell = new Terminal.Cell();
+
+ for (int row = startRow; row <= endRow; row++) {
+ for (int col = startCol; col <= endCol;) {
+ mTerm.getCell(row, col, cell);
+
+ mBgPaint.setColor(cell.bgColor);
+ mTextPaint.setColor(cell.fgColor);
+
+ final int y = row * mCharHeight;
+ final int x = col * mCharWidth;
+ final int xEnd = x + (cell.width * mCharWidth);
+
+ canvas.drawRect(x, y, xEnd, y + mCharHeight, mBgPaint);
+ canvas.drawText(cell.chars, 0, cell.chars.length, x, y - mCharTop, mTextPaint);
+
+ col += cell.width;
+ }
+ }
+
+ final long delta = SystemClock.elapsedRealtime() - start;
+ Log.d(TAG, "onDraw() took " + delta + "ms");
+ }
+}