mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-21 21:01:43 +08:00
api(floaty): floaty.rawWindow()
This commit is contained in:
parent
ac0e9952c8
commit
44b7f0b39a
@ -9,10 +9,16 @@ module.exports = function(runtime, global){
|
||||
return wrap(runtime.floaty.window(layout));
|
||||
}
|
||||
|
||||
floaty.__view_cache__ = {};
|
||||
floaty.rawWindow = function(layout){
|
||||
if(typeof(layout) == 'xml'){
|
||||
layout = layout.toString();
|
||||
}
|
||||
return wrap(runtime.floaty.rawWindow(layout));
|
||||
}
|
||||
|
||||
function wrap(window){
|
||||
var proxyObject = new com.stardust.autojs.rhino.ProxyJavaObject(global, window, window.getClass());
|
||||
var viewCache = {};
|
||||
proxyObject.__proxy__ = {
|
||||
set: function(name, value){
|
||||
window[name] = value;
|
||||
@ -20,12 +26,12 @@ module.exports = function(runtime, global){
|
||||
get: function(name) {
|
||||
var value = window[name];
|
||||
if(typeof(value) == 'undefined'){
|
||||
value = floaty.__view_cache__[name];
|
||||
value = viewCache[name];
|
||||
if(!value){
|
||||
value = window.findView(name);
|
||||
if(value){
|
||||
value = ui.__decorate__(value);
|
||||
floaty.__view_cache__[name] = value;
|
||||
viewCache[name] = value;
|
||||
}
|
||||
}
|
||||
if(!value){
|
||||
|
||||
@ -10,6 +10,10 @@ import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.core.ui.inflater.inflaters.Exceptions;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.concurrent.VolatileBox;
|
||||
import com.stardust.concurrent.VolatileDispose;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.ResizableFloaty;
|
||||
import com.stardust.enhancedfloaty.ResizableFloatyWindow;
|
||||
@ -21,7 +25,7 @@ import com.stardust.enhancedfloaty.gesture.ResizeGesture;
|
||||
* Created by Stardust on 2017/12/5.
|
||||
*/
|
||||
|
||||
public class FloatyWindow extends ResizableFloatyWindow {
|
||||
public class BaseResizableFloatyWindow extends ResizableFloatyWindow {
|
||||
|
||||
public interface ViewSupplier {
|
||||
|
||||
@ -29,8 +33,7 @@ public class FloatyWindow extends ResizableFloatyWindow {
|
||||
|
||||
}
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private boolean mCreated = false;
|
||||
private VolatileDispose<RuntimeException> mInflateException = new VolatileDispose<>();
|
||||
private View mCloseButton;
|
||||
private static final String TAG = "ResizableFloatyWindow";
|
||||
private WindowManager mWindowManager;
|
||||
@ -43,26 +46,17 @@ public class FloatyWindow extends ResizableFloatyWindow {
|
||||
private MyFloaty mFloaty;
|
||||
|
||||
|
||||
public FloatyWindow(Context context, ViewSupplier viewSupplier) {
|
||||
public BaseResizableFloatyWindow(Context context, ViewSupplier viewSupplier) {
|
||||
this(new MyFloaty(context, viewSupplier));
|
||||
}
|
||||
|
||||
private FloatyWindow(MyFloaty floaty) {
|
||||
private BaseResizableFloatyWindow(MyFloaty floaty) {
|
||||
super(floaty);
|
||||
mFloaty = floaty;
|
||||
}
|
||||
|
||||
public void waitFor() {
|
||||
synchronized (mLock) {
|
||||
if (mCreated) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public RuntimeException waitForCreation() {
|
||||
return mInflateException.blockedGetOrThrow(ScriptInterruptedException.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,14 +66,16 @@ public class FloatyWindow extends ResizableFloatyWindow {
|
||||
if (this.mFloaty == null) {
|
||||
throw new IllegalStateException("Must start this service by static method ResizableExpandableFloatyWindow.startService");
|
||||
} else {
|
||||
this.initWindowView(service);
|
||||
try {
|
||||
this.initWindowView(service);
|
||||
} catch (RuntimeException e) {
|
||||
mInflateException.setAndNotify(e);
|
||||
return;
|
||||
}
|
||||
this.mWindowBridge = new WindowBridge.DefaultImpl(this.mWindowLayoutParams, this.mWindowManager, this.mWindowView);
|
||||
this.initGesture();
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mCreated = true;
|
||||
mLock.notify();
|
||||
}
|
||||
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION);
|
||||
}
|
||||
|
||||
public void setOnCloseButtonClickListener(View.OnClickListener listener) {
|
||||
@ -161,7 +157,8 @@ public class FloatyWindow extends ResizableFloatyWindow {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
this.mWindowManager.removeView(this.mWindowView);
|
||||
if (mWindowView != null)
|
||||
this.mWindowManager.removeView(this.mWindowView);
|
||||
FloatyService.removeWindow(this);
|
||||
}
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
package com.stardust.autojs.core.floaty;
|
||||
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.core.ui.inflater.inflaters.Exceptions;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.concurrent.VolatileBox;
|
||||
import com.stardust.concurrent.VolatileDispose;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.enhancedfloaty.WindowBridge;
|
||||
|
||||
public class RawWindow implements FloatyWindow {
|
||||
|
||||
|
||||
public interface RawFloaty {
|
||||
|
||||
View inflateWindowView(FloatyService service, ViewGroup parent);
|
||||
}
|
||||
|
||||
private WindowBridge mWindowBridge;
|
||||
private VolatileDispose<RuntimeException> mInflateException = new VolatileDispose<>();
|
||||
private WindowManager mWindowManager;
|
||||
private ViewGroup mWindowView;
|
||||
private View mWindowContent;
|
||||
private RawFloaty mRawFloaty;
|
||||
private WindowManager.LayoutParams mWindowLayoutParams;
|
||||
|
||||
public RawWindow(RawFloaty rawFloaty) {
|
||||
mRawFloaty = rawFloaty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(FloatyService floatyService, WindowManager windowManager) {
|
||||
mWindowManager = windowManager;
|
||||
mWindowView = (ViewGroup) View.inflate(floatyService, R.layout.raw_window, null);
|
||||
mWindowLayoutParams = createWindowLayoutParams();
|
||||
try {
|
||||
mWindowContent = mRawFloaty.inflateWindowView(floatyService, mWindowView);
|
||||
mWindowManager.addView(mWindowView, mWindowLayoutParams);
|
||||
} catch (RuntimeException e) {
|
||||
mInflateException.setAndNotify(e);
|
||||
return;
|
||||
}
|
||||
mWindowBridge = new WindowBridge.DefaultImpl(mWindowLayoutParams, windowManager, mWindowView);
|
||||
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION);
|
||||
}
|
||||
|
||||
public RuntimeException waitForCreation() {
|
||||
return mInflateException.blockedGetOrThrow(ScriptInterruptedException.class);
|
||||
}
|
||||
|
||||
|
||||
protected WindowManager.LayoutParams createWindowLayoutParams() {
|
||||
int flags =
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
| WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
|
||||
}
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
|
||||
flags,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
layoutParams.gravity = Gravity.TOP | Gravity.START;
|
||||
return layoutParams;
|
||||
}
|
||||
|
||||
|
||||
public void disableWindowFocus() {
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
}
|
||||
|
||||
public void requestWindowFocus() {
|
||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
mWindowView.requestFocus();
|
||||
}
|
||||
|
||||
public void setTouchable(boolean touchable) {
|
||||
if (touchable) {
|
||||
mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
} else {
|
||||
mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
}
|
||||
mWindowManager.updateViewLayout(mWindowView, mWindowLayoutParams);
|
||||
}
|
||||
|
||||
public WindowBridge getWindowBridge() {
|
||||
return mWindowBridge;
|
||||
}
|
||||
|
||||
public ViewGroup getWindowView() {
|
||||
return mWindowView;
|
||||
}
|
||||
|
||||
public View getWindowContent() {
|
||||
return mWindowContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDestroy(FloatyService floatyService) {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (mWindowView != null)
|
||||
mWindowManager.removeView(mWindowView);
|
||||
FloatyService.removeWindow(this);
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,9 @@ import android.view.View;
|
||||
|
||||
public class Exceptions {
|
||||
|
||||
public static final RuntimeException NO_EXCEPTION = new RuntimeException();
|
||||
|
||||
|
||||
public interface ExceptionHandler {
|
||||
boolean handleUnsupportedException(UnsupportedOperationException e, View v, String attrName, String value);
|
||||
}
|
||||
|
||||
@ -5,16 +5,16 @@ import android.content.Intent;
|
||||
import android.os.Looper;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.core.floaty.FloatyWindow;
|
||||
import com.stardust.autojs.core.floaty.BaseResizableFloatyWindow;
|
||||
import com.stardust.autojs.core.floaty.RawWindow;
|
||||
import com.stardust.autojs.core.ui.JsViewHelper;
|
||||
import com.stardust.autojs.core.ui.inflater.DynamicLayoutInflater;
|
||||
import com.stardust.autojs.core.ui.inflater.inflaters.Exceptions;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.autojs.util.FloatingPermission;
|
||||
import com.stardust.concurrent.VolatileDispose;
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.util.UiHandler;
|
||||
import com.stardust.util.ViewUtil;
|
||||
@ -30,7 +30,7 @@ public class Floaty {
|
||||
private DynamicLayoutInflater mLayoutInflater;
|
||||
private Context mContext;
|
||||
private UiHandler mUiHandler;
|
||||
private CopyOnWriteArraySet<JsFloatyWindow> mWindows = new CopyOnWriteArraySet<>();
|
||||
private CopyOnWriteArraySet<JsWindow> mWindows = new CopyOnWriteArraySet<>();
|
||||
private ScriptRuntime mRuntime;
|
||||
|
||||
public Floaty(UiHandler uiHandler, UI ui, ScriptRuntime runtime) {
|
||||
@ -40,51 +40,175 @@ public class Floaty {
|
||||
mLayoutInflater = ui.getLayoutInflater();
|
||||
}
|
||||
|
||||
public JsFloatyWindow window(String xml) {
|
||||
public JsResizableWindow window(String xml) {
|
||||
try {
|
||||
FloatingPermission.waitForPermissionGranted(mContext);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
JsFloatyWindow window = new JsFloatyWindow((context, parent) -> mLayoutInflater.inflate(xml, parent));
|
||||
JsResizableWindow window = new JsResizableWindow((context, parent) -> mLayoutInflater.inflate(xml, parent));
|
||||
addWindow(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
public JsFloatyWindow window(View view) {
|
||||
public JsResizableWindow window(View view) {
|
||||
try {
|
||||
FloatingPermission.waitForPermissionGranted(view.getContext());
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
JsFloatyWindow window = new JsFloatyWindow((context, parent) -> view);
|
||||
JsResizableWindow window = new JsResizableWindow((context, parent) -> view);
|
||||
addWindow(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
private synchronized void addWindow(JsFloatyWindow window) {
|
||||
public JsRawWindow rawWindow(String xml) {
|
||||
try {
|
||||
FloatingPermission.waitForPermissionGranted(mContext);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
JsRawWindow window = new JsRawWindow((context, parent) -> mLayoutInflater.inflate(xml, parent));
|
||||
addWindow(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
public JsRawWindow rawWindow(View view) {
|
||||
try {
|
||||
FloatingPermission.waitForPermissionGranted(mContext);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
JsRawWindow window = new JsRawWindow((context, parent) -> view);
|
||||
addWindow(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
private synchronized void addWindow(JsWindow window) {
|
||||
mWindows.add(window);
|
||||
}
|
||||
|
||||
private synchronized boolean removeWindow(JsFloatyWindow window) {
|
||||
private synchronized boolean removeWindow(JsWindow window) {
|
||||
return mWindows.remove(window);
|
||||
}
|
||||
|
||||
public synchronized void closeAll() {
|
||||
for (JsFloatyWindow window : mWindows) {
|
||||
for (JsWindow window : mWindows) {
|
||||
window.close(false);
|
||||
}
|
||||
mWindows.clear();
|
||||
}
|
||||
|
||||
public class JsFloatyWindow {
|
||||
public interface JsWindow {
|
||||
void close(boolean removeFromWindows);
|
||||
}
|
||||
|
||||
public class JsRawWindow implements JsWindow {
|
||||
|
||||
private RawWindow mWindow;
|
||||
private boolean mExitOnClose;
|
||||
|
||||
public JsRawWindow(RawWindow.RawFloaty floaty) {
|
||||
mWindow = new RawWindow(floaty);
|
||||
mUiHandler.post(() -> {
|
||||
mUiHandler.getContext().startService(new Intent(mUiHandler.getContext(), FloatyService.class));
|
||||
FloatyService.addWindow(mWindow);
|
||||
});
|
||||
RuntimeException exception = mWindow.waitForCreation();
|
||||
if (exception != Exceptions.NO_EXCEPTION && exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
public View findView(String id) {
|
||||
return JsViewHelper.findViewByStringId(mWindow.getWindowContent(), id);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return mWindow.getWindowBridge().getX();
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return mWindow.getWindowBridge().getY();
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return mWindow.getWindowView().getWidth();
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return mWindow.getWindowView().getHeight();
|
||||
}
|
||||
|
||||
public void setSize(int w, int h) {
|
||||
runWithWindow(() -> {
|
||||
mWindow.getWindowBridge().updateMeasure(w, h);
|
||||
ViewUtil.setViewMeasure(mWindow.getWindowView(), w, h);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void setTouchable(boolean touchable) {
|
||||
runWithWindow(() -> mWindow.setTouchable(touchable));
|
||||
}
|
||||
|
||||
private void runWithWindow(Runnable r) {
|
||||
if (mWindow == null)
|
||||
return;
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
r.run();
|
||||
return;
|
||||
}
|
||||
mUiHandler.post(() -> {
|
||||
if (mWindow == null)
|
||||
return;
|
||||
r.run();
|
||||
});
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y) {
|
||||
runWithWindow(() -> mWindow.getWindowBridge().updatePosition(x, y));
|
||||
}
|
||||
|
||||
public void exitOnClose() {
|
||||
mExitOnClose = true;
|
||||
}
|
||||
|
||||
public void requestFocus() {
|
||||
mWindow.requestWindowFocus();
|
||||
}
|
||||
|
||||
public void disableFocus() {
|
||||
mWindow.disableWindowFocus();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
close(true);
|
||||
}
|
||||
|
||||
public void close(boolean removeFromWindows) {
|
||||
if (removeFromWindows && !removeWindow(this)) {
|
||||
return;
|
||||
}
|
||||
runWithWindow(() -> {
|
||||
mWindow.close();
|
||||
mWindow = null;
|
||||
if (mExitOnClose) {
|
||||
mRuntime.exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class JsResizableWindow implements JsWindow {
|
||||
|
||||
private View mView;
|
||||
private volatile FloatyWindow mWindow;
|
||||
private volatile BaseResizableFloatyWindow mWindow;
|
||||
private boolean mExitOnClose = false;
|
||||
|
||||
public JsFloatyWindow(FloatyWindow.ViewSupplier supplier) {
|
||||
mWindow = new FloatyWindow(mContext, (context, parent) -> {
|
||||
public JsResizableWindow(BaseResizableFloatyWindow.ViewSupplier supplier) {
|
||||
mWindow = new BaseResizableFloatyWindow(mContext, (context, parent) -> {
|
||||
mView = supplier.inflate(context, parent);
|
||||
return mView;
|
||||
});
|
||||
@ -92,7 +216,10 @@ public class Floaty {
|
||||
mUiHandler.getContext().startService(new Intent(mUiHandler.getContext(), FloatyService.class));
|
||||
FloatyService.addWindow(mWindow);
|
||||
});
|
||||
mWindow.waitFor();
|
||||
RuntimeException exception = mWindow.waitForCreation();
|
||||
if (exception != Exceptions.NO_EXCEPTION && exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
mWindow.setOnCloseButtonClickListener(v -> close());
|
||||
//setSize(mWindow.getWindowBridge().getScreenWidth() / 2, mWindow.getWindowBridge().getScreenHeight() / 2);
|
||||
}
|
||||
@ -118,9 +245,14 @@ public class Floaty {
|
||||
}
|
||||
|
||||
public void setSize(int w, int h) {
|
||||
runWithWindow(() -> ViewUtil.setViewMeasure(mWindow.getRootView(), w, h));
|
||||
runWithWindow(() -> {
|
||||
mWindow.getWindowBridge().updateMeasure(w, h);
|
||||
ViewUtil.setViewMeasure(mWindow.getRootView(), w, h);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private void runWithWindow(Runnable r) {
|
||||
if (mWindow == null)
|
||||
return;
|
||||
@ -163,7 +295,7 @@ public class Floaty {
|
||||
close(true);
|
||||
}
|
||||
|
||||
void close(boolean removeFromWindows) {
|
||||
public void close(boolean removeFromWindows) {
|
||||
if (removeFromWindows && !removeWindow(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
6
autojs/src/main/res/layout/raw_window.xml
Normal file
6
autojs/src/main/res/layout/raw_window.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</FrameLayout>
|
||||
Loading…
Reference in New Issue
Block a user