Merge pull request #617 from AnBui2004/master

4.0.5
This commit is contained in:
An Bui 2026-04-27 18:56:08 +07:00 committed by GitHub
commit 46d70be632
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 125 additions and 44 deletions

View file

@ -12,8 +12,8 @@ android {
applicationId "com.vectras.vm"
minSdk minApi
targetSdk targetApi
versionCode 108
versionName "4.0.4"
versionCode 109
versionName "4.0.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true

View file

@ -86,7 +86,7 @@ class FullBufferBitmapData extends AbstractBitmapData {
// this fixes the issue with Nougat Devices displaying black screen for 24bit color mode C24bit
Bitmap bitmapTmp = Bitmap.createBitmap(framebufferwidth, framebufferheight, Config.bitmapConfig);
bitmapTmp.setPixels(bitmapPixels, offset(xo, yo), data.framebufferwidth, 0, 0, drawWidth, drawHeight);
canvas.drawBitmap(bitmapTmp, (float) vncCanvas.getWidth() / -2 + (float) framebufferwidth / 2, (float) vncCanvas.getHeight() / 2 - (float) framebufferheight / 2, null);
canvas.drawBitmap(bitmapTmp, 0, 0, null);
/*
}
@ -105,8 +105,8 @@ class FullBufferBitmapData extends AbstractBitmapData {
if(data.vncCanvas.connection.getUseLocalCursor())
{
// OneToOne
int locationX = vncCanvas.getWidth() / -2 + framebufferwidth / 2 + data.vncCanvas.mouseX;
int locationY = vncCanvas.getHeight() / 2 - framebufferheight / 2 + data.vncCanvas.mouseY;
int locationX = data.vncCanvas.mouseX;
int locationY = data.vncCanvas.mouseY;
if (vncCanvas.getScaleType() == ImageView.ScaleType.FIT_CENTER) {
// Full screen
@ -115,6 +115,7 @@ class FullBufferBitmapData extends AbstractBitmapData {
} else if (vncCanvas.getScaleType() == ImageView.ScaleType.FIT_XY){
// Scale to fit screen
locationX = vncCanvas.getWidth() / 2 + framebufferwidth / -2 + data.vncCanvas.mouseX;
locationY = vncCanvas.getHeight() / 2 - framebufferheight / 2 + data.vncCanvas.mouseY;
}
setCursorRect(locationX, locationY);

View file

@ -2193,6 +2193,9 @@ public class VncCanvas extends AppCompatImageView {
setScaleX((float) getWidth() / getImageWidth());
setScaleY((float) getHeight() / getImageHeight());
});
} else if (getScaleType() == ScaleType.FIT_CENTER || getScaleType() == ScaleType.FIT_START) {
setScaleX(1);
setScaleY(1);
}
}
@ -2208,6 +2211,18 @@ public class VncCanvas extends AppCompatImageView {
setScaleX((float) parent.getWidth() / getImageWidth());
setScaleY((float) parent.getHeight() / getImageHeight());
});
} else if (getScaleType() == ScaleType.FIT_CENTER || getScaleType() == ScaleType.FIT_START) {
setScaleX(1);
setScaleY(1);
}
}
public final ScaleType FULL_SCREEN_MODE = ScaleType.FIT_CENTER;
public final ScaleType STRETCH_TO_FIT_MODE = ScaleType.FIT_XY;
public final ScaleType ONE_TO_ONE_MODE = ScaleType.CENTER;
public void setScaleMode(ScaleType mode) {
setScaleType(mode);
setupScaleMode();
}
}

View file

@ -21,7 +21,10 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RenderEffect;
import android.graphics.Shader;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@ -115,7 +118,7 @@ public class MainVNCActivity extends VncCanvasActivity {
getContext = this;
UIUtils.edgeToEdge(this);
UIUtils.setOnApplyWindowInsetsListener(binding.vncMainLayout);
UIUtils.setOnApplyWindowInsetsListener(binding.vncControlLayout);
initializeControlFragment();
initializeDesktopControl();
initializeGameControl();
@ -170,7 +173,11 @@ public class MainVNCActivity extends VncCanvasActivity {
binding.lnNosignal.setOnClickListener(v -> {
// In VNCCanvasActivity.
// Do not attempt to reconnect while connected.
tryReconnect();
tryReconnect(false);
});
binding.lnConnecting.setOnClickListener(v -> {
});
ConnectionBean.useLocalCursor = MainSettingsManager.getShowVirtualMouse(this) || VMManager.isNeedUseVirtualMouse();
@ -178,7 +185,7 @@ public class MainVNCActivity extends VncCanvasActivity {
streamAudio = new StreamAudio(this);
streamAudio.setFile(VmFileManager.findAudioRaw(this, Config.vmID));
if (!isConnected) tryReconnect();
if (!isConnected) tryReconnect(false);
}
private void setDefaulViewMode() {
@ -448,12 +455,11 @@ public class MainVNCActivity extends VncCanvasActivity {
//Apply settings when connection is successful.
try {
vncCanvas.setupScaleMode(binding.main);
if (MainSettingsManager.getVNCScaleMode(this) == VNCConfig.oneToOne) {
AbstractScaling.getById(R.id.itemOneToOne)
.setScaleTypeForActivity(this);
vncCanvas.setScaleMode(vncCanvas.ONE_TO_ONE_MODE);
} else if (MainSettingsManager.getVNCScaleMode(this) == VNCConfig.scaleToFitScreen) {
vncCanvas.setScaleType(ImageView.ScaleType.FIT_XY);
vncCanvas.setupScaleMode(binding.main);
vncCanvas.setScaleMode(vncCanvas.STRETCH_TO_FIT_MODE);
}
} catch (Exception e) {
MainSettingsManager.setVNCScaleMode(this, VNCConfig.fitToScreen);
@ -780,6 +786,8 @@ public class MainVNCActivity extends VncCanvasActivity {
if (VmAudioManager.currentVmId.equals(Config.vmID) && VmAudioManager.streamAudio.isPlaying())
streamAudio.setCross(VmAudioManager.streamAudio);
if (!streamAudio.isPlaying()) streamAudio.play();
unBlurLayout();
});
}
@ -792,6 +800,8 @@ public class MainVNCActivity extends VncCanvasActivity {
if (!VmAudioManager.currentVmId.equals(Config.vmID)) streamAudio.setCross(null);
if (streamAudio.isPlaying()) streamAudio.stop();
blurLayout();
});
}
@ -819,19 +829,13 @@ public class MainVNCActivity extends VncCanvasActivity {
// }
} else {
// Try reconnect.
if (Config.forceRefeshVNCDisplay) {
startActivity(new Intent(this, MainVNCActivity.class));
overridePendingTransition(0, 0);
finish();
} else {
tryReconnect();
}
tryReconnect(true);
}
}
private boolean isTrying;
private void tryReconnect() {
private void tryReconnect(boolean forceRefeshVNCDisplay) {
if (isTrying) return;
isTrying = true;
@ -855,7 +859,7 @@ public class MainVNCActivity extends VncCanvasActivity {
binding.lnNosignal.setVisibility(View.VISIBLE);
binding.lnConnecting.setVisibility(View.GONE);
} else {
if (Config.forceRefeshVNCDisplay) {
if (forceRefeshVNCDisplay && Config.forceRefeshVNCDisplay) {
runOnUiThread(() -> {
startActivity(new Intent(MainVNCActivity.this, MainVNCActivity.class));
overridePendingTransition(0, 0);
@ -867,6 +871,12 @@ public class MainVNCActivity extends VncCanvasActivity {
binding.lnConnecting.setVisibility(View.GONE);
}
}
if (!isConnected) {
blurLayout();
} else {
unBlurLayout();
}
}
}
}, 0);
@ -911,19 +921,32 @@ public class MainVNCActivity extends VncCanvasActivity {
// Create and show the dialog.
LoggerDialogFragment newFragment = new LoggerDialogFragment();
newFragment.show(ft, "Logger");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
getSupportFragmentManager().executePendingTransactions();
if (newFragment.getDialog() == null) return;
blurLayout();
newFragment.getDialog().setOnDismissListener(d -> unBlurLayout());
}
});
bindingControls.shutdownBtn.setOnClickListener(v -> DialogUtils.threeDialog(this, getString(R.string.power), getString(R.string.shutdown_or_reset_content_vnc), getString(R.string.shutdown), getString(R.string.reset), getString(R.string.power), true, R.drawable.power_settings_new_24px, true,
this::shutdownthisvm, QmpSender::quickReset, VMManager::pressPowerButton, null));
bindingControls.shutdownBtn.setOnClickListener(v -> {
blurLayout();
DialogUtils.threeDialog(this, getString(R.string.power), getString(R.string.shutdown_or_reset_content_vnc), getString(R.string.shutdown), getString(R.string.reset), getString(R.string.power), true, R.drawable.power_settings_new_24px, true,
this::shutdownthisvm, QmpSender::quickReset, VMManager::pressPowerButton, this::unBlurLayout);
});
bindingControls.shutdownBtn.setOnLongClickListener(view -> {
blurLayout();
DialogUtils.twoDialog(this, "Exit", "You will be left here but the virtual machine will continue to run.", "Exit", getString(R.string.cancel), true, R.drawable.exit_to_app_24px, true,
() -> {
started = false;
if (!VmAudioManager.currentVmId.equals(Config.vmID))
streamAudio.setCross(null);
finish();
}, null, null);
}, null, this::unBlurLayout);
return false;
});
@ -957,9 +980,41 @@ public class MainVNCActivity extends VncCanvasActivity {
vmControllerDialog.vncCanvas = vncCanvas;
vmControllerDialog.streamAudio = streamAudio;
vmControllerDialog.show(getSupportFragmentManager(), "VmControllerDialog");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
getSupportFragmentManager().executePendingTransactions();
blurLayout();
vmControllerDialog.setOnDismissCallback(this::unBlurLayout);
}
});
}
boolean isBlurring;
private void blurLayout() {
if (isBlurring) return;
isBlurring = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
RenderEffect blurEffect = RenderEffect.createBlurEffect(
25f, 25f,
Shader.TileMode.CLAMP
);
binding.vncCanvasLayout.setRenderEffect(blurEffect);
binding.vncControlLayout.setRenderEffect(blurEffect);
}
}
private void unBlurLayout() {
if (!isBlurring) return;
isBlurring = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
binding.vncCanvasLayout.setRenderEffect(null);
binding.vncControlLayout.setRenderEffect(null);
}
}
private void initializeDesktopControl() {
bindingDesktopControls.upBtn.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {

View file

@ -3,6 +3,7 @@ package com.vectras.vm.manager;
import android.androidVNC.ConnectionBean;
import android.androidVNC.VncCanvas;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
@ -17,7 +18,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.color.MaterialColors;
import com.vectras.qemu.Config;
import com.vectras.qemu.MainSettingsManager;
import com.vectras.qemu.MainVNCActivity;
@ -117,6 +117,7 @@ public class VmControllerDialog extends DialogFragment {
}
if (streamAudio == null ||
!isAdded() ||
FileUtils.getFileSize(VmFileManager.findAudioRaw(requireContext(), Config.vmID)) == 0 ||
(isAdded() && (!(requireActivity() instanceof MainVNCActivity)) && !VmAudioManager.currentVmId.equals(Config.vmID))
) {
@ -299,9 +300,7 @@ public class VmControllerDialog extends DialogFragment {
if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.oneToOne) return;
MainSettingsManager.setVNCScaleMode(requireActivity(), VNCConfig.oneToOne);
requireActivity().startActivity(new Intent(requireActivity(), MainVNCActivity.class));
requireActivity().overridePendingTransition(0, 0);
requireActivity().finish();
requireActivity().recreate();
dismiss();
});
@ -309,9 +308,7 @@ public class VmControllerDialog extends DialogFragment {
if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.fitToScreen) return;
MainSettingsManager.setVNCScaleMode(requireActivity(), VNCConfig.fitToScreen);
requireActivity().startActivity(new Intent(requireActivity(), MainVNCActivity.class));
requireActivity().overridePendingTransition(0, 0);
requireActivity().finish();
requireActivity().recreate();
dismiss();
});
@ -319,9 +316,7 @@ public class VmControllerDialog extends DialogFragment {
if (MainSettingsManager.getVNCScaleMode(requireActivity()) == VNCConfig.scaleToFitScreen) return;
MainSettingsManager.setVNCScaleMode(requireActivity(), VNCConfig.scaleToFitScreen);
requireActivity().startActivity(new Intent(requireActivity(), MainVNCActivity.class));
requireActivity().overridePendingTransition(0, 0);
requireActivity().finish();
requireActivity().recreate();
dismiss();
});
} else {
@ -333,6 +328,20 @@ public class VmControllerDialog extends DialogFragment {
return dialog;
}
private Runnable onDismissCallback;
public void setOnDismissCallback(Runnable callback) {
this.onDismissCallback = callback;
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissCallback != null) {
onDismissCallback.run();
}
}
private void takeScreenshot() {
ProgressDialog progressDialog = new ProgressDialog(requireActivity());
progressDialog.setText(getString(R.string.taking_a_screenshot));

View file

@ -9,6 +9,7 @@
android:orientation="vertical">
<RelativeLayout
android:id="@+id/vnc_main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -31,7 +32,7 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/vnc_main_layout"
android:id="@+id/vnc_control_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
@ -71,7 +72,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.8"
android:background="?attr/colorSurfaceContainer" />
android:background="#E6000000" />
<LinearLayout
android:layout_width="match_parent"
@ -83,21 +84,21 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/cast_warning_24px"
app:tint="?attr/colorOnSurface" />
app:tint="@android:color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/no_signal"
android:textColor="?attr/colorOnSurface"
android:textColor="@android:color/white"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tap_to_try_again"
android:textColor="?attr/colorOnSurface" />
android:textColor="@android:color/white" />
</LinearLayout>
</FrameLayout>
@ -112,7 +113,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.8"
android:background="?attr/colorSurfaceContainer" />
android:background="#E6000000" />
<LinearLayout
android:layout_width="match_parent"

View file

@ -5,11 +5,11 @@
"url": "https://github.com/xoureldeen/Vectras-VM-Android/releases",
"Message": "<h2>4.0.0</h2>\nBugs fixed.",
"cancellable": true,
"versionCodeBeta":"108",
"versionNameBeta":"4.0.4",
"versionNameBetas":"4.0.0,4.0.1,4.0.2,4.0.3,4.0.4",
"versionCodeBeta":"109",
"versionNameBeta":"4.0.5",
"versionNameBetas":"4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5",
"sizeBeta": "45 MB",
"urlBeta": "https://github.com/AnBui2004/Vectras-VM-Emu-Android/releases",
"MessageBeta": "<h2>4.0.4</h2>Bugs fixed.",
"MessageBeta": "<h2>4.0.5</h2>Bugs fixed.",
"cancellableBeta": true
}