- Added the input devices option.
- Added the acceleration option.
- Added the bubble option for the built-in X11 display.
- Fixed the freeze when forcing a shutdown of all virtual machines.
- Fixed the black screen for the X11 display.
- Updated Termux:X11 (Nightly 20260729).
- Bugs fixed.
This commit is contained in:
An Bui 2026-07-29 15:07:05 +07:00
parent 5f49e19105
commit f41fd5f2fc
31 changed files with 970 additions and 60 deletions

View file

@ -13,8 +13,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 155
versionName "4.4.8"
versionCode 156
versionName "4.4.9"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

View file

@ -166,6 +166,9 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("battery", current.battery);
vmConfigMap.put("mouse", current.mouse);
vmConfigMap.put("keyboard", current.keyboard);
boolean isUsingDiskInQemuExtraParams = VMManager.isHaveADisk(current.itemExtra);
if (FileUtils.isFileExists(current.itemPath)) {
@ -219,6 +222,8 @@ public class ExportRomActivity extends AppCompatActivity {
vmConfigMap.put("isUseUefi", current.isUseUefi);
vmConfigMap.put("isUseDefaultBios", current.isUseDefaultBios);
vmConfigMap.put("accel", current.accel);
vmConfigMap.put("qemu", VmFileManager.pathToTextMark(this, current.vmID, current.itemExtra));
vmConfigMap.put("arch", current.itemArch);

View file

@ -131,6 +131,17 @@ public class StartVM {
}
}
String inputDevicesParams = "";
String mouse = Objects.requireNonNull(VMCreatorSelector.getMouse(activity, vmData.mouse).get("value")).toString();
if (!mouse.isEmpty()) {
inputDevicesParams += " -device " + mouse;
}
String keyboard = Objects.requireNonNull(VMCreatorSelector.getKeyboard(activity, vmData.keyboard).get("value")).toString();
if (!keyboard.isEmpty()) {
inputDevicesParams += " -device " + keyboard;
}
if (!inputDevicesParams.isEmpty() && !ParamManager.hasUsb(extraParams)) inputDevicesParams = " -usb" + inputDevicesParams;
String graphicsParams = "";
String graphics = Objects.requireNonNull(VMCreatorSelector.getGraphicsCard(activity, vmData.graphicCard).get("value")).toString();
if (!graphics.isEmpty()) {
@ -172,7 +183,13 @@ public class StartVM {
bootParams = " -boot " + bootFromParams + (!bootFromParams.isEmpty() && !showBootMenuParams.isEmpty() ? "," : "") + showBootMenuParams + " ";
}
extraParams = machineParams + cpuParams + memoryParams + bootParams + graphicsParams + networkParams + soundParams + " " + extraParams;
String accelParams = "";
String accel = Objects.requireNonNull(VMCreatorSelector.getAccel(activity, vmData.accel).get("value")).toString();
if (!accel.isEmpty()) {
accelParams = " -accel " + ((vmData.accel > 1 && !DeviceUtils.is64bit()) ? Objects.requireNonNull(VMCreatorSelector.getAccel(activity, 1).get("value")).toString() : accel);
}
extraParams = machineParams + inputDevicesParams + cpuParams + memoryParams + bootParams + graphicsParams + networkParams + soundParams + accelParams + " " + extraParams;
return env(activity, extraParams, vmData.itemPath, false);
}

View file

@ -45,6 +45,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.PropertyPermission;
import java.util.Random;
public class VMManager {
@ -904,8 +905,16 @@ public class VMManager {
public static void requestKillAllQemuProcess(Activity activity, Runnable runnable) {
DialogUtils.twoDialog(activity, activity.getString(R.string.do_you_want_to_kill_all_qemu_processes), activity.getString(R.string.all_running_vms_will_be_forcibly_shut_down), activity.getString(R.string.kill_all), activity.getString(R.string.cancel), true, R.drawable.power_settings_new_24px, true,
() -> {
killallqemuprocesses(activity);
ProgressDialog progressDialog = new ProgressDialog(activity);
progressDialog.setText(activity.getString(R.string.shutting_down));
progressDialog.show();
new Thread(() -> {
killallqemuprocesses(activity);
activity.runOnUiThread(() -> {
progressDialog.reset();
if (runnable != null) runnable.run();
});
}).start();
}, null, null);
}

View file

@ -30,9 +30,11 @@ import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.AppConfig;
import com.vectras.vm.R;
import com.vectras.vm.creator.configs.ListManager;
import com.vectras.vm.creator.editor.AccelerationConfigsDialog;
import com.vectras.vm.creator.editor.AdvancedConfigsDialog;
import com.vectras.vm.creator.editor.BoardConfigsDialog;
import com.vectras.vm.creator.editor.GraphicsConfigsDialog;
import com.vectras.vm.creator.editor.InputDevicesConfigsDialog;
import com.vectras.vm.creator.editor.NetworkConfigsDialog;
import com.vectras.vm.creator.editor.SoundConfigsDialog;
import com.vectras.vm.creator.utils.CreatorUtils;
@ -210,6 +212,15 @@ public class VMCreatorActivity extends AppCompatActivity {
dialog.show(getSupportFragmentManager(), "board_configs_dialog");
});
binding.lnInputDevices.setOnClickListener(v -> {
save();
InputDevicesConfigsDialog dialog = new InputDevicesConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "input_devices_configs_dialog");
});
binding.lnStorage.setOnClickListener(v -> {
save();
@ -255,6 +266,15 @@ public class VMCreatorActivity extends AppCompatActivity {
dialog.show(getSupportFragmentManager(), "sound_configs_dialog");
});
binding.lnAcceleration.setOnClickListener(v -> {
save();
AccelerationConfigsDialog dialog = new AccelerationConfigsDialog();
dialog.setConfigs(current);
dialog.setOnDismiss(this::loadConfig);
dialog.show(getSupportFragmentManager(), "acceleration_configs_dialog");
});
binding.lnAdvanced.setOnClickListener(v -> {
save();
@ -524,26 +544,9 @@ public class VMCreatorActivity extends AppCompatActivity {
}
private void setDefault() {
String defQemuParams;
if (DeviceUtils.is64bit()) {
defQemuParams = switch (MainSettingsManager.getArch(this)) {
case "ARM64" ->
"-accel tcg,thread=multi -device nec-usb-xhci -device usb-kbd -device usb-mouse";
case "PPC" -> "-M mac99 -accel tcg,thread=multi";
default ->
"-accel tcg,thread=multi -usb -device usb-tablet";
};
} else {
defQemuParams = switch (MainSettingsManager.getArch(this)) {
case "ARM64" ->
"-device nec-usb-xhci -device usb-kbd -device usb-mouse";
case "PPC" -> "-M mac99";
default ->
"-usb -device usb-tablet";
};
}
current = new DataMainRoms();
binding.title.setText(getString(R.string.new_vm));
current.itemExtra = defQemuParams;
String currentArch = MainSettingsManager.getArch(this);
@ -565,6 +568,9 @@ public class VMCreatorActivity extends AppCompatActivity {
// ENSONIQ AudioPCI ES1370 : Intel HD Audio Controller (ich6)
current.soundCard = currentArch.equals(MainSettingsManager.PPC_ARCH) ? 5 : 2;
// TCG (multi-threaded) : TCG (single-threaded)
current.accel = DeviceUtils.is64bit() ? 2 : 1;
}
private void checkVMID() {
@ -601,14 +607,14 @@ public class VMCreatorActivity extends AppCompatActivity {
DialogUtils.oneDialog(this, getString(R.string.oops), getString(R.string.need_set_name), getString(R.string.ok), true, R.drawable.error_96px, true, null, null);
} else {
String _contentDialog = "";
if (current.itemExtra.isEmpty()) {
_contentDialog = getResources().getString(R.string.qemu_params_is_empty);
}
// if (current.itemExtra.isEmpty()) {
// _contentDialog = getResources().getString(R.string.qemu_params_is_empty);
// }
if (isAllDriveEmpty() && !VMManager.isHaveADisk(current.itemExtra)) {
if (!_contentDialog.isEmpty()) {
_contentDialog += "\n\n";
}
// if (!_contentDialog.isEmpty()) {
// _contentDialog += "\n\n";
// }
_contentDialog += getResources().getString(R.string.you_have_not_added_any_storage_devices);
}

View file

@ -5,6 +5,7 @@ import android.content.Context;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.vm.R;
import com.vectras.vm.utils.CpuHelper;
import com.vectras.vm.utils.DeviceUtils;
import com.vectras.vm.utils.UniversalPickerDialog;
import java.util.ArrayList;
@ -280,4 +281,27 @@ public class ListManager {
UniversalPickerDialog.putToList(list, context.getString(R.string.ati), "ati-vga");
return list;
}
public static ArrayList<HashMap<String, Object>> mouseTypes(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.ps_2), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.usb), "usb-mouse");
UniversalPickerDialog.putToList(list, context.getString(R.string.usb_tablet), "usb-tablet");
return list;
}
public static ArrayList<HashMap<String, Object>> keyboardTypes(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.ps_2), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.usb), "usb-kbd");
return list;
}
public static ArrayList<HashMap<String, Object>> accelTypes(Context context) {
ArrayList<HashMap<String, Object>> list = new ArrayList<>();
UniversalPickerDialog.putToList(list, context.getString(R.string.none), "");
UniversalPickerDialog.putToList(list, context.getString(R.string.tcg_single_thread), "tcg,thread=single");
if (DeviceUtils.is64bit()) UniversalPickerDialog.putToList(list, context.getString(R.string.tcg_multi_thread), "tcg,thread=multi");
return list;
}
}

View file

@ -0,0 +1,112 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorAccelerationDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class AccelerationConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "AccelerationConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorAccelerationDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
if (savedInstanceState == null) DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorAccelerationDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
AccelerationConfigsDialogCallback callback;
public void setOnDismiss(AccelerationConfigsDialogCallback callback) {
this.callback = callback;
}
public interface AccelerationConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
// Auto save.
public void onPause() {
super.onPause();
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.sbvType.setOnClickListener(v -> VMCreatorSelector.accel(requireActivity(), configs.accel, ((position, name, value) -> {
configs.accel = position;
binding.sbvType.setSubtitle(name);
})));
load();
}
private void load() {
if (!isAdded()) return;
binding.sbvType.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getAccel(requireActivity(), configs.accel).get("name")).toString());
}
private void save() {
}
}

View file

@ -36,6 +36,7 @@ public class BoardConfigsDialog extends BottomSheetDialogFragment {
boolean isSave = true;
int availableMemory = Integer.MAX_VALUE;
int warningMemory = Integer.MAX_VALUE;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
@ -58,6 +59,9 @@ public class BoardConfigsDialog extends BottomSheetDialogFragment {
}
availableMemory = RamInfo.vectrasMemory(requireActivity());
warningMemory = availableMemory / 100 * 80;
if (availableMemory - warningMemory >= 1024) warningMemory = availableMemory / 100 * 90;
if (availableMemory - warningMemory >= 1024) warningMemory = availableMemory / 100 * 95;
binding = CreatorBoardDialogBinding.inflate(getLayoutInflater());
@ -168,7 +172,7 @@ public class BoardConfigsDialog extends BottomSheetDialogFragment {
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable editable) {
if (!editable.toString().isEmpty() && Integer.parseInt(editable.toString()) > (availableMemory / 100 * 80)) {
if (!editable.toString().isEmpty() && Integer.parseInt(editable.toString()) >= warningMemory) {
binding.cpiMemory.setError(getString(R.string.capacity_too_large));
} else {
binding.cpiMemory.setError(null);

View file

@ -0,0 +1,118 @@
package com.vectras.vm.creator.editor;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.vectras.vm.R;
import com.vectras.vm.creator.utils.EditorUtils;
import com.vectras.vm.creator.utils.VMCreatorSelector;
import com.vectras.vm.databinding.CreatorInputDevicesDialogBinding;
import com.vectras.vm.main.vms.DataMainRoms;
import com.vectras.vm.utils.DialogUtils;
import java.util.Objects;
public class InputDevicesConfigsDialog extends BottomSheetDialogFragment {
final String TAG = "InputDevicesConfigsDialog";
String vmId;
DataMainRoms configs;
boolean isSave = true;
public void setConfigs(DataMainRoms configs) {
this.configs = configs;
if (configs != null) {
vmId = configs.vmID;
}
}
CreatorInputDevicesDialogBinding binding;
@NonNull
@Override
public BottomSheetDialog onCreateDialog(Bundle savedInstanceState) {
// This can happen after the app is freed from memory and then reopened.
if (configs == null) {
isSave = false;
if (savedInstanceState == null) DialogUtils.oopsDialog(requireActivity(), getString(R.string.something_went_wrong));
dismiss();
return EditorUtils.getDummyDialog(requireActivity());
}
binding = CreatorInputDevicesDialogBinding.inflate(getLayoutInflater());
BottomSheetDialog dialog = new BottomSheetDialog(requireActivity());
dialog.setContentView(binding.getRoot());
initialize();
dialog.setOnShowListener(d -> {
BottomSheetBehavior<FrameLayout> behavior = dialog.getBehavior();
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setSkipCollapsed(true);
});
return dialog;
}
InputDevicesConfigsDialogCallback callback;
public void setOnDismiss(InputDevicesConfigsDialogCallback callback) {
this.callback = callback;
}
public interface InputDevicesConfigsDialogCallback {
void onDismiss(DataMainRoms configs);
}
public void onDismiss(@NonNull DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
// Auto save.
public void onPause() {
super.onPause();
if (callback != null && isSave) {
save();
callback.onDismiss(configs);
}
}
private void initialize() {
if (!isAdded()) return;
binding.sbvMouse.setOnClickListener(v -> VMCreatorSelector.mouse(requireActivity(), configs.mouse, ((position, name, value) -> {
configs.mouse = position;
binding.sbvMouse.setSubtitle(name);
})));
binding.sbvKeyboard.setOnClickListener(v -> VMCreatorSelector.keyboard(requireActivity(), configs.keyboard, ((position, name, value) -> {
configs.keyboard = position;
binding.sbvKeyboard.setSubtitle(name);
})));
load();
}
private void load() {
if (!isAdded()) return;
binding.sbvMouse.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getMouse(requireActivity(), configs.mouse).get("name")).toString());
binding.sbvKeyboard.setSubtitle(Objects.requireNonNull(VMCreatorSelector.getKeyboard(requireActivity(), configs.keyboard).get("name")).toString());
}
private void save() {
}
}

View file

@ -70,6 +70,22 @@ public class VMCreatorSelector {
return ListManager.networkCards(context).get(position);
}
public static void mouse(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.mouseTypes(activity), position, callback, activity.getString(R.string.types));
}
public static HashMap<String, Object> getMouse(Context context, int position) {
return ListManager.mouseTypes(context).get(position);
}
public static void keyboard(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.keyboardTypes(activity), position, callback, activity.getString(R.string.types));
}
public static HashMap<String, Object> getKeyboard(Context context, int position) {
return ListManager.keyboardTypes(context).get(position);
}
public static void soundCard(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.soundCards(activity), position, callback, activity.getString(R.string.cards));
}
@ -86,6 +102,14 @@ public class VMCreatorSelector {
showDialog(activity, ListManager.bootFrom(activity), position, callback, activity.getString(R.string.boot_from));
}
public static void accel(Activity activity, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback) {
showDialog(activity, ListManager.accelTypes(activity), position, callback, activity.getString(R.string.types));
}
public static HashMap<String, Object> getAccel(Context context, int position) {
return ListManager.accelTypes(context).get(position);
}
public static void showDialog(Activity activity, ArrayList<HashMap<String, Object>> list, int position, UniversalPickerDialog.UniversalPickerDialogCallback callback, String title) {
UniversalPickerDialog.show(activity, list, position, callback, title);
}

View file

@ -67,6 +67,12 @@ public class DataMainRoms {
public boolean sharedFolder;
// Input devices
public int mouse;
public int keyboard;
// Graphics
public int graphicCard;
@ -91,6 +97,10 @@ public class DataMainRoms {
public boolean isUseDefaultBios = true;
// Acceleration
public int accel;
// Advanced
@SerializedName(

View file

@ -18,4 +18,8 @@ public class ParamManager {
public static boolean hasMemory(String param) {
return Pattern.compile("(?<![\\w-])--?m\\s+(\\d+)([a-zA-Z]*)").matcher(param).find();
}
public static boolean hasUsb(String param) {
return Pattern.compile("(?<=^|\\s)-usb(?=$|\\s)").matcher(param).find();
}
}

View file

@ -392,7 +392,7 @@ public class VmControllerDialog extends DialogFragment {
});
if (isAdded() && requireActivity() instanceof MainVNCActivity mainVNCActivity) {
if (isAdded() && requireActivity() instanceof MainVNCActivity mainVNCActivity && vncCanvas != null) {
binding.sliderBrightness.setValue(vncCanvas.getAlpha() * 100);
binding.sliderBrightness.addOnChangeListener((slider, value, fromUser) -> vncCanvas.setAlpha(value / 100));

View file

@ -26,6 +26,14 @@ public class SettingsData {
set(context, "opengl", value);
}
public static void x11Bubble(Context context, boolean value) {
set(context, "x11_bubble", value);
}
public static boolean x11Bubble(Context context) {
return get(context, "x11_bubble");
}
// Core
public static boolean get(Context context, String key) {

View file

@ -38,9 +38,10 @@ public class X11DisplaySettingsActivity extends AppCompatActivity {
private void initialize() {
binding.swEnabled.setChecked(MainSettingsManager.getVmUi(this).equals("X11"));
binding.swRunQemuWithXterm.setChecked(MainSettingsManager.getRunQemuWithXterm(this));
binding.swUseExternal.setChecked(MainSettingsManager.getExternalX11(this));
binding.swUseSdl.setChecked(MainSettingsManager.getUseSdl(this));
binding.swUseOpengl.setChecked(SettingsData.opengl(this));
binding.swUseExternal.setChecked(MainSettingsManager.getExternalX11(this));
binding.swBubble.setChecked(SettingsData.x11Bubble(this));
binding.swEnabled.setOnCheckedChangeListener((buttonView, isChecked) -> {
MainSettingsManager.setVmUi(this, isChecked ? "X11" : "VNC");
@ -54,9 +55,9 @@ public class X11DisplaySettingsActivity extends AppCompatActivity {
} else {
if (PackageUtils.isInstalled("com.termux.x11", this)) {
Intent intent = new Intent();
intent.setClassName("com.termux.x11", "com.termux.x11.MainActivity");
intent.setClassName("com.termux.x11", "com.termux.x11.LoriePreferences");
intent.setAction(Intent.ACTION_MAIN);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
} else {
DialogUtils.needInstallTermuxX11(this);
@ -64,6 +65,9 @@ public class X11DisplaySettingsActivity extends AppCompatActivity {
}
});
binding.swUseExternal.setOnCheckedChangeListener((buttonView, isChecked) -> MainSettingsManager.setExternalX11(this, isChecked));
binding.lnUseExternal.setOnClickListener(v -> binding.swUseExternal.toggle());
binding.swRunQemuWithXterm.setOnCheckedChangeListener((buttonView, isChecked) -> MainSettingsManager.setRunQemuWithXterm(this, isChecked));
binding.lnRunQemuWithXterm.setOnClickListener(v -> binding.swRunQemuWithXterm.toggle());
@ -73,8 +77,8 @@ public class X11DisplaySettingsActivity extends AppCompatActivity {
binding.swUseOpengl.setOnCheckedChangeListener((buttonView, isChecked) -> SettingsData.opengl(this, isChecked));
binding.lnUseOpengl.setOnClickListener(v -> binding.swUseOpengl.toggle());
binding.swUseExternal.setOnCheckedChangeListener((buttonView, isChecked) -> MainSettingsManager.setExternalX11(this, isChecked));
binding.lnUseExternal.setOnClickListener(v -> binding.swUseExternal.toggle());
binding.swBubble.setOnCheckedChangeListener((buttonView, isChecked) -> SettingsData.x11Bubble(this, isChecked));
binding.lnBubble.setOnClickListener(v -> binding.swBubble.toggle());
binding.lnTurnipZink.setOnClickListener(v -> startActivity(new Intent(this, TurnipZinkSetupWizardActivity.class)));
@ -86,10 +90,11 @@ public class X11DisplaySettingsActivity extends AppCompatActivity {
private void uiController(boolean isEnabled) {
binding.lnAllOptions.setAlpha(isEnabled ? 1f : 0.5f);
binding.lnPreferences.setEnabled(isEnabled);
binding.lnUseExternal.setEnabled(isEnabled);
binding.lnRunQemuWithXterm.setEnabled(isEnabled);
binding.lnUseSdl.setEnabled(isEnabled);
binding.lnUseOpengl.setEnabled(isEnabled);
binding.lnUseExternal.setEnabled(isEnabled);
binding.lnBubble.setEnabled(isEnabled);
binding.lnTurnipZink.setEnabled(isEnabled);
}
}

View file

@ -46,6 +46,7 @@ import com.vectras.vm.manager.VmControllerDialog;
import com.vectras.vm.manager.VmFileManager;
import com.vectras.vm.manager.VmListManager;
import com.vectras.vm.manager.VmPicker;
import com.vectras.vm.settings.SettingsData;
import com.vectras.vm.sound.StreamAudio;
import com.vectras.vm.utils.DialogUtils;
import com.vectras.vm.utils.UIUtils;
@ -161,7 +162,9 @@ public class AddIn {
ControlersOptionsFragment newFragment = new ControlersOptionsFragment();
newFragment.binding = binding.controlsfragment;
newFragment.show(ft, "Controllers");
newFragment.setOnDismiss = () -> binding.lnBubbleContainer.setVisibility(bindingControls.mainControl.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
if (SettingsData.x11Bubble(activity))
newFragment.setOnDismiss = () -> binding.lnBubbleContainer.setVisibility(bindingControls.mainControl.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
});
@ -557,14 +560,15 @@ public class AddIn {
}
public void handleOnBack() {
if (bindingControls.mainControl.getVisibility() == View.GONE) {
if (bindingControls.mainControl.getVisibility() == View.GONE && !SettingsData.x11Bubble(activity)) {
bindingControls.mainControl.setVisibility(View.VISIBLE);
} else if (streamAudio != null) {
if (!VmAudioManager.currentVmId.equals(Config.vmID))
streamAudio.setCross(null);
if (streamAudio.isPlaying()) streamAudio.stop();
} else {
if (streamAudio != null) {
if (!VmAudioManager.currentVmId.equals(Config.vmID))
streamAudio.setCross(null);
if (streamAudio.isPlaying()) streamAudio.stop();
}
activity.finish();
}
}

View file

@ -505,6 +505,11 @@ public class LorieView extends SurfaceView implements InputStub {
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
X11Activity.getInstance().onBackPressed();
return true;
}
if (imeBuggyKeys.contains(event.getKeyCode())) {
// IME does not handle/send events for some keys correctly correctly.
// So we should send key release manually in the case if IME will not send it...
@ -522,6 +527,11 @@ public class LorieView extends SurfaceView implements InputStub {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
X11Activity.getInstance().onBackPressed();
return true;
}
if (imeBuggyKeys.contains(event.getKeyCode())) {
// remove messages we posted in dispatchKeyEventPreIme
int action = event.getAction();

View file

@ -112,7 +112,7 @@ public class X11Activity extends AppCompatActivity {
Log.e("X11Activity", "Something went wrong while we extracted connection details from binder.", e);
}
} else if (ACTION_STOP.equals(intent.getAction())) {
finishAffinity();
finish();
} else if (ACTION_PREFERENCES_CHANGED.equals(intent.getAction())) {
Log.d("X11Activity", "preference: " + intent.getStringExtra("key"));
if (!"additionalKbdVisible".equals(intent.getStringExtra("key")))
@ -158,7 +158,7 @@ public class X11Activity extends AppCompatActivity {
return instance;
}
AddIn addIn;
public AddIn addIn;
ActivityX11Binding binding;
@ -261,6 +261,13 @@ public class X11Activity extends AppCompatActivity {
addIn.initialize(binding);
}
@Override
protected void onNewIntent(@NonNull Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
onReceiveConnection(intent);
}
@Override
protected void onDestroy() {
unregisterReceiver(receiver);

View file

@ -480,7 +480,7 @@ public class TouchInputHandler {
return noAction;
switch(pref.asList().get()) {
case "toggle soft keyboard": return (key, down) -> { if (down) X11Activity.toggleKeyboardVisibility(mActivity); };
//case "toggle soft keyboard": return (key, down) -> { if (down) X11Activity.toggleKeyboardVisibility(mActivity); };
case "toggle additional key bar": return (key, down) -> { if (down) mActivity.toggleExtraKeys(); };
case "open preferences": return (key, down) -> { if (down) mActivity.startActivity(new Intent(mActivity, LoriePreferences.class) {{ setAction(Intent.ACTION_MAIN); }}); };
case "release pointer and keyboard capture": return (key, down) -> { if (down) setCapturingEnabled(false); };

View file

@ -0,0 +1,306 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:layoutDirection="ltr"
android:paddingLeft="0dp"
android:paddingTop="0dp"
android:paddingRight="0dp"
android:paddingBottom="0dp"
android:background="@android:color/black">
<com.vectras.vm.x11.LorieView
android:id="@+id/lorieView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:layout_gravity="center" />
<include
android:id="@+id/controlsfragment"
layout="@layout/controls_fragment" />
<TextView
android:id="@+id/keyEventStatusTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
/>
<LinearLayout
android:id="@+id/ln_bubble_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_bubble"
style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/radio_button_unchecked_24px"/>
</LinearLayout>
<FrameLayout
android:id="@+id/stub"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.9"
android:background="#E6000000"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical" >
<ImageView
android:id="@+id/x11_image"
android:layout_width="48dp"
android:layout_height="48dp"
android:scaleType="fitCenter"
app:srcCompat="@drawable/cast_warning_24px"
app:tint="@android:color/white"
android:contentDescription="X Logo"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:gravity="center_horizontal|center_vertical"
android:text="@string/no_signal"
android:textColor="#FFFFFF"
android:textSize="20sp" />
<Button
android:id="@+id/preferences_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings"
android:textColor="@android:color/black"
android:backgroundTint="@android:color/white" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="10dp" />
<Button
android:id="@+id/help_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/help_button_text"
android:visibility="gone" />
</LinearLayout>
</FrameLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/mouse_helper_visibility"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:translationX="0px"
android:translationY="0px">
<Button
android:id="@+id/button_visibility"
android:layout_width="64px"
android:layout_height="64px"
android:minWidth="44dip"
android:minHeight="22dip"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="X"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
<LinearLayout
android:id="@+id/mouse_helper_secondary_layer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:visibility="visible">
<Button
android:id="@+id/button_left_click"
android:layout_width="64px"
android:layout_height="64px"
android:minWidth="44dip"
android:minHeight="22dip"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="L"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
<Button
android:id="@+id/button_middle_click"
android:layout_width="64px"
android:layout_height="64px"
android:minWidth="44dip"
android:minHeight="22dip"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="M"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
<Button
android:id="@+id/button_right_click"
android:layout_width="64px"
android:layout_height="64px"
android:minWidth="44dip"
android:minHeight="22dip"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="R"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/mouse_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:layout_marginBottom="40dp"
android:orientation="vertical"
android:alpha="0.7"
android:translationX="0px"
android:translationY="0px">
<LinearLayout
android:id="@+id/mouse_buttons_secondary_layer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:visibility="visible">
<Button
android:id="@+id/mouse_button_left_click"
android:layout_width="96dp"
android:layout_height="48dp"
android:minWidth="48dp"
android:minHeight="48dp"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="L"
android:textColor="@android:color/black"
android:background="@drawable/mouse_buttons"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
<Button
android:id="@+id/mouse_button_middle_click"
android:layout_width="48dp"
android:layout_height="48dp"
android:minWidth="48dp"
android:minHeight="48dp"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="M"
android:textColor="@android:color/black"
android:background="@drawable/mouse_buttons"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
<Button
android:id="@+id/mouse_button_right_click"
android:layout_width="96dp"
android:layout_height="48dp"
android:minWidth="48dp"
android:minHeight="48dp"
android:padding="0px"
android:paddingStart="0px"
android:paddingLeft="0px"
android:paddingTop="0px"
android:paddingEnd="0px"
android:paddingRight="0px"
android:paddingBottom="0px"
android:text="R"
android:textColor="@android:color/black"
android:background="@drawable/mouse_buttons"
android:textSize="8sp"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
</LinearLayout>
<ImageButton
android:id="@+id/mouse_buttons_position"
android:layout_width="40dp"
android:layout_height="40dp"
android:minWidth="40dp"
android:minHeight="40dp"
android:adjustViewBounds="true"
android:padding="2dp"
android:scaleType="fitCenter"
android:src="@android:drawable/ic_menu_mylocation"
android:contentDescription="MOVE"
android:layout_gravity="center"
android:background="@drawable/mouse_buttons"
tools:ignore="HardcodedText,PxUsage,SmallSp" />
</LinearLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/terminal_toolbar_view_pager"
android:visibility="gone"
android:pointerIcon="arrow"
android:layout_width="match_parent"
android:layout_height="37.5dp"
android:background="@android:color/black"
android:layout_gravity="bottom|center" />
<View
android:id="@+id/activity_termux_bottom_space_view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/transparent"
android:layout_gravity="bottom|center" />
</FrameLayout>

View file

@ -194,6 +194,38 @@
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_input_devices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/input_devices"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/input_devices_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_storage"
android:layout_width="match_parent"
@ -354,6 +386,38 @@
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_acceleration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/acceleration"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/acceleration_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_advanced"
android:layout_width="match_parent"

View file

@ -71,6 +71,48 @@
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_use_external"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:background="@drawable/object_shape_middle_high"
android:padding="16dp" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/sw_use_external"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/external"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/use_external_x11_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_use_external"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:clickable="false"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_run_qemu_with_xterm"
android:layout_width="match_parent"
@ -198,7 +240,7 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ln_use_external"
android:id="@+id/ln_bubble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
@ -211,26 +253,26 @@
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/sw_use_external"
app:layout_constraintEnd_toStartOf="@id/sw_bubble"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/external"
android:text="@string/bubble"
android:textSize="18sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/use_external_x11_note"
android:text="@string/bubble_setting_note"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
</LinearLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sw_use_external"
android:id="@+id/sw_bubble"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="true"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/acceleration" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/acceleration_type"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_single_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.core.widget.NestedScrollView
android:id="@+id/nsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="true"
android:requiresFadingEdge="vertical"
android:fadingEdgeLength="48dp">
<LinearLayout
android:id="@+id/ln_all_options"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingHorizontal="16dp"
android:paddingBottom="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
style="@style/MaterialAlertDialog.Material3Expressive.Title.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:text="@string/input_devices" />
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_mouse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
app:title="@string/mouse"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_top_high"/>
<com.vectras.vm.view.SelectBoxView
android:id="@+id/sbv_keyboard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/keyboard"
app:subtitle="@string/defaulttext"
android:background="@drawable/object_shape_bottom_high"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -680,6 +680,18 @@
<string name="graphics_note">Thẻ đồ hoạ,…</string>
<string name="opengl_setting_note">Màn hình sẽ hỗ trợ OpenGL khi chạy máy ảo. 3Dfx sẽ không hoạt động khi dùng tính năng này.</string>
<string name="qemu_opengl_is_not_available_content">OpenGL chỉ có sẵn khi dùng màn hình X11 và đã bật dùng Open GL. Đến cài đặt để tìm hiểu thêm.</string>
<string name="input_devices">Các thiết bị nhập</string>
<string name="input_devices_note">Chuột, bàn phím,…</string>
<string name="mouse">Chuột</string>
<string name="usb_tablet">Cảm ứng USB</string>
<string name="types">Các loại</string>
<string name="acceleration">Tăng tốc</string>
<string name="acceleration_note">Loại tăng tốc,…</string>
<string name="acceleration_type">Loại tăng tốc</string>
<string name="tcg_single_thread">TCG (đơn luồng)</string>
<string name="tcg_multi_thread">TCG (đa luồng)</string>
<string name="bubble">Bong bóng</string>
<string name="bubble_setting_note">Dùng bong bóng dể hiện các phím điều khiển khi chúng bị ẩn thay vì dùng phím quay lại.</string>
<!--======================TERMUX STRINGS====================-->
<string name="application_name" translatable="false">Vterm</string>

View file

@ -23,7 +23,7 @@
<string name="zoom_in">Zoom In</string>
<string name="zoom_out">Zoom Out</string>
<string name="help">Help</string>
<string name="keyboard">KEYBOARD</string>
<string name="keyboard">Keyboard</string>
<string name="name">name</string>
<string name="size">size:</string>
<string name="vectras_website">Vectras website</string>
@ -701,7 +701,18 @@
<string name="graphics_note">Graphics card,…</string>
<string name="opengl_setting_note">The display will support OpenGL when running a virtual machine. 3Dfx will not work when using this feature.</string>
<string name="qemu_opengl_is_not_available_content">OpenGL is only available when using an X11 display and with OpenGL enabled. Go to settings to learn more.</string>
<string name="input_devices">Input devices</string>
<string name="input_devices_note">Mouse, keyboard,…</string>
<string name="mouse">Mouse</string>
<string name="usb_tablet">USB tablet</string>
<string name="types">Types</string>
<string name="acceleration">Acceleration</string>
<string name="acceleration_note">Acceleration type,…</string>
<string name="acceleration_type">Acceleration type</string>
<string name="tcg_single_thread">TCG (single-threaded)</string>
<string name="tcg_multi_thread">TCG (multi-threaded)</string>
<string name="bubble">Bubble</string>
<string name="bubble_setting_note">Use bubble to show hidden controls instead of using the back button.</string>
<!--======================TERMUX STRINGS====================-->
@ -943,8 +954,7 @@ E.g. <b>META</b> for <i>META key</i>, \n
<string name="lorie_pref_storeSecondaryDisplayPreferencesSeparately">Store preferences for secondary displays separately</string>
<string name="lorie_pref_storeSecondaryDisplayPreferencesSeparately_summary">Open this screen on display you want to configure</string>
<string name="lorie_pref_adjustHeightForEK">Adjust display height for extra keys bar</string>
<string name="lorie_pref_adjustHeightForEK_summary">May cause screen flickering during toggling EK bar.</string>
<string name="lorie_pref_adjustHeightForEK">Prevent extra keys bar from covering the display</string>
<string name="lorie_pref_useTermuxEKBarBehaviour">Deactivate special keys on additional key bar after each keypress</string>
<string name="lorie_pref_useTermuxEKBarBehaviour_summary">Use long-tap to lock special keys</string>
<string name="lorie_pref_opacityEKBar">Opacity of extra keys bar, %</string>
@ -964,6 +974,8 @@ E.g. <b>META</b> for <i>META key</i>, \n
<string name="lorie_pref_summary_requiresIntercepting">Requires intercepting system shortcuts with Dex mode or with Accessibility service</string>
<string name="lorie_pref_summary_requiresTrackpadAndNative">Requires "Touchscreen input mode" to be "Trackpad" and "Display resolution mode" to be not "native"</string>
<string name="usb" translatable="false">USB</string>
<string name="ps_2" translatable="false">PS/2</string>
<string name="opengl" translatable="false">OpenGL</string>

View file

@ -5,11 +5,11 @@
"url": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases/tag/4.4.1",
"Message": "<h2>4.4.1</h2>\nBugs fixed.",
"cancellable": true,
"versionCodeBeta":"155",
"versionNameBeta":"4.4.8",
"versionNameBetas":"4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,4.0.7,4.0.8,4.0.9,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8,4.1.9,4.2.1,4.2.2,4.2.3,4.2.4,4.2.5,4.2.6,4.2.7,4.2.8,4.2.9,4.3.0,4.3.1,4.3.2,4.3.3,4.3.4,4.3.5,4.3.6,4.3.7,4.3.8,4.3.9,4.4.0,4.4.1,4.4.2,4.4.3,4.4.4,4.4.5,4.4.6,4.4.7,4.4.8",
"versionCodeBeta":"156",
"versionNameBeta":"4.4.9",
"versionNameBetas":"4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,4.0.7,4.0.8,4.0.9,4.1.1,4.1.2,4.1.3,4.1.4,4.1.5,4.1.6,4.1.7,4.1.8,4.1.9,4.2.1,4.2.2,4.2.3,4.2.4,4.2.5,4.2.6,4.2.7,4.2.8,4.2.9,4.3.0,4.3.1,4.3.2,4.3.3,4.3.4,4.3.5,4.3.6,4.3.7,4.3.8,4.3.9,4.4.0,4.4.1,4.4.2,4.4.3,4.4.4,4.4.5,4.4.6,4.4.7,4.4.8,4.4.9",
"sizeBeta": "47 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
"MessageBeta": "<h2>4.4.8</h2>Bugs fixed.",
"MessageBeta": "<h2>4.4.9</h2>Bugs fixed.",
"cancellableBeta": true
}