gujjwal00 / avnc

VNC Client for Android
GNU General Public License v3.0
651 stars 59 forks source link

Feature Request - Send Alt+F4 key combination to remote session #258

Open elesbb opened 2 weeks ago

elesbb commented 2 weeks ago

I was using bVNC before I discovered aVNC.

I like aVNC more as it has better customization. But after pressing "ALT+F4" to close out the window in my VNC session, it closed out aVNC, as the default android behavior consumes the meta key combinations.

In bVNC, it would send the event instead of android exiting the app.

I also noticed in aVNC, when pressing "Ctrl+Shift+Left Arrow" the highlighting of text does not work, you must press Shift before ctrl or alt. In bVNC this is not the case.

Basically, it seems like aVNC does not fully consume all the events from the keyboard.

I have decompiled bVNC but can't see anything special that it does which allows the consumption of these keyevents. Would love to have those key events on aVNC consumed first as well

gujjwal00 commented 1 week ago

I tested with Hacker's Keyboard app, and AVNC correctly forwards Alt+F4 to server. I don't have access to an external keyboard right now, so can you please:

  1. Open AVNC Settings => Tools => Key test.
  2. Check the Copy automatically on exit box, and tap on the gray area.
  3. Now press 'Alt+F4'
  4. If AVNC didn't exit, manually tap the Copy button.
  5. Paste the logs here.
gujjwal00 commented 1 week ago

And please run the above mentioned test for Ctrl+Shift+Left Arrow too.

elesbb commented 2 days ago

Hello, thanks!

So I installed latest version, did the test as you asked. And it closed out AVNC. Here are the logs:

<details>
<summary>Key test</summary>
<p>

```python
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=0, eventTime=552166952000, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x88, repeatCount=1, eventTime=552568677860, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=2, eventTime=552619377131, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=3, eventTime=552670548328, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=4, eventTime=552721591558, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=5, eventTime=552772525412, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=6, eventTime=552824714787, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=7, eventTime=552875363953, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=8, eventTime=552925618641, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=9, eventTime=552977418641, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=10, eventTime=553028108589, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=11, eventTime=553079285985, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=12, eventTime=553130075516, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=13, eventTime=553180813693, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=14, eventTime=553231174735, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=15, eventTime=553281590828, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=16, eventTime=553333404682, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=17, eventTime=553384272234, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=18, eventTime=553435272912, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=19, eventTime=553485936349, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=20, eventTime=553536436870, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=21, eventTime=553587792599, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=22, eventTime=553638595047, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=23, eventTime=553689423953, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=24, eventTime=553739820724, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=25, eventTime=553790314370, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=26, eventTime=553841522599, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=27, eventTime=553892757859, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x8, repeatCount=28, eventTime=553943959161, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }
KeyEvent { action=ACTION_UP, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_ALT_ON|META_ALT_LEFT_ON, flags=0x28, repeatCount=0, eventTime=554029343380, downTime=552166952000, deviceId=11, source=0x301, displayId=-1 }

Preview text: 


Basically, F4 key is consumed by the system and not the application.

Here's the `Ctrl+Shift+Left Arrow` squence:
Key test

```python KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_CTRL_LEFT, scanCode=29, metaState=META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=0, eventTime=831789229000, downTime=831789229000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=0, eventTime=832665780000, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x88, repeatCount=1, eventTime=833068238899, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=2, eventTime=833120195044, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=3, eventTime=833170622440, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=4, eventTime=833221938638, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=5, eventTime=833273233742, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=6, eventTime=833324434732, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=7, eventTime=833375532440, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=8, eventTime=833427558326, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=9, eventTime=833477741451, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=10, eventTime=833529829419, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=11, eventTime=833580977180, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=12, eventTime=833631588169, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=13, eventTime=833682318221, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=14, eventTime=833733852023, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=15, eventTime=833784852753, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_DPAD_LEFT, scanCode=105, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=0, eventTime=833792647000, downTime=833792647000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_UP, keyCode=KEYCODE_DPAD_LEFT, scanCode=105, metaState=META_SHIFT_ON|META_ALT_ON|META_ALT_LEFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=0, eventTime=833942694000, downTime=833792647000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_UP, keyCode=KEYCODE_ALT_LEFT, scanCode=56, metaState=META_SHIFT_ON|META_SHIFT_LEFT_ON|META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=0, eventTime=834392964000, downTime=832665780000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_UP, keyCode=KEYCODE_SHIFT_LEFT, scanCode=42, metaState=META_CTRL_ON|META_CTRL_LEFT_ON, flags=0x8, repeatCount=0, eventTime=834467955000, downTime=832090056000, deviceId=11, source=0x301, displayId=-1 } KeyEvent { action=ACTION_UP, keyCode=KEYCODE_CTRL_LEFT, scanCode=29, metaState=0, flags=0x8, repeatCount=0, eventTime=834493993000, downTime=831789229000, deviceId=11, source=0x301, displayId=-1 } Preview text: ```



This one looks like the shift is not consumed (the actual key event) and sent to the server.

Thanks for looking into this!
gujjwal00 commented 1 day ago

As you said, AVNC never receives F4 key event, so it can't forward it to server. In case of Ctrl+Shift+Left Arrow, ACTION_DOWN event for Shift key is missing, so that explains why the shortcut isn't working.

These type of things usually happen due to changes made to stock Android by device manufacturers. So it may not be possible to fix these shortcuts for your device, unless there is a workaround.

Since you seem to be familiar to programming, can you run bVNC in Android Studio to figure out how it intercepts Alt+F4? You don't have to decompile bVNC, it's open source: https://github.com/iiordanov/remote-desktop-clients/

elesbb commented 1 day ago

As you said, AVNC never receives F4 key event, so it can't forward it to server. In case of Ctrl+Shift+Left Arrow, ACTION_DOWN event for Shift key is missing, so that explains why the shortcut isn't working.

Yeah I have no idea why SHIFT key down isn't being received. It seems to ignore if any of the CTRL, ALT keys are pressed before pressing shift. If I press SHIFT first, then it is fine. But that is not what I am used to lol. So I get all tripped up lmao

These type of things usually happen due to changes made to stock Android by device manufacturers. So it may not be possible to fix these shortcuts for your device, unless there is a workaround.

bVNC and Termux X11 both "properly" handle these key sequences. They work as if I were on a PC.

Since you seem to be familiar to programming, can you run bVNC in Android Studio to figure out how it intercepts Alt+F4? You don't have to decompile bVNC, it's open source: https://github.com/iiordanov/remote-desktop-clients/

https://github.com/iiordanov/remote-desktop-clients/tree/master/bVNC-app/src/main Sadly its not really open source. There is no code just an AndroidManifest.xml file. Unless I am navigating the code incorrectly on GitHub. EDIT: Can confirm, I am an idiot. Found the source: https://github.com/iiordanov/remote-desktop-clients/tree/master/bVNC However, Termux-x11 is open source, and I have been playing with their stuff. Nothing seems out of the ordinary for it in terms of the key hooks and what not. I am going to continue playing around tho and see what is so unique about it that enables the keys to be consumed by the app and not the system.

gujjwal00 commented 22 minutes ago

Let me know if you find something.