mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-05 02:05:25 +08:00
Move terminal input related classed to com.termux.app.input package
This commit is contained in:
@@ -48,6 +48,9 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.termux.R;
|
import com.termux.R;
|
||||||
import com.termux.app.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY;
|
import com.termux.app.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY;
|
||||||
|
import com.termux.app.input.BellHandler;
|
||||||
|
import com.termux.app.input.extrakeys.ExtraKeysView;
|
||||||
|
import com.termux.app.input.FullScreenWorkAround;
|
||||||
import com.termux.terminal.EmulatorDebug;
|
import com.termux.terminal.EmulatorDebug;
|
||||||
import com.termux.terminal.TerminalColors;
|
import com.termux.terminal.TerminalColors;
|
||||||
import com.termux.terminal.TerminalSession;
|
import com.termux.terminal.TerminalSession;
|
||||||
@@ -455,7 +458,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
mBellSoundPool.play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f);
|
mBellSoundPool.play(mBellSoundId, 1.f, 1.f, 1, 0, 1.f);
|
||||||
break;
|
break;
|
||||||
case TermuxPreferences.BELL_VIBRATE:
|
case TermuxPreferences.BELL_VIBRATE:
|
||||||
BellUtil.getInstance(TermuxActivity.this).doBell();
|
BellHandler.getInstance(TermuxActivity.this).doBell();
|
||||||
break;
|
break;
|
||||||
case TermuxPreferences.BELL_IGNORE:
|
case TermuxPreferences.BELL_IGNORE:
|
||||||
// Ignore the bell character.
|
// Ignore the bell character.
|
||||||
|
@@ -8,6 +8,7 @@ import android.view.KeyEvent;
|
|||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
|
import com.termux.app.input.extrakeys.ExtraKeysView;
|
||||||
import com.termux.terminal.KeyHandler;
|
import com.termux.terminal.KeyHandler;
|
||||||
import com.termux.terminal.TerminalEmulator;
|
import com.termux.terminal.TerminalEmulator;
|
||||||
import com.termux.terminal.TerminalSession;
|
import com.termux.terminal.TerminalSession;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package com.termux.app;
|
package com.termux.app.input;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -6,15 +6,15 @@ import android.os.Looper;
|
|||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
|
|
||||||
public class BellUtil {
|
public class BellHandler {
|
||||||
private static BellUtil instance = null;
|
private static BellHandler instance = null;
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
public static BellUtil getInstance(Context context) {
|
public static BellHandler getInstance(Context context) {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new BellUtil((Vibrator) context.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE));
|
instance = new BellHandler((Vibrator) context.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ public class BellUtil {
|
|||||||
private long lastBell = 0;
|
private long lastBell = 0;
|
||||||
private final Runnable bellRunnable;
|
private final Runnable bellRunnable;
|
||||||
|
|
||||||
private BellUtil(final Vibrator vibrator) {
|
private BellHandler(final Vibrator vibrator) {
|
||||||
bellRunnable = new Runnable() {
|
bellRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
@@ -1,9 +1,11 @@
|
|||||||
package com.termux.app;
|
package com.termux.app.input;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.termux.app.TermuxActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Work around for fullscreen mode in Termux to fix ExtraKeysView not being visible.
|
* Work around for fullscreen mode in Termux to fix ExtraKeysView not being visible.
|
||||||
* This class is derived from:
|
* This class is derived from:
|
||||||
@@ -13,11 +15,11 @@ import android.view.ViewGroup;
|
|||||||
* For more information, see https://issuetracker.google.com/issues/36911528
|
* For more information, see https://issuetracker.google.com/issues/36911528
|
||||||
*/
|
*/
|
||||||
public class FullScreenWorkAround {
|
public class FullScreenWorkAround {
|
||||||
private View mChildOfContent;
|
private final View mChildOfContent;
|
||||||
private int mUsableHeightPrevious;
|
private int mUsableHeightPrevious;
|
||||||
private ViewGroup.LayoutParams mViewGroupLayoutParams;
|
private final ViewGroup.LayoutParams mViewGroupLayoutParams;
|
||||||
|
|
||||||
private int mNavBarHeight;
|
private final int mNavBarHeight;
|
||||||
|
|
||||||
|
|
||||||
public static void apply(TermuxActivity activity) {
|
public static void apply(TermuxActivity activity) {
|
13
app/src/main/java/com/termux/app/input/KeyboardShortcut.java
Normal file
13
app/src/main/java/com/termux/app/input/KeyboardShortcut.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package com.termux.app.input;
|
||||||
|
|
||||||
|
public class KeyboardShortcut {
|
||||||
|
|
||||||
|
public final int codePoint;
|
||||||
|
public final int shortcutAction;
|
||||||
|
|
||||||
|
public KeyboardShortcut(int codePoint, int shortcutAction) {
|
||||||
|
this.codePoint = codePoint;
|
||||||
|
this.shortcutAction = shortcutAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,92 @@
|
|||||||
|
package com.termux.app.input.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,31 +1,24 @@
|
|||||||
package com.termux.app;
|
package com.termux.app.input.extrakeys;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ExtraKeysInfos {
|
public class ExtraKeysInfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matrix of buttons displayed
|
* Matrix of buttons displayed
|
||||||
*/
|
*/
|
||||||
private ExtraKeyButton[][] buttons;
|
private final ExtraKeyButton[][] buttons;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This corresponds to one of the CharMapDisplay below
|
* This corresponds to one of the CharMapDisplay below
|
||||||
*/
|
*/
|
||||||
private String style = "default";
|
private String style = "default";
|
||||||
|
|
||||||
public ExtraKeysInfos(String propertiesInfo, String style) throws JSONException {
|
public ExtraKeysInfo(String propertiesInfo, String style) throws JSONException {
|
||||||
this.style = style;
|
this.style = style;
|
||||||
|
|
||||||
// Convert String propertiesInfo to Array of Arrays
|
// Convert String propertiesInfo to Array of Arrays
|
||||||
@@ -151,7 +144,7 @@ public class ExtraKeysInfos {
|
|||||||
put("-", "―"); // U+2015 ― HORIZONTAL BAR
|
put("-", "―"); // U+2015 ― HORIZONTAL BAR
|
||||||
}};
|
}};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Multiple maps are available to quickly change
|
* Multiple maps are available to quickly change
|
||||||
* the style of the keys.
|
* the style of the keys.
|
||||||
*/
|
*/
|
||||||
@@ -258,83 +251,3 @@ public class ExtraKeysInfos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 String key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the key is a macro, i.e. a sequence of keys separated by space.
|
|
||||||
*/
|
|
||||||
private boolean macro;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The text that will be shown on the button.
|
|
||||||
*/
|
|
||||||
private String display;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The information of the popup (triggered by swipe up).
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private ExtraKeyButton popup = null;
|
|
||||||
|
|
||||||
public ExtraKeyButton(ExtraKeysInfos.CharDisplayMap charDisplayMap, JSONObject config) throws JSONException {
|
|
||||||
this(charDisplayMap, config, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExtraKeyButton(ExtraKeysInfos.CharDisplayMap charDisplayMap, JSONObject config, 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] = ExtraKeysInfos.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,4 +1,4 @@
|
|||||||
package com.termux.app;
|
package com.termux.app.input.extrakeys;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -78,6 +78,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
put("F12", KeyEvent.KEYCODE_F12);
|
put("F12", KeyEvent.KEYCODE_F12);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
@SuppressLint("RtlHardcoded")
|
||||||
private void sendKey(View view, String keyName, boolean forceCtrlDown, boolean forceLeftAltDown) {
|
private void sendKey(View view, String keyName, boolean forceCtrlDown, boolean forceLeftAltDown) {
|
||||||
TerminalView terminalView = view.findViewById(R.id.terminal_view);
|
TerminalView terminalView = view.findViewById(R.id.terminal_view);
|
||||||
if ("KEYBOARD".equals(keyName)) {
|
if ("KEYBOARD".equals(keyName)) {
|
||||||
@@ -87,7 +88,8 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
DrawerLayout drawer = view.findViewById(R.id.drawer_layout);
|
DrawerLayout drawer = view.findViewById(R.id.drawer_layout);
|
||||||
drawer.openDrawer(Gravity.LEFT);
|
drawer.openDrawer(Gravity.LEFT);
|
||||||
} else if (keyCodesForString.containsKey(keyName)) {
|
} else if (keyCodesForString.containsKey(keyName)) {
|
||||||
int keyCode = keyCodesForString.get(keyName);
|
Integer keyCode = keyCodesForString.get(keyName);
|
||||||
|
if (keyCode == null) return;
|
||||||
int metaState = 0;
|
int metaState = 0;
|
||||||
if (forceCtrlDown) {
|
if (forceCtrlDown) {
|
||||||
metaState |= KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON;
|
metaState |= KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON;
|
||||||
@@ -172,6 +174,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
|
|
||||||
private Button createSpecialButton(String buttonKey, boolean needUpdate) {
|
private Button createSpecialButton(String buttonKey, boolean needUpdate) {
|
||||||
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonKey));
|
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonKey));
|
||||||
|
if (state == null) return null;
|
||||||
state.isOn = true;
|
state.isOn = true;
|
||||||
Button button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
Button button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
||||||
button.setTextColor(state.isActive ? INTERESTING_COLOR : TEXT_COLOR);
|
button.setTextColor(state.isActive ? INTERESTING_COLOR : TEXT_COLOR);
|
||||||
@@ -187,6 +190,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
Button button;
|
Button button;
|
||||||
if(isSpecialButton(extraButton)) {
|
if(isSpecialButton(extraButton)) {
|
||||||
button = createSpecialButton(extraButton.getKey(), false);
|
button = createSpecialButton(extraButton.getKey(), false);
|
||||||
|
if (button == null) return;
|
||||||
} else {
|
} else {
|
||||||
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
||||||
button.setTextColor(TEXT_COLOR);
|
button.setTextColor(TEXT_COLOR);
|
||||||
@@ -235,7 +239,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
* "-_-" will input the string "-_-"
|
* "-_-" will input the string "-_-"
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
void reload(ExtraKeysInfos infos) {
|
public void reload(ExtraKeysInfo infos) {
|
||||||
if(infos == null)
|
if(infos == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -256,6 +260,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
Button button;
|
Button button;
|
||||||
if(isSpecialButton(buttonInfo)) {
|
if(isSpecialButton(buttonInfo)) {
|
||||||
button = createSpecialButton(buttonInfo.getKey(), true);
|
button = createSpecialButton(buttonInfo.getKey(), true);
|
||||||
|
if (button == null) return;
|
||||||
} else {
|
} else {
|
||||||
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
||||||
}
|
}
|
||||||
@@ -282,6 +287,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
View root = getRootView();
|
View root = getRootView();
|
||||||
if (isSpecialButton(buttonInfo)) {
|
if (isSpecialButton(buttonInfo)) {
|
||||||
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonInfo.getKey()));
|
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonInfo.getKey()));
|
||||||
|
if (state == null) return;
|
||||||
state.setIsActive(!state.isActive);
|
state.setIsActive(!state.isActive);
|
||||||
} else {
|
} else {
|
||||||
sendKey(root, buttonInfo);
|
sendKey(root, buttonInfo);
|
||||||
@@ -343,6 +349,7 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
if (buttonInfo.getPopup() != null) {
|
if (buttonInfo.getPopup() != null) {
|
||||||
if (isSpecialButton(buttonInfo.getPopup())) {
|
if (isSpecialButton(buttonInfo.getPopup())) {
|
||||||
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonInfo.getPopup().getKey()));
|
SpecialButtonState state = specialButtons.get(SpecialButton.valueOf(buttonInfo.getPopup().getKey()));
|
||||||
|
if (state == null) return true;
|
||||||
state.setIsActive(!state.isActive);
|
state.setIsActive(!state.isActive);
|
||||||
} else {
|
} else {
|
||||||
sendKey(root, buttonInfo.getPopup());
|
sendKey(root, buttonInfo.getPopup());
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.termux.app.ExtraKeysView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.termux.app.input.extrakeys.ExtraKeysView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/extra_keys"
|
android:id="@+id/extra_keys"
|
||||||
style="?android:attr/buttonBarStyle"
|
style="?android:attr/buttonBarStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
Reference in New Issue
Block a user