208 lines
8.0 KiB
Java
208 lines
8.0 KiB
Java
package com.termux.app;
|
|
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
import android.preference.PreferenceManager;
|
|
import android.support.annotation.IntDef;
|
|
import android.util.Log;
|
|
import android.util.TypedValue;
|
|
import android.widget.Toast;
|
|
|
|
import com.termux.terminal.TerminalSession;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Properties;
|
|
|
|
final class TermuxPreferences {
|
|
|
|
@IntDef({BELL_VIBRATE, BELL_BEEP, BELL_IGNORE})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface AsciiBellBehaviour {
|
|
}
|
|
|
|
static final int BELL_VIBRATE = 1;
|
|
static final int BELL_BEEP = 2;
|
|
static final int BELL_IGNORE = 3;
|
|
|
|
private final int MIN_FONTSIZE;
|
|
private static final int MAX_FONTSIZE = 256;
|
|
|
|
private static final String FULLSCREEN_KEY = "fullscreen";
|
|
private static final String SHOW_EXTRA_KEYS_KEY = "show_extra_keys";
|
|
private static final String FONTSIZE_KEY = "fontsize";
|
|
private static final String CURRENT_SESSION_KEY = "current_session";
|
|
private static final String SHOW_WELCOME_DIALOG_KEY = "intro_dialog";
|
|
|
|
private boolean mFullScreen;
|
|
private int mFontSize;
|
|
|
|
@AsciiBellBehaviour
|
|
int mBellBehaviour = BELL_VIBRATE;
|
|
|
|
boolean mBackIsEscape;
|
|
boolean mShowExtraKeys;
|
|
|
|
TermuxPreferences(Context context) {
|
|
reloadFromProperties(context);
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
float dipInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, context.getResources().getDisplayMetrics());
|
|
|
|
// This is a bit arbitrary and sub-optimal. We want to give a sensible default for minimum font size
|
|
// to prevent invisible text due to zoom be mistake:
|
|
MIN_FONTSIZE = (int) (4f * dipInPixels);
|
|
|
|
mFullScreen = prefs.getBoolean(FULLSCREEN_KEY, false);
|
|
mShowExtraKeys = prefs.getBoolean(SHOW_EXTRA_KEYS_KEY, false);
|
|
|
|
// http://www.google.com/design/spec/style/typography.html#typography-line-height
|
|
int defaultFontSize = Math.round(12 * dipInPixels);
|
|
// Make it divisible by 2 since that is the minimal adjustment step:
|
|
if (defaultFontSize % 2 == 1) defaultFontSize--;
|
|
|
|
try {
|
|
mFontSize = Integer.parseInt(prefs.getString(FONTSIZE_KEY, Integer.toString(defaultFontSize)));
|
|
} catch (NumberFormatException | ClassCastException e) {
|
|
mFontSize = defaultFontSize;
|
|
}
|
|
mFontSize = Math.max(MIN_FONTSIZE, Math.min(mFontSize, MAX_FONTSIZE));
|
|
}
|
|
|
|
boolean isFullScreen() {
|
|
return mFullScreen;
|
|
}
|
|
|
|
void setFullScreen(Context context, boolean newValue) {
|
|
mFullScreen = newValue;
|
|
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(FULLSCREEN_KEY, newValue).apply();
|
|
}
|
|
|
|
boolean isShowExtraKeys() {
|
|
return mShowExtraKeys;
|
|
}
|
|
|
|
boolean toggleShowExtraKeys(Context context) {
|
|
mShowExtraKeys = !mShowExtraKeys;
|
|
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(SHOW_EXTRA_KEYS_KEY, mShowExtraKeys).apply();
|
|
return mShowExtraKeys;
|
|
}
|
|
|
|
int getFontSize() {
|
|
return mFontSize;
|
|
}
|
|
|
|
void changeFontSize(Context context, boolean increase) {
|
|
mFontSize += (increase ? 1 : -1) * 2;
|
|
mFontSize = Math.max(MIN_FONTSIZE, Math.min(mFontSize, MAX_FONTSIZE));
|
|
|
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
prefs.edit().putString(FONTSIZE_KEY, Integer.toString(mFontSize)).apply();
|
|
}
|
|
|
|
static void storeCurrentSession(Context context, TerminalSession session) {
|
|
PreferenceManager.getDefaultSharedPreferences(context).edit().putString(TermuxPreferences.CURRENT_SESSION_KEY, session.mHandle).commit();
|
|
}
|
|
|
|
static TerminalSession getCurrentSession(TermuxActivity context) {
|
|
String sessionHandle = PreferenceManager.getDefaultSharedPreferences(context).getString(TermuxPreferences.CURRENT_SESSION_KEY, "");
|
|
for (int i = 0, len = context.mTermService.getSessions().size(); i < len; i++) {
|
|
TerminalSession session = context.mTermService.getSessions().get(i);
|
|
if (session.mHandle.equals(sessionHandle)) return session;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static boolean isShowWelcomeDialog(Context context) {
|
|
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(SHOW_WELCOME_DIALOG_KEY, true);
|
|
}
|
|
|
|
public static void disableWelcomeDialog(Context context) {
|
|
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(SHOW_WELCOME_DIALOG_KEY, false).apply();
|
|
}
|
|
|
|
public void reloadFromProperties(Context context) {
|
|
try {
|
|
File propsFile = new File(TermuxService.HOME_PATH + "/.termux/termux.properties");
|
|
if (!propsFile.exists())
|
|
propsFile = new File(TermuxService.HOME_PATH + "/.config/termux/termux.properties");
|
|
|
|
Properties props = new Properties();
|
|
if (propsFile.isFile() && propsFile.canRead()) {
|
|
try (FileInputStream in = new FileInputStream(propsFile)) {
|
|
props.load(in);
|
|
}
|
|
}
|
|
|
|
switch (props.getProperty("bell-character", "vibrate")) {
|
|
case "beep":
|
|
mBellBehaviour = BELL_BEEP;
|
|
break;
|
|
case "ignore":
|
|
mBellBehaviour = BELL_IGNORE;
|
|
break;
|
|
default: // "vibrate".
|
|
mBellBehaviour = BELL_VIBRATE;
|
|
break;
|
|
}
|
|
|
|
mBackIsEscape = "escape".equals(props.getProperty("back-key", "back"));
|
|
|
|
shortcuts.clear();
|
|
parseAction("shortcut.create-session", SHORTCUT_ACTION_CREATE_SESSION, props);
|
|
parseAction("shortcut.next-session", SHORTCUT_ACTION_NEXT_SESSION, props);
|
|
parseAction("shortcut.previous-session", SHORTCUT_ACTION_PREVIOUS_SESSION, props);
|
|
parseAction("shortcut.rename-session", SHORTCUT_ACTION_RENAME_SESSION, props);
|
|
} catch (Exception e) {
|
|
Toast.makeText(context, "Error loading properties: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
|
Log.e("termux", "Error loading props", e);
|
|
}
|
|
}
|
|
|
|
public static final int SHORTCUT_ACTION_CREATE_SESSION = 1;
|
|
public static final int SHORTCUT_ACTION_NEXT_SESSION = 2;
|
|
public static final int SHORTCUT_ACTION_PREVIOUS_SESSION = 3;
|
|
public static final int SHORTCUT_ACTION_RENAME_SESSION = 4;
|
|
|
|
public final static class KeyboardShortcut {
|
|
|
|
public KeyboardShortcut(int codePoint, int shortcutAction) {
|
|
this.codePoint = codePoint;
|
|
this.shortcutAction = shortcutAction;
|
|
}
|
|
|
|
final int codePoint;
|
|
final int shortcutAction;
|
|
}
|
|
|
|
final List<KeyboardShortcut> shortcuts = new ArrayList<>();
|
|
|
|
private void parseAction(String name, int shortcutAction, Properties props) {
|
|
String value = props.getProperty(name);
|
|
if (value == null) return;
|
|
String[] parts = value.toLowerCase().trim().split("\\+");
|
|
String input = parts.length == 2 ? parts[1].trim() : null;
|
|
if (!(parts.length == 2 && parts[0].trim().equals("ctrl")) || input.isEmpty() || input.length() > 2) {
|
|
Log.e("termux", "Keyboard shortcut '" + name + "' is not Ctrl+<something>");
|
|
return;
|
|
}
|
|
|
|
char c = input.charAt(0);
|
|
int codePoint = c;
|
|
if (Character.isLowSurrogate(c)) {
|
|
if (input.length() != 2 || Character.isHighSurrogate(input.charAt(1))) {
|
|
Log.e("termux", "Keyboard shortcut '" + name + "' is not Ctrl+<something>");
|
|
return;
|
|
} else {
|
|
codePoint = Character.toCodePoint(input.charAt(1), c);
|
|
}
|
|
}
|
|
shortcuts.add(new KeyboardShortcut(codePoint, shortcutAction));
|
|
}
|
|
|
|
}
|