Android: support lambda expressions in Java code

use -classpath instead of -bootclasspath param to allow
javac to use the default boot class path to support
building lambdas, pass the user Android class via -classpath.

Task-number: QTBUG-118077
Change-Id: I1ba8274d57e1bd528a1d5b7d779191e7f1412184
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
This commit is contained in:
Assam Boudjelthia 2023-11-16 20:18:49 +02:00
parent 323cf718f6
commit 64fe6d836c
10 changed files with 466 additions and 629 deletions

View File

@ -19,7 +19,8 @@ function(qt_internal_add_jar target)
set(javac_source_version "8")
endif()
set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}" -Xlint:unchecked -bootclasspath "${QT_ANDROID_JAR}")
set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}"
-Xlint:unchecked -classpath "${QT_ANDROID_JAR}")
add_jar(${ARGV})
foreach(f IN LISTS arg_SOURCES)

View File

@ -63,12 +63,7 @@ public class QtActivityDelegate
setActionBarVisibility(false);
QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener =
new QtInputDelegate.KeyboardVisibilityListener() {
@Override
public void onKeyboardVisibilityChange() {
m_displayManager.updateFullScreen(m_activity);
}
};
() -> m_displayManager.updateFullScreen(m_activity);
m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener);
try {
@ -98,13 +93,10 @@ public class QtActivityDelegate
@UsedFromNativeCode
public void setSystemUiVisibility(int systemUiVisibility)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_displayManager.setSystemUiVisibility(m_activity, systemUiVisibility);
m_layout.requestLayout();
QtNative.updateWindow();
}
QtNative.runAction(() -> {
m_displayManager.setSystemUiVisibility(m_activity, systemUiVisibility);
m_layout.requestLayout();
QtNative.updateWindow();
});
}
@ -160,16 +152,13 @@ public class QtActivityDelegate
if (m_surfaces != null)
return;
Runnable startApplication = new Runnable() {
@Override
public void run() {
try {
QtNative.startApplication(appParams, mainLib);
m_started = true;
} catch (Exception e) {
e.printStackTrace();
m_activity.finish();
}
Runnable startApplication = () -> {
try {
QtNative.startApplication(appParams, mainLib);
m_started = true;
} catch (Exception e) {
e.printStackTrace();
m_activity.finish();
}
};
@ -224,27 +213,24 @@ public class QtActivityDelegate
: m_activity.getDisplay().getRefreshRate();
QtDisplayManager.handleRefreshRateChanged(refreshRate);
m_layout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (!m_inputDelegate.isKeyboardVisible())
return true;
m_layout.getViewTreeObserver().addOnPreDrawListener(() -> {
if (!m_inputDelegate.isKeyboardVisible())
return true;
Rect r = new Rect();
m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
DisplayMetrics metrics = new DisplayMetrics();
m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
final int kbHeight = metrics.heightPixels - r.bottom;
if (kbHeight < 0) {
m_inputDelegate.setKeyboardVisibility(false, System.nanoTime());
return true;
}
final int[] location = new int[2];
m_layout.getLocationOnScreen(location);
QtInputDelegate.keyboardGeometryChanged(location[0], r.bottom - location[1],
r.width(), kbHeight);
Rect r = new Rect();
m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
DisplayMetrics metrics = new DisplayMetrics();
m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
final int kbHeight = metrics.heightPixels - r.bottom;
if (kbHeight < 0) {
m_inputDelegate.setKeyboardVisibility(false, System.nanoTime());
return true;
}
final int[] location = new int[2];
m_layout.getLocationOnScreen(location);
QtInputDelegate.keyboardGeometryChanged(location[0], r.bottom - location[1],
r.width(), kbHeight);
return true;
});
m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_layout));
}
@ -256,39 +242,36 @@ public class QtActivityDelegate
public void hideSplashScreen(final int duration)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_splashScreen == null)
return;
QtNative.runAction(() -> {
if (m_splashScreen == null)
return;
if (duration <= 0) {
m_layout.removeView(m_splashScreen);
m_splashScreen = null;
return;
if (duration <= 0) {
m_layout.removeView(m_splashScreen);
m_splashScreen = null;
return;
}
final Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(duration);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
hideSplashScreen(0);
}
final Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(duration);
@Override
public void onAnimationRepeat(Animation animation) {
}
fadeOut.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
hideSplashScreen(0);
}
@Override
public void onAnimationStart(Animation animation) {
}
});
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
});
m_splashScreen.startAnimation(fadeOut);
}
m_splashScreen.startAnimation(fadeOut);
});
}
@ -342,13 +325,8 @@ public class QtActivityDelegate
public void initializeAccessibility()
{
final QtActivityDelegate currentDelegate = this;
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity, m_layout,
currentDelegate);
}
});
QtNative.runAction(() -> m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity,
m_layout, currentDelegate));
}
void handleUiModeChange(int uiMode)
@ -381,23 +359,13 @@ public class QtActivityDelegate
@UsedFromNativeCode
public void resetOptionsMenu()
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_activity.invalidateOptionsMenu();
}
});
QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
}
@UsedFromNativeCode
public void openOptionsMenu()
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_activity.openOptionsMenu();
}
});
QtNative.runAction(() -> m_activity.openOptionsMenu());
}
private boolean m_contextMenuVisible = false;
@ -411,38 +379,22 @@ public class QtActivityDelegate
@UsedFromNativeCode
public void openContextMenu(final int x, final int y, final int w, final int h)
{
m_layout.postDelayed(new Runnable() {
@Override
public void run() {
m_layout.setLayoutParams(m_inputDelegate.getQtEditText(), new QtLayout.LayoutParams(w, h, x, y), false);
PopupMenu popup = new PopupMenu(m_activity, m_inputDelegate.getQtEditText());
QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
return m_activity.onContextItemSelected(menuItem);
}
});
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override
public void onDismiss(PopupMenu popupMenu) {
m_activity.onContextMenuClosed(popupMenu.getMenu());
}
});
popup.show();
}
m_layout.postDelayed(() -> {
m_layout.setLayoutParams(m_inputDelegate.getQtEditText(), new QtLayout.LayoutParams(w, h, x, y), false);
PopupMenu popup = new PopupMenu(m_activity, m_inputDelegate.getQtEditText());
QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu());
popup.setOnMenuItemClickListener(menuItem ->
m_activity.onContextItemSelected(menuItem));
popup.setOnDismissListener(popupMenu ->
m_activity.onContextMenuClosed(popupMenu.getMenu()));
popup.show();
}, 100);
}
@UsedFromNativeCode
public void closeContextMenu()
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_activity.closeContextMenu();
}
});
QtNative.runAction(() -> m_activity.closeContextMenu());
}
void setActionBarVisibility(boolean visible)
@ -457,117 +409,104 @@ public class QtActivityDelegate
@UsedFromNativeCode
public void insertNativeView(int id, View view, int x, int y, int w, int h) {
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
}
QtNative.runAction(() -> {
if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
}
if (m_nativeViews.containsKey(id))
m_layout.removeView(m_nativeViews.remove(id));
if (m_nativeViews.containsKey(id))
m_layout.removeView(m_nativeViews.remove(id));
if (w < 0 || h < 0) {
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
} else {
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
}
if (w < 0 || h < 0) {
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
} else {
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
}
view.setId(id);
m_layout.addView(view);
m_nativeViews.put(id, view);
}
});
view.setId(id);
m_layout.addView(view);
m_nativeViews.put(id, view);
});
}
@UsedFromNativeCode
public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) {
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_surfaces.size() == 0) {
TypedValue attr = new TypedValue();
m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true);
if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) {
m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data));
} else {
m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme()));
}
if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
}
}
if (m_surfaces.containsKey(id))
m_layout.removeView(m_surfaces.remove(id));
QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth);
if (w < 0 || h < 0) {
surface.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
QtNative.runAction(() -> {
if (m_surfaces.size() == 0) {
TypedValue attr = new TypedValue();
m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true);
if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) {
m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data));
} else {
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme()));
}
if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
}
// Native views are always inserted in the end of the stack (i.e., on top).
// All other views are stacked based on the order they are created.
final int surfaceCount = getSurfaceCount();
m_layout.addView(surface, surfaceCount);
m_surfaces.put(id, surface);
if (!m_splashScreenSticky)
hideSplashScreen();
}
if (m_surfaces.containsKey(id))
m_layout.removeView(m_surfaces.remove(id));
QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth);
if (w < 0 || h < 0) {
surface.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
} else {
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
}
// Native views are always inserted in the end of the stack (i.e., on top).
// All other views are stacked based on the order they are created.
final int surfaceCount = getSurfaceCount();
m_layout.addView(surface, surfaceCount);
m_surfaces.put(id, surface);
if (!m_splashScreenSticky)
hideSplashScreen();
});
}
@UsedFromNativeCode
public void setSurfaceGeometry(int id, int x, int y, int w, int h) {
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_surfaces.containsKey(id)) {
QtSurface surface = m_surfaces.get(id);
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} else if (m_nativeViews.containsKey(id)) {
View view = m_nativeViews.get(id);
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} else {
Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
return;
}
QtNative.runAction(() -> {
if (m_surfaces.containsKey(id)) {
QtSurface surface = m_surfaces.get(id);
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} else if (m_nativeViews.containsKey(id)) {
View view = m_nativeViews.get(id);
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} else {
Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
}
});
}
@UsedFromNativeCode
public void destroySurface(int id) {
QtNative.runAction(new Runnable() {
@Override
public void run() {
View view = null;
QtNative.runAction(() -> {
View view = null;
if (m_surfaces.containsKey(id)) {
view = m_surfaces.remove(id);
} else if (m_nativeViews.containsKey(id)) {
view = m_nativeViews.remove(id);
} else {
Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
}
if (m_surfaces.containsKey(id)) {
view = m_surfaces.remove(id);
} else if (m_nativeViews.containsKey(id)) {
view = m_nativeViews.remove(id);
} else {
Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
}
if (view == null)
return;
if (view == null)
return;
// Keep last frame in stack until it is replaced to get correct
// shutdown transition
if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) {
m_dummyView = view;
} else {
m_layout.removeView(view);
}
// Keep last frame in stack until it is replaced to get correct
// shutdown transition
if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) {
m_dummyView = view;
} else {
m_layout.removeView(view);
}
});
}
@ -580,41 +519,35 @@ public class QtActivityDelegate
@UsedFromNativeCode
public void bringChildToFront(int id)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
View view = m_surfaces.get(id);
if (view != null) {
final int surfaceCount = getSurfaceCount();
if (surfaceCount > 0)
m_layout.moveChild(view, surfaceCount - 1);
return;
}
view = m_nativeViews.get(id);
if (view != null)
m_layout.moveChild(view, -1);
QtNative.runAction(() -> {
View view = m_surfaces.get(id);
if (view != null) {
final int surfaceCount = getSurfaceCount();
if (surfaceCount > 0)
m_layout.moveChild(view, surfaceCount - 1);
return;
}
view = m_nativeViews.get(id);
if (view != null)
m_layout.moveChild(view, -1);
});
}
@UsedFromNativeCode
public void bringChildToBack(int id)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
View view = m_surfaces.get(id);
if (view != null) {
m_layout.moveChild(view, 0);
return;
}
QtNative.runAction(() -> {
View view = m_surfaces.get(id);
if (view != null) {
m_layout.moveChild(view, 0);
return;
}
view = m_nativeViews.get(id);
if (view != null) {
final int index = getSurfaceCount();
m_layout.moveChild(view, index);
}
view = m_nativeViews.get(id);
if (view != null) {
final int index = getSurfaceCount();
m_layout.moveChild(view, index);
}
});
}

View File

@ -52,12 +52,7 @@ public class QtActivityLoader extends QtLoader {
"fatal_error_msg", "string", packageName);
errorDialog.setMessage(resources.getString(id));
errorDialog.setButton(Dialog.BUTTON_POSITIVE, resources.getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
(dialog, which) -> finish());
errorDialog.show();
}

View File

@ -35,21 +35,14 @@ public class QtClipboardManager
{
if (context != null) {
final Semaphore semaphore = new Semaphore(0);
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_clipboardManager =
(ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
if (m_clipboardManager != null) {
m_clipboardManager.addPrimaryClipChangedListener(
new ClipboardManager.OnPrimaryClipChangedListener() {
public void onPrimaryClipChanged() {
onClipboardDataChanged(m_nativePointer);
}
});
}
semaphore.release();
QtNative.runAction(() -> {
m_clipboardManager =
(ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
if (m_clipboardManager != null) {
m_clipboardManager.addPrimaryClipChangedListener(
() -> onClipboardDataChanged(m_nativePointer));
}
semaphore.release();
});
try {
semaphore.acquire();

View File

@ -188,12 +188,9 @@ public class QtInputDelegate {
{
if (m_imm == null)
return;
m_editText.postDelayed(new Runnable() {
@Override
public void run() {
m_imm.restartInput(m_editText);
m_editText.m_optionsChanged = false;
}
m_editText.postDelayed(() -> {
m_imm.restartInput(m_editText);
m_editText.m_optionsChanged = false;
}, 5);
}
@ -201,53 +198,47 @@ public class QtInputDelegate {
final int x, final int y, final int width, final int height,
final int inputHints, final int enterKeyType)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_imm == null)
return;
QtNative.runAction(() -> {
if (m_imm == null)
return;
if (updateSoftInputMode(activity, height))
return;
if (updateSoftInputMode(activity, height))
return;
setEditTextOptions(enterKeyType, inputHints);
setEditTextOptions(enterKeyType, inputHints);
// TODO: The editText is added to the QtLayout, but is it ever removed?
QtLayout.LayoutParams layoutParams = new QtLayout.LayoutParams(width, height, x, y);
layout.setLayoutParams(m_editText, layoutParams, false);
m_editText.requestFocus();
// TODO: The editText is added to the QtLayout, but is it ever removed?
QtLayout.LayoutParams layoutParams = new QtLayout.LayoutParams(width, height, x, y);
layout.setLayoutParams(m_editText, layoutParams, false);
m_editText.requestFocus();
m_editText.postDelayed(new Runnable() {
m_editText.postDelayed(() -> {
m_imm.showSoftInput(m_editText, 0, new ResultReceiver(new Handler()) {
@Override
public void run() {
m_imm.showSoftInput(m_editText, 0, new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case InputMethodManager.RESULT_SHOWN:
QtNativeInputConnection.updateCursorPosition();
//FALLTHROUGH
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
setKeyboardVisibility(true, System.nanoTime());
if (m_softInputMode == 0) {
probeForKeyboardHeight(layout, activity,
x, y, width, height, inputHints, enterKeyType);
}
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case InputMethodManager.RESULT_SHOWN:
QtNativeInputConnection.updateCursorPosition();
//FALLTHROUGH
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
setKeyboardVisibility(true, System.nanoTime());
if (m_softInputMode == 0) {
probeForKeyboardHeight(layout, activity,
x, y, width, height, inputHints, enterKeyType);
}
}
});
if (m_editText.m_optionsChanged) {
m_imm.restartInput(m_editText);
m_editText.m_optionsChanged = false;
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
}
}
}, 15);
}
});
if (m_editText.m_optionsChanged) {
m_imm.restartInput(m_editText);
m_editText.m_optionsChanged = false;
}
}, 15);
});
}
@ -392,35 +383,32 @@ public class QtInputDelegate {
private void probeForKeyboardHeight(QtLayout layout, Activity activity, int x, int y,
int width, int height, int inputHints, int enterKeyType)
{
layout.postDelayed(new Runnable() {
@Override
public void run() {
if (!m_keyboardIsVisible)
return;
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
if (metrics.heightPixels != r.bottom) {
if (metrics.widthPixels > metrics.heightPixels) { // landscape
if (m_landscapeKeyboardHeight != r.bottom) {
m_landscapeKeyboardHeight = r.bottom;
showSoftwareKeyboard(activity, layout, x, y, width, height,
inputHints, enterKeyType);
}
} else {
if (m_portraitKeyboardHeight != r.bottom) {
m_portraitKeyboardHeight = r.bottom;
showSoftwareKeyboard(activity, layout, x, y, width, height,
inputHints, enterKeyType);
}
layout.postDelayed(() -> {
if (!m_keyboardIsVisible)
return;
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
if (metrics.heightPixels != r.bottom) {
if (metrics.widthPixels > metrics.heightPixels) { // landscape
if (m_landscapeKeyboardHeight != r.bottom) {
m_landscapeKeyboardHeight = r.bottom;
showSoftwareKeyboard(activity, layout, x, y, width, height,
inputHints, enterKeyType);
}
} else {
// no luck ?
// maybe the delay was too short, so let's make it longer
if (m_probeKeyboardHeightDelayMs < 1000)
m_probeKeyboardHeightDelayMs *= 2;
if (m_portraitKeyboardHeight != r.bottom) {
m_portraitKeyboardHeight = r.bottom;
showSoftwareKeyboard(activity, layout, x, y, width, height,
inputHints, enterKeyType);
}
}
} else {
// no luck ?
// maybe the delay was too short, so let's make it longer
if (m_probeKeyboardHeightDelayMs < 1000)
m_probeKeyboardHeightDelayMs *= 2;
}
}, m_probeKeyboardHeightDelayMs);
}
@ -428,29 +416,26 @@ public class QtInputDelegate {
public void hideSoftwareKeyboard()
{
m_isKeyboardHidingAnimationOngoing = true;
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_imm == null)
return;
QtNative.runAction(() -> {
if (m_imm == null)
return;
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, System.nanoTime());
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
}
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, System.nanoTime());
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
}
});
}
}
});
});
}
@ -458,14 +443,11 @@ public class QtInputDelegate {
public void updateSelection(final int selStart, final int selEnd,
final int candidatesStart, final int candidatesEnd)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_imm == null)
return;
QtNative.runAction(() -> {
if (m_imm == null)
return;
m_imm.updateSelection(m_editText, selStart, selEnd, candidatesStart, candidatesEnd);
}
m_imm.updateSelection(m_editText, selStart, selEnd, candidatesStart, candidatesEnd);
});
}
@ -490,13 +472,8 @@ public class QtInputDelegate {
int editX, int editY, int editButtons,
int x1, int y1, int x2, int y2, boolean rtl)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
updateHandleImpl(activity, layout, mode, editX, editY, editButtons,
x1, y1, x2, y2, rtl);
}
});
QtNative.runAction(() -> updateHandleImpl(activity, layout, mode, editX, editY, editButtons,
x1, y1, x2, y2, rtl));
}
private void updateHandleImpl(Activity activity, QtLayout layout, int mode,

View File

@ -462,13 +462,10 @@ public abstract class QtLoader {
ArrayList<String> oneEntryArray = new ArrayList<>(Collections.singletonList(mainLibName));
String mainLibPath = getLibrariesFullPaths(oneEntryArray).get(0);
final boolean[] success = {true};
QtNative.getQtThread().run(new Runnable() {
@Override
public void run() {
m_mainLib = loadLibraryHelper(mainLibPath);
if (m_mainLib == null)
success[0] = false;
}
QtNative.getQtThread().run(() -> {
m_mainLib = loadLibraryHelper(mainLibPath);
if (m_mainLib == null)
success[0] = false;
});
return success[0];
@ -488,15 +485,12 @@ public abstract class QtLoader {
ArrayList<String> fullPathLibs = getLibrariesFullPaths(libraries);
final boolean[] success = {true};
QtNative.getQtThread().run(new Runnable() {
@Override
public void run() {
for (int i = 0; i < fullPathLibs.size(); ++i) {
String libName = fullPathLibs.get(i);
if (loadLibraryHelper(libName) == null) {
success[0] = false;
break;
}
QtNative.getQtThread().run(() -> {
for (int i = 0; i < fullPathLibs.size(); ++i) {
String libName = fullPathLibs.get(i);
if (loadLibraryHelper(libName) == null) {
success[0] = false;
break;
}
}
});

View File

@ -159,177 +159,163 @@ public class QtMessageDialogHelper
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_activity.runOnUiThread(() -> {
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();
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);
if (m_title != null)
m_dialog.setTitle(m_title);
m_dialog.setOnCancelListener(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 = view -> {
TextView tv = (TextView)view;
if (tv != null) {
ClipboardManager cm = (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);
view.setTextAppearance(m_activity, android.R.style.TextAppearance_Medium);
view.setText(m_text);
view.setTextAppearance(m_activity, android.R.style.TextAppearance_Medium);
RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layout.setMargins(16, 8, 16, 8);
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);
view.setTextAppearance(m_activity, android.R.style.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;
}
dialogLayout.addView(view, layout);
lastView = view;
}
if (m_informativeText != null)
if (m_detailedText != null)
{
TextView view= new TextView(m_activity);
view.setId(id++);
view.setOnLongClickListener(copyText);
view.setLongClickable(true);
view.setText(m_detailedText);
view.setTextAppearance(m_activity, android.R.style.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)
{
TextView view= new TextView(m_activity);
view.setId(id++);
view.setOnLongClickListener(copyText);
view.setLongClickable(true);
view.setText(m_informativeText);
view.setTextAppearance(m_activity, android.R.style.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);
view.setTextAppearance(m_activity, android.R.style.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;
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();
}
bv.setText(button.m_text);
bv.setOnClickListener(button);
if (!firstButton) // first button
{
View spacer = new View(m_activity);
try {
LinearLayout.LayoutParams 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 = new LinearLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT, 1.0f);
buttonsLayout.addView(bv, layout);
firstButton = false;
}
Button bv;
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;
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();
}
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
bv.setText(button.m_text);
bv.setOnClickListener(button);
if (!firstButton) // first button
{
View spacer = new View(m_activity);
try {
LinearLayout.LayoutParams 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 = new LinearLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT, 1.0f);
buttonsLayout.addView(bv, layout);
firstButton = false;
}
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);
relativeParams.setMargins(2, 0, 2, 0);
dialogLayout.addView(buttonsLayout, relativeParams);
dialogLayout.addView(horizontalDevider, relativeParams);
lastView = horizontalDevider;
} catch (Exception e) {
e.printStackTrace();
}
scrollView.addView(dialogLayout);
m_dialog.setView(scrollView);
m_dialog.show();
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);
relativeParams.setMargins(2, 0, 2, 0);
dialogLayout.addView(buttonsLayout, relativeParams);
}
scrollView.addView(dialogLayout);
m_dialog.setView(scrollView);
m_dialog.show();
});
}
@UsedFromNativeCode
public void hide()
{
m_activity.runOnUiThread( new Runnable() {
@Override
public void run() {
if (m_dialog != null && m_dialog.isShowing())
m_dialog.dismiss();
reset();
}
m_activity.runOnUiThread(() -> {
if (m_dialog != null && m_dialog.isShowing())
m_dialog.dismiss();
reset();
});
}

View File

@ -46,12 +46,7 @@ public class QtNative
private static final QtThread m_qtThread = new QtThread();
private static ClassLoader m_classLoader = null;
private static final Runnable runPendingCppRunnablesRunnable = new Runnable() {
@Override
public void run() {
runPendingCppRunnables();
}
};
private static final Runnable runPendingCppRunnablesRunnable = QtNative::runPendingCppRunnables;
public static boolean isStarted()
{
@ -255,12 +250,7 @@ public class QtNative
@UsedFromNativeCode
private static void setViewVisibility(final View view, final boolean visible)
{
runAction(new Runnable() {
@Override
public void run() {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
});
runAction(() -> view.setVisibility(visible ? View.VISIBLE : View.GONE));
}
public static boolean startApplication(ArrayList<String> params, String mainLib)
@ -269,18 +259,8 @@ public class QtNative
synchronized (m_mainActivityMutex) {
String paramsStr = String.join("\t", params);
final String qtParams = mainLib + "\t" + paramsStr;
m_qtThread.run(new Runnable() {
@Override
public void run() {
res[0] = startQtAndroidPlugin(qtParams);
}
});
m_qtThread.post(new Runnable() {
@Override
public void run() {
startQtApplication();
}
});
m_qtThread.run(() -> res[0] = startQtAndroidPlugin(qtParams));
m_qtThread.post(QtNative::startQtApplication);
waitForServiceSetup();
m_started = true;
}
@ -289,17 +269,14 @@ public class QtNative
public static void quitApp()
{
runAction(new Runnable() {
@Override
public void run() {
quitQtAndroidPlugin();
if (isActivityValid())
m_activity.get().finish();
if (isServiceValid())
m_service.get().stopSelf();
runAction(() -> {
quitQtAndroidPlugin();
if (isActivityValid())
m_activity.get().finish();
if (isServiceValid())
m_service.get().stopSelf();
m_started = false;
}
m_started = false;
});
}

View File

@ -45,12 +45,9 @@ public class QtThread {
public void run(final Runnable runnable) {
final Semaphore sem = new Semaphore(0);
synchronized (m_qtThread) {
m_pendingRunnables.add(new Runnable() {
@Override
public void run() {
runnable.run();
sem.release();
}
m_pendingRunnables.add(() -> {
runnable.run();
sem.release();
});
m_qtThread.notify();
}

View File

@ -161,99 +161,83 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate
public void notifyScrolledEvent(int viewId)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
sendEventForVirtualViewId(viewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
}
});
QtNative.runAction(() -> sendEventForVirtualViewId(viewId,
AccessibilityEvent.TYPE_VIEW_SCROLLED));
}
public void notifyLocationChange(int viewId)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_focusedVirtualViewId == viewId)
invalidateVirtualViewId(m_focusedVirtualViewId);
}
QtNative.runAction(() -> {
if (m_focusedVirtualViewId == viewId)
invalidateVirtualViewId(m_focusedVirtualViewId);
});
}
public void notifyObjectHide(int viewId, int parentId)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
// If the object had accessibility focus, we need to clear it.
// Note: This code is mostly copied from
// AccessibilityNodeProvider::performAction, but we remove the
// focus only if the focused view id matches the one that was hidden.
if (m_focusedVirtualViewId == viewId) {
m_focusedVirtualViewId = INVALID_ID;
m_view.invalidate();
sendEventForVirtualViewId(viewId,
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
}
// When the object is hidden, we need to notify its parent about
// content change, not the hidden object itself
invalidateVirtualViewId(parentId);
QtNative.runAction(() -> {
// If the object had accessibility focus, we need to clear it.
// Note: This code is mostly copied from
// AccessibilityNodeProvider::performAction, but we remove the
// focus only if the focused view id matches the one that was hidden.
if (m_focusedVirtualViewId == viewId) {
m_focusedVirtualViewId = INVALID_ID;
m_view.invalidate();
sendEventForVirtualViewId(viewId,
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
}
// When the object is hidden, we need to notify its parent about
// content change, not the hidden object itself
invalidateVirtualViewId(parentId);
});
}
public void notifyObjectFocus(int viewId)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
if (m_view == null)
return;
m_focusedVirtualViewId = viewId;
m_view.invalidate();
sendEventForVirtualViewId(viewId,
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
}
QtNative.runAction(() -> {
if (m_view == null)
return;
m_focusedVirtualViewId = viewId;
m_view.invalidate();
sendEventForVirtualViewId(viewId,
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
});
}
public void notifyValueChanged(int viewId, String value)
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
// Send a TYPE_ANNOUNCEMENT event with the new value
QtNative.runAction(() -> {
// Send a TYPE_ANNOUNCEMENT event with the new value
if ((viewId == INVALID_ID) || !m_manager.isEnabled()) {
Log.w(TAG, "notifyValueChanged() for invalid view");
return;
}
final ViewGroup group = (ViewGroup) m_view.getParent();
if (group == null) {
Log.w(TAG, "Could not announce value because ViewGroup was null.");
return;
}
final AccessibilityEvent event =
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT);
event.setEnabled(true);
event.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
event.setContentDescription(value);
if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) {
Log.w(TAG, "No value to announce for " + event.getClassName());
return;
}
event.setPackageName(m_view.getContext().getPackageName());
event.setSource(m_view, viewId);
if (!group.requestSendAccessibilityEvent(m_view, event))
Log.w(TAG, "Failed to send value change announcement for " + event.getClassName());
if ((viewId == INVALID_ID) || !m_manager.isEnabled()) {
Log.w(TAG, "notifyValueChanged() for invalid view");
return;
}
final ViewGroup group = (ViewGroup) m_view.getParent();
if (group == null) {
Log.w(TAG, "Could not announce value because ViewGroup was null.");
return;
}
final AccessibilityEvent event =
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_ANNOUNCEMENT);
event.setEnabled(true);
event.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
event.setContentDescription(value);
if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) {
Log.w(TAG, "No value to announce for " + event.getClassName());
return;
}
event.setPackageName(m_view.getContext().getPackageName());
event.setSource(m_view, viewId);
if (!group.requestSendAccessibilityEvent(m_view, event))
Log.w(TAG, "Failed to send value change announcement for " + event.getClassName());
});
}