summaryrefslogtreecommitdiffstats
path: root/tests/auto/android/src
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/android/src')
-rw-r--r--tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java327
-rw-r--r--tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java209
-rw-r--r--tests/auto/android/src/org/qtproject/qt5/android/QtNative.java421
-rw-r--r--tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java163
4 files changed, 1120 insertions, 0 deletions
diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java b/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java
new file mode 100644
index 0000000000..ae4ca3c30a
--- /dev/null
+++ b/tests/auto/android/src/org/qtproject/qt5/android/QtActivity.java
@@ -0,0 +1,327 @@
+/*
+ Copyright (c) 2012, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt-project.org/legal
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.qtproject.qt5.android.tests.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.text.method.MetaKeyKeyListener;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+
+public class QtActivity extends Activity {
+ private int m_id =- 1;
+ private boolean softwareKeyboardIsVisible = false;
+ private long m_metaState;
+ private int m_lastChar = 0;
+ private boolean m_fullScreen = false;
+ private boolean m_started = false;
+ private QtSurface m_surface = null;
+ private boolean m_usesGL = false;
+ private void loadQtLibs(String[] libs, String environment, String params, String mainLib, String nativeLibDir) throws Exception
+ {
+ QtNative.loadQtLibraries(libs);
+ // start application
+
+ final String envPaths = "NECESSITAS_API_LEVEL=2\tHOME=" + getDir("files", MODE_WORLD_WRITEABLE).getAbsolutePath() +
+ "\tTMPDIR=" + getDir("files", MODE_WORLD_WRITEABLE).getAbsolutePath() +
+ "\tCACHE_PATH=" + getDir("files", MODE_WORLD_WRITEABLE).getAbsolutePath();
+ if (environment != null && environment.length() > 0)
+ environment = envPaths + "\t" + environment;
+ else
+ environment = envPaths;
+
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ QtNative.startApplication(params, environment, mainLib, nativeLibDir);
+ m_surface.applicationStarted(m_usesGL);
+ m_started = true;
+ }
+
+ private boolean m_quitApp = true;
+ private Process m_debuggerProcess = null; // debugger process
+
+ private void startApp(final boolean firstStart)
+ {
+ try {
+ String qtLibs[] = getResources().getStringArray(R.array.qt_libs);
+ ArrayList<String> libraryList = new ArrayList<String>();
+ for (int i = 0; i < qtLibs.length; i++)
+ libraryList.add("/data/local/qt/lib/lib" + qtLibs[i] + ".so");
+
+ String mainLib = null;
+ String nativeLibDir = null;
+ if (getIntent().getExtras() != null) {
+ if (getIntent().getExtras().containsKey("extra_libs")) {
+ String extra_libs = getIntent().getExtras().getString("extra_libs");
+ for (String lib : extra_libs.split(":"))
+ libraryList.add(lib);
+ }
+ if (getIntent().getExtras().containsKey("lib_name")) {
+ mainLib = getIntent().getExtras().getString("lib_name");
+ int slash = mainLib.lastIndexOf("/");
+ if (slash >= 0) {
+ nativeLibDir = mainLib.substring(0, slash+1);
+ mainLib = mainLib.substring(slash+1+3, mainLib.length()-3); //remove lib and .so
+ } else {
+ nativeLibDir = "";
+ }
+ }
+
+ if (getIntent().getExtras().containsKey("needsOpenGl"))
+ m_usesGL = getIntent().getExtras().getBoolean("needsOpenGl");
+ } else {
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ System.exit(0);
+ }
+ String[] libs = new String[libraryList.size()];
+ libs = libraryList.toArray(libs);
+ loadQtLibs(libs, "QML_IMPORT_PATH=/data/local/qt/imports\tQT_PLUGIN_PATH=/data/local/qt/plugins",
+ "-xml\t-silent\t-o\toutput.xml", mainLib, nativeLibDir);
+ } catch (Exception e) {
+ Log.e(QtNative.QtTAG, "Can't create main activity", e);
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ getDir("files", MODE_WORLD_WRITEABLE);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ m_quitApp = true;
+ QtNative.setMainActivity(this);
+ if (null == getLastNonConfigurationInstance()) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ QtNative.setApplicationDisplayMetrics(metrics.widthPixels, metrics.heightPixels,
+ metrics.widthPixels, metrics.heightPixels,
+ metrics.xdpi, metrics.ydpi);
+ }
+ m_surface = new QtSurface(this, m_id);
+ setContentView(m_surface);
+ if (null == getLastNonConfigurationInstance())
+ startApp(true);
+ }
+
+ public QtSurface getQtSurface()
+ {
+ return m_surface;
+ }
+
+ @Override
+ public Object onRetainNonConfigurationInstance()
+ {
+ super.onRetainNonConfigurationInstance();
+ m_quitApp = false;
+ return true;
+ }
+
+ @Override
+ protected void onDestroy()
+ {
+ QtNative.setMainActivity(null);
+ super.onDestroy();
+ if (m_quitApp) {
+ Log.i(QtNative.QtTAG, "onDestroy");
+ if (m_debuggerProcess != null)
+ m_debuggerProcess.destroy();
+ System.exit(0);// FIXME remove it or find a better way
+ }
+ QtNative.setMainActivity(null);
+ }
+
+ @Override
+ protected void onResume()
+ {
+ // fire all lostActions
+ synchronized (QtNative.m_mainActivityMutex) {
+ Iterator<Runnable> itr = QtNative.getLostActions().iterator();
+ while (itr.hasNext())
+ runOnUiThread(itr.next());
+ if (m_started) {
+ QtNative.clearLostActions();
+ QtNative.updateWindow();
+ }
+ }
+ super.onResume();
+ }
+
+ public void redrawWindow(int left, int top, int right, int bottom)
+ {
+ m_surface.drawBitmap(new Rect(left, top, right, bottom));
+ }
+
+ public void setFullScreen(boolean enterFullScreen)
+ {
+ if (m_fullScreen == enterFullScreen)
+ return;
+ if (m_fullScreen = enterFullScreen)
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ else
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState)
+ {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean("FullScreen", m_fullScreen);
+ outState.putBoolean("Started", m_started);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState)
+ {
+ super.onRestoreInstanceState(savedInstanceState);
+ setFullScreen(savedInstanceState.getBoolean("FullScreen"));
+ m_started = savedInstanceState.getBoolean("Started");
+ if (m_started)
+ m_surface.applicationStarted(true);
+ }
+
+ public void showSoftwareKeyboard()
+ {
+ softwareKeyboardIsVisible = true;
+ InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
+ }
+
+ public void resetSoftwareKeyboard()
+ {
+ }
+
+ public void hideSoftwareKeyboard()
+ {
+ if (softwareKeyboardIsVisible) {
+ InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.toggleSoftInput(0, 0);
+ }
+ softwareKeyboardIsVisible = false;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event)
+ {
+ if (m_started && event.getAction() == KeyEvent.ACTION_MULTIPLE &&
+ event.getCharacters() != null &&
+ event.getCharacters().length() == 1 &&
+ event.getKeyCode() == 0) {
+ Log.i(QtNative.QtTAG, "dispatchKeyEvent at MULTIPLE with one character: " + event.getCharacters());
+ QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState());
+ QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState());
+ }
+
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event)
+ {
+ if (!m_started)
+ return false;
+ m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event);
+ int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState));
+ int lc = c;
+ m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState);
+
+ if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
+ c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
+ int composed = KeyEvent.getDeadChar(m_lastChar, c);
+ c = composed;
+ }
+ m_lastChar = lc;
+ if (keyCode != KeyEvent.KEYCODE_BACK)
+ QtNative.keyDown(keyCode, c, event.getMetaState());
+ return true;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event)
+ {
+ if (!m_started)
+ return false;
+ m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event);
+ QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState());
+ return true;
+ }
+
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ }
+
+/* public boolean onCreateOptionsMenu(Menu menu)
+ {
+ QtNative.createOptionsMenu(menu);
+ try {
+ return onPrepareOptionsMenu(menu);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public boolean onPrepareOptionsMenu(Menu menu)
+ {
+ QtNative.prepareOptionsMenu(menu);
+ try {
+ return (Boolean) onPrepareOptionsMenu(menu);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ return QtNative.optionsItemSelected(item.getGroupId(), item.getItemId());
+ }*/
+}
diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java b/tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java
new file mode 100644
index 0000000000..e69a03061b
--- /dev/null
+++ b/tests/auto/android/src/org/qtproject/qt5/android/QtInputConnection.java
@@ -0,0 +1,209 @@
+/*
+ Copyright (c) 2012, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt-project.org/legal
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android;
+
+import android.content.Context;
+import android.content.Intent;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.ExtractedText;
+import android.view.inputmethod.ExtractedTextRequest;
+import android.view.inputmethod.InputMethodManager;
+
+class QtExtractedText
+{
+ public int partialEndOffset;
+ public int partialStartOffset;
+ public int selectionEnd;
+ public int selectionStart;
+ public int startOffset;
+ public String text;
+}
+
+class QtNativeInputConnection
+{
+ static native boolean commitText(String text, int newCursorPosition);
+ static native boolean commitCompletion(String text, int position);
+ static native boolean deleteSurroundingText(int leftLength, int rightLength);
+ static native boolean finishComposingText();
+ static native int getCursorCapsMode(int reqModes);
+ static native QtExtractedText getExtractedText(int hintMaxChars, int hintMaxLines, int flags);
+ static native String getSelectedText(int flags);
+ static native String getTextAfterCursor(int length, int flags);
+ static native String getTextBeforeCursor(int length, int flags);
+ static native boolean setComposingText(String text, int newCursorPosition);
+ static native boolean setSelection(int start, int end);
+ static native boolean selectAll();
+ static native boolean cut();
+ static native boolean copy();
+ static native boolean copyURL();
+ static native boolean paste();
+}
+
+public class QtInputConnection extends BaseInputConnection
+{
+ private static final int ID_SELECT_ALL = android.R.id.selectAll;
+ private static final int ID_START_SELECTING_TEXT = android.R.id.startSelectingText;
+ private static final int ID_STOP_SELECTING_TEXT = android.R.id.stopSelectingText;
+ private static final int ID_CUT = android.R.id.cut;
+ private static final int ID_COPY = android.R.id.copy;
+ private static final int ID_PASTE = android.R.id.paste;
+ private static final int ID_COPY_URL = android.R.id.copyUrl;
+ private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod;
+ private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary;
+ View m_view;
+
+ public QtInputConnection(View targetView)
+ {
+ super(targetView, true);
+ m_view = targetView;
+ }
+
+ @Override
+ public boolean beginBatchEdit()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean endBatchEdit()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean commitCompletion(CompletionInfo text)
+ {
+ return QtNativeInputConnection.commitCompletion(text.getText().toString(), text.getPosition());
+ }
+
+ @Override
+ public boolean commitText(CharSequence text, int newCursorPosition)
+ {
+ return QtNativeInputConnection.commitText(text.toString(), newCursorPosition);
+ }
+
+ @Override
+ public boolean deleteSurroundingText(int leftLength, int rightLength)
+ {
+ return QtNativeInputConnection.deleteSurroundingText(leftLength, rightLength);
+ }
+
+ @Override
+ public boolean finishComposingText()
+ {
+ return QtNativeInputConnection.finishComposingText();
+ }
+
+ @Override
+ public int getCursorCapsMode(int reqModes)
+ {
+ return QtNativeInputConnection.getCursorCapsMode(reqModes);
+ }
+
+ @Override
+ public ExtractedText getExtractedText(ExtractedTextRequest request, int flags)
+ {
+ QtExtractedText qExtractedText = QtNativeInputConnection.getExtractedText(request.hintMaxChars, request.hintMaxLines, flags);
+ ExtractedText extractedText = new ExtractedText();
+ extractedText.partialEndOffset = qExtractedText.partialEndOffset;
+ extractedText.partialStartOffset = qExtractedText.partialStartOffset;
+ extractedText.selectionEnd = qExtractedText.selectionEnd;
+ extractedText.selectionStart = qExtractedText.selectionStart;
+ extractedText.startOffset = qExtractedText.startOffset;
+ extractedText.text = qExtractedText.text;
+ return extractedText;
+ }
+
+ public CharSequence getSelectedText(int flags)
+ {
+ return QtNativeInputConnection.getSelectedText(flags);
+ }
+
+ @Override
+ public CharSequence getTextAfterCursor(int length, int flags)
+ {
+ return QtNativeInputConnection.getTextAfterCursor(length, flags);
+ }
+
+ @Override
+ public CharSequence getTextBeforeCursor(int length, int flags)
+ {
+ return QtNativeInputConnection.getTextBeforeCursor(length, flags);
+ }
+
+ @Override
+ public boolean performContextMenuAction(int id)
+ {
+ switch (id) {
+ case ID_SELECT_ALL:
+ return QtNativeInputConnection.selectAll();
+ case ID_COPY:
+ return QtNativeInputConnection.copy();
+ case ID_COPY_URL:
+ return QtNativeInputConnection.copyURL();
+ case ID_CUT:
+ return QtNativeInputConnection.cut();
+ case ID_PASTE:
+ return QtNativeInputConnection.paste();
+
+ case ID_SWITCH_INPUT_METHOD:
+ InputMethodManager imm = (InputMethodManager)m_view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ imm.showInputMethodPicker();
+ }
+ return true;
+
+ case ID_ADD_TO_DICTIONARY:
+// TODO
+// String word = m_editable.subSequence(0, m_editable.length()).toString();
+// if (word != null) {
+// Intent i = new Intent("com.android.settings.USER_DICTIONARY_INSERT");
+// i.putExtra("word", word);
+// i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+// m_view.getContext().startActivity(i);
+// }
+ return true;
+ }
+ return super.performContextMenuAction(id);
+ }
+
+ @Override
+ public boolean setComposingText(CharSequence text, int newCursorPosition) {
+ return QtNativeInputConnection.setComposingText(text.toString(), newCursorPosition);
+ }
+
+ @Override
+ public boolean setSelection(int start, int end) {
+ return QtNativeInputConnection.setSelection(start, end);
+ }
+}
diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java b/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java
new file mode 100644
index 0000000000..8faeabe5b0
--- /dev/null
+++ b/tests/auto/android/src/org/qtproject/qt5/android/QtNative.java
@@ -0,0 +1,421 @@
+/*
+ Copyright (c) 2012, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt-project.org/legal
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.Application;
+import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MotionEvent;
+
+public class QtNative extends Application
+{
+ private static QtActivity m_mainActivity = null;
+ private static QtSurface m_mainView = null;
+ public static Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations
+
+ public static final String QtTAG = "Qt JAVA"; // string used for Log.x
+ private static ArrayList<Runnable> m_lostActions = new ArrayList<Runnable>(); // a list containing all actions which could not be performed (e.g. the main activity is destroyed, etc.)
+ private static boolean m_started = false;
+ private static int m_displayMetricsScreenWidthPixels = 0;
+ private static int m_displayMetricsScreenHeightPixels = 0;
+ private static int m_displayMetricsDesktopWidthPixels = 0;
+ private static int m_displayMetricsDesktopHeightPixels = 0;
+ private static double m_displayMetricsXDpi = .0;
+ private static double m_displayMetricsYDpi = .0;
+ private static int m_oldx, m_oldy;
+ private static final int m_moveThreshold = 0;
+
+ public static ClassLoader classLoader()
+ {
+ return m_mainActivity.getClassLoader();
+ }
+
+ public static Activity activity()
+ {
+ return m_mainActivity;
+ }
+
+ public static QtSurface mainView()
+ {
+ return m_mainView;
+ }
+
+ public static void openURL(String url)
+ {
+ Uri uri = Uri.parse(url);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ activity().startActivity(intent);
+ }
+
+ // this method loads full path libs
+ public static void loadQtLibraries(String[] libraries)
+ {
+ if (libraries == null)
+ return;
+
+ for (int i = 0; i < libraries.length; i++) {
+ try {
+ File f = new File(libraries[i]);
+ if (f.exists())
+ System.load(libraries[i]);
+ } catch (SecurityException e) {
+ Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e);
+ } catch (Exception e) {
+ Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e);
+ }
+ }
+ }
+
+ // this method loads bundled libs by name.
+ public static void loadBundledLibraries(String[] libraries)
+ {
+ for (int i = 0; i < libraries.length; i++) {
+ try {
+ System.loadLibrary(libraries[i]);
+ } catch (UnsatisfiedLinkError e) {
+ Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e);
+ } catch (SecurityException e) {
+ Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e);
+ } catch (Exception e) {
+ Log.i(QtTAG, "Can't load '" + libraries[i] + "'", e);
+ }
+ }
+ }
+
+ public static void setMainActivity(QtActivity qtMainActivity)
+ {
+ synchronized (m_mainActivityMutex) {
+ m_mainActivity = qtMainActivity;
+ }
+ }
+ public static void setMainView(QtSurface qtSurface)
+ {
+ synchronized (m_mainActivityMutex) {
+ m_mainView = qtSurface;
+ }
+ }
+
+ static public ArrayList<Runnable> getLostActions()
+ {
+ return m_lostActions;
+ }
+
+ static public void clearLostActions()
+ {
+ m_lostActions.clear();
+ }
+
+ private static boolean runAction(Runnable action)
+ {
+ synchronized (m_mainActivityMutex) {
+ if (m_mainActivity == null)
+ m_lostActions.add(action);
+ else
+ m_mainActivity.runOnUiThread(action);
+ return m_mainActivity != null;
+ }
+ }
+
+ public static boolean startApplication(String params, String environment, String mainLibrary, String nativeLibraryDir) throws Exception
+ {
+ File f = new File(nativeLibraryDir+"lib"+mainLibrary+".so");
+ if (!f.exists())
+ throw new Exception("Can't find main library '" + mainLibrary + "'");
+
+ if (params == null)
+ params = "-platform\tandroid";
+
+ boolean res = false;
+ synchronized (m_mainActivityMutex) {
+ res = startQtAndroidPlugin();
+ setDisplayMetrics(m_displayMetricsScreenWidthPixels,
+ m_displayMetricsScreenHeightPixels,
+ m_displayMetricsDesktopWidthPixels,
+ m_displayMetricsDesktopHeightPixels,
+ m_displayMetricsXDpi,
+ m_displayMetricsYDpi);
+ startQtApplication(f.getAbsolutePath()+"\t"+params, environment);
+ m_started = true;
+ }
+ return res;
+ }
+
+ public static void setApplicationDisplayMetrics(int screenWidthPixels,
+ int screenHeightPixels, int desktopWidthPixels,
+ int desktopHeightPixels, double XDpi, double YDpi)
+ {
+ /* Fix buggy dpi report */
+ if (XDpi < android.util.DisplayMetrics.DENSITY_LOW)
+ XDpi = android.util.DisplayMetrics.DENSITY_LOW;
+ if (YDpi < android.util.DisplayMetrics.DENSITY_LOW)
+ YDpi = android.util.DisplayMetrics.DENSITY_LOW;
+
+ synchronized (m_mainActivityMutex) {
+ if (m_started) {
+ setDisplayMetrics(screenWidthPixels, screenHeightPixels, desktopWidthPixels, desktopHeightPixels, XDpi, YDpi);
+ } else {
+ m_displayMetricsScreenWidthPixels = screenWidthPixels;
+ m_displayMetricsScreenHeightPixels = screenHeightPixels;
+ m_displayMetricsDesktopWidthPixels = desktopWidthPixels;
+ m_displayMetricsDesktopHeightPixels = desktopHeightPixels;
+ m_displayMetricsXDpi = XDpi;
+ m_displayMetricsYDpi = YDpi;
+ }
+ }
+ }
+
+ public static void pauseApplication()
+ {
+ synchronized (m_mainActivityMutex) {
+ if (m_started)
+ pauseQtApp();
+ }
+ }
+
+ public static void resumeApplication()
+ {
+ synchronized (m_mainActivityMutex) {
+ if (m_started) {
+ resumeQtApp();
+ updateWindow();
+ }
+ }
+ }
+ // application methods
+ public static native void startQtApplication(String params, String env);
+ public static native void pauseQtApp();
+ public static native void resumeQtApp();
+ public static native boolean startQtAndroidPlugin();
+ public static native void quitQtAndroidPlugin();
+ public static native void terminateQt();
+ // application methods
+
+ private static void quitApp()
+ {
+ m_mainActivity.finish();
+ }
+
+ private static void redrawSurface(final int left, final int top, final int right, final int bottom )
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_mainActivity.redrawWindow(left, top, right, bottom);
+ }
+ });
+ }
+
+ @Override
+ public void onTerminate()
+ {
+ if (m_started)
+ terminateQt();
+ super.onTerminate();
+ }
+
+
+ static public void sendTouchEvent(MotionEvent event, int id)
+ {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_UP:
+ mouseUp(id,(int) event.getX(), (int) event.getY());
+ break;
+
+ case MotionEvent.ACTION_DOWN:
+ mouseDown(id,(int) event.getX(), (int) event.getY());
+ m_oldx = (int) event.getX();
+ m_oldy = (int) event.getY();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ int dx = (int) (event.getX() - m_oldx);
+ int dy = (int) (event.getY() - m_oldy);
+ if (Math.abs(dx) > m_moveThreshold || Math.abs(dy) > m_moveThreshold) {
+ mouseMove(id,(int) event.getX(), (int) event.getY());
+ m_oldx = (int) event.getX();
+ m_oldy = (int) event.getY();
+ }
+ break;
+ }
+ }
+
+ static public void sendTrackballEvent(MotionEvent event, int id)
+ {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_UP:
+ mouseUp(id, (int) event.getX(), (int) event.getY());
+ break;
+
+ case MotionEvent.ACTION_DOWN:
+ mouseDown(id, (int) event.getX(), (int) event.getY());
+ m_oldx = (int) event.getX();
+ m_oldy = (int) event.getY();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ int dx = (int) (event.getX() - m_oldx);
+ int dy = (int) (event.getY() - m_oldy);
+ if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
+ mouseMove(id, (int) event.getX(), (int) event.getY());
+ m_oldx = (int) event.getX();
+ m_oldy = (int) event.getY();
+ }
+ break;
+ }
+ }
+
+
+ private static void showSoftwareKeyboard(final int x, final int y
+ , final int width, final int height
+ , final int inputHints )
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_mainActivity.showSoftwareKeyboard();
+ }
+ });
+ }
+
+ private static void resetSoftwareKeyboard()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_mainActivity.resetSoftwareKeyboard();
+ }
+ });
+ }
+
+ private static void hideSoftwareKeyboard()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_mainActivity.hideSoftwareKeyboard();
+ }
+ });
+ }
+
+ private static void setFullScreen(final boolean fullScreen)
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_mainActivity.setFullScreen(fullScreen);
+ updateWindow();
+ }
+ });
+ }
+
+ // screen methods
+ public static native void setDisplayMetrics(int screenWidthPixels,
+ int screenHeightPixels, int desktopWidthPixels,
+ int desktopHeightPixels, double XDpi, double YDpi);
+ // screen methods
+
+ private static void showOptionsMenu()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_mainActivity != null)
+ m_mainActivity.openOptionsMenu();
+ }
+ });
+ }
+
+ private static void hideOptionsMenu()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_mainActivity != null)
+ m_mainActivity.closeOptionsMenu();
+ }
+ });
+ }
+
+ private static void showContextMenu()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_mainActivity != null)
+ m_mainActivity.openContextMenu(m_mainView);
+ }
+ });
+ }
+
+ private static void hideContextMenu()
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ if (m_mainActivity != null)
+ m_mainActivity.closeContextMenu();
+ }
+ });
+ }
+
+ // pointer methods
+ public static native void mouseDown(int winId, int x, int y);
+ public static native void mouseUp(int winId, int x, int y);
+ public static native void mouseMove(int winId, int x, int y);
+ public static native void touchBegin(int winId);
+ public static native void touchAdd(int winId, int pointerId, int action, boolean primary, int x, int y, float size, float pressure);
+ public static native void touchEnd(int winId, int action);
+ // pointer methods
+
+ // keyboard methods
+ public static native void keyDown(int key, int unicode, int modifier);
+ public static native void keyUp(int key, int unicode, int modifier);
+ // keyboard methods
+
+ // surface methods
+ public static native void destroySurface();
+ public static native void setSurface(Object surface);
+ public static native void lockSurface();
+ public static native void unlockSurface();
+ // surface methods
+
+ // window methods
+ public static native void updateWindow();
+ // window methods
+
+ // options menu methods
+ public static native void createOptionsMenu(Menu menu);
+ public static native boolean prepareOptionsMenu(Menu menu);
+ public static native boolean optionsItemSelected(int groupId, int itemId);
+ // options menu methods
+}
diff --git a/tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java b/tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java
new file mode 100644
index 0000000000..7e7db031ec
--- /dev/null
+++ b/tests/auto/android/src/org/qtproject/qt5/android/QtSurface.java
@@ -0,0 +1,163 @@
+/*
+ Copyright (c) 2012, BogDan Vatra <bogdan@kde.org>
+ Contact: http://www.qt-project.org/legal
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.qtproject.qt5.android;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
+{
+ private Bitmap m_bitmap=null;
+ private boolean m_started = false;
+ private boolean m_usesGL = false;
+ public QtSurface(Context context, int id)
+ {
+ super(context);
+ setFocusable(true);
+ getHolder().addCallback(this);
+ getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
+ setId(id);
+ }
+
+ public void applicationStarted(boolean usesGL)
+ {
+ m_started = true;
+ m_usesGL = usesGL;
+ if (getWidth() < 1 || getHeight() < 1)
+ return;
+ if (m_usesGL) {
+ QtNative.setSurface(getHolder().getSurface());
+ } else {
+ QtNative.lockSurface();
+ QtNative.setSurface(null);
+ m_bitmap=Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.RGB_565);
+ QtNative.setSurface(m_bitmap);
+ QtNative.unlockSurface();
+ }
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder)
+ {
+ DisplayMetrics metrics = new DisplayMetrics();
+ ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ QtNative.setApplicationDisplayMetrics(metrics.widthPixels,
+ metrics.heightPixels, getWidth(), getHeight(), metrics.xdpi, metrics.ydpi);
+
+ if (m_usesGL)
+ holder.setFormat(PixelFormat.RGBA_8888);
+ else
+ holder.setFormat(PixelFormat.RGB_565);
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
+ {
+ Log.i(QtNative.QtTAG,"surfaceChanged: "+width+","+height);
+ if (width < 1 || height < 1)
+ return;
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ QtNative.setApplicationDisplayMetrics(metrics.widthPixels,
+ metrics.heightPixels, width, height, metrics.xdpi, metrics.ydpi);
+
+ if (!m_started)
+ return;
+
+ if (m_usesGL) {
+ QtNative.setSurface(holder.getSurface());
+ } else {
+ QtNative.lockSurface();
+ QtNative.setSurface(null);
+ m_bitmap=Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
+ QtNative.setSurface(m_bitmap);
+ QtNative.unlockSurface();
+ QtNative.updateWindow();
+ }
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder)
+ {
+ Log.i(QtNative.QtTAG,"surfaceDestroyed ");
+ if (m_usesGL) {
+ QtNative.destroySurface();
+ } else {
+ if (!m_started)
+ return;
+
+ QtNative.lockSurface();
+ QtNative.setSurface(null);
+ QtNative.unlockSurface();
+ }
+ }
+
+ public void drawBitmap(Rect rect)
+ {
+ if (!m_started)
+ return;
+ QtNative.lockSurface();
+ if (null != m_bitmap) {
+ try {
+ Canvas cv=getHolder().lockCanvas(rect);
+ cv.drawBitmap(m_bitmap, rect, rect, null);
+ getHolder().unlockCanvasAndPost(cv);
+ } catch (Exception e) {
+ Log.e(QtNative.QtTAG, "Can't create main activity", e);
+ }
+ }
+ QtNative.unlockSurface();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event)
+ {
+ if (!m_started)
+ return false;
+ QtNative.sendTouchEvent(event, getId());
+ return true;
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event)
+ {
+ if (!m_started)
+ return false;
+ QtNative.sendTrackballEvent(event, getId());
+ return true;
+ }
+}