This commit is contained in:
Epic Studios 2024-01-13 05:49:49 +02:00
parent 7350c7cc47
commit a512997f38
27 changed files with 2237 additions and 1584 deletions

View file

@ -1,4 +1,4 @@
![logo](https://raw.githubusercontent.com/epicstudios856/Vectras-VM-Android/master/resources/vectras-logo.png)
![logo](https://github.com/ahmedbarakat2007/Vectras-windows-emulator/assets/118398763/096d4a06-8d3c-489f-9fb5-d273f361200c)
[![Telegram Channel][ico-telegram]][link-telegram]
[![Latest Version][ico-version]][link-releases]
[![Software License][ico-license]](LICENSE.md)

View file

@ -20,8 +20,8 @@ android {
applicationId "com.vectras.vm"
minSdk 21
targetSdk 34
versionCode 6
versionName "2.2"
versionCode 7
versionName "2.3"
ndk { abiFilters "armeabi-v7a","arm64-v8a", "x86", "x86_64" }
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -53,8 +53,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.7.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation 'androidx.navigation:navigation-fragment:2.7.6'

View file

@ -98,7 +98,9 @@
<activity
android:name="com.vectras.qemu.MainSDLActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize"
android:launchMode="singleTask" />
android:launchMode="singleTask"
android:theme="@style/Theme.FullScreen"
android:windowSoftInputMode="adjustPan" />
<activity
android:name="com.vectras.qemu.MainVNCActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize"

View file

@ -2,7 +2,7 @@ package android.androidVNC;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;
import android.content.DialogInterface;

View file

@ -26,6 +26,8 @@ import android.os.Environment;
import android.widget.ImageView.ScaleType;
import com.vectras.vm.AppConfig;
import com.vectras.vm.SplashActivity;
import com.vectras.vm.VectrasApp;
import java.util.Hashtable;
import java.util.LinkedHashMap;
@ -116,7 +118,7 @@ public class Config {
public static String getMachineDir(){
return getBasefileDir() + machineFolder;
}
public static String logFilePath = null;
public static String logFilePath = cacheDir + "/vectras/vectras-log.txt";
public static final String defaultDNSServer = "8.8.8.8";
@ -176,7 +178,9 @@ public class Config {
//Change to true in prod if you want to be notified by default for new versions
public static boolean defaultCheckNewVersion = true;
public static final String sharedFolder = AppConfig.sharedFolder;
// App config
public static final String datadirpath = VectrasApp.getApp().getExternalFilesDir("data")+"/";
public static final String sharedFolder = datadirpath + "Vectras/ProgramFiles/";
public static String machinename = "VECTRAS";
public static int paused = 0;

File diff suppressed because it is too large Load diff

View file

@ -248,7 +248,7 @@ public class MainSettingsManager extends AppCompatActivity
implements Preference.OnPreferenceChangeListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);/*
Preference pref = findPreference("customMemory");
if (pref != null) {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@ -278,7 +278,7 @@ public class MainSettingsManager extends AppCompatActivity
}
});
}
}*/
}
private void onMemory() {
@ -629,6 +629,61 @@ public class MainSettingsManager extends AppCompatActivity
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getBoolean("virtio", false);
}
public static void setAvx(Activity activity, boolean AVX) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("AVX", AVX);
edit.apply();
}
public static boolean getAvx(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getBoolean("AVX", false);
}
public static void setTbSize(Activity activity, String TbSize) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("TbSize", TbSize);
edit.apply();
}
public static String getTbSize(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getString("TbSize", "2048");
}
public static void setVmUi(Activity activity, String vmUi) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("vmUi", vmUi);
edit.apply();
}
public static String getVmUi(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getString("vmUi", "VNC");
}
public static void setUsbTablet(Activity activity, boolean UsbTablet) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("UsbTablet", UsbTablet);
edit.apply();
}
public static boolean getUsbTablet(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getBoolean("UsbTablet", false);
}
public static void setCustomParams(Activity activity, String customParams) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("customParams", customParams);
edit.apply();
}
public static String getCustomParams(Activity activity) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
return prefs.getString("customParams", "");
}
public static boolean isFirstLaunch(Activity activity) {
PackageInfo pInfo = null;

View file

@ -6,12 +6,14 @@ import android.androidVNC.VncCanvasActivity;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.core.view.MenuItemCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentTransaction;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
@ -51,6 +53,7 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.vectras.qemu.utils.FileUtils;
import com.vectras.vm.Fragment.ControlersOptionsFragment;
import com.vectras.vm.MainActivity;
import com.vectras.vm.R;
@ -124,8 +127,15 @@ public class MainVNCActivity extends VncCanvasActivity {
ImageButton ctrlBtn = findViewById(R.id.ctrlBtn);
ImageButton altBtn = findViewById(R.id.altBtn);
ImageButton delBtn = findViewById(R.id.delBtn);
ImageButton btnLogs = findViewById(R.id.btnLogs);
Button ctrlAltDelBtn = findViewById(R.id.ctrlAltDelBtn);
qmpBtn = findViewById(R.id.btnQmp);
btnLogs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FileUtils.viewVectrasLog(activity);
}
});
shutdownBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -1184,20 +1194,11 @@ public class MainVNCActivity extends VncCanvasActivity {
}
public void onBackPressed() {
// super.onBackPressed();
if (!MainSettingsManager.getAlwaysShowMenuToolbar(activity)) {
ActionBar bar = this.getSupportActionBar();
if (bar != null) {
if (bar.isShowing() && Config.mouseMode == Config.MouseMode.Trackpad) {
bar.hide();
}/* else
bar.show();*/
}
} else
super.onBackPressed();
super.onBackPressed();
Machine.stopVM(activity);
return;
}
public void onHideToolbar() {

View file

@ -64,22 +64,22 @@ public class StartVM {
public String vnc_passwd = "vectras";
// cpu/board settings
private String cpu;
public String cpu;
private String arch = "x86";
private String machine_type;
private int memory = 128;
public int memory = 128;
private int cpuNum = 1;
public int enablekvm;
public int enable_mttcg;
// disks
public String hda_img_path;
private String hdb_img_path;
private String hdc_img_path;
private String hdd_img_path;
public String hdb_img_path;
public String hdc_img_path;
public String hdd_img_path;
public String shared_folder_path;
public int shared_folder_readonly = 1;
private String hd_cache = "default";
public String hd_cache = "default";
//removable devices
public String cd_iso_path;
@ -88,26 +88,30 @@ public class StartVM {
public String sd_img_path;
//boot options
private String bootdevice = null;
public String bootdevice = null;
private String kernel;
private String initrd;
//graphics
private String vga_type = "std";
public String vga_type = "std";
//audio
public String sound_card;
// net
private String net_cfg = "None";
private String nic_card = null;
public String net_cfg = "None";
public String nic_card = null;
private String hostfwd = null;
private String guestfwd = null;
//advanced
private int disableacpi = 0;
private int disablehpet = 0;
private int disabletsc = 0;
public int disableacpi = 0;
public int disablehpet = 0;
public int disabletsc = 0;
public boolean enablleAvx = false;
public String tbSize = "2048";
public String extra_params;
/**
@ -120,7 +124,11 @@ public class StartVM {
save_dir = Config.getMachineDir() + name;
save_state_name = save_dir + "/" + Config.state_filename;
hda_img_path = Config.hda_path;
extra_params = Config.extra_params;
extra_params += " ";
extra_params += MainSettingsManager.getCustomParams(MainActivity.activity);
shared_folder_path = Config.sharedFolder;
//extra_params = Config.extra_params;
this.context = context;
@ -133,6 +141,14 @@ public class StartVM {
this.enable_mttcg = 0;
this.vnc_allow_external = 0;
this.enablleAvx = MainSettingsManager.getAvx(MainActivity.activity);
this.tbSize = MainSettingsManager.getTbSize(MainActivity.activity);
if (MainSettingsManager.getUsbTablet(MainActivity.activity))
this.mouse = "usb-tablet";
else
this.mouse = "ps2";
}
public static void onVMResolutionChanged(int width, int height) {
@ -283,7 +299,8 @@ public class StartVM {
}
if (mouse != null && !mouse.equals("ps2")) {
paramsList.add("-usb");
paramsList.add("-machine");
paramsList.add("usb=on");
paramsList.add("-device");
paramsList.add(mouse);
}
@ -309,7 +326,7 @@ public class StartVM {
private void addAudioOptions(ArrayList<String> paramsList) {
if (sound_card != null && !sound_card.equals("None")) {
if (sound_card != null && !sound_card.equals("None") && enablevnc != 1) {
paramsList.add("-soundhw");
paramsList.add(sound_card);
}
@ -384,7 +401,7 @@ public class StartVM {
if (this.cpuNum > 1 &&
(enablekvm == 1 || enable_mttcg == 1 || !Config.enableSMPOnlyOnKVM)) {
paramsList.add("-smp");
paramsList.add("sockets="+"1"+",cores="+this.cpuNum+",threads="+this.cpuNum+"");
paramsList.add("sockets=" + "1" + ",cores=" + this.cpuNum + ",threads=" + this.cpuNum + "");
}
if (machine_type != null && !machine_type.equals("Default")) {
@ -411,7 +428,11 @@ public class StartVM {
if (this.cpu != null && !cpu.equals("Default")) {
paramsList.add("-cpu");
paramsList.add(cpu + ",+avx");
String cpuParams = null;
cpuParams += cpu;
if (enablleAvx)
cpuParams += ",+avx";
paramsList.add(cpuParams);
}
@ -429,7 +450,7 @@ public class StartVM {
tcgParams += ",thread=multi";
else
tcgParams += ",thread=single";
tcgParams += ",tb-size=2048";
tcgParams += ",tb-size=" + tbSize;
paramsList.add(tcgParams);
//#endif
}

View file

@ -1,13 +1,15 @@
package com.vectras.qemu.utils;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import com.vectras.qemu.Config;
import com.vectras.vm.MainActivity;
import com.vectras.vm.R;

View file

@ -1,5 +1,6 @@
package com.vectras.vm.Fragment;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@ -21,6 +22,7 @@ import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -28,6 +30,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.vectras.vm.R;
import com.vectras.vm.RomsManagerActivity;
import com.vectras.vm.MainActivity;
import com.vectras.vm.VectrasApp;
import com.vectras.vm.adapter.LogsAdapter;
import com.vectras.vm.logger.VectrasStatus;
import com.vectras.vm.utils.UIUtils;
@ -46,20 +49,21 @@ import java.util.TimerTask;
public class LoggerFragment extends Fragment {
View view;
MainActivity activity = MainActivity.activity;
private final String CREDENTIAL_SHARED_PREF = "settings_prefs";
private LogsAdapter mLogAdapter;
private RecyclerView logList;
private Timer _timer = new Timer();
private TimerTask t;
Activity activity;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// TODO Auto-generated method stub
view = inflater.inflate(R.layout.fragment_logs, container, false);
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.activity);
mLogAdapter = new LogsAdapter(layoutManager, MainActivity.activity);
activity = getActivity();
LinearLayoutManager layoutManager = new LinearLayoutManager(VectrasApp.getApp());
mLogAdapter = new LogsAdapter(layoutManager, VectrasApp.getApp());
logList = (RecyclerView) view.findViewById(R.id.recyclerLog);
logList.setAdapter(mLogAdapter);
logList.setLayoutManager(layoutManager);

View file

@ -6,6 +6,7 @@ import android.androidVNC.RfbProto;
import android.androidVNC.VncCanvas;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
@ -49,6 +50,7 @@ import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.vectordrawable.graphics.drawable.ArgbEvaluator;
import androidx.viewpager.widget.ViewPager;
@ -71,6 +73,7 @@ import com.vectras.qemu.utils.Machine;
import com.vectras.qemu.utils.QmpClient;
import com.vectras.vm.Fragment.HomeFragment;
import com.vectras.vm.Fragment.LoggerFragment;
import com.vectras.vm.MainRoms.AdapterMainRoms;
import com.vectras.vm.logger.VectrasStatus;
import com.vectras.vm.utils.AppUpdater;
import com.vectras.qemu.utils.FileInstaller;
@ -146,7 +149,6 @@ public class MainActivity extends AppCompatActivity {
setupStrictMode();
execTimer();
checkAndLoadLibs();
Config.logFilePath = Config.cacheDir + "/vectras/vectras-log.txt";
activity = this;
this.setContentView(R.layout.main);
this.setupWidgets();
@ -446,7 +448,7 @@ public class MainActivity extends AppCompatActivity {
}
});
if (MainSettingsManager.getPromptUpdateVersion(activity))
updateApp(true);
updateApp(false);
/*FirebaseUser user = mAuth.getCurrentUser();
TextView usernameTxt = findViewById(R.id.usernameTxt);
TextView emailTxt = findViewById(R.id.emailTxt);
@ -476,6 +478,12 @@ public class MainActivity extends AppCompatActivity {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(activity, R.style.MainDialogTheme).create();
alertDialog.setTitle("JOIN US ON TELEGRAM");
TextView title = alertDialog.findViewById(R.id.title_text);
ObjectAnimator rgbAnim=ObjectAnimator.ofObject(title,"textColor",new ArgbEvaluator(), Color.RED,Color.GREEN,Color.BLUE);
rgbAnim.setDuration(1000);
rgbAnim.setRepeatMode(ValueAnimator.REVERSE);
rgbAnim.setRepeatCount(ValueAnimator.INFINITE);
rgbAnim.start();
alertDialog.setMessage("Join us on Telegram where we publish all the news and updates and receive your opinions and bugs");
alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "JOIN", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
@ -533,6 +541,7 @@ public class MainActivity extends AppCompatActivity {
}
@SuppressLint("NotifyDataSetChanged")
@Override
public void onStart() {
super.onStart();
@ -541,6 +550,8 @@ public class MainActivity extends AppCompatActivity {
} else {
Config.hd_if_type = "ide";
}
setupFolders();
Config.ui = MainSettingsManager.getVmUi(activity);
InterstitialAd.load(this, "ca-app-pub-3568137780412047/7745973511", adRequest,
new InterstitialAdLoadCallback() {
@Override
@ -756,21 +767,18 @@ public class MainActivity extends AppCompatActivity {
}
public static void setupFolders() {
Thread t = new Thread(new Runnable() {
public void run() {
try {
Config.cacheDir = activity.getCacheDir().getAbsolutePath();
Config.storagedir = Environment.getDataDirectory().toString();
Config.cacheDir = activity.getCacheDir().getAbsolutePath();
Config.storagedir = Environment.getExternalStorageDirectory().toString();
// Create Temp folder
File folder = new File(Config.getTmpFolder());
if (!folder.exists())
folder. mkdirs();
// Create Temp folder
File folder = new File(Config.getTmpFolder());
if (!folder.exists())
folder.mkdirs();
} catch (Exception ignored) {
}
});
t.start();
}
}
//XXX: sometimes this needs to be called from the main thread otherwise

View file

@ -1,7 +1,7 @@
package com.vectras.vm.utils;
import android.app.Activity;
import android.app.AlertDialog;
import androidx.appcompat.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;

View file

@ -207,11 +207,11 @@ public class SDLActivity extends AppCompatActivity {
mClipboardHandler = new SDLClipboardHandler_Old();
}
//Vectras: override
//Limbo: override
// Set up the surface
//mSurface = new SDLSurface(getApplication());
//Vectras: override
//Limbo: override
//mLayout = new RelativeLayout(this);
//mLayout.addView(mSurface);
@ -1079,7 +1079,7 @@ public class SDLActivity extends AppCompatActivity {
mClipboardHandler.clipboardSetText(string);
}
//Vectras:
//Limbo:
protected void runSDLMain(){
}
@ -1105,7 +1105,7 @@ class SDLMain implements Runnable {
Log.v("SDL", "Running main function " + function + " from library " + library);
//Vectras: we override
//Limbo: we override
//SDLActivity.nativeRunMain(library, function, arguments);
SDLActivity.mSingleton.runSDLMain();
@ -1122,375 +1122,6 @@ class SDLMain implements Runnable {
}
/**
SDLSurface. This is what we draw on, so we need to know when it's created
in order to do anything useful.
Because of this, that's where we set up the SDL thread
*/
//Vectras: should be public
class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
// Sensors
protected static SensorManager mSensorManager;
protected static Display mDisplay;
// Keep track of the surface size to normalize touch events
protected static float mWidth, mHeight;
// Startup
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
if (Build.VERSION.SDK_INT >= 12) {
setOnGenericMotionListener(new SDLGenericMotionListener_API12());
}
// Some arbitrary defaults to avoid a potential division by zero
mWidth = 1.0f;
mHeight = 1.0f;
}
public void handlePause() {
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
}
public void handleResume() {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
}
public Surface getNativeSurface() {
return getHolder().getSurface();
}
// Called when we have a valid drawing surface
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
// Called when we lose the surface
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL", "surfaceDestroyed()");
// Transition to pause, if needed
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
SDLActivity.handleNativeState();
SDLActivity.mIsSurfaceReady = false;
SDLActivity.onNativeSurfaceDestroyed();
}
// Called when the surface is resized
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
Log.v("SDL", "surfaceChanged()");
int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
switch (format) {
case PixelFormat.A_8:
Log.v("SDL", "pixel format A_8");
break;
case PixelFormat.LA_88:
Log.v("SDL", "pixel format LA_88");
break;
case PixelFormat.L_8:
Log.v("SDL", "pixel format L_8");
break;
case PixelFormat.RGBA_4444:
Log.v("SDL", "pixel format RGBA_4444");
sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
break;
case PixelFormat.RGBA_5551:
Log.v("SDL", "pixel format RGBA_5551");
sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
break;
case PixelFormat.RGBA_8888:
Log.v("SDL", "pixel format RGBA_8888");
sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
break;
case PixelFormat.RGBX_8888:
Log.v("SDL", "pixel format RGBX_8888");
sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
break;
case PixelFormat.RGB_332:
Log.v("SDL", "pixel format RGB_332");
sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
break;
case PixelFormat.RGB_565:
Log.v("SDL", "pixel format RGB_565");
sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
break;
case PixelFormat.RGB_888:
Log.v("SDL", "pixel format RGB_888");
// Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
break;
default:
Log.v("SDL", "pixel format unknown " + format);
break;
}
mWidth = width;
mHeight = height;
SDLActivity.onNativeResize(width, height, sdlFormat, mDisplay.getRefreshRate());
Log.v("SDL", "Window size: " + width + "x" + height);
boolean skip = false;
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
{
// Accept any
}
else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT)
{
if (mWidth > mHeight) {
skip = true;
}
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
if (mWidth < mHeight) {
skip = true;
}
}
// Special Patch for Square Resolution: Black Berry Passport
if (skip) {
double min = Math.min(mWidth, mHeight);
double max = Math.max(mWidth, mHeight);
if (max / min < 1.20) {
Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
skip = false;
}
}
if (skip) {
Log.v("SDL", "Skip .. Surface is not ready.");
SDLActivity.mIsSurfaceReady = false;
return;
}
/* Surface is ready */
SDLActivity.mIsSurfaceReady = true;
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
SDLActivity.onNativeSurfaceChanged();
SDLActivity.handleNativeState();
}
// Key events
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// Dispatch the different events depending on where they come from
// Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
// So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
//
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
// So, retrieve the device itself and check all of its sources
if (SDLControllerManager.isDeviceSDLJoystick(event.getDeviceId())) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(event.getDeviceId(), keyCode) == 0) {
return true;
}
}
}
if ((event.getSource() & InputDevice.SOURCE_KEYBOARD) != 0) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
//Log.v("SDL", "key down: " + keyCode);
if (SDLActivity.isTextInputEvent(event)) {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
SDLActivity.onNativeKeyDown(keyCode);
return true;
}
else if (event.getAction() == KeyEvent.ACTION_UP) {
//Log.v("SDL", "key up: " + keyCode);
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
}
if ((event.getSource() & InputDevice.SOURCE_MOUSE) != 0) {
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
// they are ignored here because sending them as mouse input to SDL is messy
if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
case KeyEvent.ACTION_UP:
// mark the event as handled or it will be handled by system
// handling KEYCODE_BACK by system will call onBackPressed()
return true;
}
}
}
return false;
}
// Touch events
@Override
public boolean onTouch(View v, MotionEvent event) {
/* Ref: http://developer.android.com/training/gestures/multi.html */
final int touchDevId = event.getDeviceId();
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int mouseButton;
int i = -1;
float x,y,p;
// !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) {
if (Build.VERSION.SDK_INT < 14) {
mouseButton = 1; // all mouse buttons are the left button
} else {
try {
mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event);
} catch(Exception e) {
mouseButton = 1; // oh well.
}
}
SDLActivity.onSDLNativeMouse(mouseButton, action, event.getX(0), event.getY(0));
} else {
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onSDLNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onSDLNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onSDLNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
default:
break;
}
}
return true;
}
// Sensor events
public void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
} else {
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x, y;
switch (mDisplay.getRotation()) {
case Surface.ROTATION_90:
x = -event.values[1];
y = event.values[0];
break;
case Surface.ROTATION_270:
x = event.values[1];
y = -event.values[0];
break;
case Surface.ROTATION_180:
x = -event.values[1];
y = -event.values[0];
break;
default:
x = event.values[0];
y = event.values[1];
break;
}
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
y / SensorManager.GRAVITY_EARTH,
event.values[2] / SensorManager.GRAVITY_EARTH);
}
}
}
/* This is a fake invisible editor view that receives the input and defines the
* pan&scan region
*/

View file

@ -0,0 +1,384 @@
package org.libsdl.app;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
/**
* SDLSurface. This is what we draw on, so we need to know when it's created
* in order to do anything useful.
* <p>
* Because of this, that's where we set up the SDL thread
*/
//Limbo: should be public
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
// Sensors
protected static SensorManager mSensorManager;
protected static Display mDisplay;
// Keep track of the surface size to normalize touch events
protected static float mWidth, mHeight;
// Startup
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
mDisplay = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
if (Build.VERSION.SDK_INT >= 12) {
setOnGenericMotionListener(new SDLGenericMotionListener_API12());
}
// Some arbitrary defaults to avoid a potential division by zero
mWidth = 1.0f;
mHeight = 1.0f;
}
public void handlePause() {
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
}
public void handleResume() {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
}
public Surface getNativeSurface() {
return getHolder().getSurface();
}
// Called when we have a valid drawing surface
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
// Called when we lose the surface
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL", "surfaceDestroyed()");
// Transition to pause, if needed
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
SDLActivity.handleNativeState();
SDLActivity.mIsSurfaceReady = false;
SDLActivity.onNativeSurfaceDestroyed();
}
// Called when the surface is resized
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
Log.v("SDL", "surfaceChanged()");
int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
switch (format) {
case PixelFormat.A_8:
Log.v("SDL", "pixel format A_8");
break;
case PixelFormat.LA_88:
Log.v("SDL", "pixel format LA_88");
break;
case PixelFormat.L_8:
Log.v("SDL", "pixel format L_8");
break;
case PixelFormat.RGBA_4444:
Log.v("SDL", "pixel format RGBA_4444");
sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
break;
case PixelFormat.RGBA_5551:
Log.v("SDL", "pixel format RGBA_5551");
sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
break;
case PixelFormat.RGBA_8888:
Log.v("SDL", "pixel format RGBA_8888");
sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
break;
case PixelFormat.RGBX_8888:
Log.v("SDL", "pixel format RGBX_8888");
sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
break;
case PixelFormat.RGB_332:
Log.v("SDL", "pixel format RGB_332");
sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
break;
case PixelFormat.RGB_565:
Log.v("SDL", "pixel format RGB_565");
sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
break;
case PixelFormat.RGB_888:
Log.v("SDL", "pixel format RGB_888");
// Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
break;
default:
Log.v("SDL", "pixel format unknown " + format);
break;
}
mWidth = width;
mHeight = height;
SDLActivity.onNativeResize(width, height, sdlFormat, mDisplay.getRefreshRate());
Log.v("SDL", "Window size: " + width + "x" + height);
boolean skip = false;
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
// Accept any
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
if (mWidth > mHeight) {
skip = true;
}
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
if (mWidth < mHeight) {
skip = true;
}
}
// Special Patch for Square Resolution: Black Berry Passport
if (skip) {
double min = Math.min(mWidth, mHeight);
double max = Math.max(mWidth, mHeight);
if (max / min < 1.20) {
Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
skip = false;
}
}
if (skip) {
Log.v("SDL", "Skip .. Surface is not ready.");
SDLActivity.mIsSurfaceReady = false;
return;
}
/* Surface is ready */
SDLActivity.mIsSurfaceReady = true;
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
SDLActivity.onNativeSurfaceChanged();
SDLActivity.handleNativeState();
}
// Key events
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// Dispatch the different events depending on where they come from
// Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
// So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
//
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
// So, retrieve the device itself and check all of its sources
if (SDLControllerManager.isDeviceSDLJoystick(event.getDeviceId())) {
// Note that we process events with specific key codes here
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLControllerManager.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
return true;
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (SDLControllerManager.onNativePadUp(event.getDeviceId(), keyCode) == 0) {
return true;
}
}
}
if ((event.getSource() & InputDevice.SOURCE_KEYBOARD) != 0) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
//Log.v("SDL", "key down: " + keyCode);
if (SDLActivity.isTextInputEvent(event)) {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
SDLActivity.onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
//Log.v("SDL", "key up: " + keyCode);
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
}
if ((event.getSource() & InputDevice.SOURCE_MOUSE) != 0) {
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
// they are ignored here because sending them as mouse input to SDL is messy
if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
case KeyEvent.ACTION_UP:
// mark the event as handled or it will be handled by system
// handling KEYCODE_BACK by system will call onBackPressed()
return true;
}
}
}
return false;
}
// Touch events
@Override
public boolean onTouch(View v, MotionEvent event) {
/* Ref: http://developer.android.com/training/gestures/multi.html */
final int touchDevId = event.getDeviceId();
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int mouseButton;
int i = -1;
float x, y, p;
// !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) {
if (Build.VERSION.SDK_INT < 14) {
mouseButton = 1; // all mouse buttons are the left button
} else {
try {
mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event);
} catch (Exception e) {
mouseButton = 1; // oh well.
}
}
SDLActivity.onSDLNativeMouse(mouseButton, action, event.getX(0), event.getY(0));
} else {
switch (action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onSDLNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onSDLNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
if (p > 1.0f) {
// may be larger than 1.0f on some devices
// see the documentation of getPressure(i)
p = 1.0f;
}
SDLActivity.onSDLNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
default:
break;
}
}
return true;
}
// Sensor events
public void enableSensor(int sensortype, boolean enabled) {
// TODO: This uses getDefaultSensor - what if we have >1 accels?
if (enabled) {
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
} else {
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x, y;
switch (mDisplay.getRotation()) {
case Surface.ROTATION_90:
x = -event.values[1];
y = event.values[0];
break;
case Surface.ROTATION_270:
x = event.values[1];
y = -event.values[0];
break;
case Surface.ROTATION_180:
x = -event.values[1];
y = -event.values[0];
break;
default:
x = event.values[0];
y = event.values[1];
break;
}
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
y / SensorManager.GRAVITY_EARTH,
event.values[2] / SensorManager.GRAVITY_EARTH);
}
}
}

View file

@ -0,0 +1,8 @@
<vector android:height="24dp" android:viewportHeight="256"
android:viewportWidth="256" android:width="24dp"
android:tint="?attr/colorControlNormal" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000000"
android:pathData="M63.2,21.1c-8.3,1.1 -17.9,5.9 -24.1,12.2 -6.3,6.4 -8.9,10.5 -11.3,18 -1.7,5.5 -1.8,10.8 -1.8,79.2 0,70.7 0.1,73.5 2,79.8 2.7,8.6 9.4,17.5 17.1,22.6 11.6,7.8 8.9,7.5 78.3,7.9 40.6,0.2 64.4,-0.1 69,-0.8 17,-2.5 30.7,-14.2 35.8,-30.3 1.7,-5.5 1.8,-11.1 1.8,-79.3 0,-71.3 -0.1,-73.6 -2,-79.5 -5.6,-16.4 -19.2,-27.7 -36.2,-29.9 -8.8,-1.1 -119.7,-1.1 -128.6,0.1zM146.6,109c7.4,20.1 14.1,38.2 14.9,40.2l1.5,3.8 -5.4,-0 -5.3,-0 -4,-11.3 -4,-11.2 -16.3,-0 -16.3,-0 -4,11.2 -4,11.3 -5.3,-0 -5.4,-0 1.1,-2.8c0.9,-2.3 27,-73 28.4,-77 0.3,-0.9 2.1,-1.2 5.6,-1l5.1,0.3 13.4,36.5zM50.5,200.1c3.3,1.6 8.4,3.3 11.4,3.9 7.1,1.3 125,1.3 132,-0 7.5,-1.4 14.8,-4.9 21,-9.8l5.4,-4.4 -0.5,8c-0.8,14.1 -8.9,25.5 -21.4,30.1 -5.3,2 -7.4,2.1 -70.4,2.1 -63,-0 -65.1,-0.1 -70.4,-2.1 -7.2,-2.6 -14.8,-9.6 -18.2,-16.6 -2.1,-4.2 -2.9,-7.5 -3.2,-13.6l-0.5,-8.1 4.4,3.8c2.4,2 7.1,5 10.4,6.7z" android:strokeColor="#00000000"/>
<path android:fillColor="#000000"
android:pathData="M121.2,103.2l-6,17.3 6.4,0.3c3.5,0.2 9.3,0.2 12.8,-0l6.4,-0.3 -6,-17.3c-3.3,-9.4 -6.4,-17.2 -6.8,-17.2 -0.4,-0 -3.5,7.8 -6.8,17.2z" android:strokeColor="#00000000"/>
</vector>

View file

@ -0,0 +1,6 @@
<vector android:height="24dp" android:viewportHeight="256"
android:viewportWidth="256" android:width="24dp"
android:tint="?attr/colorControlNormal" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000000"
android:pathData="M63.2,21.1c-8.3,1.1 -17.9,5.9 -24.1,12.2 -6.3,6.4 -8.9,10.5 -11.3,18 -1.7,5.5 -1.8,10.8 -1.8,79.2 0,70.7 0.1,73.5 2,79.8 2.7,8.6 9.4,17.5 17.1,22.6 11.6,7.8 8.9,7.5 78.3,7.9 40.6,0.2 64.4,-0.1 69,-0.8 17,-2.5 30.7,-14.2 35.8,-30.3 1.7,-5.5 1.8,-11.1 1.8,-79.3 0,-71.3 -0.1,-73.6 -2,-79.5 -5.6,-16.4 -19.2,-27.7 -36.2,-29.9 -8.8,-1.1 -119.7,-1.1 -128.6,0.1zM159,76.5l0,4.5 -13,-0 -13,-0 0,36 0,36 -5,-0 -5,-0 0,-36 0,-36 -13,-0 -13,-0 0,-4.5 0,-4.5 31,-0 31,-0 0,4.5zM50.5,200.1c3.3,1.6 8.4,3.3 11.4,3.9 7.1,1.3 125,1.3 132,-0 7.5,-1.4 14.8,-4.9 21,-9.8l5.4,-4.4 -0.5,8c-0.8,14.1 -8.9,25.5 -21.4,30.1 -5.3,2 -7.4,2.1 -70.4,2.1 -63,-0 -65.1,-0.1 -70.4,-2.1 -7.2,-2.6 -14.8,-9.6 -18.2,-16.6 -2.1,-4.2 -2.9,-7.5 -3.2,-13.6l-0.5,-8.1 4.4,3.8c2.4,2 7.1,5 10.4,6.7z" android:strokeColor="#00000000"/>
</vector>

View file

@ -1,18 +1,14 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:background="#000000"
android:keepScreenOn="true"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -24,7 +20,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:orientation="vertical">
<ImageView
@ -38,14 +34,13 @@
android:id="@+id/sdl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_centerHorizontal="true"
android:layout_margin="4dp"
android:orientation="vertical"/>
android:orientation="vertical" />
<include layout="@layout/controls_fragment" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>

View file

@ -1,6 +1,7 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
@ -11,6 +12,7 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#AB000000"
android:visibility="gone"
app:subtitleTextColor="@android:color/white" />
<RelativeLayout
@ -38,7 +40,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:keepScreenOn="true"/>
android:keepScreenOn="true" />
</RelativeLayout>
@ -62,4 +64,4 @@
android:layout_centerHorizontal="true" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View file

@ -195,6 +195,16 @@
android:paddingRight="10dp"
android:translationY="-6dp">
<ImageButton
android:id="@+id/btnLogs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:background="@drawable/controls_button"
android:backgroundTint="?attr/colorPrimary"
android:src="@drawable/round_menu_24"
app:tint="?attr/colorPrimary" />
<ImageButton
android:id="@+id/btnSettings"
android:layout_width="wrap_content"

View file

@ -0,0 +1,99 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".LimboSDLActivity">
<item
android:id="@+id/itemKeyboard"
android:title="@string/showkbd_label"/>
<item
android:id="@+id/itemMouse"
android:title="@string/center_mouse"/>
<item
android:id="@+id/itemDrives"
android:title="@string/drives">
</item>
<item
android:id="@+id/itemDisplay"
android:title="@string/display"/>
<item
android:id="@+id/itemVolume"
android:title="@string/volume">
</item>
<item
android:id="@+id/itemMonitor"
android:title="@string/monitor">
</item>
<item
android:id="@+id/itemHideToolbar"
android:title="@string/hide_toolbar"/>
<item
android:id="@+id/itemSaveState"
android:title="@string/save_state"/>
<item
android:id="@+id/itemReset"
android:title="@string/reset"/>
<item
android:id="@+id/itemShutdown"
android:title="@string/shutdown"/>
<item
android:id="@+id/itemViewLog"
android:title="@string/view_log"/>
<item
android:id="@+id/itemHelp"
android:title="@string/help"/>
<!--XXXX: Not needed-->
<item
android:id="@+id/itemScaling"
android:icon="@android:drawable/ic_menu_zoom"
android:title="@string/scaling">
<menu>
<group
android:id="@+id/groupScaling"
android:checkableBehavior="single" >
<item
android:id="@+id/itemOneToOne"
android:title="@string/one_to_one"/>
<item
android:id="@+id/itemZoomIn"
android:title="@string/zoom_in"/>
<item
android:id="@+id/itemZoomOut"
android:title="@string/zoom_out"/>
<item
android:id="@+id/itemFitToScreen"
android:title="@string/fit_to_screen"/>
<item
android:id="@+id/itemStretchToScreen"
android:title="@string/stretch_to_screen"/>
</group>
</menu>
</item>
<item
android:id="@+id/itemExternalMouse"
android:title="@string/external_mouse">
</item>
<item
android:id="@+id/itemSaveSnapshot"
android:title="@string/save_snapshot"/>
<item
android:id="@+id/itemCtrlC"
android:title="@string/ctrl_c"/>
<item
android:id="@+id/itemCtrlAltDel"
android:title="@string/ctrl_alt_del"/>
</menu>

View file

@ -65,7 +65,7 @@
<item name="android:activityCloseEnterAnimation">@anim/popup_in</item>
<item name="android:activityCloseExitAnimation">@anim/popup_out</item>
</style>
<style name="Theme.FullScreen" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Theme.FullScreen" parent="AppTheme">
<item name="android:windowFullscreen">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">false</item>

View file

@ -16,4 +16,12 @@
<item>5</item>
<item>6</item>
</string-array>
<string-array name="vmUiLabels">
<item>SDL</item>
<item>VNC</item>
</string-array>
<string-array name="vmUiValues">
<item>SDL</item>
<item>VNC</item>
</string-array>
</resources>

View file

@ -1,6 +1,6 @@
<resources>
<string name="app_name">Vectras VM</string>
<string name="app_version">2.2</string>
<string name="app_version">2.3</string>
<string name="str_home">Home</string>
<string name="str_logger">Logger</string>
<string name="fab_info">Start Emulation</string>

View file

@ -67,7 +67,7 @@
<item name="android:activityCloseEnterAnimation">@anim/popup_in</item>
<item name="android:activityCloseExitAnimation">@anim/popup_out</item>
</style>
<style name="Theme.FullScreen" parent="Theme.Material3.DayNight.NoActionBar">
<style name="Theme.FullScreen" parent="AppTheme">
<item name="android:windowFullscreen">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">false</item>

View file

@ -23,14 +23,30 @@
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="MEMORY"
android:enabled="false"
android:shouldDisableView="true"
app:shouldDisableView="true"
app:useSimpleSummaryProvider="true"
app:icon="@drawable/round_memory_24" />
<EditTextPreference
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="2048"
android:inputType="number"
android:key="TbSize"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="TB SIZE (MB)"
app:useSimpleSummaryProvider="true"
app:icon="@drawable/ic_t" />
<SwitchPreferenceCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="true"
android:defaultValue="false"
android:key="AVX"
android:title="AVX"
app:icon="@drawable/ic_a" />
<SwitchPreferenceCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="false"
android:key="MTTCG"
android:title="MTTCG"
app:icon="@drawable/ic_mttcg" />
@ -42,6 +58,7 @@
android:entryValues="@array/cpuCoresValues"
android:key="cpuNum"
android:title="CPU CORES"
app:useSimpleSummaryProvider="true"
app:icon="@drawable/round_hub_24" />
<SwitchPreferenceCompat
android:layout_width="wrap_content"
@ -52,5 +69,42 @@
android:summaryOff="hdd type: ide"
app:summaryOn="hdd type: virtio"
app:icon="@drawable/round_dns_24" />
<EditTextPreference
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue=""
android:inputType="text"
android:key="customParams"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="CUSTOM PARAMS"
app:useSimpleSummaryProvider="true"
app:icon="@drawable/round_terminal_24" />
</PreferenceCategory>
<PreferenceCategory
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:title="VM UI ENVIRONMENT"
app:iconSpaceReserved="false">
<ListPreference
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="SDL"
android:entries="@array/vmUiLabels"
android:entryValues="@array/vmUiValues"
android:key="vmUi"
android:title="UI"
app:useSimpleSummaryProvider="true"
app:icon="@drawable/computer"/>
<SwitchPreferenceCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:defaultValue="true"
android:key="UsbTablet"
android:title="USB TABLET"
app:summaryOn="mouse: usb tablet"
app:summaryOff="mouse: ps2"
app:icon="@drawable/round_mouse_24" />
</PreferenceCategory>
</PreferenceScreen>

View file

@ -2,8 +2,10 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:title="USER INTERFACE"
app:icon="@drawable/ic_theme">
app:iconSpaceReserved="false">
<SwitchPreferenceCompat
android:defaultValue="false"