mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-05 02:05:25 +08:00
Remove moved files
This commit is contained in:
@@ -1,71 +0,0 @@
|
|||||||
package com.termux.app;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.text.Selection;
|
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.ViewGroup.LayoutParams;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
public final class DialogUtils {
|
|
||||||
|
|
||||||
public interface TextSetListener {
|
|
||||||
void onTextSet(String text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void textInput(Activity activity, int titleText, String initialText,
|
|
||||||
int positiveButtonText, final TextSetListener onPositive,
|
|
||||||
int neutralButtonText, final TextSetListener onNeutral,
|
|
||||||
int negativeButtonText, final TextSetListener onNegative,
|
|
||||||
final DialogInterface.OnDismissListener onDismiss) {
|
|
||||||
final EditText input = new EditText(activity);
|
|
||||||
input.setSingleLine();
|
|
||||||
if (initialText != null) {
|
|
||||||
input.setText(initialText);
|
|
||||||
Selection.setSelection(input.getText(), initialText.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
final AlertDialog[] dialogHolder = new AlertDialog[1];
|
|
||||||
input.setImeActionLabel(activity.getResources().getString(positiveButtonText), KeyEvent.KEYCODE_ENTER);
|
|
||||||
input.setOnEditorActionListener((v, actionId, event) -> {
|
|
||||||
onPositive.onTextSet(input.getText().toString());
|
|
||||||
dialogHolder[0].dismiss();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
float dipInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, activity.getResources().getDisplayMetrics());
|
|
||||||
// https://www.google.com/design/spec/components/dialogs.html#dialogs-specs
|
|
||||||
int paddingTopAndSides = Math.round(16 * dipInPixels);
|
|
||||||
int paddingBottom = Math.round(24 * dipInPixels);
|
|
||||||
|
|
||||||
LinearLayout layout = new LinearLayout(activity);
|
|
||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
|
||||||
layout.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
|
||||||
layout.setPadding(paddingTopAndSides, paddingTopAndSides, paddingTopAndSides, paddingBottom);
|
|
||||||
layout.addView(input);
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity)
|
|
||||||
.setTitle(titleText).setView(layout)
|
|
||||||
.setPositiveButton(positiveButtonText, (d, whichButton) -> onPositive.onTextSet(input.getText().toString()));
|
|
||||||
|
|
||||||
if (onNeutral != null) {
|
|
||||||
builder.setNeutralButton(neutralButtonText, (dialog, which) -> onNeutral.onTextSet(input.getText().toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onNegative == null) {
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
} else {
|
|
||||||
builder.setNegativeButton(negativeButtonText, (dialog, which) -> onNegative.onTextSet(input.getText().toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onDismiss != null) builder.setOnDismissListener(onDismiss);
|
|
||||||
|
|
||||||
dialogHolder[0] = builder.create();
|
|
||||||
dialogHolder[0].setCanceledOnTouchOutside(false);
|
|
||||||
dialogHolder[0].show();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,63 +0,0 @@
|
|||||||
package com.termux.app.terminal;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.os.Vibrator;
|
|
||||||
|
|
||||||
public class BellHandler {
|
|
||||||
private static BellHandler instance = null;
|
|
||||||
private static final Object lock = new Object();
|
|
||||||
|
|
||||||
public static BellHandler getInstance(Context context) {
|
|
||||||
if (instance == null) {
|
|
||||||
synchronized (lock) {
|
|
||||||
if (instance == null) {
|
|
||||||
instance = new BellHandler((Vibrator) context.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long DURATION = 50;
|
|
||||||
private static final long MIN_PAUSE = 3 * DURATION;
|
|
||||||
|
|
||||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
private long lastBell = 0;
|
|
||||||
private final Runnable bellRunnable;
|
|
||||||
|
|
||||||
private BellHandler(final Vibrator vibrator) {
|
|
||||||
bellRunnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (vibrator != null) {
|
|
||||||
vibrator.vibrate(DURATION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void doBell() {
|
|
||||||
long now = now();
|
|
||||||
long timeSinceLastBell = now - lastBell;
|
|
||||||
|
|
||||||
if (timeSinceLastBell < 0) {
|
|
||||||
// there is a next bell pending; don't schedule another one
|
|
||||||
} else if (timeSinceLastBell < MIN_PAUSE) {
|
|
||||||
// there was a bell recently, scheudle the next one
|
|
||||||
handler.postDelayed(bellRunnable, MIN_PAUSE - timeSinceLastBell);
|
|
||||||
lastBell = lastBell + MIN_PAUSE;
|
|
||||||
} else {
|
|
||||||
// the last bell was long ago, do it now
|
|
||||||
bellRunnable.run();
|
|
||||||
lastBell = now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long now() {
|
|
||||||
return SystemClock.uptimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,68 +0,0 @@
|
|||||||
package com.termux.app.terminal;
|
|
||||||
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import com.termux.app.TermuxActivity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Work around for fullscreen mode in Termux to fix ExtraKeysView not being visible.
|
|
||||||
* This class is derived from:
|
|
||||||
* https://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible
|
|
||||||
* and has some additional tweaks
|
|
||||||
* ---
|
|
||||||
* For more information, see https://issuetracker.google.com/issues/36911528
|
|
||||||
*/
|
|
||||||
public class FullScreenWorkAround {
|
|
||||||
private final View mChildOfContent;
|
|
||||||
private int mUsableHeightPrevious;
|
|
||||||
private final ViewGroup.LayoutParams mViewGroupLayoutParams;
|
|
||||||
|
|
||||||
private final int mNavBarHeight;
|
|
||||||
|
|
||||||
|
|
||||||
public static void apply(TermuxActivity activity) {
|
|
||||||
new FullScreenWorkAround(activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FullScreenWorkAround(TermuxActivity activity) {
|
|
||||||
ViewGroup content = activity.findViewById(android.R.id.content);
|
|
||||||
mChildOfContent = content.getChildAt(0);
|
|
||||||
mViewGroupLayoutParams = mChildOfContent.getLayoutParams();
|
|
||||||
mNavBarHeight = activity.getNavBarHeight();
|
|
||||||
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(this::possiblyResizeChildOfContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void possiblyResizeChildOfContent() {
|
|
||||||
int usableHeightNow = computeUsableHeight();
|
|
||||||
if (usableHeightNow != mUsableHeightPrevious) {
|
|
||||||
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
|
|
||||||
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
|
|
||||||
if (heightDifference > (usableHeightSansKeyboard / 4)) {
|
|
||||||
// keyboard probably just became visible
|
|
||||||
|
|
||||||
// ensures that usable layout space does not extend behind the
|
|
||||||
// soft keyboard, causing the extra keys to not be visible
|
|
||||||
mViewGroupLayoutParams.height = (usableHeightSansKeyboard - heightDifference) + getNavBarHeight();
|
|
||||||
} else {
|
|
||||||
// keyboard probably just became hidden
|
|
||||||
mViewGroupLayoutParams.height = usableHeightSansKeyboard;
|
|
||||||
}
|
|
||||||
mChildOfContent.requestLayout();
|
|
||||||
mUsableHeightPrevious = usableHeightNow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getNavBarHeight() {
|
|
||||||
return mNavBarHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int computeUsableHeight() {
|
|
||||||
Rect r = new Rect();
|
|
||||||
mChildOfContent.getWindowVisibleDisplayFrame(r);
|
|
||||||
return (r.bottom - r.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@@ -1,13 +0,0 @@
|
|||||||
package com.termux.app.terminal;
|
|
||||||
|
|
||||||
public class KeyboardShortcut {
|
|
||||||
|
|
||||||
public final int codePoint;
|
|
||||||
public final int shortcutAction;
|
|
||||||
|
|
||||||
public KeyboardShortcut(int codePoint, int shortcutAction) {
|
|
||||||
this.codePoint = codePoint;
|
|
||||||
this.shortcutAction = shortcutAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,92 +0,0 @@
|
|||||||
package com.termux.app.terminal.extrakeys;
|
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ExtraKeyButton {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The key that will be sent to the terminal, either a control character
|
|
||||||
* defined in ExtraKeysView.keyCodesForString (LEFT, RIGHT, PGUP...) or
|
|
||||||
* some text.
|
|
||||||
*/
|
|
||||||
private final String key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the key is a macro, i.e. a sequence of keys separated by space.
|
|
||||||
*/
|
|
||||||
private final boolean macro;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The text that will be shown on the button.
|
|
||||||
*/
|
|
||||||
private final String display;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The information of the popup (triggered by swipe up).
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private ExtraKeyButton popup = null;
|
|
||||||
|
|
||||||
public ExtraKeyButton(ExtraKeysInfo.CharDisplayMap charDisplayMap, JSONObject config) throws JSONException {
|
|
||||||
this(charDisplayMap, config, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExtraKeyButton(ExtraKeysInfo.CharDisplayMap charDisplayMap, JSONObject config, @Nullable ExtraKeyButton popup) throws JSONException {
|
|
||||||
String keyFromConfig = config.optString("key", null);
|
|
||||||
String macroFromConfig = config.optString("macro", null);
|
|
||||||
String[] keys;
|
|
||||||
if (keyFromConfig != null && macroFromConfig != null) {
|
|
||||||
throw new JSONException("Both key and macro can't be set for the same key");
|
|
||||||
} else if (keyFromConfig != null) {
|
|
||||||
keys = new String[]{keyFromConfig};
|
|
||||||
this.macro = false;
|
|
||||||
} else if (macroFromConfig != null) {
|
|
||||||
keys = macroFromConfig.split(" ");
|
|
||||||
this.macro = true;
|
|
||||||
} else {
|
|
||||||
throw new JSONException("All keys have to specify either key or macro");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < keys.length; i++) {
|
|
||||||
keys[i] = ExtraKeysInfo.replaceAlias(keys[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.key = TextUtils.join(" ", keys);
|
|
||||||
|
|
||||||
String displayFromConfig = config.optString("display", null);
|
|
||||||
if (displayFromConfig != null) {
|
|
||||||
this.display = displayFromConfig;
|
|
||||||
} else {
|
|
||||||
this.display = Arrays.stream(keys)
|
|
||||||
.map(key -> charDisplayMap.get(key, key))
|
|
||||||
.collect(Collectors.joining(" "));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.popup = popup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getKey() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMacro() {
|
|
||||||
return macro;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDisplay() {
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public ExtraKeyButton getPopup() {
|
|
||||||
return popup;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,253 +0,0 @@
|
|||||||
package com.termux.app.terminal.extrakeys;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
public class ExtraKeysInfo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Matrix of buttons displayed
|
|
||||||
*/
|
|
||||||
private final ExtraKeyButton[][] buttons;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This corresponds to one of the CharMapDisplay below
|
|
||||||
*/
|
|
||||||
private String style = "default";
|
|
||||||
|
|
||||||
public ExtraKeysInfo(String propertiesInfo, String style) throws JSONException {
|
|
||||||
this.style = style;
|
|
||||||
|
|
||||||
// Convert String propertiesInfo to Array of Arrays
|
|
||||||
JSONArray arr = new JSONArray(propertiesInfo);
|
|
||||||
Object[][] matrix = new Object[arr.length()][];
|
|
||||||
for (int i = 0; i < arr.length(); i++) {
|
|
||||||
JSONArray line = arr.getJSONArray(i);
|
|
||||||
matrix[i] = new Object[line.length()];
|
|
||||||
for (int j = 0; j < line.length(); j++) {
|
|
||||||
matrix[i][j] = line.get(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert matrix to buttons
|
|
||||||
this.buttons = new ExtraKeyButton[matrix.length][];
|
|
||||||
for (int i = 0; i < matrix.length; i++) {
|
|
||||||
this.buttons[i] = new ExtraKeyButton[matrix[i].length];
|
|
||||||
for (int j = 0; j < matrix[i].length; j++) {
|
|
||||||
Object key = matrix[i][j];
|
|
||||||
|
|
||||||
JSONObject jobject = normalizeKeyConfig(key);
|
|
||||||
|
|
||||||
ExtraKeyButton button;
|
|
||||||
|
|
||||||
if(! jobject.has("popup")) {
|
|
||||||
// no popup
|
|
||||||
button = new ExtraKeyButton(getSelectedCharMap(), jobject);
|
|
||||||
} else {
|
|
||||||
// a popup
|
|
||||||
JSONObject popupJobject = normalizeKeyConfig(jobject.get("popup"));
|
|
||||||
ExtraKeyButton popup = new ExtraKeyButton(getSelectedCharMap(), popupJobject);
|
|
||||||
button = new ExtraKeyButton(getSelectedCharMap(), jobject, popup);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.buttons[i][j] = button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* "hello" -> {"key": "hello"}
|
|
||||||
*/
|
|
||||||
private static JSONObject normalizeKeyConfig(Object key) throws JSONException {
|
|
||||||
JSONObject jobject;
|
|
||||||
if(key instanceof String) {
|
|
||||||
jobject = new JSONObject();
|
|
||||||
jobject.put("key", key);
|
|
||||||
} else if(key instanceof JSONObject) {
|
|
||||||
jobject = (JSONObject) key;
|
|
||||||
} else {
|
|
||||||
throw new JSONException("An key in the extra-key matrix must be a string or an object");
|
|
||||||
}
|
|
||||||
return jobject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExtraKeyButton[][] getMatrix() {
|
|
||||||
return buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HashMap that implements Python dict.get(key, default) function.
|
|
||||||
* Default java.util .get(key) is then the same as .get(key, null);
|
|
||||||
*/
|
|
||||||
static class CleverMap<K,V> extends HashMap<K,V> {
|
|
||||||
V get(K key, V defaultValue) {
|
|
||||||
if(containsKey(key))
|
|
||||||
return get(key);
|
|
||||||
else
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CharDisplayMap extends CleverMap<String, String> {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keys are displayed in a natural looking way, like "→" for "RIGHT"
|
|
||||||
*/
|
|
||||||
static final CharDisplayMap classicArrowsDisplay = new CharDisplayMap() {{
|
|
||||||
// classic arrow keys (for ◀ ▶ ▲ ▼ @see arrowVariationDisplay)
|
|
||||||
put("LEFT", "←"); // U+2190 ← LEFTWARDS ARROW
|
|
||||||
put("RIGHT", "→"); // U+2192 → RIGHTWARDS ARROW
|
|
||||||
put("UP", "↑"); // U+2191 ↑ UPWARDS ARROW
|
|
||||||
put("DOWN", "↓"); // U+2193 ↓ DOWNWARDS ARROW
|
|
||||||
}};
|
|
||||||
|
|
||||||
static final CharDisplayMap wellKnownCharactersDisplay = new CharDisplayMap() {{
|
|
||||||
// well known characters // https://en.wikipedia.org/wiki/{Enter_key, Tab_key, Delete_key}
|
|
||||||
put("ENTER", "↲"); // U+21B2 ↲ DOWNWARDS ARROW WITH TIP LEFTWARDS
|
|
||||||
put("TAB", "↹"); // U+21B9 ↹ LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
|
|
||||||
put("BKSP", "⌫"); // U+232B ⌫ ERASE TO THE LEFT sometimes seen and easy to understand
|
|
||||||
put("DEL", "⌦"); // U+2326 ⌦ ERASE TO THE RIGHT not well known but easy to understand
|
|
||||||
put("DRAWER", "☰"); // U+2630 ☰ TRIGRAM FOR HEAVEN not well known but easy to understand
|
|
||||||
put("KEYBOARD", "⌨"); // U+2328 ⌨ KEYBOARD not well known but easy to understand
|
|
||||||
}};
|
|
||||||
|
|
||||||
static final CharDisplayMap lessKnownCharactersDisplay = new CharDisplayMap() {{
|
|
||||||
// https://en.wikipedia.org/wiki/{Home_key, End_key, Page_Up_and_Page_Down_keys}
|
|
||||||
// home key can mean "goto the beginning of line" or "goto first page" depending on context, hence the diagonal
|
|
||||||
put("HOME", "⇱"); // from IEC 9995 // U+21F1 ⇱ NORTH WEST ARROW TO CORNER
|
|
||||||
put("END", "⇲"); // from IEC 9995 // ⇲ // U+21F2 ⇲ SOUTH EAST ARROW TO CORNER
|
|
||||||
put("PGUP", "⇑"); // no ISO character exists, U+21D1 ⇑ UPWARDS DOUBLE ARROW will do the trick
|
|
||||||
put("PGDN", "⇓"); // no ISO character exists, U+21D3 ⇓ DOWNWARDS DOUBLE ARROW will do the trick
|
|
||||||
}};
|
|
||||||
|
|
||||||
static final CharDisplayMap arrowTriangleVariationDisplay = new CharDisplayMap() {{
|
|
||||||
// alternative to classic arrow keys
|
|
||||||
put("LEFT", "◀"); // U+25C0 ◀ BLACK LEFT-POINTING TRIANGLE
|
|
||||||
put("RIGHT", "▶"); // U+25B6 ▶ BLACK RIGHT-POINTING TRIANGLE
|
|
||||||
put("UP", "▲"); // U+25B2 ▲ BLACK UP-POINTING TRIANGLE
|
|
||||||
put("DOWN", "▼"); // U+25BC ▼ BLACK DOWN-POINTING TRIANGLE
|
|
||||||
}};
|
|
||||||
|
|
||||||
static final CharDisplayMap notKnownIsoCharacters = new CharDisplayMap() {{
|
|
||||||
// Control chars that are more clear as text // https://en.wikipedia.org/wiki/{Function_key, Alt_key, Control_key, Esc_key}
|
|
||||||
// put("FN", "FN"); // no ISO character exists
|
|
||||||
put("CTRL", "⎈"); // ISO character "U+2388 ⎈ HELM SYMBOL" is unknown to people and never printed on computers, however "U+25C7 ◇ WHITE DIAMOND" is a nice presentation, and "^" for terminal app and mac is often used
|
|
||||||
put("ALT", "⎇"); // ISO character "U+2387 ⎇ ALTERNATIVE KEY SYMBOL'" is unknown to people and only printed as the Option key "⌥" on Mac computer
|
|
||||||
put("ESC", "⎋"); // ISO character "U+238B ⎋ BROKEN CIRCLE WITH NORTHWEST ARROW" is unknown to people and not often printed on computers
|
|
||||||
}};
|
|
||||||
|
|
||||||
static final CharDisplayMap nicerLookingDisplay = new CharDisplayMap() {{
|
|
||||||
// nicer looking for most cases
|
|
||||||
put("-", "―"); // U+2015 ― HORIZONTAL BAR
|
|
||||||
}};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multiple maps are available to quickly change
|
|
||||||
* the style of the keys.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some classic symbols everybody knows
|
|
||||||
*/
|
|
||||||
private static final CharDisplayMap defaultCharDisplay = new CharDisplayMap() {{
|
|
||||||
putAll(classicArrowsDisplay);
|
|
||||||
putAll(wellKnownCharactersDisplay);
|
|
||||||
putAll(nicerLookingDisplay);
|
|
||||||
// all other characters are displayed as themselves
|
|
||||||
}};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classic symbols and less known symbols
|
|
||||||
*/
|
|
||||||
private static final CharDisplayMap lotsOfArrowsCharDisplay = new CharDisplayMap() {{
|
|
||||||
putAll(classicArrowsDisplay);
|
|
||||||
putAll(wellKnownCharactersDisplay);
|
|
||||||
putAll(lessKnownCharactersDisplay); // NEW
|
|
||||||
putAll(nicerLookingDisplay);
|
|
||||||
}};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only arrows
|
|
||||||
*/
|
|
||||||
private static final CharDisplayMap arrowsOnlyCharDisplay = new CharDisplayMap() {{
|
|
||||||
putAll(classicArrowsDisplay);
|
|
||||||
// putAll(wellKnownCharactersDisplay); // REMOVED
|
|
||||||
// putAll(lessKnownCharactersDisplay); // REMOVED
|
|
||||||
putAll(nicerLookingDisplay);
|
|
||||||
}};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Full Iso
|
|
||||||
*/
|
|
||||||
private static final CharDisplayMap fullIsoCharDisplay = new CharDisplayMap() {{
|
|
||||||
putAll(classicArrowsDisplay);
|
|
||||||
putAll(wellKnownCharactersDisplay);
|
|
||||||
putAll(lessKnownCharactersDisplay); // NEW
|
|
||||||
putAll(nicerLookingDisplay);
|
|
||||||
putAll(notKnownIsoCharacters); // NEW
|
|
||||||
}};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some people might call our keys differently
|
|
||||||
*/
|
|
||||||
static private final CharDisplayMap controlCharsAliases = new CharDisplayMap() {{
|
|
||||||
put("ESCAPE", "ESC");
|
|
||||||
put("CONTROL", "CTRL");
|
|
||||||
put("RETURN", "ENTER"); // Technically different keys, but most applications won't see the difference
|
|
||||||
put("FUNCTION", "FN");
|
|
||||||
// no alias for ALT
|
|
||||||
|
|
||||||
// Directions are sometimes written as first and last letter for brevety
|
|
||||||
put("LT", "LEFT");
|
|
||||||
put("RT", "RIGHT");
|
|
||||||
put("DN", "DOWN");
|
|
||||||
// put("UP", "UP"); well, "UP" is already two letters
|
|
||||||
|
|
||||||
put("PAGEUP", "PGUP");
|
|
||||||
put("PAGE_UP", "PGUP");
|
|
||||||
put("PAGE UP", "PGUP");
|
|
||||||
put("PAGE-UP", "PGUP");
|
|
||||||
|
|
||||||
// no alias for HOME
|
|
||||||
// no alias for END
|
|
||||||
|
|
||||||
put("PAGEDOWN", "PGDN");
|
|
||||||
put("PAGE_DOWN", "PGDN");
|
|
||||||
put("PAGE-DOWN", "PGDN");
|
|
||||||
|
|
||||||
put("DELETE", "DEL");
|
|
||||||
put("BACKSPACE", "BKSP");
|
|
||||||
|
|
||||||
// easier for writing in termux.properties
|
|
||||||
put("BACKSLASH", "\\");
|
|
||||||
put("QUOTE", "\"");
|
|
||||||
put("APOSTROPHE", "'");
|
|
||||||
}};
|
|
||||||
|
|
||||||
CharDisplayMap getSelectedCharMap() {
|
|
||||||
switch (style) {
|
|
||||||
case "arrows-only":
|
|
||||||
return arrowsOnlyCharDisplay;
|
|
||||||
case "arrows-all":
|
|
||||||
return lotsOfArrowsCharDisplay;
|
|
||||||
case "all":
|
|
||||||
return fullIsoCharDisplay;
|
|
||||||
case "none":
|
|
||||||
return new CharDisplayMap();
|
|
||||||
default:
|
|
||||||
return defaultCharDisplay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the 'controlCharsAliases' mapping to all the strings in *buttons*
|
|
||||||
* Modifies the array, doesn't return a new one.
|
|
||||||
*/
|
|
||||||
public static String replaceAlias(String key) {
|
|
||||||
return controlCharsAliases.get(key, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,382 +0,0 @@
|
|||||||
package com.termux.app.terminal.extrakeys;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.HapticFeedbackConstants;
|
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.GridLayout;
|
|
||||||
import android.widget.PopupWindow;
|
|
||||||
|
|
||||||
import com.termux.R;
|
|
||||||
import com.termux.view.TerminalView;
|
|
||||||
|
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A view showing extra keys (such as Escape, Ctrl, Alt) not normally available on an Android soft
|
|
||||||
* keyboard.
|
|
||||||
*/
|
|
||||||
public final class ExtraKeysView extends GridLayout {
|
|
||||||
|
|
||||||
private static final int TEXT_COLOR = 0xFFFFFFFF;
|
|
||||||
private static final int BUTTON_COLOR = 0x00000000;
|
|
||||||
private static final int INTERESTING_COLOR = 0xFF80DEEA;
|
|
||||||
private static final int BUTTON_PRESSED_COLOR = 0xFF7F7F7F;
|
|
||||||
|
|
||||||
public ExtraKeysView(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final Map<String, Integer> keyCodesForString = new HashMap<String, Integer>() {{
|
|
||||||
put("SPACE", KeyEvent.KEYCODE_SPACE);
|
|
||||||
put("ESC", KeyEvent.KEYCODE_ESCAPE);
|
|
||||||
put("TAB", KeyEvent.KEYCODE_TAB);
|
|
||||||
put("HOME", KeyEvent.KEYCODE_MOVE_HOME);
|
|
||||||
put("END", KeyEvent.KEYCODE_MOVE_END);
|
|
||||||
put("PGUP", KeyEvent.KEYCODE_PAGE_UP);
|
|
||||||
put("PGDN", KeyEvent.KEYCODE_PAGE_DOWN);
|
|
||||||
put("INS", KeyEvent.KEYCODE_INSERT);
|
|
||||||
put("DEL", KeyEvent.KEYCODE_FORWARD_DEL);
|
|
||||||
put("BKSP", KeyEvent.KEYCODE_DEL);
|
|
||||||
put("UP", KeyEvent.KEYCODE_DPAD_UP);
|
|
||||||
put("LEFT", KeyEvent.KEYCODE_DPAD_LEFT);
|
|
||||||
put("RIGHT", KeyEvent.KEYCODE_DPAD_RIGHT);
|
|
||||||
put("DOWN", KeyEvent.KEYCODE_DPAD_DOWN);
|
|
||||||
put("ENTER", KeyEvent.KEYCODE_ENTER);
|
|
||||||
put("F1", KeyEvent.KEYCODE_F1);
|
|
||||||
put("F2", KeyEvent.KEYCODE_F2);
|
|
||||||
put("F3", KeyEvent.KEYCODE_F3);
|
|
||||||
put("F4", KeyEvent.KEYCODE_F4);
|
|
||||||
put("F5", KeyEvent.KEYCODE_F5);
|
|
||||||
put("F6", KeyEvent.KEYCODE_F6);
|
|
||||||
put("F7", KeyEvent.KEYCODE_F7);
|
|
||||||
put("F8", KeyEvent.KEYCODE_F8);
|
|
||||||
put("F9", KeyEvent.KEYCODE_F9);
|
|
||||||
put("F10", KeyEvent.KEYCODE_F10);
|
|
||||||
put("F11", KeyEvent.KEYCODE_F11);
|
|
||||||
put("F12", KeyEvent.KEYCODE_F12);
|
|
||||||
}};
|
|
||||||
|
|
||||||
@SuppressLint("RtlHardcoded")
|
|
||||||
private void sendKey(View view, String keyName, boolean forceCtrlDown, boolean forceLeftAltDown) {
|
|
||||||
TerminalView terminalView = view.findViewById(R.id.terminal_view);
|
|
||||||
if ("KEYBOARD".equals(keyName)) {
|
|
||||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
||||||
imm.toggleSoftInput(0, 0);
|
|
||||||
} else if ("DRAWER".equals(keyName)) {
|
|
||||||
DrawerLayout drawer = view.findViewById(R.id.drawer_layout);
|
|
||||||
drawer.openDrawer(Gravity.LEFT);
|
|
||||||
} else if (keyCodesForString.containsKey(keyName)) {
|
|
||||||
Integer keyCode = keyCodesForString.get(keyName);
|
|
||||||
if (keyCode == null) return;
|
|
||||||
int metaState = 0;
|
|
||||||
if (forceCtrlDown) {
|
|
||||||
metaState |= KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON;
|
|
||||||
}
|
|
||||||
if (forceLeftAltDown) {
|
|
||||||
metaState |= KeyEvent.META_ALT_ON | KeyEvent.META_ALT_LEFT_ON;
|
|
||||||
}
|
|
||||||
KeyEvent keyEvent = new KeyEvent(0, 0, KeyEvent.ACTION_UP, keyCode, 0, metaState);
|
|
||||||
terminalView.onKeyDown(keyCode, keyEvent);
|
|
||||||
} else {
|
|
||||||
// not a control char
|
|
||||||
keyName.codePoints().forEach(codePoint -> {
|
|
||||||
terminalView.inputCodePoint(codePoint, forceCtrlDown, forceLeftAltDown);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendKey(View view, ExtraKeyButton buttonInfo) {
|
|
||||||
if (buttonInfo.isMacro()) {
|
|
||||||
String[] keys = buttonInfo.getKey().split(" ");
|
|
||||||
boolean ctrlDown = false;
|
|
||||||
boolean altDown = false;
|
|
||||||
for (String key : keys) {
|
|
||||||
if ("CTRL".equals(key)) {
|
|
||||||
ctrlDown = true;
|
|
||||||
} else if ("ALT".equals(key)) {
|
|
||||||
altDown = true;
|
|
||||||
} else {
|
|
||||||
sendKey(view, key, ctrlDown, altDown);
|
|
||||||
ctrlDown = false;
|
|
||||||
altDown = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendKey(view, buttonInfo.getKey(), false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SpecialButton {
|
|
||||||
CTRL, ALT, FN
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class SpecialButtonState {
|
|
||||||
boolean isOn = false;
|
|
||||||
boolean isActive = false;
|
|
||||||
List<Button> buttons = new ArrayList<>();
|
|
||||||
|
|
||||||
void setIsActive(boolean value) {
|
|
||||||
isActive = value;
|
|
||||||
buttons.forEach(button -> button.setTextColor(value ? INTERESTING_COLOR : TEXT_COLOR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<SpecialButton, SpecialButtonState> specialButtons = new HashMap<SpecialButton, SpecialButtonState>() {{
|
|
||||||
put(SpecialButton.CTRL, new SpecialButtonState());
|
|
||||||
put(SpecialButton.ALT, new SpecialButtonState());
|
|
||||||
put(SpecialButton.FN, new SpecialButtonState());
|
|
||||||
}};
|
|
||||||
|
|
||||||
private final Set<String> specialButtonsKeys = specialButtons.keySet().stream().map(Enum::name).collect(Collectors.toSet());
|
|
||||||
|
|
||||||
private boolean isSpecialButton(ExtraKeyButton button) {
|
|
||||||
return specialButtonsKeys.contains(button.getKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScheduledExecutorService scheduledExecutor;
|
|
||||||
private PopupWindow popupWindow;
|
|
||||||
private int longPressCount;
|
|
||||||
|
|
||||||
public boolean readSpecialButton(SpecialButton name) {
|
|
||||||
SpecialButtonState state = specialButtons.get(name);
|
|
||||||
if (state == null)
|
|
||||||
throw new RuntimeException("Must be a valid special button (see source)");
|
|
||||||
|
|
||||||
if (!state.isOn || !state.isActive)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
state.setIsActive(false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Button createSpecialButton(String buttonKey, boolean needUpdate) {
|
|
||||||
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonKey));
|
|
||||||
if (state == null) return null;
|
|
||||||
state.isOn = true;
|
|
||||||
Button button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
|
||||||
button.setTextColor(state.isActive ? INTERESTING_COLOR : TEXT_COLOR);
|
|
||||||
if (needUpdate) {
|
|
||||||
state.buttons.add(button);
|
|
||||||
}
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
void popup(View view, ExtraKeyButton extraButton) {
|
|
||||||
int width = view.getMeasuredWidth();
|
|
||||||
int height = view.getMeasuredHeight();
|
|
||||||
Button button;
|
|
||||||
if(isSpecialButton(extraButton)) {
|
|
||||||
button = createSpecialButton(extraButton.getKey(), false);
|
|
||||||
if (button == null) return;
|
|
||||||
} else {
|
|
||||||
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
|
||||||
button.setTextColor(TEXT_COLOR);
|
|
||||||
}
|
|
||||||
button.setText(extraButton.getDisplay());
|
|
||||||
button.setPadding(0, 0, 0, 0);
|
|
||||||
button.setMinHeight(0);
|
|
||||||
button.setMinWidth(0);
|
|
||||||
button.setMinimumWidth(0);
|
|
||||||
button.setMinimumHeight(0);
|
|
||||||
button.setWidth(width);
|
|
||||||
button.setHeight(height);
|
|
||||||
button.setBackgroundColor(BUTTON_PRESSED_COLOR);
|
|
||||||
popupWindow = new PopupWindow(this);
|
|
||||||
popupWindow.setWidth(LayoutParams.WRAP_CONTENT);
|
|
||||||
popupWindow.setHeight(LayoutParams.WRAP_CONTENT);
|
|
||||||
popupWindow.setContentView(button);
|
|
||||||
popupWindow.setOutsideTouchable(true);
|
|
||||||
popupWindow.setFocusable(false);
|
|
||||||
popupWindow.showAsDropDown(view, 0, -2 * height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General util function to compute the longest column length in a matrix.
|
|
||||||
*/
|
|
||||||
static int maximumLength(Object[][] matrix) {
|
|
||||||
int m = 0;
|
|
||||||
for (Object[] row : matrix)
|
|
||||||
m = Math.max(m, row.length);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reload the view given parameters in termux.properties
|
|
||||||
*
|
|
||||||
* @param infos matrix as defined in termux.properties extrakeys
|
|
||||||
* Can Contain The Strings CTRL ALT TAB FN ENTER LEFT RIGHT UP DOWN or normal strings
|
|
||||||
* Some aliases are possible like RETURN for ENTER, LT for LEFT and more (@see controlCharsAliases for the whole list).
|
|
||||||
* Any string of length > 1 in total Uppercase will print a warning
|
|
||||||
*
|
|
||||||
* Examples:
|
|
||||||
* "ENTER" will trigger the ENTER keycode
|
|
||||||
* "LEFT" will trigger the LEFT keycode and be displayed as "←"
|
|
||||||
* "→" will input a "→" character
|
|
||||||
* "−" will input a "−" character
|
|
||||||
* "-_-" will input the string "-_-"
|
|
||||||
*/
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
public void reload(ExtraKeysInfo infos) {
|
|
||||||
if(infos == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(SpecialButtonState state : specialButtons.values())
|
|
||||||
state.buttons = new ArrayList<>();
|
|
||||||
|
|
||||||
removeAllViews();
|
|
||||||
|
|
||||||
ExtraKeyButton[][] buttons = infos.getMatrix();
|
|
||||||
|
|
||||||
setRowCount(buttons.length);
|
|
||||||
setColumnCount(maximumLength(buttons));
|
|
||||||
|
|
||||||
for (int row = 0; row < buttons.length; row++) {
|
|
||||||
for (int col = 0; col < buttons[row].length; col++) {
|
|
||||||
final ExtraKeyButton buttonInfo = buttons[row][col];
|
|
||||||
|
|
||||||
Button button;
|
|
||||||
if(isSpecialButton(buttonInfo)) {
|
|
||||||
button = createSpecialButton(buttonInfo.getKey(), true);
|
|
||||||
if (button == null) return;
|
|
||||||
} else {
|
|
||||||
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.setText(buttonInfo.getDisplay());
|
|
||||||
button.setTextColor(TEXT_COLOR);
|
|
||||||
button.setPadding(0, 0, 0, 0);
|
|
||||||
|
|
||||||
final Button finalButton = button;
|
|
||||||
button.setOnClickListener(v -> {
|
|
||||||
if (Settings.System.getInt(getContext().getContentResolver(),
|
|
||||||
Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) != 0) {
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 28) {
|
|
||||||
finalButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
|
||||||
} else {
|
|
||||||
// Perform haptic feedback only if no total silence mode enabled.
|
|
||||||
if (Settings.Global.getInt(getContext().getContentResolver(), "zen_mode", 0) != 2) {
|
|
||||||
finalButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
View root = getRootView();
|
|
||||||
if (isSpecialButton(buttonInfo)) {
|
|
||||||
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonInfo.getKey()));
|
|
||||||
if (state == null) return;
|
|
||||||
state.setIsActive(!state.isActive);
|
|
||||||
} else {
|
|
||||||
sendKey(root, buttonInfo);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
button.setOnTouchListener((v, event) -> {
|
|
||||||
final View root = getRootView();
|
|
||||||
switch (event.getAction()) {
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
|
||||||
longPressCount = 0;
|
|
||||||
v.setBackgroundColor(BUTTON_PRESSED_COLOR);
|
|
||||||
if (Arrays.asList("UP", "DOWN", "LEFT", "RIGHT", "BKSP", "DEL").contains(buttonInfo.getKey())) {
|
|
||||||
// autorepeat
|
|
||||||
scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
|
|
||||||
scheduledExecutor.scheduleWithFixedDelay(() -> {
|
|
||||||
longPressCount++;
|
|
||||||
sendKey(root, buttonInfo);
|
|
||||||
}, 400, 80, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
if (buttonInfo.getPopup() != null) {
|
|
||||||
if (popupWindow == null && event.getY() < 0) {
|
|
||||||
if (scheduledExecutor != null) {
|
|
||||||
scheduledExecutor.shutdownNow();
|
|
||||||
scheduledExecutor = null;
|
|
||||||
}
|
|
||||||
v.setBackgroundColor(BUTTON_COLOR);
|
|
||||||
popup(v, buttonInfo.getPopup());
|
|
||||||
}
|
|
||||||
if (popupWindow != null && event.getY() > 0) {
|
|
||||||
v.setBackgroundColor(BUTTON_PRESSED_COLOR);
|
|
||||||
popupWindow.dismiss();
|
|
||||||
popupWindow = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_CANCEL:
|
|
||||||
v.setBackgroundColor(BUTTON_COLOR);
|
|
||||||
if (scheduledExecutor != null) {
|
|
||||||
scheduledExecutor.shutdownNow();
|
|
||||||
scheduledExecutor = null;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case MotionEvent.ACTION_UP:
|
|
||||||
v.setBackgroundColor(BUTTON_COLOR);
|
|
||||||
if (scheduledExecutor != null) {
|
|
||||||
scheduledExecutor.shutdownNow();
|
|
||||||
scheduledExecutor = null;
|
|
||||||
}
|
|
||||||
if (longPressCount == 0 || popupWindow != null) {
|
|
||||||
if (popupWindow != null) {
|
|
||||||
popupWindow.setContentView(null);
|
|
||||||
popupWindow.dismiss();
|
|
||||||
popupWindow = null;
|
|
||||||
if (buttonInfo.getPopup() != null) {
|
|
||||||
if (isSpecialButton(buttonInfo.getPopup())) {
|
|
||||||
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonInfo.getPopup().getKey()));
|
|
||||||
if (state == null) return true;
|
|
||||||
state.setIsActive(!state.isActive);
|
|
||||||
} else {
|
|
||||||
sendKey(root, buttonInfo.getPopup());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v.performClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
LayoutParams param = new GridLayout.LayoutParams();
|
|
||||||
param.width = 0;
|
|
||||||
param.height = 0;
|
|
||||||
param.setMargins(0, 0, 0, 0);
|
|
||||||
param.columnSpec = GridLayout.spec(col, GridLayout.FILL, 1.f);
|
|
||||||
param.rowSpec = GridLayout.spec(row, GridLayout.FILL, 1.f);
|
|
||||||
button.setLayoutParams(param);
|
|
||||||
|
|
||||||
addView(button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,80 +0,0 @@
|
|||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:fitsSystemWindows="true">
|
|
||||||
|
|
||||||
<androidx.drawerlayout.widget.DrawerLayout
|
|
||||||
android:id="@+id/drawer_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_above="@+id/viewpager"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.termux.view.TerminalView
|
|
||||||
android:id="@+id/terminal_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginRight="3dp"
|
|
||||||
android:layout_marginLeft="3dp"
|
|
||||||
android:focusableInTouchMode="true"
|
|
||||||
android:scrollbarThumbVertical="@drawable/terminal_scroll_shape"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
android:autofillHints="password" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/left_drawer"
|
|
||||||
android:layout_width="240dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="start"
|
|
||||||
android:background="@android:color/white"
|
|
||||||
android:choiceMode="singleChoice"
|
|
||||||
android:divider="@android:color/transparent"
|
|
||||||
android:dividerHeight="0dp"
|
|
||||||
android:descendantFocusability="blocksDescendants"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ListView
|
|
||||||
android:id="@+id/left_drawer_list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_gravity="top"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:choiceMode="singleChoice"
|
|
||||||
android:longClickable="true" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
style="?android:attr/buttonBarStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/toggle_keyboard_button"
|
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/toggle_soft_keyboard" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/new_session_button"
|
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/new_session" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
|
||||||
android:id="@+id/viewpager"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="37.5dp"
|
|
||||||
android:background="@android:drawable/screen_background_dark_transparent"
|
|
||||||
android:layout_alignParentBottom="true" />
|
|
||||||
</RelativeLayout>
|
|
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<com.termux.app.terminal.extrakeys.ExtraKeysView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/extra_keys"
|
|
||||||
style="?android:attr/buttonBarStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:orientation="horizontal" />
|
|
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/text_input"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:imeOptions="actionSend|flagNoFullscreen"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:inputType="text"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:textColorHighlight="@android:color/darker_gray"
|
|
||||||
android:paddingTop="0dp"
|
|
||||||
android:textCursorDrawable="@null"
|
|
||||||
android:paddingBottom="0dp"
|
|
||||||
tools:ignore="LabelFor" />
|
|
@@ -1,9 +0,0 @@
|
|||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/row_line"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
|
||||||
android:background="@drawable/selected_session_background"
|
|
||||||
android:ellipsize="marquee"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:padding="6dip"
|
|
||||||
android:textSize="14sp" />
|
|
@@ -1,10 +0,0 @@
|
|||||||
package com.termux.terminal;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public final class EmulatorDebug {
|
|
||||||
|
|
||||||
/** The tag to use with {@link Log}. */
|
|
||||||
public static final String LOG_TAG = "termux";
|
|
||||||
|
|
||||||
}
|
|
Reference in New Issue
Block a user