Jeff Sharkey | ef946f3 | 2013-02-19 17:29:18 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.terminal; |
| 18 | |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 19 | import android.graphics.Color; |
Kenny Root | 8c04033 | 2013-02-18 23:31:29 -0800 | [diff] [blame] | 20 | |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 21 | /** |
| 22 | * Single terminal session backed by a pseudo terminal on the local device. |
| 23 | */ |
| 24 | public class Terminal { |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 25 | public static final String TAG = "Terminal"; |
| 26 | |
| 27 | public final int key; |
Jeff Sharkey | 479bd64 | 2013-02-21 17:45:16 -0800 | [diff] [blame] | 28 | |
Jeff Sharkey | de15e79 | 2013-02-23 15:42:10 -0800 | [diff] [blame] | 29 | private static int sNumber = 0; |
| 30 | |
Jeff Sharkey | ef946f3 | 2013-02-19 17:29:18 -0800 | [diff] [blame] | 31 | static { |
| 32 | System.loadLibrary("jni_terminal"); |
| 33 | } |
| 34 | |
Jeff Sharkey | 9cae0a9 | 2013-02-20 21:41:29 -0800 | [diff] [blame] | 35 | /** |
| 36 | * Represents a run of one or more {@code VTermScreenCell} which all have |
| 37 | * the same formatting. |
| 38 | */ |
| 39 | public static class CellRun { |
| 40 | char[] data; |
| 41 | int dataSize; |
| 42 | int colSize; |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 43 | |
| 44 | boolean bold; |
| 45 | int underline; |
| 46 | boolean blink; |
| 47 | boolean reverse; |
| 48 | boolean strike; |
| 49 | int font; |
| 50 | |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 51 | int fg = Color.CYAN; |
| 52 | int bg = Color.DKGRAY; |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 53 | } |
| 54 | |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 55 | // NOTE: clients must not call back into terminal while handling a callback, |
| 56 | // since native mutex isn't reentrant. |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 57 | public interface TerminalClient { |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 58 | public void onDamage(int startRow, int endRow, int startCol, int endCol); |
| 59 | public void onMoveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, |
Jeff Sharkey | 6a142b6 | 2013-02-23 12:27:57 -0800 | [diff] [blame] | 60 | int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol); |
Tom Marshall | 5b68e8a | 2014-12-31 10:51:01 -0800 | [diff] [blame] | 61 | public void onMoveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible); |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 62 | public void onBell(); |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 63 | } |
| 64 | |
Colin Cross | 96403af | 2014-04-08 15:15:34 -0700 | [diff] [blame] | 65 | private final long mNativePtr; |
Jeff Sharkey | 479bd64 | 2013-02-21 17:45:16 -0800 | [diff] [blame] | 66 | private final Thread mThread; |
| 67 | |
Jeff Sharkey | de15e79 | 2013-02-23 15:42:10 -0800 | [diff] [blame] | 68 | private String mTitle; |
| 69 | |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 70 | private TerminalClient mClient; |
| 71 | |
Tom Marshall | 5b68e8a | 2014-12-31 10:51:01 -0800 | [diff] [blame] | 72 | private boolean mCursorVisible; |
| 73 | private int mCursorRow; |
| 74 | private int mCursorCol; |
| 75 | |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 76 | private final TerminalCallbacks mCallbacks = new TerminalCallbacks() { |
| 77 | @Override |
| 78 | public int damage(int startRow, int endRow, int startCol, int endCol) { |
| 79 | if (mClient != null) { |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 80 | mClient.onDamage(startRow, endRow, startCol, endCol); |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 81 | } |
| 82 | return 1; |
| 83 | } |
| 84 | |
| 85 | @Override |
Jeff Sharkey | a76e338 | 2013-02-21 19:09:55 -0800 | [diff] [blame] | 86 | public int moveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, |
| 87 | int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol) { |
Jeff Sharkey | a76e338 | 2013-02-21 19:09:55 -0800 | [diff] [blame] | 88 | if (mClient != null) { |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 89 | mClient.onMoveRect(destStartRow, destEndRow, destStartCol, destEndCol, srcStartRow, |
Jeff Sharkey | 6a142b6 | 2013-02-23 12:27:57 -0800 | [diff] [blame] | 90 | srcEndRow, srcStartCol, srcEndCol); |
Jeff Sharkey | a76e338 | 2013-02-21 19:09:55 -0800 | [diff] [blame] | 91 | } |
| 92 | return 1; |
| 93 | } |
| 94 | |
| 95 | @Override |
Tom Marshall | 5b68e8a | 2014-12-31 10:51:01 -0800 | [diff] [blame] | 96 | public int moveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible) { |
| 97 | mCursorVisible = (visible != 0); |
| 98 | mCursorRow = posRow; |
| 99 | mCursorCol = posCol; |
| 100 | if (mClient != null) { |
| 101 | mClient.onMoveCursor(posRow, posCol, oldPosRow, oldPosCol, visible); |
| 102 | } |
| 103 | return 1; |
| 104 | } |
| 105 | |
| 106 | @Override |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 107 | public int bell() { |
| 108 | if (mClient != null) { |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 109 | mClient.onBell(); |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 110 | } |
| 111 | return 1; |
| 112 | } |
| 113 | }; |
Jeff Sharkey | ef946f3 | 2013-02-19 17:29:18 -0800 | [diff] [blame] | 114 | |
| 115 | public Terminal() { |
Tom Marshall | d3090cb | 2014-12-31 10:42:02 -0800 | [diff] [blame] | 116 | mNativePtr = nativeInit(mCallbacks); |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 117 | key = sNumber++; |
| 118 | mTitle = TAG + " " + key; |
| 119 | mThread = new Thread(mTitle) { |
Jeff Sharkey | d439bac | 2013-02-20 22:17:51 -0800 | [diff] [blame] | 120 | @Override |
| 121 | public void run() { |
Jeff Sharkey | 479bd64 | 2013-02-21 17:45:16 -0800 | [diff] [blame] | 122 | nativeRun(mNativePtr); |
Jeff Sharkey | d439bac | 2013-02-20 22:17:51 -0800 | [diff] [blame] | 123 | } |
Jeff Sharkey | 479bd64 | 2013-02-21 17:45:16 -0800 | [diff] [blame] | 124 | }; |
| 125 | } |
| 126 | |
| 127 | /** |
| 128 | * Start thread which internally forks and manages the pseudo terminal. |
| 129 | */ |
| 130 | public void start() { |
| 131 | mThread.start(); |
Jeff Sharkey | ef946f3 | 2013-02-19 17:29:18 -0800 | [diff] [blame] | 132 | } |
| 133 | |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 134 | public void destroy() { |
| 135 | if (nativeDestroy(mNativePtr) != 0) { |
| 136 | throw new IllegalStateException("destroy failed"); |
Jeff Sharkey | de15e79 | 2013-02-23 15:42:10 -0800 | [diff] [blame] | 137 | } |
| 138 | } |
| 139 | |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 140 | public void setClient(TerminalClient client) { |
| 141 | mClient = client; |
| 142 | } |
| 143 | |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 144 | public void resize(int rows, int cols, int scrollRows) { |
| 145 | if (nativeResize(mNativePtr, rows, cols, scrollRows) != 0) { |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 146 | throw new IllegalStateException("resize failed"); |
| 147 | } |
Jeff Sharkey | 5d4b395 | 2013-02-19 20:34:29 -0800 | [diff] [blame] | 148 | } |
| 149 | |
Jeff Sharkey | ef946f3 | 2013-02-19 17:29:18 -0800 | [diff] [blame] | 150 | public int getRows() { |
| 151 | return nativeGetRows(mNativePtr); |
| 152 | } |
| 153 | |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 154 | public int getCols() { |
| 155 | return nativeGetCols(mNativePtr); |
| 156 | } |
| 157 | |
Jeff Sharkey | 00b0081 | 2013-04-14 16:16:49 -0700 | [diff] [blame] | 158 | public int getScrollRows() { |
| 159 | return nativeGetScrollRows(mNativePtr); |
| 160 | } |
| 161 | |
Jeff Sharkey | 9cae0a9 | 2013-02-20 21:41:29 -0800 | [diff] [blame] | 162 | public void getCellRun(int row, int col, CellRun run) { |
| 163 | if (nativeGetCellRun(mNativePtr, row, col, run) != 0) { |
Jeff Sharkey | 410e0da | 2013-02-19 23:10:46 -0800 | [diff] [blame] | 164 | throw new IllegalStateException("getCell failed"); |
| 165 | } |
| 166 | } |
| 167 | |
Tom Marshall | 5b68e8a | 2014-12-31 10:51:01 -0800 | [diff] [blame] | 168 | public boolean getCursorVisible() { |
| 169 | return mCursorVisible; |
| 170 | } |
| 171 | |
| 172 | public int getCursorRow() { |
| 173 | return mCursorRow; |
| 174 | } |
| 175 | |
| 176 | public int getCursorCol() { |
| 177 | return mCursorCol; |
| 178 | } |
| 179 | |
Jeff Sharkey | de15e79 | 2013-02-23 15:42:10 -0800 | [diff] [blame] | 180 | public String getTitle() { |
| 181 | // TODO: hook up to title passed through termprop |
| 182 | return mTitle; |
| 183 | } |
| 184 | |
Michael Wright | 007efde | 2013-02-25 11:22:30 -0800 | [diff] [blame] | 185 | public boolean dispatchKey(int modifiers, int key) { |
Michael Wright | c8be179 | 2013-02-26 11:09:12 -0800 | [diff] [blame] | 186 | return nativeDispatchKey(mNativePtr, modifiers, key); |
Michael Wright | 007efde | 2013-02-25 11:22:30 -0800 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | public boolean dispatchCharacter(int modifiers, int character) { |
Michael Wright | c8be179 | 2013-02-26 11:09:12 -0800 | [diff] [blame] | 190 | return nativeDispatchCharacter(mNativePtr, modifiers, character); |
Michael Wright | 007efde | 2013-02-25 11:22:30 -0800 | [diff] [blame] | 191 | } |
| 192 | |
Tom Marshall | d3090cb | 2014-12-31 10:42:02 -0800 | [diff] [blame] | 193 | private static native long nativeInit(TerminalCallbacks callbacks); |
Colin Cross | 96403af | 2014-04-08 15:15:34 -0700 | [diff] [blame] | 194 | private static native int nativeDestroy(long ptr); |
Jeff Sharkey | 479bd64 | 2013-02-21 17:45:16 -0800 | [diff] [blame] | 195 | |
Colin Cross | 96403af | 2014-04-08 15:15:34 -0700 | [diff] [blame] | 196 | private static native int nativeRun(long ptr); |
| 197 | private static native int nativeResize(long ptr, int rows, int cols, int scrollRows); |
| 198 | private static native int nativeGetCellRun(long ptr, int row, int col, CellRun run); |
| 199 | private static native int nativeGetRows(long ptr); |
| 200 | private static native int nativeGetCols(long ptr); |
| 201 | private static native int nativeGetScrollRows(long ptr); |
Michael Wright | 007efde | 2013-02-25 11:22:30 -0800 | [diff] [blame] | 202 | |
Colin Cross | 96403af | 2014-04-08 15:15:34 -0700 | [diff] [blame] | 203 | private static native boolean nativeDispatchKey(long ptr, int modifiers, int key); |
| 204 | private static native boolean nativeDispatchCharacter(long ptr, int modifiers, int character); |
Jeff Sharkey | ef946f3 | 2013-02-19 17:29:18 -0800 | [diff] [blame] | 205 | } |