6.6.2 - Alpha - floaty.window/floaty.rawWindow 同时支持主线程和子线程执行

This commit is contained in:
SuperMonster003
2025-01-12 23:52:22 +08:00
parent 5a174079e7
commit f68880f3b6
7 changed files with 129 additions and 144 deletions

View File

@@ -5,13 +5,15 @@
"fix": [ "fix": [
"notice 模块缺失 getBuilder 等扩展方法的问题 _[`issue #301`](http://issues.autojs6.com/301)_", "notice 模块缺失 getBuilder 等扩展方法的问题 _[`issue #301`](http://issues.autojs6.com/301)_",
"dx 库在 Android 7.x 无法正常使用的问题 _[`issue #293`](http://issues.autojs6.com/293)_", "dx 库在 Android 7.x 无法正常使用的问题 _[`issue #293`](http://issues.autojs6.com/293)_",
"ScriptRuntime 使用 require 引用内置模块时可能出现的同步状态异常 (试修)_[`issue #298`](http://issues.autojs6.com/298)_" "ScriptRuntime 使用 require 引用内置模块时可能出现的同步状态异常 (试修)_[`issue #298`](http://issues.autojs6.com/298)_",
"floaty.window/floaty.rawWindow 无法在子线程执行的问题"
], ],
"improvement": [ "improvement": [
"精简打包应用模板 APK 文件大小", "精简打包应用模板 APK 文件大小",
"打包页面支持 Pinyin 库选项", "打包页面支持 Pinyin 库选项",
"APK 文件类型信息对话框增加文件大小与签名方案信息", "APK 文件类型信息对话框增加文件大小与签名方案信息",
"APK 文件类型信息对话框增加点击监听器支持文本复制与应用详情跳转" "APK 文件类型信息对话框增加点击监听器支持文本复制与应用详情跳转",
"floaty.window/floaty.rawWindow 同时支持主线程和子线程执行"
] ]
}, },
"v6.6.1": { "v6.6.1": {

View File

@@ -1,79 +1,58 @@
package org.autojs.autojs.core.floaty package org.autojs.autojs.core.floaty
import android.content.Context import android.content.Context
import android.graphics.PixelFormat
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.view.WindowManager.LayoutParams import android.view.WindowManager.LayoutParams
import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import org.autojs.autojs.concurrent.VolatileDispose import org.autojs.autojs.concurrent.VolatileDispose
import org.autojs.autojs.core.ui.inflater.Exceptions import org.autojs.autojs.core.ui.inflater.Exceptions
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
import org.autojs.autojs.ui.enhancedfloaty.FloatyService import org.autojs.autojs.ui.enhancedfloaty.FloatyService
import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow
import org.autojs.autojs.ui.enhancedfloaty.ResizableFloaty import org.autojs.autojs.ui.enhancedfloaty.ResizableFloaty
import org.autojs.autojs.ui.enhancedfloaty.ResizableFloatyWindow import org.autojs.autojs.ui.enhancedfloaty.ResizableFloatyWindow
import org.autojs.autojs.ui.enhancedfloaty.WindowBridge import org.autojs.autojs.ui.enhancedfloaty.WindowBridge
import org.autojs.autojs.ui.enhancedfloaty.WindowBridge.DefaultImpl import org.autojs.autojs.ui.enhancedfloaty.WindowBridge.DefaultImpl
import org.autojs.autojs.ui.enhancedfloaty.gesture.DragGesture import org.autojs.autojs.ui.enhancedfloaty.gesture.DragGesture
import org.autojs.autojs.ui.enhancedfloaty.gesture.ResizeGesture import org.autojs.autojs.ui.enhancedfloaty.gesture.ResizeGesture
import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat
import org.autojs.autojs6.R import org.autojs.autojs6.R
import org.autojs.autojs6.databinding.FloatyWindowBinding import org.autojs.autojs6.databinding.FloatyWindowBinding
import org.autojs.autojs6.databinding.RawWindowBinding
/** /**
* Created by Stardust on Dec 5, 2017. * Created by Stardust on Dec 5, 2017.
* Modified by SuperMonster003 as of Jun 10, 2022. * Modified by SuperMonster003 as of Jun 10, 2022.
* Transformed by SuperMonster003 on Oct 10, 2022. * Transformed by SuperMonster003 on Oct 10, 2022.
*/ */
class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) : FloatyWindow() { class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) : ResizableFloatyWindow(BaseResizableFloaty(context, viewSupplier)) {
private var rawWindowBinding: RawWindowBinding
private val mInflateException = VolatileDispose<RuntimeException>() private val mInflateException = VolatileDispose<RuntimeException>()
private var mOffset = context.resources.getDimensionPixelSize(R.dimen.floaty_window_offset) private val mOffset = context.resources.getDimensionPixelSize(R.dimen.floaty_window_offset)
private val mFloaty = MyFloaty(context, viewSupplier) private val mFloaty by lazy { floaty as BaseResizableFloaty }
private val mCloseButton by lazy { mFloaty.getCloseButtonView(rootView) }
private val mMoveCursor by lazy { mFloaty.getMoveCursorView(rootView) }
private val mResizer by lazy { mFloaty.getResizerView(rootView) }
val rootView = mFloaty.rootView val rootView by lazy { mFloaty.rootView }
private var mCloseButton = mFloaty.getCloseButtonView(rootView) var isAdjustEnabled: Boolean
private var mMoveCursor = mFloaty.getMoveCursorView(rootView) get() = mMoveCursor.visibility == View.VISIBLE
private var mResizer = mFloaty.getResizerView(rootView) set(enabled) {
if (!enabled) {
mMoveCursor.visibility = View.GONE
mResizer.visibility = View.GONE
mCloseButton.visibility = View.GONE
} else {
mMoveCursor.visibility = View.VISIBLE
mResizer.visibility = View.VISIBLE
mCloseButton.visibility = View.VISIBLE
}
}
// @Reference to aiselp (https://github.com/aiselp) by SuperMonster003 on Mar 27, 2023. fun waitForCreation(): RuntimeException? = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
// ! https://github.com/kkevsekk1/AutoX/pull/529/commits/782f1c3c12dee64d9b1ad70aba462afaf60313a4#diff-b8e544bc658140f04a7fa7171cc938032f18c92495ca25bb08e2d2eb546b70f5
init {
val layoutParams = createWindowLayoutParams()
rawWindowBinding = RawWindowBinding.inflate(LayoutInflater.from(context))
val windowView = rawWindowBinding.root
val params = ViewGroup.LayoutParams(-2, -2)
windowView.addView(rootView, params)
windowView.isFocusableInTouchMode = true
super.setWindowLayoutParams(layoutParams)
super.setWindowView(windowView)
super.setWindowManager(context.getSystemService(FloatyService.WINDOW_SERVICE) as WindowManager)
super.setWindowBridge(super.onCreateWindowBridge(layoutParams))
}
interface ViewSupplier {
fun inflate(context: Context, parent: ViewGroup?): View
}
private fun createWindowLayoutParams() = LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
WindowTypeCompat.getPhoneWindowType(),
LayoutParams.FLAG_LAYOUT_NO_LIMITS or LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
).apply { gravity = Gravity.TOP or Gravity.START }
// fun waitForCreation(): RuntimeException = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
override fun onCreateWindowBridge(params: LayoutParams): WindowBridge { override fun onCreateWindowBridge(params: LayoutParams): WindowBridge {
return object : DefaultImpl(params, windowManager, windowView) { return object : DefaultImpl(params, windowManager, windowView) {
@@ -85,10 +64,6 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
} }
} }
override fun onCreateWindowLayoutParams(): LayoutParams {
return super.getWindowLayoutParams()
}
override fun onCreate(service: FloatyService, manager: WindowManager) { override fun onCreate(service: FloatyService, manager: WindowManager) {
try { try {
super.onCreate(service, manager) super.onCreate(service, manager)
@@ -121,22 +96,6 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
mCloseButton.setOnClickListener(listener) mCloseButton.setOnClickListener(listener)
} }
var isAdjustEnabled: Boolean
get() = mMoveCursor.visibility == View.VISIBLE
set(enabled) {
if (!enabled) {
mMoveCursor.visibility = View.GONE
mResizer.visibility = View.GONE
mCloseButton.visibility = View.GONE
} else {
mMoveCursor.visibility = View.VISIBLE
mResizer.visibility = View.VISIBLE
mCloseButton.visibility = View.VISIBLE
}
}
override fun onCreateView(floatyService: FloatyService?): View? = super.getWindowView()
fun disableWindowFocus() { fun disableWindowFocus() {
windowLayoutParams.apply { windowLayoutParams.apply {
flags = flags or LayoutParams.FLAG_NOT_FOCUSABLE flags = flags or LayoutParams.FLAG_NOT_FOCUSABLE
@@ -152,18 +111,17 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
windowView?.requestLayout() windowView?.requestLayout()
} }
private class MyFloaty(context: Context, contentViewSupplier: ViewSupplier) : ResizableFloaty { private class BaseResizableFloaty(private val context: Context, private val contentViewSupplier: ViewSupplier) : ResizableFloaty {
private val floatyWindowBinding = FloatyWindowBinding.inflate(LayoutInflater.from(context)) private val floatyWindowBinding = FloatyWindowBinding.inflate(LayoutInflater.from(context))
val rootView = floatyWindowBinding.root val rootView = floatyWindowBinding.root
init { override fun inflateView(floatyService: FloatyService, resizableFloatyWindow: ResizableFloatyWindow): FrameLayout {
contentViewSupplier.inflate(context, floatyWindowBinding.container) contentViewSupplier.inflate(context, floatyWindowBinding.container)
return rootView
} }
override fun inflateView(floatyService: FloatyService, resizableFloatyWindow: ResizableFloatyWindow) = rootView
override fun getResizerView(view: View): ImageView = floatyWindowBinding.resizer override fun getResizerView(view: View): ImageView = floatyWindowBinding.resizer
override fun getMoveCursorView(view: View): ImageView = floatyWindowBinding.moveCursor override fun getMoveCursorView(view: View): ImageView = floatyWindowBinding.moveCursor
@@ -171,4 +129,9 @@ class BaseResizableFloatyWindow(context: Context, viewSupplier: ViewSupplier) :
override fun getCloseButtonView(view: View): ImageView = floatyWindowBinding.close override fun getCloseButtonView(view: View): ImageView = floatyWindowBinding.close
} }
interface ViewSupplier {
fun inflate(context: Context, parent: ViewGroup?): View
}
} }

View File

@@ -1,41 +1,28 @@
package org.autojs.autojs.core.floaty package org.autojs.autojs.core.floaty
import android.content.Context
import android.graphics.PixelFormat import android.graphics.PixelFormat
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.view.WindowManager.LayoutParams import android.view.WindowManager.LayoutParams
import org.autojs.autojs.concurrent.VolatileDispose
import org.autojs.autojs.core.ui.inflater.Exceptions
import org.autojs.autojs.runtime.exception.ScriptInterruptedException
import org.autojs.autojs.ui.enhancedfloaty.FloatyService import org.autojs.autojs.ui.enhancedfloaty.FloatyService
import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow import org.autojs.autojs.ui.enhancedfloaty.FloatyWindow
import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat import org.autojs.autojs.ui.enhancedfloaty.util.WindowTypeCompat
import org.autojs.autojs.concurrent.VolatileDispose
import org.autojs.autojs.core.ui.inflater.Exceptions
import org.autojs.autojs6.R import org.autojs.autojs6.R
/** /**
* Modified by SuperMonster003 as of Mar 27, 2022. * Modified by SuperMonster003 as of Mar 27, 2022.
* Transformed by SuperMonster003 on Mar 27, 2022. * Transformed by SuperMonster003 on Mar 27, 2022.
*/ */
class RawWindow(rawFloaty: BaseResizableFloatyWindow.ViewSupplier, context: Context) : FloatyWindow() { class RawWindow(private val supplier: BaseResizableFloatyWindow.ViewSupplier) : FloatyWindow() {
private val mInflateException = VolatileDispose<RuntimeException>() private val mInflateException = VolatileDispose<RuntimeException>()
var contentView: View lateinit var contentView: View
// @Reference to aiselp (https://github.com/aiselp) by SuperMonster003 on Mar 27, 2023.
// ! https://github.com/kkevsekk1/AutoX/pull/529/commits/782f1c3c12dee64d9b1ad70aba462afaf60313a4#diff-b8e544bc658140f04a7fa7171cc938032f18c92495ca25bb08e2d2eb546b70f5
init {
val windowView = View.inflate(context, R.layout.raw_window, null) as ViewGroup
contentView = rawFloaty.inflate(context, windowView)
val mWindowLayoutParams = createWindowLayoutParams()
super.setWindowView(windowView)
super.setWindowManager(context.getSystemService(FloatyService.WINDOW_SERVICE) as WindowManager)
super.setWindowLayoutParams(mWindowLayoutParams)
super.setWindowBridge(super.onCreateWindowBridge(mWindowLayoutParams))
}
override fun onCreate(floatyService: FloatyService, windowManager: WindowManager) { override fun onCreate(floatyService: FloatyService, windowManager: WindowManager) {
try { try {
@@ -47,19 +34,29 @@ class RawWindow(rawFloaty: BaseResizableFloatyWindow.ViewSupplier, context: Cont
mInflateException.setAndNotify(Exceptions.NO_EXCEPTION) mInflateException.setAndNotify(Exceptions.NO_EXCEPTION)
} }
override fun onCreateView(floatyService: FloatyService): View? = super.getWindowView() override fun onCreateView(floatyService: FloatyService): View {
val windowView = View.inflate(floatyService, R.layout.raw_window, null) as ViewGroup
contentView = supplier.inflate(floatyService, windowView)
return windowView
}
override fun onCreateWindowLayoutParams(): LayoutParams = super.getWindowLayoutParams() override fun onCreateWindowLayoutParams(): LayoutParams {
@Suppress("DEPRECATION")
val flags = LayoutParams.FLAG_LAYOUT_NO_LIMITS or
LayoutParams.FLAG_NOT_TOUCH_MODAL or
LayoutParams.FLAG_FULLSCREEN or
LayoutParams.FLAG_NOT_FOCUSABLE or
LayoutParams.FLAG_TRANSLUCENT_STATUS
return LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
WindowTypeCompat.getWindowType(),
flags,
PixelFormat.TRANSLUCENT
).apply { gravity = Gravity.TOP or Gravity.START }
}
// fun waitForCreation(): RuntimeException = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java) fun waitForCreation(): RuntimeException? = mInflateException.blockedGetOrThrow(ScriptInterruptedException::class.java)
private fun createWindowLayoutParams() = LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
WindowTypeCompat.getWindowType(),
LayoutParams.FLAG_LAYOUT_NO_LIMITS or LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
).apply { gravity = Gravity.TOP or Gravity.START }
fun disableWindowFocus() { fun disableWindowFocus() {
windowLayoutParams.apply { windowLayoutParams.apply {

View File

@@ -5,10 +5,12 @@ import android.content.Intent
import android.view.ContextThemeWrapper import android.view.ContextThemeWrapper
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import kotlinx.coroutines.Runnable
import org.autojs.autojs.annotation.ScriptInterface import org.autojs.autojs.annotation.ScriptInterface
import org.autojs.autojs.core.floaty.BaseResizableFloatyWindow import org.autojs.autojs.core.floaty.BaseResizableFloatyWindow
import org.autojs.autojs.core.floaty.RawWindow import org.autojs.autojs.core.floaty.RawWindow
import org.autojs.autojs.core.ui.JsViewHelper import org.autojs.autojs.core.ui.JsViewHelper
import org.autojs.autojs.core.ui.inflater.Exceptions
import org.autojs.autojs.permission.DisplayOverOtherAppsPermission import org.autojs.autojs.permission.DisplayOverOtherAppsPermission
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.augment.ui.UI import org.autojs.autojs.runtime.api.augment.ui.UI
@@ -23,7 +25,6 @@ import org.autojs.autojs6.R
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.concurrent.Volatile
import kotlin.math.max import kotlin.math.max
/** /**
@@ -31,16 +32,16 @@ import kotlin.math.max
* Modified by SuperMonster003 as of Mar 27, 2022. * Modified by SuperMonster003 as of Mar 27, 2022.
* Transformed by SuperMonster003 on Mar 27, 2022. * Transformed by SuperMonster003 on Mar 27, 2022.
*/ */
class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRuntime) { class Floaty(private val uiHandler: UiHandler, private val scriptRuntime: ScriptRuntime) {
private val mContext = ContextThemeWrapper(mUiHandler.applicationContext, R.style.ScriptTheme) private val mContext = ContextThemeWrapper(uiHandler.applicationContext, R.style.ScriptTheme)
private val mWindows = CopyOnWriteArraySet<JsWindow>() private val mWindows = CopyOnWriteArraySet<JsWindow>()
private val mDisplayOverOtherAppsPerm = DisplayOverOtherAppsPermission(mContext) private val mDisplayOverOtherAppsPerm = DisplayOverOtherAppsPermission(mContext)
fun window(supplier: BaseResizableFloatyWindow.ViewSupplier): JsResizableWindow { fun window(supplier: BaseResizableFloatyWindow.ViewSupplier): JsResizableWindow {
try { try {
mDisplayOverOtherAppsPerm.waitFor() mDisplayOverOtherAppsPerm.waitFor()
} catch (e: InterruptedException) { } catch (_: InterruptedException) {
throw ScriptInterruptedException() throw ScriptInterruptedException()
} }
return JsResizableWindow(supplier).also { addWindow(it) } return JsResizableWindow(supplier).also { addWindow(it) }
@@ -50,13 +51,13 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
override fun inflate(context: Context, parent: ViewGroup?) = view override fun inflate(context: Context, parent: ViewGroup?) = view
}) })
fun rawWindow(floaty: BaseResizableFloatyWindow.ViewSupplier): JsRawWindow { fun rawWindow(supplier: BaseResizableFloatyWindow.ViewSupplier): JsRawWindow {
try { try {
mDisplayOverOtherAppsPerm.waitFor() mDisplayOverOtherAppsPerm.waitFor()
} catch (e: InterruptedException) { } catch (_: InterruptedException) {
throw ScriptInterruptedException() throw ScriptInterruptedException()
} }
return JsRawWindow(floaty).also { addWindow(it) } return JsRawWindow(supplier).also { addWindow(it) }
} }
fun rawWindow(view: View) = JsRawWindow(object : BaseResizableFloatyWindow.ViewSupplier { fun rawWindow(view: View) = JsRawWindow(object : BaseResizableFloatyWindow.ViewSupplier {
@@ -100,32 +101,37 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
val timeoutForAttachedToWindowManager: Long = 2_000 val timeoutForAttachedToWindowManager: Long = 2_000
val latch = CountDownLatch(1) val latch = CountDownLatch(1)
val win = window(View(mContext).apply { visibility = View.INVISIBLE }) val win = window(View(mContext).apply { visibility = View.INVISIBLE })
UI.postRhinoRuntime(mRuntime, newBaseFunction("action", { UI.postRhinoRuntime(scriptRuntime, newBaseFunction("action", {
while (System.currentTimeMillis() - start < timeoutForAttachedToWindowManager) { while (System.currentTimeMillis() - start < timeoutForAttachedToWindowManager) {
if (runCatching { win.requestFocus() }.isSuccess) break if (runCatching { win.requestFocus() }.isSuccess) break
} }
}, NOT_CONSTRUCTABLE)) }, NOT_CONSTRUCTABLE))
latch.await(max(0, delay - (System.currentTimeMillis() - start)), TimeUnit.MILLISECONDS) latch.await(max(0, delay - (System.currentTimeMillis() - start)), TimeUnit.MILLISECONDS)
return mRuntime.clip.also { win.close() } return scriptRuntime.clip.also { win.close() }
} }
interface JsWindow { interface JsWindow {
fun close(removeFromWindows: Boolean) fun close(removeFromWindows: Boolean)
} }
inner class JsRawWindow(floaty: BaseResizableFloatyWindow.ViewSupplier) : JsWindow { inner class JsRawWindow(supplier: BaseResizableFloatyWindow.ViewSupplier) : JsWindow {
private var mWindow: RawWindow? = null private var mWindow: RawWindow? = null
private var mExitOnClose = false private var mExitOnClose = false
init { init {
mWindow = RawWindow(floaty, mUiHandler.applicationContext) val context = uiHandler.applicationContext
mUiHandler.applicationContext.startService(Intent(mUiHandler.applicationContext, FloatyService::class.java)) val window = RawWindow(supplier).also { mWindow = it }
val r = Runnable {
val r = Runnable { FloatyService.addWindow(mWindow) } context.startService(Intent(context, FloatyService::class.java))
FloatyService.addWindow(window)
/* 如果是 UI 线程则直接创建, 否则放入 UI 线程. */ }
if (isUiThread()) r.run() else mUiHandler.post(r) if (isUiThread()) {
r.run()
} else {
uiHandler.post(r)
window.waitForCreation()?.let { if (it != Exceptions.NO_EXCEPTION) throw it }
}
} }
fun findView(id: String?): View? { fun findView(id: String?): View? {
@@ -151,8 +157,11 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
} }
private fun runWithWindow(r: Runnable) { private fun runWithWindow(r: Runnable) {
mWindow ?: return when {
mUiHandler.post(r) mWindow == null -> return
isUiThread() -> r.run()
else -> uiHandler.post { mWindow?.let { r.run() } }
}
} }
fun setPosition(x: Int, y: Int) = runWithWindow { fun setPosition(x: Int, y: Int) = runWithWindow {
@@ -175,7 +184,7 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
mWindow!!.close() mWindow!!.close()
mWindow = null mWindow = null
if (mExitOnClose) { if (mExitOnClose) {
mRuntime.exit() scriptRuntime.exit()
} }
} }
} }
@@ -184,28 +193,29 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
inner class JsResizableWindow(supplier: BaseResizableFloatyWindow.ViewSupplier) : JsWindow { inner class JsResizableWindow(supplier: BaseResizableFloatyWindow.ViewSupplier) : JsWindow {
private var mView: View? = null
@Volatile @Volatile
private var mWindow: BaseResizableFloatyWindow? = null private var mWindow: BaseResizableFloatyWindow? = null
private var mView: View? = null
private var mExitOnClose = false private var mExitOnClose = false
init { init {
mWindow = BaseResizableFloatyWindow(mContext, object : BaseResizableFloatyWindow.ViewSupplier { val context = uiHandler.applicationContext
val window = BaseResizableFloatyWindow(mContext, object : BaseResizableFloatyWindow.ViewSupplier {
override fun inflate(context: Context, parent: ViewGroup?): View { override fun inflate(context: Context, parent: ViewGroup?): View {
return supplier.inflate(context, parent).also { mView = it } return supplier.inflate(context, parent).also { mView = it }
} }
}) }).also { mWindow = it }
mUiHandler.applicationContext.startService(Intent(mUiHandler.applicationContext, FloatyService::class.java)) val r = Runnable {
context.startService(Intent(context, FloatyService::class.java))
val r = Runnable { FloatyService.addWindow(mWindow!!) } FloatyService.addWindow(window)
}
/* 如果是 UI 线程则直接创建, 否则放入 UI 线程. */ if (isUiThread()) {
if (isUiThread()) r.run() else mUiHandler.post(r) r.run()
} else {
mWindow!!.setOnCloseButtonClickListener { _ -> close() } uiHandler.post(r)
// setSize(mWindow.getWindowBridge().getScreenWidth() / 2, mWindow.getWindowBridge().getScreenHeight() / 2); window.waitForCreation()?.let { if (it != Exceptions.NO_EXCEPTION) throw it }
}
window.setOnCloseButtonClickListener { close() }
} }
fun findView(id: String?) = mView?.let { JsViewHelper.findViewByStringId(it, id) } fun findView(id: String?) = mView?.let { JsViewHelper.findViewByStringId(it, id) }
@@ -225,8 +235,11 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
} }
private fun runWithWindow(r: Runnable) { private fun runWithWindow(r: Runnable) {
mWindow ?: return when {
mUiHandler.post(r) mWindow == null -> return
isUiThread() -> r.run()
else -> uiHandler.post { mWindow?.let { r.run() } }
}
} }
fun setPosition(x: Int, y: Int) = runWithWindow { fun setPosition(x: Int, y: Int) = runWithWindow {
@@ -234,7 +247,7 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
} }
var isAdjustEnabled: Boolean var isAdjustEnabled: Boolean
get() = mWindow?.isAdjustEnabled ?: false get() = mWindow?.isAdjustEnabled == true
set(enabled) { set(enabled) {
runWithWindow { mWindow!!.isAdjustEnabled = enabled } runWithWindow { mWindow!!.isAdjustEnabled = enabled }
} }
@@ -255,7 +268,7 @@ class Floaty(private val mUiHandler: UiHandler, private val mRuntime: ScriptRunt
mWindow!!.close() mWindow!!.close()
mWindow = null mWindow = null
if (mExitOnClose) { if (mExitOnClose) {
mRuntime.exit() scriptRuntime.exit()
} }
} }
} }

View File

@@ -11,6 +11,7 @@ import org.autojs.autojs.extension.FlexibleArray
import org.autojs.autojs.extension.ScriptableExtensions.defineProp import org.autojs.autojs.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.rhino.ProxyJavaObject import org.autojs.autojs.rhino.ProxyJavaObject
import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_GETTER_KEY import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_GETTER_KEY
import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_OBJECT_KEY
import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_SETTER_KEY import org.autojs.autojs.rhino.ProxyObject.Companion.PROXY_SETTER_KEY
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.Floaty import org.autojs.autojs.runtime.api.Floaty
@@ -23,6 +24,9 @@ import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.RhinoUtils.newBaseFunction import org.autojs.autojs.util.RhinoUtils.newBaseFunction
import org.autojs.autojs.util.RhinoUtils.newNativeObject import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.autojs.autojs.util.RhinoUtils.undefined import org.autojs.autojs.util.RhinoUtils.undefined
import org.mozilla.javascript.ScriptableObject.DONTENUM
import org.mozilla.javascript.ScriptableObject.PERMANENT
import org.mozilla.javascript.ScriptableObject.READONLY
import org.mozilla.javascript.Undefined import org.mozilla.javascript.Undefined
import org.mozilla.javascript.xmlimpl.XML import org.mozilla.javascript.xmlimpl.XML
import android.content.Context as AndroidContext import android.content.Context as AndroidContext
@@ -88,7 +92,7 @@ class Floaty(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
} }
} }
private fun wrap(scriptRuntime: ScriptRuntime, windowFunction: (viewSupplier: BaseResizableFloatyWindow.ViewSupplier) -> JsWindow, xml: Any?): ProxyJavaObject { private fun wrap(scriptRuntime: ScriptRuntime, windowFunction: (supplier: BaseResizableFloatyWindow.ViewSupplier) -> JsWindow, xml: Any?): ProxyJavaObject {
require(xml is XML) { "Argument xml ${xml.jsBrief()} is invalid for Floaty#wrap" } require(xml is XML) { "Argument xml ${xml.jsBrief()} is invalid for Floaty#wrap" }
val storage = mutableMapOf<String, Any?>() val storage = mutableMapOf<String, Any?>()
val layoutInflater = scriptRuntime.ui.layoutInflater val layoutInflater = scriptRuntime.ui.layoutInflater
@@ -121,10 +125,12 @@ class Floaty(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
return UNDEFINED return UNDEFINED
} }
val proxyObject = newNativeObject().also { val proxyObject = newNativeObject().also {
it.defineProp(PROXY_GETTER_KEY, newBaseFunction(PROXY_GETTER_KEY, getter, NOT_CONSTRUCTABLE)) it.defineProp(PROXY_GETTER_KEY, newBaseFunction(PROXY_GETTER_KEY, getter, NOT_CONSTRUCTABLE), READONLY or DONTENUM or PERMANENT)
it.defineProp(PROXY_SETTER_KEY, newBaseFunction(PROXY_GETTER_KEY, setter, NOT_CONSTRUCTABLE)) it.defineProp(PROXY_SETTER_KEY, newBaseFunction(PROXY_GETTER_KEY, setter, NOT_CONSTRUCTABLE), READONLY or DONTENUM or PERMANENT)
}
return ProxyJavaObject(scriptRuntime.topLevelScope, window, window::class.java).also {
it.defineProp(PROXY_OBJECT_KEY, proxyObject, READONLY or DONTENUM or PERMANENT)
} }
return ProxyJavaObject(scriptRuntime.topLevelScope, window, proxyObject)
} }
private fun toXMLString(xml: Any) = when (xml) { private fun toXMLString(xml: Any) = when (xml) {

View File

@@ -67,6 +67,10 @@ public class ResizableFloatyWindow extends FloatyWindow {
return layoutParams; return layoutParams;
} }
protected ResizableFloaty getFloaty() {
return mFloaty;
}
public View getRootView() { public View getRootView() {
return mView; return mView;
} }

View File

@@ -1,5 +1,5 @@
#Sun Jan 12 12:30:28 CST 2025 #Sun Jan 12 23:32:51 CST 2025
BUILD_TIME=1736656228596 BUILD_TIME=1736695971805
COMPILE_SDK_VERSION=34 COMPILE_SDK_VERSION=34
JAVA_VERSION=23 JAVA_VERSION=23
JAVA_VERSION_MIN_RADICAL=0 JAVA_VERSION_MIN_RADICAL=0
@@ -17,6 +17,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=34 TARGET_SDK_VERSION=34
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=2964 VERSION_BUILD=2966
VERSION_NAME=6.6.2 Alpha VERSION_NAME=6.6.2 Alpha
VSCODE_EXT_REQUIRED_VERSION=1.0.8 VSCODE_EXT_REQUIRED_VERSION=1.0.8