diff --git a/README.md b/README.md
index 15757fb..7085e87 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Releases on f-droid will be provided as soon as possible. ~~When there is a rele
[See this comment for links to install Termux and its plugins from Github](https://github.com/tareksander/termux-gui-python-bindings/issues/1#issuecomment-983797979).
[Protocol.md](Protocol.md) describes the Protocol used and the available functions you can use.
-[GUIProt0.proto](app/src/main/proto/GUIProt0.proto) contains teh documentation of the newer Protobuf-based protocol with more features.
+[GUIProt0.proto](app/src/main/proto/GUIProt0.proto) contains the documentation of the newer Protobuf-based protocol with more features.
If you want to use overlay windows or be able to open windows from the background, go into the app settings for Termux:GUI, open the advanced section and enable "Display over other apps".
### Features
diff --git a/TODO b/TODO
index 3568ae1..776af44 100644
--- a/TODO
+++ b/TODO
@@ -8,7 +8,10 @@ Roadmap:
- 1.0.0: !!! start semantic versioning from here !!!
[ ] switch to the new plugin system, deprecate shared uid
[ ] add more logging
+ [ ] Option for notifications to stay after the connection is closed
+ [ ] but ongoing notifications will be set to not ongoing, to allow dismissal
[ ] HardwareBuffer features
+ [ ] render thread
[ ] frame sync: signal when the Buffer is finished being written and can be used by the plugin,
and signal when the plugin finished using a buffer and the client can use it again
[ ] eventfd
@@ -21,7 +24,7 @@ Roadmap:
[ ] better framerate handling: https://developer.android.com/guide/topics/media/frame-rate
[ ] C library 1.0
[ ] add error codes from protobuf to C library
- [ ] add finishActivity
+ [x] add finishActivity
[/] finish tutorial
[ ] button in settings to save a logcat dump to a file
[?] RelativeLayout
@@ -43,21 +46,30 @@ Roadmap:
[ ] more screenshots
[ ] update description and readme
- 1.1.0
+ [ ] JSON protocol version 2 based on Protocol Buffers JSON encoding
[ ] add methods for android 12 widget api
[ ] settable margins and paddings
[ ] better dynamic RemoteViews
[ ] Stateful widgets
[ ] prepopulated collections views
[ ] material you theming
+ [ ] Quick settings tiles?
+ [ ] Have to be defined as services in the manifest, icon can probably be changed by a content provider or otherwise dynamically
+ [ ] Programs could set quick settings tiles and then listen for events on them
[ ] material design components
[ ] md2
[ ] md3
[ ] the material design theme should be the Activity theme
+ [ ] set md colors to activity colors
+ [ ] material you support
+ [ ] add a style enum to the create info message, error if a particular style isn't supported for a component.
+ Also allows more future versions of MD or custom styles, and can re-use the existing methods.
+ [ ] not for RemoteViews, these only support the plain Views
[ ] update the f-droid metadata
[ ] write a changelog
[ ] more screenshots
[ ] update description and readme
- - 1.2.0:
+ - 2.0.0:
[ ] remove shared uid
[ ] additional argument to methods that require a View: subtree: id of a ViewGroup that contains the View as a child, grandchild, ... .
The id gets looked up once and cached in a Hashmap (delete when view is removed).
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 23645f6..211a308 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -66,7 +66,9 @@
android:name=".GUIActivity"
android:configChanges="uiMode|locale|screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="false"
- android:supportsPictureInPicture="true" />
+ android:supportsPictureInPicture="true"
+ android:alwaysRetainTaskState="true"
+ android:persistableMode="persistNever"/>
, v: GUIProt0.View): OnKeyListener {
+ return OnKeyListener { _, _, event ->
+ val b = GUIProt0.KeyEvent.newBuilder()
+ b.v = v
+ b.codePoint = event.unicodeChar
+ var mod = 0
+ if (event.isShiftPressed) mod = GUIProt0.KeyEvent.Modifier.MOD_LSHIFT_VALUE or GUIProt0.KeyEvent.Modifier.MOD_RSHIFT_VALUE
+ if (event.isCtrlPressed) mod = mod or GUIProt0.KeyEvent.Modifier.MOD_LCTRL_VALUE or GUIProt0.KeyEvent.Modifier.MOD_RCTRL_VALUE
+ if (event.isAltPressed) mod = mod or GUIProt0.KeyEvent.Modifier.MOD_ALT_VALUE
+ if (event.isFunctionPressed) mod = mod or GUIProt0.KeyEvent.Modifier.MOD_FN_VALUE
+ if (event.isCapsLockOn) mod = mod or GUIProt0.KeyEvent.Modifier.MOD_CAPS_LOCK_VALUE
+ if (event.isNumLockOn) mod = mod or GUIProt0.KeyEvent.Modifier.MOD_NUM_LOCK_VALUE
+ b.modifiers = mod
+ b.code = event.keyCode
+ eventQueue.offer(GUIProt0.Event.newBuilder().setKeyEvent(b).build())
+ true
+ }
+ }
+
@SuppressLint("ClickableViewAccessibility")
fun setTouchListenerProto(v: View, aid: Int, enabled: Boolean, eventQueue: LinkedBlockingQueue) {
if (enabled) {
diff --git a/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleCreate.kt b/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleCreate.kt
index 5a20eb2..2dc7981 100644
--- a/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleCreate.kt
+++ b/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleCreate.kt
@@ -100,24 +100,17 @@ class HandleCreate(val v: V0Proto, val main: OutputStream, val activities: Mutab
}
}
+
+
fun image(m: CreateImageViewRequest) {
if (m.keyboard) {
create.createView(m) {
- it.setOnKeyListener { _, _, event ->
- val b = KeyEvent.newBuilder()
- b.codePoint = event.unicodeChar
- var mod = 0
- if (event.isShiftPressed) mod = KeyEvent.Modifier.MOD_LSHIFT_VALUE or KeyEvent.Modifier.MOD_RSHIFT_VALUE
- if (event.isCtrlPressed) mod = mod or KeyEvent.Modifier.MOD_LCTRL_VALUE or KeyEvent.Modifier.MOD_RCTRL_VALUE
- if (event.isAltPressed) mod = mod or KeyEvent.Modifier.MOD_ALT_VALUE
- if (event.isFunctionPressed) mod = mod or KeyEvent.Modifier.MOD_FN_VALUE
- if (event.isCapsLockOn) mod = mod or KeyEvent.Modifier.MOD_CAPS_LOCK_VALUE
- if (event.isNumLockOn) mod = mod or KeyEvent.Modifier.MOD_NUM_LOCK_VALUE
- b.modifiers = mod
- b.code = event.keyCode
- eventQueue.offer(Event.newBuilder().setKeyEvent(b).build())
- true
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ it.focusable = android.view.View.FOCUSABLE
+ } else {
+ it.isFocusable = true
}
+ it.setOnKeyListener(ProtoUtils.keyListener(eventQueue, View.newBuilder().setAid(m.data.aid).setId(it.id).build()))
}
} else {
create.createView(m) {}
@@ -287,7 +280,10 @@ class HandleCreate(val v: V0Proto, val main: OutputStream, val activities: Mutab
eventQueue.offer(Event.newBuilder().setFrameComplete(SurfaceViewFrameCompleteEvent.newBuilder().setV(View.newBuilder().setAid(m.data.aid).setId(it.id)).setTimestamp(timestamp)).build())
}
}
- it.keyboard = m.keyboard
+ if (m.keyboard) {
+ it.focusable = android.view.View.FOCUSABLE
+ it.setOnKeyListener(ProtoUtils.keyListener(eventQueue, View.newBuilder().setAid(m.data.aid).setId(it.id).build()))
+ }
it.setSecure(m.secure)
}
}
diff --git a/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleView.kt b/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleView.kt
index be85658..fe575ca 100644
--- a/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleView.kt
+++ b/app/src/main/java/com/termux/gui/protocol/protobuf/v0/HandleView.kt
@@ -722,7 +722,6 @@ class HandleView(val v: V0Proto, val main: OutputStream, val activities: Mutable
fun setSurfaceBuffer(m: SurfaceViewSetBufferRequest) {
- //println("setbuffer")
// setBuffer is synchronized with the rendering and so can be called from the connection thread
handler.handleViewConnectionThread(m.v, SurfaceViewSetBufferResponse.newBuilder(), { ret, v: HardwareBufferSurfaceView, _, _ ->
val b = hardwareBuffers[m.buffer]
diff --git a/app/src/main/java/com/termux/gui/protocol/shared/v0/RawInputConnection.kt b/app/src/main/java/com/termux/gui/protocol/shared/v0/RawInputConnection.kt
index 68ea2b5..4095a22 100644
--- a/app/src/main/java/com/termux/gui/protocol/shared/v0/RawInputConnection.kt
+++ b/app/src/main/java/com/termux/gui/protocol/shared/v0/RawInputConnection.kt
@@ -6,7 +6,7 @@ import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.*
-class RawInputConnection : InputConnection {
+class RawInputConnection(private val keyListener: View.OnKeyListener) : InputConnection {
override fun getTextBeforeCursor(n: Int, flags: Int): CharSequence? {
return null
@@ -81,7 +81,8 @@ class RawInputConnection : InputConnection {
}
override fun sendKeyEvent(event: KeyEvent): Boolean {
- return false
+ keyListener.onKey(null, KeyEvent.KEYCODE_UNKNOWN, event)
+ return true
}
override fun clearMetaKeyStates(states: Int): Boolean {
diff --git a/app/src/main/java/com/termux/gui/views/HardwareBufferSurfaceView.kt b/app/src/main/java/com/termux/gui/views/HardwareBufferSurfaceView.kt
index 78297ef..3a84be2 100644
--- a/app/src/main/java/com/termux/gui/views/HardwareBufferSurfaceView.kt
+++ b/app/src/main/java/com/termux/gui/views/HardwareBufferSurfaceView.kt
@@ -125,7 +125,7 @@ class HardwareBufferSurfaceView(c: Context) : SurfaceView(c), Choreographer.Fram
*/
val RENDER_LOCK = Object()
- var keyboard: Boolean = false
+ private var keyListener: OnKeyListener? = null
var surfaceChangedListener: SurfaceChangedListener? = null
var frameCallback: FrameCallbackListener? = null
var config: Config = Config()
@@ -610,15 +610,17 @@ class HardwareBufferSurfaceView(c: Context) : SurfaceView(c), Choreographer.Fram
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
- return if (keyboard) {
+ val l = keyListener
+ return if (l != null) {
outAttrs.inputType = EditorInfo.TYPE_NULL
- RawInputConnection()
+ RawInputConnection(l)
} else {
super.onCreateInputConnection(outAttrs)
}
}
override fun setOnKeyListener(l: OnKeyListener?) {
+ keyListener = l
super.setOnKeyListener(l)
}
diff --git a/app/src/main/java/com/termux/gui/views/KeyboardImageView.kt b/app/src/main/java/com/termux/gui/views/KeyboardImageView.kt
index b9acf5c..0f40ded 100644
--- a/app/src/main/java/com/termux/gui/views/KeyboardImageView.kt
+++ b/app/src/main/java/com/termux/gui/views/KeyboardImageView.kt
@@ -9,14 +9,20 @@ import com.termux.gui.protocol.shared.v0.RawInputConnection
* ImageView with InputConnection to get KeyEvents.
*/
class KeyboardImageView(c: Context) : AppCompatImageView(c) {
-
-
+ private var keyListener: OnKeyListener? = null
+
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
- outAttrs.inputType = EditorInfo.TYPE_NULL
- return RawInputConnection()
+ val l = keyListener
+ return if (l != null) {
+ outAttrs.inputType = EditorInfo.TYPE_NULL
+ RawInputConnection(l)
+ } else {
+ super.onCreateInputConnection(outAttrs)
+ }
}
-
+
override fun setOnKeyListener(l: OnKeyListener?) {
+ keyListener = l;
super.setOnKeyListener(l)
}