mirror of
https://github.com/xoureldeen/Vectras-VM-Android.git
synced 2026-07-09 17:28:54 +00:00
4.2.4
- Faster return to virtual machine. - Fixed the frozen virtual machine startup dialog when using X11. - Added audio support for the built-in X11 display. - Improved notifications. - Qemu 7.2.22 has been improved and requires manual updating with the Upgrade tool using a command in the Terminal.
This commit is contained in:
parent
3b16fd8b7d
commit
09f9654ccd
13 changed files with 239 additions and 98 deletions
1
.github/ISSUE_TEMPLATE/bug.yaml
vendored
1
.github/ISSUE_TEMPLATE/bug.yaml
vendored
|
|
@ -32,6 +32,7 @@ body:
|
|||
options:
|
||||
- Latest
|
||||
- Beta
|
||||
- 4.2.0
|
||||
- 4.1.0
|
||||
- 4.0.0
|
||||
- 3.9.0
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ QEMU 8.2.0 - 3dfx (only for Vectras VM 2.9.5):
|
|||
- [See them at the Internet Archive](https://archive.org/details/vectras-vm-x86_64.tar_202603nbab)
|
||||
|
||||
QEMU 7.2.22 - 3dfx (for Vectras VM 4.2.2+):
|
||||
- [For Android ARM (64-bit)](https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-vectras-vm-arm64-v8a.tar.gz)
|
||||
- [For Android ARM (64-bit)](https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-june-2026-vectras-vm-arm64-v8a.tar.gz)
|
||||
- [See more at the Internet Archive](https://archive.org/details/qemu-7-2-22-for-vectras-vm-nbab)
|
||||
|
||||
### 💽 3Dfx Wrappers
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ android {
|
|||
applicationId "com.vectras.vm"
|
||||
minSdk minApi
|
||||
targetSdk targetApi
|
||||
versionCode 127
|
||||
versionName "4.2.3"
|
||||
versionCode 128
|
||||
versionName "4.2.4"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ public class StartVM {
|
|||
private static DataMainRoms vmConfigs;
|
||||
|
||||
public static String env(Activity activity, DataMainRoms vmData) {
|
||||
if (VMManager.isVMRunning(activity, vmData.vmID)) return "";
|
||||
|
||||
vmConfigs = vmData;
|
||||
|
||||
if (VMManager.isNeedLoadMigrate() && FileUtils.isFileExists(VmFileManager.getSnapshotSh(Config.vmID))) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
|
|||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.settings.UpdaterActivity;
|
||||
import com.vectras.vm.utils.NotificationUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
@ -21,6 +22,12 @@ public class FCMService
|
|||
&& !Objects.requireNonNull(data.get("targetVersions")).contains(getString(R.string.app_version))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> activityClass = null;
|
||||
|
||||
if (data.get("activityClass") != null) {
|
||||
if (Objects.equals(data.get("activityClass"), "update")) activityClass = UpdaterActivity.class;
|
||||
}
|
||||
|
||||
NotificationUtils.pushNow(this,
|
||||
1,
|
||||
|
|
@ -31,7 +38,7 @@ public class FCMService
|
|||
data.get("image") != null ? data.get("image") : null,
|
||||
-1,
|
||||
data.get("url") != null ? data.get("url") : null,
|
||||
null);
|
||||
activityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import android.widget.Toast;
|
|||
import com.vectras.qemu.Config;
|
||||
import com.vectras.qemu.MainSettingsManager;
|
||||
import com.vectras.qemu.MainVNCActivity;
|
||||
import com.vectras.vm.AppConfig;
|
||||
import com.vectras.vm.MainService;
|
||||
import com.vectras.vm.R;
|
||||
import com.vectras.vm.StartVM;
|
||||
|
|
@ -55,6 +54,26 @@ public class MainStartVM {
|
|||
|
||||
private static StartVmDialog dialog;
|
||||
|
||||
public static final int PENDDING_EMPTY = -1;
|
||||
|
||||
public static final int STARTED_VM = 0;
|
||||
public static final int STARTED_VM_READY_RUNNING = 1;
|
||||
|
||||
public static final int ERROR_VM = 10;
|
||||
public static final int ERROR_BREAK = 11;
|
||||
public static final int ERROR_INVALID_VM_ID = 12;
|
||||
public static final int ERROR_MAKE_TEMP_FOLDER = 13;
|
||||
public static final int ERROR_UNSAFE_COMMAND = 14;
|
||||
public static final int ERROR_ACCEL = 15;
|
||||
public static final int ERROR_VNC_TCP_PORT = 16;
|
||||
public static final int ERROR_SHARED_FOLDER = 17;
|
||||
public static final int ERROR_RESUME = 18;
|
||||
|
||||
public interface MainStartVMCallback {
|
||||
void onStarted(int statusCode, String message);
|
||||
void onError(int errorCode, String message);
|
||||
}
|
||||
|
||||
public static void startNow(Activity activity, DataMainRoms vmConfig) {
|
||||
breakNow = false;
|
||||
|
||||
|
|
@ -62,7 +81,10 @@ public class MainStartVM {
|
|||
|
||||
VMManager.setArch(vmConfig.itemArch, activity);
|
||||
|
||||
if (!(MainSettingsManager.getVmUi(activity).equals("X11") && DisplaySystem.isUseBuiltInX11())) {
|
||||
if (
|
||||
MainSettingsManager.getVmUi(activity).equals("VNC") ||
|
||||
(MainSettingsManager.getVmUi(activity).equals("X11") && !DisplaySystem.isUseBuiltInX11())
|
||||
) {
|
||||
showDialog(activity, vmConfig.vmID, vmConfig.itemName, vmConfig.itemIcon, activity.getString(R.string.preparing));
|
||||
}
|
||||
|
||||
|
|
@ -82,9 +104,22 @@ public class MainStartVM {
|
|||
String thumbnailFile,
|
||||
StartVmDialog dialog
|
||||
) {
|
||||
startNow(context, vmName, env, vmID, thumbnailFile, dialog, null);
|
||||
}
|
||||
|
||||
public static void startNow(
|
||||
Context context,
|
||||
String vmName,
|
||||
String env,
|
||||
String vmID,
|
||||
String thumbnailFile,
|
||||
StartVmDialog dialog,
|
||||
MainStartVMCallback callback
|
||||
) {
|
||||
|
||||
if (breakNow) {
|
||||
breakNow = false;
|
||||
if (callback != null) callback.onError(PENDDING_EMPTY, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +127,10 @@ public class MainStartVM {
|
|||
|
||||
if (isLaunchFromPending) {
|
||||
isLaunchFromPending = false;
|
||||
if (pendingVMID.isEmpty()) return;
|
||||
if (pendingVMID.isEmpty()) {
|
||||
if (callback != null) callback.onError(ERROR_INVALID_VM_ID, "");
|
||||
return;
|
||||
}
|
||||
pendingVMID = "";
|
||||
} else {
|
||||
if (MainSettingsManager.getVmUi(context).equals("X11") && !DisplaySystem.isUseBuiltInX11()) {
|
||||
|
|
@ -128,8 +166,6 @@ public class MainStartVM {
|
|||
|
||||
breakNow = false;
|
||||
|
||||
if (dialog == null || !dialog.isShowing()) showDialog((Activity) context, vmID, vmName, thumbnailFile, null);
|
||||
|
||||
String finalvmID;
|
||||
if (vmID == null || vmID.isEmpty()) {
|
||||
finalvmID = VMManager.startRamdomVMID();
|
||||
|
|
@ -140,14 +176,23 @@ public class MainStartVM {
|
|||
Config.vmID = finalvmID;
|
||||
|
||||
if (VMManager.isVMRunning(context, finalvmID)) {
|
||||
Toast.makeText(context, "This VM is already running.", Toast.LENGTH_LONG).show();
|
||||
DisplaySystem.launch(context);
|
||||
if (!MainSettingsManager.getVmUi(context).equals("VNC")) VmAudioManager.stream(vmID);
|
||||
|
||||
dismissDialog();
|
||||
|
||||
Toast.makeText(context, context.getString(R.string.this_vm_is_already_running), Toast.LENGTH_LONG).show();
|
||||
DisplaySystem.launch(context);
|
||||
if (
|
||||
!MainSettingsManager.getVmUi(context).equals("VNC") &&
|
||||
!DisplaySystem.isUseBuiltInX11()
|
||||
)
|
||||
VmAudioManager.stream(vmID);
|
||||
|
||||
if (callback != null) callback.onStarted(STARTED_VM_READY_RUNNING, "");
|
||||
return;
|
||||
}
|
||||
|
||||
// Place it here to avoid freezing when the dialog box appears upon returning to the virtual machine.
|
||||
if (dialog == null || !dialog.isShowing()) showDialog((Activity) context, vmID, vmName, thumbnailFile, null);
|
||||
|
||||
File romDir = new File(Config.getCacheDir() + "/" + finalvmID);
|
||||
if (!romDir.exists()) {
|
||||
if (!romDir.mkdirs()) {
|
||||
|
|
@ -159,6 +204,7 @@ public class MainStartVM {
|
|||
);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_MAKE_TEMP_FOLDER, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -172,6 +218,7 @@ public class MainStartVM {
|
|||
);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_UNSAFE_COMMAND, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -182,6 +229,7 @@ public class MainStartVM {
|
|||
() -> startNow(context, vmName, env.replace("tcg,thread=multi", "tcg,thread=single"), finalvmID, thumbnailFile, finalDialog1), null, null);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_ACCEL, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -198,6 +246,7 @@ public class MainStartVM {
|
|||
null);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_VNC_TCP_PORT, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -221,6 +270,7 @@ public class MainStartVM {
|
|||
);
|
||||
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_SHARED_FOLDER, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -228,10 +278,11 @@ public class MainStartVM {
|
|||
|
||||
if (breakNow) {
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_BREAK, "");
|
||||
return;
|
||||
}
|
||||
|
||||
startVm(context, vmName, env, finalvmID, thumbnailFile);
|
||||
startVm(context, vmName, env, finalvmID, thumbnailFile, callback);
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
|
|
@ -241,7 +292,8 @@ public class MainStartVM {
|
|||
String vmName,
|
||||
String env,
|
||||
String vmID,
|
||||
String thumbnailFile
|
||||
String thumbnailFile,
|
||||
MainStartVMCallback callback
|
||||
) {
|
||||
VMManager.isQemuStopedWithError = false;
|
||||
|
||||
|
|
@ -257,6 +309,7 @@ public class MainStartVM {
|
|||
|
||||
if (breakNow) {
|
||||
dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_BREAK, "");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -332,6 +385,8 @@ public class MainStartVM {
|
|||
null,
|
||||
null
|
||||
);
|
||||
|
||||
if (callback != null) callback.onError(ERROR_RESUME, "");
|
||||
});
|
||||
|
||||
return;
|
||||
|
|
@ -372,12 +427,18 @@ public class MainStartVM {
|
|||
Log.i(TAG, "Virtual machine running.");
|
||||
|
||||
if (activity != null) {
|
||||
activity.runOnUiThread(MainStartVM::dismissDialog);
|
||||
activity.runOnUiThread(() -> {
|
||||
MainStartVM.dismissDialog();
|
||||
if (callback != null) callback.onStarted(STARTED_VM, "");
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
assert activity != null;
|
||||
activity.runOnUiThread(MainStartVM::dismissDialog);
|
||||
activity.runOnUiThread(() -> {
|
||||
MainStartVM.dismissDialog();
|
||||
if (callback != null) callback.onError(ERROR_VM, "");
|
||||
});
|
||||
}
|
||||
|
||||
skipIDEwithARM64DialogInStartVM = false;
|
||||
|
|
@ -404,9 +465,9 @@ public class MainStartVM {
|
|||
VMManager.isTryAgain = false;
|
||||
}
|
||||
|
||||
public static void startPending(Context context) {
|
||||
public static void startPending(Context context, MainStartVMCallback callback) {
|
||||
isLaunchFromPending = true;
|
||||
startNow(context, pendingVMName, pendingEnv, pendingVMID, pendingThumbnailFile, null);
|
||||
startNow(context, pendingVMName, pendingEnv, pendingVMID, pendingThumbnailFile, null, callback);
|
||||
}
|
||||
|
||||
private static void showDialog(Activity activity, String vmId, String vmName, String thumbnailPath, String status) {
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@ package com.vectras.vm.x11;
|
|||
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
|
||||
|
||||
import android.app.Dialog;
|
||||
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Looper;
|
||||
|
||||
import static android.view.InputDevice.KEYBOARD_TYPE_ALPHABETIC;
|
||||
import static android.view.KeyEvent.*;
|
||||
import static android.view.WindowManager.LayoutParams.*;
|
||||
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
|
|
@ -28,6 +29,9 @@ import com.vectras.vm.databinding.DesktopControlsBinding;
|
|||
import com.vectras.vm.databinding.GameControlsBinding;
|
||||
import com.vectras.vm.main.core.MainStartVM;
|
||||
import com.vectras.vm.manager.QmpSender;
|
||||
import com.vectras.vm.manager.VmAudioManager;
|
||||
import com.vectras.vm.manager.VmFileManager;
|
||||
import com.vectras.vm.utils.StreamAudio;
|
||||
import com.vectras.vm.utils.UIUtils;
|
||||
|
||||
import static com.vectras.vm.x11.CmdEntryPoint.ACTION_START;
|
||||
|
|
@ -119,6 +123,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
public boolean ctrlClicked = false;
|
||||
public boolean altClicked = false;
|
||||
|
||||
private StreamAudio streamAudio;
|
||||
|
||||
ActivityX11Binding binding;
|
||||
ControlsFragmentBinding bindingControls;
|
||||
DesktopControlsBinding bindingDesktopControls;
|
||||
|
|
@ -178,11 +184,11 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
|
||||
@Override
|
||||
@SuppressLint({
|
||||
"AppCompatMethod",
|
||||
"ObsoleteSdkInt",
|
||||
"ClickableViewAccessibility",
|
||||
"WrongConstant",
|
||||
"UnspecifiedRegisterReceiverFlag"
|
||||
"AppCompatMethod",
|
||||
"ObsoleteSdkInt",
|
||||
"ClickableViewAccessibility",
|
||||
"WrongConstant",
|
||||
"UnspecifiedRegisterReceiverFlag"
|
||||
})
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
@ -281,8 +287,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
}
|
||||
|
||||
if (e.getScanCode() == KEY_BACK
|
||||
&& e.getDevice().getKeyboardType()
|
||||
!= KEYBOARD_TYPE_ALPHABETIC
|
||||
&& e.getDevice().getKeyboardType()
|
||||
!= KEYBOARD_TYPE_ALPHABETIC
|
||||
|| e.getScanCode() == 0) {
|
||||
if (toggleIMEUsingBackKey && e.getAction() == ACTION_UP) {
|
||||
Log.d(TAG, "KEYCODE_BACK: toggleIMEUsingBackKey");
|
||||
|
|
@ -688,31 +694,49 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
|
||||
bindingDesktopControls.ctrlaltdelBtn.setVisibility(View.GONE);
|
||||
|
||||
MainStartVM.startPending(this);
|
||||
MainStartVM.startPending(this, new MainStartVM.MainStartVMCallback() {
|
||||
@Override
|
||||
public void onStarted(int statusCode, String message) {
|
||||
MainStartVM.dismissDialog();
|
||||
setupSound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorCode, String message) {
|
||||
MainStartVM.dismissDialog();
|
||||
if (errorCode == MainStartVM.PENDDING_EMPTY) setupSound();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void onBack() {
|
||||
if (bindingControls.mainControl.getVisibility() == View.GONE) {
|
||||
bindingControls.mainControl.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (streamAudio != null) {
|
||||
if (!VmAudioManager.currentVmId.equals(Config.vmID)) streamAudio.setCross(null);
|
||||
if (streamAudio.isPlaying()) streamAudio.stop();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void keyDownUp(int keyEventCode) {
|
||||
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
|
||||
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
|
||||
}
|
||||
|
||||
|
||||
private void sendKey(int keyEventCode, boolean up) {
|
||||
if (up)
|
||||
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
|
||||
else dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
unregisterReceiver(receiver);
|
||||
if (streamAudio != null) streamAudio.stop();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
|
|
@ -790,7 +814,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
v.startDragAndDrop(
|
||||
ClipData.newPlainText("", ""),
|
||||
new View.DragShadowBuilder(binding.buttonVisibility) {
|
||||
public void onDrawShadow(@NonNull Canvas canvas) {}
|
||||
public void onDrawShadow(@NonNull Canvas canvas) {
|
||||
}
|
||||
},
|
||||
null,
|
||||
View.DRAG_FLAG_GLOBAL);
|
||||
|
|
@ -927,48 +952,46 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
startTime = SystemClock.uptimeMillis();
|
||||
binding.mouseButtonsPosition.setPressed(true);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
{
|
||||
int[] offset = new int[2];
|
||||
int[] offset2 = new int[2];
|
||||
binding.mouseButtons.getLocationOnScreen(offset);
|
||||
binding.frame.getLocationOnScreen(offset2);
|
||||
binding.mouseButtons.setX(
|
||||
MathUtils.clamp(
|
||||
offset[0] - startOffset[0] + e.getX(),
|
||||
offset2[0],
|
||||
offset2[0]
|
||||
+ binding.frame.getWidth()
|
||||
- binding.mouseButtons.getWidth()));
|
||||
binding.mouseButtons.setY(
|
||||
MathUtils.clamp(
|
||||
offset[1] - startOffset[1] + e.getY(),
|
||||
offset2[1],
|
||||
offset2[1]
|
||||
+ binding.frame.getHeight()
|
||||
- binding.mouseButtons.getHeight()));
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
{
|
||||
final int[] _pos = new int[2];
|
||||
binding.mouseButtons.getLocationOnScreen(_pos);
|
||||
int deltaX =
|
||||
(int) (startOffset[0] - e.getX())
|
||||
+ (startPosition[0] - _pos[0]);
|
||||
int deltaY =
|
||||
(int) (startOffset[1] - e.getY())
|
||||
+ (startPosition[1] - _pos[1]);
|
||||
binding.mouseButtonsPosition.setPressed(false);
|
||||
case MotionEvent.ACTION_MOVE: {
|
||||
int[] offset = new int[2];
|
||||
int[] offset2 = new int[2];
|
||||
binding.mouseButtons.getLocationOnScreen(offset);
|
||||
binding.frame.getLocationOnScreen(offset2);
|
||||
binding.mouseButtons.setX(
|
||||
MathUtils.clamp(
|
||||
offset[0] - startOffset[0] + e.getX(),
|
||||
offset2[0],
|
||||
offset2[0]
|
||||
+ binding.frame.getWidth()
|
||||
- binding.mouseButtons.getWidth()));
|
||||
binding.mouseButtons.setY(
|
||||
MathUtils.clamp(
|
||||
offset[1] - startOffset[1] + e.getY(),
|
||||
offset2[1],
|
||||
offset2[1]
|
||||
+ binding.frame.getHeight()
|
||||
- binding.mouseButtons.getHeight()));
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP: {
|
||||
final int[] _pos = new int[2];
|
||||
binding.mouseButtons.getLocationOnScreen(_pos);
|
||||
int deltaX =
|
||||
(int) (startOffset[0] - e.getX())
|
||||
+ (startPosition[0] - _pos[0]);
|
||||
int deltaY =
|
||||
(int) (startOffset[1] - e.getY())
|
||||
+ (startPosition[1] - _pos[1]);
|
||||
binding.mouseButtonsPosition.setPressed(false);
|
||||
|
||||
if (deltaX * deltaX + deltaY * deltaY < touchSlop
|
||||
&& SystemClock.uptimeMillis() - startTime
|
||||
<= tapTimeout) {
|
||||
v.performClick();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
if (deltaX * deltaX + deltaY * deltaY < touchSlop
|
||||
&& SystemClock.uptimeMillis() - startTime
|
||||
<= tapTimeout) {
|
||||
v.performClick();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1067,8 +1090,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
binding.mouseButtons
|
||||
.setVisibility(
|
||||
p.getBoolean("showMouseHelper", false)
|
||||
&& "1".equals(p.getString("touchMode", "1"))
|
||||
&& mClientConnected
|
||||
&& "1".equals(p.getString("touchMode", "1"))
|
||||
&& mClientConnected
|
||||
? View.VISIBLE
|
||||
: View.GONE);
|
||||
|
||||
|
|
@ -1146,11 +1169,11 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
37.5f
|
||||
* getResources().getDisplayMetrics().density
|
||||
* (mExtraKeys.getExtraKeysInfo() == null
|
||||
? 0
|
||||
: mExtraKeys
|
||||
.getExtraKeysInfo()
|
||||
.getMatrix()
|
||||
.length));
|
||||
? 0
|
||||
: mExtraKeys
|
||||
.getExtraKeysInfo()
|
||||
.getMatrix()
|
||||
.length));
|
||||
terminalToolbarViewPager.setLayoutParams(layoutParams);
|
||||
}
|
||||
binding.frame.setPadding(
|
||||
|
|
@ -1158,8 +1181,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
0,
|
||||
0,
|
||||
preferences.getBoolean("adjustHeightForEK", false)
|
||||
&& terminalToolbarViewPager.getVisibility()
|
||||
== View.VISIBLE
|
||||
&& terminalToolbarViewPager.getVisibility()
|
||||
== View.VISIBLE
|
||||
? terminalToolbarViewPager.getHeight()
|
||||
: 0);
|
||||
},
|
||||
|
|
@ -1213,8 +1236,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
public boolean handleKey(KeyEvent e) {
|
||||
if (filterOutWinKey
|
||||
&& (e.getKeyCode() == KEYCODE_META_LEFT
|
||||
|| e.getKeyCode() == KEYCODE_META_RIGHT
|
||||
|| e.isMetaPressed())) return false;
|
||||
|| e.getKeyCode() == KEYCODE_META_RIGHT
|
||||
|| e.isMetaPressed())) return false;
|
||||
return mLorieKeyListener.onKey(getLorieView(), e.getKeyCode(), e);
|
||||
}
|
||||
|
||||
|
|
@ -1319,15 +1342,15 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
if (appOpsManager == null) return false;
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
return appOpsManager.unsafeCheckOpNoThrow(
|
||||
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
|
||||
android.os.Process.myUid(),
|
||||
context.getPackageName())
|
||||
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
|
||||
android.os.Process.myUid(),
|
||||
context.getPackageName())
|
||||
== AppOpsManager.MODE_ALLOWED;
|
||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||
return appOpsManager.checkOpNoThrow(
|
||||
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
|
||||
android.os.Process.myUid(),
|
||||
context.getPackageName())
|
||||
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
|
||||
android.os.Process.myUid(),
|
||||
context.getPackageName())
|
||||
== AppOpsManager.MODE_ALLOWED;
|
||||
else
|
||||
return false;
|
||||
|
|
@ -1384,8 +1407,8 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
binding.mouseButtons
|
||||
.setVisibility(
|
||||
p.getBoolean("showMouseHelper", false)
|
||||
&& "1".equals(p.getString("touchMode", "1"))
|
||||
&& mClientConnected
|
||||
&& "1".equals(p.getString("touchMode", "1"))
|
||||
&& mClientConnected
|
||||
? View.VISIBLE
|
||||
: View.GONE);
|
||||
binding.stub
|
||||
|
|
@ -1433,6 +1456,31 @@ public class X11Activity extends AppCompatActivity implements View.OnApplyWindow
|
|||
return mInputHandler.shouldInterceptKeys();
|
||||
}
|
||||
|
||||
private void setupSound() {
|
||||
if (streamAudio == null) {
|
||||
streamAudio = new StreamAudio(X11Activity.this);
|
||||
streamAudio.setFile(VmFileManager.findAudioRaw(X11Activity.this, Config.vmID));
|
||||
|
||||
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying())
|
||||
streamAudio.setCross(VmAudioManager.streamAudio);
|
||||
|
||||
playSound();
|
||||
}
|
||||
}
|
||||
|
||||
int playSoundRequests;
|
||||
|
||||
private void playSound() {
|
||||
if (streamAudio == null || streamAudio.isPlaying() || playSoundRequests > 0) return;
|
||||
playSoundRequests++;
|
||||
|
||||
streamAudio.stop();
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
if (!streamAudio.isPlaying()) streamAudio.play();
|
||||
playSoundRequests--;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
private void shutdownthisvm() {
|
||||
QmpSender.quickShutdown();
|
||||
Config.setDefault();
|
||||
|
|
|
|||
|
|
@ -195,6 +195,25 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:clickable="false"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="16dp" >
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="16dp"
|
||||
android:src="@drawable/info_24px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/x11_general_setting_note" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
|
|
|||
|
|
@ -750,6 +750,7 @@
|
|||
<string name="use_external_x11_note">Dùng ứng dụng Termux:X11 thay vì màn hình có sẵn.</string>
|
||||
<string name="blur_effect">Hiệu ứng mờ</string>
|
||||
<string name="blur_effect_note">Làm mờ xung quanh để tăng khả năng tập trung vào một vùng cần được chú ý.</string>
|
||||
<string name="x11_general_setting_note">Bạn cần khởi động lại ứng dụng khi chuyển đổi giữa tích hợp sẵn và ngoài.</string>
|
||||
|
||||
<!-- CPUs -->
|
||||
|
||||
|
|
|
|||
|
|
@ -603,6 +603,7 @@
|
|||
<string name="in_system_settings">In system settings.</string>
|
||||
<string name="missing_packages">Missing packages</string>
|
||||
<string name="missing_packages_content">These are the missing packages that you should install:</string>
|
||||
<string name="x11_general_setting_note">You need to restart the app when switching between built-in and external.</string>
|
||||
|
||||
|
||||
<!--======================TERMUX STRINGS====================-->
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ async function sendNotification() {
|
|||
title: "Vectras VM",
|
||||
message: "Welcome!",
|
||||
image: "https://github.com/xoureldeen/Vectras-VM-Android/blob/master/resources/vectrasvm.png",
|
||||
url : "https://github.com/xoureldeen/Vectras-VM-Android",
|
||||
//targetVersions: "3.9.0,3.9.1"
|
||||
url: "https://github.com/xoureldeen/Vectras-VM-Android",
|
||||
//activityClass: "update",
|
||||
//targetVersions: "4.1.0,4.2.0",
|
||||
targetVersions: ""
|
||||
},
|
||||
topic: "vectrasvmandroidgithub"
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ rm -rf /usr/share/qemu
|
|||
clear
|
||||
|
||||
echo -e "\e[1;37m[i] Downloading..."
|
||||
aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-vectras-vm-arm64-v8a.tar.gz
|
||||
aria2c -x 4 --async-dns=false --disable-ipv6 --check-certificate=false -o setup.tar.gz https://archive.org/download/qemu-7-2-22-for-vectras-vm-nbab/base-june-2026-vectras-vm-arm64-v8a.tar.gz
|
||||
clear
|
||||
|
||||
echo -e "\e[1;37m[i] Installing..."
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
|
||||
"Message": "<h2>4.1.0</h2>\nBugs fixed.",
|
||||
"cancellable": true,
|
||||
"versionCodeBeta":"127",
|
||||
"versionNameBeta":"4.2.3",
|
||||
"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.0,4.2.1,4.2.2,4.2.3",
|
||||
"versionCodeBeta":"128",
|
||||
"versionNameBeta":"4.2.4",
|
||||
"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.0,4.2.1,4.2.2,4.2.3,4.2.4",
|
||||
"sizeBeta": "45 MB",
|
||||
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
|
||||
"MessageBeta": "<h2>4.2.3</h2>Bugs fixed.",
|
||||
"MessageBeta": "<h2>4.2.4</h2>Bugs fixed.",
|
||||
"cancellableBeta": true
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue