Initial work to make android STK use SDL2 completely
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
package org.supertuxkart.stk_dbg;
|
||||
|
||||
import org.supertuxkart.stk_dbg.STKEditText;
|
||||
import org.libsdl.app.SDLActivity;
|
||||
|
||||
import org.libsdl.app.SDLControllerManager;
|
||||
import org.libsdl.app.HIDDeviceManager;
|
||||
|
||||
import android.app.NativeActivity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -32,45 +29,13 @@ import org.minidns.hla.ResolverResult;
|
||||
import org.minidns.record.SRV;
|
||||
import org.minidns.record.TXT;
|
||||
|
||||
public class SuperTuxKartActivity extends NativeActivity
|
||||
public class SuperTuxKartActivity extends SDLActivity
|
||||
{
|
||||
// Same as irrlicht
|
||||
enum TouchInputEvent
|
||||
{
|
||||
ETIE_PRESSED_DOWN,
|
||||
ETIE_LEFT_UP,
|
||||
ETIE_MOVED,
|
||||
ETIE_COUNT
|
||||
}
|
||||
|
||||
class TouchEventData
|
||||
{
|
||||
public TouchInputEvent event_type;
|
||||
public int x;
|
||||
public int y;
|
||||
TouchEventData()
|
||||
{
|
||||
event_type = TouchInputEvent.ETIE_PRESSED_DOWN;
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
};
|
||||
|
||||
private TouchEventData[] m_touch_event_data;
|
||||
private STKEditText m_stk_edittext;
|
||||
private static Context m_context;
|
||||
private static HIDDeviceManager m_hid_device_manager;
|
||||
|
||||
private int m_bottom_y;
|
||||
// ------------------------------------------------------------------------
|
||||
private native void saveKeyboardHeight(int height);
|
||||
// ------------------------------------------------------------------------
|
||||
private native void startSTK();
|
||||
// ------------------------------------------------------------------------
|
||||
private native static void addKey(int key_code, int action, int meta_state,
|
||||
int scan_code, int unichar);
|
||||
// ------------------------------------------------------------------------
|
||||
private native static void addTouch(int id, int x, int y, int event_type);
|
||||
// ------------------------------------------------------------------------
|
||||
private native static void addDNSSrvRecords(String name, int weight);
|
||||
// ------------------------------------------------------------------------
|
||||
private void hideKeyboardNative(final boolean clear_text)
|
||||
@@ -88,24 +53,14 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
imm.hideSoftInputFromWindow(m_stk_edittext.getWindowToken(), 0);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
private void hideNavBar(View decor_view)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < 19)
|
||||
return;
|
||||
decor_view.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
private void createSTKEditText()
|
||||
{
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
// We move the dummy edittext out of the android screen because we draw
|
||||
// our own manually
|
||||
params.setMargins(0, -100000, 1, -100010);
|
||||
m_stk_edittext = new STKEditText(this);
|
||||
// For some copy-and-paste text are not done by commitText in
|
||||
// STKInputConnection, so we need an extra watcher
|
||||
@@ -120,7 +75,7 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
@Override
|
||||
public void afterTextChanged(Editable edit)
|
||||
{
|
||||
if (!isHardwareKeyboardConnected() && m_stk_edittext != null)
|
||||
if (m_stk_edittext != null)
|
||||
m_stk_edittext.updateSTKEditBox();
|
||||
}
|
||||
});
|
||||
@@ -133,15 +88,7 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
public void onCreate(Bundle instance)
|
||||
{
|
||||
super.onCreate(instance);
|
||||
// We don't use native activity input event queue
|
||||
getWindow().takeInputQueue(null);
|
||||
System.loadLibrary("main");
|
||||
m_touch_event_data = new TouchEventData[32];
|
||||
for (int i = 0; i < 32; i++)
|
||||
m_touch_event_data[i] = new TouchEventData();
|
||||
m_context = this;
|
||||
m_stk_edittext = null;
|
||||
|
||||
m_bottom_y = 0;
|
||||
final View root = getWindow().getDecorView().findViewById(
|
||||
android.R.id.content);
|
||||
root.getViewTreeObserver().addOnGlobalLayoutListener(new
|
||||
@@ -155,26 +102,13 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
int screen_height = root.getRootView().getHeight();
|
||||
int keyboard_height = screen_height - (r.bottom);
|
||||
saveKeyboardHeight(keyboard_height);
|
||||
int moved_height = 0;
|
||||
int margin = screen_height - m_bottom_y;
|
||||
if (keyboard_height > margin)
|
||||
moved_height = -keyboard_height + margin;
|
||||
SDLActivity.moveView(moved_height);
|
||||
}
|
||||
});
|
||||
|
||||
final View decor_view = getWindow().getDecorView();
|
||||
decor_view.setOnSystemUiVisibilityChangeListener(
|
||||
new View.OnSystemUiVisibilityChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onSystemUiVisibilityChange(int visibility)
|
||||
{
|
||||
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0)
|
||||
hideNavBar(decor_view);
|
||||
}
|
||||
});
|
||||
SDLControllerManager.nativeSetupJNI();
|
||||
SDLControllerManager.initialize();
|
||||
m_hid_device_manager = HIDDeviceManager.acquire(this);
|
||||
// We only start stk main thread after JNI_OnLoad (for initializing the
|
||||
// java environment)
|
||||
startSTK();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
@@ -182,194 +116,16 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
{
|
||||
super.onPause();
|
||||
hideKeyboardNative(false/*clear_text*/);
|
||||
if (m_hid_device_manager != null)
|
||||
m_hid_device_manager.setFrozen(true);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
public void onResume()
|
||||
|
||||
/* STK statically link SDL2. */
|
||||
protected String[] getLibraries()
|
||||
{
|
||||
super.onResume();
|
||||
if (m_hid_device_manager != null)
|
||||
m_hid_device_manager.setFrozen(false);
|
||||
return new String[]{ "main" };
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
protected void onDestroy()
|
||||
{
|
||||
if (m_hid_device_manager != null)
|
||||
{
|
||||
HIDDeviceManager.release(m_hid_device_manager);
|
||||
m_hid_device_manager = null;
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean has_focus)
|
||||
{
|
||||
super.onWindowFocusChanged(has_focus);
|
||||
if (has_focus)
|
||||
hideNavBar(getWindow().getDecorView());
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event)
|
||||
{
|
||||
int key_code = event.getKeyCode();
|
||||
int action = event.getAction();
|
||||
int device_id = event.getDeviceId();
|
||||
int source = event.getSource();
|
||||
int meta_state = event.getMetaState();
|
||||
int scan_code = event.getScanCode();
|
||||
// KeyCharacterMap.COMBINING_ACCENT is not handled at the moment
|
||||
int unichar = event.getUnicodeChar(meta_state);
|
||||
int repeat_count = event.getRepeatCount();
|
||||
|
||||
// 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(device_id))
|
||||
{
|
||||
// Note that we process events with specific key codes here
|
||||
if (action == KeyEvent.ACTION_DOWN)
|
||||
{
|
||||
if (SDLControllerManager.onNativePadDown(device_id, key_code, meta_state, scan_code, unichar, repeat_count) == 0)
|
||||
return true;
|
||||
}
|
||||
else if (action == KeyEvent.ACTION_UP)
|
||||
{
|
||||
if (SDLControllerManager.onNativePadUp(device_id, key_code, meta_state, scan_code, unichar) == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// User pressed back button
|
||||
if (key_code == KeyEvent.KEYCODE_BACK &&
|
||||
action == KeyEvent.ACTION_DOWN)
|
||||
{
|
||||
// Avoid repeating the event which leads to some strange behaviour
|
||||
// For ACTION_UP it's always zero
|
||||
if (repeat_count == 0)
|
||||
addKey(key_code, action, meta_state, scan_code, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean has_hardware_keyboard = isHardwareKeyboardConnected();
|
||||
// Allow hacker keyboard (one of the native android keyboard)
|
||||
// to close itself when pressing the esc button
|
||||
if (key_code == KeyEvent.KEYCODE_ESCAPE &&
|
||||
action == KeyEvent.ACTION_DOWN && !has_hardware_keyboard &&
|
||||
m_stk_edittext != null && m_stk_edittext.isFocused())
|
||||
{
|
||||
hideKeyboardNative(/*clear_text*/false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when user change cursor / select all text in native android
|
||||
// keyboard
|
||||
boolean ret = super.dispatchKeyEvent(event);
|
||||
if (!has_hardware_keyboard && m_stk_edittext != null)
|
||||
m_stk_edittext.updateSTKEditBox();
|
||||
|
||||
// Allow sending navigation key event found in native android keyboard
|
||||
// so user can using up or down to toggle multiple textfield
|
||||
boolean send_navigation = key_code == KeyEvent.KEYCODE_DPAD_UP ||
|
||||
key_code == KeyEvent.KEYCODE_DPAD_DOWN ||
|
||||
key_code == KeyEvent.KEYCODE_DPAD_LEFT ||
|
||||
key_code == KeyEvent.KEYCODE_DPAD_RIGHT;
|
||||
// We don't send navigation event if it's consumed by input method
|
||||
send_navigation = send_navigation && !ret;
|
||||
|
||||
if (has_hardware_keyboard || send_navigation)
|
||||
{
|
||||
if (has_hardware_keyboard &&
|
||||
m_stk_edittext != null && m_stk_edittext.isFocused())
|
||||
m_stk_edittext.beforeHideKeyboard(/*clear_text*/true);
|
||||
addKey(key_code, action, meta_state, scan_code, unichar);
|
||||
// We use only java to handle key for hardware keyboard
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent ev)
|
||||
{
|
||||
if (SDLControllerManager.useGenericMotionListener(ev))
|
||||
return true;
|
||||
return super.dispatchGenericMotionEvent(ev);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev)
|
||||
{
|
||||
boolean ret = super.dispatchTouchEvent(ev);
|
||||
if (!ret)
|
||||
{
|
||||
TouchInputEvent event_type;
|
||||
int action = ev.getAction();
|
||||
switch (action & MotionEvent.ACTION_MASK)
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
event_type = TouchInputEvent.ETIE_PRESSED_DOWN;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
event_type = TouchInputEvent.ETIE_MOVED;
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
event_type = TouchInputEvent.ETIE_LEFT_UP;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 1;
|
||||
int idx = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
|
||||
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
|
||||
// Process all touches for move action.
|
||||
if (event_type == TouchInputEvent.ETIE_MOVED)
|
||||
{
|
||||
count = ev.getPointerCount();
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int id = ev.getPointerId(i + idx);
|
||||
int x = (int)ev.getX(i + idx);
|
||||
int y = (int)ev.getY(i + idx);
|
||||
|
||||
if (id >= 32)
|
||||
continue;
|
||||
|
||||
// Don't send move event when nothing changed
|
||||
if (m_touch_event_data[id].event_type == event_type &&
|
||||
m_touch_event_data[id].x == x &&
|
||||
m_touch_event_data[id].y == y)
|
||||
continue;
|
||||
|
||||
m_touch_event_data[id].event_type = event_type;
|
||||
m_touch_event_data[id].x = x;
|
||||
m_touch_event_data[id].y = y;
|
||||
addTouch(id, x, y, event_type.ordinal());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
public void showKeyboard(final int type)
|
||||
public void showKeyboard(final int type, final int y)
|
||||
{
|
||||
final Context context = this;
|
||||
// Need to run in ui thread as it access the view m_stk_edittext
|
||||
@@ -378,6 +134,7 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
m_bottom_y = y;
|
||||
InputMethodManager imm = (InputMethodManager)
|
||||
getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm == null)
|
||||
@@ -404,6 +161,7 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
m_bottom_y = 0;
|
||||
hideKeyboardNative(clear_text);
|
||||
}
|
||||
});
|
||||
@@ -486,5 +244,9 @@ public class SuperTuxKartActivity extends NativeActivity
|
||||
.keyboard == Configuration.KEYBOARD_QWERTY;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
public static Context getContext() { return m_context; }
|
||||
public int getScreenSize()
|
||||
{
|
||||
return getResources().getConfiguration().screenLayout &
|
||||
Configuration.SCREENLAYOUT_SIZE_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user