summaryrefslogtreecommitdiffstats
path: root/src/android/jar/src
diff options
context:
space:
mode:
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());
+ }
}
}