Xorg: launch xserver

This commit is contained in:
zt515
2017-12-02 00:16:01 +08:00
parent 4b6b707e33
commit 136ba9bc63
10 changed files with 937 additions and 905 deletions

View File

@ -138,7 +138,9 @@ public class Globals {
public static boolean MultitouchGesturesUsed[] = new boolean[4]; public static boolean MultitouchGesturesUsed[] = new boolean[4];
public static int MultitouchGestureSensitivity = 1; public static int MultitouchGestureSensitivity = 1;
public static int TouchscreenCalibration[] = new int[4]; public static int TouchscreenCalibration[] = new int[4];
public static String DataDir = new String(""); public static String DataDir = "/data/data/io.neoterm/files/usr/share/xorg-neoterm";
public static String UnSecureDataDir = "/data/data/io.neoterm/files/usr/share/xorg-neoterm";
public static String HomeDir = "/data/data/io.neoterm/files/home";
public static boolean VideoLinearFilter = true; public static boolean VideoLinearFilter = true;
public static boolean MultiThreadedVideo = false; public static boolean MultiThreadedVideo = false;

View File

@ -14,4 +14,8 @@ public class NeoGLView extends DemoGLSurfaceView {
public void callNativeScreenKeyboardShown(int shown) { public void callNativeScreenKeyboardShown(int shown) {
nativeScreenKeyboardShown(shown); nativeScreenKeyboardShown(shown);
} }
public void callNativeScreenVisibleRect(int x, int y, int w, int h) {
nativeScreenVisibleRect(x, y, w, h);
}
} }

View File

@ -0,0 +1,13 @@
package io.neoterm;
import io.neoterm.xorg.NeoXorgViewClient;
/**
* @author kiva
*/
public class NeoXorgSettings {
public static void init(NeoXorgViewClient client) {
Settings.Load(client);
}
}

View File

@ -23,21 +23,23 @@ freely, subject to the following restrictions:
package io.neoterm; package io.neoterm;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.os.Build;
import java.io.*;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Environment; import android.os.Environment;
import android.os.StatFs; import android.os.StatFs;
import java.util.Locale;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;
import java.lang.String;
import android.content.Intent;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.net.Uri; import android.util.Log;
import android.os.Build;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Locale;
import java.util.zip.GZIPInputStream;
import io.neoterm.xorg.NeoXorgViewClient; import io.neoterm.xorg.NeoXorgViewClient;
import io.neoterm.xorg.R; import io.neoterm.xorg.R;
@ -45,8 +47,7 @@ import io.neoterm.xorg.R;
// TODO: too much code here, split into multiple files, possibly auto-generated menus? // TODO: too much code here, split into multiple files, possibly auto-generated menus?
@SuppressWarnings("JniMissingFunction") @SuppressWarnings("JniMissingFunction")
public class Settings public class Settings {
{
static String SettingsFileName = "libsdl-settings.cfg"; static String SettingsFileName = "libsdl-settings.cfg";
static boolean settingsLoaded = false; static boolean settingsLoaded = false;
@ -54,10 +55,9 @@ public class Settings
static final int SETTINGS_FILE_VERSION = 5; static final int SETTINGS_FILE_VERSION = 5;
static boolean convertButtonSizeFromOldSdlVersion = false; static boolean convertButtonSizeFromOldSdlVersion = false;
static void Save(final MainActivity p) static void Save(final NeoXorgViewClient p) {
{
try { try {
ObjectOutputStream out = new ObjectOutputStream(p.openFileOutput( SettingsFileName, p.MODE_PRIVATE )); ObjectOutputStream out = new ObjectOutputStream(p.getContext().openFileOutput(SettingsFileName, Context.MODE_PRIVATE));
out.writeInt(SETTINGS_FILE_VERSION); out.writeInt(SETTINGS_FILE_VERSION);
out.writeBoolean(Globals.DownloadToSdcard); out.writeBoolean(Globals.DownloadToSdcard);
out.writeBoolean(Globals.PhoneHasArrowKeys); out.writeBoolean(Globals.PhoneHasArrowKeys);
@ -81,24 +81,20 @@ public class Settings
out.writeInt(Globals.MoveMouseWithJoystickSpeed); out.writeInt(Globals.MoveMouseWithJoystickSpeed);
out.writeInt(Globals.MoveMouseWithJoystickAccel); out.writeInt(Globals.MoveMouseWithJoystickAccel);
out.writeInt(SDL_Keys.JAVA_KEYCODE_LAST); out.writeInt(SDL_Keys.JAVA_KEYCODE_LAST);
for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ ) for (int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++) {
{
out.writeInt(Globals.RemapHwKeycode[i]); out.writeInt(Globals.RemapHwKeycode[i]);
} }
out.writeInt(Globals.RemapScreenKbKeycode.length); out.writeInt(Globals.RemapScreenKbKeycode.length);
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ ) for (int i = 0; i < Globals.RemapScreenKbKeycode.length; i++) {
{
out.writeInt(Globals.RemapScreenKbKeycode[i]); out.writeInt(Globals.RemapScreenKbKeycode[i]);
} }
out.writeInt(Globals.ScreenKbControlsShown.length); out.writeInt(Globals.ScreenKbControlsShown.length);
for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ ) for (int i = 0; i < Globals.ScreenKbControlsShown.length; i++) {
{
out.writeBoolean(Globals.ScreenKbControlsShown[i]); out.writeBoolean(Globals.ScreenKbControlsShown[i]);
} }
out.writeInt(Globals.TouchscreenKeyboardTransparency); out.writeInt(Globals.TouchscreenKeyboardTransparency);
out.writeInt(Globals.RemapMultitouchGestureKeycode.length); out.writeInt(Globals.RemapMultitouchGestureKeycode.length);
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ ) for (int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++) {
{
out.writeInt(Globals.RemapMultitouchGestureKeycode[i]); out.writeInt(Globals.RemapMultitouchGestureKeycode[i]);
out.writeBoolean(Globals.MultitouchGesturesUsed[i]); out.writeBoolean(Globals.MultitouchGesturesUsed[i]);
} }
@ -130,7 +126,6 @@ public class Settings
out.writeBoolean(Globals.OptionalDataDownload[i]); out.writeBoolean(Globals.OptionalDataDownload[i]);
out.writeBoolean(false); // Unused out.writeBoolean(false); // Unused
out.writeInt(Globals.TouchscreenKeyboardDrawSize); out.writeInt(Globals.TouchscreenKeyboardDrawSize);
out.writeInt(p.getApplicationVersion());
// Gyroscope calibration data, now unused // Gyroscope calibration data, now unused
out.writeFloat(0.0f); out.writeFloat(0.0f);
out.writeFloat(0.0f); out.writeFloat(0.0f);
@ -155,27 +150,25 @@ public class Settings
out.writeBoolean(Globals.AutoDetectOrientation); out.writeBoolean(Globals.AutoDetectOrientation);
out.writeBoolean(Globals.TvBorders); out.writeBoolean(Globals.TvBorders);
out.writeBoolean(Globals.ForceHardwareMouse); out.writeBoolean(Globals.ForceHardwareMouse);
convertButtonSizeFromOldSdlVersion = false;
out.writeBoolean(convertButtonSizeFromOldSdlVersion);
out.close(); out.close();
settingsLoaded = true; settingsLoaded = true;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
} catch (SecurityException e) { } catch (SecurityException e) {
} catch ( IOException e ) {}; } catch (IOException e) {
}
;
} }
static void Load( final MainActivity p ) static void Load(final NeoXorgViewClient p) {
{
if (settingsLoaded) // Prevent starting twice if (settingsLoaded) // Prevent starting twice
{ {
return; return;
} }
Log.i("SDL", "libSDL: Settings.Load(): enter"); Log.i("SDL", "libSDL: Settings.Load(): enter");
nativeInitKeymap(); nativeInitKeymap();
for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ ) for (int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++) {
{
int sdlKey = nativeGetKeymapKey(i); int sdlKey = nativeGetKeymapKey(i);
int idx = 0; int idx = 0;
for (int ii = 0; ii < SDL_Keys.values.length; ii++) for (int ii = 0; ii < SDL_Keys.values.length; ii++)
@ -183,8 +176,7 @@ public class Settings
idx = ii; idx = ii;
Globals.RemapHwKeycode[i] = idx; Globals.RemapHwKeycode[i] = idx;
} }
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ ) for (int i = 0; i < Globals.RemapScreenKbKeycode.length; i++) {
{
int sdlKey = nativeGetKeymapKeyScreenKb(i); int sdlKey = nativeGetKeymapKeyScreenKb(i);
int idx = 0; int idx = 0;
for (int ii = 0; ii < SDL_Keys.values.length; ii++) for (int ii = 0; ii < SDL_Keys.values.length; ii++)
@ -200,8 +192,7 @@ public class Settings
Globals.ScreenKbControlsShown[8] = true; Globals.ScreenKbControlsShown[8] = true;
if (Globals.AppUsesThirdJoystick) if (Globals.AppUsesThirdJoystick)
Globals.ScreenKbControlsShown[9] = true; Globals.ScreenKbControlsShown[9] = true;
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ ) for (int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++) {
{
int sdlKey = nativeGetKeymapKeyMultitouchGesture(i); int sdlKey = nativeGetKeymapKeyMultitouchGesture(i);
int idx = 0; int idx = 0;
for (int ii = 0; ii < SDL_Keys.values.length; ii++) for (int ii = 0; ii < SDL_Keys.values.length; ii++)
@ -219,9 +210,9 @@ public class Settings
p.getWindowManager().getDefaultDisplay().getMetrics(dm); p.getWindowManager().getDefaultDisplay().getMetrics(dm);
displayX = dm.widthPixels; displayX = dm.widthPixels;
displayY = dm.heightPixels; displayY = dm.heightPixels;
} catch (Exception eeeee) {} } catch (Exception eeeee) {
for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ ) }
{ for (int i = 0; i < Globals.ScreenKbControlsLayout.length; i++) {
Globals.ScreenKbControlsLayout[i][0] *= (float) displayX / 800.0f; Globals.ScreenKbControlsLayout[i][0] *= (float) displayX / 800.0f;
Globals.ScreenKbControlsLayout[i][2] *= (float) displayX / 800.0f; Globals.ScreenKbControlsLayout[i][2] *= (float) displayX / 800.0f;
Globals.ScreenKbControlsLayout[i][1] *= (float) displayY / 480.0f; Globals.ScreenKbControlsLayout[i][1] *= (float) displayY / 480.0f;
@ -233,17 +224,10 @@ public class Settings
} }
Log.i("SDL", "android.os.Build.MODEL: " + Build.MODEL); Log.i("SDL", "android.os.Build.MODEL: " + Build.MODEL);
if( (Build.MODEL.equals("GT-N7000") || Build.MODEL.equals("SGH-I717"))
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1 )
{
// Samsung Galaxy Note generates a keypress when you hover a stylus over the screen, and that messes up OpenTTD dialogs
// ICS update sends events in a proper way
Globals.RemapHwKeycode[112] = SDL_1_2_Keycodes.SDLK_UNKNOWN;
}
convertButtonSizeFromOldSdlVersion = false; convertButtonSizeFromOldSdlVersion = false;
try { try {
ObjectInputStream settingsFile = new ObjectInputStream(new FileInputStream( p.getFilesDir().getAbsolutePath() + "/" + SettingsFileName )); ObjectInputStream settingsFile = new ObjectInputStream(new FileInputStream(p.getContext().getFilesDir().getAbsolutePath() + "/" + SettingsFileName));
if (settingsFile.readInt() != SETTINGS_FILE_VERSION) if (settingsFile.readInt() != SETTINGS_FILE_VERSION)
throw new IOException(); throw new IOException();
Globals.DownloadToSdcard = settingsFile.readBoolean(); Globals.DownloadToSdcard = settingsFile.readBoolean();
@ -269,27 +253,23 @@ public class Settings
Globals.MoveMouseWithJoystickSpeed = settingsFile.readInt(); Globals.MoveMouseWithJoystickSpeed = settingsFile.readInt();
Globals.MoveMouseWithJoystickAccel = settingsFile.readInt(); Globals.MoveMouseWithJoystickAccel = settingsFile.readInt();
int readKeys = settingsFile.readInt(); int readKeys = settingsFile.readInt();
for( int i = 0; i < readKeys; i++ ) for (int i = 0; i < readKeys; i++) {
{
Globals.RemapHwKeycode[i] = settingsFile.readInt(); Globals.RemapHwKeycode[i] = settingsFile.readInt();
} }
if (settingsFile.readInt() != Globals.RemapScreenKbKeycode.length) if (settingsFile.readInt() != Globals.RemapScreenKbKeycode.length)
throw new IOException(); throw new IOException();
for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ ) for (int i = 0; i < Globals.RemapScreenKbKeycode.length; i++) {
{
Globals.RemapScreenKbKeycode[i] = settingsFile.readInt(); Globals.RemapScreenKbKeycode[i] = settingsFile.readInt();
} }
if (settingsFile.readInt() != Globals.ScreenKbControlsShown.length) if (settingsFile.readInt() != Globals.ScreenKbControlsShown.length)
throw new IOException(); throw new IOException();
for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ ) for (int i = 0; i < Globals.ScreenKbControlsShown.length; i++) {
{
Globals.ScreenKbControlsShown[i] = settingsFile.readBoolean(); Globals.ScreenKbControlsShown[i] = settingsFile.readBoolean();
} }
Globals.TouchscreenKeyboardTransparency = settingsFile.readInt(); Globals.TouchscreenKeyboardTransparency = settingsFile.readInt();
if (settingsFile.readInt() != Globals.RemapMultitouchGestureKeycode.length) if (settingsFile.readInt() != Globals.RemapMultitouchGestureKeycode.length)
throw new IOException(); throw new IOException();
for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ ) for (int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++) {
{
Globals.RemapMultitouchGestureKeycode[i] = settingsFile.readInt(); Globals.RemapMultitouchGestureKeycode[i] = settingsFile.readInt();
Globals.MultitouchGesturesUsed[i] = settingsFile.readBoolean(); Globals.MultitouchGesturesUsed[i] = settingsFile.readBoolean();
} }
@ -328,7 +308,6 @@ public class Settings
Globals.OptionalDataDownload[i] = settingsFile.readBoolean(); Globals.OptionalDataDownload[i] = settingsFile.readBoolean();
settingsFile.readBoolean(); // Unused settingsFile.readBoolean(); // Unused
Globals.TouchscreenKeyboardDrawSize = settingsFile.readInt(); Globals.TouchscreenKeyboardDrawSize = settingsFile.readInt();
int cfgVersion = settingsFile.readInt();
// Gyroscope calibration data, now unused // Gyroscope calibration data, now unused
settingsFile.readFloat(); settingsFile.readFloat();
settingsFile.readFloat(); settingsFile.readFloat();
@ -353,26 +332,12 @@ public class Settings
Globals.AutoDetectOrientation = settingsFile.readBoolean(); Globals.AutoDetectOrientation = settingsFile.readBoolean();
Globals.TvBorders = settingsFile.readBoolean(); Globals.TvBorders = settingsFile.readBoolean();
Globals.ForceHardwareMouse = settingsFile.readBoolean(); Globals.ForceHardwareMouse = settingsFile.readBoolean();
convertButtonSizeFromOldSdlVersion = settingsFile.readBoolean();
settingsLoaded = true; settingsLoaded = true;
Log.i("SDL", "libSDL: Settings.Load(): loaded settings successfully"); Log.i("SDL", "libSDL: Settings.Load(): loaded settings successfully");
settingsFile.close(); settingsFile.close();
Log.i("SDL", "libSDL: old cfg version " + cfgVersion + ", our version " + p.getApplicationVersion());
if( cfgVersion != p.getApplicationVersion() )
{
DeleteFilesOnUpgrade(p);
if( Globals.ResetSdlConfigForThisVersion )
{
Log.i("SDL", "libSDL: old cfg version " + cfgVersion + ", our version " + p.getApplicationVersion() + " and we need to clean up config file");
// Delete settings file, and restart the application
DeleteSdlConfigOnUpgradeAndRestart(p);
}
Save(p);
}
return; return;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
@ -382,47 +347,35 @@ public class Settings
} catch (IOException e) { } catch (IOException e) {
Log.i("SDL", "libSDL: settings file cannot be read: " + e); Log.i("SDL", "libSDL: settings file cannot be read: " + e);
DeleteFilesOnUpgrade(p); DeleteFilesOnUpgrade(p);
if (convertButtonSizeFromOldSdlVersion && Globals.TouchscreenKeyboardSize + 1 < Globals.TOUCHSCREEN_KEYBOARD_CUSTOM) if (convertButtonSizeFromOldSdlVersion && Globals.TouchscreenKeyboardSize + 1 < Globals.TOUCHSCREEN_KEYBOARD_CUSTOM) {
{
Globals.TouchscreenKeyboardSize++; // New default button size is bigger, but we are keeping old button size for existing installations Globals.TouchscreenKeyboardSize++; // New default button size is bigger, but we are keeping old button size for existing installations
//if (Globals.AppTouchscreenKeyboardKeysAmount <= 4 && Globals.TouchscreenKeyboardSize + 1 < Globals.TOUCHSCREEN_KEYBOARD_CUSTOM) //if (Globals.AppTouchscreenKeyboardKeysAmount <= 4 && Globals.TouchscreenKeyboardSize + 1 < Globals.TOUCHSCREEN_KEYBOARD_CUSTOM)
// Globals.TouchscreenKeyboardSize ++; // If there are only 4 buttons they are even bigger // Globals.TouchscreenKeyboardSize ++; // If there are only 4 buttons they are even bigger
} }
if( Globals.ResetSdlConfigForThisVersion )
{
Log.i("SDL", "libSDL: old cfg version unknown or too old, our version " + p.getApplicationVersion() + " and we need to clean up config file");
DeleteSdlConfigOnUpgradeAndRestart(p);
} }
}; ;
if( Globals.DataDir.length() == 0 ) if (Globals.DataDir.length() == 0) {
{ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
if( !Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) )
{
Log.i("SDL", "libSDL: SD card or external storage is not mounted (state " + Environment.getExternalStorageState() + "), switching to the internal storage."); Log.i("SDL", "libSDL: SD card or external storage is not mounted (state " + Environment.getExternalStorageState() + "), switching to the internal storage.");
Globals.DownloadToSdcard = false; Globals.DownloadToSdcard = false;
} }
Globals.DataDir = Globals.DownloadToSdcard ? Globals.DataDir = Globals.DownloadToSdcard ?
SdcardAppPath.get().bestPath(p) : SdcardAppPath.get().bestPath(p.getContext()) :
p.getFilesDir().getAbsolutePath(); p.getContext().getFilesDir().getAbsolutePath();
} }
Log.i("SDL", "libSDL: Settings.Load(): loading settings failed, running config dialog"); Log.i("SDL", "libSDL: Settings.Load(): loading settings failed, running config dialog");
p.setScreenOrientation(); p.initScreenOrientation();
p.setUpStatusLabel();
if( checkRamSize(p) )
SettingsMenu.showConfig(p, true);
} }
// =============================================================================================== // ===============================================================================================
public static boolean deleteRecursively(File dir) public static boolean deleteRecursively(File dir) {
{
boolean success = true; boolean success = true;
if (dir.isDirectory()) { if (dir.isDirectory()) {
String[] children = dir.list(); String[] children = dir.list();
for (int i=0; i<children.length; i++) for (int i = 0; i < children.length; i++) {
{
if (!deleteRecursively(new File(dir, children[i]))) if (!deleteRecursively(new File(dir, children[i])))
success = false; success = false;
} }
@ -431,14 +384,13 @@ public class Settings
success = false; success = false;
return success; return success;
} }
public static boolean deleteRecursivelyAndLog(File dir)
{ public static boolean deleteRecursivelyAndLog(File dir) {
boolean success = true; boolean success = true;
Log.v("SDL", "Deleting old file: " + dir.getAbsolutePath() + " exists " + dir.exists()); Log.v("SDL", "Deleting old file: " + dir.getAbsolutePath() + " exists " + dir.exists());
if (dir.isDirectory()) { if (dir.isDirectory()) {
String[] children = dir.list(); String[] children = dir.list();
for (int i=0; i<children.length; i++) for (int i = 0; i < children.length; i++) {
{
if (!deleteRecursively(new File(dir, children[i]))) if (!deleteRecursively(new File(dir, children[i])))
success = false; success = false;
} }
@ -447,33 +399,32 @@ public class Settings
success = false; success = false;
return success; return success;
} }
public static void DeleteFilesOnUpgrade(final MainActivity p)
{ public static void DeleteFilesOnUpgrade(final NeoXorgViewClient p) {
String[] files = Globals.DeleteFilesOnUpgrade.split(" "); String[] files = Globals.DeleteFilesOnUpgrade.split(" ");
for(String path: files) for (String path : files) {
{
if (path.equals("")) if (path.equals(""))
continue; continue;
deleteRecursivelyAndLog(new File( p.getFilesDir().getAbsolutePath() + "/" + path )); deleteRecursivelyAndLog(new File(p.getContext().getFilesDir().getAbsolutePath() + "/" + path));
for( String sdpath: SdcardAppPath.get().allPaths(p) ) for (String sdpath : SdcardAppPath.get().allPaths(p.getContext()))
deleteRecursivelyAndLog(new File(sdpath + "/" + path)); deleteRecursivelyAndLog(new File(sdpath + "/" + path));
} }
} }
public static void DeleteSdlConfigOnUpgradeAndRestart(final MainActivity p)
{ public static void DeleteSdlConfigOnUpgradeAndRestart(final NeoXorgViewClient p) {
try { try {
ObjectOutputStream out = new ObjectOutputStream(p.openFileOutput( SettingsFileName, p.MODE_PRIVATE )); ObjectOutputStream out = new ObjectOutputStream(p.getContext().openFileOutput(SettingsFileName, Context.MODE_PRIVATE));
out.writeInt(-1); out.writeInt(-1);
out.close(); out.close();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
} catch ( IOException e ) { } } catch (IOException e) {
new File( p.getFilesDir() + "/" + SettingsFileName ).delete(); }
new File(p.getContext().getFilesDir() + "/" + SettingsFileName).delete();
} }
// =============================================================================================== // ===============================================================================================
static void applyMouseEmulationOptions() static void applyMouseEmulationOptions() {
{
if (Globals.AppUsesMouse) if (Globals.AppUsesMouse)
nativeSetMouseUsed(Globals.RightClickMethod, nativeSetMouseUsed(Globals.RightClickMethod,
Globals.ShowScreenUnderFinger, Globals.ShowScreenUnderFinger,
@ -500,14 +451,12 @@ public class Settings
Globals.ScreenFollowsMouse ? 1 : 0); Globals.ScreenFollowsMouse ? 1 : 0);
} }
static void Apply(NeoXorgViewClient p) static void Apply(NeoXorgViewClient p) {
{
setEnvVars(p); setEnvVars(p);
nativeSetVideoDepth(Globals.VideoDepthBpp, Globals.NeedGles2 ? 1 : 0, Globals.NeedGles3 ? 1 : 0); nativeSetVideoDepth(Globals.VideoDepthBpp, Globals.NeedGles2 ? 1 : 0, Globals.NeedGles3 ? 1 : 0);
if (Globals.VideoLinearFilter) if (Globals.VideoLinearFilter)
nativeSetVideoLinearFilter(); nativeSetVideoLinearFilter();
if( Globals.CompatibilityHacksVideo ) if (Globals.CompatibilityHacksVideo) {
{
Globals.MultiThreadedVideo = true; Globals.MultiThreadedVideo = true;
Globals.SwVideoMode = true; Globals.SwVideoMode = true;
nativeSetCompatibilityHacks(); nativeSetCompatibilityHacks();
@ -523,16 +472,14 @@ public class Settings
if (Globals.AppUsesMultitouch) if (Globals.AppUsesMultitouch)
nativeSetMultitouchUsed(); nativeSetMultitouchUsed();
nativeSetAccelerometerSettings(Globals.AccelerometerSensitivity, Globals.AccelerometerCenterPos); nativeSetAccelerometerSettings(Globals.AccelerometerSensitivity, Globals.AccelerometerCenterPos);
if( Globals.UseTouchscreenKeyboard ) if (Globals.UseTouchscreenKeyboard) {
{
boolean screenKbReallyUsed = false; boolean screenKbReallyUsed = false;
for (int i = 0; i < Globals.ScreenKbControlsShown.length; i++) for (int i = 0; i < Globals.ScreenKbControlsShown.length; i++)
if (Globals.ScreenKbControlsShown[i]) if (Globals.ScreenKbControlsShown[i])
screenKbReallyUsed = true; screenKbReallyUsed = true;
if (p.isRunningOnOUYA()) if (p.isRunningOnOUYA())
screenKbReallyUsed = false; screenKbReallyUsed = false;
if( screenKbReallyUsed ) if (screenKbReallyUsed) {
{
nativeSetTouchscreenKeyboardUsed(); nativeSetTouchscreenKeyboardUsed();
nativeSetupScreenKeyboard(Globals.TouchscreenKeyboardSize, nativeSetupScreenKeyboard(Globals.TouchscreenKeyboardSize,
Globals.TouchscreenKeyboardDrawSize, Globals.TouchscreenKeyboardDrawSize,
@ -543,8 +490,7 @@ public class Settings
SetupTouchscreenKeyboardGraphics(p.getContext()); SetupTouchscreenKeyboardGraphics(p.getContext());
for (int i = 0; i < Globals.RemapScreenKbKeycode.length; i++) for (int i = 0; i < Globals.RemapScreenKbKeycode.length; i++)
nativeSetKeymapKeyScreenKb(i, SDL_Keys.values[Globals.RemapScreenKbKeycode[i]]); nativeSetKeymapKeyScreenKb(i, SDL_Keys.values[Globals.RemapScreenKbKeycode[i]]);
if( Globals.TouchscreenKeyboardSize == Globals.TOUCHSCREEN_KEYBOARD_CUSTOM ) if (Globals.TouchscreenKeyboardSize == Globals.TOUCHSCREEN_KEYBOARD_CUSTOM) {
{
for (int i = 0; i < Globals.ScreenKbControlsLayout.length; i++) for (int i = 0; i < Globals.ScreenKbControlsLayout.length; i++)
if (Globals.ScreenKbControlsLayout[i][0] < Globals.ScreenKbControlsLayout[i][2]) if (Globals.ScreenKbControlsLayout[i][0] < Globals.ScreenKbControlsLayout[i][2])
nativeSetScreenKbKeyLayout(i, Globals.ScreenKbControlsLayout[i][0], Globals.ScreenKbControlsLayout[i][1], nativeSetScreenKbKeyLayout(i, Globals.ScreenKbControlsLayout[i][0], Globals.ScreenKbControlsLayout[i][1],
@ -552,8 +498,7 @@ public class Settings
} }
for (int i = 0; i < Globals.ScreenKbControlsShown.length; i++) for (int i = 0; i < Globals.ScreenKbControlsShown.length; i++)
nativeSetScreenKbKeyUsed(i, Globals.ScreenKbControlsShown[i] ? 1 : 0); nativeSetScreenKbKeyUsed(i, Globals.ScreenKbControlsShown[i] ? 1 : 0);
} } else
else
Globals.UseTouchscreenKeyboard = false; Globals.UseTouchscreenKeyboard = false;
} }
@ -567,21 +512,20 @@ public class Settings
Globals.TouchscreenCalibration[2], Globals.TouchscreenCalibration[3]); Globals.TouchscreenCalibration[2], Globals.TouchscreenCalibration[3]);
} }
static void setEnvVars(NeoXorgViewClient p) static void setEnvVars(NeoXorgViewClient p) {
{ String lang = Locale.getDefault().getLanguage();
String lang = new String(Locale.getDefault().getLanguage());
if (Locale.getDefault().getCountry().length() > 0) if (Locale.getDefault().getCountry().length() > 0)
lang = lang + "_" + Locale.getDefault().getCountry(); lang = lang + "_" + Locale.getDefault().getCountry();
Log.i("SDL", "libSDL: setting envvar LANGUAGE to '" + lang + "'"); Log.i("SDL", "libSDL: setting env LANGUAGE to '" + lang + "'");
nativeSetEnv("LANG", lang); nativeSetEnv("LANG", lang);
nativeSetEnv("LANGUAGE", lang); nativeSetEnv("LANGUAGE", lang);
// TODO: get current user name and set envvar USER, the API is not availalbe on Android 1.6 so I don't bother with this // TODO: get current user name and set envvar USER, the API is not availalbe on Android 1.6 so I don't bother with this
nativeSetEnv("APPDIR", p.getContext().getFilesDir().getAbsolutePath()); nativeSetEnv("APPDIR", p.getContext().getFilesDir().getAbsolutePath());
nativeSetEnv("SECURE_STORAGE_DIR", p.getContext().getFilesDir().getAbsolutePath()); nativeSetEnv("SECURE_STORAGE_DIR", p.getContext().getFilesDir().getAbsolutePath());
nativeSetEnv("DATADIR", Globals.DataDir); nativeSetEnv("DATADIR", Globals.DataDir);
nativeSetEnv( "UNSECURE_STORAGE_DIR", Globals.DataDir ); nativeSetEnv("UNSECURE_STORAGE_DIR", Globals.UnSecureDataDir);
SdcardAppPath.get().setEnv(p.getContext()); SdcardAppPath.get().setEnv(p.getContext());
nativeSetEnv( "HOME", Globals.DataDir ); nativeSetEnv("HOME", Globals.HomeDir);
nativeSetEnv("SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath()); nativeSetEnv("SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath());
nativeSetEnv("SDCARD_DOWNLOADS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()); nativeSetEnv("SDCARD_DOWNLOADS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
nativeSetEnv("SDCARD_PICTURES", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()); nativeSetEnv("SDCARD_PICTURES", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
@ -594,10 +538,10 @@ public class Settings
nativeSetEnv("ANDROID_MY_OWN_APP_FILE", p.getContext().getPackageResourcePath()); // This may be different from p.getPackageCodePath() on multi-user systems, but should still be the same .apk file nativeSetEnv("ANDROID_MY_OWN_APP_FILE", p.getContext().getPackageResourcePath()); // This may be different from p.getPackageCodePath() on multi-user systems, but should still be the same .apk file
try { try {
nativeSetEnv("ANDROID_APP_NAME", p.getContext().getString(p.getContext().getApplicationInfo().labelRes)); nativeSetEnv("ANDROID_APP_NAME", p.getContext().getString(p.getContext().getApplicationInfo().labelRes));
} catch (Exception eeeeee) {} } catch (Exception eeeeee) {
}
Log.d("SDL", "libSDL: Is running on OUYA: " + p.isRunningOnOUYA()); Log.d("SDL", "libSDL: Is running on OUYA: " + p.isRunningOnOUYA());
if( p.isRunningOnOUYA() ) if (p.isRunningOnOUYA()) {
{
nativeSetEnv("OUYA", "1"); nativeSetEnv("OUYA", "1");
nativeSetEnv("TV", "1"); nativeSetEnv("TV", "1");
nativeSetEnv("ANDROID_TV", "1"); nativeSetEnv("ANDROID_TV", "1");
@ -626,21 +570,19 @@ public class Settings
nativeSetEnv("DISPLAY_HEIGHT_MM", String.valueOf((int) (y * 25.4f))); nativeSetEnv("DISPLAY_HEIGHT_MM", String.valueOf((int) (y * 25.4f)));
nativeSetEnv("DISPLAY_RESOLUTION_WIDTH", String.valueOf(Math.max(dm.widthPixels, dm.heightPixels))); nativeSetEnv("DISPLAY_RESOLUTION_WIDTH", String.valueOf(Math.max(dm.widthPixels, dm.heightPixels)));
nativeSetEnv("DISPLAY_RESOLUTION_HEIGHT", String.valueOf(Math.min(dm.widthPixels, dm.heightPixels))); nativeSetEnv("DISPLAY_RESOLUTION_HEIGHT", String.valueOf(Math.min(dm.widthPixels, dm.heightPixels)));
} catch (Exception eeeee) {} } catch (Exception eeeee) {
}
} }
static byte [] loadRaw(Context p, int res) static byte[] loadRaw(Context p, int res) {
{
byte[] buf = new byte[65536 * 2]; byte[] buf = new byte[65536 * 2];
byte[] a = new byte[1048576 * 5]; // We need 5Mb buffer for Keen theme, and this Java code is inefficient byte[] a = new byte[1048576 * 5]; // We need 5Mb buffer for Keen theme, and this Java code is inefficient
int written = 0; int written = 0;
try { try {
InputStream is = new GZIPInputStream(p.getResources().openRawResource(res)); InputStream is = new GZIPInputStream(p.getResources().openRawResource(res));
int readed = 0; int readed = 0;
while( (readed = is.read(buf)) >= 0 ) while ((readed = is.read(buf)) >= 0) {
{ if (written + readed > a.length) {
if( written + readed > a.length )
{
byte[] b = new byte[written + readed]; byte[] b = new byte[written + readed];
System.arraycopy(a, 0, b, 0, written); System.arraycopy(a, 0, b, 0, written);
a = b; a = b;
@ -648,16 +590,16 @@ public class Settings
System.arraycopy(buf, 0, a, written, readed); System.arraycopy(buf, 0, a, written, readed);
written += readed; written += readed;
} }
} catch(Exception e) {}; } catch (Exception e) {
}
;
byte[] b = new byte[written]; byte[] b = new byte[written];
System.arraycopy(a, 0, b, 0, written); System.arraycopy(a, 0, b, 0, written);
return b; return b;
} }
static void SetupTouchscreenKeyboardGraphics(Context p) static void SetupTouchscreenKeyboardGraphics(Context p) {
{ if (Globals.UseTouchscreenKeyboard) {
if( Globals.UseTouchscreenKeyboard )
{
if (Globals.TouchscreenKeyboardTheme < 0) if (Globals.TouchscreenKeyboardTheme < 0)
Globals.TouchscreenKeyboardTheme = 0; Globals.TouchscreenKeyboardTheme = 0;
if (Globals.TouchscreenKeyboardTheme > 9) if (Globals.TouchscreenKeyboardTheme > 9)
@ -686,87 +628,77 @@ public class Settings
} }
} }
abstract static class SdcardAppPath abstract static class SdcardAppPath {
{ public static SdcardAppPath get() {
public static SdcardAppPath get()
{
return Kitkat.Holder.sInstance; return Kitkat.Holder.sInstance;
} }
public String path(final Context p)
{ public String path(final Context p) {
return get().path(p); return get().path(p);
} }
public void setEnv(final Context p)
{ public void setEnv(final Context p) {
get().setEnv(p); get().setEnv(p);
} }
public String bestPath(final Context p)
{ public String bestPath(final Context p) {
return get().bestPath(p); return get().bestPath(p);
};
public String[] allPaths(final Context p)
{
return get().allPaths(p);
};
public static final String deprecatedPath(final Context p)
{
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/app-data/" + p.getPackageName();
} }
private static class Froyo extends SdcardAppPath ;
{
private static class Holder public String[] allPaths(final Context p) {
{ return get().allPaths(p);
private static final Froyo sInstance = new Froyo();
} }
;
private static class Froyo extends SdcardAppPath {
@Override @Override
public String path(final Context p) public String path(final Context p) {
{ if (p.getExternalFilesDir(null) == null) {
if( p.getExternalFilesDir(null) == null )
{
if (Environment.getExternalStorageDirectory() == null) if (Environment.getExternalStorageDirectory() == null)
return "/sdcard/Android/data/" + p.getPackageName() + "/files"; return "/sdcard/Android/data/" + p.getPackageName() + "/files";
return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + p.getPackageName() + "/files"; return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + p.getPackageName() + "/files";
} }
return p.getExternalFilesDir(null).getAbsolutePath(); return p.getExternalFilesDir(null).getAbsolutePath();
} }
@Override @Override
public void setEnv(final Context p) public void setEnv(final Context p) {
{
nativeSetEnv("UNSECURE_STORAGE_DIR_0", Globals.DataDir); nativeSetEnv("UNSECURE_STORAGE_DIR_0", Globals.DataDir);
} }
@Override @Override
public String bestPath(final Context p) public String bestPath(final Context p) {
{
return path(p); return path(p);
} }
@Override @Override
public String[] allPaths(final Context p) public String[] allPaths(final Context p) {
{ return new String[]{path(p)};
return new String[] { path(p), deprecatedPath(p) };
} }
} }
private static class Kitkat extends Froyo
{ private static class Kitkat extends Froyo {
private static class Holder private static class Holder {
{
private static final Kitkat sInstance = new Kitkat(); private static final Kitkat sInstance = new Kitkat();
} }
@Override @Override
public String bestPath(final Context p) public String bestPath(final Context p) {
{
File[] paths = p.getExternalFilesDirs(null); File[] paths = p.getExternalFilesDirs(null);
String ret = path(p); String ret = path(p);
long maxSize = -1; long maxSize = -1;
for( File path: paths ) for (File path : paths) {
{
if (path == null) if (path == null)
continue; continue;
long size = -1; long size = -1;
try { try {
StatFs stat = new StatFs(path.getPath()); StatFs stat = new StatFs(path.getPath());
size = (long) stat.getAvailableBlocks() * stat.getBlockSize() / 1024 / 1024; size = (long) stat.getAvailableBlocks() * stat.getBlockSize() / 1024 / 1024;
} catch (Exception ee) {} // Can throw an exception if we cannot read from SD card } catch (Exception ee) {
} // Can throw an exception if we cannot read from SD card
try { try {
path.mkdirs(); path.mkdirs();
@ -775,21 +707,21 @@ public class Settings
size = -1; // Not writable size = -1; // Not writable
} }
if( size > maxSize ) if (size > maxSize) {
{
maxSize = size; maxSize = size;
ret = path.getAbsolutePath(); ret = path.getAbsolutePath();
} }
} }
return ret; return ret;
}; }
;
@Override @Override
public void setEnv(final Context p) public void setEnv(final Context p) {
{
File[] paths = p.getExternalFilesDirs(null); File[] paths = p.getExternalFilesDirs(null);
int index = 0; int index = 0;
for( File path: paths ) for (File path : paths) {
{
if (path == null) if (path == null)
continue; continue;
if (!path.exists()) if (!path.exists())
@ -798,12 +730,11 @@ public class Settings
index++; index++;
} }
} }
@Override @Override
public String[] allPaths(final Context p) public String[] allPaths(final Context p) {
{
ArrayList<String> ret = new ArrayList<String>(); ArrayList<String> ret = new ArrayList<String>();
for( File path: p.getExternalFilesDirs(null) ) for (File path : p.getExternalFilesDirs(null)) {
{
if (path == null) if (path == null)
continue; continue;
try { try {
@ -814,73 +745,15 @@ public class Settings
} }
ret.add(path.getAbsolutePath()); ret.add(path.getAbsolutePath());
} }
ret.add(deprecatedPath(p));
return ret.toArray(new String[0]); return ret.toArray(new String[0]);
} }
} }
} }
static boolean checkRamSize(final MainActivity p)
{
try {
BufferedReader reader = new BufferedReader(new FileReader("/proc/meminfo"));
String line = null;
while( ( line = reader.readLine() ) != null )
{
if( line.indexOf("MemTotal:") == 0 )
{
String[] fields = line.split("[ \t]+");
Long size = Long.parseLong(fields[1]);
Log.i("SDL", "Device RAM size: " + size / 1024 + " Mb, required minimum RAM: " + Globals.AppMinimumRAM + " Mb" );
if( size / 1024 < Globals.AppMinimumRAM )
{
settingsChanged = true;
AlertDialog.Builder builder = new AlertDialog.Builder(p);
builder.setTitle(R.string.not_enough_ram);
builder.setMessage(p.getResources().getString( R.string.not_enough_ram_size, Globals.AppMinimumRAM, (int)(size / 1024)) );
builder.setPositiveButton(p.getResources().getString(R.string.ok), new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int item)
{
p.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + p.getPackageName())));
System.exit(0);
}
});
builder.setNegativeButton(p.getResources().getString(R.string.ignore), new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int item)
{
SettingsMenu.showConfig(p, true);
return;
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener()
{
public void onCancel(DialogInterface dialog)
{
p.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + p.getPackageName())));
System.exit(0);
}
});
final AlertDialog alert = builder.create();
alert.setOwnerActivity(p);
alert.show();
return false;
}
}
}
} catch ( Exception e ) {
Log.i("SDL", "Error: cannot parse /proc/meminfo: " + e.toString());
}
return true;
}
static final int SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP = 0; static final int SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP = 0;
public static void setConfigOptionFromSDL(int option, int value) public static void setConfigOptionFromSDL(int option, int value) {
{ switch (option) {
switch (option)
{
case SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP: case SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP:
Globals.VideoDepthBpp = value; Globals.VideoDepthBpp = value;
break; break;
@ -892,6 +765,7 @@ public class Settings
} }
private static native void nativeSetAccelerometerSettings(int sensitivity, int centerPos); private static native void nativeSetAccelerometerSettings(int sensitivity, int centerPos);
private static native void nativeSetMouseUsed(int RightClickMethod, int ShowScreenUnderFinger, int LeftClickMethod, private static native void nativeSetMouseUsed(int RightClickMethod, int ShowScreenUnderFinger, int LeftClickMethod,
int MoveMouseWithJoystick, int ClickMouseWithDpad, int MaxForce, int MaxRadius, int MoveMouseWithJoystick, int ClickMouseWithDpad, int MaxForce, int MaxRadius,
int MoveMouseWithJoystickSpeed, int MoveMouseWithJoystickAccel, int MoveMouseWithJoystickSpeed, int MoveMouseWithJoystickAccel,
@ -902,29 +776,54 @@ public class Settings
int HoverJitterFilter, int RightMouseButtonLongPress, int HoverJitterFilter, int RightMouseButtonLongPress,
int MoveMouseWithGyroscope, int MoveMouseWithGyroscopeSpeed, int MoveMouseWithGyroscope, int MoveMouseWithGyroscopeSpeed,
int ForceScreenUpdateMouseClick, int ScreenFollowsMouse); int ForceScreenUpdateMouseClick, int ScreenFollowsMouse);
private static native void nativeSetJoystickUsed(int amount); private static native void nativeSetJoystickUsed(int amount);
private static native void nativeSetAccelerometerUsed(); private static native void nativeSetAccelerometerUsed();
private static native void nativeSetMultitouchUsed(); private static native void nativeSetMultitouchUsed();
private static native void nativeSetTouchscreenKeyboardUsed(); private static native void nativeSetTouchscreenKeyboardUsed();
private static native void nativeSetVideoLinearFilter(); private static native void nativeSetVideoLinearFilter();
private static native void nativeSetVideoDepth(int bpp, int gles2, int gles3); private static native void nativeSetVideoDepth(int bpp, int gles2, int gles3);
private static native void nativeSetCompatibilityHacks(); private static native void nativeSetCompatibilityHacks();
private static native void nativeSetVideoMultithreaded(); private static native void nativeSetVideoMultithreaded();
private static native void nativeSetVideoForceSoftwareMode(); private static native void nativeSetVideoForceSoftwareMode();
private static native void nativeSetupScreenKeyboard(int size, int drawsize, int theme, int transparency, int floatingScreenJoystick, int buttonAmount); private static native void nativeSetupScreenKeyboard(int size, int drawsize, int theme, int transparency, int floatingScreenJoystick, int buttonAmount);
private static native void nativeSetupScreenKeyboardButtons(byte[] img); private static native void nativeSetupScreenKeyboardButtons(byte[] img);
private static native void nativeInitKeymap(); private static native void nativeInitKeymap();
private static native int nativeGetKeymapKey(int key); private static native int nativeGetKeymapKey(int key);
private static native void nativeSetKeymapKey(int javakey, int key); private static native void nativeSetKeymapKey(int javakey, int key);
private static native int nativeGetKeymapKeyScreenKb(int keynum); private static native int nativeGetKeymapKeyScreenKb(int keynum);
private static native void nativeSetKeymapKeyScreenKb(int keynum, int key); private static native void nativeSetKeymapKeyScreenKb(int keynum, int key);
private static native void nativeSetScreenKbKeyUsed(int keynum, int used); private static native void nativeSetScreenKbKeyUsed(int keynum, int used);
private static native void nativeSetScreenKbKeyLayout(int keynum, int x1, int y1, int x2, int y2); private static native void nativeSetScreenKbKeyLayout(int keynum, int x1, int y1, int x2, int y2);
private static native int nativeGetKeymapKeyMultitouchGesture(int keynum); private static native int nativeGetKeymapKeyMultitouchGesture(int keynum);
private static native void nativeSetKeymapKeyMultitouchGesture(int keynum, int key); private static native void nativeSetKeymapKeyMultitouchGesture(int keynum, int key);
private static native void nativeSetMultitouchGestureSensitivity(int sensitivity); private static native void nativeSetMultitouchGestureSensitivity(int sensitivity);
private static native void nativeSetTouchscreenCalibration(int x1, int y1, int x2, int y2); private static native void nativeSetTouchscreenCalibration(int x1, int y1, int x2, int y2);
public static native void nativeSetEnv(final String name, final String value); public static native void nativeSetEnv(final String name, final String value);
public static native int nativeChmod(final String name, int mode); public static native int nativeChmod(final String name, int mode);
public static native void nativeChdir(final String dir); public static native void nativeChdir(final String dir);
} }

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import io.neoterm.Globals import io.neoterm.Globals
import io.neoterm.NeoXorgSettings
import io.neoterm.R import io.neoterm.R
import io.neoterm.frontend.component.NeoComponent import io.neoterm.frontend.component.NeoComponent
import io.neoterm.frontend.logging.NLog import io.neoterm.frontend.logging.NLog
@ -66,7 +67,7 @@ class SessionComponent : NeoComponent {
return result return result
} }
private fun checkLibrariesLoaded() { private fun checkLibrariesLoaded(): Boolean {
if (!IS_LIBRARIES_LOADED) { if (!IS_LIBRARIES_LOADED) {
synchronized(SessionComponent::class.java) { synchronized(SessionComponent::class.java) {
if (!IS_LIBRARIES_LOADED) { if (!IS_LIBRARIES_LOADED) {
@ -74,6 +75,7 @@ class SessionComponent : NeoComponent {
} }
} }
} }
return IS_LIBRARIES_LOADED
} }
} }
@ -88,7 +90,10 @@ class SessionComponent : NeoComponent {
fun createSession(context: Context, parameter: XParameter): XSession { fun createSession(context: Context, parameter: XParameter): XSession {
if (context is Activity) { if (context is Activity) {
checkLibrariesLoaded() if (!checkLibrariesLoaded()) {
throw RuntimeException("Cannot load libraries!")
}
return XSession(context, XSessionData()) return XSession(context, XSessionData())
} }
throw RuntimeException("Creating X sessions requires Activity, but got Context") throw RuntimeException("Creating X sessions requires Activity, but got Context")

View File

@ -24,7 +24,7 @@ import java.util.*
* @author kiva * @author kiva
*/ */
class XSession constructor(private val mActivity: Activity, private val sessionData: XSessionData) : NeoXorgViewClient { class XSession constructor(private val mActivity: Activity, val mSessionData: XSessionData) : NeoXorgViewClient {
var mSessionName = ""; var mSessionName = "";
init { init {
@ -33,20 +33,42 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} }
if (sessionData.audioThread == null) { mSessionData.client = this
sessionData.audioThread = NeoAudioThread(this) NeoXorgSettings.init(this)
if (mSessionData.audioThread == null) {
mSessionData.audioThread = NeoAudioThread(this)
} }
} }
fun onPause() {
mSessionData.isPaused = true
if (mSessionData.glView != null) {
mSessionData.glView?.onPause()
}
}
fun onDestroy() {
if (mSessionData.glView != null) {
mSessionData.glView?.exitApp()
}
}
fun onResume() {
if (mSessionData.glView != null) {
mSessionData.glView?.onResume()
}
mSessionData.isPaused = false
}
override fun getContext() = mActivity override fun getContext() = mActivity
override fun isKeyboardWithoutTextInputShown() = sessionData.keyboardWithoutTextInputShown override fun isKeyboardWithoutTextInputShown() = mSessionData.keyboardWithoutTextInputShown
override fun isPaused() = sessionData.isPaused override fun isPaused() = mSessionData.isPaused
override fun runOnUiThread(runnable: Runnable?) = mActivity.runOnUiThread(runnable) override fun runOnUiThread(runnable: Runnable?) = mActivity.runOnUiThread(runnable)
override fun getGLView() = sessionData.glView override fun getGLView() = mSessionData.glView
override fun getWindow() = mActivity.window!! override fun getWindow() = mActivity.window!!
@ -56,14 +78,14 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
val inputManager = mActivity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager val inputManager = mActivity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (!isKeyboardWithoutTextInputShown) { if (!isKeyboardWithoutTextInputShown) {
sessionData.keyboardWithoutTextInputShown = true mSessionData.keyboardWithoutTextInputShown = true
runOnUiThread(Runnable { runOnUiThread(Runnable {
if (keyboard == 0) { if (keyboard == 0) {
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
inputManager.showSoftInput(glView, InputMethodManager.SHOW_FORCED) inputManager.showSoftInput(glView, InputMethodManager.SHOW_FORCED)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
} else { } else {
if (sessionData.screenKeyboard != null) if (mSessionData.screenKeyboard != null)
return@Runnable return@Runnable
val builtinKeyboard = BuiltInKeyboardView(mActivity, null) val builtinKeyboard = BuiltInKeyboardView(mActivity, null)
@ -159,17 +181,17 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
override fun onKey(p1: Int, p2: IntArray) {} override fun onKey(p1: Int, p2: IntArray) {}
}) })
sessionData.screenKeyboard = builtinKeyboard mSessionData.screenKeyboard = builtinKeyboard
val layout = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM) val layout = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM)
sessionData.videoLayout!!.addView(sessionData.screenKeyboard, layout) mSessionData.videoLayout!!.addView(mSessionData.screenKeyboard, layout)
} }
}) })
} else { } else {
sessionData.keyboardWithoutTextInputShown = false mSessionData.keyboardWithoutTextInputShown = false
runOnUiThread { runOnUiThread {
if (sessionData.screenKeyboard != null) { if (mSessionData.screenKeyboard != null) {
sessionData.videoLayout!!.removeView(sessionData.screenKeyboard) mSessionData.videoLayout!!.removeView(mSessionData.screenKeyboard)
sessionData.screenKeyboard = null mSessionData.screenKeyboard = null
} }
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
inputManager.hideSoftInputFromWindow(glView!!.windowToken, 0) inputManager.hideSoftInputFromWindow(glView!!.windowToken, 0)
@ -179,23 +201,23 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
} }
override fun setScreenKeyboardHintMessage(hideMessage: String?) { override fun setScreenKeyboardHintMessage(hideMessage: String?) {
sessionData.screenKeyboardHintMessage = hideMessage mSessionData.screenKeyboardHintMessage = hideMessage
if (sessionData.screenKeyboard is EditText) { if (mSessionData.screenKeyboard is EditText) {
runOnUiThread { runOnUiThread {
val editText = sessionData.screenKeyboard as EditText? val editText = mSessionData.screenKeyboard as EditText?
editText?.hint = hideMessage ?: mActivity.getString(R.string.text_edit_click_here) editText?.hint = hideMessage ?: mActivity.getString(R.string.text_edit_click_here)
} }
} }
} }
override fun isScreenKeyboardShown() = sessionData.screenKeyboard != null override fun isScreenKeyboardShown() = mSessionData.screenKeyboard != null
override fun showScreenKeyboard(oldText: String?) { override fun showScreenKeyboard(oldText: String?) {
if (Globals.CompatibilityHacksTextInputEmulatesHwKeyboard) { if (Globals.CompatibilityHacksTextInputEmulatesHwKeyboard) {
showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard) showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard)
return return
} }
if (sessionData.screenKeyboard != null) if (mSessionData.screenKeyboard != null)
return return
val screenKeyboard = EditText(mActivity, null, val screenKeyboard = EditText(mActivity, null,
@ -203,7 +225,7 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
android.R.style.TextAppearance_Material_Widget_EditText android.R.style.TextAppearance_Material_Widget_EditText
else android.R.style.TextAppearance_Widget_EditText) else android.R.style.TextAppearance_Widget_EditText)
val hint = sessionData.screenKeyboardHintMessage val hint = mSessionData.screenKeyboardHintMessage
screenKeyboard.hint = hint ?: mActivity.getString(R.string.text_edit_click_here) screenKeyboard.hint = hint ?: mActivity.getString(R.string.text_edit_click_here)
screenKeyboard.setText(oldText) screenKeyboard.setText(oldText)
screenKeyboard.setSelection(screenKeyboard.text.length) screenKeyboard.setSelection(screenKeyboard.text.length)
@ -213,8 +235,8 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
if (isRunningOnOUYA && Globals.TvBorders) if (isRunningOnOUYA && Globals.TvBorders)
screenKeyboard.setPadding(100, 100, 100, 100) // Bad bad HDMI TVs all have cropped borders screenKeyboard.setPadding(100, 100, 100, 100) // Bad bad HDMI TVs all have cropped borders
sessionData.screenKeyboard = screenKeyboard mSessionData.screenKeyboard = screenKeyboard
sessionData.videoLayout!!.addView(sessionData.screenKeyboard) mSessionData.videoLayout!!.addView(mSessionData.screenKeyboard)
screenKeyboard.inputType = InputType.TYPE_CLASS_TEXT screenKeyboard.inputType = InputType.TYPE_CLASS_TEXT
screenKeyboard.isFocusableInTouchMode = true screenKeyboard.isFocusableInTouchMode = true
@ -236,19 +258,19 @@ class XSession constructor(private val mActivity: Activity, private val sessionD
if (isKeyboardWithoutTextInputShown) if (isKeyboardWithoutTextInputShown)
showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard) showScreenKeyboardWithoutTextInputField(Globals.TextInputKeyboard)
if (sessionData.screenKeyboard == null || sessionData.screenKeyboard !is EditText) if (mSessionData.screenKeyboard == null || mSessionData.screenKeyboard !is EditText)
return return
synchronized(sessionData.textInput) { synchronized(mSessionData.textInput) {
val text = (sessionData.screenKeyboard as EditText).text.toString() val text = (mSessionData.screenKeyboard as EditText).text.toString()
for (i in 0 until text.length) { for (i in 0 until text.length) {
NeoRenderer.callNativeTextInput(text[i].toInt(), text.codePointAt(i)) NeoRenderer.callNativeTextInput(text[i].toInt(), text.codePointAt(i))
} }
} }
NeoRenderer.callNativeTextInputFinished() NeoRenderer.callNativeTextInputFinished()
inputManager.hideSoftInputFromWindow(sessionData.screenKeyboard!!.windowToken, 0) inputManager.hideSoftInputFromWindow(mSessionData.screenKeyboard!!.windowToken, 0)
sessionData.videoLayout!!.removeView(sessionData.screenKeyboard) mSessionData.videoLayout!!.removeView(mSessionData.screenKeyboard)
sessionData.screenKeyboard = null mSessionData.screenKeyboard = null
glView!!.isFocusableInTouchMode = true glView!!.isFocusableInTouchMode = true
glView!!.isFocusable = true glView!!.isFocusable = true
glView!!.requestFocus() glView!!.requestFocus()

View File

@ -8,17 +8,17 @@ import de.mrapp.android.tabswitcher.Tab
* @author kiva * @author kiva
*/ */
open class NeoTab(title: CharSequence) : Tab(title) { open class NeoTab(title: CharSequence) : Tab(title) {
fun onPause() {} open fun onPause() {}
fun onResume() {} open fun onResume() {}
fun onStart() {} open fun onStart() {}
fun onStop() {} open fun onStop() {}
fun onWindowFocusChanged(hasFocus: Boolean) {} open fun onWindowFocusChanged(hasFocus: Boolean) {}
fun onDestroy() {} open fun onDestroy() {}
fun onConfigurationChanged(newConfig: Configuration) {} open fun onConfigurationChanged(newConfig: Configuration) {}
} }

View File

@ -1,19 +1,22 @@
package io.neoterm.ui.term.tab package io.neoterm.ui.term.tab
import android.content.Context import android.content.Context
import android.graphics.Rect
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout
import de.mrapp.android.tabswitcher.Tab import de.mrapp.android.tabswitcher.Tab
import de.mrapp.android.tabswitcher.TabSwitcher import de.mrapp.android.tabswitcher.TabSwitcher
import de.mrapp.android.tabswitcher.TabSwitcherDecorator import de.mrapp.android.tabswitcher.TabSwitcherDecorator
import io.neoterm.Globals
import io.neoterm.NeoGLView
import io.neoterm.R import io.neoterm.R
import io.neoterm.component.color.ColorSchemeComponent import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.frontend.session.shell.client.TermCompleteListener
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
import io.neoterm.frontend.component.ComponentManager import io.neoterm.frontend.component.ComponentManager
import io.neoterm.frontend.preference.NeoPreference import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.terminal.TerminalView import io.neoterm.frontend.terminal.TerminalView
import io.neoterm.frontend.terminal.eks.ExtraKeysView import io.neoterm.frontend.terminal.eks.ExtraKeysView
import io.neoterm.ui.term.NeoTermActivity import io.neoterm.ui.term.NeoTermActivity
@ -28,6 +31,8 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
private val VIEW_TYPE_X = 2 private val VIEW_TYPE_X = 2
} }
private fun setViewLayerType(view: View?) = view?.setLayerType(View.LAYER_TYPE_NONE, null)
override fun onInflateView(inflater: LayoutInflater, parent: ViewGroup?, viewType: Int): View { override fun onInflateView(inflater: LayoutInflater, parent: ViewGroup?, viewType: Int): View {
return when (viewType) { return when (viewType) {
VIEW_TYPE_TERM -> { VIEW_TYPE_TERM -> {
@ -60,13 +65,63 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
} }
VIEW_TYPE_X -> { VIEW_TYPE_X -> {
val xtab = tab as XSessionTab toolbar.visibility = View.GONE
bindXSessionView(tab) bindXSessionView(tab as XSessionTab)
} }
} }
} }
private fun bindXSessionView(tab: XSessionTab) { private fun bindXSessionView(tab: XSessionTab) {
val sessionData = tab.sessionData ?: return
if (sessionData.videoLayout == null) {
val videoLayout = findViewById<FrameLayout>(R.id.xorg_video_layout)
sessionData.videoLayout = videoLayout
setViewLayerType(videoLayout)
}
val videoLayout = sessionData.videoLayout!!
if (sessionData.glView == null) {
Thread {
sessionData.client?.runOnUiThread {
sessionData.glView = NeoGLView(sessionData.client)
sessionData.glView?.isFocusableInTouchMode = true
sessionData.glView?.isFocusable = true
sessionData.glView?.requestFocus()
setViewLayerType(sessionData.glView)
videoLayout.addView(sessionData.glView,
FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT))
if (Globals.HideSystemMousePointer
&& android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
sessionData.glView?.pointerIcon =
android.view.PointerIcon.getSystemIcon(context,
android.view.PointerIcon.TYPE_NULL)
}
val r = Rect()
videoLayout.getWindowVisibleDisplayFrame(r)
sessionData.glView?.callNativeScreenVisibleRect(r.left, r.top, r.right, r.bottom)
videoLayout.viewTreeObserver.addOnGlobalLayoutListener({
val r = Rect()
videoLayout.getWindowVisibleDisplayFrame(r)
val heightDiff = videoLayout.rootView.height - videoLayout.height // Take system bar into consideration
val widthDiff = videoLayout.rootView.width - videoLayout.width // Nexus 5 has system bar at the right side
Log.v("SDL", "Main window visible region changed: " + r.left + ":" + r.top + ":" + r.width() + ":" + r.height())
videoLayout.postDelayed({
sessionData.glView?.callNativeScreenVisibleRect(r.left + widthDiff, r.top + heightDiff, r.width(), r.height())
}, 300)
videoLayout.postDelayed({
sessionData.glView?.callNativeScreenVisibleRect(r.left + widthDiff, r.top + heightDiff, r.width(), r.height())
}, 600)
})
}
}.start()
}
} }
private fun bindTerminalView(tab: Tab, view: TerminalView?, extraKeysView: ExtraKeysView?) { private fun bindTerminalView(tab: Tab, view: TerminalView?, extraKeysView: ExtraKeysView?) {
@ -105,9 +160,9 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
} }
} }
private fun createAutoCompleteListener(view: TerminalView): OnAutoCompleteListener? { // private fun createAutoCompleteListener(view: TerminalView): OnAutoCompleteListener? {
return TermCompleteListener(view) // return TermCompleteListener(view)
} // }
override fun getViewTypeCount(): Int { override fun getViewTypeCount(): Int {
return 2 return 2

View File

@ -1,5 +1,6 @@
package io.neoterm.ui.term.tab package io.neoterm.ui.term.tab
import android.content.res.Configuration
import io.neoterm.frontend.session.xorg.XSession import io.neoterm.frontend.session.xorg.XSession
/** /**
@ -7,4 +8,35 @@ import io.neoterm.frontend.session.xorg.XSession
*/ */
class XSessionTab(title: CharSequence) : NeoTab(title) { class XSessionTab(title: CharSequence) : NeoTab(title) {
var session: XSession? = null var session: XSession? = null
val sessionData
get() = session?.mSessionData
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (!hasFocus) {
onPause()
} else {
onResume()
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
session?.updateScreenOrientation()
}
override fun onPause() {
session?.onPause()
super.onPause()
}
override fun onDestroy() {
super.onDestroy()
session?.onDestroy()
}
override fun onResume() {
super.onResume()
session?.onResume()
}
} }

View File

@ -3,10 +3,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <FrameLayout
android:layout_centerInParent="true" android:id="@+id/xorg_video_layout"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:text="Hello X Server! Comming soon."/> android:layout_centerInParent="true" />
</RelativeLayout> </RelativeLayout>