summaryrefslogtreecommitdiffstats
path: root/src/android/jar/src
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-26 22:30:27 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-26 22:35:48 +0100
commit4a8273a6fc2e741e811cf5dabc9a3c240306cf7f (patch)
tree2148abc88f8543eecdc0b97b2dd92594836af9b2 /src/android/jar/src
parent036c5db468164297d213764c59a4b59daa76d90a (diff)
parent1c2be58fecaff1de5f2849192eb712984ebd59bd (diff)
Merge remote-tracking branch 'origin/stable' into dev
For the conflicts in msvc_nmake.cpp the ifdefs are extended since we need to support windows phone in the target branch while it is not there in the current stable branch (as of Qt 5.2). Conflicts: configure qmake/generators/win32/msvc_nmake.cpp src/3rdparty/angle/src/libEGL/Surface.cpp src/angle/src/common/common.pri src/corelib/global/qglobal.h src/corelib/io/qstandardpaths.cpp src/plugins/platforms/qnx/qqnxintegration.cpp src/plugins/platforms/qnx/qqnxscreeneventhandler.h src/plugins/platforms/xcb/qglxintegration.h src/widgets/kernel/win.pri tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp tools/configure/configureapp.cpp Change-Id: I00b579eefebaf61d26ab9b00046d2b5bd5958812
Diffstat (limited to 'src/android/jar/src')
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java152
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtEditText.java23
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java83
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java425
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java35
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtSurface.java32
6 files changed, 657 insertions, 93 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index 11af4d4280..3dcffeb07d 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -42,13 +42,6 @@
package org.qtproject.qt5.android;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -57,6 +50,8 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
import android.text.method.MetaKeyKeyListener;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -66,11 +61,19 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.Surface;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
-import android.view.Surface;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
public class QtActivityDelegate
{
@@ -109,8 +112,9 @@ public class QtActivityDelegate
private boolean m_quitApp = true;
private Process m_debuggerProcess = null; // debugger process
- public boolean m_keyboardIsVisible = false;
- public boolean m_keyboardIsHiding = false;
+ private boolean m_keyboardIsVisible = false;
+ public boolean m_backKeyPressedSent = false;
+
public QtLayout getQtLayout()
{
@@ -173,6 +177,13 @@ public class QtActivityDelegate
private final int ApplicationInactive = 0x2;
private final int ApplicationActive = 0x4;
+ public void setKeyboardVisibility(boolean visibility)
+ {
+ if (m_keyboardIsVisible == visibility)
+ return;
+ m_keyboardIsVisible = visibility;
+ QtNative.keyboardVisibilityChanged(m_keyboardIsVisible);
+ }
public void resetSoftwareKeyboard()
{
if (m_imm == null)
@@ -181,6 +192,7 @@ public class QtActivityDelegate
@Override
public void run() {
m_imm.restartInput(m_editText);
+ m_editText.m_optionsChanged = false;
}
}, 5);
}
@@ -253,15 +265,25 @@ public class QtActivityDelegate
m_editText.postDelayed(new Runnable() {
@Override
public void run() {
- m_imm.showSoftInput(m_editText, 0);
- m_keyboardIsVisible = true;
- m_keyboardIsHiding = false;
- m_editText.postDelayed(new Runnable() {
+ m_imm.showSoftInput(m_editText, 0, new ResultReceiver(new Handler()) {
@Override
- public void run() {
- m_imm.restartInput(m_editText);
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case InputMethodManager.RESULT_SHOWN:
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ setKeyboardVisibility(true);
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ setKeyboardVisibility(false);
+ break;
+ }
}
- }, 25);
+ });
+ if (m_editText.m_optionsChanged) {
+ m_imm.restartInput(m_editText);
+ m_editText.m_optionsChanged = false;
+ }
}
}, 15);
}
@@ -270,9 +292,21 @@ public class QtActivityDelegate
{
if (m_imm == null)
return;
- m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0);
- m_keyboardIsVisible = false;
- m_keyboardIsHiding = false;
+ m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0, new ResultReceiver( new Handler()){
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ switch (resultCode) {
+ case InputMethodManager.RESULT_SHOWN:
+ case InputMethodManager.RESULT_UNCHANGED_SHOWN:
+ setKeyboardVisibility(true);
+ break;
+ case InputMethodManager.RESULT_HIDDEN:
+ case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
+ setKeyboardVisibility(false);
+ break;
+ }
+ }
+ });
}
public boolean isSoftwareKeyboardVisible()
@@ -362,7 +396,7 @@ public class QtActivityDelegate
+ "\tNECESSITAS_API_LEVEL=" + necessitasApiLevel
+ "\tHOME=" + m_activity.getFilesDir().getAbsolutePath()
+ "\tTMPDIR=" + m_activity.getFilesDir().getAbsolutePath();
- if (android.os.Build.VERSION.SDK_INT < 14)
+ if (Build.VERSION.SDK_INT < 14)
additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Droid Sans;Droid Sans Fallback";
else
additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Roboto;Droid Sans;Droid Sans Fallback";
@@ -378,6 +412,7 @@ public class QtActivityDelegate
m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY);
else
m_applicationParameters = "";
+ setActionBarVisibility(false);
return true;
}
@@ -585,9 +620,9 @@ public class QtActivityDelegate
}
m_layout = new QtLayout(m_activity);
m_surface = new QtSurface(m_activity, 0);
- m_editText = new QtEditText(m_activity);
+ m_editText = new QtEditText(m_activity, this);
m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
- m_layout.addView(m_surface,0);
+ m_layout.addView(m_surface, 0);
m_activity.setContentView(m_layout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT));
@@ -717,8 +752,12 @@ public class QtActivityDelegate
}
m_lastChar = lc;
- if (keyCode != KeyEvent.KEYCODE_BACK)
- QtNative.keyDown(keyCode, c, event.getMetaState());
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ m_backKeyPressedSent = !m_keyboardIsVisible;
+ if (!m_backKeyPressedSent)
+ return true;
+ }
+ QtNative.keyDown(keyCode, c, event.getMetaState());
return true;
}
@@ -737,8 +776,9 @@ public class QtActivityDelegate
}
}
- if (keyCode == KeyEvent.KEYCODE_BACK && m_keyboardIsVisible && !m_keyboardIsHiding) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && !m_backKeyPressedSent) {
hideSoftwareKeyboard();
+ setKeyboardVisibility(false);
return true;
}
@@ -775,7 +815,10 @@ public class QtActivityDelegate
public boolean onPrepareOptionsMenu(Menu menu)
{
m_opionsMenuIsVisible = true;
- return QtNative.onPrepareOptionsMenu(menu);
+ boolean res = QtNative.onPrepareOptionsMenu(menu);
+ if (!res || menu.size() == 0)
+ setActionBarVisibility(false);
+ return res;
}
public boolean onOptionsItemSelected(MenuItem item)
@@ -791,8 +834,17 @@ public class QtActivityDelegate
public void resetOptionsMenu()
{
- if (m_opionsMenuIsVisible)
- m_activity.closeOptionsMenu();
+ setActionBarVisibility(true);
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ Activity.class.getMethod("invalidateOptionsMenu").invoke(m_activity);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ else
+ if (m_opionsMenuIsVisible)
+ m_activity.closeOptionsMenu();
}
private boolean m_contextMenuVisible = false;
public void onCreateContextMenu(ContextMenu menu,
@@ -833,4 +885,46 @@ public class QtActivityDelegate
{
m_activity.closeContextMenu();
}
+
+ private boolean hasPermanentMenuKey()
+ {
+ try {
+ return Build.VERSION.SDK_INT < 11 || (Build.VERSION.SDK_INT >= 14 &&
+ (Boolean)ViewConfiguration.class.getMethod("hasPermanentMenuKey").invoke(ViewConfiguration.get(m_activity)));
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ private Object getActionBar()
+ {
+ try {
+ return Activity.class.getMethod("getActionBar").invoke(m_activity);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private void setActionBarVisibility(boolean visible)
+ {
+ if (hasPermanentMenuKey() || !visible) {
+ if (Build.VERSION.SDK_INT > 10 && getActionBar() != null) {
+ try {
+ Class.forName("android.app.ActionBar").getMethod("hide").invoke(getActionBar());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ } else {
+ if (Build.VERSION.SDK_INT > 10 && getActionBar() != null)
+ try {
+ Class.forName("android.app.ActionBar").getMethod("show").invoke(getActionBar());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java b/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java
index b95e0c070c..593746aac9 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtEditText.java
@@ -50,33 +50,47 @@ import android.view.inputmethod.InputConnection;
public class QtEditText extends View
{
- QtInputConnection m_inputConnection;
int m_initialCapsMode = 0;
int m_imeOptions = 0;
int m_inputType = InputType.TYPE_CLASS_TEXT;
+ boolean m_optionsChanged = false;
+ QtActivityDelegate m_activityDelegate;
public void setImeOptions(int m_imeOptions)
{
+ if (m_imeOptions == this.m_imeOptions)
+ return;
this.m_imeOptions = m_imeOptions;
+ m_optionsChanged = true;
}
public void setInitialCapsMode(int m_initialCapsMode)
{
+ if (m_initialCapsMode == this.m_initialCapsMode)
+ return;
this.m_initialCapsMode = m_initialCapsMode;
+ m_optionsChanged = true;
}
public void setInputType(int m_inputType)
{
+ if (m_inputType == this.m_inputType)
+ return;
this.m_inputType = m_inputType;
+ m_optionsChanged = true;
}
- public QtEditText(Context context)
+ public QtEditText(Context context, QtActivityDelegate activityDelegate)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
- m_inputConnection = new QtInputConnection(this);
+ m_activityDelegate = activityDelegate;
+ }
+ public QtActivityDelegate getActivityDelegate()
+ {
+ return m_activityDelegate;
}
@Override
@@ -86,8 +100,9 @@ public class QtEditText extends View
outAttrs.imeOptions = m_imeOptions;
outAttrs.initialCapsMode = m_initialCapsMode;
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI;
- return m_inputConnection;
+ return new QtInputConnection(this);
}
+
// // DEBUG CODE
// @Override
// protected void onDraw(Canvas canvas) {
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
index f251369737..4b2d50ca1f 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
@@ -43,8 +43,6 @@
package org.qtproject.qt5.android;
import android.content.Context;
-import android.os.Build;
-import android.view.View;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedText;
@@ -82,6 +80,22 @@ class QtNativeInputConnection
static native boolean paste();
}
+class HideKeyboardRunnable implements Runnable {
+ private QtInputConnection m_connection;
+ HideKeyboardRunnable(QtInputConnection connection)
+ {
+ m_connection = connection;
+ }
+
+ @Override
+ public void run() {
+ if (m_connection.getInputState() == QtInputConnection.InputStates.Hiding) {
+ QtNative.activityDelegate().setKeyboardVisibility(false);
+ m_connection.reset();
+ }
+ }
+}
+
public class QtInputConnection extends BaseInputConnection
{
private static final int ID_SELECT_ALL = android.R.id.selectAll;
@@ -92,67 +106,83 @@ public class QtInputConnection extends BaseInputConnection
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;
- boolean m_closing;
- public QtInputConnection(View targetView)
+
+ enum InputStates { Visible, FinishComposing, Hiding };
+
+ private QtEditText m_view = null;
+ private InputStates m_inputState = InputStates.Visible;
+
+ public void reset()
+ {
+ m_inputState = InputStates.Visible;
+ }
+
+ public InputStates getInputState()
+ {
+ return m_inputState;
+ }
+
+ private void setClosing(boolean closing)
+ {
+ if (closing && m_inputState == InputStates.Hiding)
+ return;
+
+ if (closing && m_inputState == InputStates.FinishComposing && m_view.getActivityDelegate().isSoftwareKeyboardVisible()) {
+ m_view.postDelayed(new HideKeyboardRunnable(this), 100);
+ m_inputState = InputStates.Hiding;
+ } else {
+ if (m_inputState == InputStates.Hiding)
+ QtNative.activityDelegate().setKeyboardVisibility(true);
+ m_inputState = closing ? InputStates.FinishComposing : InputStates.Visible;
+ }
+ }
+
+ public QtInputConnection(QtEditText targetView)
{
super(targetView, true);
m_view = targetView;
- m_closing = false;
}
@Override
public boolean beginBatchEdit()
{
- m_closing = false;
+ setClosing(false);
return true;
}
@Override
public boolean endBatchEdit()
{
- m_closing = false;
+// setClosing(false);
return true;
}
@Override
public boolean commitCompletion(CompletionInfo text)
{
- m_closing = false;
+ setClosing(false);
return QtNativeInputConnection.commitCompletion(text.getText().toString(), text.getPosition());
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition)
{
- m_closing = false;
+ setClosing(false);
return QtNativeInputConnection.commitText(text.toString(), newCursorPosition);
}
@Override
public boolean deleteSurroundingText(int leftLength, int rightLength)
{
- m_closing = false;
+ setClosing(false);
return QtNativeInputConnection.deleteSurroundingText(leftLength, rightLength);
}
@Override
public boolean finishComposingText()
{
- if (m_closing) {
- QtNative.activityDelegate().m_keyboardIsHiding = true;
- m_view.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (QtNative.activityDelegate().m_keyboardIsHiding)
- QtNative.activityDelegate().m_keyboardIsVisible=false;
- }
- }, 5000); // it seems finishComposingText comes musch faster than onKeyUp event,
- // so we must delay hide notification
- m_closing = false;
- } else {
- m_closing = true;
- }
+ // on some/all android devices hide event is not coming, but instead finishComposingText() is called twice
+ setClosing(true);
return QtNativeInputConnection.finishComposingText();
}
@@ -234,18 +264,21 @@ public class QtInputConnection extends BaseInputConnection
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition)
{
+ setClosing(false);
return QtNativeInputConnection.setComposingText(text.toString(), newCursorPosition);
}
@Override
public boolean setComposingRegion(int start, int end)
{
+ setClosing(false);
return QtNativeInputConnection.setComposingRegion(start, end);
}
@Override
public boolean setSelection(int start, int end)
{
+ setClosing(false);
return QtNativeInputConnection.setSelection(start, end);
}
}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
new file mode 100644
index 0000000000..6ee1304c12
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
@@ -0,0 +1,425 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the Android port of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+
+package org.qtproject.qt5.android;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.text.ClipboardManager;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+
+class QtNativeDialogHelper
+{
+ static native void dialogResult(long handler, int buttonID);
+}
+
+class ButtonStruct implements View.OnClickListener
+{
+ ButtonStruct(QtMessageDialogHelper dialog, int id, String text)
+ {
+ m_dialog = dialog;
+ m_id = id;
+ m_text = text;
+ }
+ QtMessageDialogHelper m_dialog;
+ private int m_id;
+ String m_text;
+
+ @Override
+ public void onClick(View view) {
+ QtNativeDialogHelper.dialogResult(m_dialog.handler(), m_id);
+ }
+}
+
+public class QtMessageDialogHelper
+{
+
+ public QtMessageDialogHelper(Activity activity)
+ {
+ m_activity = activity;
+ }
+
+
+ public void setIcon(int icon)
+ {
+ m_icon = icon;
+
+ }
+
+ private Drawable getIconDrawable()
+ {
+ if (m_icon == 0)
+ return null;
+
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ TypedValue typedValue = new TypedValue();
+ m_theme.resolveAttribute(Class.forName("android.R$attr").getDeclaredField("alertDialogIcon").getInt(null), typedValue, true);
+ return m_activity.getResources().getDrawable(typedValue.resourceId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // Information, Warning, Critical, Question
+ switch (m_icon)
+ {
+ case 1: // Information
+ try {
+ return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_info").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ case 2: // Warning
+// try {
+// return Class.forName("android.R$drawable").getDeclaredField("stat_sys_warning").getInt(null);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// break;
+ case 3: // Critical
+ try {
+ return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_alert").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ case 4: // Question
+ try {
+ return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_menu_help").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ }
+ return null;
+ }
+
+ public void setTile(String title)
+ {
+ m_title = title;
+ }
+
+ public void setText(String text)
+ {
+ m_text = text;
+ }
+
+ public void setInformativeText(String informativeText)
+ {
+ m_informativeText = informativeText;
+ }
+
+ public void setDetailedText(String text)
+ {
+ m_detailedText = text;
+ }
+
+ public void addButton(int id, String text)
+ {
+ if (m_buttonsList == null)
+ m_buttonsList = new ArrayList<ButtonStruct>();
+ m_buttonsList.add(new ButtonStruct(this, id, text));
+ }
+
+ private void setTextAppearance(TextView view, String attr, String style)
+ {
+ try {
+ int[] attrs = (int[]) Class.forName("android.R$styleable").getDeclaredField("TextAppearance").get(null);
+ final TypedArray a = m_theme.obtainStyledAttributes(null,
+ attrs,
+ Class.forName("android.R$attr").getDeclaredField(attr).getInt(null),
+ Class.forName("android.R$style").getDeclaredField(style).getInt(null));
+ final int textSize = a.getDimensionPixelSize(
+ Class.forName("android.R$styleable").getDeclaredField("TextAppearance_textSize").getInt(null), 0);
+ if (textSize != 0)
+ view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+
+ final int textColor = a.getColor(
+ Class.forName("android.R$styleable").getDeclaredField("TextAppearance_textColor").getInt(null), 0x3138);
+ if (textColor != 0x3138)
+ view.setTextColor(textColor);
+
+ a.recycle();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private Drawable getStyledDrawable(String drawable) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException
+ {
+ int[] attrs = {Class.forName("android.R$attr").getDeclaredField(drawable).getInt(null)};
+ final TypedArray a = m_theme.obtainStyledAttributes(attrs);
+ Drawable d = a.getDrawable(0);
+ a.recycle();
+ return d;
+ }
+
+
+ public void show(long handler)
+ {
+ m_handler = handler;
+ m_activity.runOnUiThread( new Runnable() {
+ @Override
+ public void run() {
+ if (m_dialog != null && m_dialog.isShowing())
+ m_dialog.dismiss();
+
+ m_dialog = new AlertDialog.Builder(m_activity).create();
+ m_theme = m_dialog.getWindow().getContext().getTheme();
+
+ if (m_title != null)
+ m_dialog.setTitle(m_title);
+ m_dialog.setOnCancelListener( new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialogInterface) {
+ QtNativeDialogHelper.dialogResult(handler(), -1);
+ }
+ });
+ m_dialog.setCancelable(m_buttonsList == null);
+ m_dialog.setCanceledOnTouchOutside(m_buttonsList == null);
+ m_dialog.setIcon(getIconDrawable());
+ ScrollView scrollView = new ScrollView(m_activity);
+ RelativeLayout dialogLayout = new RelativeLayout(m_activity);
+ int id = 1;
+ View lastView = null;
+ View.OnLongClickListener copyText = new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ TextView tv = (TextView)view;
+ if (tv != null) {
+ ClipboardManager cm = (android.text.ClipboardManager) m_activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setText(tv.getText());
+ }
+ return true;
+ }
+ };
+ if (m_text != null)
+ {
+ TextView view = new TextView(m_activity);
+ view.setId(id++);
+ view.setOnLongClickListener(copyText);
+ view.setLongClickable(true);
+
+ view.setText(m_text);
+ setTextAppearance(view, "textAppearanceMedium", "TextAppearance_Medium");
+
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(16, 8, 16, 8);
+ layout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(view, layout);
+ lastView = view;
+ }
+
+ if (m_informativeText != null)
+ {
+ TextView view= new TextView(m_activity);
+ view.setId(id++);
+ view.setOnLongClickListener(copyText);
+ view.setLongClickable(true);
+
+ view.setText(m_informativeText);
+ setTextAppearance(view, "textAppearanceMedium", "TextAppearance_Medium");
+
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(16, 8, 16, 8);
+ if (lastView != null)
+ layout.addRule(RelativeLayout.BELOW, lastView.getId());
+ else
+ layout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(view, layout);
+ lastView = view;
+ }
+
+ if (m_detailedText != null)
+ {
+ TextView view= new TextView(m_activity);
+ view.setId(id++);
+ view.setOnLongClickListener(copyText);
+ view.setLongClickable(true);
+
+ view.setText(m_detailedText);
+ setTextAppearance(view, "textAppearanceSmall", "TextAppearance_Small");
+
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(16, 8, 16, 8);
+ if (lastView != null)
+ layout.addRule(RelativeLayout.BELOW, lastView.getId());
+ else
+ layout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(view, layout);
+ lastView = view;
+ }
+
+ if (m_buttonsList != null)
+ {
+ LinearLayout buttonsLayout = new LinearLayout(m_activity);
+ buttonsLayout.setOrientation(LinearLayout.HORIZONTAL);
+ buttonsLayout.setId(id++);
+ boolean firstButton = true;
+ for (ButtonStruct button: m_buttonsList)
+ {
+ Button bv;
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ bv = new Button(m_activity, null, Class.forName("android.R$attr").getDeclaredField("borderlessButtonStyle").getInt(null));
+ } catch (Exception e) {
+ bv = new Button(m_activity);
+ e.printStackTrace();
+ }
+ } else {
+ bv = new Button(m_activity);
+ }
+
+ bv.setText(button.m_text);
+ bv.setOnClickListener(button);
+ if (!firstButton) // first button
+ {
+ LinearLayout.LayoutParams layout = null;
+ View spacer = new View(m_activity);
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ layout = new LinearLayout.LayoutParams(1, RelativeLayout.LayoutParams.MATCH_PARENT);
+ spacer.setBackgroundDrawable(getStyledDrawable("dividerVertical"));
+ buttonsLayout.addView(spacer, layout);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ LinearLayout.LayoutParams layout = null;
+ layout = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT, 1.0f);
+ buttonsLayout.addView(bv, layout);
+ firstButton = false;
+ }
+
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ View horizontalDevider = new View(m_activity);
+ horizontalDevider.setId(id++);
+ horizontalDevider.setBackgroundDrawable(getStyledDrawable("dividerHorizontal"));
+ RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 1);
+ relativeParams.setMargins(0, 10, 0, 0);
+ if (lastView != null) {
+ relativeParams.addRule(RelativeLayout.BELOW, lastView.getId());
+ }
+ else
+ relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(horizontalDevider, relativeParams);
+ lastView = horizontalDevider;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ if (lastView != null) {
+ relativeParams.addRule(RelativeLayout.BELOW, lastView.getId());
+ }
+ else
+ relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ if (Build.VERSION.SDK_INT < 11)
+ relativeParams.setMargins(2, 12, 2, 4);
+ else
+ relativeParams.setMargins(2, 0, 2, 0);
+ dialogLayout.addView(buttonsLayout, relativeParams);
+ }
+ scrollView.addView(dialogLayout);
+ m_dialog.setView(scrollView);
+ m_dialog.show();
+ }
+ });
+ }
+
+ public void hide()
+ {
+ m_activity.runOnUiThread( new Runnable() {
+ @Override
+ public void run() {
+ if (m_dialog != null && m_dialog.isShowing())
+ m_dialog.dismiss();
+ reset();
+ }
+ });
+ }
+
+ public long handler()
+ {
+ return m_handler;
+ }
+
+ public void reset()
+ {
+ m_icon = 0;
+ m_title = null;
+ m_text = null;
+ m_informativeText = null;
+ m_detailedText = null;
+ m_buttonsList = null;
+ m_dialog = null;
+ m_handler = 0;
+ }
+
+ private Activity m_activity;
+ private int m_icon = 0;
+ private String m_title, m_text, m_informativeText, m_detailedText;
+ private ArrayList<ButtonStruct> m_buttonsList;
+ private AlertDialog m_dialog;
+ private long m_handler = 0;
+ private Resources.Theme m_theme;
+}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 1385c90e3e..57f3642b56 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -50,7 +50,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.os.Build;
import android.text.ClipboardManager;
import android.util.Log;
import android.view.ContextMenu;
@@ -110,9 +109,13 @@ public class QtNative
public static void openURL(String url)
{
- Uri uri = Uri.parse(url);
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- activity().startActivity(intent);
+ try {
+ Uri uri = Uri.parse(url);
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ activity().startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
// this method loads full path libs
@@ -419,30 +422,21 @@ public class QtNative
private static boolean isSoftwareKeyboardVisible()
{
- Semaphore semaphore = new Semaphore(1);
- Boolean ret = false;
- class RunnableRes implements Runnable {
- @SuppressWarnings("unused")
- Boolean returnValue = null;
- Semaphore semaphore = null;
- RunnableRes(Boolean ret, Semaphore sem) {
- semaphore = sem;
- returnValue = ret;
- }
+ final Semaphore semaphore = new Semaphore(0);
+ final Boolean[] ret = {false};
+ runAction(new Runnable() {
@Override
public void run() {
- returnValue = m_activityDelegate.isSoftwareKeyboardVisible();
+ ret[0] = m_activityDelegate.isSoftwareKeyboardVisible();
semaphore.release();
}
- }
-
- runAction(new RunnableRes(ret, semaphore));
+ });
try {
semaphore.acquire();
} catch (Exception e) {
e.printStackTrace();
}
- return ret;
+ return ret[0];
}
private static void setFullScreen(final boolean fullScreen)
@@ -458,7 +452,7 @@ public class QtNative
private static void registerClipboardManager()
{
- final Semaphore semaphore = new Semaphore(1);
+ final Semaphore semaphore = new Semaphore(0);
runAction(new Runnable() {
@Override
public void run() {
@@ -569,6 +563,7 @@ public class QtNative
// keyboard methods
public static native void keyDown(int key, int unicode, int modifier);
public static native void keyUp(int key, int unicode, int modifier);
+ public static native void keyboardVisibilityChanged(boolean visibility);
// keyboard methods
// surface methods
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java
index cd0bddf2c8..c499dc3898 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtSurface.java
@@ -117,21 +117,23 @@ public class QtSurface extends SurfaceView implements SurfaceHolder.Callback
// Initialize Accessibility
// The accessibility code depends on android API level 16, so dynamically resolve it
- try {
- final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate";
- Class<?> qtDelegateClass = Class.forName(a11yDelegateClassName);
- Constructor constructor = qtDelegateClass.getConstructor(Class.forName("android.view.View"));
- m_accessibilityDelegate = constructor.newInstance(this);
-
- Class a11yDelegateClass = Class.forName("android.view.View$AccessibilityDelegate");
- Method setDelegateMethod = this.getClass().getMethod("setAccessibilityDelegate", a11yDelegateClass);
- setDelegateMethod.invoke(this, m_accessibilityDelegate);
- } catch (ClassNotFoundException e) {
- // Class not found is fine since we are compatible with Android API < 16, but the function will
- // only be available with that API level.
- } catch (Exception e) {
- // Unknown exception means something went wrong.
- Log.w("Qt A11y", "Unknown exception: " + e.toString());
+ if (android.os.Build.VERSION.SDK_INT >= 16) {
+ try {
+ final String a11yDelegateClassName = "org.qtproject.qt5.android.accessibility.QtAccessibilityDelegate";
+ Class<?> qtDelegateClass = Class.forName(a11yDelegateClassName);
+ Constructor constructor = qtDelegateClass.getConstructor(Class.forName("android.view.View"));
+ m_accessibilityDelegate = constructor.newInstance(this);
+
+ Class a11yDelegateClass = Class.forName("android.view.View$AccessibilityDelegate");
+ Method setDelegateMethod = this.getClass().getMethod("setAccessibilityDelegate", a11yDelegateClass);
+ setDelegateMethod.invoke(this, m_accessibilityDelegate);
+ } catch (ClassNotFoundException e) {
+ // Class not found is fine since we are compatible with Android API < 16, but the function will
+ // only be available with that API level.
+ } catch (Exception e) {
+ // Unknown exception means something went wrong.
+ Log.w("Qt A11y", "Unknown exception: " + e.toString());
+ }
}
}