From 6ff16e3559223b9df959bffcae46d98360b68187 Mon Sep 17 00:00:00 2001 From: Caten Date: Mon, 4 Aug 2025 14:40:57 +0800 Subject: [PATCH] Remove the embedded AVNC and import it as a Flutter plugin --- .gitmodules | 9 - android/app/CMakeLists.txt | 114 - android/app/build.gradle | 15 +- .../com.gaurav.avnc.model.db.MainDb/1.json | 160 -- .../com.gaurav.avnc.model.db.MainDb/2.json | 188 -- .../com.gaurav.avnc.model.db.MainDb/3.json | 209 -- .../com.gaurav.avnc.model.db.MainDb/4.json | 216 -- .../com.gaurav.avnc.model.db.MainDb/5.json | 215 -- android/app/src/main/AndroidManifest.xml | 26 - .../src/main/assets/license/Apache-2.0.txt | 202 -- .../main/assets/license/BSD-libjpeg-turbo.txt | 29 - .../app/src/main/assets/license/GPL-3.0.txt | 674 ----- android/app/src/main/assets/license/X11.txt | 48 - .../app/src/main/assets/license/sshlib.txt | 87 - android/app/src/main/cpp/ClientEx.h | 87 - android/app/src/main/cpp/Cursor.h | 111 - android/app/src/main/cpp/Utility.h | 94 - android/app/src/main/cpp/native-vnc.cpp | 561 ---- .../com/example/tiny_computer/MainActivity.kt | 27 - .../kotlin/com/gaurav/avnc/model/LoginInfo.kt | 27 - .../com/gaurav/avnc/model/ServerProfile.kt | 224 -- .../kotlin/com/gaurav/avnc/model/db/MainDb.kt | 67 - .../gaurav/avnc/model/db/ServerProfileDao.kt | 55 - .../com/gaurav/avnc/ui/about/AboutActivity.kt | 53 - .../com/gaurav/avnc/ui/about/AboutFragment.kt | 53 - .../gaurav/avnc/ui/about/LibrariesFragment.kt | 86 - .../gaurav/avnc/ui/about/LicenseFragment.kt | 66 - .../gaurav/avnc/ui/prefs/ListPreferenceEx.kt | 57 - .../com/gaurav/avnc/ui/prefs/PrefsActivity.kt | 155 - .../com/gaurav/avnc/ui/vnc/Dispatcher.kt | 310 -- .../com/gaurav/avnc/ui/vnc/FrameScroller.kt | 86 - .../com/gaurav/avnc/ui/vnc/FrameState.kt | 291 -- .../com/gaurav/avnc/ui/vnc/FrameView.kt | 106 - .../com/gaurav/avnc/ui/vnc/HostKeyFragment.kt | 51 - .../avnc/ui/vnc/IntentReceiverActivity.kt | 83 - .../com/gaurav/avnc/ui/vnc/KeyHandler.kt | 386 --- .../com/gaurav/avnc/ui/vnc/LayoutManager.kt | 319 --- .../com/gaurav/avnc/ui/vnc/LoginFragment.kt | 172 -- .../kotlin/com/gaurav/avnc/ui/vnc/Toolbar.kt | 294 -- .../com/gaurav/avnc/ui/vnc/TouchHandler.kt | 543 ---- .../com/gaurav/avnc/ui/vnc/VirtualKeys.kt | 118 - .../com/gaurav/avnc/ui/vnc/VncActivity.kt | 400 --- .../kotlin/com/gaurav/avnc/ui/vnc/gl/Frame.kt | 108 - .../com/gaurav/avnc/ui/vnc/gl/FrameProgram.kt | 91 - .../com/gaurav/avnc/ui/vnc/gl/Renderer.kt | 101 - .../gaurav/avnc/ui/vnc/gl/ShaderCompiler.kt | 97 - .../com/gaurav/avnc/ui/vnc/gl/Shaders.kt | 36 - .../com/gaurav/avnc/util/AppPreferences.kt | 156 - .../kotlin/com/gaurav/avnc/util/Binding.kt | 101 - .../kotlin/com/gaurav/avnc/util/Clipboard.kt | 72 - .../kotlin/com/gaurav/avnc/util/Debugging.kt | 82 - .../com/gaurav/avnc/util/DeviceAuthPrompt.kt | 133 - .../kotlin/com/gaurav/avnc/util/LiveEvent.kt | 89 - .../com/gaurav/avnc/util/LiveRequest.kt | 55 - .../kotlin/com/gaurav/avnc/util/MsgDialog.kt | 35 - .../com/gaurav/avnc/util/OpenableDocument.kt | 23 - .../kotlin/com/gaurav/avnc/util/SamsungDex.kt | 53 - .../kotlin/com/gaurav/avnc/util/SpinnerEx.kt | 49 - .../gaurav/avnc/viewmodel/BaseViewModel.kt | 43 - .../gaurav/avnc/viewmodel/EditorViewModel.kt | 51 - .../gaurav/avnc/viewmodel/PrefsViewModel.kt | 113 - .../gaurav/avnc/viewmodel/UrlBarViewModel.kt | 22 - .../com/gaurav/avnc/viewmodel/VncViewModel.kt | 421 --- .../avnc/viewmodel/service/Discovery.kt | 191 -- .../avnc/viewmodel/service/SshTunnel.kt | 242 -- .../kotlin/com/gaurav/avnc/vnc/Messenger.kt | 102 - .../com/gaurav/avnc/vnc/PointerButton.kt | 20 - .../com/gaurav/avnc/vnc/UserCredential.kt | 17 - .../kotlin/com/gaurav/avnc/vnc/VncClient.kt | 348 --- .../main/kotlin/com/gaurav/avnc/vnc/VncUri.kt | 78 - .../kotlin/com/gaurav/avnc/vnc/XKeySym.kt | 2525 ----------------- .../com/gaurav/avnc/vnc/XKeySymAndroid.kt | 337 --- .../com/gaurav/avnc/vnc/XKeySymUnicode.kt | 819 ------ .../kotlin/com/gaurav/avnc/vnc/XTKeyCode.kt | 573 ---- .../app/src/main/res/color/control_icon.xml | 17 - .../main/res/drawable/bg_circular_button.xml | 25 - .../src/main/res/drawable/bg_frame_view.xml | 14 - .../src/main/res/drawable/bg_round_rect.xml | 16 - .../main/res/drawable/bg_toggle_button.xml | 13 - .../app/src/main/res/drawable/bg_urlbar.xml | 18 - .../src/main/res/drawable/ic_arrow_back.xml | 10 - .../app/src/main/res/drawable/ic_bookmark.xml | 9 - android/app/src/main/res/drawable/ic_bug.xml | 9 - .../app/src/main/res/drawable/ic_clear.xml | 9 - .../app/src/main/res/drawable/ic_computer.xml | 9 - .../res/drawable/ic_computer_shortcut.xml | 22 - .../app/src/main/res/drawable/ic_download.xml | 9 - .../src/main/res/drawable/ic_experimental.xml | 9 - android/app/src/main/res/drawable/ic_file.xml | 10 - .../app/src/main/res/drawable/ic_gesture.xml | 9 - .../app/src/main/res/drawable/ic_github.xml | 9 - android/app/src/main/res/drawable/ic_gpl.xml | 92 - android/app/src/main/res/drawable/ic_help.xml | 9 - android/app/src/main/res/drawable/ic_info.xml | 9 - android/app/src/main/res/drawable/ic_key.xml | 9 - .../app/src/main/res/drawable/ic_keyboard.xml | 9 - .../res/drawable/ic_keyboard_arrow_down.xml | 9 - .../res/drawable/ic_keyboard_arrow_left.xml | 9 - .../res/drawable/ic_keyboard_arrow_right.xml | 9 - .../res/drawable/ic_keyboard_arrow_up.xml | 9 - .../main/res/drawable/ic_keyboard_mini.xml | 9 - .../res/drawable/ic_launcher_background.xml | 41 - .../res/drawable/ic_launcher_foreground.xml | 46 - .../res/drawable/ic_launcher_monochrome.xml | 46 - .../src/main/res/drawable/ic_lightbulb.xml | 9 - android/app/src/main/res/drawable/ic_lock.xml | 9 - android/app/src/main/res/drawable/ic_menu.xml | 9 - .../app/src/main/res/drawable/ic_mouse.xml | 9 - .../app/src/main/res/drawable/ic_palette.xml | 9 - .../app/src/main/res/drawable/ic_password.xml | 9 - .../app/src/main/res/drawable/ic_person.xml | 9 - android/app/src/main/res/drawable/ic_plus.xml | 12 - .../app/src/main/res/drawable/ic_refresh.xml | 9 - android/app/src/main/res/drawable/ic_save.xml | 9 - .../main/res/drawable/ic_screen_rotation.xml | 9 - .../app/src/main/res/drawable/ic_search.xml | 9 - .../app/src/main/res/drawable/ic_settings.xml | 9 - .../app/src/main/res/drawable/ic_shield.xml | 9 - android/app/src/main/res/drawable/ic_ssh.xml | 17 - android/app/src/main/res/drawable/ic_star.xml | 9 - .../src/main/res/drawable/ic_super_key.xml | 9 - android/app/src/main/res/drawable/ic_swap.xml | 12 - .../src/main/res/drawable/ic_toggle_more.xml | 12 - .../app/src/main/res/drawable/ic_toolbar.xml | 17 - .../app/src/main/res/drawable/ic_tools.xml | 12 - .../app/src/main/res/drawable/ic_upload.xml | 9 - .../app/src/main/res/drawable/ic_video.xml | 10 - .../src/main/res/drawable/ic_visibility.xml | 9 - .../app/src/main/res/drawable/ic_warning.xml | 9 - .../app/src/main/res/drawable/ic_wordmark.xml | 114 - .../app/src/main/res/drawable/ic_zoom_in.xml | 12 - .../src/main/res/drawable/ic_zoom_options.xml | 9 - .../src/main/res/drawable/ic_zoom_reset.xml | 9 - .../app/src/main/res/drawable/indicator.xml | 15 - .../src/main/res/layout/activity_about.xml | 37 - .../src/main/res/layout/activity_settings.xml | 29 - .../app/src/main/res/layout/activity_vnc.xml | 157 - .../src/main/res/layout/fragment_about.xml | 64 - .../main/res/layout/fragment_credential.xml | 87 - .../main/res/layout/fragment_libraries.xml | 59 - .../src/main/res/layout/fragment_license.xml | 71 - .../res/layout/fragment_profile_editor.xml | 89 - .../fragment_profile_editor_advanced.xml | 459 --- android/app/src/main/res/layout/help_btn.xml | 15 - .../main/res/layout/server_discovery_item.xml | 35 - .../app/src/main/res/layout/server_item.xml | 98 - .../src/main/res/layout/toolbar_drawer.xml | 139 - .../app/src/main/res/layout/virtual_keys.xml | 258 -- android/app/src/main/res/mipmap-hdpi/avnc.png | Bin 4881 -> 0 bytes .../src/main/res/values-zh-rCN/strings.xml | 197 -- .../src/main/res/values-zh-rTW/strings.xml | 194 -- android/app/src/main/res/values/arrays.xml | 185 -- android/app/src/main/res/values/colors.xml | 12 - android/app/src/main/res/values/dimens.xml | 21 - android/app/src/main/res/values/strings.xml | 208 -- android/app/src/main/res/values/styles.xml | 144 - .../app/src/main/res/xml/pref_appearance.xml | 20 - android/app/src/main/res/xml/pref_input.xml | 162 -- android/app/src/main/res/xml/pref_main.xml | 36 - android/app/src/main/res/xml/pref_server.xml | 23 - android/app/src/main/res/xml/pref_viewer.xml | 89 - android/extern/libjpeg-turbo | 1 - android/extern/libvncserver | 1 - android/extern/wolfssl | 1 - lib/main.dart | 6 +- lib/workflow.dart | 4 +- pubspec.lock | 9 + pubspec.yaml | 4 + 168 files changed, 21 insertions(+), 18086 deletions(-) delete mode 100644 android/app/CMakeLists.txt delete mode 100644 android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/1.json delete mode 100644 android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/2.json delete mode 100644 android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/3.json delete mode 100644 android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/4.json delete mode 100644 android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/5.json delete mode 100644 android/app/src/main/assets/license/Apache-2.0.txt delete mode 100644 android/app/src/main/assets/license/BSD-libjpeg-turbo.txt delete mode 100644 android/app/src/main/assets/license/GPL-3.0.txt delete mode 100644 android/app/src/main/assets/license/X11.txt delete mode 100644 android/app/src/main/assets/license/sshlib.txt delete mode 100644 android/app/src/main/cpp/ClientEx.h delete mode 100644 android/app/src/main/cpp/Cursor.h delete mode 100644 android/app/src/main/cpp/Utility.h delete mode 100644 android/app/src/main/cpp/native-vnc.cpp delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/model/LoginInfo.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/model/ServerProfile.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/model/db/MainDb.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/model/db/ServerProfileDao.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutActivity.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutFragment.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LibrariesFragment.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LicenseFragment.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/ListPreferenceEx.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/PrefsActivity.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Dispatcher.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameScroller.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameState.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameView.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/HostKeyFragment.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/IntentReceiverActivity.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/KeyHandler.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LayoutManager.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LoginFragment.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Toolbar.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/TouchHandler.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VirtualKeys.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VncActivity.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Frame.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/FrameProgram.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Renderer.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/ShaderCompiler.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Shaders.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/AppPreferences.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/Binding.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/Clipboard.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/Debugging.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/DeviceAuthPrompt.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/LiveEvent.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/LiveRequest.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/MsgDialog.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/OpenableDocument.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/SamsungDex.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/util/SpinnerEx.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/BaseViewModel.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/EditorViewModel.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/PrefsViewModel.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/UrlBarViewModel.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/VncViewModel.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/Discovery.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/SshTunnel.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/Messenger.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/PointerButton.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/UserCredential.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncClient.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncUri.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySym.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymAndroid.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymUnicode.kt delete mode 100644 android/app/src/main/kotlin/com/gaurav/avnc/vnc/XTKeyCode.kt delete mode 100644 android/app/src/main/res/color/control_icon.xml delete mode 100644 android/app/src/main/res/drawable/bg_circular_button.xml delete mode 100644 android/app/src/main/res/drawable/bg_frame_view.xml delete mode 100644 android/app/src/main/res/drawable/bg_round_rect.xml delete mode 100644 android/app/src/main/res/drawable/bg_toggle_button.xml delete mode 100644 android/app/src/main/res/drawable/bg_urlbar.xml delete mode 100644 android/app/src/main/res/drawable/ic_arrow_back.xml delete mode 100644 android/app/src/main/res/drawable/ic_bookmark.xml delete mode 100644 android/app/src/main/res/drawable/ic_bug.xml delete mode 100644 android/app/src/main/res/drawable/ic_clear.xml delete mode 100644 android/app/src/main/res/drawable/ic_computer.xml delete mode 100644 android/app/src/main/res/drawable/ic_computer_shortcut.xml delete mode 100644 android/app/src/main/res/drawable/ic_download.xml delete mode 100644 android/app/src/main/res/drawable/ic_experimental.xml delete mode 100644 android/app/src/main/res/drawable/ic_file.xml delete mode 100644 android/app/src/main/res/drawable/ic_gesture.xml delete mode 100644 android/app/src/main/res/drawable/ic_github.xml delete mode 100644 android/app/src/main/res/drawable/ic_gpl.xml delete mode 100644 android/app/src/main/res/drawable/ic_help.xml delete mode 100644 android/app/src/main/res/drawable/ic_info.xml delete mode 100644 android/app/src/main/res/drawable/ic_key.xml delete mode 100644 android/app/src/main/res/drawable/ic_keyboard.xml delete mode 100644 android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml delete mode 100644 android/app/src/main/res/drawable/ic_keyboard_arrow_left.xml delete mode 100644 android/app/src/main/res/drawable/ic_keyboard_arrow_right.xml delete mode 100644 android/app/src/main/res/drawable/ic_keyboard_arrow_up.xml delete mode 100644 android/app/src/main/res/drawable/ic_keyboard_mini.xml delete mode 100644 android/app/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 android/app/src/main/res/drawable/ic_launcher_foreground.xml delete mode 100644 android/app/src/main/res/drawable/ic_launcher_monochrome.xml delete mode 100644 android/app/src/main/res/drawable/ic_lightbulb.xml delete mode 100644 android/app/src/main/res/drawable/ic_lock.xml delete mode 100644 android/app/src/main/res/drawable/ic_menu.xml delete mode 100644 android/app/src/main/res/drawable/ic_mouse.xml delete mode 100644 android/app/src/main/res/drawable/ic_palette.xml delete mode 100644 android/app/src/main/res/drawable/ic_password.xml delete mode 100644 android/app/src/main/res/drawable/ic_person.xml delete mode 100644 android/app/src/main/res/drawable/ic_plus.xml delete mode 100644 android/app/src/main/res/drawable/ic_refresh.xml delete mode 100644 android/app/src/main/res/drawable/ic_save.xml delete mode 100644 android/app/src/main/res/drawable/ic_screen_rotation.xml delete mode 100644 android/app/src/main/res/drawable/ic_search.xml delete mode 100644 android/app/src/main/res/drawable/ic_settings.xml delete mode 100644 android/app/src/main/res/drawable/ic_shield.xml delete mode 100644 android/app/src/main/res/drawable/ic_ssh.xml delete mode 100644 android/app/src/main/res/drawable/ic_star.xml delete mode 100644 android/app/src/main/res/drawable/ic_super_key.xml delete mode 100644 android/app/src/main/res/drawable/ic_swap.xml delete mode 100644 android/app/src/main/res/drawable/ic_toggle_more.xml delete mode 100644 android/app/src/main/res/drawable/ic_toolbar.xml delete mode 100644 android/app/src/main/res/drawable/ic_tools.xml delete mode 100644 android/app/src/main/res/drawable/ic_upload.xml delete mode 100644 android/app/src/main/res/drawable/ic_video.xml delete mode 100644 android/app/src/main/res/drawable/ic_visibility.xml delete mode 100644 android/app/src/main/res/drawable/ic_warning.xml delete mode 100644 android/app/src/main/res/drawable/ic_wordmark.xml delete mode 100644 android/app/src/main/res/drawable/ic_zoom_in.xml delete mode 100644 android/app/src/main/res/drawable/ic_zoom_options.xml delete mode 100644 android/app/src/main/res/drawable/ic_zoom_reset.xml delete mode 100644 android/app/src/main/res/drawable/indicator.xml delete mode 100644 android/app/src/main/res/layout/activity_about.xml delete mode 100644 android/app/src/main/res/layout/activity_settings.xml delete mode 100644 android/app/src/main/res/layout/activity_vnc.xml delete mode 100644 android/app/src/main/res/layout/fragment_about.xml delete mode 100644 android/app/src/main/res/layout/fragment_credential.xml delete mode 100644 android/app/src/main/res/layout/fragment_libraries.xml delete mode 100644 android/app/src/main/res/layout/fragment_license.xml delete mode 100644 android/app/src/main/res/layout/fragment_profile_editor.xml delete mode 100644 android/app/src/main/res/layout/fragment_profile_editor_advanced.xml delete mode 100644 android/app/src/main/res/layout/help_btn.xml delete mode 100644 android/app/src/main/res/layout/server_discovery_item.xml delete mode 100644 android/app/src/main/res/layout/server_item.xml delete mode 100644 android/app/src/main/res/layout/toolbar_drawer.xml delete mode 100644 android/app/src/main/res/layout/virtual_keys.xml delete mode 100644 android/app/src/main/res/mipmap-hdpi/avnc.png delete mode 100644 android/app/src/main/res/values-zh-rTW/strings.xml delete mode 100644 android/app/src/main/res/values/colors.xml delete mode 100644 android/app/src/main/res/values/dimens.xml delete mode 100644 android/app/src/main/res/xml/pref_appearance.xml delete mode 100644 android/app/src/main/res/xml/pref_input.xml delete mode 100644 android/app/src/main/res/xml/pref_main.xml delete mode 100644 android/app/src/main/res/xml/pref_server.xml delete mode 100644 android/app/src/main/res/xml/pref_viewer.xml delete mode 160000 android/extern/libjpeg-turbo delete mode 160000 android/extern/libvncserver delete mode 160000 android/extern/wolfssl diff --git a/.gitmodules b/.gitmodules index 0cbcc36..3d3782c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,3 @@ -[submodule "android/extern/libvncserver"] - path = android/extern/libvncserver - url = https://github.com/gujjwal00/libvncserver.git -[submodule "android/extern/libjpeg-turbo"] - path = android/extern/libjpeg-turbo - url = https://github.com/libjpeg-turbo/libjpeg-turbo.git -[submodule "android/extern/wolfssl"] - path = android/extern/wolfssl - url = https://github.com/wolfSSL/wolfssl.git [submodule "android/app/src/main/cpp/libtirpc"] path = android/app/src/main/cpp/libtirpc url = https://github.com/alisw/libtirpc diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt deleted file mode 100644 index 8816bf9..0000000 --- a/android/app/CMakeLists.txt +++ /dev/null @@ -1,114 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(NativeVNC C CXX ASM) - -set(AVNC_EXTERN_DIR ${PROJECT_SOURCE_DIR}/../extern) -set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared Libs" FORCE) - -############################################################################### -# Utilities -############################################################################### - -# Make sure given submodule is checked out -macro(avnc_check_submodule name) - if (NOT EXISTS "${AVNC_EXTERN_DIR}/${name}/CMakeLists.txt") - message(FATAL_ERROR "git submodule for ${name} is not initialized. Please run 'git submodule update --init'.") - endif () -endmacro() - -# Required to enable SIMD support on ARM -if (CMAKE_ANDROID_ARCH STREQUAL "arm64") - set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --target=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}") -elseif (CMAKE_ANDROID_ARCH STREQUAL "arm") - set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} --target=arm-linux-androideabi${ANDROID_NATIVE_API_LEVEL}") -endif () - -############################################################################### -# JPEG -############################################################################### -avnc_check_submodule(libjpeg-turbo) - -set(AVNC_LIBJPEG_SRC_DIR ${AVNC_EXTERN_DIR}/libjpeg-turbo) -set(AVNC_LIBJPEG_BUILD_DIR ${CMAKE_BINARY_DIR}/libjpeg-turbo) - -add_subdirectory(${AVNC_LIBJPEG_SRC_DIR} ${AVNC_LIBJPEG_BUILD_DIR}) - -# Set these variables so FindJPEG can find the library -set(JPEG_LIBRARY ${AVNC_LIBJPEG_BUILD_DIR}/libturbojpeg.a) - -# Create an interface library to manage include directories -add_library(libjpeg INTERFACE) -target_include_directories(libjpeg INTERFACE ${AVNC_LIBJPEG_SRC_DIR}) - -############################################################################### -# SSL -############################################################################### -avnc_check_submodule(wolfssl) - -set(AVNC_LIBSSL_SRC_DIR ${AVNC_EXTERN_DIR}/wolfssl) -set(AVNC_LIBSSL_BUILD_DIR ${CMAKE_BINARY_DIR}/wolfssl) - -# CMake support in wolfSSl is still under development, so we have to -# manually set some flags to enable OpenSSL compatibility layer -set(WOLFSSL_CRL yes) -set(WOLFSSL_DES3 yes) -set(WOLFSSL_CRYPT_TESTS no) -add_definitions(-DOPENSSL_ALL -DOPENSSL_EXTRA -DHAVE_CRL -DHAVE_EX_DATA - -DHAVE_ANON -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB -DWOLFSSL_DES_ECB - -DWC_NO_HARDEN) - -add_subdirectory(${AVNC_LIBSSL_SRC_DIR} ${AVNC_LIBSSL_BUILD_DIR}) - -# Create an interface library to manage include directories -add_library(libssl INTERFACE) -target_include_directories(libssl INTERFACE ${AVNC_LIBSSL_SRC_DIR}/wolfssl) - -############################################################################### -# LibVNC -############################################################################### -avnc_check_submodule(libvncserver) - -set(AVNC_LIBVNC_SRC_DIR ${AVNC_EXTERN_DIR}/libvncserver) -set(AVNC_LIBVNC_BUILD_DIR ${CMAKE_BINARY_DIR}/libvncserver) - -add_subdirectory(${AVNC_LIBVNC_SRC_DIR} ${AVNC_LIBVNC_BUILD_DIR}) - -# Create an interface library to manage include directories -add_library(libvnc INTERFACE) -target_include_directories(libvnc INTERFACE ${AVNC_LIBVNC_SRC_DIR}/include ${AVNC_LIBVNC_BUILD_DIR}/include) - -############################################################################### -# Native VNC -# -# It contains implementation of JNI native methods, some NDK scaffolding and -# some helpers for OpenGL ES rendering. This is the library loaded from Java. -############################################################################### -set(AVNC_NATIVE_SOURCE src/main/cpp/native-vnc.cpp) - -add_library(native-vnc SHARED ${AVNC_NATIVE_SOURCE}) - -# Link libraries -target_link_libraries(native-vnc - PRIVATE - libjpeg - libssl - libvnc - vncclient -) - -# Link NDK libraries -find_library(LIB_LOG log) -find_library(LIB_GLES GLESv2) - -target_link_libraries(native-vnc - PRIVATE - ${LIB_LOG} - ${LIB_GLES} -) - -############################################################################### -# Termux X11 -# -############################################################################### -set(X11_EXTERN_DIR ${PROJECT_SOURCE_DIR}/src/main/cpp) -add_subdirectory(${X11_EXTERN_DIR}) \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 3699760..de049b7 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -57,12 +57,6 @@ android { buildConfigField "String", "COMMIT", "\"" + ("git rev-parse HEAD\n".execute().getText().trim() ?: (System.getenv('CURRENT_COMMIT') ?: "NO_COMMIT")) + "\"" - javaCompileOptions { - annotationProcessorOptions { - arguments += ["room.schemaLocation": "$projectDir/roomSchema/".toString()] - } - } - } buildTypes { @@ -98,7 +92,7 @@ android { externalNativeBuild { cmake { version '3.22.1' - path file('CMakeLists.txt') + path file('src/main/cpp/CMakeLists.txt') } } @@ -131,13 +125,6 @@ dependencies { implementation "androidx.dynamicanimation:dynamicanimation:1.0.0" implementation "androidx.biometric:biometric-ktx:1.2.0-alpha05" implementation "androidx.recyclerview:recyclerview:1.2.1" - - - def roomVersion = "2.6.1" - implementation "androidx.room:room-runtime:$roomVersion" - implementation "androidx.room:room-ktx:$roomVersion" - kapt "androidx.room:room-compiler:$roomVersion" - implementation "com.google.android.material:material:1.11.0" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0" diff --git a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/1.json b/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/1.json deleted file mode 100644 index 59449e7..0000000 --- a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/1.json +++ /dev/null @@ -1,160 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 1, - "identityHash": "ccb0ad6d8acbefcb44a49c07f353adc8", - "entities": [ - { - "tableName": "profiles", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `keyCompatMode` INTEGER NOT NULL, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "ID", - "columnName": "ID", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "host", - "columnName": "host", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "port", - "columnName": "port", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "username", - "columnName": "username", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "securityType", - "columnName": "securityType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "channelType", - "columnName": "channelType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "colorLevel", - "columnName": "colorLevel", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "imageQuality", - "columnName": "imageQuality", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "viewOnly", - "columnName": "viewOnly", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useLocalCursor", - "columnName": "useLocalCursor", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "keyCompatMode", - "columnName": "keyCompatMode", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useRepeater", - "columnName": "useRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "idOnRepeater", - "columnName": "idOnRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshHost", - "columnName": "sshHost", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPort", - "columnName": "sshPort", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshUsername", - "columnName": "sshUsername", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshAuthType", - "columnName": "sshAuthType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshPassword", - "columnName": "sshPassword", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKey", - "columnName": "sshPrivateKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKeyPassword", - "columnName": "sshPrivateKeyPassword", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "ID" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - } - ], - "views": [], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'ccb0ad6d8acbefcb44a49c07f353adc8')" - ] - } -} \ No newline at end of file diff --git a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/2.json b/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/2.json deleted file mode 100644 index 8b3b6de..0000000 --- a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/2.json +++ /dev/null @@ -1,188 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 2, - "identityHash": "d54a9ffbaa53dfe8f4ce8f5708a719ae", - "entities": [ - { - "tableName": "profiles", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `keyCompatMode` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "ID", - "columnName": "ID", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "host", - "columnName": "host", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "port", - "columnName": "port", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "username", - "columnName": "username", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "securityType", - "columnName": "securityType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "channelType", - "columnName": "channelType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "colorLevel", - "columnName": "colorLevel", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "imageQuality", - "columnName": "imageQuality", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useRawEncoding", - "columnName": "useRawEncoding", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "zoom1", - "columnName": "zoom1", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "zoom2", - "columnName": "zoom2", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "viewOnly", - "columnName": "viewOnly", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useLocalCursor", - "columnName": "useLocalCursor", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "keyCompatMode", - "columnName": "keyCompatMode", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "gestureStyle", - "columnName": "gestureStyle", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "useRepeater", - "columnName": "useRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "idOnRepeater", - "columnName": "idOnRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshHost", - "columnName": "sshHost", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPort", - "columnName": "sshPort", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshUsername", - "columnName": "sshUsername", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshAuthType", - "columnName": "sshAuthType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshPassword", - "columnName": "sshPassword", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKey", - "columnName": "sshPrivateKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKeyPassword", - "columnName": "sshPrivateKeyPassword", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "ID" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - } - ], - "views": [], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd54a9ffbaa53dfe8f4ce8f5708a719ae')" - ] - } -} \ No newline at end of file diff --git a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/3.json b/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/3.json deleted file mode 100644 index 97c4878..0000000 --- a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/3.json +++ /dev/null @@ -1,209 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 3, - "identityHash": "eb32c7692bb75a6297413b807713616c", - "entities": [ - { - "tableName": "profiles", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `serverTypeHint` TEXT NOT NULL DEFAULT '', `compatFlags` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `screenOrientation` TEXT NOT NULL DEFAULT 'auto', `shortcutRank` INTEGER NOT NULL DEFAULT 0, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "ID", - "columnName": "ID", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "host", - "columnName": "host", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "port", - "columnName": "port", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "username", - "columnName": "username", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "securityType", - "columnName": "securityType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "channelType", - "columnName": "channelType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "colorLevel", - "columnName": "colorLevel", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "imageQuality", - "columnName": "imageQuality", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useRawEncoding", - "columnName": "useRawEncoding", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "zoom1", - "columnName": "zoom1", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "zoom2", - "columnName": "zoom2", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "viewOnly", - "columnName": "viewOnly", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useLocalCursor", - "columnName": "useLocalCursor", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "serverTypeHint", - "columnName": "serverTypeHint", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "fieldPath": "compatFlags", - "columnName": "compatFlags", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "gestureStyle", - "columnName": "gestureStyle", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "screenOrientation", - "columnName": "screenOrientation", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "shortcutRank", - "columnName": "shortcutRank", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "useRepeater", - "columnName": "useRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "idOnRepeater", - "columnName": "idOnRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshHost", - "columnName": "sshHost", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPort", - "columnName": "sshPort", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshUsername", - "columnName": "sshUsername", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshAuthType", - "columnName": "sshAuthType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshPassword", - "columnName": "sshPassword", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKey", - "columnName": "sshPrivateKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKeyPassword", - "columnName": "sshPrivateKeyPassword", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "ID" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - } - ], - "views": [], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'eb32c7692bb75a6297413b807713616c')" - ] - } -} \ No newline at end of file diff --git a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/4.json b/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/4.json deleted file mode 100644 index b449cdb..0000000 --- a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/4.json +++ /dev/null @@ -1,216 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 4, - "identityHash": "5ff9de8e52fb13b10ee86f9c75714cd5", - "entities": [ - { - "tableName": "profiles", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `serverTypeHint` TEXT NOT NULL DEFAULT '', `compatFlags` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `screenOrientation` TEXT NOT NULL DEFAULT 'auto', `shortcutRank` INTEGER NOT NULL DEFAULT 0, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `resizeRemoteDesktop` INTEGER NOT NULL DEFAULT 0, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "ID", - "columnName": "ID", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "host", - "columnName": "host", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "port", - "columnName": "port", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "username", - "columnName": "username", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "securityType", - "columnName": "securityType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "channelType", - "columnName": "channelType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "colorLevel", - "columnName": "colorLevel", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "imageQuality", - "columnName": "imageQuality", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useRawEncoding", - "columnName": "useRawEncoding", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "zoom1", - "columnName": "zoom1", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "zoom2", - "columnName": "zoom2", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "viewOnly", - "columnName": "viewOnly", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useLocalCursor", - "columnName": "useLocalCursor", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "serverTypeHint", - "columnName": "serverTypeHint", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "fieldPath": "compatFlags", - "columnName": "compatFlags", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "gestureStyle", - "columnName": "gestureStyle", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "screenOrientation", - "columnName": "screenOrientation", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "shortcutRank", - "columnName": "shortcutRank", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "useRepeater", - "columnName": "useRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "idOnRepeater", - "columnName": "idOnRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "resizeRemoteDesktop", - "columnName": "resizeRemoteDesktop", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "sshHost", - "columnName": "sshHost", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPort", - "columnName": "sshPort", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshUsername", - "columnName": "sshUsername", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshAuthType", - "columnName": "sshAuthType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshPassword", - "columnName": "sshPassword", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKey", - "columnName": "sshPrivateKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKeyPassword", - "columnName": "sshPrivateKeyPassword", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "columnNames": [ - "ID" - ], - "autoGenerate": true - }, - "indices": [], - "foreignKeys": [] - } - ], - "views": [], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5ff9de8e52fb13b10ee86f9c75714cd5')" - ] - } -} \ No newline at end of file diff --git a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/5.json b/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/5.json deleted file mode 100644 index f705366..0000000 --- a/android/app/roomSchema/com.gaurav.avnc.model.db.MainDb/5.json +++ /dev/null @@ -1,215 +0,0 @@ -{ - "formatVersion": 1, - "database": { - "version": 5, - "identityHash": "8448d51fc9838e5760b91d4b5318ade2", - "entities": [ - { - "tableName": "profiles", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `host` TEXT NOT NULL, `port` INTEGER NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, `securityType` INTEGER NOT NULL, `channelType` INTEGER NOT NULL, `colorLevel` INTEGER NOT NULL, `imageQuality` INTEGER NOT NULL, `useRawEncoding` INTEGER NOT NULL DEFAULT 0, `zoom1` REAL NOT NULL DEFAULT 1.0, `zoom2` REAL NOT NULL DEFAULT 1.0, `viewOnly` INTEGER NOT NULL, `useLocalCursor` INTEGER NOT NULL, `serverTypeHint` TEXT NOT NULL DEFAULT '', `flags` INTEGER NOT NULL, `gestureStyle` TEXT NOT NULL DEFAULT 'auto', `screenOrientation` TEXT NOT NULL DEFAULT 'auto', `useCount` INTEGER NOT NULL, `useRepeater` INTEGER NOT NULL, `idOnRepeater` INTEGER NOT NULL, `resizeRemoteDesktop` INTEGER NOT NULL DEFAULT 0, `sshHost` TEXT NOT NULL, `sshPort` INTEGER NOT NULL, `sshUsername` TEXT NOT NULL, `sshAuthType` INTEGER NOT NULL, `sshPassword` TEXT NOT NULL, `sshPrivateKey` TEXT NOT NULL, `sshPrivateKeyPassword` TEXT NOT NULL)", - "fields": [ - { - "fieldPath": "ID", - "columnName": "ID", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "name", - "columnName": "name", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "host", - "columnName": "host", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "port", - "columnName": "port", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "username", - "columnName": "username", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "password", - "columnName": "password", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "securityType", - "columnName": "securityType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "channelType", - "columnName": "channelType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "colorLevel", - "columnName": "colorLevel", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "imageQuality", - "columnName": "imageQuality", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useRawEncoding", - "columnName": "useRawEncoding", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "zoom1", - "columnName": "zoom1", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "zoom2", - "columnName": "zoom2", - "affinity": "REAL", - "notNull": true, - "defaultValue": "1.0" - }, - { - "fieldPath": "viewOnly", - "columnName": "viewOnly", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useLocalCursor", - "columnName": "useLocalCursor", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "serverTypeHint", - "columnName": "serverTypeHint", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "''" - }, - { - "fieldPath": "flags", - "columnName": "flags", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "gestureStyle", - "columnName": "gestureStyle", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "screenOrientation", - "columnName": "screenOrientation", - "affinity": "TEXT", - "notNull": true, - "defaultValue": "'auto'" - }, - { - "fieldPath": "useCount", - "columnName": "useCount", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "useRepeater", - "columnName": "useRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "idOnRepeater", - "columnName": "idOnRepeater", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "resizeRemoteDesktop", - "columnName": "resizeRemoteDesktop", - "affinity": "INTEGER", - "notNull": true, - "defaultValue": "0" - }, - { - "fieldPath": "sshHost", - "columnName": "sshHost", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPort", - "columnName": "sshPort", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshUsername", - "columnName": "sshUsername", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshAuthType", - "columnName": "sshAuthType", - "affinity": "INTEGER", - "notNull": true - }, - { - "fieldPath": "sshPassword", - "columnName": "sshPassword", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKey", - "columnName": "sshPrivateKey", - "affinity": "TEXT", - "notNull": true - }, - { - "fieldPath": "sshPrivateKeyPassword", - "columnName": "sshPrivateKeyPassword", - "affinity": "TEXT", - "notNull": true - } - ], - "primaryKey": { - "autoGenerate": true, - "columnNames": [ - "ID" - ] - }, - "indices": [], - "foreignKeys": [] - } - ], - "views": [], - "setupQueries": [ - "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8448d51fc9838e5760b91d4b5318ade2')" - ] - } -} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8b722d7..e7a5e8a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -46,32 +46,6 @@ - - - - - - - - - - - - - - - - -Copyright (C)2015 Viktor Szathmáry. All Rights Reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -- Neither the name of the libjpeg-turbo Project nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/android/app/src/main/assets/license/GPL-3.0.txt b/android/app/src/main/assets/license/GPL-3.0.txt deleted file mode 100644 index f288702..0000000 --- a/android/app/src/main/assets/license/GPL-3.0.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/android/app/src/main/assets/license/X11.txt b/android/app/src/main/assets/license/X11.txt deleted file mode 100644 index cc24f6e..0000000 --- a/android/app/src/main/assets/license/X11.txt +++ /dev/null @@ -1,48 +0,0 @@ - -/*********************************************************** -Copyright 1987, 1994, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - - ******************************************************************/ diff --git a/android/app/src/main/assets/license/sshlib.txt b/android/app/src/main/assets/license/sshlib.txt deleted file mode 100644 index 078da66..0000000 --- a/android/app/src/main/assets/license/sshlib.txt +++ /dev/null @@ -1,87 +0,0 @@ -Copyright (c) 2007-2008 Trilead AG (http://www.trilead.com) - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -a.) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -b.) Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -c.) Neither the name of Trilead nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -Trilead SSH-2 for Java includes code that was written by Dr. Christian Plattner -during his PhD at ETH Zurich. The license states the following: - -Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich), - Department of Computer Science (http://www.inf.ethz.ch), - Christian Plattner. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -a.) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -b.) Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -c.) Neither the name of ETH Zurich nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -The Java implementations of the AES, Blowfish and 3DES ciphers have been -taken (and slightly modified) from the cryptography package released by -"The Legion Of The Bouncy Castle". - -Their license states the following: - -Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle -(http://www.bouncycastle.org) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/android/app/src/main/cpp/ClientEx.h b/android/app/src/main/cpp/ClientEx.h deleted file mode 100644 index 5019fad..0000000 --- a/android/app/src/main/cpp/ClientEx.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -#ifndef AVNC_CLIENTEX_H -#define AVNC_CLIENTEX_H - -#include -#include "Cursor.h" - -/** - * We attach some additional data to every rfbClient. - * ClientEx is used as wrapper for this data. - */ -struct ClientEx { - // Reference to managed `VncClient` - jobject managedClient; - - // Although frame width & height are maintained in rfbClient, those values - // are modified before our MallocFrameBuffer callback is triggered, and - // we cannot protect them with a mutex. So we maintain the framebuffer - // size here, protected with fbMutex. - int fbRealWidth; - int fbRealHeight; - - // Cursor data used for client-side cursor rendering - Cursor *cursor; - - // Protects modification to framebuffer & cursor - MUTEX(mutex); -}; - -const int ClientExTag = 1; - -ClientEx *getClientExtension(rfbClient *client) { - return (ClientEx *) rfbClientGetClientData(client, (void *) &ClientExTag); -} - -void setClientExtension(rfbClient *client, ClientEx *ex) { - rfbClientSetClientData(client, (void *) &ClientExTag, ex); -} - -/** - * Returns reference to managed `VncClient` associated with given rfbClient. - */ -jobject getManagedClient(rfbClient *client) { - return getClientExtension(client)->managedClient; -} - -/** - * Associate given rfbClient & managed `VncClient`. - */ -void setManagedClient(rfbClient *client, jobject managedClient) { - getClientExtension(client)->managedClient = managedClient; -} - -/** - * Create new ClientEx and assign it to given client. - */ -ClientEx *assignClientExtension(rfbClient *client) { - auto ex = (ClientEx *) malloc(sizeof(ClientEx)); - if (ex) { - INIT_MUTEX(ex->mutex); - ex->cursor = nullptr; - setClientExtension(client, ex); - } - return ex; -} - -/** - * Free all resources related to client extension. - */ -void freeClientExtension(rfbClient *client) { - auto ex = getClientExtension(client); - if (ex) { - TINI_MUTEX(ex->mutex); - freeCursor(ex->cursor); - free(ex); - setClientExtension(client, nullptr); - } -} - -#endif //AVNC_CLIENTEX_H diff --git a/android/app/src/main/cpp/Cursor.h b/android/app/src/main/cpp/Cursor.h deleted file mode 100644 index 18d308f..0000000 --- a/android/app/src/main/cpp/Cursor.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -#ifndef AVNC_CURSOR_H -#define AVNC_CURSOR_H - - -/****************************************************************************** - * Some servers (e.g TigerVNC) may not send the cursor immediately after - * connection. To provide consistent experience to users, we use a default - * cursor as fallback. - *****************************************************************************/ - -const uint16_t DefaultCursorWidth = 10; -const uint16_t DefaultCursorHeight = 16; -const uint16_t DefaultCursorXHot = 1; -const uint16_t DefaultCursorYHot = 1; - -const uint32_t DefaultCursorBuffer[DefaultCursorWidth * DefaultCursorHeight] - = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, - 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, - 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, - 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, - 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, - 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, - 0x00FFFFFF, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0x00FFFFFF, 0x00FFFFFF, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0}; - -const uint8_t DefaultCursorMask[DefaultCursorWidth * DefaultCursorHeight] - = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}; - - -/****************************************************************************** - * Cursor management - *****************************************************************************/ - -/** - * Wrapper for cursor information. - * - * rfbClient struct does not maintain all cursor related information inside it. - * Things like xHot, yHot are passed only via the cursor shape callback. - * This wrapper holds all information necessary to render the cursor. - */ -struct Cursor { - uint8_t *buffer; - uint8_t *mask; - uint8_t *scratchBuffer; //Used during rendering - uint16_t width; - uint16_t height; - uint16_t xHot; - uint16_t yHot; -}; - -//Only 4-byte pixels are currently supported -const uint8_t PixelBytes = 4; - -/** - * Creates a new CursorData, initialized with default cursor info. - */ -Cursor *newCursor() { - auto cursor = (Cursor *) malloc(sizeof(Cursor)); - if (cursor) { - cursor->buffer = (uint8_t *) DefaultCursorBuffer; - cursor->mask = (uint8_t *) DefaultCursorMask; - cursor->scratchBuffer = (uint8_t *) malloc(DefaultCursorWidth * DefaultCursorHeight * PixelBytes); - cursor->width = DefaultCursorWidth; - cursor->height = DefaultCursorHeight; - cursor->xHot = DefaultCursorXHot; - cursor->yHot = DefaultCursorYHot; - } - return cursor; -} - -void freeCursorBuffers(Cursor *cursor) { - if (cursor) { - free(cursor->scratchBuffer); - if (cursor->buffer != (uint8_t *) DefaultCursorBuffer) free(cursor->buffer); - if (cursor->mask != (uint8_t *) DefaultCursorMask) free(cursor->mask); - } -} - -void freeCursor(Cursor *cursor) { - freeCursorBuffers(cursor); - free(cursor); -} - -void updateCursor(Cursor *cursor, uint8_t *buffer, uint8_t *mask, uint16_t width, uint16_t height, - uint16_t xHot, uint16_t yHot) { - - freeCursorBuffers(cursor); - cursor->buffer = buffer; - cursor->mask = mask; - cursor->scratchBuffer = (uint8_t *) malloc(width * height * PixelBytes); - cursor->width = width; - cursor->height = height; - cursor->xHot = xHot; - cursor->yHot = yHot; -} - -#endif //AVNC_CURSOR_H \ No newline at end of file diff --git a/android/app/src/main/cpp/Utility.h b/android/app/src/main/cpp/Utility.h deleted file mode 100644 index d1c6418..0000000 --- a/android/app/src/main/cpp/Utility.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -#ifndef AVNC_UTILITY_H -#define AVNC_UTILITY_H - -#include -#include -#include -#include - - -/****************************************************************************** - * Utilities - *****************************************************************************/ - -/** - * Returns a native copy of the given jstring. - * Caller is responsible for releasing the memory. - */ -static char *getNativeStrCopy(JNIEnv *env, jstring jStr) { - const char *cStr = env->GetStringUTFChars(jStr, nullptr); - char *str = strdup(cStr); - env->ReleaseStringUTFChars(jStr, cStr); - return str; -} - -/****************************************************************************** - * Logging - *****************************************************************************/ -const char *LOG_TAG = "NativeVnc"; - -void log_info(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, fmt, args); - va_end(args); -} - -void log_error(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, fmt, args); - va_end(args); -} - -/** - * Converts given errno value to its description. - */ -static const char *errnoToStr(int e) { - - // LibVNC is patched to report `getaddrinfo` errors as negative 'errno'. - // See ConnectClientToTcpAddr6WithTimeout() in sockets.c - if (e < -1000) { - return gai_strerror((-e) - 1000); - } - - switch (e) { - case ENETDOWN: - case ENETRESET: - case ENETUNREACH: - case ECONNABORTED: - case EHOSTDOWN: - case EHOSTUNREACH: - case ETIMEDOUT: - case ENOMEM: - case EPROTO: - case EIO: - return strerror(e); - - case ECONNREFUSED: - return "Connection refused! Server may be down or running on different port"; - - case ECONNRESET: - return "Connection closed by server"; - - case EACCES: - return "Authentication failed"; - - default: - // In this case we don't want to display errno description to user - // because it is more likely to be misleading (e.g. EINTR, EAGAIN). - // BUT add it to logs in case LibVNC didn't. - log_error("errnoToStr: (%d %s)", errno, strerror(errno)); - return ""; - } -} - -#endif //AVNC_UTILITY_H diff --git a/android/app/src/main/cpp/native-vnc.cpp b/android/app/src/main/cpp/native-vnc.cpp deleted file mode 100644 index 01fb294..0000000 --- a/android/app/src/main/cpp/native-vnc.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -#include -#include -#include - -#include "ClientEx.h" -#include "Utility.h" - - -/****************************************************************************** - * Library Initialization - *****************************************************************************/ - -struct JniContext { - JavaVM *vm; //JVM Instance - jclass managedCls; //Managed `VncClient` class - jmethodID cbFramebufferUpdated; //Cached reference to managed callback - - JNIEnv *getEnv() const { - JNIEnv *env = nullptr; - - if (vm != nullptr && vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) - return env; - - return nullptr; //Should not happen - } -}; - -static JniContext context{}; - -/** - * Called when our library is loaded. - */ -JNIEXPORT jint -JNI_OnLoad(JavaVM *vm, void *unused) { - context.vm = vm; - - if (context.getEnv() == nullptr) - return JNI_ERR; - - return JNI_VERSION_1_6; -} - -JNIEXPORT void -JNI_OnUnload(JavaVM *vm, void *reserved) { - if (context.managedCls != nullptr) - context.getEnv()->DeleteGlobalRef(context.managedCls); -} - - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_initLibrary(JNIEnv *env, jclass clazz) { - context.managedCls = (jclass) env->NewGlobalRef(clazz); - context.cbFramebufferUpdated = env->GetMethodID(clazz, "cbFinishedFrameBufferUpdate", "()V"); - //TODO: Cache more method IDs so we don't have to repeatedly search them - - rfbClientLog = &log_info; - rfbClientErr = &log_error; -} - - -/****************************************************************************** - * rfbClient Callbacks - *****************************************************************************/ - -static char *onGetPassword(rfbClient *client) { - auto obj = getManagedClient(client); - auto env = context.getEnv(); - auto cls = context.managedCls; - - auto mid = env->GetMethodID(cls, "cbGetPassword", "()Ljava/lang/String;"); - auto jPassword = (jstring) env->CallObjectMethod(obj, mid); - - return getNativeStrCopy(env, jPassword); -} - -static rfbCredential *onGetCredential(rfbClient *client, int credentialType) { - if (credentialType != rfbCredentialTypeUser) { - //Only user credentials (i.e. username & password) are currently supported - rfbClientErr("Unsupported credential type requested"); - return nullptr; - } - - auto obj = getManagedClient(client); - auto env = context.getEnv(); - auto cls = context.managedCls; - - //Retrieve credentials - jmethodID mid = env->GetMethodID(cls, "cbGetCredential", - "()Lcom/gaurav/avnc/vnc/UserCredential;"); - jobject jCredential = env->CallObjectMethod(obj, mid); - if (jCredential == nullptr) { - return nullptr; - } - - //Extract username & password - auto jCredentialCls = env->GetObjectClass(jCredential); - auto usernameField = env->GetFieldID(jCredentialCls, "username", "Ljava/lang/String;"); - auto jUsername = env->GetObjectField(jCredential, usernameField); - - auto passwordField = env->GetFieldID(jCredentialCls, "password", "Ljava/lang/String;"); - auto jPassword = env->GetObjectField(jCredential, passwordField); - - //Create native rfbCredential - auto credential = (rfbCredential *) malloc(sizeof(rfbCredential)); - credential->userCredential.username = getNativeStrCopy(env, (jstring) jUsername); - credential->userCredential.password = getNativeStrCopy(env, (jstring) jPassword); - - return credential; -} - -static void onBell(rfbClient *client) { - auto obj = getManagedClient(client); - auto env = context.getEnv(); - auto cls = context.managedCls; - - jmethodID mid = env->GetMethodID(cls, "cbBell", "()V"); - env->CallVoidMethod(obj, mid); -} - -static void onGotXCutText(rfbClient *client, const char *text, int len, bool is_utf8) { - auto obj = getManagedClient(client); - auto env = context.getEnv(); - auto cls = context.managedCls; - - jmethodID mid = env->GetMethodID(cls, "cbGotXCutText", "([BZ)V"); - jbyteArray bytes = env->NewByteArray(len); - env->SetByteArrayRegion(bytes, 0, len, reinterpret_cast(text)); - env->CallVoidMethod(obj, mid, bytes, is_utf8); -} - -static void onGotXCutTextLatin1(rfbClient *client, const char *text, int len) { - onGotXCutText(client, text, len, false); -} - -static void onGotXCutTextUTF8(rfbClient *client, const char *text, int len) { - onGotXCutText(client, text, len, true); -} - -static rfbBool onHandleCursorPos(rfbClient *client, int x, int y) { - auto obj = getManagedClient(client); - auto env = context.getEnv(); - auto cls = context.managedCls; - - jmethodID mid = env->GetMethodID(cls, "cbHandleCursorPos", "(II)V"); - env->CallVoidMethod(obj, mid, x, y); - - return TRUE; -} - -static void onFinishedFrameBufferUpdate(rfbClient *client) { - auto obj = getManagedClient(client); - auto env = context.getEnv(); - - env->CallVoidMethod(obj, context.cbFramebufferUpdated); -} - -/** - * We need to use our own allocator to know when frame size has changed. - * and to acquire framebuffer lock during modification. - */ -static rfbBool onMallocFrameBuffer(rfbClient *client) { - - const auto width = client->width; - const auto height = client->height; - const auto requestedSize = (uint64_t) width * height * client->format.bitsPerPixel / 8; - - if (requestedSize >= SIZE_MAX) { - rfbClientErr("CRITICAL: cannot allocate frameBuffer, requested size is too large\n"); - return FALSE; - } - - auto allocSize = (size_t) requestedSize; - auto ex = getClientExtension(client); - - LOCK(ex->mutex); - { - - if (client->frameBuffer) - free(client->frameBuffer); - - client->frameBuffer = static_cast(malloc(allocSize)); - - if (client->frameBuffer) { - ex->fbRealWidth = width; - ex->fbRealHeight = height; - memset(client->frameBuffer, 0, allocSize); //Clear any garbage - } else { - ex->fbRealWidth = 0; - ex->fbRealHeight = 0; - } - } - UNLOCK(ex->mutex); - - if (client->frameBuffer == nullptr) { - rfbClientErr("CRITICAL: frameBuffer allocation failed\n"); - return FALSE; - } - - auto obj = getManagedClient(client); - auto env = context.getEnv(); - auto cls = context.managedCls; - - auto mid = env->GetMethodID(cls, "cbFramebufferSizeChanged", "(II)V"); - env->CallVoidMethod(obj, mid, width, height); - - return TRUE; -} - -static void onGotCursorShape(rfbClient *client, int xHot, int yHot, int width, int height, int bytesPerPixel) { - auto ex = getClientExtension(client); - - LOCK(ex->mutex); - - //Steel buffers from rfbClient - updateCursor(ex->cursor, client->rcSource, client->rcMask, (uint16_t) width, (uint16_t) height, - (uint16_t) xHot, (uint16_t) yHot); - client->rcSource = NULL; - client->rcMask = NULL; - - UNLOCK(ex->mutex); - - //Fake framebuffer update to trigger rendering - onFinishedFrameBufferUpdate(client); -} - -/** - * Hooks callbacks to rfbClient. - */ -static void setCallbacks(rfbClient *client) { - client->GetPassword = onGetPassword; - client->GetCredential = onGetCredential; - client->Bell = onBell; - client->GotXCutText = onGotXCutTextLatin1; - client->GotXCutTextUTF8 = onGotXCutTextUTF8; - client->HandleCursorPos = onHandleCursorPos; - client->FinishedFrameBufferUpdate = onFinishedFrameBufferUpdate; - client->MallocFrameBuffer = onMallocFrameBuffer; - client->GotCursorShape = onGotCursorShape; -} - - -/****************************************************************************** - * Native method Implementation - *****************************************************************************/ - -extern "C" -JNIEXPORT jlong JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeClientCreate(JNIEnv *env, jobject thiz) { - rfbClient *client = rfbGetClient(8, 3, 4); - if (client == nullptr) - return 0; - - if (!assignClientExtension(client)) - return 0; - - setCallbacks(client); - client->canHandleNewFBSize = TRUE; - - //Attach reference to managed object - auto obj = env->NewGlobalRef(thiz); - setManagedClient(client, obj); - - return (jlong) client; -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeConfigure(JNIEnv *env, jobject thiz, jlong client_ptr, - jint securityType, jboolean use_local_cursor, jint image_quality, - jboolean use_raw_encoding) { - auto client = (rfbClient *) client_ptr; - - // 0 means all auth types - if (securityType != 0) { - uint32_t auth[1] = {static_cast(securityType)}; - SetClientAuthSchemes(client, auth, 1); - } - - if (use_local_cursor) { - client->appData.useRemoteCursor = TRUE; - getClientExtension(client)->cursor = newCursor(); - } - - client->appData.qualityLevel = image_quality; - if (use_raw_encoding) - client->appData.encodingsString = "raw"; -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeSetDest(JNIEnv *env, jobject thiz, jlong client_ptr, - jstring host, jint port) { - auto client = (rfbClient *) client_ptr; - client->destHost = getNativeStrCopy(env, host); - client->destPort = port; -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeInit(JNIEnv *env, jobject thiz, jlong client_ptr, - jstring host, jint port) { - auto client = (rfbClient *) client_ptr; - - client->serverHost = getNativeStrCopy(env, host); - client->serverPort = port < 100 ? port + 5900 : port; - - if (rfbInitClient(client, nullptr, nullptr)) { - return JNI_TRUE; - } - - return JNI_FALSE; - -} -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeIsServerMacOS(JNIEnv *env, jobject thiz, jlong client_ptr) { - auto client = (rfbClient *) client_ptr; - return client->serverMajor == 3 && client->serverMinor == 889; -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeCleanup(JNIEnv *env, jobject thiz, - jlong client_ptr) { - auto client = (rfbClient *) client_ptr; - - if (client->frameBuffer) { - free(client->frameBuffer); - client->frameBuffer = nullptr; - } - - auto managedClient = getManagedClient(client); - env->DeleteGlobalRef(managedClient); - - freeClientExtension(client); - rfbClientCleanup(client); -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeProcessServerMessage(JNIEnv *env, jobject thiz, - jlong client_ptr, - jint u_sec_timeout) { - auto client = (rfbClient *) client_ptr; - - auto waitResult = WaitForMessage(client, static_cast(u_sec_timeout)); - - if (waitResult == 0) // Timeout - return JNI_TRUE; - - if (waitResult > 0 && HandleRFBServerMessage(client)) - return JNI_TRUE; - - return JNI_FALSE; -} - -extern "C" -JNIEXPORT jstring JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeGetLastErrorStr(JNIEnv *env, jobject thiz) { - auto str = errnoToStr(errno); - return env->NewStringUTF(str); -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeSendKeyEvent(JNIEnv *env, jobject thiz, jlong client_ptr, - jint key_sym, jint xt_code, jboolean is_down) { - auto client = (rfbClient *) client_ptr; - rfbBool down = is_down ? TRUE : FALSE; - - if (xt_code > 0 && SendExtendedKeyEvent(client, key_sym, xt_code, down)) - return JNI_TRUE; - else - return SendKeyEvent(client, key_sym, down); -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeSendPointerEvent(JNIEnv *env, jobject thiz, jlong client_ptr, jint x, jint y, - jint mask) { - return (jboolean) SendPointerEvent((rfbClient *) client_ptr, x, y, mask); -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeSendCutText(JNIEnv *env, jobject thiz, jlong client_ptr, jbyteArray bytes, - jboolean is_utf8) { - auto client = (rfbClient *) client_ptr; - auto textBuffer = env->GetByteArrayElements(bytes, nullptr); - auto textLen = env->GetArrayLength(bytes); - auto textChars = reinterpret_cast(textBuffer); - - rfbBool result = is_utf8 - ? SendClientCutTextUTF8(client, textChars, textLen) - : SendClientCutText(client, textChars, textLen); - - env->ReleaseByteArrayElements(bytes, textBuffer, JNI_ABORT); - return (jboolean) result; -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeIsUTF8CutTextSupported(JNIEnv *env, jobject thiz, jlong client_ptr) { - return (jboolean) (((rfbClient *) client_ptr)->extendedClipboardServerCapabilities != 0); -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeSetDesktopSize(JNIEnv *env, jobject thiz, jlong client_ptr, jint width, - jint height) { - return (jboolean) SendExtDesktopSize((rfbClient *) client_ptr, width, height); -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeRefreshFrameBuffer(JNIEnv *env, jobject thiz, jlong clientPtr) { - auto client = (rfbClient *) clientPtr; - return (jboolean) SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, TRUE); -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeSetAutomaticFramebufferUpdates(JNIEnv *env, jobject thiz, jlong client_ptr, - jboolean enabled) { - auto client = ((rfbClient *) client_ptr); - client->automaticUpdateRequests = enabled ? TRUE : FALSE; - if (enabled) SendIncrementalFramebufferUpdateRequest(client); -} - -extern "C" -JNIEXPORT jstring JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeGetDesktopName(JNIEnv *env, jobject thiz, jlong client_ptr) { - auto client = (rfbClient *) client_ptr; - return env->NewStringUTF(client->desktopName ? client->desktopName : ""); -} - -extern "C" -JNIEXPORT jint JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeGetWidth(JNIEnv *env, jobject thiz, jlong client_ptr) { - return ((rfbClient *) client_ptr)->width; -} - -extern "C" -JNIEXPORT jint JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeGetHeight(JNIEnv *env, jobject thiz, jlong client_ptr) { - return ((rfbClient *) client_ptr)->height; -} - -extern "C" -JNIEXPORT jboolean JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeIsEncrypted(JNIEnv *env, jobject thiz, jlong client_ptr) { - return static_cast(((rfbClient *) client_ptr)->tlsSession ? JNI_TRUE : JNI_FALSE); -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeUploadFrameTexture(JNIEnv *env, jobject thiz, - jlong client_ptr) { - auto client = (rfbClient *) client_ptr; - auto ex = getClientExtension(client); - - LOCK(ex->mutex); - - if (client->frameBuffer) { - glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA, - ex->fbRealWidth, - ex->fbRealHeight, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - client->frameBuffer); - } - - UNLOCK(ex->mutex); -} - -extern "C" -JNIEXPORT void JNICALL -Java_com_gaurav_avnc_vnc_VncClient_nativeUploadCursor(JNIEnv *env, jobject thiz, jlong client_ptr, jint px, jint py) { - - auto client = (rfbClient *) client_ptr; - auto ex = getClientExtension(client); - auto cursor = ex->cursor; - - if (!cursor) - return; - - //Current algo for cursor rendering is slightly weird. Main issue is that - //glTexSubImage2D() does not perform any composition with target texture. - //So, we have to manually blend transparent/invalid pixels of the cursor - //with corresponding pixels from framebuffer. scratchBuffer is used for - //this composition. - - LOCK(ex->mutex); - - //Effective cursor position in framebuffer - int32_t fbCursorX = px - cursor->xHot; - int32_t fbCursorY = py - cursor->yHot; - - //Rectangular portion of the framebuffer to be updated. - //Cursor can overflow outside the framebuffer if moved near the edges, - //but glTexSubImage2D() doesn't allow values outside target texture, - //so we need to only update the intersection of framebuffer & cursor. - int32_t left = -1, top = -1, right = -1, bottom = -1; - - auto fb = (uint32_t *) client->frameBuffer; - auto buffer = (uint32_t *) cursor->buffer; - auto scratch = (uint32_t *) cursor->scratchBuffer; - auto mask = cursor->mask; - - //Scratch buffer index - int32_t z = 0; - - for (int32_t y = 0; y < cursor->height; ++y) { - for (int32_t x = 0; x < cursor->width; ++x) { - - //Corresponding pixel in framebuffer - auto fbX = fbCursorX + x; - auto fbY = fbCursorY + y; - - if (fbX >= 0 && fbX < ex->fbRealWidth && fbY >= 0 && fbY < ex->fbRealHeight) { - auto isValidPixel = mask[y * cursor->width + x]; - if (isValidPixel) - scratch[z++] = buffer[y * cursor->width + x]; - else - scratch[z++] = fb[fbY * ex->fbRealWidth + fbX]; - - if (left == -1 && top == -1) { - left = fbX; - top = fbY; - } - right = fbX; - bottom = fbY; - } - } - } - - if (left >= 0 && top >= 0) - glTexSubImage2D(GL_TEXTURE_2D, - 0, - left, - top, - right - left + 1, - bottom - top + 1, - GL_RGBA, - GL_UNSIGNED_BYTE, - scratch); - - UNLOCK(ex->mutex); -} diff --git a/android/app/src/main/kotlin/com/example/tiny_computer/MainActivity.kt b/android/app/src/main/kotlin/com/example/tiny_computer/MainActivity.kt index 97198b5..2834c90 100644 --- a/android/app/src/main/kotlin/com/example/tiny_computer/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/tiny_computer/MainActivity.kt @@ -6,47 +6,20 @@ import android.content.Intent import androidx.annotation.NonNull import androidx.annotation.Keep import androidx.appcompat.app.AppCompatDelegate -import com.gaurav.avnc.util.AppPreferences import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity: FlutterActivity() { - - @Keep - lateinit var prefs: AppPreferences - - private fun updateNightMode(theme: String) { - val nightMode = when (theme) { - "light" -> AppCompatDelegate.MODE_NIGHT_NO - "dark" -> AppCompatDelegate.MODE_NIGHT_YES - else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - } - AppCompatDelegate.setDefaultNightMode(nightMode) - } override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) - prefs = AppPreferences(this) - prefs.ui.theme.observeForever { updateNightMode(it) } MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "android").setMethodCallHandler { // 注册通道并设置方法调用处理器 call, result -> // 判断方法名 when (call.method) { - "launchUsingUri" -> { - com.gaurav.avnc.ui.vnc.startVncActivity(this, com.gaurav.avnc.vnc.VncUri(call.argument("vncUri")!!)) - result.success(0) - } - "launchPrefsPage" -> { - startActivity(Intent(this, com.gaurav.avnc.ui.prefs.PrefsActivity::class.java)) - result.success(0) - } - "launchAboutPage" -> { - startActivity(Intent(this, com.gaurav.avnc.ui.about.AboutActivity::class.java)) - result.success(0) - } "launchSignal9Page" -> { startActivity(Intent(this, Signal9Activity::class.java)) result.success(0) diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/model/LoginInfo.kt b/android/app/src/main/kotlin/com/gaurav/avnc/model/LoginInfo.kt deleted file mode 100644 index 675b30e..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/model/LoginInfo.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.model - -/** - * Generic wrapper for login information. - * This can be used to hold different [Type]s of credentials. - */ -data class LoginInfo( - var name: String = "", // Profile name - var host: String = "", - var username: String = "", - var password: String = "", -) { - enum class Type { - VNC_PASSWORD, - VNC_CREDENTIAL, // Username & Password - SSH_PASSWORD, - SSH_KEY_PASSWORD - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/model/ServerProfile.kt b/android/app/src/main/kotlin/com/gaurav/avnc/model/ServerProfile.kt deleted file mode 100644 index c3c49ee..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/model/ServerProfile.kt +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.model - -import android.os.Parcelable -import androidx.room.ColumnInfo -import androidx.room.Entity -import androidx.room.PrimaryKey -import kotlinx.parcelize.IgnoredOnParcel -import kotlinx.parcelize.Parcelize -import kotlinx.serialization.Serializable -import kotlin.reflect.KProperty - -/** - * This class holds connection configuration of a remote VNC server. - * - * Some fields remain unused until that feature is implemented. - */ -@Parcelize -@Serializable -@Entity(tableName = "profiles") -data class ServerProfile( - - @PrimaryKey(autoGenerate = true) - var ID: Long = 0, - - /** - * Descriptive name of the server (e.g. 'Kitchen PC'). - */ - var name: String = "", - - /** - * Internet address of the server (without port number). - * This can be hostname or IP address. - */ - var host: String = "", - - /** - * Port number of the server. - */ - var port: Int = 5900, - - /** - * Username used for authentication. - */ - var username: String = "", - - /** - * Password used for authentication. - * Note: Username & password may not be used for all security types. - */ - var password: String = "", - - /** - * Security type to use when connecting to this server (e.g. VncAuth). - * 0 enables all supported types. - */ - var securityType: Int = 0, - - /** - * Transport channel to be used for communicating with the server. - * e.g. TCP, SSH Tunnel - */ - var channelType: Int = CHANNEL_TCP, - - /** - * Specifies the color level of received frames. - * This value determines the pixel-format used for framebuffer. - */ - var colorLevel: Int = 0, - - /** - * Specifies the image quality of the frames. - * This mainly affects the compression level used by some encodings. - */ - var imageQuality: Int = 5, - - /** - * Use raw encoding for framebuffer. - * This can improve performance when server is running on localhost. - */ - @ColumnInfo(defaultValue = "0") - var useRawEncoding: Boolean = false, - - /** - * Initial zoom for the viewer. - * This will be used in portrait orientation, or when per-orientation zooming is disabled. - */ - @ColumnInfo(defaultValue = "1.0") - var zoom1: Float = 1f, - - /** - * This will be used in landscape orientation if per-orientation zooming is enabled. - */ - @ColumnInfo(defaultValue = "1.0") - var zoom2: Float = 1f, - - /** - * Specifies whether 'View Only' mode should be used. - * In this mode client does not send any input messages to remote server. - */ - var viewOnly: Boolean = false, - - /** - * Whether the cursor should be drawn by client instead of server. - * It's value is currently ignored, and hardcoded to true. - * See [com.gaurav.avnc.viewmodel.VncViewModel.preConnect] - */ - var useLocalCursor: Boolean = true, - - /** - * Server type hint received from user, e.g. tigervnc, tightvnc, vino - * Can be used in future to handle known server quirks. - */ - @ColumnInfo(defaultValue = "") - var serverTypeHint: String = "", - - /** - * Composite field for various flags. - * This is accessed via individual members like [fLegacyKeySym]. - */ - var flags: Long = FLAG_LEGACY_KEYSYM, - - /** - * Preferred style to use for gesture handling. - * Possible values: auto, touchscreen, touchpad - */ - @ColumnInfo(defaultValue = "auto") - var gestureStyle: String = "auto", - - /** - * Preferred screen orientation. - * Possible values: auto, portrait, landscape - */ - @ColumnInfo(defaultValue = "auto") - var screenOrientation: String = "auto", - - /** - * Usage count tracks how many times user has connected to a server. - * Can be used to put frequent servers on top. - */ - var useCount: Int = 0, - - /** - * Whether UltraVNC Repeater is used for connections. - * When repeater is used, [host] & [port] identifies the repeater. - */ - var useRepeater: Boolean = false, - - /** - * When using a repeater, this value identifies the VNC server. - * Valid IDs: [0, 999999999]. - */ - var idOnRepeater: Int = 0, - - /** - * Resize remote desktop to match with local window size. - */ - @ColumnInfo(defaultValue = "0") - var resizeRemoteDesktop: Boolean = false, - - /** - * These values are used for SSH Tunnel - */ - var sshHost: String = "", - var sshPort: Int = 22, - var sshUsername: String = "", - var sshAuthType: Int = SSH_AUTH_KEY, - var sshPassword: String = "", - var sshPrivateKey: String = "", - var sshPrivateKeyPassword: String = "" - -) : Parcelable { - - companion object { - // Channel types (from RFC 7869) - const val CHANNEL_TCP = 1 - const val CHANNEL_SSH_TUNNEL = 24 - - // SSH auth types - const val SSH_AUTH_KEY = 1 - const val SSH_AUTH_PASSWORD = 2 - - // Flag masks - private const val FLAG_LEGACY_KEYSYM = 0x01L - private const val FLAG_BUTTON_UP_DELAY = 0x02L - private const val FLAG_ZOOM_LOCKED = 0x04L - } - - /** - * Delegated property builder for [flags] field. - */ - private class Flag(val flag: Long) { - operator fun getValue(p: ServerProfile, kp: KProperty<*>) = (p.flags and flag) != 0L - operator fun setValue(p: ServerProfile, kp: KProperty<*>, value: Boolean) { - p.flags = if (value) p.flags or flag else p.flags and flag.inv() - } - } - - /** - * Flag to emit legacy X KeySym events in certain cases. - */ - @IgnoredOnParcel - var fLegacyKeySym by Flag(FLAG_LEGACY_KEYSYM) - - /** - * Flag to insert artificial delay before UP event of left-click. - */ - @IgnoredOnParcel - var fButtonUpDelay by Flag(FLAG_BUTTON_UP_DELAY) - - /** - * If zoom is locked, user requests to change [zoom1] & [zoom2] - * should be ignored. - */ - @IgnoredOnParcel - var fZoomLocked by Flag(FLAG_ZOOM_LOCKED) -} diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/model/db/MainDb.kt b/android/app/src/main/kotlin/com/gaurav/avnc/model/db/MainDb.kt deleted file mode 100644 index 5990106..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/model/db/MainDb.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.model.db - -import android.content.Context -import androidx.room.AutoMigration -import androidx.room.Database -import androidx.room.RenameColumn -import androidx.room.Room -import androidx.room.RoomDatabase -import androidx.room.migration.AutoMigrationSpec -import androidx.sqlite.db.SupportSQLiteDatabase -import com.gaurav.avnc.model.ServerProfile - -@Database(entities = [ServerProfile::class], version = MainDb.VERSION, exportSchema = true, autoMigrations = [ - AutoMigration(from = 1, to = 2, spec = MainDb.MigrationSpec1to2::class), // in v2.0.0 - AutoMigration(from = 2, to = 3, spec = MainDb.MigrationSpec2to3::class), // in v2.1.0 - AutoMigration(from = 3, to = 4), // in v2.2.2 - AutoMigration(from = 4, to = 5, spec = MainDb.MigrationSpec4to5::class), // in v2.3.0 -]) -abstract class MainDb : RoomDatabase() { - abstract val serverProfileDao: ServerProfileDao - - companion object { - /** - * Current database version - */ - const val VERSION = 5 - - private var instance: MainDb? = null - - /** - * Returns database singleton. - * If database is not yet created then it will be created on first call. - */ - @Synchronized - fun getInstance(context: Context): MainDb { - if (instance == null) { - instance = Room.databaseBuilder(context, MainDb::class.java, "main").build() - } - return instance!! - } - } - - /******************************** Migrations ***********************************/ - // Added in v2.0.0 - class MigrationSpec1to2 : AutoMigrationSpec { - override fun onPostMigrate(db: SupportSQLiteDatabase) { - db.execSQL("UPDATE profiles SET imageQuality = 5") - } - } - - // Added in v2.1.0 - @RenameColumn(tableName = "profiles", fromColumnName = "keyCompatMode", toColumnName = "compatFlags") - class MigrationSpec2to3 : AutoMigrationSpec - - // Added in v2.3.0 - @RenameColumn(tableName = "profiles", fromColumnName = "compatFlags", toColumnName = "flags") - @RenameColumn(tableName = "profiles", fromColumnName = "shortcutRank", toColumnName = "useCount") - class MigrationSpec4to5 : AutoMigrationSpec -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/model/db/ServerProfileDao.kt b/android/app/src/main/kotlin/com/gaurav/avnc/model/db/ServerProfileDao.kt deleted file mode 100644 index 99a0441..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/model/db/ServerProfileDao.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.model.db - -import androidx.lifecycle.LiveData -import androidx.room.Dao -import androidx.room.Delete -import androidx.room.Insert -import androidx.room.Query -import androidx.room.Update -import com.gaurav.avnc.model.ServerProfile - -@Dao -interface ServerProfileDao { - - @Query("SELECT * FROM profiles") - fun getLiveList(): LiveData> - - @Query("SELECT * FROM profiles ORDER BY name COLLATE NOCASE") - fun getSortedLiveList(): LiveData> - - //Synchronous version - @Query("SELECT * FROM profiles") - suspend fun getList(): List - - @Query("SELECT * FROM profiles WHERE ID = :id") - suspend fun getByID(id: Long): ServerProfile? - - @Query("SELECT * FROM profiles WHERE name = :name") - suspend fun getByName(name: String): List - - @Query("SELECT * FROM profiles WHERE name LIKE :query OR host LIKE :query OR sshHost LIKE :query ORDER BY useCount DESC") - fun search(query: String): LiveData> - - @Insert - suspend fun insert(profile: ServerProfile): Long - - @Insert - suspend fun insert(profiles: List) - - @Update - suspend fun update(profile: ServerProfile) - - @Delete - suspend fun delete(profile: ServerProfile) - - @Query("DELETE FROM profiles") - suspend fun deleteAll() -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutActivity.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutActivity.kt deleted file mode 100644 index af6835d..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutActivity.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.about - -import android.os.Bundle -import androidx.activity.enableEdgeToEdge -import androidx.appcompat.app.AppCompatActivity -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.example.tiny_computer.R - -/** - * Activity for app details. - */ -class AboutActivity : AppCompatActivity() { - - companion object { - const val GIT_REPO_URL = "https://github.com/gujjwal00/avnc" - const val BUG_REPORT_URL = "https://github.com/gujjwal00/avnc/issues/new" - } - - override fun onCreate(savedInstanceState: Bundle?) { - enableEdgeToEdge() - super.onCreate(savedInstanceState) - - setContentView(R.layout.activity_about) - setSupportActionBar(findViewById(R.id.toolbar)) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.about_main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - if (savedInstanceState == null) { - supportFragmentManager.beginTransaction() - .replace(R.id.fragment_host, AboutFragment()) - .commit() - } - } - - override fun onSupportNavigateUp(): Boolean { - onBackPressedDispatcher.onBackPressed() - return true - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutFragment.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutFragment.kt deleted file mode 100644 index cea2e42..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/AboutFragment.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.about - -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment -import com.example.tiny_computer.BuildConfig -import com.example.tiny_computer.R -import com.example.tiny_computer.databinding.FragmentAboutBinding - -class AboutFragment : Fragment() { - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - val binding = FragmentAboutBinding.inflate(inflater, container, false) - - binding.apply { - repoBtn.setOnClickListener { openUrl(AboutActivity.GIT_REPO_URL) } - libraryBtn.setOnClickListener { showFragment(LibrariesFragment()) } - licenceBtn.setOnClickListener { showFragment(LicenseFragment()) } - } - - return binding.root - } - - override fun onResume() { - super.onResume() - requireActivity().setTitle(R.string.title_about) - } - - private fun openUrl(url: String) { - if (url.isNotEmpty()) { - runCatching { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) } - } - } - - private fun showFragment(fragment: Fragment) { - parentFragmentManager.beginTransaction() - .replace(R.id.fragment_host, fragment) - .addToBackStack(null) - .commit() - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LibrariesFragment.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LibrariesFragment.kt deleted file mode 100644 index 915ac13..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LibrariesFragment.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.about - -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.util.TypedValue -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.fragment.app.Fragment -import com.example.tiny_computer.R -import com.example.tiny_computer.databinding.FragmentLibrariesBinding - -class LibrariesFragment : Fragment() { - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - - val binding = FragmentLibrariesBinding.inflate(inflater, container, false) - - for (library in libraries) { - val textView = inflater.inflate(android.R.layout.simple_list_item_1, binding.libraryList, false) as TextView - - textView.text = library.name - textView.setOnClickListener { openUrl(library.homepage) } - - //Apply ripple background - with(TypedValue()) { - requireContext().theme.resolveAttribute(android.R.attr.selectableItemBackground, this, true) - textView.setBackgroundResource(resourceId) - } - - binding.libraryList.addView(textView) - } - - return binding.root - } - - override fun onResume() { - super.onResume() - requireActivity().setTitle(R.string.title_open_source_libraries) - } - - private fun openUrl(url: String) { - if (url.isNotEmpty()) { - runCatching { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) } - } - } - - - private data class Library( - val name: String, - val homepage: String - ) - - private val libraries = listOf( - Library("LibVNCClient", - "https://github.com/LibVNC/libvncserver"), - - Library("Libjpeg-turbo", - "https://github.com/libjpeg-turbo/libjpeg-turbo"), - - Library("wolfSSL", - "https://github.com/wolfSSL/wolfssl"), - - Library("ConnectBot's SSH library", - "https://github.com/connectbot/sshlib/"), - - Library("Android Jetpack (Androidx)", - "https://github.com/libjpeg-turbo/libjpeg-turbo"), - - Library("Material Components for Android", - "https://github.com/material-components/material-components-android"), - - Library("Material Icons", - "https://fonts.google.com/icons"), - ) -} diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LicenseFragment.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LicenseFragment.kt deleted file mode 100644 index 7876fb0..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/about/LicenseFragment.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.about - -import android.content.res.AssetManager -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.fragment.app.Fragment -import androidx.lifecycle.lifecycleScope -import com.example.tiny_computer.R -import com.example.tiny_computer.databinding.FragmentLicenseBinding -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -class LicenseFragment : Fragment() { - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - val binding = FragmentLicenseBinding.inflate(inflater, container, false) - loadLicenses(binding.licenseText, resources.assets) - return binding.root - } - - override fun onResume() { - super.onResume() - requireActivity().setTitle(R.string.title_license) - } - - - // These are relative to assets directory - private val licenseFiles = listOf( - "license/GPL-3.0.txt", - "license/Apache-2.0.txt", - "license/BSD-libjpeg-turbo.txt", - "license/sshlib.txt", - "license/X11.txt", - ) - - private fun loadLicenses(tv: TextView, assets: AssetManager) { - lifecycleScope.launch(Dispatchers.IO) { - var combinedText = "" - - licenseFiles.forEach { - val reader = assets.open(it).reader() - val text = reader.readText() - reader.close() - - combinedText += text - combinedText += "\n\n------------------------------------------------------------------------------\n\n" - } - - withContext(Dispatchers.Main) { - tv.text = combinedText - } - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/ListPreferenceEx.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/ListPreferenceEx.kt deleted file mode 100644 index 3a9d0fb..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/ListPreferenceEx.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.prefs - -import android.content.Context -import android.util.AttributeSet -import android.widget.ImageButton -import androidx.fragment.app.FragmentActivity -import androidx.preference.ListPreference -import androidx.preference.PreferenceViewHolder -import com.example.tiny_computer.R -import com.gaurav.avnc.util.MsgDialog - -/** - * List preference with some extra features. - */ -class ListPreferenceEx(context: Context, attrs: AttributeSet) : ListPreference(context, attrs) { - - /** - * Summary used when preference is disabled. - */ - var disabledStateSummary: CharSequence? = null - - override fun getSummary(): CharSequence? { - if (!isEnabled && disabledStateSummary != null) - return disabledStateSummary - return super.getSummary() - } - - - /** - * Message shown in a dialog, when help button of the preference is clicked. - * This will only work if [R.layout.help_btn] is used as widget layout. - */ - var helpMessage: CharSequence? = null - - override fun onBindViewHolder(holder: PreferenceViewHolder) { - super.onBindViewHolder(holder) - (holder.findViewById(R.id.help_btn) as? ImageButton)?.setOnClickListener { showHelp() } - } - - private fun showHelp() { - helpMessage?.let { helpMessage -> - (context as? FragmentActivity)?.let { fragmentActivity -> - MsgDialog.show(fragmentActivity.supportFragmentManager, - fragmentActivity.getString(R.string.desc_help_btn), - helpMessage) - } - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/PrefsActivity.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/PrefsActivity.kt deleted file mode 100644 index ef330fc..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/prefs/PrefsActivity.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.prefs - -import android.content.SharedPreferences.OnSharedPreferenceChangeListener -import android.content.pm.PackageManager -import android.os.Build -import android.os.Bundle -import androidx.activity.enableEdgeToEdge -import androidx.annotation.Keep -import androidx.appcompat.app.AppCompatActivity -import androidx.core.text.HtmlCompat -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat -import androidx.preference.SwitchPreference -import com.example.tiny_computer.R -import com.gaurav.avnc.util.DeviceAuthPrompt -import com.google.android.material.appbar.MaterialToolbar - -class PrefsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { - - override fun onCreate(savedInstanceState: Bundle?) { - DeviceAuthPrompt.applyFingerprintDialogFix(supportFragmentManager) - enableEdgeToEdge() - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_settings) - - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.settings_main)) { v, insets -> - val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) - v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) - insets - } - - if (savedInstanceState == null) { - supportFragmentManager - .beginTransaction() - .replace(R.id.fragment_host, Main()) - .commit() - } - - setSupportActionBar(findViewById(R.id.toolbar)) - supportActionBar?.setDisplayHomeAsUpEnabled(true) - } - - override fun onSupportNavigateUp(): Boolean { - onBackPressedDispatcher.onBackPressed() - return true - } - - /** - * Starts new fragment corresponding to given [pref]. - */ - override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean { - val fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment!!) - - supportFragmentManager.beginTransaction() - .replace(R.id.fragment_host, fragment) - .addToBackStack(null) - .commit() - - return true - } - - - /************************************************************************** - * Preference Fragments - **************************************************************************/ - - abstract class PrefFragment(private val prefResource: Int) : PreferenceFragmentCompat() { - - override fun onResume() { - super.onResume() - activity?.title = preferenceScreen.title - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(prefResource, rootKey) - } - } - - @Keep class Main : PrefFragment(R.xml.pref_main) - @Keep class Appearance : PrefFragment(R.xml.pref_appearance) - - @Keep class Viewer : PrefFragment(R.xml.pref_viewer) { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // If system does not support PiP, disable its preference - val hasPiPSupport = Build.VERSION.SDK_INT >= 26 && - requireActivity().packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) - - if (!hasPiPSupport) { - findPreference("pip_enabled")!!.apply { - isEnabled = false - summary = getString(R.string.msg_pip_not_supported) - } - } - } - } - - @Keep class Input : PrefFragment(R.xml.pref_input) { - private var invertScrollingUpdater: OnSharedPreferenceChangeListener? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - val canChangePtrIcon = Build.VERSION.SDK_INT >= 24 - - if (!canChangePtrIcon) { - findPreference("hide_local_cursor")!!.apply { - isEnabled = false - summary = getString(R.string.msg_ptr_hiding_not_supported) - } - } - - val style = findPreference("gesture_style")!! - val swipe1 = findPreference("gesture_swipe1")!! - val longPressSwipe = findPreference("gesture_long_press_swipe")!! - - swipe1.disabledStateSummary = getString(R.string.pref_gesture_action_move_pointer) - longPressSwipe.helpMessage = getText(R.string.msg_drag_gesture_help) - - swipe1.isEnabled = style.value != "touchpad" - style.setOnPreferenceChangeListener { _, value -> swipe1.isEnabled = value != "touchpad"; true } - - val styleHelp = "${getString(R.string.pref_gesture_style_touchscreen)}
" + - getString(R.string.pref_gesture_style_touchscreen_summary) + "

" + - "${getString(R.string.pref_gesture_style_touchpad)}
" + - getString(R.string.pref_gesture_style_touchpad_summary) - - style.helpMessage = HtmlCompat.fromHtml(styleHelp, 0) - - // To reduce clutter & avoid 'UI overload', pref to invert vertical scrolling is - // only visible when 'Scroll remote content' option is used. - invertScrollingUpdater = OnSharedPreferenceChangeListener { prefs, _ -> - findPreference("invert_vertical_scrolling")!!.apply { - isVisible = prefs.all.values.contains("remote-scroll") - } - } - invertScrollingUpdater?.onSharedPreferenceChanged(swipe1.sharedPreferences, null) //Initial update - swipe1.sharedPreferences?.registerOnSharedPreferenceChangeListener(invertScrollingUpdater) - - } - } - - @Keep class Server : PrefFragment(R.xml.pref_server) -} diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Dispatcher.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Dispatcher.kt deleted file mode 100644 index 58a6ffa..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Dispatcher.kt +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.graphics.PointF -import com.gaurav.avnc.viewmodel.VncViewModel -import com.gaurav.avnc.vnc.Messenger -import com.gaurav.avnc.vnc.PointerButton -import kotlin.math.abs - -/** - * We allow users to customize the actions for different events. - * This class reads those preferences and invokes proper handlers. - * - * Input handling overview: - * - *- +----------------+ +--------------------+ +--------------+ - *- | Touch events | | Key events | | Virtual keys | - *- +----------------+ +--------------------+ +--------------+ - *- | | | - *- v v | - *- +----------------+ +--------------------+ | - *- | [TouchHandler] | | [KeyHandler] |<------------+ - *- +----------------+ +--------------------+ - *- | | - *- | v - *- | +--------------------+ - *- +------------->+ [Dispatcher] + - *- +--------------------+ - *- | - *- | - *- +--------------------+---------------------+ - *- | | | - *- v v v - *- +---------------+ +----------------+ +---------------+ - *- | [Messenger] | | [VncViewModel] | | [VncActivity] | - *- +---------------+ +----------------+ +---------------+ - *- - *- - * - * 1. First we identify which gesture/key was input by the user. - * 2. Then we select an action based on user preferences. This is done here in [Dispatcher]. - * 3. Then that action is executed. Some actions change local app state (e.g. zoom in/out), - * while others send events to remote server (e.g. mouse click). - */ -class Dispatcher(private val activity: VncActivity) { - - private val viewModel = activity.viewModel - private val profile = viewModel.profile - private val messenger = viewModel.messenger - private val gesturePref = viewModel.pref.input.gesture - - - /************************************************************************** - * Action configuration - **************************************************************************/ - private val directMode = DirectMode() - private val relativeMode = RelativeMode() - private var config = Config() - - private inner class Config { - val gestureStyle = if (profile.gestureStyle == "auto") gesturePref.style else profile.gestureStyle - val defaultMode = if (gestureStyle == "touchscreen") directMode else relativeMode - - val tap1Action = selectPointAction(gesturePref.tap1) - val tap2Action = selectPointAction(gesturePref.tap2) - val doubleTapAction = selectPointAction(gesturePref.doubleTap) - val longPressAction = selectPointAction(gesturePref.longPress) - - val swipe1Pref = if (gestureStyle == "touchpad") "move-pointer" else gesturePref.swipe1 - val swipe1Action = selectSwipeAction(swipe1Pref) - val swipe2Action = selectSwipeAction(gesturePref.swipe2) - val doubleTapSwipeAction = selectSwipeAction(gesturePref.doubleTapSwipe) - val longPressSwipeAction = selectSwipeAction(gesturePref.longPressSwipe) - val flingAction = selectFlingAction() - - val mouseBackAction = selectPointAction(viewModel.pref.input.mouseBack) - - private fun selectPointAction(actionName: String): (PointF) -> Unit { - return when (actionName) { - "left-click" -> { p -> defaultMode.doClick(PointerButton.Left, p) } - "double-click" -> { p -> defaultMode.doDoubleClick(PointerButton.Left, p) } - "middle-click" -> { p -> defaultMode.doClick(PointerButton.Middle, p) } - "right-click" -> { p -> defaultMode.doClick(PointerButton.Right, p) } - "open-keyboard" -> { _ -> doOpenKeyboard() } - else -> { _ -> } //Nothing - } - } - - /** - * Returns a lambda which accepts four arguments: - * - * sp: Start point of the gesture - * cp: Current point of the gesture - * dx: Change along x-axis since last event - * dy: Change along y-axis since last event - */ - private fun selectSwipeAction(actionName: String): (PointF, PointF, Float, Float) -> Unit { - return when (actionName) { - "pan" -> { _, _, dx, dy -> doPan(dx, dy) } - "move-pointer" -> { _, cp, dx, dy -> defaultMode.doMovePointer(cp, dx, dy) } - "remote-scroll" -> { sp, _, dx, dy -> defaultMode.doRemoteScroll(sp, dx, dy) } - "remote-drag" -> { _, cp, dx, dy -> defaultMode.doRemoteDrag(PointerButton.Left, cp, dx, dy) } - "remote-drag-middle" -> { _, cp, dx, dy -> defaultMode.doRemoteDrag(PointerButton.Middle, cp, dx, dy) } - else -> { _, _, _, _ -> } //Nothing - } - } - - /** - * Fling is only used for smooth-scrolling the frame. - * So it only makes sense when 1-finger-swipe is set to "pan". - */ - private fun selectFlingAction(): (Float, Float) -> Unit { - return if (swipe1Pref == "pan") { vx, vy -> startFrameFling(vx, vy) } - else { _, _ -> } - } - } - - /************************************************************************** - * Event receivers - **************************************************************************/ - - fun onGestureStart() = config.defaultMode.onGestureStart() - fun onGestureStop(p: PointF) = config.defaultMode.onGestureStop(p) - - fun onTap1(p: PointF) = config.tap1Action(p) - fun onTap2(p: PointF) = config.tap2Action(p) - fun onDoubleTap(p: PointF) = config.doubleTapAction(p) - fun onLongPress(p: PointF) = config.longPressAction(p) - - fun onSwipe1(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.swipe1Action(sp, cp, dx, dy) - fun onSwipe2(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.swipe2Action(sp, cp, dx, dy) - fun onDoubleTapSwipe(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.doubleTapSwipeAction(sp, cp, dx, dy) - fun onLongPressSwipe(sp: PointF, cp: PointF, dx: Float, dy: Float) = config.longPressSwipeAction(sp, cp, dx, dy) - - fun onScale(scaleFactor: Float, fx: Float, fy: Float) = doScale(scaleFactor, fx, fy) - fun onFling(vx: Float, vy: Float) = config.flingAction(vx, vy) - - fun onMouseButtonDown(button: PointerButton, p: PointF) = directMode.doButtonDown(button, p) - fun onMouseButtonUp(button: PointerButton, p: PointF) = directMode.doButtonUp(button, p) - fun onMouseMove(p: PointF) = directMode.doMovePointer(p, 0f, 0f) - fun onMouseScroll(p: PointF, hs: Float, vs: Float) = directMode.doRemoteScrollFromMouse(p, hs, vs) - fun onMouseBack(p: PointF) = config.mouseBackAction(p) - - fun onStylusTap(p: PointF) = directMode.doClick(PointerButton.Left, p) - fun onStylusDoubleTap(p: PointF) = directMode.doDoubleClick(PointerButton.Left, p) - fun onStylusLongPress(p: PointF) = directMode.doClick(PointerButton.Right, p) - fun onStylusScroll(p: PointF) = directMode.doButtonDown(PointerButton.Left, p) - - fun onXKey(keySym: Int, xtCode: Int, isDown: Boolean) = messenger.sendKey(keySym, xtCode, isDown) - - fun onGestureStyleChanged() { - config = Config() - } - - /************************************************************************** - * Available actions - **************************************************************************/ - - private fun doOpenKeyboard() = activity.showKeyboard() - private fun doScale(scaleFactor: Float, fx: Float, fy: Float) = viewModel.updateZoom(scaleFactor, fx, fy) - private fun doPan(dx: Float, dy: Float) = viewModel.panFrame(dx, dy) - private fun startFrameFling(vx: Float, vy: Float) = viewModel.frameScroller.fling(vx, vy) - private fun stopFrameFling() = viewModel.frameScroller.stop() - - /** - * Most actions have the same implementation in both modes, only difference being - * the point where event is sent. [transformPoint] is used for this mode-specific - * point selection. - */ - private abstract inner class AbstractMode { - //Used for remote scrolling - private var accumulatedDx = 0F - private var accumulatedDy = 0F - private val deltaPerScroll = 20F //For how much dx/dy, one scroll event will be sent - private val yScrollDirection = (if (gesturePref.invertVerticalScrolling) -1 else 1) - - abstract fun transformPoint(p: PointF): PointF? - abstract fun doMovePointer(p: PointF, dx: Float, dy: Float) - abstract fun doRemoteDrag(button: PointerButton, p: PointF, dx: Float, dy: Float) - - open fun onGestureStart() = stopFrameFling() - open fun onGestureStop(p: PointF) = doButtonRelease(p) - - fun doButtonDown(button: PointerButton, p: PointF) { - transformPoint(p)?.let { messenger.sendPointerButtonDown(button, it) } - } - - fun doButtonUp(button: PointerButton, p: PointF) { - transformPoint(p)?.let { messenger.sendPointerButtonUp(button, it) } - } - - fun doButtonRelease(p: PointF) { - transformPoint(p)?.let { messenger.sendPointerButtonRelease(it) } - } - - fun doClick(button: PointerButton, p: PointF) { - doButtonDown(button, p) - // Some (obscure) apps seems to ignore click event if button-up is received too early - if (button == PointerButton.Left && profile.fButtonUpDelay) - messenger.insertButtonUpDelay() - doButtonUp(button, p) - } - - fun doDoubleClick(button: PointerButton, p: PointF) { - doClick(button, p) - doClick(button, p) - } - - fun doRemoteScroll(focus: PointF, dx: Float, dy: Float) { - accumulatedDx += dx - accumulatedDy += dy * yScrollDirection - - //Drain horizontal change - while (abs(accumulatedDx) >= deltaPerScroll) { - if (accumulatedDx > 0) { - doClick(PointerButton.WheelLeft, focus) - accumulatedDx -= deltaPerScroll - } else { - doClick(PointerButton.WheelRight, focus) - accumulatedDx += deltaPerScroll - } - } - - //Drain vertical change - while (abs(accumulatedDy) >= deltaPerScroll) { - if (accumulatedDy > 0) { - doClick(PointerButton.WheelUp, focus) - accumulatedDy -= deltaPerScroll - } else { - doClick(PointerButton.WheelDown, focus) - accumulatedDy += deltaPerScroll - } - } - } - - /** - * [hs] Movement of horizontal scroll wheel - * [vs] Movement of vertical scroll wheel - */ - fun doRemoteScrollFromMouse(p: PointF, hs: Float, vs: Float) { - doRemoteScroll(p, hs * deltaPerScroll, vs * deltaPerScroll) - } - } - - /** - * Actions happen at touch-point, which is simply transformed from - * viewport coordinates into corresponding position in framebuffer. - */ - private inner class DirectMode : AbstractMode() { - override fun transformPoint(p: PointF) = viewModel.frameState.toFb(p) - override fun doMovePointer(p: PointF, dx: Float, dy: Float) = doButtonDown(PointerButton.None, p) - override fun doRemoteDrag(button: PointerButton, p: PointF, dx: Float, dy: Float) = doButtonDown(button, p) - } - - /** - * Actions happen at [pointerPosition], which is updated by [doMovePointer]. - */ - private inner class RelativeMode : AbstractMode() { - private val pointerPosition = PointF(0f, 0f) - - override fun onGestureStart() { - super.onGestureStart() - //Initialize with the latest pointer position - pointerPosition.apply { - x = viewModel.client.pointerX.toFloat() - y = viewModel.client.pointerY.toFloat() - } - viewModel.client.ignorePointerMovesByServer = true - } - - override fun onGestureStop(p: PointF) { - super.onGestureStop(p) - viewModel.client.ignorePointerMovesByServer = false - } - - override fun transformPoint(p: PointF) = pointerPosition - - override fun doMovePointer(p: PointF, dx: Float, dy: Float) { - val xLimit = viewModel.frameState.fbWidth - 1 - val yLimit = viewModel.frameState.fbHeight - 1 - if (xLimit < 0 || yLimit < 0) - return - - pointerPosition.apply { - offset(dx, dy) - x = x.coerceIn(0f, xLimit) - y = y.coerceIn(0f, yLimit) - } - doButtonDown(PointerButton.None, pointerPosition) - - //Try to keep the pointer centered on screen - val vp = viewModel.frameState.toVP(pointerPosition) - val centerDiffX = viewModel.frameState.safeArea.centerX() - vp.x - val centerDiffY = viewModel.frameState.safeArea.centerY() - vp.y - viewModel.panFrame(centerDiffX, centerDiffY) - } - - override fun doRemoteDrag(button: PointerButton, p: PointF, dx: Float, dy: Float) { - doButtonDown(button, p) - doMovePointer(p, dx, dy) - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameScroller.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameScroller.kt deleted file mode 100644 index d4056ca..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameScroller.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import androidx.dynamicanimation.animation.FlingAnimation -import androidx.dynamicanimation.animation.FloatValueHolder -import com.gaurav.avnc.viewmodel.VncViewModel - -/** - * Implements fling animation for the frame. - */ -class FrameScroller(val viewModel: VncViewModel) { - - private val fs = viewModel.frameState - private val xAnimator = FlingAnimation(FloatValueHolder()) - private val yAnimator = FlingAnimation(FloatValueHolder()) - - init { - xAnimator.addUpdateListener { _, x, _ -> - viewModel.moveFrameTo(x, fs.frameY) - } - - yAnimator.addUpdateListener { _, y, _ -> - viewModel.moveFrameTo(fs.frameX, y) - } - } - - /** - * Stop current animation - */ - fun stop() { - xAnimator.cancel() - yAnimator.cancel() - } - - /** - * Starts fling animation according to given velocities - */ - fun fling(vx: Float, vy: Float) { - stop() - - val x = fs.frameX - val y = fs.frameY - val safe = fs.safeArea - - /** - * Fling limits. - * - * There are two cases: - * - * 1) x >= safeLeft : It means frame is completely visible and centered horizontally. - * In this case both minX,maxX = x (ie. no movement possible). - - * 2) x < safeLeft : Here, 'scaled frame width' > 'safe width'. In this case - * minX is negative and maxX = safeLeft. - * - * minY,maxY are calculated similarly. - */ - val minX = if (x >= safe.left) x else (safe.width()) - (fs.fbWidth * fs.scale) - val maxX = if (x >= safe.left) x else safe.left - val minY = if (y >= safe.top) y else (safe.height()) - (fs.fbHeight * fs.scale) - val maxY = if (y >= safe.top) y else safe.top - - xAnimator.apply { - setStartValue(x) - setStartVelocity(vx) - setMinValue(minX) - setMaxValue(maxX) - start() - } - - yAnimator.apply { - setStartValue(y) - setStartVelocity(vy) - setMinValue(minY) - setMaxValue(maxY) - start() - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameState.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameState.kt deleted file mode 100644 index 8cf45f2..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameState.kt +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.graphics.PointF -import android.graphics.RectF -import com.gaurav.avnc.ui.vnc.FrameState.Snapshot -import kotlin.math.max -import kotlin.math.min - -/** - * Represents current 'view' state of the frame. - * - * Terminology - * =========== - * - * Framebuffer: This is the buffer holding pixel data. It resides in native memory. - * - * Frame: This is the actual content rendered on screen. It can be thought of as - * 'rendered framebuffer'. Its size changes based on current [scale] and its position - * is stored in [frameX] & [frameY]. - * - * Window: Top-level window of the application/activity. - * - * Viewport: This is the area of window where frame is rendered. It is denoted by [FrameView]. - * - * Safe area: Area inside viewport which is safe for interaction with frame, maintained in [safeArea]. - * - * Window denotes 'total' area available to our activity, viewport denotes 'visible to user' - * area, and safe area denotes 'able to click' area. Most of the time all three will be equal, - * but viewport can be smaller than window (e.g. if soft keyboard is visible), and safe area - * can be smaller than viewport (e.g. due to display cutout). - * - * +---------------------------+ - - - * | \Cutout/ | | | Viewport - * | | | | - - * | | | | | SafeArea - * +---------------------------+ | - - - * | Soft Keyboard | | Window - * +---------------------------+ - - * - * Differentiating between these allows us to handle layout changes more easily and cleanly. - * We use window size to calculate base scale because we don't want to change scale when - * keyboard is shown/hidden. Viewport size is used for rendering the frame, fully immersive. - * Safe area is used to coerce frame position so that user can pan every part of frame inside - * safe area to interact with it. - * - * See [LayoutManager] for more information about these values. - * - * State & Coordinates - * =================== - * - * Both frame & viewport are in same coordinate space. Viewport is assumed to be fixed - * in its place with [0,0] represented by top-left corner. Only frame is scaled/moved. - * To make sure frame does not move off-screen, after each state change, values are - * coerced within range by [coerceValues]. - * - * Rendering is done by [com.gaurav.avnc.ui.vnc.gl.Renderer] based on these values. - * - * - * Scaling - * ======= - * - * Scaling controls the 'size' of rendered frame. It involves multiple factors, like window size, - * framebuffer size, user choice etc. To achieve best experience, we split scaling in two parts. - * One automatic, and one user controlled. - * - * 1. Base Scale [baseScale] : - * Motivation behind base scale is to start with the most optimal frame size. It is automatically - * calculated (and updated) using window size & framebuffer size. When orientation of local - * device is such that longer edge of the window is aligned with longer edge of the frame, - * base scale will satisfy following constraints (see [calculateBaseScale]): - * - * - Frame is completely visible - * - Frame's aspect ratio is maintained - * - Maximum window space is utilized - * - * 2. Zoom Scale [zoomScale] : - * This is the user controlled part. It is updated only in response to pinch gestures. - * To allow different zoom in different orientations, two separate zoom scales are maintained - * in [zoomScale1] & [zoomScale2]. Based on user preference and current orientation, [zoomScale] - * will be delegated to one of these. - * - * Conceptually, zoom scale works 'on top of' the base scale. - * Effective scale [scale] is calculated as the product of these two parts, so: - - * FrameSize = (FramebufferSize * BaseScale) * ZoomScale - * - * - * Thread safety - * ============= - * - * Frame state is accessed from two threads: Its properties are updated in UI thread - * and consumed by the renderer thread. There is a chance that Renderer thread may see - * half-updated state (e.g. [frameX] is changed inside [pan] but [coerceValues] is not yet called). - * This half-updated state can cause flickering issues. - * - * To avoid this we use [Snapshot]. All updates to frame state are guarded by [lock]. - * Render thread uses [getSnapshot] to retrieve a consistent state to render the frame. - */ -class FrameState( - private val minZoomScale: Float = 0.5F, - private val maxZoomScale: Float = 5F, - private val usePerOrientationZoom: Boolean = false -) { - - //Frame position, relative to top-left corner (0,0) - var frameX = 0F; private set - var frameY = 0F; private set - - //VNC framebuffer size - var fbWidth = 0F; private set - var fbHeight = 0F; private set - - //Viewport/FrameView size - var vpWidth = 0F; private set - var vpHeight = 0F; private set - - //Size of activity window - var windowWidth = 0F; private set - var windowHeight = 0F; private set - - var safeArea = RectF(); private set - - //Scaling - var zoomScale1 = 1F; private set - var zoomScale2 = 1F; private set - private val useZoomScale1 get() = (!usePerOrientationZoom || windowHeight > windowWidth) - - var baseScale = 1F; private set - var zoomScale - get() = if (useZoomScale1) zoomScale1 else zoomScale2 - private set(value) = if (useZoomScale1) zoomScale1 = value else zoomScale2 = value - - val scale get() = baseScale * zoomScale - - /** - * Immutable wrapper for frame state - */ - data class Snapshot( - val frameX: Float, - val frameY: Float, - val fbWidth: Float, - val fbHeight: Float, - val vpWidth: Float, - val vpHeight: Float, - val scale: Float - ) - - private val lock = Any() - private inline fun withLock(block: () -> T) = synchronized(lock) { block() } - - fun setFramebufferSize(w: Float, h: Float) = withLock { - fbWidth = w - fbHeight = h - calculateBaseScale() - coerceValues() - } - - fun setViewportSize(w: Float, h: Float) = withLock { - vpWidth = w - vpHeight = h - coerceValues() - } - - fun setWindowSize(w: Float, h: Float) = withLock { - windowWidth = w - windowHeight = h - calculateBaseScale() - coerceValues() - } - - fun setSafeArea(rect: RectF) = withLock { - safeArea = RectF(rect) - coerceValues() - } - - /** - * Adjust zoom scale according to give [scaleFactor]. - * - * Returns 'how much' scale factor is actually applied (after coercing). - */ - fun updateZoom(scaleFactor: Float): Float = withLock { - val oldScale = zoomScale - - zoomScale *= scaleFactor - coerceValues() - - return zoomScale / oldScale //Applied scale factor - } - - fun setZoom(zoom1: Float, zoom2: Float) = withLock { - zoomScale1 = zoom1 - zoomScale2 = zoom2 - coerceValues() - } - - /** - * Shift frame by given delta. - */ - fun pan(deltaX: Float, deltaY: Float) = withLock { - frameX += deltaX - frameY += deltaY - coerceValues() - } - - /** - * Move frame to given position. - */ - fun moveTo(x: Float, y: Float) = withLock { - frameX = x - frameY = y - coerceValues() - } - - /** - * Checks if given point is inside of framebuffer. - */ - fun isValidFbPoint(x: Float, y: Float) = (x >= 0F && x < fbWidth) && (y >= 0F && y < fbHeight) - - /** - * Converts given viewport point to corresponding framebuffer point. - * Returns null if given point lies outside of framebuffer. - */ - fun toFb(vpPoint: PointF): PointF? { - val fbX = (vpPoint.x - frameX) / scale - val fbY = (vpPoint.y - frameY) / scale - - if (isValidFbPoint(fbX, fbY)) - return PointF(fbX, fbY) - else - return null - } - - /** - * Converts given framebuffer point to corresponding point in viewport. - */ - fun toVP(fbPoint: PointF): PointF { - return PointF(fbPoint.x * scale + frameX, fbPoint.y * scale + frameY) - } - - /** - * Returns immutable & consistent snapshot of frame state. - */ - fun getSnapshot(): Snapshot = withLock { - return Snapshot(frameX = frameX, frameY = frameY, - fbWidth = fbWidth, fbHeight = fbHeight, - vpWidth = vpWidth, vpHeight = vpHeight, scale = scale) - } - - private fun calculateBaseScale() { - if (fbHeight == 0F || fbWidth == 0F || windowHeight == 0F) - return //Not enough info yet - - val s1 = max(windowWidth, windowHeight) / max(fbWidth, fbHeight) - val s2 = min(windowWidth, windowHeight) / min(fbWidth, fbHeight) - - baseScale = min(s1, s2) - } - - /** - * Makes sure state values are within constraints. - */ - private fun coerceValues() { - zoomScale1 = zoomScale1.coerceIn(minZoomScale, maxZoomScale) - zoomScale2 = zoomScale2.coerceIn(minZoomScale, maxZoomScale) - - if (safeArea.isEmpty || !safeArea.intersect(0f, 0f, vpWidth, vpHeight)) - safeArea.set(0f, 0f, vpWidth, vpHeight) - - frameX = coercePosition(frameX, safeArea.left, safeArea.right, fbWidth) - frameY = coercePosition(frameY, safeArea.top, safeArea.bottom, fbHeight) - } - - /** - * Coerce position value in a direction (horizontal/vertical). - */ - private fun coercePosition(current: Float, safeMin: Float, safeMax: Float, fb: Float): Float { - val scaledFb = (fb * scale) - val diff = (safeMax - safeMin) - scaledFb - - return if (diff >= 0) diff / 2 + safeMin //Frame will be smaller than safe area, so center it - else current.coerceIn(diff + safeMin, safeMin) //otherwise, make sure safe area is completely filled. - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameView.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameView.kt deleted file mode 100644 index ca0c302..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/FrameView.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.annotation.SuppressLint -import android.content.Context -import android.opengl.GLSurfaceView -import android.os.Build -import android.util.AttributeSet -import android.view.KeyEvent -import android.view.MotionEvent -import android.view.PointerIcon -import android.view.inputmethod.BaseInputConnection -import android.view.inputmethod.EditorInfo -import com.gaurav.avnc.ui.vnc.gl.Renderer -import com.gaurav.avnc.viewmodel.VncViewModel -import com.gaurav.avnc.vnc.VncClient - -/** - * This class renders the VNC framebuffer on screen. - * - * It derives from [GLSurfaceView], which creates an EGL Display, where we can - * render the framebuffer using OpenGL ES. See [GLSurfaceView] for more details. - * - * Actual rendering is done by [Renderer], which is executed on a dedicated - * thread by [GLSurfaceView]. - * - * - *- +-------------------+ +--------------------+ +--------------------+ - *- | [FrameView] | | [VncViewModel] | | [VncClient] | - *- +--------+----------+ +----------+---------+ +----------+---------+ - *- | | | - *- | | | - *- | Render Request | [FrameState] | Framebuffer - *- | v | - *- | +----------+---------+ | - *- +-------------------> | [Renderer] | <------------------+ - *- +--------------------+ - - */ -class FrameView(context: Context?, attrs: AttributeSet? = null) : GLSurfaceView(context, attrs) { - - private lateinit var touchHandler: TouchHandler - private lateinit var keyHandler: KeyHandler - - /** - * Input connection used for intercepting key events - */ - inner class InputConnection : BaseInputConnection(this, false) { - override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean { - return keyHandler.onCommitText(text) || super.commitText(text, newCursorPosition) - } - - override fun sendKeyEvent(event: KeyEvent): Boolean { - return keyHandler.onKeyEvent(event) || super.sendKeyEvent(event) - } - } - - /** - * Should be called from [VncActivity.onCreate]. - */ - fun initialize(activity: VncActivity) { - val viewModel = activity.viewModel - - touchHandler = activity.touchHandler - keyHandler = activity.keyHandler - - setEGLContextClientVersion(2) - setRenderer(Renderer(viewModel)) - renderMode = RENDERMODE_WHEN_DIRTY - - // Hide local cursor if requested and supported - if (Build.VERSION.SDK_INT >= 24 && viewModel.pref.input.hideLocalCursor) - pointerIcon = PointerIcon.getSystemIcon(context, PointerIcon.TYPE_NULL) - } - - override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection { - outAttrs.imeOptions = outAttrs.imeOptions or - EditorInfo.IME_FLAG_NO_EXTRACT_UI or - EditorInfo.IME_FLAG_NO_FULLSCREEN - return InputConnection() - } - - override fun onCheckIsTextEditor(): Boolean { - return true - } - - @SuppressLint("ClickableViewAccessibility") - override fun onTouchEvent(event: MotionEvent): Boolean { - return touchHandler.onTouchEvent(event) - } - - override fun onGenericMotionEvent(event: MotionEvent): Boolean { - return touchHandler.onGenericMotionEvent(event) - } - - override fun onHoverEvent(event: MotionEvent): Boolean { - return touchHandler.onHoverEvent(event) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/HostKeyFragment.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/HostKeyFragment.kt deleted file mode 100644 index 56a493c..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/HostKeyFragment.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.app.Dialog -import android.os.Bundle -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.activityViewModels -import com.example.tiny_computer.R -import com.gaurav.avnc.viewmodel.VncViewModel -import com.google.android.material.dialog.MaterialAlertDialogBuilder - -/** - * This dialog is used to get user-confirmation before connecting to unknown SSH servers. - */ -class HostKeyFragment : DialogFragment() { - val viewModel by activityViewModels() - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val request = viewModel.sshHostKeyVerifyRequest - val hostKey = request.value!! - val titleRes = if (hostKey.isKnownHost) R.string.title_ssh_host_key_changed else R.string.title_unknown_ssh_host - - val message = """ - | - |Host: ${hostKey.host} - |Key type: ${hostKey.algo.uppercase()} - |Key fingerprint: - | - |${hostKey.getFingerprint()} - | - |Please make sure your are connecting to the valid host. - | - |If you continue, this host & key will be marked as known. - """.trimMargin() - - return MaterialAlertDialogBuilder(requireContext()) - .setTitle(titleRes) - .setMessage(message) - .setPositiveButton(R.string.title_continue) { _, _ -> request.offerResponse(true) } - .setNegativeButton(android.R.string.cancel) { _, _ -> request.offerResponse(false) } - .setCancelable(false) - .create() - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/IntentReceiverActivity.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/IntentReceiverActivity.kt deleted file mode 100644 index aaf6a2a..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/IntentReceiverActivity.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ -package com.gaurav.avnc.ui.vnc - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.lifecycleScope -import com.example.tiny_computer.R -import com.gaurav.avnc.model.db.MainDb -import com.gaurav.avnc.vnc.VncUri -import kotlinx.coroutines.launch - -/** - * Handles "external" intents and launches [VncActivity] with appropriate profiles. - * - * Current intent types: - * - vnc:// URIs - * - App shortcuts - */ -class IntentReceiverActivity : AppCompatActivity() { - - companion object { - private const val SHORTCUT_PROFILE_ID_KEY = "com.gaurav.avnc.shortcut_profile_id" - - fun createShortcutIntent(context: Context, profileId: Long): Intent { - check(profileId != 0L) { "Cannot create shortcut with profileId = 0." } - return Intent(context, IntentReceiverActivity::class.java).apply { - action = Intent.ACTION_VIEW - putExtra(SHORTCUT_PROFILE_ID_KEY, profileId) - } - } - } - - private val profileDao by lazy { MainDb.getInstance(this).serverProfileDao } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - handleIntent() - } - - private fun handleIntent() = lifecycleScope.launch { - if (intent.data?.scheme == "vnc") - launchFromVncUri(VncUri(intent.data!!.toString())) - else if (intent.hasExtra(SHORTCUT_PROFILE_ID_KEY)) - launchFromProfileId(intent.getLongExtra(SHORTCUT_PROFILE_ID_KEY, 0)) - else - toast("Invalid intent: Server info is missing!") - - finish() - } - - private suspend fun launchFromVncUri(uri: VncUri) { - if (uri.connectionName.isNotBlank()) launchFromProfileName(uri.connectionName) - else launchVncUri(uri) - } - - private fun launchVncUri(uri: VncUri) { - if (uri.host.isEmpty()) toast(getString(R.string.msg_invalid_vnc_uri)) - else startVncActivity(this, uri) - } - - private suspend fun launchFromProfileName(name: String) { - val profile = profileDao.getByName(name).firstOrNull() - if (profile == null) toast("No server found with name '$name'") - else startVncActivity(this, profile) - } - - private suspend fun launchFromProfileId(profileId: Long) { - val profile = profileDao.getByID(profileId) - if (profile == null) toast(getString(R.string.msg_shortcut_server_deleted)) - else startVncActivity(this, profile) - } - - private fun toast(msg: String) = Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/KeyHandler.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/KeyHandler.kt deleted file mode 100644 index a964f30..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/KeyHandler.kt +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.os.Build -import android.view.KeyCharacterMap -import android.view.KeyEvent -import com.gaurav.avnc.util.AppPreferences -import com.gaurav.avnc.vnc.XKeySym -import com.gaurav.avnc.vnc.XKeySymAndroid -import com.gaurav.avnc.vnc.XKeySymAndroid.updateKeyMap -import com.gaurav.avnc.vnc.XKeySymUnicode -import com.gaurav.avnc.vnc.XTKeyCode - -/** - * Handler for key events - * - * Key handling in RFB protocol works on 'key symbols' instead of key-codes/scan-codes - * which makes it dependent on keyboard layout. VNC servers implement various heuristics - * to compensate for this & maximize portability. Our implementation is derived after - * testing with some popular servers. It might not handle all the edge cases. - * - * There is an extension to RFB protocol (ExtendedKeyEvent) implemented by some servers. - * It includes support for sending XT keycodes along with key symbol. This extension - * greatly reduces the key handling complexity. Unfortunately, as soft keyboards are - * more common on Android, most [KeyEvent]s don't provide raw scan codes. - * - * Basically, job of this class is to convert the received [KeyEvent] into a 'KeySym'. - * That KeySym will be sent to the server. - * - *- [KeyEvent] +----------------+ KeySym +----------------+ - *- ----------------> | [KeyHandler] | ------------> | [Dispatcher] | - *- +----------------+ +----------------+ - * - * This class emits (conceptually) three types of key symbols: - * - * 1. X KeySym - Individual symbols defined by X Windows System - * 2. Unicode KeySym - Unicode code points encoded as X KeySym - * 3. Legacy X KeySym - Old KeySyms which are now superseded by their Unicode KeySym equivalents - * - * - * To decide which one to emit, we look at following things: - * - * a. Key code of [KeyEvent] (may not be available, e.g. in case of [KeyEvent.ACTION_MULTIPLE]) - * b. Unicode character of [KeyEvent] (may not be available, e.g. in case of [KeyEvent.KEYCODE_F1]) - * c. Current [cfLegacyKeysym] - * - * - *- [KeyEvent] - *- | - *- v - *- +----------------------------+ - *- | Is Unicode Char Available? | - *- +-------------+--------------+ - *- | - *- Yes | No - *- +-------------+--------------+ - *- | | - *- +---------v----------+ +-------v-------+ - *- | Use Unicode Char | | Use Key Code | - *- +---------+----------+ +-------+-------+ - *- | | - *- +---------v----------+ | - *- | In compat mode? | | - *- +---------+----------+ | - *- | | - *- Yes | No | - *- +---------+----------+ | - *- | | | - *- v v v - *- (Legacy X KeySym) (Unicode KeySym) (X KeySym) - * - * See [handleKeyEvent] as a starting point. - * - * - * Reference: - * [X Windows System Protocol](https://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#keysym_encoding) - * - */ -class KeyHandler(private val dispatcher: Dispatcher, private val cfLegacyKeysym: Boolean, prefs: AppPreferences) { - - /** - * Pre-KeyEvent hook. - * This is NOT triggered for all characters. - */ - fun onCommitText(text: CharSequence?): Boolean { - return handleCCedilla(text) - } - - /** - * Shortcut to send both up & down events. Useful for Virtual Keys. - */ - fun onKey(keyCode: Int) { - onKeyEvent(keyCode, true) - onKeyEvent(keyCode, false) - } - - fun onKeyEvent(keyCode: Int, isDown: Boolean) { - val action = if (isDown) KeyEvent.ACTION_DOWN else KeyEvent.ACTION_UP - onKeyEvent(KeyEvent(action, keyCode)) - } - - fun onKeyEvent(event: KeyEvent): Boolean { - if (shouldIgnoreEvent(event)) - return false - - return handleKeyEvent(preProcessEvent(event)) - } - - - /** - * This will parse the [event] and call [emitForKeyEvent] appropriately. - */ - private fun handleKeyEvent(event: KeyEvent): Boolean { - - //Deprecated action types are still received for non-ASCII characters - @Suppress("DEPRECATION") - when (event.action) { - - KeyEvent.ACTION_DOWN -> return emitForKeyEvent(event.keyCode, getUnicodeChar(event), true, event.scanCode) - KeyEvent.ACTION_UP -> return emitForKeyEvent(event.keyCode, getUnicodeChar(event), false, event.scanCode) - - KeyEvent.ACTION_MULTIPLE -> { - if (event.keyCode == KeyEvent.KEYCODE_UNKNOWN) { - - // Here, only Unicode characters are available. - for (uChar in toCodePoints(event.characters)) { - emitForKeyEvent(0, uChar, true) - emitForKeyEvent(0, uChar, false) - } - - } else { - - // Here, only keyCode is available. - // According to Android docs, this case doesn't happen anymore. - for (i in 1..event.repeatCount) { - emitForKeyEvent(event.keyCode, 0, true) - emitForKeyEvent(event.keyCode, 0, false) - } - } - return true - } - } - return false - } - - /** - * Emits an event for given details. - * It will call [emitForAndroidKeyCode] or [emitForUnicodeChar] depending on arguments. - */ - private fun emitForKeyEvent(keyCode: Int, unicodeChar: Int, isDown: Boolean, scanCode: Int = 0): Boolean { - val xtCode = if (scanCode == 0) 0 else XTKeyCode.fromAndroidScancode(scanCode) - - if (handleDiacritics(keyCode, unicodeChar, isDown)) - return true - - // Always emit using keyCode for these because Android returns a unicodeChar - // for these but most servers don't handle their Unicode characters. - when (keyCode) { - KeyEvent.KEYCODE_ENTER, - KeyEvent.KEYCODE_NUMPAD_ENTER, - KeyEvent.KEYCODE_SPACE, - KeyEvent.KEYCODE_TAB -> - return emitForAndroidKeyCode(keyCode, isDown, xtCode) - } - - // We prefer to use unicodeChar even when keyCode is available because - // most servers ignore previously sent SHIFT/CAPS_LOCK keys. - // As Android takes meta keys into account when calculating unicodeChar, - // it works well with these servers. - - if (unicodeChar != 0) - return emitForUnicodeChar(unicodeChar, isDown, xtCode) - else - return emitForAndroidKeyCode(keyCode, isDown, xtCode) - } - - /** - * Emits X KeySym corresponding to [keyCode] - */ - private fun emitForAndroidKeyCode(keyCode: Int, isDown: Boolean, xtCode: Int = 0): Boolean { - val keySym = XKeySymAndroid.getKeySymForAndroidKeyCode(keyCode) - return emit(keySym, isDown, xtCode) - } - - /** - * Emits either Unicode KeySym or legacy KeySym for [uChar], depending on [cfLegacyKeysym]. - */ - private fun emitForUnicodeChar(uChar: Int, isDown: Boolean, xtCode: Int = 0): Boolean { - var uKeySym = 0 - - if (cfLegacyKeysym) - uKeySym = XKeySymUnicode.getLegacyKeySymForUnicodeChar(uChar) - - if (uKeySym == 0) - uKeySym = XKeySymUnicode.getKeySymForUnicodeChar(uChar) - - - // If we are generating legacy KeySym and the character is uppercase, - // we need to fake press the Shift key. Otherwise, most servers can't - // handle them. This is just a compat shim and ideally server should - // support Unicode KeySym. - val shouldFakeShift = uKeySym in 0x100..0xfffe && uChar.toChar().isUpperCase() - if (shouldFakeShift) - emitForAndroidKeyCode(KeyEvent.KEYCODE_SHIFT_LEFT, true) - - emit(uKeySym, isDown, xtCode) - - if (shouldFakeShift) - emitForAndroidKeyCode(KeyEvent.KEYCODE_SHIFT_LEFT, false) - - return true - } - - - /** - * Sends given X key to [dispatcher]. - */ - private fun emit(keySym: Int, isDown: Boolean, xtCode: Int = 0): Boolean { - if (keySym == 0) - return false - - return dispatcher.onXKey(keySym, xtCode, isDown) - } - - - /** - * Returns unicode character for given event. - * Normally [KeyEvent.getUnicodeChar] is sufficient for our need, but sometimes - * we have to fiddle with meta state to extract a suitable character. - * - * Consider Ctrl+Shift+A: [KeyEvent.getUnicodeChar] returns 0 for this case, - * because there is no character mapping for A when Ctrl & Shift both are pressed. - * But we want to obtain capital 'A' here, so that we can send it to server. - * This ensures proper working of keyboard shortcuts. - */ - private fun getUnicodeChar(event: KeyEvent): Int { - val uChar = event.unicodeChar - if (uChar != 0 || event.metaState == 0) - return uChar - - // Try without Alt/Ctrl - val altCtrl = KeyEvent.META_ALT_MASK or KeyEvent.META_CTRL_MASK - return event.getUnicodeChar(event.metaState and altCtrl.inv()) - } - - /** - * Some cases where we want to ignore events. - */ - private fun shouldIgnoreEvent(event: KeyEvent): Boolean { - val keyCode = event.keyCode - - // As if our key-handling wasn't already complex enough, Android - // decided to mess-up NumLock handling. When any numpad number-key - // is pressed (e.g. 7) and NumLock is off, it will _still_ send - // the number keycode (e.g. KEYCODE_NUMPAD_7) first. And if apps don't - // handle that, it will fallback to secondary action (e.g. KEYCODE_MOVE_HOME). - // So we have to ignore the first events when NumLock is off. - return (keyCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_9 - || keyCode == KeyEvent.KEYCODE_NUMPAD_DOT) && !event.isNumLockOn - } - - /************************************************************************************ - * Diacritics (Accents) Support - * - * Instead of sending diacritics directly to server, we handle their composition here. - * This is done because: - * - * - Android does not report real 'combining' accents to us. Instead we get the - * corresponding 'printing' characters, with the `COMBINING_ACCENT` flag set. - * See the source code of [KeyCharacterMap] for more details. - * - * - Although most servers don't support diacritics directly, some of them can - * handle the final composed characters (e.g. TightVNC). - * - * - * Behaviour: - * - * - Until an accent is received, all events are ignored by [handleDiacritics]. - * - When first accent is received, we start tracking by adding it to [accentSequence]. - * - When next key is received (can be another accent), we add it to [accentSequence]. - * - Then we try to compose a printable character from [accentSequence], and if successful, - * the composed character is sent to the server. - * - If composition was successful, or we received non-accent key, we stop tracking - * by clearing [accentSequence]. - * - ************************************************************************************/ - private var accentSequence = ArrayList(2) - - private fun handleDiacritics(keyCode: Int, uChar: Int, isDown: Boolean): Boolean { - val isUp = !isDown - val isAccent = uChar and KeyCharacterMap.COMBINING_ACCENT != 0 - val maskedChar = uChar and KeyCharacterMap.COMBINING_ACCENT_MASK - - if (!isAccent && accentSequence.size == 0) return false // No tracking yet (most common case) - if (!isAccent && isUp && !accentSequence.contains(maskedChar)) return false // Spurious key-ups - if (KeyEvent.isModifierKey(keyCode)) return false // Modifier keys are passed-on to the server - - if (isDown) - accentSequence.add(maskedChar) - - if (accentSequence.size <= 1) // Nothing to compose yet - return true - - var composed = accentSequence.last() - for (i in 0 until accentSequence.lastIndex) - composed = KeyEvent.getDeadChar(accentSequence[i], composed) - - if (composed != 0) - emitForUnicodeChar(composed, isDown) - - if (isUp && (composed != 0 || !isAccent)) - accentSequence.clear() - - return true - } - - /** - * 'Ç' & 'ç' requires special handling because Android generates them with extra ALT key press, - * and gives no indication in KeyEvents that accents are involved. So we have to handle these - * before events are synthesized by InputConnection in FrameView. - */ - private fun handleCCedilla(text: CharSequence?): Boolean { - if (text == "ç") { - emitForUnicodeChar('ç'.code, true) - emitForUnicodeChar('ç'.code, false) - return true - } - - if (text == "Ç") { - emitForAndroidKeyCode(KeyEvent.KEYCODE_SHIFT_LEFT, true) - emitForUnicodeChar('Ç'.code, true) - emitForUnicodeChar('Ç'.code, false) - emitForAndroidKeyCode(KeyEvent.KEYCODE_SHIFT_LEFT, false) - return true - } - - return false - } - - /************************************************************************************ - * Custom key-mappings - ***********************************************************************************/ - - init { - if (prefs.input.kmLanguageSwitchToSuper) updateKeyMap(KeyEvent.KEYCODE_LANGUAGE_SWITCH, XKeySym.XK_Super_L) - if (prefs.input.kmRightAltToSuper) updateKeyMap(KeyEvent.KEYCODE_ALT_RIGHT, XKeySym.XK_Super_L) - } - - // We can't map Back key to Escape inside init because we don't - // want to affect Back key events coming from Navigation Bar. - // So we have to test each event. - private val kmBackToEscape = prefs.input.kmBackToEscape - - private fun preProcessEvent(event: KeyEvent): KeyEvent { - if (event.keyCode == KeyEvent.KEYCODE_BACK && kmBackToEscape - && (event.flags and KeyEvent.FLAG_VIRTUAL_HARD_KEY == 0)) - return KeyEvent(event.action, KeyEvent.KEYCODE_ESCAPE) - - return event - } - - /************************************************************************************ - * Convert String to Array of Unicode code-points - ***********************************************************************************/ - - private val cpCache = intArrayOf(0) - - private fun toCodePoints(string: String): IntArray { - //Handle simple & most probable case - if (string.length == 1) - return cpCache.apply { this[0] = string[0].code } - - if (Build.VERSION.SDK_INT >= 24) - return string.codePoints().toArray() - - //Otherwise, do simple conversion (will be incorrect non-MBP code points) - return string.map { it.code }.toIntArray() - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LayoutManager.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LayoutManager.kt deleted file mode 100644 index cc61150..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LayoutManager.kt +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.graphics.Rect -import android.graphics.RectF -import android.os.Build.VERSION.SDK_INT -import android.view.RoundedCorner -import android.view.View -import android.view.WindowManager -import androidx.annotation.RequiresApi -import androidx.core.graphics.Insets -import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsCompat.Type -import androidx.core.view.WindowInsetsControllerCompat -import androidx.core.view.isVisible -import androidx.core.view.updatePadding -import kotlin.math.max - -/** - * This class is responsible for managing fullscreen layout & insets handling. - * Layout handling is quite complex because of Android APIs (or lack thereof). - * It gets way worse here because AVNC shows fullscreen content. - * - * Situation is so bad, it's almost funny. - * - * Almost every Android version has introduced some new APIs, deprecated others, - * or downright changed existing behaviour (sometimes just for ONE version). - * AndroidX compat library has been the only respite. It has at least hidden a - * bunch of if-else statement from our own code. But all that mess is still there. - */ -class LayoutManager(activity: VncActivity) { - private val viewModel = activity.viewModel - private val rootView = activity.binding.root - private val frameView = activity.binding.frameView - private val virtualKeys = activity.virtualKeys - private val window = activity.window - private val insetController = WindowCompat.getInsetsController(window, window.decorView) - - - fun initialize() { - if (SDK_INT >= 30) - hookInsetsListener() - else - hookSystemUiChangeListener() - - hookGlobalLayoutListener() - } - - fun onConnectionStateChanged() { - updateFullscreen() - } - - fun onWindowFocusChanged(hasFocus: Boolean) { - if (hasFocus && SDK_INT < 30) - updateFullscreen() - } - - @RequiresApi(30) - private fun hookInsetsListener() { - ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { v, insets -> - updateWindowInsets(insets) - updateNavigationBarVisibility(insets) - ViewCompat.onApplyWindowInsets(v, insets) - } - } - - private fun hookGlobalLayoutListener() { - rootView.viewTreeObserver.addOnGlobalLayoutListener { - viewModel.frameState.setWindowSize(rootView.width.toFloat(), rootView.height.toFloat()) - viewModel.frameState.setViewportSize(frameView.width.toFloat(), frameView.height.toFloat()) - virtualKeys.container?.let { updateVirtualKeyInsets(it) } - - if (SDK_INT < 30) - manuallyGenerateWindowInsets() - - applyInsets() - viewModel.resizeRemoteDesktop() - } - } - - /** - * System's WindowInsets are basically useless for us on API < 30. Neither are - * they dispatched in all cases, nor they always include necessary information. - * So, on these platforms, insets are generated manually. - * - * We could apply required padding directly here, but simulating insets means that - * [applyInsets] has a single implementation for all platforms. - */ - private fun manuallyGenerateWindowInsets() { - val decorView = window.decorView - val visibleFrame = Rect() - decorView.getWindowVisibleDisplayFrame(visibleFrame) - - // Transform from screen coordinates to window coordinates - // Both can be different, e.g. when in PiP mode - val locationOnScreen = intArrayOf(0, 0) - decorView.getLocationOnScreen(locationOnScreen) - visibleFrame.offset(-locationOnScreen[0], -locationOnScreen[1]) - - // Generate insets (left & top are always 0) - val right = max(0, decorView.right - visibleFrame.right) - val bottom = max(0, decorView.bottom - visibleFrame.bottom) - val insets = WindowInsetsCompat.Builder() - .setInsets(Type.ime(), Insets.of(0, 0, 0, bottom)) - .setInsets(Type.navigationBars(), Insets.of(0, 0, right, 0)) - .build() - - updateWindowInsets(insets) - } - - /** - * Flags to hide system bars are not 'sticky' on API < 30. System will automatically - * clear them in a lot of situations, e.g. when IME is shown. So we have to keep - * reminding it that we still want to remain fullscreen. - * Same reason why [onWindowFocusChanged] exists. - */ - private fun hookSystemUiChangeListener() { - @Suppress("DEPRECATION") - window.decorView.setOnSystemUiVisibilityChangeListener { updateFullscreen() } - } - - - /************************************************************************************ - * Fullscreen - ************************************************************************************/ - private val fullscreenEnabled = viewModel.pref.viewer.fullscreen - private val defaultSystemBarBehaviour = insetController.systemBarsBehavior - - private fun updateFullscreen() { - if (!fullscreenEnabled) - return - - if (viewModel.client.connected) - enterFullscreen() - else - leaveFullscreen() - } - - private fun enterFullscreen() { - WindowCompat.setDecorFitsSystemWindows(window, false) - insetController.hide(Type.systemBars()) - insetController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - - if (SDK_INT < 30) { - // This flag is required to keep the status bar hidden when IME is visible - @Suppress("DEPRECATION") - window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) - } - } - - private fun leaveFullscreen() { - WindowCompat.setDecorFitsSystemWindows(window, true) - insetController.show(Type.systemBars()) - insetController.systemBarsBehavior = defaultSystemBarBehaviour - } - - @RequiresApi(30) - private fun updateNavigationBarVisibility(insets: WindowInsetsCompat) { - // On API 30, Android doesn't automatically show the navigation bar with keyboard. - // So to hide the keyboard, user has to first swipe to un-hide the navigation bar - // and then tap on Back button. To avoid this, we manually show the navigation bar - // whenever keyboard is visible. Although only API 30 seems to be affected, fix is - // applied on 30+ APIs to ensure consistency. - if (insets.isVisible(Type.ime())) - insetController.show(Type.navigationBars()) - else if (fullscreenEnabled && viewModel.client.connected) { - insetController.hide(Type.navigationBars()) - } - } - - /************************************************************************************ - * Insets - * - * Insets are Android's way of telling us when our window is obscured by something. - * To provide optimal experience, insets are divided into two categories: - * - * Opaque Insets: These insets don't allow interaction with app's window behind them. - * IME & nav bar are such insets. These are handled by adding padding to [rootView], - * effectively resizing [frameView] to visible portion of the screen. - * - * Safe Area Insets: These obstructs [frameView] only partially, e.g. display cutout. - * We want the frame to be rendered behind these cutouts to provide fully immersive - * experience, but also allow user to pan out of these insets when they need to - * interact with remote content. These are implemented as 'safe area' in [FrameState]. - * - * All insets are in window coordinates. - * - ************************************************************************************/ - private var windowInsets = WindowInsetsCompat.Builder().build() - private var virtualKeyInsets = Insets.NONE // Insets caused by virtual keys - - private fun updateWindowInsets(insetsCompat: WindowInsetsCompat) { - // Copy constructor of WindowInsetsCompat is partially broken on API below 30. - // We are manually generating insets on API <30 anyway, so don't need to create a copy. - windowInsets = if (SDK_INT < 30) insetsCompat else WindowInsetsCompat(insetsCompat) - } - - private fun updateVirtualKeyInsets(vkRoot: View) { - if (vkRoot.isVisible) { - val vkLocation = intArrayOf(0, 0) - vkRoot.getLocationInWindow(vkLocation) - val b = max(0, window.decorView.height - vkLocation[1]) - - if (virtualKeyInsets.bottom != b) - virtualKeyInsets = Insets.of(0, 0, 0, b) - } else { - virtualKeyInsets = Insets.NONE - } - } - - private fun applyInsets() { - val opaqueInsets = listOf(windowInsets.getInsets(Type.ime()), windowInsets.getInsets(Type.navigationBars())) - val maxOpaqueInsets = opaqueInsets.fold(Insets.NONE) { a, i -> Insets.max(a, i) } - applyOpaqueInsets(maxOpaqueInsets) - - //val cutoutInsets = windowInsets.getInsets(Type.displayCutout()) - //val cornerInsets = calculateCornerInsets(windowInsets) - val safeAreaInsets = listOf(maxOpaqueInsets, /*cutoutInsets, cornerInsets,*/ virtualKeyInsets) - val maxSafeAreaInsets = safeAreaInsets.fold(Insets.NONE) { a, i -> Insets.max(a, i) } - applySafeAreaInsets(maxSafeAreaInsets) - - // TODO: Apply insets to drawer - } - - private fun applyOpaqueInsets(opaqueInsets: Insets) { - // Guess if IME is closing - if (!windowInsets.isVisible(Type.ime()) && rootView.paddingBottom != 0) - virtualKeys.onKeyboardClose() - - val insets = windowInsetsToViewInsets(opaqueInsets, rootView) - if (rootView.paddingRight != insets.right || rootView.paddingBottom != insets.bottom) - rootView.updatePadding(0, 0, insets.right, insets.bottom) - } - - private fun applySafeAreaInsets(safeAreaInsets: Insets) { - val insets = windowInsetsToViewInsets(safeAreaInsets, frameView) - val safeArea = Rect(insets.left, - insets.top, - frameView.width - insets.right, - frameView.height - insets.bottom) - - viewModel.setSafeArea(RectF(safeArea)) - } - - /** - * Returns insets caused by rounded corners. - * - * Android does not provide pre-calculated insets for rounded screen corners. - * Information about corners is available since API 31. We use this information - * to calculate effective insets. - */ - private fun calculateCornerInsets(windowInsetsCompat: WindowInsetsCompat): Insets { - val windowInsets = windowInsetsCompat.toWindowInsets() - if (SDK_INT < 31 || windowInsets == null) - return Insets.NONE - - val wWidth = window.decorView.width - val wHeight = window.decorView.height - - var l = 0 - var t = 0 - var r = 0 - var b = 0 - - windowInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT)?.center?.let { - t = max(t, it.y) - l = max(l, it.x) - } - windowInsets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT)?.center?.let { - t = max(t, it.y) - r = max(r, wWidth - it.x) - } - windowInsets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT)?.center?.let { - b = max(b, wHeight - it.y) - l = max(l, it.x) - } - windowInsets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT)?.center?.let { - b = max(b, wHeight - it.y) - r = max(r, wWidth - it.x) - } - - // Corner insets are only applied along longer axis. Applying along both axis is unnecessary. - if (wWidth > wHeight) - return Insets.of(l, 0, r, 0) - else - return Insets.of(0, t, 0, b) - } - - /** - * Transforms given insets [insets] from Window's coordinates to [view]'s coordinates - */ - private fun windowInsetsToViewInsets(insets: Insets, view: View): Insets { - val viewLocation = intArrayOf(0, 0) - view.getLocationInWindow(viewLocation) - - // View frame in window coordinates - val vl = viewLocation[0] - val vt = viewLocation[1] - val vr = vl + view.width - val vb = vt + view.height - - // Insets applicable to given view - val l = max(0, insets.left - vl) - val t = max(0, insets.top - vt) - val r = max(0, insets.right - (window.decorView.width - vr)) - val b = max(0, insets.bottom - (window.decorView.height - vb)) - - return Insets.of(l, t, r, b) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LoginFragment.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LoginFragment.kt deleted file mode 100644 index 9f3a968..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/LoginFragment.kt +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.app.Dialog -import android.os.Bundle -import android.util.ArrayMap -import android.widget.ArrayAdapter -import androidx.core.view.isVisible -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Observer -import com.example.tiny_computer.R -import com.example.tiny_computer.databinding.FragmentCredentialBinding -import com.gaurav.avnc.model.LoginInfo -import com.gaurav.avnc.model.ServerProfile -import com.gaurav.avnc.viewmodel.VncViewModel -import com.gaurav.avnc.viewmodel.VncViewModel.State.Companion.isConnected -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.textfield.TextInputLayout - -/** - * Allows user to enter login information. - * - * There are different types of login information ([LoginInfo.Type]), - * but all of them basically boils down to a username/password combo. - * - * User can choose to "remember" the information, in which case it will be - * saved in the profile. - * - */ -class LoginFragment : DialogFragment() { - private lateinit var binding: FragmentCredentialBinding - private val viewModel by activityViewModels() - private val loginType by lazy { viewModel.loginInfoRequest.value!! } - private val loginInfo by lazy { getLoginInfoFromProfile(viewModel.profile) } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - binding = FragmentCredentialBinding.inflate(layoutInflater, null, false) - - binding.loginInfo = loginInfo - binding.usernameLayout.isVisible = loginInfo.username.isBlank() && loginType == LoginInfo.Type.VNC_CREDENTIAL - binding.passwordLayout.isVisible = loginInfo.password.isBlank() - binding.remember.isVisible = viewModel.profile.ID != 0L && loginType != LoginInfo.Type.SSH_KEY_PASSWORD - - if (loginType == LoginInfo.Type.SSH_KEY_PASSWORD) { - binding.passwordLayout.setHint(R.string.hint_key_password) - binding.pkPasswordMsg.isVisible = viewModel.profile.sshPrivateKeyPassword.isNotBlank() - } - - setupAutoComplete() - isCancelable = false - - return MaterialAlertDialogBuilder(requireContext()) - .setTitle(getTitle()) - .setView(binding.root) - .setPositiveButton(android.R.string.ok) { _, _ -> onOk() } - .setNegativeButton(android.R.string.cancel) { _, _ -> onCancel() } - .create() - } - - private fun getTitle() = when (loginType) { - LoginInfo.Type.VNC_PASSWORD, - LoginInfo.Type.VNC_CREDENTIAL -> R.string.title_vnc_login - LoginInfo.Type.SSH_PASSWORD -> R.string.title_ssh_login - LoginInfo.Type.SSH_KEY_PASSWORD -> R.string.title_unlock_private_key - } - - private fun getLoginInfoFromProfile(p: ServerProfile): LoginInfo { - return when (loginType) { - LoginInfo.Type.VNC_PASSWORD -> LoginInfo(p.name, p.host, "", p.password) - LoginInfo.Type.VNC_CREDENTIAL -> LoginInfo(p.name, p.host, p.username, p.password) - LoginInfo.Type.SSH_PASSWORD -> LoginInfo(p.name, p.sshHost, "", p.sshPassword) - LoginInfo.Type.SSH_KEY_PASSWORD -> LoginInfo(p.name, p.sshHost, "", "" /*p.sshPrivateKeyPassword*/) - } - } - - private fun setLoginInfoInProfile(p: ServerProfile, l: LoginInfo) { - when (loginType) { - LoginInfo.Type.VNC_PASSWORD -> p.password = l.password - LoginInfo.Type.VNC_CREDENTIAL -> { - p.username = l.username - p.password = l.password - } - LoginInfo.Type.SSH_PASSWORD -> p.sshPassword = l.password - LoginInfo.Type.SSH_KEY_PASSWORD -> p.sshPrivateKeyPassword = "" /* key password is not saved anymore */ - } - } - - private fun onOk() { - loginInfo.password = getRealPassword(loginInfo.password) - viewModel.loginInfoRequest.offerResponse(loginInfo) - if (binding.remember.isChecked || binding.pkPasswordMsg.isVisible /* to forget saved password */) - saveLoginInfo(loginInfo) - } - - private fun onCancel() { - viewModel.loginInfoRequest.cancelRequest() - requireActivity().finish() - } - - /** - * If user has asked to remember credentials, we need to save them - * to database. But we don't want to save them immediately because - * user might have mistyped them. So, we wait until successful - * connection before saving them. - */ - private fun saveLoginInfo(loginInfo: LoginInfo) { - // Use activity as owner because this fragment will likely be destroyed before connecting - viewModel.state.observe(requireActivity(), object : Observer { - override fun onChanged(value: VncViewModel.State) { - if (value.isConnected) { - setLoginInfoInProfile(viewModel.profile, loginInfo) - viewModel.saveProfile() - viewModel.state.removeObserver(this) - } - } - }) - } - - /** - * Hooks completion adapters - * - * This feature might not be that useful to end-users, but it saves a lot of time - * during development because I have to frequently install/uninstall app, test - * different servers running on different addresses/ports. - */ - private fun setupAutoComplete() { - - viewModel.savedProfiles.observe(this) { profiles -> - val logins = profiles.map { getLoginInfoFromProfile(it) } - val usernames = logins.map { it.username }.filter { it.isNotEmpty() }.distinct() - val passwords = preparePasswordSuggestions(logins) - - if (usernames.isNotEmpty()) { - val usernameAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, usernames) - binding.username.setAdapter(usernameAdapter) - binding.usernameLayout.endIconMode = TextInputLayout.END_ICON_DROPDOWN_MENU - } - - if (passwords.isNotEmpty()) { - val passwordAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, passwords) - binding.password.setAdapter(passwordAdapter) - binding.passwordLayout.endIconMode = TextInputLayout.END_ICON_DROPDOWN_MENU - } - } - } - - /** - * Instead of showing plaintext passwords, we show server name & host in suggestion - * list. When user taps OK, we convert the suggestion back to real password. - */ - private val passwordMap = ArrayMap() - - private fun preparePasswordSuggestions(list: List): List { - list.filter { it.password.isNotEmpty() } - .map { Pair("from: ${it.name} [${it.host}]", it.password) } - .distinct() - .toMap(passwordMap) - .removeAll(passwordMap.values) //Guard against (very unlikely) clash with real password - - return passwordMap.keys.toList() - } - - private fun getRealPassword(typedPassword: String) = passwordMap[typedPassword] ?: typedPassword -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Toolbar.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Toolbar.kt deleted file mode 100644 index b381628..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/Toolbar.kt +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.annotation.SuppressLint -import android.graphics.Rect -import android.os.Build -import android.view.GestureDetector -import android.view.Gravity -import android.view.MotionEvent -import android.view.View -import android.widget.Toast -import androidx.annotation.RequiresApi -import androidx.annotation.StringRes -import androidx.core.view.GravityCompat -import androidx.drawerlayout.widget.DrawerLayout -import androidx.lifecycle.lifecycleScope -import com.example.tiny_computer.R -import com.gaurav.avnc.viewmodel.VncViewModel.State -import com.gaurav.avnc.viewmodel.VncViewModel.State.Companion.isConnected -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch - -/** - * - * Overview of toolbar layout: - * - * DrawerLayout - * +-------------------+--------------+ - * | | | - * | Toolbar Drawer | | - * | [drawerView] | | - * | | | - * |+---+ | | - * || B | | | - * || t | | | - * || n |+------------+| Scrim | - * || s || Flyout || | - * |+---++------------+| | - * | | | - * | | | - * | | | - * | | | - * | | | - * +-------------------+--------------+ - * - * User can align the toolbar to left or right edge. - * - */ -class Toolbar(private val activity: VncActivity, private val dispatcher: Dispatcher) { - private val viewModel = activity.viewModel - private val binding = activity.binding.toolbar - private val drawerLayout = activity.binding.drawerLayout - private val drawerView = binding.root - private val openWithSwipe = viewModel.pref.viewer.toolbarOpenWithSwipe - - fun initialize() { - binding.keyboardBtn.setOnClickListener { activity.showKeyboard(); close() } - binding.zoomOptions.setOnLongClickListener { resetZoomToDefault(); close(); true } - binding.zoomResetBtn.setOnClickListener { resetZoomToDefault(); close() } - binding.zoomResetBtn.setOnLongClickListener { resetZoom(); close(); true } - binding.zoomLockBtn.isChecked = viewModel.profile.fZoomLocked - binding.zoomLockBtn.setOnCheckedChangeListener { _, checked -> toggleZoomLock(checked); close() } - binding.zoomSaveBtn.setOnClickListener { saveZoom(); close() } - binding.virtualKeysBtn.setOnClickListener { activity.virtualKeys.show(); close() } - - // Root view is transparent. Click on it should work just like a click in scrim area - drawerView.setOnClickListener { close() } - - viewModel.state.observe(activity) { onStateChange(it) } - - setupAlignment() - setupFlyoutClose() - setupGestureStyleSelection() - setupGestureExclusionRect() - setupDrawerCloseOnScrimSwipe() - } - - fun open() { - drawerLayout.openDrawer(drawerView) - } - - fun close() { - drawerLayout.closeDrawer(drawerView) - } - - private fun toast(@StringRes msgRes: Int) = Toast.makeText(activity, msgRes, Toast.LENGTH_SHORT).show() - - private fun resetZoom() { - viewModel.resetZoom() - toast(R.string.msg_zoom_reset) - } - - private fun resetZoomToDefault() { - viewModel.resetZoomToDefault() - toast(R.string.msg_zoom_reset_default) - } - - private fun toggleZoomLock(enabled: Boolean) { - viewModel.toggleZoomLock(enabled) - toast(if (enabled) R.string.msg_zoom_locked else R.string.msg_zoom_unlocked) - } - - private fun saveZoom() { - viewModel.saveZoom() - toast(R.string.msg_zoom_saved) - } - - private fun setupGestureStyleSelection() { - val styleButtonMap = mapOf( - "auto" to R.id.gesture_style_auto, - "touchscreen" to R.id.gesture_style_touchscreen, - "touchpad" to R.id.gesture_style_touchpad - ) - - binding.gestureStyleGroup.let { group -> - group.check(styleButtonMap[viewModel.profile.gestureStyle] ?: -1) - group.setOnCheckedChangeListener { _, id -> - for ((k, v) in styleButtonMap) - if (v == id) viewModel.profile.gestureStyle = k - viewModel.saveProfile() - dispatcher.onGestureStyleChanged() - close() - } - } - } - - private fun onStateChange(state: State) { - if (state.isConnected) - highlightForFirstTimeUser() - - if (Build.VERSION.SDK_INT >= 29) - updateGestureExclusionRect() - - updateLockMode(state.isConnected) - } - - /** - * Open the drawer for couple of seconds and then close it. - */ - private fun highlightForFirstTimeUser() { - if (!viewModel.pref.runInfo.hasConnectedSuccessfully) { - viewModel.pref.runInfo.hasConnectedSuccessfully = true - activity.lifecycleScope.launch { - open() - delay(2000) - close() - } - } - } - - private fun updateLockMode(isConnected: Boolean) { - if (isConnected && openWithSwipe) - drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED) - else - drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) - } - - - /** - * Setup gravity & layout direction - */ - @SuppressLint("RtlHardcoded") - private fun setupAlignment() { - val gravity = if (viewModel.pref.viewer.toolbarAlignment == "start") GravityCompat.START else GravityCompat.END - - val lp = drawerView.layoutParams as DrawerLayout.LayoutParams - lp.gravity = gravity - drawerView.layoutParams = lp - - // Before layout pass, layoutDirection should be retrieved from Activity config - val layoutDirection = activity.resources.configuration.layoutDirection - val isLeftAligned = Gravity.getAbsoluteGravity(gravity, layoutDirection) == Gravity.LEFT - - // We need the layout direction based on alignment rather than language/locale - // so that flyouts and button icons are properly ordered. - drawerView.layoutDirection = if (isLeftAligned) View.LAYOUT_DIRECTION_LTR else View.LAYOUT_DIRECTION_RTL - - // Let the gesture group have natural layout as it contains text elements - binding.gestureStyleGroup.layoutDirection = layoutDirection - } - - /** - * Setup gesture exclusion updates - */ - private fun setupGestureExclusionRect() { - if (Build.VERSION.SDK_INT >= 29) { - binding.primaryButtons.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> - updateGestureExclusionRect() - } - } - } - - /** - * Add System Gesture exclusion rects to allow toolbar opening when gesture navigation is active. - * Note: Some ROMs, e.g. MIUI, completely ignore whatever is set here. - */ - @RequiresApi(29) - private fun updateGestureExclusionRect() { - if (!openWithSwipe || !viewModel.state.value.isConnected) { - drawerLayout.systemGestureExclusionRects = listOf() - } else { - // Area covered by primaryButtons, in drawerLayout's coordinate space - val rect = Rect(drawerView.left, binding.primaryButtons.top, drawerView.right, binding.primaryButtons.bottom) - - if (rect.left < 0) rect.offset(-rect.left, 0) - if (rect.right > drawerLayout.width) rect.offset(-(rect.right - drawerLayout.width), 0) - - if (viewModel.pref.viewer.fullscreen) { - // For fullscreen activities, Android does not enforce the height limit of exclusion area. - // We could use the entire height for opening toolbar, but that will completely disable gestures. - // So we pad by one-third of available space in each direction - val padding = (drawerLayout.height - rect.height()) / 6 - if (padding > 0) { - rect.top -= padding - rect.bottom += padding - } - } - - drawerLayout.systemGestureExclusionRects = listOf(rect) - } - } - - /** - * Close flyouts after drawer is closed. - * - * We can't do this in [close] because that will change toolbar width _while_ drawer - * is closing. This can conflict with close animation, and mess with internal calculations - * of DrawerLayout, resulting in failure of close operation. - */ - private fun setupFlyoutClose() { - drawerLayout.addDrawerListener(object : DrawerLayout.SimpleDrawerListener() { - override fun onDrawerClosed(closedView: View) { - if (closedView == drawerView) { - binding.zoomOptions.isChecked = false - binding.gestureStyleToggle.isChecked = false - } - } - }) - } - - /** - * Normally, drawers in [DrawerLayout] are closed by two gestures: - * 1. Swipe 'on' the drawer - * 2. Tap inside Scrim (dimmed region outside of drawer) - * - * Notably, swiping inside scrim area does NOT hide the drawer. This can be jarring - * to users if drawer is relatively small & most of the layout area acts as scrim. - * The toolbar drawer is affected by this issue. - * - * This function attempts to detect these swipe gestures and close the drawer - * when they happen. - * - * Note: It will set a custom TouchListener on [drawerLayout]. - */ - @SuppressLint("ClickableViewAccessibility", "RtlHardcoded") - private fun setupDrawerCloseOnScrimSwipe() { - drawerLayout.setOnTouchListener(object : View.OnTouchListener { - var drawerOpen = false - var drawerGravity = Gravity.LEFT - - val detector = GestureDetector(drawerLayout.context, object : GestureDetector.SimpleOnGestureListener() { - - override fun onFling(e1: MotionEvent?, e2: MotionEvent, vX: Float, vY: Float): Boolean { - if ((drawerGravity == Gravity.LEFT && vX < 0) || (drawerGravity == Gravity.RIGHT && vX > 0)) { - close() - drawerOpen = false - } - return true - } - }) - - override fun onTouch(v: View, event: MotionEvent): Boolean { - if (event.actionMasked == MotionEvent.ACTION_DOWN) { - drawerOpen = drawerLayout.isDrawerOpen(drawerView) - drawerGravity = Gravity.getAbsoluteGravity( - (drawerView.layoutParams as DrawerLayout.LayoutParams).gravity, - drawerLayout.layoutDirection) and Gravity.HORIZONTAL_GRAVITY_MASK - } - - if (drawerOpen) - detector.onTouchEvent(event) - - return false - } - }) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/TouchHandler.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/TouchHandler.kt deleted file mode 100644 index b5b87e5..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/TouchHandler.kt +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.content.Context -import android.graphics.PointF -import android.os.Build -import android.view.GestureDetector -import android.view.GestureDetector.SimpleOnGestureListener -import android.view.HapticFeedbackConstants -import android.view.InputDevice -import android.view.MotionEvent -import android.view.ScaleGestureDetector -import android.view.ViewConfiguration -import com.gaurav.avnc.viewmodel.VncViewModel -import com.gaurav.avnc.vnc.PointerButton -import kotlin.math.PI -import kotlin.math.abs -import kotlin.math.atan2 -import kotlin.math.max - -/** - * Handler for touch events. It detects various gestures and notifies [dispatcher]. - */ -class TouchHandler(private val viewModel: VncViewModel, private val dispatcher: Dispatcher) - : ScaleGestureDetector.OnScaleGestureListener, SimpleOnGestureListener() { - - //Extension to easily access touch position - private fun MotionEvent.point() = PointF(x, y) - - /**************************************************************************************** - * Touch Event receivers - * - * Note: On some devices, 'Source' property for Stylus events is set to both - * [InputDevice.SOURCE_STYLUS] & [InputDevice.SOURCE_MOUSE]. Hence, we should - * pass the events to [handleStylusEvent] before [handleMouseEvent]. - ****************************************************************************************/ - - fun onTouchEvent(event: MotionEvent): Boolean { - val handled = handleStylusEvent(event) || handleMouseEvent(event) || handleGestureEvent(event) - handleGestureStartStop(event) - return handled - } - - fun onGenericMotionEvent(event: MotionEvent): Boolean { - return onHoverEvent(event) || handleStylusEvent(event) || handleMouseEvent(event) - } - - fun onHoverEvent(event: MotionEvent): Boolean { - if (event.actionMasked == MotionEvent.ACTION_HOVER_MOVE) { - lastHoverPoint = event.point() - dispatcher.onMouseMove(lastHoverPoint) - return true - } - return false - } - - private fun handleGestureStartStop(event: MotionEvent) { - when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> dispatcher.onGestureStart() - MotionEvent.ACTION_UP, - MotionEvent.ACTION_CANCEL -> dispatcher.onGestureStop(event.point()) - } - } - - // Used for back-press interception - private var lastHoverPoint = PointF() - fun onMouseBack() { - dispatcher.onMouseBack(lastHoverPoint) - } - - /**************************************************************************************** - * Mouse - ****************************************************************************************/ - private val mousePassthrough = viewModel.pref.input.mousePassthrough - - private fun handleMouseEvent(e: MotionEvent): Boolean { - if (Build.VERSION.SDK_INT < 23 || !mousePassthrough || !e.isFromSource(InputDevice.SOURCE_MOUSE)) - return false - - val p = e.point() - - when (e.actionMasked) { - MotionEvent.ACTION_BUTTON_PRESS -> dispatcher.onMouseButtonDown(convertButton(e.actionButton), p) - MotionEvent.ACTION_BUTTON_RELEASE -> dispatcher.onMouseButtonUp(convertButton(e.actionButton), p) - MotionEvent.ACTION_MOVE -> dispatcher.onMouseMove(p) - - MotionEvent.ACTION_SCROLL -> { - val hs = e.getAxisValue(MotionEvent.AXIS_HSCROLL) - val vs = e.getAxisValue(MotionEvent.AXIS_VSCROLL) - dispatcher.onMouseScroll(p, hs, vs) - } - } - - // Allow touchpad gestures to be passed on to GestureDetector - return !(e.buttonState == 0 && e.getToolType(0) != MotionEvent.TOOL_TYPE_MOUSE) - } - - /** - * Convert from [MotionEvent] button to [PointerButton] - */ - private fun convertButton(button: Int) = when (button) { - MotionEvent.BUTTON_PRIMARY -> PointerButton.Left - MotionEvent.BUTTON_SECONDARY -> PointerButton.Right - MotionEvent.BUTTON_TERTIARY -> PointerButton.Middle - else -> PointerButton.None - } - - - /**************************************************************************************** - * Stylus - ****************************************************************************************/ - private val stylusGestureDetector = GestureDetector(viewModel.app, StylusGestureListener()) - - private fun handleStylusEvent(event: MotionEvent): Boolean { - if (event.isFromSource(InputDevice.SOURCE_STYLUS) && - event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS) { - stylusGestureDetector.onTouchEvent(event) - return true - } - return false - } - - inner class StylusGestureListener : SimpleOnGestureListener() { - private var scrolling = false - - override fun onDown(e: MotionEvent): Boolean { - scrolling = false - return true - } - - override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - dispatcher.onStylusTap(e.point()) - return true - } - - override fun onDoubleTap(e: MotionEvent): Boolean { - dispatcher.onStylusDoubleTap(e.point()) - return true - } - - override fun onLongPress(e: MotionEvent) { - viewModel.frameViewRef.get()?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - dispatcher.onStylusLongPress(e.point()) - } - - override fun onScroll(e1: MotionEvent?, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean { - // Scrolling with stylus button pressed is currently used for scale gesture - if (e1 != null && e2.buttonState and MotionEvent.BUTTON_STYLUS_PRIMARY == 0) { - - // When scrolling starts, we need to send the first event at initial touch-point. - // Otherwise, we will loose the small distance (touch-slope) required by onScroll(). - if (!scrolling) { - scrolling = true - dispatcher.onStylusScroll(e1.point()) - } - dispatcher.onStylusScroll(e2.point()) - } - return true - } - } - - - /**************************************************************************************** - * Finger Gestures (and everything else beside mouse & stylus) - ****************************************************************************************/ - private val scaleDetector = ScaleGestureDetector(viewModel.app, this).apply { isQuickScaleEnabled = false } - private val gestureDetector = GestureDetectorEx(viewModel.app, FingerGestureListener()) - private val swipeVsScale = SwipeVsScale() - private val longPressSwipeEnabled = viewModel.pref.input.gesture.longPressSwipeEnabled - private val swipeSensitivity = viewModel.pref.input.gesture.swipeSensitivity - - - private fun handleGestureEvent(event: MotionEvent): Boolean { - swipeVsScale.onTouchEvent(event) - scaleDetector.onTouchEvent(event) - return gestureDetector.onTouchEvent(event) - } - - override fun onScaleBegin(detector: ScaleGestureDetector) = true - override fun onScaleEnd(detector: ScaleGestureDetector) {} - override fun onScale(detector: ScaleGestureDetector): Boolean { - if (swipeVsScale.shouldScale()) - dispatcher.onScale(detector.scaleFactor, detector.focusX, detector.focusY) - return true - } - - private inner class FingerGestureListener : GestureDetectorEx.GestureListenerEx { - - override fun onSingleTapConfirmed(e: MotionEvent) = dispatcher.onTap1(e.point()) - override fun onDoubleTapConfirmed(e: MotionEvent) = dispatcher.onDoubleTap(e.point()) - - override fun onMultiFingerTap(e: MotionEvent, fingerCount: Int) { - when (fingerCount) { - 2 -> dispatcher.onTap2(e.point()) - // Taps by 3+ fingers are not exposed yet - } - } - - override fun onLongPress(e: MotionEvent) { - viewModel.frameViewRef.get()?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - - // If long-press-swipe is disabled, we can dispatch long-press immediately - if (!longPressSwipeEnabled) dispatcher.onLongPress(e.point()) - } - - override fun onLongPressConfirmed(e: MotionEvent) { - if (longPressSwipeEnabled) dispatcher.onLongPress(e.point()) - } - - - override fun onScroll(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) { - val startPoint = e1.point() - val currentPoint = e2.point() - val normalizedDx = dx * swipeSensitivity - val normalizedDy = dy * swipeSensitivity - - when (e2.pointerCount) { - 1 -> dispatcher.onSwipe1(startPoint, currentPoint, normalizedDx, normalizedDy) - 2 -> if (swipeVsScale.shouldSwipe()) - dispatcher.onSwipe2(startPoint, currentPoint, normalizedDx, normalizedDy) - } - } - - override fun onScrollAfterLongPress(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) { - dispatcher.onLongPressSwipe(e1.point(), e2.point(), dx, dy) - } - - override fun onScrollAfterDoubleTap(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) { - dispatcher.onDoubleTapSwipe(e1.point(), e2.point(), dx, dy) - } - - override fun onFling(velocityX: Float, velocityY: Float) { - dispatcher.onFling(velocityX, velocityY) - } - } - - /** - * Stock [GestureDetector] only detects the most common gestures. But we need to - * detect some more gestures to provide maximum flexibility to the user. - * - * [GestureDetectorEx] is used to for this purpose. It internally uses stock - * [GestureDetector], and some custom event processing to detect more gestures. - */ - private class GestureDetectorEx(context: Context, val listener: GestureListenerEx) { - - /** - * Detected gestures. Some of these come directly from stock [GestureDetector], - * while the following are custom detected: - * - * [onDoubleTapConfirmed] - * To support double-tap-swipe gesture, double-tap is not immediately triggered on - * ACTION_DOWN of second tap. Instead, [doubleTapDetected] flag is set, and when - * final ACTION_UP is received (within timeout), [onDoubleTapConfirmed] is called. - * - * [onMultiFingerTap] - * Maximum number of fingers that went down is tracked in [maxFingerDown]. If - * ACTION_UP is received within a timeout, and more than one finger went down - * without any scrolling, [onMultiFingerTap] is called. - * - * [onLongPressConfirmed] - * Similar to [onDoubleTapConfirmed], to support long-press-swipe, we wait for - * ACTION_UP to confirm long-press. - * Note: [onLongPress] is always called immediately. It enables haptic feedback - * and supports cases where waiting for [onLongPressConfirmed] is not necessary. - * - * [onScrollAfterDoubleTap] - * This is the double-tap-swipe gesture. If scrolling after [doubleTapDetected] flag - * is set, [onScrollAfterDoubleTap] is called. - * - * [onScrollAfterLongPress] - * This is the long-press-swipe gesture. If scrolling after [longPressDetected] flag - * is set, [onScrollAfterLongPress] is called. - */ - interface GestureListenerEx { - fun onSingleTapConfirmed(e: MotionEvent) - fun onDoubleTapConfirmed(e: MotionEvent) - fun onMultiFingerTap(e: MotionEvent, fingerCount: Int) - - fun onLongPress(e: MotionEvent) - fun onLongPressConfirmed(e: MotionEvent) - - fun onScroll(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) - fun onScrollAfterLongPress(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) - fun onScrollAfterDoubleTap(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) - - fun onFling(velocityX: Float, velocityY: Float) - } - - - /** - * Stock [GestureDetector] has two unwanted behaviours: - * - If long-press or double-tap is detected, scroll events will not be reported anymore. - * - If you don't lift the finger after double-tap, a long-press will be triggered. - * - * Fortunately, [GestureDetector] lets us disable long-press detection, which allows us - * to use a combination of multiple [GestureDetector]s to overcome the restrictions: - * - * - +------------------+ - * - +->| [innerDetector1] | - * - | +------------------+ - * - | (tap, long-press) - * - +----------------+ event | - * - | [onTouchEvent] |---------+ - * - +----------------+ | - * - | - * - | +------------------+ double-tap event +------------------+ - * - +->| [innerDetector2] |-------------------->| [innerDetector3] | - * - +------------------+ +------------------+ - * - (double-tap) (double-tap-swipe) - * - */ - private val innerDetector1 = GestureDetector(context, InnerListener1()) - private val innerDetector2 = GestureDetector(context, InnerListener2()).apply { setIsLongpressEnabled(false) } - private val innerDetector3 = GestureDetector(context, InnerListener3()).apply { setIsLongpressEnabled(false) } - - private var longPressDetected = false - private var doubleTapDetected = false - private var scrolling = false - private var maxFingerDown = 0 - private var currentDownEvent: MotionEvent? = null - - - private inner class InnerListener1 : SimpleOnGestureListener() { - override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - listener.onSingleTapConfirmed(e) - return true - } - - override fun onLongPress(e: MotionEvent) { - if (doubleTapDetected) - return // Ignore long-press triggered during double-tap-swipe - - longPressDetected = true - listener.onLongPress(e) - } - - override fun onFling(e1: MotionEvent?, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { - listener.onFling(velocityX, velocityY) - return true - } - } - - private inner class InnerListener2 : SimpleOnGestureListener() { - override fun onDoubleTap(e: MotionEvent): Boolean { - doubleTapDetected = true - return true - } - - override fun onDoubleTapEvent(e: MotionEvent) = innerDetector3.onTouchEvent(e) - - override fun onScroll(e1: MotionEvent?, e2: MotionEvent, dx: Float, dy: Float) = handleScroll(e1, e2, dx, dy) - } - - private inner class InnerListener3 : SimpleOnGestureListener() { - override fun onScroll(e1: MotionEvent?, e2: MotionEvent, dx: Float, dy: Float) = handleScroll(e1, e2, dx, dy) - } - - private fun handleScroll(e1: MotionEvent?, e2: MotionEvent, dx: Float, dy: Float): Boolean { - e1 ?: return false - if (!scrolling) { - scrolling = true - // Send first scroll event on initial touch-down point, because GestureDetector - // requires certain amount of finger movement before scroll is triggered, and - // we don't want to 'loose' that small movement. - callOnScroll(e1, e1, 0f, 0f) - } - - callOnScroll(e1, e2, -dx, -dy) - return true - } - - private fun callOnScroll(e1: MotionEvent, e2: MotionEvent, dx: Float, dy: Float) { - if (doubleTapDetected) - listener.onScrollAfterDoubleTap(e1, e2, dx, dy) - else if (longPressDetected) - listener.onScrollAfterLongPress(e1, e2, dx, dy) - else - listener.onScroll(e1, e2, dx, dy) - } - - /** - * Event receiver - */ - fun onTouchEvent(e: MotionEvent): Boolean { - innerDetector1.onTouchEvent(e) - innerDetector2.onTouchEvent(e) - - when (e.actionMasked) { - MotionEvent.ACTION_DOWN -> { - maxFingerDown = 1 - currentDownEvent = MotionEvent.obtain(e) - } - - MotionEvent.ACTION_POINTER_DOWN -> { - maxFingerDown = max(maxFingerDown, e.pointerCount) - } - - MotionEvent.ACTION_UP -> { - currentDownEvent?.let { downEvent -> - if (longPressDetected && !doubleTapDetected && !scrolling && maxFingerDown <= 1) - listener.onLongPressConfirmed(downEvent) - - if (doubleTapDetected && !longPressDetected && !scrolling && maxFingerDown <= 1) - listener.onDoubleTapConfirmed(downEvent) - - val gestureDuration = (e.eventTime - downEvent.eventTime) - if (maxFingerDown > 1 && !scrolling && gestureDuration < ViewConfiguration.getDoubleTapTimeout()) - listener.onMultiFingerTap(downEvent, maxFingerDown) - } - - reset() - } - - MotionEvent.ACTION_CANCEL -> reset() - } - - return true - } - - private fun reset() { - longPressDetected = false - doubleTapDetected = false - scrolling = false - maxFingerDown = 0 - currentDownEvent?.recycle() - currentDownEvent = null - } - } - - - /** - * Swipe vs Scale detector. - * - * Many two-finger gestures are detected as both swipe & scale gestures because - * [GestureDetector] & [ScaleGestureDetector] work independently. This works - * very well when two-finger swipe pref is set to 'pan' (default value). - * But when the pref is set to 'remote-scroll', this independent detection - * becomes an issue. When user tries to scale, it frequently triggers remote - * scrolling. And when user tries to scroll, it triggers scaling. - * - * This class tries to clearly differentiate between these two gestures. - * It works by tracking the fingers, and calculating the angle between two paths. - * Then [decide] between two gestures by comparing the angle to some thresholds. - * - * This class can mis-detect some gestures because fingers don't always move - * perfectly, but it does provide huge improvement over existing situation. - */ - private inner class SwipeVsScale { - private val enabled = viewModel.pref.input.gesture.swipe2 == "remote-scroll" - private var detecting = false - private var scaleDetected = false - private var swipeDetected = false - - private var f1Id = 0 // Finger 1 - private var f2Id = 0 // Finger 2 - private val f1Start = PointF() - private val f2Start = PointF() - private val f1Current = PointF() - private val f2Current = PointF() - - - fun onTouchEvent(e: MotionEvent) { - if (!enabled) - return - - when (e.actionMasked) { - MotionEvent.ACTION_DOWN, - MotionEvent.ACTION_CANCEL, - MotionEvent.ACTION_UP, - MotionEvent.ACTION_POINTER_UP -> { - detecting = false - scaleDetected = false - swipeDetected = false - } - - MotionEvent.ACTION_POINTER_DOWN -> { - detecting = e.pointerCount == 2 - if (detecting) { - f1Id = e.getPointerId(0) - f2Id = e.getPointerId(1) - f1Start.set(e.getX(0), e.getY(0)) - f2Start.set(e.getX(1), e.getY(1)) - f1Current.set(f1Start) - f2Current.set(f2Start) - } - } - - MotionEvent.ACTION_MOVE -> { - if (detecting) { - val i1 = e.findPointerIndex(f1Id) - val i2 = e.findPointerIndex(f2Id) - if (i1 != -1 && i2 != -1) { - f1Current.set(e.getX(i1), e.getY(i1)) - f2Current.set(e.getX(i2), e.getY(i2)) - } - } - } - } - } - - fun shouldScale(): Boolean { - decide() - return !enabled || (detecting && scaleDetected) - } - - fun shouldSwipe(): Boolean { - decide() - return !enabled || (detecting && swipeDetected) - } - - /** - * Decides if gesture can be considered a swipe/scale - */ - private fun decide() { - if (!detecting) - return - - val t1 = theta(f1Start, f1Current) - val t2 = theta(f2Start, f2Current) - val diff = abs(t1 - t2) - - scaleDetected = diff > 45 - swipeDetected = diff < 30 - } - - /** - * Returns the angle made by line [p1]->[p2] with the positive x-axis. - * Returned angle will be in range [0, 360] - */ - private fun theta(p1: PointF, p2: PointF): Double { - val theta = atan2(p2.y - p1.y, p2.x - p1.x) - val degree = (theta / PI) * 180 - return (degree + 360) % 360 // Map [-180, 180] to [0, 360] - } - } -} diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VirtualKeys.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VirtualKeys.kt deleted file mode 100644 index 96d2ac8..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VirtualKeys.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.annotation.SuppressLint -import android.view.MotionEvent -import android.view.View -import android.view.ViewConfiguration -import androidx.databinding.BindingAdapter -import com.example.tiny_computer.databinding.VirtualKeysBinding - -/** - * Virtual keys allow the user to input keys which are not normally found on - * keyboards but can be useful for controlling remote server. - * - * This class manages the inflation & visibility of virtual keys. - */ -class VirtualKeys(activity: VncActivity) { - - private val pref = activity.viewModel.pref.input - private val keyHandler = activity.keyHandler - private val stub = activity.binding.virtualKeysStub - private var openedWithKb = false - - val container: View? get() = stub.root - - fun show() { - init() - container?.visibility = View.VISIBLE - } - - fun hide() { - container?.visibility = View.GONE - openedWithKb = false //Reset flag - } - - fun onKeyboardOpen() { - if (pref.vkOpenWithKeyboard && container?.visibility != View.VISIBLE) { - show() - openedWithKb = true - } - } - - fun onKeyboardClose() { - if (openedWithKb) { - hide() - openedWithKb = false - } - } - - fun releaseMetaKeys() { - val binding = stub.binding as? VirtualKeysBinding - binding?.apply { - superBtn.isChecked = false - shiftBtn.isChecked = false - ctrlBtn.isChecked = false - altBtn.isChecked = false - } - } - - private fun init() { - if (stub.isInflated) - return - - stub.viewStub?.inflate() - val binding = stub.binding as VirtualKeysBinding - binding.h = keyHandler - binding.showAll = pref.vkShowAll - binding.hideBtn.setOnClickListener { hide() } - } -} - -/** - * When a View is touched, we schedule a callback to to simulate a click. - * As long as finger stays on the view, we keep repeating this callback. - * - * Another option here is to send VNC KeyEvent(down) on [MotionEvent.ACTION_DOWN] - * and then send VNC KeyEvent(up) on [MotionEvent.ACTION_UP]. - */ -@BindingAdapter("isRepeatable") -fun repeatableKeyBinding(keyView: View, repeatable: Boolean) { - if (!repeatable) - return - - keyView.setOnTouchListener(object : View.OnTouchListener { - private var doRepeat = false - - private fun repeat(v: View) { - if (doRepeat) { - v.performClick() - v.postDelayed({ repeat(v) }, ViewConfiguration.getKeyRepeatDelay().toLong()) - } - } - - @SuppressLint("ClickableViewAccessibility") - override fun onTouch(v: View, event: MotionEvent): Boolean { - when (event.actionMasked) { - MotionEvent.ACTION_DOWN -> { - doRepeat = true - v.postDelayed({ repeat(v) }, ViewConfiguration.getKeyRepeatTimeout().toLong()) - } - - MotionEvent.ACTION_POINTER_DOWN, - MotionEvent.ACTION_UP, - MotionEvent.ACTION_CANCEL -> { - doRepeat = false - } - } - return false - } - }) -} diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VncActivity.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VncActivity.kt deleted file mode 100644 index c9c3fc8..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/VncActivity.kt +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc - -import android.app.Activity -import android.app.PictureInPictureParams -import android.content.Context -import android.content.Intent -import android.content.pm.ActivityInfo -import android.content.res.Configuration -import android.os.Build -import android.os.Bundle -import android.os.Parcelable -import android.os.SystemClock -import android.util.Log -import android.util.Rational -import android.view.InputDevice -import android.view.KeyEvent -import android.view.WindowManager -import android.view.inputmethod.InputMethodManager -import android.widget.Toast -import androidx.activity.viewModels -import androidx.annotation.RequiresApi -import androidx.appcompat.app.AppCompatActivity -import androidx.core.os.BundleCompat -import androidx.core.view.isVisible -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import androidx.lifecycle.viewmodel.initializer -import androidx.lifecycle.viewmodel.viewModelFactory -import com.example.tiny_computer.R -import com.example.tiny_computer.databinding.ActivityVncBinding -import com.gaurav.avnc.model.ServerProfile -import com.gaurav.avnc.util.DeviceAuthPrompt -import com.gaurav.avnc.util.SamsungDex -import com.gaurav.avnc.viewmodel.VncViewModel -import com.gaurav.avnc.viewmodel.VncViewModel.State.Companion.isConnected -import com.gaurav.avnc.viewmodel.VncViewModel.State.Companion.isDisconnected -import com.gaurav.avnc.vnc.VncUri -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.parcelize.Parcelize -import java.lang.ref.WeakReference - -/********** [VncActivity] startup helpers *********************************/ - -private const val PROFILE_KEY = "com.gaurav.avnc.server_profile" -private const val FRAME_STATE_KEY = "com.gaurav.avnc.frame_state" - -fun createVncIntent(context: Context, profile: ServerProfile): Intent { - return Intent(context, VncActivity::class.java).apply { - putExtra(PROFILE_KEY, profile) - } -} - -fun startVncActivity(source: Activity, profile: ServerProfile) { - source.startActivity(createVncIntent(source, profile)) -} - -fun startVncActivity(source: Activity, uri: VncUri) { - startVncActivity(source, uri.toServerProfile()) -} - -@Parcelize -private data class SavedFrameState(val frameX: Float, val frameY: Float, val zoom1: Float, val zoom2: Float) : Parcelable - -private fun startVncActivity(source: Activity, profile: ServerProfile, frameState: SavedFrameState) { - source.startActivity(createVncIntent(source, profile).also { it.putExtra(FRAME_STATE_KEY, frameState) }) -} -/**************************************************************************/ - - -/** - * This activity handles the connection to a VNC server. - */ -class VncActivity : AppCompatActivity() { - - lateinit var viewModel: VncViewModel - lateinit var binding: ActivityVncBinding - private val dispatcher by lazy { Dispatcher(this) } - val touchHandler by lazy { TouchHandler(viewModel, dispatcher) } - val keyHandler by lazy { KeyHandler(dispatcher, viewModel.profile.fLegacyKeySym, viewModel.pref) } - val virtualKeys by lazy { VirtualKeys(this) } - private val serverUnlockPrompt = DeviceAuthPrompt(this) - private val layoutManager by lazy { LayoutManager(this) } - private val toolbar by lazy { Toolbar(this, dispatcher) } - private var restoredFromBundle = false - private var wasConnectedWhenStopped = false - private var onStartTime = 0L - - override fun onCreate(savedInstanceState: Bundle?) { - DeviceAuthPrompt.applyFingerprintDialogFix(supportFragmentManager) - - super.onCreate(savedInstanceState) - if (!loadViewModel(savedInstanceState)) { - finish() - return - } - - viewModel.initConnection() - - //Main UI - binding = DataBindingUtil.setContentView(this, R.layout.activity_vnc) - binding.viewModel = viewModel - binding.lifecycleOwner = this - binding.frameView.initialize(this) - viewModel.frameViewRef = WeakReference(binding.frameView) - toolbar.initialize() - - setupLayout() - setupServerUnlock() - - //Observers - binding.reconnectBtn.setOnClickListener { retryConnection() } - viewModel.loginInfoRequest.observe(this) { showLoginDialog() } - viewModel.sshHostKeyVerifyRequest.observe(this) { showHostKeyDialog() } - viewModel.state.observe(this) { onClientStateChanged(it) } - - savedInstanceState?.let { - restoredFromBundle = true - wasConnectedWhenStopped = it.getBoolean("wasConnectedWhenStopped") - } - } - - override fun onStart() { - super.onStart() - binding.frameView.onResume() - viewModel.resumeFrameBufferUpdates() - onStartTime = SystemClock.uptimeMillis() - - // Refresh framebuffer on activity restart: - // - It forces read/write on the socket. This allows us to verify the socket, which might have - // been closed by the server while app process was frozen in background - // - It also attempts to fix some unusual cases of old updates requests being lost while AVNC - // was frozen by the system - if (wasConnectedWhenStopped) viewModel.refreshFrameBuffer() - } - - override fun onStop() { - super.onStop() - virtualKeys.releaseMetaKeys() - binding.frameView.onPause() - viewModel.pauseFrameBufferUpdates() - wasConnectedWhenStopped = viewModel.state.value.isConnected - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putParcelable(PROFILE_KEY, viewModel.profile) - outState.putBoolean("wasConnectedWhenStopped", wasConnectedWhenStopped || viewModel.state.value.isConnected) - } - - private fun loadViewModel(savedState: Bundle?): Boolean { - @Suppress("DEPRECATION") - val profile = savedState?.getParcelable(PROFILE_KEY) - ?: intent.getParcelableExtra(PROFILE_KEY) - - if (profile == null) { - Toast.makeText(this, "Error: Missing Server Info", Toast.LENGTH_LONG).show() - return false - } - - val factory = viewModelFactory { initializer { VncViewModel(profile, application) } } - viewModel = viewModels { factory }.value - return true - } - - private fun retryConnection(seamless: Boolean = false) { - //We simply create a new activity to force creation of new ViewModel - //which effectively restarts the connection. - if (!isFinishing) { - val savedFrameState = viewModel.frameState.let { - SavedFrameState(frameX = it.frameX, frameY = it.frameY, zoom1 = it.zoomScale1, zoom2 = it.zoomScale2) - } - - startVncActivity(this, viewModel.profile, savedFrameState) - - if (seamless) { - @Suppress("DEPRECATION") - overridePendingTransition(0, 0) - } - finish() - } - } - - private fun setupServerUnlock() { - serverUnlockPrompt.init( - onSuccess = { viewModel.serverUnlockRequest.offerResponse(true) }, - onFail = { viewModel.serverUnlockRequest.offerResponse(false) } - ) - - viewModel.serverUnlockRequest.observe(this) { - if (serverUnlockPrompt.canLaunch()) - serverUnlockPrompt.launch(getString(R.string.title_unlock_dialog)) - else - viewModel.serverUnlockRequest.offerResponse(true) - } - } - - private fun showLoginDialog() { - LoginFragment().show(supportFragmentManager, "LoginDialog") - } - - private fun showHostKeyDialog() { - HostKeyFragment().show(supportFragmentManager, "HostKeyFragment") - } - - fun showKeyboard() { - val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - - binding.frameView.requestFocus() - imm.showSoftInput(binding.frameView, 0) - - virtualKeys.onKeyboardOpen() - } - - private fun onClientStateChanged(newState: VncViewModel.State) { - val isConnected = newState.isConnected - - binding.frameView.isVisible = isConnected - binding.frameView.keepScreenOn = isConnected && viewModel.pref.viewer.keepScreenOn - SamsungDex.setMetaKeyCapture(this, isConnected) - layoutManager.onConnectionStateChanged() - updateStatusContainerVisibility(isConnected) - autoReconnect(newState) - - if (isConnected && !restoredFromBundle) { - incrementUseCount() - restoreFrameState() - } - } - - private fun incrementUseCount() { - viewModel.profile.useCount += 1 - viewModel.saveProfile() - } - - private fun updateStatusContainerVisibility(isConnected: Boolean) { - binding.statusContainer.isVisible = true - binding.statusContainer - .animate() - .alpha(if (isConnected) 0f else 1f) - .withEndAction { binding.statusContainer.isVisible = !isConnected } - } - - private fun restoreFrameState() { - intent.extras?.let { extras -> - BundleCompat.getParcelable(extras, FRAME_STATE_KEY, SavedFrameState::class.java)?.let { - viewModel.setZoom(it.zoom1, it.zoom2) - viewModel.panFrame(it.frameX, it.frameY) - } - } - } - - private var autoReconnecting = false - private fun autoReconnect(state: VncViewModel.State) { - if (!state.isDisconnected) - return - - // If disconnected when coming back from background, try to reconnect immediately - if (wasConnectedWhenStopped && (SystemClock.uptimeMillis() - onStartTime) in 0..2000) { - Log.d(javaClass.simpleName, "Disconnected while in background, reconnecting ...") - retryConnection(true) - } - - if (autoReconnecting || !viewModel.pref.server.autoReconnect) - return - - autoReconnecting = true - lifecycleScope.launch { - lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { - val timeout = 5 //seconds, must be >1 - repeat(timeout) { - binding.autoReconnectProgress.setProgressCompat((100 * it) / (timeout - 1), true) - delay(1000) - if (it >= (timeout - 1)) - retryConnection() - } - } - } - } - - /************************************************************************************ - * Layout handling. - ************************************************************************************/ - private fun setupLayout() { - setupOrientation() - layoutManager.initialize() - - if (Build.VERSION.SDK_INT >= 28 && viewModel.pref.viewer.drawBehindCutout) { - window.attributes = window.attributes.apply { - layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - } - } - } - - private fun setupOrientation() { - val choice = viewModel.profile.screenOrientation.let { - if (it != "auto") it else viewModel.pref.viewer.orientation - } - - requestedOrientation = when (choice) { - "portrait" -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT - "landscape" -> ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE - else -> ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - } - } - - override fun onWindowFocusChanged(hasFocus: Boolean) { - super.onWindowFocusChanged(hasFocus) - layoutManager.onWindowFocusChanged(hasFocus) - if (hasFocus) viewModel.sendClipboardText() - } - - - /************************************************************************************ - * Picture-in-Picture support - ************************************************************************************/ - - override fun onUserLeaveHint() { - super.onUserLeaveHint() - enterPiPMode() - } - - @RequiresApi(26) - override fun onPictureInPictureModeChanged(inPiP: Boolean, newConfig: Configuration) { - super.onPictureInPictureModeChanged(inPiP, newConfig) - if (inPiP) { - toolbar.close() - viewModel.resetZoom() - virtualKeys.hide() - } - } - - private fun enterPiPMode() { - val canEnter = viewModel.pref.viewer.pipEnabled && viewModel.client.connected - - if (canEnter && Build.VERSION.SDK_INT >= 26) { - - var w = viewModel.frameState.fbWidth - var h = viewModel.frameState.fbHeight - if (w <= 0 || h <= 0) - return - - // Android require aspect ratio to be less than 2.39 - w = w.coerceIn(1f, 2.3f * h) - h = h.coerceIn(1f, 2.3f * w) - - val aspectRatio = Rational(w.toInt(), h.toInt()) - val param = PictureInPictureParams.Builder().setAspectRatio(aspectRatio).build() - - try { - enterPictureInPictureMode(param) - } catch (e: IllegalStateException) { - Log.w(javaClass.simpleName, "Cannot enter PiP mode", e) - } - } - } - - /************************************************************************************ - * Input - ************************************************************************************/ - - override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { - return keyHandler.onKeyEvent(event) || workarounds(event) || super.onKeyDown(keyCode, event) - } - - override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { - return keyHandler.onKeyEvent(event) || workarounds(event) || super.onKeyUp(keyCode, event) - } - - override fun onKeyMultiple(keyCode: Int, repeatCount: Int, event: KeyEvent): Boolean { - return keyHandler.onKeyEvent(event) || super.onKeyMultiple(keyCode, repeatCount, event) - } - - private fun workarounds(keyEvent: KeyEvent): Boolean { - - //It seems that some device manufacturers are hell-bent on making developers' - //life miserable. In their infinite wisdom, they decided that Android apps don't - //need Mouse right-click events. It is hardcoded to act as back-press, without - //giving apps a chance to handle it. For better or worse, they set the 'source' - //for such key events to Mouse, enabling the following workarounds. - if (keyEvent.keyCode == KeyEvent.KEYCODE_BACK && - InputDevice.getDevice(keyEvent.deviceId)?.supportsSource(InputDevice.SOURCE_MOUSE) == true && - viewModel.pref.input.interceptMouseBack) { - if (keyEvent.action == KeyEvent.ACTION_DOWN) - touchHandler.onMouseBack() - return true - } - return false - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Frame.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Frame.kt deleted file mode 100644 index a0a33e0..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Frame.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc.gl - -import android.opengl.GLES20.GL_FLOAT -import android.opengl.GLES20.GL_TRIANGLES -import android.opengl.GLES20.glDrawArrays -import android.opengl.GLES20.glEnableVertexAttribArray -import android.opengl.GLES20.glVertexAttribPointer -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.nio.FloatBuffer - -/** - * Frame is represented as two triangles: - * - * [0, fbHeight] +-----------+ [fbWidth, fbHeight] - * | /| - * | / | - * | / | - * | / | - * [0, 0] +-----------+ [fbWidth, 0] - * - * Frame texture is mapped onto these triangles. - */ -class Frame { - - companion object { - const val FLOAT_SIZE = 4 - const val TRIANGLE_COMPONENT = 2 //[x,y] - const val TEXTURE_COMPONENT = 2 //[x,y] - const val STRIDE = (TEXTURE_COMPONENT + TEXTURE_COMPONENT) * FLOAT_SIZE - } - - private var fbWidth = 0F - private var fbHeight = 0F - private var vertexData: FloatArray - private var vertexBuffer: FloatBuffer - - init { - vertexData = generateVertexData() - vertexBuffer = ByteBuffer.allocateDirect(vertexData.size * 4) - .order(ByteOrder.nativeOrder()) - .asFloatBuffer() - .put(vertexData) - } - - /** - * Generates vertex data for frame. - */ - private fun generateVertexData(): FloatArray { - - //Note: Textures have their own coordinate system. [0,0] represents bottom-left - // and [1,1] represents upper-right corner. - - return floatArrayOf( - //@formatter:off - //Triangle coordinates //Texture coordinates - 0F, 0F, 0F, 0F, - fbWidth, 0F, 1F, 0F, - fbWidth, fbHeight, 1F, 1F, - - 0F, 0F, 0F, 0F, - fbWidth, fbHeight, 1F, 1F, - 0F, fbHeight, 0F, 1F - //@formatter:on - ) - } - - - fun bind(program: FrameProgram) { - setVertexAttributePointer(0, program.aPositionLocation, TRIANGLE_COMPONENT, STRIDE) - setVertexAttributePointer(TRIANGLE_COMPONENT, program.aTextureCoordinatesLocation, TEXTURE_COMPONENT, STRIDE) - } - - private fun setVertexAttributePointer(dataOffset: Int, attributeLocation: Int, componentCount: Int, stride: Int) { - vertexBuffer.position(dataOffset) - glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, false, stride, vertexBuffer) - glEnableVertexAttribArray(attributeLocation) - vertexBuffer.position(0) - } - - /** - * Should be called whenever the size of framebuffer is changed. - * This size will be used to calculate frame vertices. - */ - fun updateFbSize(width: Float, height: Float) { - if (width == fbWidth && height == fbHeight) - return //Nothing to do - - fbWidth = width - fbHeight = height - - vertexData = generateVertexData() - vertexBuffer.position(0) - vertexBuffer.put(vertexData) - } - - fun draw() { - glDrawArrays(GL_TRIANGLES, 0, 6) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/FrameProgram.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/FrameProgram.kt deleted file mode 100644 index 0d991e4..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/FrameProgram.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc.gl - -import android.opengl.GLES20.GL_CLAMP_TO_EDGE -import android.opengl.GLES20.GL_LINEAR -import android.opengl.GLES20.GL_TEXTURE0 -import android.opengl.GLES20.GL_TEXTURE_2D -import android.opengl.GLES20.GL_TEXTURE_MAG_FILTER -import android.opengl.GLES20.GL_TEXTURE_MIN_FILTER -import android.opengl.GLES20.GL_TEXTURE_WRAP_S -import android.opengl.GLES20.GL_TEXTURE_WRAP_T -import android.opengl.GLES20.glActiveTexture -import android.opengl.GLES20.glBindTexture -import android.opengl.GLES20.glGenTextures -import android.opengl.GLES20.glGetAttribLocation -import android.opengl.GLES20.glGetUniformLocation -import android.opengl.GLES20.glTexParameteri -import android.opengl.GLES20.glUniform1i -import android.opengl.GLES20.glUniformMatrix4fv -import android.opengl.GLES20.glUseProgram -import android.util.Log -import com.example.tiny_computer.BuildConfig - -/** - * Represents the GL program used for Frame rendering. - * - * NOTE: It must be instantiated in an OpenGL context. - */ -class FrameProgram { - - companion object { - // Attribute constants - const val A_POSITION = "a_Position" - const val A_TEXTURE_COORDINATES = "a_TextureCoordinates" - - // Uniform constants - const val U_PROJECTION = "u_Projection" - const val U_TEXTURE_UNIT = "u_TextureUnit" - } - - val program = ShaderCompiler.buildProgram(Shaders.VERTEX_SHADER, Shaders.FRAGMENT_SHADER) - val aPositionLocation = glGetAttribLocation(program, A_POSITION) - val aTextureCoordinatesLocation = glGetAttribLocation(program, A_TEXTURE_COORDINATES) - val uProjectionLocation = glGetUniformLocation(program, U_PROJECTION) - val uTexUnitLocation = glGetUniformLocation(program, U_TEXTURE_UNIT) - val textureId = createTexture() - var validated = false - - - fun setUniforms(projectionMatrix: FloatArray) { - glUniformMatrix4fv(uProjectionLocation, 1, false, projectionMatrix, 0) - glActiveTexture(GL_TEXTURE0) - glBindTexture(GL_TEXTURE_2D, textureId) - glUniform1i(uTexUnitLocation, 0) - } - - private fun createTexture(): Int { - val texturesObjects = intArrayOf(0) - glGenTextures(1, texturesObjects, 0) - if (texturesObjects[0] == 0) { - Log.e("Texture", "Could not generate texture.") - return 0 - } - - glBindTexture(GL_TEXTURE_2D, texturesObjects[0]) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) - glBindTexture(GL_TEXTURE_2D, 0) - return texturesObjects[0] - } - - fun validate() { - if (BuildConfig.DEBUG && !validated) { - ShaderCompiler.validateProgram(program) - validated = true - } - } - - fun useProgram() { - glUseProgram(program) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Renderer.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Renderer.kt deleted file mode 100644 index 25bc1e8..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Renderer.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc.gl - -import android.opengl.GLES20.GL_COLOR_BUFFER_BIT -import android.opengl.GLES20.glClear -import android.opengl.GLES20.glClearColor -import android.opengl.GLES20.glViewport -import android.opengl.GLSurfaceView -import android.opengl.Matrix -import com.gaurav.avnc.viewmodel.VncViewModel -import javax.microedition.khronos.egl.EGLConfig -import javax.microedition.khronos.opengles.GL10 - -/** - * Frame renderer. - */ -class Renderer(val viewModel: VncViewModel) : GLSurfaceView.Renderer { - - private val projectionMatrix = FloatArray(16) - private val hideCursor = viewModel.pref.input.hideRemoteCursor - private lateinit var program: FrameProgram - private lateinit var frame: Frame - - override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { - glClearColor(0f, 0f, 0f, 1f) - - frame = Frame() - program = FrameProgram() - } - - override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) { - glViewport(0, 0, width, height) - } - - /** - * Draws frame on screen according to current state. - * - * Y-axis of coordinate system used by OpenGL is in opposite direction (upwards) - * relative to Y-axis in screen coordinates (downwards). - * - * To compensate for this, we invert the Y-coordinates of drawn frame. This is - * achieved by: - * 1. Using clipping region [-height, 0] instead of [0, height] for Y-axis - * 2. Inverting sign of Y-axis position - * 3. Inverting sign of Y-axis scale (to flip the frame) - * - * So the frame is drawn as follows in OpenGL: - * - * +Y ^ - * | - * |[0,0] [width,0] - * -X <-----|---------------------+-------------> +X - * | | - * | | - * | Frame | - * | | - * | | - * +---------------------+ - * |[0,-height] [width,-height] - * | - * -Y v - * - * Doing this inversion here allows rest of the code to not worry about difference - * in Y-axis direction. - * - */ - override fun onDrawFrame(gl: GL10?) { - glClear(GL_COLOR_BUFFER_BIT) - - if (!viewModel.client.connected) - return - - val state = viewModel.frameState.getSnapshot() - if (state.vpWidth == 0f || state.vpHeight == 0f) - return - - Matrix.setIdentityM(projectionMatrix, 0) - Matrix.orthoM(projectionMatrix, 0, 0f, state.vpWidth, -state.vpHeight, 0f, -1f, 1f) - Matrix.translateM(projectionMatrix, 0, state.frameX, -state.frameY, 0f) - Matrix.scaleM(projectionMatrix, 0, state.scale, -state.scale, 1f) - - program.useProgram() - program.setUniforms(projectionMatrix) - - viewModel.client.uploadFrameTexture() - if (!hideCursor) viewModel.client.uploadCursor() - - frame.updateFbSize(state.fbWidth, state.fbHeight) - frame.bind(program) - - program.validate() - frame.draw() - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/ShaderCompiler.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/ShaderCompiler.kt deleted file mode 100644 index 49cf298..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/ShaderCompiler.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc.gl - -import android.opengl.GLES20.GL_COMPILE_STATUS -import android.opengl.GLES20.GL_FRAGMENT_SHADER -import android.opengl.GLES20.GL_LINK_STATUS -import android.opengl.GLES20.GL_VALIDATE_STATUS -import android.opengl.GLES20.GL_VERTEX_SHADER -import android.opengl.GLES20.glAttachShader -import android.opengl.GLES20.glCompileShader -import android.opengl.GLES20.glCreateProgram -import android.opengl.GLES20.glCreateShader -import android.opengl.GLES20.glDeleteProgram -import android.opengl.GLES20.glDeleteShader -import android.opengl.GLES20.glGetProgramInfoLog -import android.opengl.GLES20.glGetProgramiv -import android.opengl.GLES20.glGetShaderInfoLog -import android.opengl.GLES20.glGetShaderiv -import android.opengl.GLES20.glLinkProgram -import android.opengl.GLES20.glShaderSource -import android.opengl.GLES20.glValidateProgram -import android.util.Log - -object ShaderCompiler { - - private const val TAG = "ShaderCompiler" - - fun compileShader(type: Int, shaderText: String): Int { - val shaderObjectId = glCreateShader(type) - if (shaderObjectId == 0) { - Log.e(TAG, "Could not create shader object") - return 0 - } - glShaderSource(shaderObjectId, shaderText) - glCompileShader(shaderObjectId) - Log.d(TAG, glGetShaderInfoLog(shaderObjectId)) - - val status = intArrayOf(0) - glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, status, 0) - if (status[0] == 0) { - Log.e(TAG, "Shader compilation failed") - glDeleteShader(shaderObjectId) - return 0 - } - - return shaderObjectId - } - - fun linkProgram(vertexShaderId: Int, fragmentShaderId: Int): Int { - val programId = glCreateProgram() - if (programId == 0) { - Log.e(TAG, "Could not create program object") - return 0 - } - - glAttachShader(programId, vertexShaderId) - glAttachShader(programId, fragmentShaderId) - glLinkProgram(programId) - Log.d(TAG, glGetProgramInfoLog(programId)) - - val status = intArrayOf(0) - glGetProgramiv(programId, GL_LINK_STATUS, status, 0) - if (status[0] == 0) { - Log.e(TAG, "Program linking failed") - glDeleteProgram(programId) - return 0 - } - - return programId - } - - fun validateProgram(programId: Int): Boolean { - glValidateProgram(programId) - val status = intArrayOf(0) - glGetProgramiv(programId, GL_VALIDATE_STATUS, status, 0) - Log.d(TAG, "Program [" + programId + "] validation result: " + status[0]) - Log.d(TAG, "Program [" + programId + "] validation log: " + glGetProgramInfoLog(programId)) - return status[0] != 0 - } - - fun buildProgram(vertexShaderSource: String, fragmentShaderSource: String): Int { - val vertexShaderId = compileShader(GL_VERTEX_SHADER, vertexShaderSource) - val fragmentShaderId = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource) - - if (vertexShaderId == 0 || fragmentShaderId == 0) - return 0 - - return linkProgram(vertexShaderId, fragmentShaderId) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Shaders.kt b/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Shaders.kt deleted file mode 100644 index 3fef6fd..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/ui/vnc/gl/Shaders.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.ui.vnc.gl - -/** - * Shaders used for rendering framebuffer - */ -object Shaders { - //language=GLSL - const val VERTEX_SHADER = """ - uniform mat4 u_Projection; - attribute vec2 a_Position; - attribute vec2 a_TextureCoordinates; - varying vec2 v_TextureCoordinates; - void main() - { - v_TextureCoordinates = a_TextureCoordinates; - gl_Position = u_Projection * vec4(a_Position, 0, 1); - }""" - - //language=GLSL - const val FRAGMENT_SHADER = """ - precision mediump float; - uniform sampler2D u_TextureUnit; - varying vec2 v_TextureCoordinates; - void main() - { - gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates); - }""" -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/AppPreferences.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/AppPreferences.kt deleted file mode 100644 index 8a331d2..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/AppPreferences.kt +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.content.Context -import android.content.SharedPreferences -import androidx.core.content.edit -import androidx.lifecycle.LiveData -import androidx.preference.PreferenceManager - -/** - * Utility class for accessing app preferences - */ -class AppPreferences(context: Context) { - - private val prefs = PreferenceManager.getDefaultSharedPreferences(context) - - inner class UI { - val theme = LivePref("theme", "system") - } - - inner class Viewer { - val orientation; get() = prefs.getString("viewer_orientation", "landscape") - val fullscreen; get() = prefs.getBoolean("fullscreen_display", true) - val pipEnabled; get() = prefs.getBoolean("pip_enabled", true) - val drawBehindCutout; get() = prefs.getBoolean("viewer_draw_behind_cutout", false) - val keepScreenOn; get() = prefs.getBoolean("keep_screen_on", true) - val toolbarAlignment; get() = prefs.getString("toolbar_alignment", "start") - val toolbarOpenWithSwipe; get() = prefs.getBoolean("toolbar_open_with_swipe", true) - val zoomMax; get() = prefs.getInt("zoom_max", 500) / 100F - val zoomMin; get() = prefs.getInt("zoom_min", 50) / 100F - val perOrientationZoom; get() = prefs.getBoolean("per_orientation_zoom", true) - val toolbarShowGestureStyleToggle; get() = prefs.getBoolean("toolbar_show_gesture_style_toggle", true) - } - - inner class Gesture { - val style; get() = prefs.getString("gesture_style", "touchpad")!! - val tap1 = "left-click" //Preference UI was removed - val tap2; get() = prefs.getString("gesture_tap2", "open-keyboard")!! - val doubleTap; get() = prefs.getString("gesture_double_tap", "double-click")!! - val longPress; get() = prefs.getString("gesture_long_press", "right-click")!! - val swipe1; get() = prefs.getString("gesture_swipe1", "pan")!! - val swipe2; get() = prefs.getString("gesture_swipe2", "remote-scroll")!! - val doubleTapSwipe; get() = prefs.getString("gesture_double_tap_swipe", "remote-drag")!! - val longPressSwipe; get() = prefs.getString("gesture_long_press_swipe", "none")!! - val longPressSwipeEnabled; get() = (longPressSwipe != "none") - val swipeSensitivity; get() = prefs.getInt("gesture_swipe_sensitivity", 10) / 10f - val invertVerticalScrolling; get() = prefs.getBoolean("invert_vertical_scrolling", false) - } - - inner class Input { - val gesture = Gesture() - - val vkOpenWithKeyboard; get() = prefs.getBoolean("vk_open_with_keyboard", false) - val vkShowAll; get() = prefs.getBoolean("vk_show_all", true) - - val mousePassthrough; get() = prefs.getBoolean("mouse_passthrough", true) - val hideLocalCursor; get() = prefs.getBoolean("hide_local_cursor", true) - val hideRemoteCursor; get() = prefs.getBoolean("hide_remote_cursor", false) - val mouseBack; get() = prefs.getString("mouse_back", "right-click")!! - val interceptMouseBack; get() = mouseBack != "default" - - val kmLanguageSwitchToSuper; get() = prefs.getBoolean("km_language_switch_to_super", false) - val kmRightAltToSuper; get() = prefs.getBoolean("km_right_alt_to_super", false) - val kmBackToEscape; get() = prefs.getBoolean("km_back_to_escape", false) - } - - inner class Server { - val clipboardSync; get() = prefs.getBoolean("clipboard_sync", true) - val autoReconnect; get() = prefs.getBoolean("auto_reconnect", false) - } - - /** - * These are used for one-time features/tips. - * These are not exposed to user. - */ - inner class RunInfo { - var hasConnectedSuccessfully: Boolean - get() = prefs.getBoolean("run_info_has_connected_successfully", false) - set(value) = prefs.edit { putBoolean("run_info_has_connected_successfully", value) } - - var hasShownV2WelcomeMsg - get() = prefs.getBoolean("run_info_has_shown_v2_welcome_msg", false) - set(value) = prefs.edit { putBoolean("run_info_has_shown_v2_welcome_msg", value) } - } - - val ui = UI() - val viewer = Viewer() - val input = Input() - val server = Server() - val runInfo = RunInfo() - - - /** - * For some preference changes we want to provide live feedback to user. - * This class is used for such scenarios. Based on [LiveData], it notifies - * the observers whenever the value of given preference is changed. - * - * For now, each [LivePref] creates a separate change listener, but if - * number of [LivePref]s grow, we can optimize by sharing a single listener. - */ - inner class LivePref(val key: String, private val defValue: T) : LiveData() { - private val prefChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, changedKey -> - if (key == changedKey) - updateValue() - } - - private var initialized = false - - override fun onActive() { - if (!initialized) { - initialized = true - updateValue() - prefs.registerOnSharedPreferenceChangeListener(prefChangeListener) - } - } - - private fun updateValue() { - @Suppress("UNCHECKED_CAST") - when (defValue) { - is Boolean -> value = prefs.getBoolean(key, defValue) as T - is String -> value = prefs.getString(key, defValue) as T - is Int -> value = prefs.getInt(key, defValue) as T - is Long -> value = prefs.getLong(key, defValue) as T - is Float -> value = prefs.getFloat(key, defValue) as T - } - } - } - - - /****************************** Migrations *******************************/ - init { - if (!prefs.getBoolean("gesture_direct_touch", true)) prefs.edit { - remove("gesture_direct_touch") - putString("gesture_style", "touchpad") - } - - if (!prefs.getBoolean("natural_scrolling", true)) prefs.edit { - remove("natural_scrolling") - putBoolean("invert_vertical_scrolling", true) - } - - prefs.getString("gesture_drag", null)?.let { - prefs.edit { - remove("gesture_drag") - putString("gesture_long_press_swipe", it) - } - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/Binding.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/Binding.kt deleted file mode 100644 index 8205efd..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/Binding.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.content.Context -import android.util.Log -import android.view.View -import android.widget.AdapterView -import android.widget.SimpleAdapter -import android.widget.Spinner -import androidx.core.view.isInvisible -import androidx.core.view.isVisible -import androidx.databinding.BindingAdapter -import androidx.databinding.InverseBindingAdapter -import androidx.databinding.InverseBindingListener - - -@BindingAdapter("isVisible") -fun visibilityAdapter(view: View, isVisible: Boolean) { - view.isVisible = isVisible -} - -@BindingAdapter("isInvisible") -fun invisibilityAdapter(view: View, isInvisible: Boolean) { - view.isInvisible = isInvisible -} - -/************************************************************************************************** - * Spinner value binding - * These allows the Spinner to be populated using data-binding in XMl layouts. - * There are 4 attributes used for this: - * - * app:value => Reference to the backing field which actually stores the selected value. - * This can be used with two-way binding to update the backing field whenever - * selection changes in Spinner. - * For now, Only String & Int types are supported for backing field. - * - * app:values => String Array, holds possible values of app:value - * - * app:valueLabels => String Array, Optional. If provided, these labels will be shown in the UI - * instead of raw app:values - * - * app:valueDescriptions => String Array, Optional. Short descriptions of values, shown in Spinner - * Popup below each label. - * - * - *************************************************************************************************/ -private fun prepareEntryMap(labels: Array, descriptions: Array?) = mutableListOf>().apply { - for (i in labels.indices) - add(mapOf("label" to labels[i], "description" to descriptions?.getOrNull(i))) -} - -private class SpinnerAdapter(context: Context, labels: Array, descriptions: Array?, val values: Array) - : SimpleAdapter(context, prepareEntryMap(labels, descriptions), android.R.layout.simple_list_item_1, - arrayOf("label", "description"), intArrayOf(android.R.id.text1, android.R.id.text2)) - -@BindingAdapter("valueLabels", "valueDescriptions", "values", "value", requireAll = false) -fun spinnerValueAdapter(spinner: Spinner, labels: Array?, descriptions: Array?, values: Array?, value: Any?) { - if (spinner.adapter == null && values != null) { - check(labels == null || labels.size == values.size) - check(descriptions == null || descriptions.size == values.size) - - val adapter = SpinnerAdapter(spinner.context, labels ?: values, descriptions, values) - if (descriptions != null) - adapter.setDropDownViewResource(android.R.layout.simple_list_item_2) - - spinner.adapter = adapter - } - - if (spinner.adapter != null && value != null) { - val adapter = spinner.adapter as SpinnerAdapter - val index = adapter.values.indexOf(value.toString()) - if (index != -1) - spinner.setSelection(index) - else - Log.e("SpinnerValue", "value: $value not found in adapter values: ${adapter.values}") - } -} - -@BindingAdapter("valueAttrChanged") -fun spinnerValueChangedAdapter(spinner: Spinner, valueChange: InverseBindingListener) { - spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(p: AdapterView<*>, v: View?, pos: Int, id: Long) = valueChange.onChange() - override fun onNothingSelected(parent: AdapterView<*>?) {} - } -} - -@InverseBindingAdapter(attribute = "value") -fun spinnerValueInverseAdapter(spinner: Spinner): String { - return (spinner.adapter as SpinnerAdapter).values[spinner.selectedItemPosition] -} - -@InverseBindingAdapter(attribute = "value") -fun spinnerValueInverseAdapterInt(spinner: Spinner) = spinnerValueInverseAdapter(spinner).toInt() - diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/Clipboard.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/Clipboard.kt deleted file mode 100644 index 0577534..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/Clipboard.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import android.util.Log -import androidx.core.content.ContextCompat -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext - -/** - * Clipboard access is slightly more complex in AVNC, because clip data can be - * unusually large. It includes stuff coming from server, and app logs. - * As clipboard access involves binder IPC, it can lead to ANR issues. So we - * use a background thread for accessing clipboard. - */ - -/** - * Puts given text on the clipboard. - */ -suspend fun setClipboardText(context: Context, text: String): Boolean { - var success = false - try { - getClipboardManager(context)?.let { - withContext(Dispatchers.IO) { - it.setPrimaryClip(ClipData.newPlainText(null, text)) - success = true - } - } - } catch (e: CancellationException) { - throw e - } catch (t: Throwable) { - Log.e("ClipboardUtil", "Could not copy text to clipboard.", t) - } - return success -} - - -/** - * Returns current clipboard text. - */ -suspend fun getClipboardText(context: Context): String? { - var result: String? = null - try { - getClipboardManager(context)?.let { - withContext(Dispatchers.IO) { - result = it.primaryClip?.getItemAt(0)?.text?.toString() - } - } - } catch (e: CancellationException) { - throw e - } catch (t: Throwable) { - Log.e("ClipboardUtil", "Could not retrieve text from clipboard.", t) - } - return result -} - -/** - * [ClipboardManager] has to be created on a thread where Looper has been initialized. - */ -private suspend fun getClipboardManager(context: Context) = withContext(Dispatchers.Main.immediate) { - ContextCompat.getSystemService(context, ClipboardManager::class.java) -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/Debugging.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/Debugging.kt deleted file mode 100644 index 58da08f..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/Debugging.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.net.Uri -import android.os.Build -import com.example.tiny_computer.BuildConfig - -/** - * Utilities to aid in debugging - */ -object Debugging { - - /** - * Returns logcat output. - * Should not be called from main thread. - */ - fun logcat(): String { - try { - return ProcessBuilder("logcat", "-d", "*") - .redirectErrorStream(true) - .start() - .inputStream - .reader() - .readText() - } catch (t: Throwable) { - return "Error getting logs: ${t.message}" - } - } - - fun clearLogs() { - try { - ProcessBuilder("logcat", "-c").start() - } catch (t: Throwable) { - //Ignore - } - } - - /** - * Generates a query parameter string which can be used with GitHub issue url. - * Currently, only `body` parameter is generated - */ - fun bugReportUrlParams(): String { - val body = """ - |**Description** - | - | - | - | - |**Additional Info** - |- App Version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) - |- Android Version: ${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT}) - """.trimMargin() - - return "?body=${Uri.encode(body)}" - } - - /** - * Wraps given logs into a
element. - * This is useful for GitHub comments. - */ - fun wrapLogs(title: String, logs: String): String { - return """ -
- $title -

- - ```python - {logs} - ``` - -

-
- """.trimIndent().replace("{logs}", logs) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/DeviceAuthPrompt.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/DeviceAuthPrompt.kt deleted file mode 100644 index a3e36cf..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/DeviceAuthPrompt.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2022 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.util.Log -import androidx.activity.viewModels -import androidx.biometric.BiometricManager -import androidx.biometric.BiometricPrompt -import androidx.biometric.FingerprintDialogFragment -import androidx.biometric.auth.AuthPromptCallback -import androidx.biometric.auth.startClass2BiometricOrCredentialAuthentication -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity -import androidx.fragment.app.FragmentFactory -import androidx.fragment.app.FragmentManager -import androidx.lifecycle.ViewModel - -/** - * Wrapper around AndroidX Biometrics library. - * - * - Allow checking for auth availability - * - Provide simplified Kotlin-style callback setup - * - Provide consistent handling for activity restarts - * - Apply workarounds for library bugs - * - * Usage: - * 1. Call [init] to setup callbacks - * 2. Call [launch] to start auth session - */ -class DeviceAuthPrompt(private val activity: FragmentActivity) { - - class PromptViewModel : ViewModel() { - var isPromptShown = false - var promptTitle = "" - } - - private val viewModel by activity.viewModels() - private var onAuthSuccess: (() -> Unit)? = null - private var onAuthFail: ((String) -> Unit)? = null - - - /** - * Setup auth callbacks. - * Should be called from onCreate() of the host activity/fragment. - * If an auth session is active, it will be updated with given callbacks. - */ - fun init(onSuccess: () -> Unit, onFail: (String) -> Unit) { - onAuthSuccess = onSuccess - onAuthFail = onFail - - if (viewModel.isPromptShown) - launch(viewModel.promptTitle) - } - - /** - * Whether user can be authenticated using Biometric or Device credentials (e.g. PIN, Password) - */ - fun canLaunch(): Boolean { - val types = BiometricManager.Authenticators.BIOMETRIC_WEAK or BiometricManager.Authenticators.DEVICE_CREDENTIAL - return BiometricManager.from(activity).canAuthenticate(types) == BiometricManager.BIOMETRIC_SUCCESS - } - - /** - * Launch auth prompt. - */ - fun launch(title: String) { - check(onAuthSuccess != null) - check(onAuthFail != null) - - activity.startClass2BiometricOrCredentialAuthentication( - title = title, - confirmationRequired = false, - callback = PromptCallback() - ) - - viewModel.isPromptShown = true - viewModel.promptTitle = title - } - - private fun onAuthFinished() { - viewModel.isPromptShown = false - } - - private inner class PromptCallback : AuthPromptCallback() { - override fun onAuthenticationSucceeded(activity: FragmentActivity?, result: BiometricPrompt.AuthenticationResult) { - onAuthSuccess?.invoke() - onAuthFinished() - } - - override fun onAuthenticationError(activity: FragmentActivity?, errorCode: Int, errString: CharSequence) { - Log.e(javaClass.simpleName, "Authentication error: $errString [$errorCode] ") - onAuthFail?.invoke(errString.toString()) - onAuthFinished() - } - } - - - companion object { - /** - * The constructor of [FingerprintDialogFragment] is currently marked private. - * When fragment manager tries to re-instantiate it after activity restart, - * it will fail and crash the app. So we install a custom [FragmentFactoryWrapper] - * which instantiates [FingerprintDialogFragment] via reflection. - * - * Issue: https://issuetracker.google.com/issues/181805603 - * - * TODO: Remove this after issue is fixed in library. - */ - fun applyFingerprintDialogFix(fm: FragmentManager) { - fm.fragmentFactory = FragmentFactoryWrapper(fm.fragmentFactory) - } - - class FragmentFactoryWrapper(private val realFactory: FragmentFactory) : FragmentFactory() { - private val fpClassName = FingerprintDialogFragment::class.java.name - - override fun instantiate(classLoader: ClassLoader, className: String): Fragment { - if (className == fpClassName) { - return FingerprintDialogFragment::class.java.getDeclaredConstructor().let { - it.isAccessible = true - it.newInstance() - } - } - return realFactory.instantiate(classLoader, className) - } - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/LiveEvent.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/LiveEvent.kt deleted file mode 100644 index ba9f5a5..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/LiveEvent.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import androidx.annotation.MainThread -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.Observer - -/** - * This class implements single-shot observable events. - * It is based on [LiveData] which does the heavy lifting for us. - * - * Single-shot - * =========== - * When this event is fired, it will notify exactly one active observer. - * If there is no active observer, it will wait for one so that the event - * is not "lost". - * - * This is the main difference between this class & [LiveData]. [LiveData] will - * notify the future observers to bring them up-to date. This can happen during - * Activity restarts where old observers are detached and new ones are attached. - * - * This class is used for events which should be handled only once. - * E.g. starting a fragment. - */ -open class LiveEvent { - - private class WrappedData(val data: T, var consumed: Boolean = false) - private class WrappedObserver(private val observer: Observer) : Observer> { - override fun onChanged(value: WrappedData) { - if (!value.consumed) { - value.consumed = true - observer.onChanged(value.data) - } - } - } - - private val liveData = MutableLiveData>() - private val wrappedObservers = mutableMapOf, WrappedObserver>() - - /** - * Peek current value of this event, irrespective of whether any observer has been notified. - */ - val value get() = liveData.value?.data - - /** - * Fire this event with given data. - * Must be called from main thread. - */ - @MainThread - fun fire(data: T) { - liveData.value = WrappedData(data) - } - - /** - * Asynchronous version of [fire]. - * Can be called from any thread. - */ - fun fireAsync(data: T) { - liveData.postValue(WrappedData(data)) - } - - @MainThread - fun observe(owner: LifecycleOwner, observer: Observer) { - val wrapped = WrappedObserver(observer) - wrappedObservers[observer] = wrapped - liveData.observe(owner, wrapped) - } - - @MainThread - fun observeForever(observer: Observer) { - val wrapped = WrappedObserver(observer) - wrappedObservers[observer] = wrapped - liveData.observeForever(wrapped) - } - - @MainThread - fun removeObserver(observer: Observer) { - wrappedObservers.remove(observer)?.let { liveData.removeObserver(it) } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/LiveRequest.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/LiveRequest.kt deleted file mode 100644 index 741b616..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/LiveRequest.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.launch -import java.util.concurrent.LinkedBlockingQueue - -/** - * Extension of [LiveEvent] to facilitate awaiting some response from observers. - * - * This simplifies the cases where a background thread needs some value from the user (i.e. UI thread), - * and we want the background thread to block until that value is available. - * - * If a request is canceled then [requestResponse] will return [cancellationValue]. - * - * @param scope can be specified to auto-cancel this request on scope cancellation. - */ -class LiveRequest(private val cancellationValue: ResponseType, scope: CoroutineScope?) - : LiveEvent() { - - private val responses = LinkedBlockingQueue() - - init { - scope?.launch { awaitCancellation() }?.invokeOnCompletion { cancelRequest() } - } - - /** - * Fires this request with given value and returns the response. - * Will block until any response is available. - * Can be called from any threads. - */ - fun requestResponse(value: RequestType): ResponseType { - responses.clear() - fireAsync(value) - return responses.take() //Blocking call - } - - /** - * Sets response for current request. - */ - fun offerResponse(response: ResponseType) = responses.offer(response) - - /** - * Cancels any pending request. - */ - fun cancelRequest() = responses.offer(cancellationValue) -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/MsgDialog.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/MsgDialog.kt deleted file mode 100644 index 7fcf917..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/MsgDialog.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.gaurav.avnc.util - -import android.app.Dialog -import android.os.Bundle -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder - - -object MsgDialog { - - /** - * Shows a dialog with given title & message, - */ - fun show(manager: FragmentManager, title: CharSequence, msg: CharSequence) { - val fragment = MsgDialogFragment() - val args = Bundle(2) - - args.putCharSequence("title", title) - args.putCharSequence("msg", msg) - fragment.arguments = args - - fragment.show(manager, null) - } - - class MsgDialogFragment : DialogFragment() { - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext()) - .setTitle(requireArguments().getCharSequence("title")) - .setMessage(requireArguments().getCharSequence("msg")) - .setPositiveButton(android.R.string.ok) { _, _ -> /* Let it dismiss */ } - .create() - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/OpenableDocument.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/OpenableDocument.kt deleted file mode 100644 index 52540b3..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/OpenableDocument.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.content.Context -import android.content.Intent -import androidx.activity.result.contract.ActivityResultContracts - -/** - * Contract for openable documents. - * This is needed because OpenDocument doesn't specify [Intent.CATEGORY_OPENABLE] - */ -class OpenableDocument : ActivityResultContracts.OpenDocument() { - override fun createIntent(context: Context, input: Array): Intent { - return super.createIntent(context, input).addCategory(Intent.CATEGORY_OPENABLE) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/SamsungDex.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/SamsungDex.kt deleted file mode 100644 index 2de08f6..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/SamsungDex.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.app.Activity -import android.content.ComponentName -import android.content.Context -import android.util.Log - -/** - * Utilities related to Samsung DeX - */ -object SamsungDex { - - /** - * Returns true, if DeX mode is enabled. - */ - private fun isInDexMode(context: Context) = runCatching { - val config = context.resources.configuration - val configClass = config.javaClass - - val flag = configClass.getField("SEM_DESKTOP_MODE_ENABLED").getInt(configClass) - val value = configClass.getField("semDesktopModeEnabled").getInt(config) - - value == flag - }.getOrDefault(false) - - - /** - * Enables/disables meta-key event capturing. - */ - fun setMetaKeyCapture(activity: Activity, isEnabled: Boolean) { - if (!isInDexMode(activity)) - return - - runCatching { - val managerClass = Class.forName("com.samsung.android.view.SemWindowManager") - val instanceMethod = managerClass.getMethod("getInstance") - val manager = instanceMethod.invoke(null) - - val requestMethod = managerClass.getDeclaredMethod("requestMetaKeyEvent", - ComponentName::class.java, - Boolean::class.java) - requestMethod.invoke(manager, activity.componentName, isEnabled) - }.onFailure { Log.d("DeX Support", "Meta key capture error", it) } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/util/SpinnerEx.kt b/android/app/src/main/kotlin/com/gaurav/avnc/util/SpinnerEx.kt deleted file mode 100644 index 44eb3d8..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/util/SpinnerEx.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.util - -import android.content.Context -import android.graphics.drawable.GradientDrawable -import android.util.AttributeSet -import android.util.TypedValue -import androidx.appcompat.widget.AppCompatSpinner -import com.google.android.material.elevation.ElevationOverlayProvider - -/** - * This class extends spinner to handle some quirks and add some utility features. - */ -class SpinnerEx(context: Context, attrs: AttributeSet? = null) : AppCompatSpinner(context, attrs) { - - init { - setupElevationOverlay() - } - - - /** - * Popup window of the Spinner does not support elevation overlay - * which makes it hard to differentiate between popup & rest of the controls in dark theme. - * - * So we manually apply the overlay to popup background. - */ - private fun setupElevationOverlay() { - // Elevation is hardcoded to 16dp because we don't have access to popup - val popupElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, - 16F, - resources.displayMetrics) - - val overlay = ElevationOverlayProvider(context) - .compositeOverlayWithThemeSurfaceColorIfNeeded(popupElevation) - - val background = popupBackground - if (background is GradientDrawable) - background.setColor(overlay) - else - background.setTint(overlay) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/BaseViewModel.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/BaseViewModel.kt deleted file mode 100644 index 5f558bc..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/BaseViewModel.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel - -import android.app.Application -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.viewModelScope -import com.gaurav.avnc.model.db.MainDb -import com.gaurav.avnc.util.AppPreferences -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext - -/** - * Base view model. - */ -open class BaseViewModel(val app: Application) : AndroidViewModel(app) { - - protected val db by lazy { MainDb.getInstance(app) } - - protected val serverProfileDao by lazy { db.serverProfileDao } - - val pref by lazy { AppPreferences(app) } - - /** - * Launches a new coroutine using [viewModelScope], and executes [block] in that coroutine. - */ - protected fun launch(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> Unit): Job { - return viewModelScope.launch(context) { this.block() } - } - - protected fun launchMain(block: suspend CoroutineScope.() -> Unit) = launch(Dispatchers.Main, block) - protected fun launchIO(block: suspend CoroutineScope.() -> Unit) = launch(Dispatchers.IO, block) -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/EditorViewModel.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/EditorViewModel.kt deleted file mode 100644 index 5d72a7f..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/EditorViewModel.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel - -import android.app.Application -import androidx.lifecycle.SavedStateHandle -import com.gaurav.avnc.model.ServerProfile - -/** - * ViewModel for profile editor - */ -class EditorViewModel(app: Application, state: SavedStateHandle, initialProfile: ServerProfile) : BaseViewModel(app) { - - /** - * Profile being edited - */ - val profile = state["profile"] ?: initialProfile.copy() - - init { - state["profile"] = profile - } - - /** - * While most fields of [profile] are straightforward to edit, some require - * more complex handling, and live feedback in UI. - * For these, we have to use dedicated LiveData fields. - */ - val useRepeater = state.getLiveData("useRepeater", profile.useRepeater) - val idOnRepeater = state.getLiveData("idOnRepeater", if (profile.useRepeater) profile.idOnRepeater.toString() else "") - val useRawEncoding = state.getLiveData("useRawEncoding", profile.useRawEncoding) - val useSshTunnel = state.getLiveData("useSshTunnel", profile.channelType == ServerProfile.CHANNEL_SSH_TUNNEL) - val sshUsePassword = state.getLiveData("sshUsePassword", profile.sshAuthType == ServerProfile.SSH_AUTH_PASSWORD) - val sshUsePrivateKey = state.getLiveData("sshUsePrivateKey", profile.sshAuthType == ServerProfile.SSH_AUTH_KEY) - val hasSshPrivateKey = state.getLiveData("hasSshPrivateKey", profile.sshPrivateKey.isNotBlank()) - - - fun prepareProfileForSave(): ServerProfile { - profile.useRepeater = useRepeater.value ?: false - profile.idOnRepeater = idOnRepeater.value?.toIntOrNull() ?: 0 - profile.useRawEncoding = useRawEncoding.value ?: false - profile.channelType = if (useSshTunnel.value == true) ServerProfile.CHANNEL_SSH_TUNNEL else ServerProfile.CHANNEL_TCP - profile.sshAuthType = if (sshUsePassword.value == true) ServerProfile.SSH_AUTH_PASSWORD else ServerProfile.SSH_AUTH_KEY - return profile - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/PrefsViewModel.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/PrefsViewModel.kt deleted file mode 100644 index bb66d75..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/PrefsViewModel.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel - -import android.app.Application -import android.net.Uri -import androidx.lifecycle.MutableLiveData -import androidx.room.withTransaction -import com.gaurav.avnc.model.ServerProfile -import com.gaurav.avnc.util.LiveEvent -import kotlinx.serialization.Serializable -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import java.io.IOException - -/** - * Viewmodel for preferences activity. - */ -class PrefsViewModel(app: Application) : BaseViewModel(app) { - - - /************************************************************************** - * Import/Export - * - * Currently, we are only exporting server profiles but preferences can be - * exported in the future. - * - * Importing/Exporting is done on a background thread. - **************************************************************************/ - - @Serializable - private data class Container( - val version: Int = 1, - val profiles: List - ) - - private val serializer = Json { - encodeDefaults = false - ignoreUnknownKeys = true - prettyPrint = true - } - - val importFinishedEvent = LiveEvent() - val exportFinishedEvent = LiveEvent() - var importExportError = MutableLiveData() - - - /** - * Exports data to given [uri]. - */ - fun export(uri: Uri) { - launchIO { - runCatching { - // Serialize - val profiles = serverProfileDao.getList() - val data = Container(profiles = profiles) - val json = serializer.encodeToString(data) - - // Write out - app.contentResolver.openOutputStream(uri)?.use { stream -> - stream.writer().use { it.write(json) } - } ?: throw IOException("Unable to write the file.") - - }.let { - importExportError.postValue(it.exceptionOrNull()?.message) - exportFinishedEvent.fireAsync(it.isSuccess) - } - } - } - - - /** - * Imports data from given [uri]. - */ - fun import(uri: Uri, deleteCurrentServers: Boolean) { - launchIO { - runCatching { - - val json = app.contentResolver.openInputStream(uri)?.use { stream -> - stream.reader().use { it.readText() } - } ?: throw IOException("Unable to read the file.") - - // Deserialize - val data = serializer.decodeFromString(json) - - //This is where migrations would be applied (if required in future) - - //Update database - if (deleteCurrentServers) { - db.withTransaction { - serverProfileDao.deleteAll() - serverProfileDao.insert(data.profiles) - } - } else { - //Reset IDs so that they don't conflict with saved profiles - data.profiles.forEach { it.ID = 0 } - serverProfileDao.insert(data.profiles) - } - - }.let { - importExportError.postValue(it.exceptionOrNull()?.message) - importFinishedEvent.fireAsync(it.isSuccess) - } - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/UrlBarViewModel.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/UrlBarViewModel.kt deleted file mode 100644 index 924086d..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/UrlBarViewModel.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel - -import android.app.Application -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.switchMap - -class UrlBarViewModel(app: Application) : BaseViewModel(app) { - - val query = MutableLiveData("") - val filteredServers = query.switchMap { - if (it.isNotBlank()) serverProfileDao.search("%$it%") - else MutableLiveData(listOf()) - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/VncViewModel.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/VncViewModel.kt deleted file mode 100644 index 3b5a0e6..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/VncViewModel.kt +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel - -import android.app.Application -import android.graphics.RectF -import android.util.Log -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.viewModelScope -import com.gaurav.avnc.model.LoginInfo -import com.gaurav.avnc.model.ServerProfile -import com.gaurav.avnc.ui.vnc.FrameScroller -import com.gaurav.avnc.ui.vnc.FrameState -import com.gaurav.avnc.ui.vnc.FrameView -import com.gaurav.avnc.util.LiveRequest -import com.gaurav.avnc.util.getClipboardText -import com.gaurav.avnc.util.setClipboardText -import com.gaurav.avnc.viewmodel.service.HostKey -import com.gaurav.avnc.viewmodel.service.SshTunnel -import com.gaurav.avnc.vnc.Messenger -import com.gaurav.avnc.vnc.UserCredential -import com.gaurav.avnc.vnc.VncClient -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import java.io.IOException -import java.lang.ref.WeakReference - -/** - * ViewModel for VncActivity - * - * Connection - * ========== - * - * At construction, we instantiate a [VncClient] referenced by [client]. Then - * activity starts the connection by calling [initConnection] which starts a coroutine to - * handle connection setup. - * - * After successful connection, we continue to operate normally until the remote - * server closes the connection, or an error occurs. Once disconnected, we - * wait for the activity to finish and then cleanup any acquired resources. - * - * Currently, lifecycle of [client] is tied to this view model. So one [VncViewModel] - * manages only one [VncClient]. - * - * - * Threading - * ========= - * - * Receiver thread :- This thread is started (as a coroutine) in [launchConnection]. - * It handles the protocol initialization, and after that processes incoming messages. - * Most of the callbacks of [VncClient.Observer] are invoked on this thread. In most - * cases it is stopped when activity is finished and this view model is cleaned up. - * - * Sender thread :- This thread is created (as an executor) by [messenger]. It is - * used to send messages to remote server. We use this dedicated thread instead - * of coroutines to preserve the order of sent messages. - * - * UI thread :- Main thread of the app. Used for updating UI and controlling other - * Threads. This is where [frameState] is updated. - * - * Renderer thread :- This is managed by [FrameView] and used for rendering frame - * via OpenGL ES. [frameState] is read from this thread to decide how/where frame - * should be drawn. - */ -class VncViewModel(val profile: ServerProfile, app: Application) : BaseViewModel(app), VncClient.Observer { - - /** - * Connection lifecycle: - * - * Created - * | - * v - * Connecting ----------+ - * | | - * v | - * Connected | - * | | - * v | - * Disconnected <-------+ - * - */ - enum class State { - Created, - Connecting, - Connected, - Disconnected; - - companion object { - val State?.isConnected get() = (this == Connected) - val State?.isDisconnected get() = (this == Disconnected) - } - } - - val client = VncClient(this) - - /** - * We have two places for connection state (both are synced): - * - * [VncClient.connected] - Simple boolean state, used most of the time - * [state] - More granular, used by observers & data binding - */ - val state = MutableLiveData(State.Created) - - /** - * Reason for disconnecting. - */ - val disconnectReason = MutableLiveData("") - - /** - * Fired when we need some credentials from user. - * It will trigger the Login dialog. - */ - val loginInfoRequest = LiveRequest(LoginInfo(), viewModelScope) - - /** - * Fired to unlock saved servers. - */ - val serverUnlockRequest = LiveRequest(false, viewModelScope) - - /** - * List of saved profiles. - * Used by login-autocompletion. - */ - val savedProfiles by lazy { serverProfileDao.getLiveList() } - - /** - * Holds a weak reference to [FrameView] instance. - * - * This is used to tell [FrameView] to re-render its content when VncClient's - * framebuffer is updated. Instead of using LiveData/LiveEvent, we keep a - * weak reference because: - * - * 1. It avoids a context-switch to UI thread. Rendering request to - * a GlSurfaceView can be sent from any thread. - * - * 2. We don't have to invoke the whole ViewModel machinery just for - * a single call to FrameView. - */ - var frameViewRef = WeakReference(null) - - /** - * Holds information about scaling, translation etc. - */ - val frameState = with(pref.viewer) { FrameState(zoomMin, zoomMax, perOrientationZoom) } - - /** - * Used for scrolling/animating the frame. - */ - val frameScroller = FrameScroller(this) - - /** - * Used for sending events to remote server. - */ - val messenger = Messenger(client) - - private val sshTunnel = SshTunnel(this) - - /** - * Used to confirm unknown hosts. - */ - val sshHostKeyVerifyRequest = LiveRequest(false, viewModelScope) - - - /************************************************************************** - * Connection management - **************************************************************************/ - - /** - * Initialize VNC connection. - * It can be called multiple times due to activity restarts. - */ - fun initConnection() { - if (state.value == State.Created) { - state.value = State.Connecting - frameState.setZoom(profile.zoom1, profile.zoom2) - launchConnection() - } - } - - private fun launchConnection() { - viewModelScope.launch(Dispatchers.IO) { - - runCatching { - - preConnect() - connect() - processMessages() - - }.onFailure { - if (it is IOException) disconnectReason.postValue(it.message) - Log.e("ReceiverCoroutine", "Connection failed", it) - } - - state.postValue(State.Disconnected) - - //Wait until activity is finished and viewmodel is cleaned up. - runCatching { awaitCancellation() } - cleanup() - } - } - - private fun preConnect() { - if (profile.ID != 0L) - if (!serverUnlockRequest.requestResponse(null)) - throw IOException("Could not unlock server") - - client.configure(profile.viewOnly, profile.securityType, true /* Hardcoded to true */, - profile.imageQuality, profile.useRawEncoding) - - if (profile.useRepeater) - client.setupRepeater(profile.idOnRepeater) - } - - private fun connect() { - when (profile.channelType) { - ServerProfile.CHANNEL_TCP -> - client.connect(profile.host, profile.port) - - ServerProfile.CHANNEL_SSH_TUNNEL -> - sshTunnel.open().use { - client.connect(it.host, it.port) - } - - else -> throw IOException("Unknown Channel: ${profile.channelType}") - } - - state.postValue(State.Connected) - - // Initial sync, slightly delayed to allow extended clipboard negotiations - launchIO { delay(1000L); sendClipboardText() } - } - - private fun processMessages() { - while (viewModelScope.isActive) - client.processServerMessage() - } - - private fun cleanup() { - messenger.cleanup() - client.cleanup() - sshTunnel.close() - } - - /** - * Can be used to persist any changes made to [profile] - */ - fun saveProfile() { - if (profile.ID != 0L) - launch { serverProfileDao.update(profile) } - } - - /************************************************************************** - * Frame management - **************************************************************************/ - - fun updateZoom(scaleFactor: Float, fx: Float, fy: Float) { - if (profile.fZoomLocked) return - - val appliedScaleFactor = frameState.updateZoom(scaleFactor) - - //Calculate how much the focus would shift after scaling - val dfx = (fx - frameState.frameX) * (appliedScaleFactor - 1) - val dfy = (fy - frameState.frameY) * (appliedScaleFactor - 1) - - //Translate in opposite direction to keep focus fixed - frameState.pan(-dfx, -dfy) - - frameViewRef.get()?.requestRender() - } - - fun resetZoom() { - frameState.setZoom(1f, 1f) - frameViewRef.get()?.requestRender() - } - - fun resetZoomToDefault() { - frameState.setZoom(profile.zoom1, profile.zoom2) - frameViewRef.get()?.requestRender() - } - - fun setZoom(zoom1: Float, zoom2: Float) { - frameState.setZoom(zoom1, zoom2) - frameViewRef.get()?.requestRender() - } - - fun panFrame(deltaX: Float, deltaY: Float) { - frameState.pan(deltaX, deltaY) - frameViewRef.get()?.requestRender() - } - - fun moveFrameTo(x: Float, y: Float) { - frameState.moveTo(x, y) - frameViewRef.get()?.requestRender() - } - - fun toggleZoomLock(enabled: Boolean) { - profile.fZoomLocked = enabled - saveProfile() - } - - fun saveZoom() { - profile.zoom1 = frameState.zoomScale1 - profile.zoom2 = frameState.zoomScale2 - saveProfile() - } - - fun setSafeArea(safeArea: RectF) { - frameState.setSafeArea(safeArea) - frameViewRef.get()?.requestRender() - } - - /************************************************************************** - * Miscellaneous - **************************************************************************/ - - fun sendClipboardText() { - if (pref.server.clipboardSync && client.connected) launchIO { - getClipboardText(app)?.let { messenger.sendClipboardText(it) } - } - } - - private var clipReceiverJob: Job? = null - private fun receiveClipboardText(text: String) { - if (!pref.server.clipboardSync) - return - - // This is a protective measure against servers which send every 'selection' made on the server. - // Setting clip text involves IPC, so these events can exhaust Binder resources, leading to ANRs. - if (clipReceiverJob?.isActive == true) { - Log.w(javaClass.simpleName, "Dropping clip text received from server, previous text is still pending") - return - } - - clipReceiverJob = launchIO { - setClipboardText(app, text) - } - } - - fun getLoginInfo(type: LoginInfo.Type): LoginInfo { - val vu = profile.username - val vp = profile.password - val sp = profile.sshPassword - - if (type == LoginInfo.Type.VNC_PASSWORD && vp.isNotBlank()) - return LoginInfo(password = vp) - - if (type == LoginInfo.Type.VNC_CREDENTIAL && vu.isNotBlank() && vp.isNotBlank()) - return LoginInfo(username = vu, password = vp) - - if (type == LoginInfo.Type.SSH_PASSWORD && sp.isNotBlank()) - return LoginInfo(password = sp) - - // Something is missing, so we have to ask the user - return loginInfoRequest.requestResponse(type) // Blocking call - } - - /** - * Resize remote desktop to match with local window size (if requested by user). - * In portrait mode, safe area is used instead of window to exclude the keyboard. - */ - fun resizeRemoteDesktop() { - if (profile.resizeRemoteDesktop) frameState.let { - if (it.windowWidth > it.windowHeight) - messenger.setDesktopSize(it.windowWidth.toInt(), it.windowHeight.toInt()) - else - messenger.setDesktopSize(it.safeArea.width().toInt(), it.safeArea.height().toInt()) - } - } - - fun pauseFrameBufferUpdates() { - //client.setAutomaticFrameBufferUpdates(false) - } - - fun resumeFrameBufferUpdates() { - //client.setAutomaticFrameBufferUpdates(true) - } - - fun refreshFrameBuffer() { - messenger.refreshFrameBuffer() - } - - /************************************************************************** - * [VncClient.Observer] Implementation - **************************************************************************/ - - override fun onPasswordRequired(): String { - return getLoginInfo(LoginInfo.Type.VNC_PASSWORD).password - } - - override fun onCredentialRequired(): UserCredential { - return getLoginInfo(LoginInfo.Type.VNC_CREDENTIAL).let { UserCredential(it.username, it.password) } - } - - override fun onFramebufferUpdated() { - frameViewRef.get()?.requestRender() - } - - override fun onGotXCutText(text: String) { - receiveClipboardText(text) - } - - override fun onFramebufferSizeChanged(width: Int, height: Int) { - launchMain { - frameState.setFramebufferSize(width.toFloat(), height.toFloat()) - } - } - - override fun onPointerMoved(x: Int, y: Int) { - frameViewRef.get()?.requestRender() - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/Discovery.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/Discovery.kt deleted file mode 100644 index 3ba6708..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/Discovery.kt +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel.service - -import android.content.Context -import android.net.nsd.NsdManager -import android.net.nsd.NsdServiceInfo -import android.net.wifi.WifiManager -import android.net.wifi.WifiManager.MulticastLock -import android.util.Log -import androidx.core.content.ContextCompat -import androidx.lifecycle.MutableLiveData -import com.gaurav.avnc.model.ServerProfile -import java.util.concurrent.Executors - -/** - * Discovers VNC servers advertising themselves on the network. - */ -object Discovery { - private const val TAG = "VncServiceDiscovery" - - /** - * List of servers found by Discovery. - */ - val servers = MutableLiveData>() - - /** - * Status of discovery. - */ - val isRunning = MutableLiveData(false) - - private val impl by lazy { Impl() } - - /** - * Starts discovery. - */ - fun start(context: Context) = impl.start(context) - - /** - * Stops discovery. - */ - fun stop() = impl.stop() - - - /** - * Due to Android API limitations, service discovery is more complicated than necessary: - * - * - [NsdManager] is asynchronous, which means every command's result is communicated later - * on a separate thread. Also, [NsdManager] throws up if more than one request is made by same - * listener. You can't call [NsdManager.discoverServices] even if discovery is already started - * So to avoid race conditions (and keep my sanity, because its one of those APIs in Android - * where I wish some day the API designers are forced to use this crap themselves), all callbacks - * of [Impl] are run on a dedicated [executor], and [startRequested] is used to track pending start. - * - * - Only one service can resolved at a time via [NsdManager.resolveService]. To handle this, - * newly found service is first added to [pendingResolves]. When resolution finishes for a - * service, we remove that service form [pendingResolves], and start resolution for the next. - * - * - Android can filter/drop multicast WiFi packets to save power. Devices, like Pixel phone, enable - * this feature. This can be turned off by acquiring a multicast lock, but [NsdManager] doesn't - * doesn't do this automatically. So we have to acquire it manually. - */ - @Suppress("DEPRECATION") // Yeah, f**k you too Google - private class Impl { - private val serviceType = "_rfb._tcp" - private var wifiManager: WifiManager? = null - private var multicastLock: MulticastLock? = null - private var nsdManager: NsdManager? = null - private val listener = DiscoveryListener() - private val executor = Executors.newSingleThreadExecutor() - - private var started = false - private var startRequested = false - private val pendingResolves = mutableMapOf() - private val resolvedProfiles = mutableSetOf() - - private fun execute(action: Runnable) { - runCatching { executor.execute(action) }.onFailure { Log.e(TAG, "Cannot execute action", it) } - } - - private fun postResolvedProfiles() { - servers.postValue(resolvedProfiles.toList()) - } - - fun start(context: Context) = execute { - if (startRequested || started) - return@execute - - val appContext = context.applicationContext // Need app context to avoid possibility of WiFiManager leaks - wifiManager = wifiManager ?: ContextCompat.getSystemService(appContext, WifiManager::class.java) - nsdManager = nsdManager ?: ContextCompat.getSystemService(appContext, NsdManager::class.java) - nsdManager!!.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, listener) - startRequested = true - - // Forget old profiles - resolvedProfiles.clear() - postResolvedProfiles() - } - - fun stop() = execute { - if (started) - nsdManager?.stopServiceDiscovery(listener) - } - - fun onStarted() = execute { - started = true - startRequested = false - isRunning.postValue(true) - - multicastLock = wifiManager?.createMulticastLock(TAG) - multicastLock?.acquire() - } - - fun onStopped() = execute { - started = false - isRunning.postValue(false) - multicastLock?.release() - multicastLock = null - } - - fun onStartFailed() = execute { - startRequested = false - } - - fun onServiceFound(serviceInfo: NsdServiceInfo) = execute { - val listener = ResolveListener() - pendingResolves[listener] = serviceInfo - if (pendingResolves.size == 1) // Kick-start the resolution chain - nsdManager?.resolveService(serviceInfo, listener) - } - - fun onServiceLost(serviceInfo: NsdServiceInfo) = execute { - resolvedProfiles.removeAll { it.name == serviceInfo.serviceName } - postResolvedProfiles() - } - - fun onResolved(si: NsdServiceInfo) = execute { - resolvedProfiles.add(ServerProfile(name = si.serviceName, host = si.host.hostAddress!!, port = si.port)) - postResolvedProfiles() - } - - fun onResolveFinished(finishedResolve: ResolveListener) = execute { - pendingResolves.remove(finishedResolve) - pendingResolves.keys.firstOrNull()?.let { nsdManager?.resolveService(pendingResolves[it], it) } - } - } - - /** - * Listener for discovery process. - */ - private class DiscoveryListener : NsdManager.DiscoveryListener { - override fun onDiscoveryStarted(serviceType: String?) = impl.onStarted() - override fun onDiscoveryStopped(serviceType: String?) = impl.onStopped() - override fun onServiceFound(serviceInfo: NsdServiceInfo) = impl.onServiceFound(serviceInfo) - override fun onServiceLost(serviceInfo: NsdServiceInfo) = impl.onServiceLost(serviceInfo) - - override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) { - Log.e(TAG, "Service discovery failed to start [E: $errorCode ]") - impl.onStartFailed() - } - - override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) { - Log.w(TAG, "Service discovery failed to stop [E: $errorCode ]") - // From our perspective, this is same as onDiscoveryStopped(). - // We can't retry stopping it because NsdManager will clear the listener - // before invoking this callback. - impl.onStopped() - } - } - - /** - * Listener for service resolution result. - */ - private class ResolveListener : NsdManager.ResolveListener { - override fun onServiceResolved(serviceInfo: NsdServiceInfo) { - impl.onResolved(serviceInfo) - impl.onResolveFinished(this) - } - - override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) { - Log.e(TAG, "Service resolution failed for '${serviceInfo}' [E: $errorCode]") - impl.onResolveFinished(this) - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/SshTunnel.kt b/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/SshTunnel.kt deleted file mode 100644 index 79501f2..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/viewmodel/service/SshTunnel.kt +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2024 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.viewmodel.service - -import android.util.Base64 -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ProcessLifecycleOwner -import androidx.lifecycle.lifecycleScope -import com.gaurav.avnc.model.LoginInfo -import com.gaurav.avnc.model.ServerProfile -import com.gaurav.avnc.viewmodel.VncViewModel -import com.trilead.ssh2.Connection -import com.trilead.ssh2.KnownHosts -import com.trilead.ssh2.LocalPortForwarder -import com.trilead.ssh2.ServerHostKeyVerifier -import com.trilead.ssh2.crypto.PEMDecoder -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import java.io.Closeable -import java.io.File -import java.io.IOException -import java.net.InetAddress -import java.net.InetSocketAddress -import java.net.NoRouteToHostException -import java.net.ServerSocket -import java.security.KeyPair -import java.security.MessageDigest - -/** - * Container for SSH Host Key - */ -class HostKey( - val host: String, - val isKnownHost: Boolean, - val algo: String, - val key: ByteArray, -) { - /** - * Returns SHA-256 fingerprint of the [key]. - */ - fun getFingerprint(): String { - val sha256 = MessageDigest.getInstance("SHA-256").digest(key) - val base64 = Base64.encodeToString(sha256, Base64.NO_PADDING) - return "SHA256:$base64" - } -} - -/** - * Implements Host Key verification. - * - * Known hosts & keys are stored in a file inside app's private storage. - * For unknown host, user is prompted to confirm the key. - */ -class HostKeyVerifier(private val viewModel: VncViewModel) : ServerHostKeyVerifier { - - private val knownHostsFile = File(viewModel.app.filesDir, "known-hosts") - - private val knownHosts = KnownHosts(knownHostsFile) - - override fun verifyServerHostKey(hostname: String, port: Int, keyAlgorithm: String, key: ByteArray): Boolean { - val verification = knownHosts.verifyHostkey(hostname, keyAlgorithm, key) - - if (verification == KnownHosts.HOSTKEY_IS_OK) - return true - - val isKnownHost = (verification == KnownHosts.HOSTKEY_HAS_CHANGED) - val hostKey = HostKey(hostname, isKnownHost, keyAlgorithm, key) - - if (viewModel.sshHostKeyVerifyRequest.requestResponse(hostKey)) { - //User has confirmed the key, so remember it. - KnownHosts.addHostkeyToFile(knownHostsFile, arrayOf(hostname), keyAlgorithm, key) - return true - } - - return false - } -} - -/** - * Small wrapper around [LocalPortForwarder]. - * - * Once connection has been successfully established via [host] & [port], - * this gate should be closed to stop new connections. - */ -class TunnelGate(val host: String, val port: Int, private val forwarder: LocalPortForwarder) : Closeable { - override fun close() { - forwarder.close() - } -} - -/** - * Manager for SSH Tunnel - */ -class SshTunnel(private val viewModel: VncViewModel) { - - private var connection: Connection? = null - private val localHost = "127.0.0.1" - - /** - * Opens the tunnel according to current profile in [viewModel]. - */ - fun open(): TunnelGate { - val profile = viewModel.profile - val connection = connect(profile) - this.connection = connection - - authenticate(connection, profile) - - if (!connection.isAuthenticationComplete) - throw IOException("SSH authentication failed") - - - // SSHLib does not expose internal ServerSocket used for local port forwarder. - // Hence, if we pass 0 as local port to let the system pick a port for us, we have no way - // to know the port system picked. - // So we create a temporary ServerSocket, close it immediately and try to use its port. - // But between the close-reuse, that port can be assigned to someone else, so we try again. - for (i in 1..50) { - val attemptedPort = ServerSocket(0).use { it.localPort } - val address = InetSocketAddress(localHost, attemptedPort) - - try { - val forwarder = connection.createLocalPortForwarder(address, profile.host, profile.port) - return TunnelGate(localHost, attemptedPort, forwarder) - } catch (e: IOException) { - //Retry - } - } - throw IOException("Cannot find a local port for SSH Tunnel") - } - - /** - * It is possible for a host to have multiple IP addresses. - * If connection failed due to [NoRouteToHostException], we try the next address (if available). - */ - private fun connect(profile: ServerProfile): Connection { - for (address in InetAddress.getAllByName(profile.sshHost)) { - try { - return Connection(address.hostAddress, profile.sshPort).apply { connect(HostKeyVerifier(viewModel)) } - } catch (e: IOException) { - if (e.cause is NoRouteToHostException) continue - else throw e - } - } - // We will reach here only if every address throws NoRouteToHostException - throw NoRouteToHostException("Unreachable SSH host: ${profile.sshHost}") - } - - private fun authenticate(connection: Connection, profile: ServerProfile) { - when (profile.sshAuthType) { - ServerProfile.SSH_AUTH_PASSWORD -> { - val password = viewModel.getLoginInfo(LoginInfo.Type.SSH_PASSWORD).password //Possibly blocking call - connection.authenticateWithPassword(profile.sshUsername, password) - } - ServerProfile.SSH_AUTH_KEY -> { - val pk = profile.sshPrivateKey - val cached = KeyCache.get(pk) - if (cached != null) { - connection.authenticateWithPublicKey(profile.sshUsername, cached) - } else { - val pem = PEMDecoder.parsePEM(pk.toCharArray()) - var password = "" - if (PEMDecoder.isPEMEncrypted(pem)) { - password = viewModel.getLoginInfo(LoginInfo.Type.SSH_KEY_PASSWORD).password //Blocking call - } - val keyPair = PEMDecoder.decode(pem, password) - connection.authenticateWithPublicKey(profile.sshUsername, keyPair) - KeyCache.put(pk, keyPair) - } - } - else -> throw IOException("Unknown SSH auth type: ${profile.sshAuthType}") - } - } - - fun close() { - connection?.close() - } - - /** - * A very simple key cache to keep unlocked/decoded keys in memory - * Strategy: - * 1. Keep keys in memory as long as app is in foreground - * 2. Clear cache if app goes in background for more than 15 minutes - */ - private object KeyCache { - private val cache = mutableMapOf() - private var lifecycleObserver: DefaultLifecycleObserver? = null - - fun get(pk: String): KeyPair? { - synchronized(cache) { - return cache[pk] - } - } - - fun put(pk: String, keyPair: KeyPair) { - synchronized(cache) { - cache[pk] = keyPair - addLifecycleObserver() - } - } - - private fun addLifecycleObserver() { - if (lifecycleObserver != null) - return // Already added - - lifecycleObserver = object : DefaultLifecycleObserver { - var cleanupJob: Job? = null - - override fun onStart(owner: LifecycleOwner) { - cleanupJob?.let { if (it.isActive) it.cancel() } - cleanupJob = null - } - - override fun onStop(owner: LifecycleOwner) { - cleanupJob = owner.lifecycleScope.launch { - delay(15 * 60 * 1000) - synchronized(cache) { - cache.values.forEach { it.private.destroy() } - cache.clear() - } - } - } - } - - ProcessLifecycleOwner.get().let { - // Observer needs to be set on main thread, - // and lifecycleScope is already bound to main thread - it.lifecycleScope.launch { - it.lifecycle.addObserver(lifecycleObserver!!) - } - } - } - } -} diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/Messenger.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/Messenger.kt deleted file mode 100644 index bca07c2..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/Messenger.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -import android.graphics.PointF -import android.util.Log -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -/** - * Allows sending different types of messages to remote server. - */ -class Messenger(private val client: VncClient) { - - /************************************************************************** - * Sender thread - **************************************************************************/ - - private val sender = Executors.newSingleThreadExecutor() - private val senderLock = Any() - - private fun execute(action: Runnable) { - synchronized(senderLock) { - if (!sender.isShutdown) - sender.execute(action) - } - } - - fun cleanup() { - synchronized(senderLock) { sender.shutdown() } - runCatching { sender.awaitTermination(60, TimeUnit.SECONDS) } - if (!sender.isTerminated) Log.w(javaClass.simpleName, "Unable to fully stop Sender thread!") - } - - - /************************************************************************** - * Input events - **************************************************************************/ - - /** - * Keeps track of current pointer button state. - */ - private var pointerButtonMask: Int = 0 - - private fun sendPointerEvent(mask: Int, p: PointF) { - val x = p.x.toInt() - val y = p.y.toInt() - client.moveClientPointer(x, y) - execute { client.sendPointerEvent(x, y, mask) } - } - - fun sendPointerButtonDown(button: PointerButton, p: PointF) { - pointerButtonMask = pointerButtonMask or button.bitMask - sendPointerEvent(pointerButtonMask, p) - } - - fun sendPointerButtonUp(button: PointerButton, p: PointF) { - pointerButtonMask = pointerButtonMask and button.bitMask.inv() - sendPointerEvent(pointerButtonMask, p) - } - - fun sendPointerButtonRelease(p: PointF) { - if (pointerButtonMask != 0) { - pointerButtonMask = 0 - sendPointerEvent(pointerButtonMask, p) - } - } - - fun sendKey(keySym: Int, xtCode: Int, isDown: Boolean): Boolean { - if (!client.connected) - return false - - execute { client.sendKeyEvent(keySym, xtCode, isDown) } - return true - } - - fun insertButtonUpDelay() { - execute { runCatching { Thread.sleep(200) } } - } - - /************************************************************************** - * Misc - **************************************************************************/ - - fun sendClipboardText(text: String) { - execute { client.sendCutText(text) } - } - - fun setDesktopSize(width: Int, height: Int) { - execute { client.setDesktopSize(width, height) } - } - - fun refreshFrameBuffer() { - execute { client.refreshFrameBuffer() } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/PointerButton.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/PointerButton.kt deleted file mode 100644 index a1b11c7..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/PointerButton.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -enum class PointerButton(val bitMask: Int) { - None(0), - Left(1), - Middle(2), - Right(4), - WheelUp(8), - WheelDown(16), - WheelLeft(32), - WheelRight(64) -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/UserCredential.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/UserCredential.kt deleted file mode 100644 index 59849db..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/UserCredential.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -/** - * This class is used for returning user credentials from callbacks. - */ -data class UserCredential( - @JvmField val username: String = "", - @JvmField val password: String = "" -) \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncClient.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncClient.kt deleted file mode 100644 index 3d2094d..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncClient.kt +++ /dev/null @@ -1,348 +0,0 @@ -package com.gaurav.avnc.vnc - -import android.view.KeyEvent -import androidx.annotation.Keep -import java.io.IOException -import java.nio.ByteBuffer -import java.nio.charset.StandardCharsets - -/** - * This is a thin wrapper around native client. - * - * - * - +------------+ +----------+ - * - | Public API | | Observer | - * - +------------+ +-----A----+ - * - | | - * - | | - * - JNI -------|------------------------------------------------|----------- - * - | | - * - | | - * - +-------v--------+ +--------------+ +--------v---------+ - * - | Native Methods |------>| LibVNCClient |<----->| Native Callbacks | - * - +----------------+ +--------------+ +------------------+ - * - * - * For every new instance of [VncClient], we create a native 'rfbClient' and - * store its pointer in [nativePtr]. Parameters for connection can be setup using - * [configure]. Connection is then started using [connect]. Then incoming - * messages are handled by [processServerMessage]. - * - * To release the resources you must call [cleanup] after you are done with - * this instance. - */ -class VncClient(private val observer: Observer) { - - /** - * Interface for event observer. - * DO NOT throw exceptions from these methods. - * There is NO guarantee about which thread will invoke [Observer] methods. - */ - interface Observer { - fun onPasswordRequired(): String - fun onCredentialRequired(): UserCredential - fun onGotXCutText(text: String) - fun onFramebufferUpdated() - fun onFramebufferSizeChanged(width: Int, height: Int) - fun onPointerMoved(x: Int, y: Int) - - //fun onBell() - } - - /** - * Value of the pointer to native 'rfbClient'. This is passed to all native methods. - */ - private val nativePtr: Long - - init { - nativePtr = nativeClientCreate() - if (nativePtr == 0L) - throw RuntimeException("Could not create native rfbClient!") - } - - @Volatile - var connected = false - private set - - /** - * Name of remote desktop - */ - val desktopName; get() = nativeGetDesktopName(nativePtr) - - /** - * Whether connection is encrypted - */ - val isEncrypted; get() = nativeIsEncrypted(nativePtr) - - /** - * In 'View-only' mode input to remote server is disabled - */ - var viewOnlyMode = false; private set - - /** - * Latest pointer position. See [moveClientPointer]. - */ - var pointerX = 0; private set - var pointerY = 0; private set - - /** - * Client-side cursor rendering creates a synchronization issue. - * Suppose if pointer is moved to (50,10) by client. A PointerEvent is sent - * to the server and cursor is immediately rendered on (50,10). - * Some servers (e.g. Vino) will send back a PointerPosition event for (50, 10). - * But, by the time that event is received from server, pointer on client - * might have already moved to (60,20) (this is almost guaranteed to happen - * with touchpad/relative action mode). So the cursor will probably 'jump back' - * depending on the order of these events. - * - * This flags works around the issue by temporarily ignoring serer-side updates. - */ - @Volatile - var ignorePointerMovesByServer = false - - - @Volatile - private var autoFBRequestsQueued = true - private var autoFBRequests = autoFBRequestsQueued - - /** - * Value of the most recent cut text sent/received from server - */ - @Volatile - private var lastCutText: String? = null - - /** - * Setup different properties for this client. - * - * @param securityType RFB security type to use. - */ - fun configure(viewOnly: Boolean, securityType: Int, useLocalCursor: Boolean, imageQuality: Int, useRawEncoding: Boolean) { - viewOnlyMode = viewOnly - nativeConfigure(nativePtr, securityType, useLocalCursor, imageQuality, useRawEncoding) - } - - fun setupRepeater(serverId: Int) { - nativeSetDest(nativePtr, "ID", serverId) - } - - /** - * Initializes VNC connection. - */ - fun connect(host: String, port: Int) { - connected = nativeInit(nativePtr, host, port) - if (!connected) throw IOException(nativeGetLastErrorStr()) - applyCompatQuirks() - } - - /** - * Waits for incoming server message, parses it and then invokes appropriate callbacks. - * - * @param uSecTimeout Timeout in microseconds. - */ - fun processServerMessage(uSecTimeout: Int = 1000000) { - if (!connected) - return - - if (!nativeProcessServerMessage(nativePtr, uSecTimeout)) { - connected = false - throw IOException(nativeGetLastErrorStr()) - } - - if (autoFBRequests != autoFBRequestsQueued) { - autoFBRequests = autoFBRequestsQueued - nativeSetAutomaticFramebufferUpdates(nativePtr, autoFBRequests) - } - } - - /** - * Sends Key event to remote server. - * - * @param keySym Key symbol - * @param xtCode Key code from [XTKeyCode] - * @param isDown true for key down, false for key up - */ - fun sendKeyEvent(keySym: Int, xtCode: Int, isDown: Boolean) = ifConnectedAndInteractive { - nativeSendKeyEvent(nativePtr, keySym, xtCode, isDown) - } - - /** - * Sends pointer event to remote server. - * - * @param x Horizontal pointer coordinate - * @param y Vertical pointer coordinate - * @param mask Button mask to identify which button was pressed. - */ - fun sendPointerEvent(x: Int, y: Int, mask: Int) = ifConnectedAndInteractive { - nativeSendPointerEvent(nativePtr, x, y, mask) - } - - /** - * Updates client-side pointer position. - * No event is sent to server. - * - * Primary use-case is to update pointer position during gestures. - * This way we can immediately render the cursor on new position without - * waiting for Network IO. - * - * It also helps with servers which don't send pointer-position updates - * if pointer was moved by the client. - * - * @param x Horizontal pointer coordinate - * @param y Vertical pointer coordinate - */ - fun moveClientPointer(x: Int, y: Int) { - pointerX = x - pointerY = y - observer.onPointerMoved(x, y) - } - - - /** - * Sends text to remote desktop's clipboard. - */ - fun sendCutText(text: String) = ifConnectedAndInteractive { - if (text != lastCutText) { - val sent = if (nativeIsUTF8CutTextSupported(nativePtr)) - nativeSendCutText(nativePtr, text.toByteArray(StandardCharsets.UTF_8), true) - else - nativeSendCutText(nativePtr, text.toByteArray(StandardCharsets.ISO_8859_1), false) - if (sent) - lastCutText = text - } - } - - /** - * Set remote desktop size to given dimensions. - * This needs server support to actually work. - * Non-positive [width] & [height] are ignored. - */ - fun setDesktopSize(width: Int, height: Int) = ifConnected { - if (width > 0 && height > 0) - nativeSetDesktopSize(nativePtr, width, height) - } - - /** - * Sends frame buffer update request to remote server. - */ - fun refreshFrameBuffer() = ifConnected { - nativeRefreshFrameBuffer(nativePtr) - } - - /** - * Controls whether framebuffer update requests are sent automatically. - * It takes effect after the next call to [processServerMessage]. - */ - /*fun setAutomaticFrameBufferUpdates(enabled: Boolean) = ifConnected { - //autoFBRequestsQueued = enabled - }*/ - - /** - * Puts framebuffer contents in currently active OpenGL texture. - * Must be called from an OpenGL ES context (i.e. from renderer thread). - */ - fun uploadFrameTexture() = nativeUploadFrameTexture(nativePtr) - - /** - * Upload cursor shape into framebuffer texture. - */ - fun uploadCursor() = nativeUploadCursor(nativePtr, pointerX, pointerY) - - /** - * Release all resources allocated by the client. - * DO NOT use this client after [cleanup]. - */ - fun cleanup() { - connected = false - nativeCleanup(nativePtr) - } - - private inline fun ifConnected(block: () -> Unit) { - if (connected) - block() - } - - private inline fun ifConnectedAndInteractive(block: () -> Unit) = ifConnected { - if (!viewOnlyMode) - block() - } - - private fun applyCompatQuirks() { - if (nativeIsServerMacOS(nativePtr)) { - XKeySymAndroid.updateKeyMap(KeyEvent.KEYCODE_ALT_LEFT, XKeySym.XK_Meta_L) - XKeySymAndroid.updateKeyMap(KeyEvent.KEYCODE_ALT_RIGHT, XKeySym.XK_Meta_R) - } - } - - private external fun nativeClientCreate(): Long - private external fun nativeConfigure(clientPtr: Long, securityType: Int, useLocalCursor: Boolean, imageQuality: Int, useRawEncoding: Boolean) - private external fun nativeInit(clientPtr: Long, host: String, port: Int): Boolean - private external fun nativeSetDest(clientPtr: Long, host: String, port: Int) - private external fun nativeProcessServerMessage(clientPtr: Long, uSecTimeout: Int): Boolean - private external fun nativeSendKeyEvent(clientPtr: Long, keySym: Int, xtCode: Int, isDown: Boolean): Boolean - private external fun nativeSendPointerEvent(clientPtr: Long, x: Int, y: Int, mask: Int): Boolean - private external fun nativeSendCutText(clientPtr: Long, bytes: ByteArray, isUTF8: Boolean): Boolean - private external fun nativeIsUTF8CutTextSupported(clientPtr: Long): Boolean - private external fun nativeSetDesktopSize(clientPtr: Long, width: Int, height: Int): Boolean - private external fun nativeRefreshFrameBuffer(clientPtr: Long): Boolean - private external fun nativeSetAutomaticFramebufferUpdates(clientPtr: Long, enabled: Boolean) - private external fun nativeGetDesktopName(clientPtr: Long): String - private external fun nativeGetWidth(clientPtr: Long): Int - private external fun nativeGetHeight(clientPtr: Long): Int - private external fun nativeIsEncrypted(clientPtr: Long): Boolean - private external fun nativeUploadFrameTexture(clientPtr: Long) - private external fun nativeUploadCursor(clientPtr: Long, px: Int, py: Int) - private external fun nativeGetLastErrorStr(): String - private external fun nativeIsServerMacOS(clientPtr: Long): Boolean - private external fun nativeCleanup(clientPtr: Long) - - @Keep - private fun cbGetPassword() = observer.onPasswordRequired() - - @Keep - private fun cbGetCredential() = observer.onCredentialRequired() - - @Keep - private fun cbGotXCutText(bytes: ByteArray, isUTF8: Boolean) { - (if (isUTF8) StandardCharsets.UTF_8 else StandardCharsets.ISO_8859_1).let { - val cutText = it.decode(ByteBuffer.wrap(bytes)).toString() - if (cutText != lastCutText) { - lastCutText = cutText - observer.onGotXCutText(cutText) - } - } - } - - @Keep - private fun cbFinishedFrameBufferUpdate() = observer.onFramebufferUpdated() - - @Keep - private fun cbFramebufferSizeChanged(w: Int, h: Int) = observer.onFramebufferSizeChanged(w, h) - - - @Keep - private fun cbBell() = Unit // observer.onBell() - - @Keep - private fun cbHandleCursorPos(x: Int, y: Int) { - if (!ignorePointerMovesByServer) - moveClientPointer(x, y) - } - - - /** - * Native library initialization - */ - companion object { - fun loadLibrary() { - System.loadLibrary("native-vnc") - } - - @JvmStatic - private external fun initLibrary() - - init { - loadLibrary() - initLibrary() - } - } -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncUri.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncUri.kt deleted file mode 100644 index b14a1ee..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/VncUri.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2020 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -import android.net.Uri -import com.gaurav.avnc.model.ServerProfile -import java.net.URI - -/** - * This class implements the `vnc` URI scheme. - * Reference: https://tools.ietf.org/html/rfc7869 - * - * If host in given URI string is an IPv6 address, it MUST be wrapped in square brackets. - * (This requirement come from using Java [URI] internally.) - * - * If given URI doesn't start with 'vnc://' scheme, it will be automatically added. - */ -class VncUri(str: String) { - - /** - * Add scheme if missing. - * It is also common for users to accidentally type 'vnc:host' instead of 'vnc://host', - * so we gracefully handle that case too. - */ - private val uriString = str.replaceFirst(Regex("^(vnc:/?/?)?", RegexOption.IGNORE_CASE), "vnc://") - - private val uri = Uri.parse(uriString) - - /** - * Older versions of Android [Uri] does not support IPv6, so we need to use Java [URI] for host & port. - * It also serves as a validation step because [URI] verifies that address is well-formed. - */ - private val javaUri = runCatching { URI(uriString) }.getOrNull() - - - val host = javaUri?.host?.trim('[', ']') ?: "" - val port = if (javaUri?.port == -1) 5900 else javaUri?.port ?: 5900 - val connectionName = uri.getQueryParameter("ConnectionName") ?: "" - val username = uri.getQueryParameter("VncUsername") ?: "" - val password = uri.getQueryParameter("VncPassword") ?: "" - val securityType = uri.getQueryParameter("SecurityType")?.toIntOrNull() ?: 0 - val channelType = uri.getQueryParameter("ChannelType")?.toIntOrNull() ?: ServerProfile.CHANNEL_TCP - val colorLevel = uri.getQueryParameter("ColorLevel")?.toIntOrNull() ?: 7 - val viewOnly = uri.getBooleanQueryParameter("ViewOnly", false) - val saveConnection = uri.getBooleanQueryParameter("SaveConnection", false) - val sshHost = uri.getQueryParameter("SshHost") ?: host - val sshPort = uri.getQueryParameter("SshPort")?.toIntOrNull() ?: 22 - val sshUsername = uri.getQueryParameter("SshUsername") ?: "" - val sshPassword = uri.getQueryParameter("SshPassword") ?: "" - - /** - * Generates a [ServerProfile] using this instance. - */ - fun toServerProfile() = ServerProfile( - name = connectionName, - host = host, - port = port, - username = username, - password = password, - securityType = securityType, - channelType = channelType, - colorLevel = colorLevel, - viewOnly = viewOnly, - sshHost = sshHost, - sshPort = sshPort, - sshUsername = sshUsername, - sshAuthType = ServerProfile.SSH_AUTH_PASSWORD, - sshPassword = sshPassword - ) - - override fun toString() = uriString -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySym.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySym.kt deleted file mode 100644 index 8710c49..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySym.kt +++ /dev/null @@ -1,2525 +0,0 @@ -@file:Suppress("unused", "SpellCheckingInspection") - -/** - * X Key Symbols. - * - * Derived from: - * [keysymdef.h](https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/keysymdef.h) - * [XF86keysym.h](https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/XF86keysym.h) - * - * @formatter:off - */ - -/*********************************************************** -Copyright 1987, 1994, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts - -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - - ******************************************************************/ - -/* - * The "X11 Window System Protocol" standard defines in Appendix A the - * keysym codes. These 29-bit integer values identify characters or - * functions associated with each key (e.g., via the visible - * engraving) of a keyboard layout. This file assigns mnemonic macro - * names for these keysyms. - * - * This file is also compiled (by src/util/makekeys.c in libX11) into - * hash tables that can be accessed with X11 library functions such as - * XStringToKeysym() and XKeysymToString(). - * - * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode - * character, this is noted in a comment that provides both the U+xxxx - * Unicode position, as well as the official Unicode name of the - * character. - * - * Where the correspondence is either not one-to-one or semantically - * unclear, the Unicode position and name are enclosed in - * parentheses. Such legacy keysyms should be considered deprecated - * and are not recommended for use in future keyboard mappings. - * - * For any future extension of the keysyms with characters already - * found in ISO 10646 / Unicode, the following algorithm shall be - * used. The new keysym code position will simply be the character's - * Unicode number plus 0x01000000. The keysym values in the range - * 0x01000100 to 0x0110ffff are reserved to represent Unicode - * characters in the range U+0100 to U+10FFFF. - * - * While most newer Unicode-based X11 clients do already accept - * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it - * will remain necessary for clients -- in the interest of - * compatibility with existing servers -- to also understand the - * existing legacy keysym values in the range 0x0100 to 0x20ff. - * - * Where several mnemonic names are defined for the same keysym in this - * file, all but the first one listed should be considered deprecated. - * - * Mnemonic names for keysyms are defined in this file with lines - * that match one of these Perl regular expressions: - * - * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\* U\+([0-9A-F]{4,6}) (.*) \*\/\s*$/ - * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\(U\+([0-9A-F]{4,6}) (.*)\)\*\/\s*$/ - * /^\#define XK_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/ - * - * Before adding new keysyms, please do consider the following: In - * addition to the keysym names defined in this file, the - * XStringToKeysym() and XKeysymToString() functions will also handle - * any keysym string of the form "U0020" to "U007E" and "U00A0" to - * "U10FFFF" for all possible Unicode characters. In other words, - * every possible Unicode character has already a keysym string - * defined algorithmically, even if it is not listed here. Therefore, - * defining an additional keysym macro is only necessary where a - * non-hexadecimal mnemonic name is needed, or where the new keysym - * does not represent any existing Unicode character. - * - * When adding new keysyms to this file, do not forget to also update the - * following as needed: - * - * - the mappings in src/KeyBind.c in the libX11 repo - * https://gitlab.freedesktop.org/xorg/lib/libx11 - * - * - the protocol specification in specs/keysyms.xml in this repo - * https://gitlab.freedesktop.org/xorg/proto/xorgproto - * - */ - -package com.gaurav.avnc.vnc - -object XKeySym { - - const val XK_VoidSymbol = 0xffffff /* Void symbol */ - - - // #ifdef XK_MISCELLANY - /* - * TTY function keys, cleverly chosen to map to ASCII, for convenience of - * programming, but could have been arbitrary (at the cost of lookup - * tables in client code). - */ - - const val XK_BackSpace = 0xff08 /* Back space, back char */ - const val XK_Tab = 0xff09 - const val XK_Linefeed = 0xff0a /* Linefeed, LF */ - const val XK_Clear = 0xff0b - const val XK_Return = 0xff0d /* Return, enter */ - const val XK_Pause = 0xff13 /* Pause, hold */ - const val XK_Scroll_Lock = 0xff14 - const val XK_Sys_Req = 0xff15 - const val XK_Escape = 0xff1b - const val XK_Delete = 0xffff /* Delete, rubout */ - - - /* International & multi-key character composition */ - - const val XK_Multi_key = 0xff20 /* Multi-key character compose */ - const val XK_Codeinput = 0xff37 - const val XK_SingleCandidate = 0xff3c - const val XK_MultipleCandidate = 0xff3d - const val XK_PreviousCandidate = 0xff3e - - /* Japanese keyboard support */ - - const val XK_Kanji = 0xff21 /* Kanji, Kanji convert */ - const val XK_Muhenkan = 0xff22 /* Cancel Conversion */ - const val XK_Henkan_Mode = 0xff23 /* Start/Stop Conversion */ - const val XK_Henkan = 0xff23 /* Alias for Henkan_Mode */ - const val XK_Romaji = 0xff24 /* to Romaji */ - const val XK_Hiragana = 0xff25 /* to Hiragana */ - const val XK_Katakana = 0xff26 /* to Katakana */ - const val XK_Hiragana_Katakana = 0xff27 /* Hiragana/Katakana toggle */ - const val XK_Zenkaku = 0xff28 /* to Zenkaku */ - const val XK_Hankaku = 0xff29 /* to Hankaku */ - const val XK_Zenkaku_Hankaku = 0xff2a /* Zenkaku/Hankaku toggle */ - const val XK_Touroku = 0xff2b /* Add to Dictionary */ - const val XK_Massyo = 0xff2c /* Delete from Dictionary */ - const val XK_Kana_Lock = 0xff2d /* Kana Lock */ - const val XK_Kana_Shift = 0xff2e /* Kana Shift */ - const val XK_Eisu_Shift = 0xff2f /* Alphanumeric Shift */ - const val XK_Eisu_toggle = 0xff30 /* Alphanumeric toggle */ - const val XK_Kanji_Bangou = 0xff37 /* Codeinput */ - const val XK_Zen_Koho = 0xff3d /* Multiple/All Candidate(s) */ - const val XK_Mae_Koho = 0xff3e /* Previous Candidate */ - - /* 0xff31 thru 0xff3f are under XK_KOREAN */ - - /* Cursor control & motion */ - - const val XK_Home = 0xff50 - const val XK_Left = 0xff51 /* Move left, left arrow */ - const val XK_Up = 0xff52 /* Move up, up arrow */ - const val XK_Right = 0xff53 /* Move right, right arrow */ - const val XK_Down = 0xff54 /* Move down, down arrow */ - const val XK_Prior = 0xff55 /* Prior, previous */ - const val XK_Page_Up = 0xff55 - const val XK_Next = 0xff56 /* Next */ - const val XK_Page_Down = 0xff56 - const val XK_End = 0xff57 /* EOL */ - const val XK_Begin = 0xff58 /* BOL */ - - - /* Misc functions */ - - const val XK_Select = 0xff60 /* Select, mark */ - const val XK_Print = 0xff61 - const val XK_Execute = 0xff62 /* Execute, run, do */ - const val XK_Insert = 0xff63 /* Insert, insert here */ - const val XK_Undo = 0xff65 - const val XK_Redo = 0xff66 /* Redo, again */ - const val XK_Menu = 0xff67 - const val XK_Find = 0xff68 /* Find, search */ - const val XK_Cancel = 0xff69 /* Cancel, stop, abort, exit */ - const val XK_Help = 0xff6a /* Help */ - const val XK_Break = 0xff6b - const val XK_Mode_switch = 0xff7e /* Character set switch */ - const val XK_script_switch = 0xff7e /* Alias for mode_switch */ - const val XK_Num_Lock = 0xff7f - - /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ - - const val XK_KP_Space = 0xff80 /* Space */ - const val XK_KP_Tab = 0xff89 - const val XK_KP_Enter = 0xff8d /* Enter */ - const val XK_KP_F1 = 0xff91 /* PF1, KP_A, ... */ - const val XK_KP_F2 = 0xff92 - const val XK_KP_F3 = 0xff93 - const val XK_KP_F4 = 0xff94 - const val XK_KP_Home = 0xff95 - const val XK_KP_Left = 0xff96 - const val XK_KP_Up = 0xff97 - const val XK_KP_Right = 0xff98 - const val XK_KP_Down = 0xff99 - const val XK_KP_Prior = 0xff9a - const val XK_KP_Page_Up = 0xff9a - const val XK_KP_Next = 0xff9b - const val XK_KP_Page_Down = 0xff9b - const val XK_KP_End = 0xff9c - const val XK_KP_Begin = 0xff9d - const val XK_KP_Insert = 0xff9e - const val XK_KP_Delete = 0xff9f - const val XK_KP_Equal = 0xffbd /* Equals */ - const val XK_KP_Multiply = 0xffaa - const val XK_KP_Add = 0xffab - const val XK_KP_Separator = 0xffac /* Separator, often comma */ - const val XK_KP_Subtract = 0xffad - const val XK_KP_Decimal = 0xffae - const val XK_KP_Divide = 0xffaf - - const val XK_KP_0 = 0xffb0 - const val XK_KP_1 = 0xffb1 - const val XK_KP_2 = 0xffb2 - const val XK_KP_3 = 0xffb3 - const val XK_KP_4 = 0xffb4 - const val XK_KP_5 = 0xffb5 - const val XK_KP_6 = 0xffb6 - const val XK_KP_7 = 0xffb7 - const val XK_KP_8 = 0xffb8 - const val XK_KP_9 = 0xffb9 - - - /* - * Auxiliary functions; note the duplicate definitions for left and right - * function keys; Sun keyboards and a few other manufacturers have such - * function key groups on the left and/or right sides of the keyboard. - * We've not found a keyboard with more than 35 function keys total. - */ - - const val XK_F1 = 0xffbe - const val XK_F2 = 0xffbf - const val XK_F3 = 0xffc0 - const val XK_F4 = 0xffc1 - const val XK_F5 = 0xffc2 - const val XK_F6 = 0xffc3 - const val XK_F7 = 0xffc4 - const val XK_F8 = 0xffc5 - const val XK_F9 = 0xffc6 - const val XK_F10 = 0xffc7 - const val XK_F11 = 0xffc8 - const val XK_L1 = 0xffc8 - const val XK_F12 = 0xffc9 - const val XK_L2 = 0xffc9 - const val XK_F13 = 0xffca - const val XK_L3 = 0xffca - const val XK_F14 = 0xffcb - const val XK_L4 = 0xffcb - const val XK_F15 = 0xffcc - const val XK_L5 = 0xffcc - const val XK_F16 = 0xffcd - const val XK_L6 = 0xffcd - const val XK_F17 = 0xffce - const val XK_L7 = 0xffce - const val XK_F18 = 0xffcf - const val XK_L8 = 0xffcf - const val XK_F19 = 0xffd0 - const val XK_L9 = 0xffd0 - const val XK_F20 = 0xffd1 - const val XK_L10 = 0xffd1 - const val XK_F21 = 0xffd2 - const val XK_R1 = 0xffd2 - const val XK_F22 = 0xffd3 - const val XK_R2 = 0xffd3 - const val XK_F23 = 0xffd4 - const val XK_R3 = 0xffd4 - const val XK_F24 = 0xffd5 - const val XK_R4 = 0xffd5 - const val XK_F25 = 0xffd6 - const val XK_R5 = 0xffd6 - const val XK_F26 = 0xffd7 - const val XK_R6 = 0xffd7 - const val XK_F27 = 0xffd8 - const val XK_R7 = 0xffd8 - const val XK_F28 = 0xffd9 - const val XK_R8 = 0xffd9 - const val XK_F29 = 0xffda - const val XK_R9 = 0xffda - const val XK_F30 = 0xffdb - const val XK_R10 = 0xffdb - const val XK_F31 = 0xffdc - const val XK_R11 = 0xffdc - const val XK_F32 = 0xffdd - const val XK_R12 = 0xffdd - const val XK_F33 = 0xffde - const val XK_R13 = 0xffde - const val XK_F34 = 0xffdf - const val XK_R14 = 0xffdf - const val XK_F35 = 0xffe0 - const val XK_R15 = 0xffe0 - - /* Modifiers */ - - const val XK_Shift_L = 0xffe1 /* Left shift */ - const val XK_Shift_R = 0xffe2 /* Right shift */ - const val XK_Control_L = 0xffe3 /* Left control */ - const val XK_Control_R = 0xffe4 /* Right control */ - const val XK_Caps_Lock = 0xffe5 /* Caps lock */ - const val XK_Shift_Lock = 0xffe6 /* Shift lock */ - - const val XK_Meta_L = 0xffe7 /* Left meta */ - const val XK_Meta_R = 0xffe8 /* Right meta */ - const val XK_Alt_L = 0xffe9 /* Left alt */ - const val XK_Alt_R = 0xffea /* Right alt */ - const val XK_Super_L = 0xffeb /* Left super */ - const val XK_Super_R = 0xffec /* Right super */ - const val XK_Hyper_L = 0xffed /* Left hyper */ - const val XK_Hyper_R = 0xffee /* Right hyper */ - // #endif /* XK_MISCELLANY */ - - /* - * Keyboard (XKB) Extension function and modifier keys - * (from Appendix C of "The X Keyboard Extension: Protocol Specification") - * Byte 3 = 0xfe - */ - - // #ifdef XK_XKB_KEYS - const val XK_ISO_Lock = 0xfe01 - const val XK_ISO_Level2_Latch = 0xfe02 - const val XK_ISO_Level3_Shift = 0xfe03 - const val XK_ISO_Level3_Latch = 0xfe04 - const val XK_ISO_Level3_Lock = 0xfe05 - const val XK_ISO_Level5_Shift = 0xfe11 - const val XK_ISO_Level5_Latch = 0xfe12 - const val XK_ISO_Level5_Lock = 0xfe13 - const val XK_ISO_Group_Shift = 0xff7e /* Alias for mode_switch */ - const val XK_ISO_Group_Latch = 0xfe06 - const val XK_ISO_Group_Lock = 0xfe07 - const val XK_ISO_Next_Group = 0xfe08 - const val XK_ISO_Next_Group_Lock = 0xfe09 - const val XK_ISO_Prev_Group = 0xfe0a - const val XK_ISO_Prev_Group_Lock = 0xfe0b - const val XK_ISO_First_Group = 0xfe0c - const val XK_ISO_First_Group_Lock = 0xfe0d - const val XK_ISO_Last_Group = 0xfe0e - const val XK_ISO_Last_Group_Lock = 0xfe0f - - const val XK_ISO_Left_Tab = 0xfe20 - const val XK_ISO_Move_Line_Up = 0xfe21 - const val XK_ISO_Move_Line_Down = 0xfe22 - const val XK_ISO_Partial_Line_Up = 0xfe23 - const val XK_ISO_Partial_Line_Down = 0xfe24 - const val XK_ISO_Partial_Space_Left = 0xfe25 - const val XK_ISO_Partial_Space_Right = 0xfe26 - const val XK_ISO_Set_Margin_Left = 0xfe27 - const val XK_ISO_Set_Margin_Right = 0xfe28 - const val XK_ISO_Release_Margin_Left = 0xfe29 - const val XK_ISO_Release_Margin_Right = 0xfe2a - const val XK_ISO_Release_Both_Margins = 0xfe2b - const val XK_ISO_Fast_Cursor_Left = 0xfe2c - const val XK_ISO_Fast_Cursor_Right = 0xfe2d - const val XK_ISO_Fast_Cursor_Up = 0xfe2e - const val XK_ISO_Fast_Cursor_Down = 0xfe2f - const val XK_ISO_Continuous_Underline = 0xfe30 - const val XK_ISO_Discontinuous_Underline = 0xfe31 - const val XK_ISO_Emphasize = 0xfe32 - const val XK_ISO_Center_Object = 0xfe33 - const val XK_ISO_Enter = 0xfe34 - - const val XK_dead_grave = 0xfe50 - const val XK_dead_acute = 0xfe51 - const val XK_dead_circumflex = 0xfe52 - const val XK_dead_tilde = 0xfe53 - const val XK_dead_perispomeni = 0xfe53 /* alias for dead_tilde */ - const val XK_dead_macron = 0xfe54 - const val XK_dead_breve = 0xfe55 - const val XK_dead_abovedot = 0xfe56 - const val XK_dead_diaeresis = 0xfe57 - const val XK_dead_abovering = 0xfe58 - const val XK_dead_doubleacute = 0xfe59 - const val XK_dead_caron = 0xfe5a - const val XK_dead_cedilla = 0xfe5b - const val XK_dead_ogonek = 0xfe5c - const val XK_dead_iota = 0xfe5d - const val XK_dead_voiced_sound = 0xfe5e - const val XK_dead_semivoiced_sound = 0xfe5f - const val XK_dead_belowdot = 0xfe60 - const val XK_dead_hook = 0xfe61 - const val XK_dead_horn = 0xfe62 - const val XK_dead_stroke = 0xfe63 - const val XK_dead_abovecomma = 0xfe64 - const val XK_dead_psili = 0xfe64 /* alias for dead_abovecomma */ - const val XK_dead_abovereversedcomma = 0xfe65 - const val XK_dead_dasia = 0xfe65 /* alias for dead_abovereversedcomma */ - const val XK_dead_doublegrave = 0xfe66 - const val XK_dead_belowring = 0xfe67 - const val XK_dead_belowmacron = 0xfe68 - const val XK_dead_belowcircumflex = 0xfe69 - const val XK_dead_belowtilde = 0xfe6a - const val XK_dead_belowbreve = 0xfe6b - const val XK_dead_belowdiaeresis = 0xfe6c - const val XK_dead_invertedbreve = 0xfe6d - const val XK_dead_belowcomma = 0xfe6e - const val XK_dead_currency = 0xfe6f - - /* extra dead elements for German T3 layout */ - const val XK_dead_lowline = 0xfe90 - const val XK_dead_aboveverticalline = 0xfe91 - const val XK_dead_belowverticalline = 0xfe92 - const val XK_dead_longsolidusoverlay = 0xfe93 - - /* dead vowels for universal syllable entry */ - const val XK_dead_a = 0xfe80 - const val XK_dead_A = 0xfe81 - const val XK_dead_e = 0xfe82 - const val XK_dead_E = 0xfe83 - const val XK_dead_i = 0xfe84 - const val XK_dead_I = 0xfe85 - const val XK_dead_o = 0xfe86 - const val XK_dead_O = 0xfe87 - const val XK_dead_u = 0xfe88 - const val XK_dead_U = 0xfe89 - const val XK_dead_small_schwa = 0xfe8a - const val XK_dead_capital_schwa = 0xfe8b - - const val XK_dead_greek = 0xfe8c - - const val XK_First_Virtual_Screen = 0xfed0 - const val XK_Prev_Virtual_Screen = 0xfed1 - const val XK_Next_Virtual_Screen = 0xfed2 - const val XK_Last_Virtual_Screen = 0xfed4 - const val XK_Terminate_Server = 0xfed5 - - const val XK_AccessX_Enable = 0xfe70 - const val XK_AccessX_Feedback_Enable = 0xfe71 - const val XK_RepeatKeys_Enable = 0xfe72 - const val XK_SlowKeys_Enable = 0xfe73 - const val XK_BounceKeys_Enable = 0xfe74 - const val XK_StickyKeys_Enable = 0xfe75 - const val XK_MouseKeys_Enable = 0xfe76 - const val XK_MouseKeys_Accel_Enable = 0xfe77 - const val XK_Overlay1_Enable = 0xfe78 - const val XK_Overlay2_Enable = 0xfe79 - const val XK_AudibleBell_Enable = 0xfe7a - - const val XK_Pointer_Left = 0xfee0 - const val XK_Pointer_Right = 0xfee1 - const val XK_Pointer_Up = 0xfee2 - const val XK_Pointer_Down = 0xfee3 - const val XK_Pointer_UpLeft = 0xfee4 - const val XK_Pointer_UpRight = 0xfee5 - const val XK_Pointer_DownLeft = 0xfee6 - const val XK_Pointer_DownRight = 0xfee7 - const val XK_Pointer_Button_Dflt = 0xfee8 - const val XK_Pointer_Button1 = 0xfee9 - const val XK_Pointer_Button2 = 0xfeea - const val XK_Pointer_Button3 = 0xfeeb - const val XK_Pointer_Button4 = 0xfeec - const val XK_Pointer_Button5 = 0xfeed - const val XK_Pointer_DblClick_Dflt = 0xfeee - const val XK_Pointer_DblClick1 = 0xfeef - const val XK_Pointer_DblClick2 = 0xfef0 - const val XK_Pointer_DblClick3 = 0xfef1 - const val XK_Pointer_DblClick4 = 0xfef2 - const val XK_Pointer_DblClick5 = 0xfef3 - const val XK_Pointer_Drag_Dflt = 0xfef4 - const val XK_Pointer_Drag1 = 0xfef5 - const val XK_Pointer_Drag2 = 0xfef6 - const val XK_Pointer_Drag3 = 0xfef7 - const val XK_Pointer_Drag4 = 0xfef8 - const val XK_Pointer_Drag5 = 0xfefd - - const val XK_Pointer_EnableKeys = 0xfef9 - const val XK_Pointer_Accelerate = 0xfefa - const val XK_Pointer_DfltBtnNext = 0xfefb - const val XK_Pointer_DfltBtnPrev = 0xfefc - - /* Single-Stroke Multiple-Character N-Graph Keysyms For The X Input Method */ - - const val XK_ch = 0xfea0 - const val XK_Ch = 0xfea1 - const val XK_CH = 0xfea2 - const val XK_c_h = 0xfea3 - const val XK_C_h = 0xfea4 - const val XK_C_H = 0xfea5 - - // #endif /* XK_XKB_KEYS */ - - /* - * 3270 Terminal Keys - * Byte 3 = 0xfd - */ - - // #ifdef XK_3270 - const val XK_3270_Duplicate = 0xfd01 - const val XK_3270_FieldMark = 0xfd02 - const val XK_3270_Right2 = 0xfd03 - const val XK_3270_Left2 = 0xfd04 - const val XK_3270_BackTab = 0xfd05 - const val XK_3270_EraseEOF = 0xfd06 - const val XK_3270_EraseInput = 0xfd07 - const val XK_3270_Reset = 0xfd08 - const val XK_3270_Quit = 0xfd09 - const val XK_3270_PA1 = 0xfd0a - const val XK_3270_PA2 = 0xfd0b - const val XK_3270_PA3 = 0xfd0c - const val XK_3270_Test = 0xfd0d - const val XK_3270_Attn = 0xfd0e - const val XK_3270_CursorBlink = 0xfd0f - const val XK_3270_AltCursor = 0xfd10 - const val XK_3270_KeyClick = 0xfd11 - const val XK_3270_Jump = 0xfd12 - const val XK_3270_Ident = 0xfd13 - const val XK_3270_Rule = 0xfd14 - const val XK_3270_Copy = 0xfd15 - const val XK_3270_Play = 0xfd16 - const val XK_3270_Setup = 0xfd17 - const val XK_3270_Record = 0xfd18 - const val XK_3270_ChangeScreen = 0xfd19 - const val XK_3270_DeleteWord = 0xfd1a - const val XK_3270_ExSelect = 0xfd1b - const val XK_3270_CursorSelect = 0xfd1c - const val XK_3270_PrintScreen = 0xfd1d - const val XK_3270_Enter = 0xfd1e - // #endif /* XK_3270 */ - - /* - * Latin 1 - * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) - * Byte 3 = 0 - */ - // #ifdef XK_LATIN1 - const val XK_space = 0x0020 /* U+0020 SPACE */ - const val XK_exclam = 0x0021 /* U+0021 EXCLAMATION MARK */ - const val XK_quotedbl = 0x0022 /* U+0022 QUOTATION MARK */ - const val XK_numbersign = 0x0023 /* U+0023 NUMBER SIGN */ - const val XK_dollar = 0x0024 /* U+0024 DOLLAR SIGN */ - const val XK_percent = 0x0025 /* U+0025 PERCENT SIGN */ - const val XK_ampersand = 0x0026 /* U+0026 AMPERSAND */ - const val XK_apostrophe = 0x0027 /* U+0027 APOSTROPHE */ - const val XK_quoteright = 0x0027 /* deprecated */ - const val XK_parenleft = 0x0028 /* U+0028 LEFT PARENTHESIS */ - const val XK_parenright = 0x0029 /* U+0029 RIGHT PARENTHESIS */ - const val XK_asterisk = 0x002a /* U+002A ASTERISK */ - const val XK_plus = 0x002b /* U+002B PLUS SIGN */ - const val XK_comma = 0x002c /* U+002C COMMA */ - const val XK_minus = 0x002d /* U+002D HYPHEN-MINUS */ - const val XK_period = 0x002e /* U+002E FULL STOP */ - const val XK_slash = 0x002f /* U+002F SOLIDUS */ - const val XK_0 = 0x0030 /* U+0030 DIGIT ZERO */ - const val XK_1 = 0x0031 /* U+0031 DIGIT ONE */ - const val XK_2 = 0x0032 /* U+0032 DIGIT TWO */ - const val XK_3 = 0x0033 /* U+0033 DIGIT THREE */ - const val XK_4 = 0x0034 /* U+0034 DIGIT FOUR */ - const val XK_5 = 0x0035 /* U+0035 DIGIT FIVE */ - const val XK_6 = 0x0036 /* U+0036 DIGIT SIX */ - const val XK_7 = 0x0037 /* U+0037 DIGIT SEVEN */ - const val XK_8 = 0x0038 /* U+0038 DIGIT EIGHT */ - const val XK_9 = 0x0039 /* U+0039 DIGIT NINE */ - const val XK_colon = 0x003a /* U+003A COLON */ - const val XK_semicolon = 0x003b /* U+003B SEMICOLON */ - const val XK_less = 0x003c /* U+003C LESS-THAN SIGN */ - const val XK_equal = 0x003d /* U+003D EQUALS SIGN */ - const val XK_greater = 0x003e /* U+003E GREATER-THAN SIGN */ - const val XK_question = 0x003f /* U+003F QUESTION MARK */ - const val XK_at = 0x0040 /* U+0040 COMMERCIAL AT */ - const val XK_A = 0x0041 /* U+0041 LATIN CAPITAL LETTER A */ - const val XK_B = 0x0042 /* U+0042 LATIN CAPITAL LETTER B */ - const val XK_C = 0x0043 /* U+0043 LATIN CAPITAL LETTER C */ - const val XK_D = 0x0044 /* U+0044 LATIN CAPITAL LETTER D */ - const val XK_E = 0x0045 /* U+0045 LATIN CAPITAL LETTER E */ - const val XK_F = 0x0046 /* U+0046 LATIN CAPITAL LETTER F */ - const val XK_G = 0x0047 /* U+0047 LATIN CAPITAL LETTER G */ - const val XK_H = 0x0048 /* U+0048 LATIN CAPITAL LETTER H */ - const val XK_I = 0x0049 /* U+0049 LATIN CAPITAL LETTER I */ - const val XK_J = 0x004a /* U+004A LATIN CAPITAL LETTER J */ - const val XK_K = 0x004b /* U+004B LATIN CAPITAL LETTER K */ - const val XK_L = 0x004c /* U+004C LATIN CAPITAL LETTER L */ - const val XK_M = 0x004d /* U+004D LATIN CAPITAL LETTER M */ - const val XK_N = 0x004e /* U+004E LATIN CAPITAL LETTER N */ - const val XK_O = 0x004f /* U+004F LATIN CAPITAL LETTER O */ - const val XK_P = 0x0050 /* U+0050 LATIN CAPITAL LETTER P */ - const val XK_Q = 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */ - const val XK_R = 0x0052 /* U+0052 LATIN CAPITAL LETTER R */ - const val XK_S = 0x0053 /* U+0053 LATIN CAPITAL LETTER S */ - const val XK_T = 0x0054 /* U+0054 LATIN CAPITAL LETTER T */ - const val XK_U = 0x0055 /* U+0055 LATIN CAPITAL LETTER U */ - const val XK_V = 0x0056 /* U+0056 LATIN CAPITAL LETTER V */ - const val XK_W = 0x0057 /* U+0057 LATIN CAPITAL LETTER W */ - const val XK_X = 0x0058 /* U+0058 LATIN CAPITAL LETTER X */ - const val XK_Y = 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */ - const val XK_Z = 0x005a /* U+005A LATIN CAPITAL LETTER Z */ - const val XK_bracketleft = 0x005b /* U+005B LEFT SQUARE BRACKET */ - const val XK_backslash = 0x005c /* U+005C REVERSE SOLIDUS */ - const val XK_bracketright = 0x005d /* U+005D RIGHT SQUARE BRACKET */ - const val XK_asciicircum = 0x005e /* U+005E CIRCUMFLEX ACCENT */ - const val XK_underscore = 0x005f /* U+005F LOW LINE */ - const val XK_grave = 0x0060 /* U+0060 GRAVE ACCENT */ - const val XK_quoteleft = 0x0060 /* deprecated */ - const val XK_a = 0x0061 /* U+0061 LATIN SMALL LETTER A */ - const val XK_b = 0x0062 /* U+0062 LATIN SMALL LETTER B */ - const val XK_c = 0x0063 /* U+0063 LATIN SMALL LETTER C */ - const val XK_d = 0x0064 /* U+0064 LATIN SMALL LETTER D */ - const val XK_e = 0x0065 /* U+0065 LATIN SMALL LETTER E */ - const val XK_f = 0x0066 /* U+0066 LATIN SMALL LETTER F */ - const val XK_g = 0x0067 /* U+0067 LATIN SMALL LETTER G */ - const val XK_h = 0x0068 /* U+0068 LATIN SMALL LETTER H */ - const val XK_i = 0x0069 /* U+0069 LATIN SMALL LETTER I */ - const val XK_j = 0x006a /* U+006A LATIN SMALL LETTER J */ - const val XK_k = 0x006b /* U+006B LATIN SMALL LETTER K */ - const val XK_l = 0x006c /* U+006C LATIN SMALL LETTER L */ - const val XK_m = 0x006d /* U+006D LATIN SMALL LETTER M */ - const val XK_n = 0x006e /* U+006E LATIN SMALL LETTER N */ - const val XK_o = 0x006f /* U+006F LATIN SMALL LETTER O */ - const val XK_p = 0x0070 /* U+0070 LATIN SMALL LETTER P */ - const val XK_q = 0x0071 /* U+0071 LATIN SMALL LETTER Q */ - const val XK_r = 0x0072 /* U+0072 LATIN SMALL LETTER R */ - const val XK_s = 0x0073 /* U+0073 LATIN SMALL LETTER S */ - const val XK_t = 0x0074 /* U+0074 LATIN SMALL LETTER T */ - const val XK_u = 0x0075 /* U+0075 LATIN SMALL LETTER U */ - const val XK_v = 0x0076 /* U+0076 LATIN SMALL LETTER V */ - const val XK_w = 0x0077 /* U+0077 LATIN SMALL LETTER W */ - const val XK_x = 0x0078 /* U+0078 LATIN SMALL LETTER X */ - const val XK_y = 0x0079 /* U+0079 LATIN SMALL LETTER Y */ - const val XK_z = 0x007a /* U+007A LATIN SMALL LETTER Z */ - const val XK_braceleft = 0x007b /* U+007B LEFT CURLY BRACKET */ - const val XK_bar = 0x007c /* U+007C VERTICAL LINE */ - const val XK_braceright = 0x007d /* U+007D RIGHT CURLY BRACKET */ - const val XK_asciitilde = 0x007e /* U+007E TILDE */ - - const val XK_nobreakspace = 0x00a0 /* U+00A0 NO-BREAK SPACE */ - const val XK_exclamdown = 0x00a1 /* U+00A1 INVERTED EXCLAMATION MARK */ - const val XK_cent = 0x00a2 /* U+00A2 CENT SIGN */ - const val XK_sterling = 0x00a3 /* U+00A3 POUND SIGN */ - const val XK_currency = 0x00a4 /* U+00A4 CURRENCY SIGN */ - const val XK_yen = 0x00a5 /* U+00A5 YEN SIGN */ - const val XK_brokenbar = 0x00a6 /* U+00A6 BROKEN BAR */ - const val XK_section = 0x00a7 /* U+00A7 SECTION SIGN */ - const val XK_diaeresis = 0x00a8 /* U+00A8 DIAERESIS */ - const val XK_copyright = 0x00a9 /* U+00A9 COPYRIGHT SIGN */ - const val XK_ordfeminine = 0x00aa /* U+00AA FEMININE ORDINAL INDICATOR */ - const val XK_guillemotleft = 0x00ab /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ - const val XK_notsign = 0x00ac /* U+00AC NOT SIGN */ - const val XK_hyphen = 0x00ad /* U+00AD SOFT HYPHEN */ - const val XK_registered = 0x00ae /* U+00AE REGISTERED SIGN */ - const val XK_macron = 0x00af /* U+00AF MACRON */ - const val XK_degree = 0x00b0 /* U+00B0 DEGREE SIGN */ - const val XK_plusminus = 0x00b1 /* U+00B1 PLUS-MINUS SIGN */ - const val XK_twosuperior = 0x00b2 /* U+00B2 SUPERSCRIPT TWO */ - const val XK_threesuperior = 0x00b3 /* U+00B3 SUPERSCRIPT THREE */ - const val XK_acute = 0x00b4 /* U+00B4 ACUTE ACCENT */ - const val XK_mu = 0x00b5 /* U+00B5 MICRO SIGN */ - const val XK_paragraph = 0x00b6 /* U+00B6 PILCROW SIGN */ - const val XK_periodcentered = 0x00b7 /* U+00B7 MIDDLE DOT */ - const val XK_cedilla = 0x00b8 /* U+00B8 CEDILLA */ - const val XK_onesuperior = 0x00b9 /* U+00B9 SUPERSCRIPT ONE */ - const val XK_masculine = 0x00ba /* U+00BA MASCULINE ORDINAL INDICATOR */ - const val XK_guillemotright = 0x00bb /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ - const val XK_onequarter = 0x00bc /* U+00BC VULGAR FRACTION ONE QUARTER */ - const val XK_onehalf = 0x00bd /* U+00BD VULGAR FRACTION ONE HALF */ - const val XK_threequarters = 0x00be /* U+00BE VULGAR FRACTION THREE QUARTERS */ - const val XK_questiondown = 0x00bf /* U+00BF INVERTED QUESTION MARK */ - const val XK_Agrave = 0x00c0 /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ - const val XK_Aacute = 0x00c1 /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ - const val XK_Acircumflex = 0x00c2 /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ - const val XK_Atilde = 0x00c3 /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ - const val XK_Adiaeresis = 0x00c4 /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ - const val XK_Aring = 0x00c5 /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ - const val XK_AE = 0x00c6 /* U+00C6 LATIN CAPITAL LETTER AE */ - const val XK_Ccedilla = 0x00c7 /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ - const val XK_Egrave = 0x00c8 /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ - const val XK_Eacute = 0x00c9 /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ - const val XK_Ecircumflex = 0x00ca /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ - const val XK_Ediaeresis = 0x00cb /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ - const val XK_Igrave = 0x00cc /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ - const val XK_Iacute = 0x00cd /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ - const val XK_Icircumflex = 0x00ce /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ - const val XK_Idiaeresis = 0x00cf /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ - const val XK_ETH = 0x00d0 /* U+00D0 LATIN CAPITAL LETTER ETH */ - const val XK_Eth = 0x00d0 /* deprecated */ - const val XK_Ntilde = 0x00d1 /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ - const val XK_Ograve = 0x00d2 /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ - const val XK_Oacute = 0x00d3 /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ - const val XK_Ocircumflex = 0x00d4 /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ - const val XK_Otilde = 0x00d5 /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ - const val XK_Odiaeresis = 0x00d6 /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ - const val XK_multiply = 0x00d7 /* U+00D7 MULTIPLICATION SIGN */ - const val XK_Oslash = 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ - const val XK_Ooblique = 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ - const val XK_Ugrave = 0x00d9 /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ - const val XK_Uacute = 0x00da /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ - const val XK_Ucircumflex = 0x00db /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ - const val XK_Udiaeresis = 0x00dc /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ - const val XK_Yacute = 0x00dd /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ - const val XK_THORN = 0x00de /* U+00DE LATIN CAPITAL LETTER THORN */ - const val XK_Thorn = 0x00de /* deprecated */ - const val XK_ssharp = 0x00df /* U+00DF LATIN SMALL LETTER SHARP S */ - const val XK_agrave = 0x00e0 /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ - const val XK_aacute = 0x00e1 /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ - const val XK_acircumflex = 0x00e2 /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ - const val XK_atilde = 0x00e3 /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ - const val XK_adiaeresis = 0x00e4 /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ - const val XK_aring = 0x00e5 /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ - const val XK_ae = 0x00e6 /* U+00E6 LATIN SMALL LETTER AE */ - const val XK_ccedilla = 0x00e7 /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ - const val XK_egrave = 0x00e8 /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ - const val XK_eacute = 0x00e9 /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ - const val XK_ecircumflex = 0x00ea /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ - const val XK_ediaeresis = 0x00eb /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ - const val XK_igrave = 0x00ec /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ - const val XK_iacute = 0x00ed /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ - const val XK_icircumflex = 0x00ee /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ - const val XK_idiaeresis = 0x00ef /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ - const val XK_eth = 0x00f0 /* U+00F0 LATIN SMALL LETTER ETH */ - const val XK_ntilde = 0x00f1 /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ - const val XK_ograve = 0x00f2 /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ - const val XK_oacute = 0x00f3 /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ - const val XK_ocircumflex = 0x00f4 /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ - const val XK_otilde = 0x00f5 /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ - const val XK_odiaeresis = 0x00f6 /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ - const val XK_division = 0x00f7 /* U+00F7 DIVISION SIGN */ - const val XK_oslash = 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ - const val XK_ooblique = 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ - const val XK_ugrave = 0x00f9 /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ - const val XK_uacute = 0x00fa /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ - const val XK_ucircumflex = 0x00fb /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ - const val XK_udiaeresis = 0x00fc /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ - const val XK_yacute = 0x00fd /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ - const val XK_thorn = 0x00fe /* U+00FE LATIN SMALL LETTER THORN */ - const val XK_ydiaeresis = 0x00ff /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ - // #endif /* XK_LATIN1 */ - - /* - * Latin 2 - * Byte 3 = 1 - */ - - // #ifdef XK_LATIN2 - const val XK_Aogonek = 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */ - const val XK_breve = 0x01a2 /* U+02D8 BREVE */ - const val XK_Lstroke = 0x01a3 /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */ - const val XK_Lcaron = 0x01a5 /* U+013D LATIN CAPITAL LETTER L WITH CARON */ - const val XK_Sacute = 0x01a6 /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */ - const val XK_Scaron = 0x01a9 /* U+0160 LATIN CAPITAL LETTER S WITH CARON */ - const val XK_Scedilla = 0x01aa /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */ - const val XK_Tcaron = 0x01ab /* U+0164 LATIN CAPITAL LETTER T WITH CARON */ - const val XK_Zacute = 0x01ac /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */ - const val XK_Zcaron = 0x01ae /* U+017D LATIN CAPITAL LETTER Z WITH CARON */ - const val XK_Zabovedot = 0x01af /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */ - const val XK_aogonek = 0x01b1 /* U+0105 LATIN SMALL LETTER A WITH OGONEK */ - const val XK_ogonek = 0x01b2 /* U+02DB OGONEK */ - const val XK_lstroke = 0x01b3 /* U+0142 LATIN SMALL LETTER L WITH STROKE */ - const val XK_lcaron = 0x01b5 /* U+013E LATIN SMALL LETTER L WITH CARON */ - const val XK_sacute = 0x01b6 /* U+015B LATIN SMALL LETTER S WITH ACUTE */ - const val XK_caron = 0x01b7 /* U+02C7 CARON */ - const val XK_scaron = 0x01b9 /* U+0161 LATIN SMALL LETTER S WITH CARON */ - const val XK_scedilla = 0x01ba /* U+015F LATIN SMALL LETTER S WITH CEDILLA */ - const val XK_tcaron = 0x01bb /* U+0165 LATIN SMALL LETTER T WITH CARON */ - const val XK_zacute = 0x01bc /* U+017A LATIN SMALL LETTER Z WITH ACUTE */ - const val XK_doubleacute = 0x01bd /* U+02DD DOUBLE ACUTE ACCENT */ - const val XK_zcaron = 0x01be /* U+017E LATIN SMALL LETTER Z WITH CARON */ - const val XK_zabovedot = 0x01bf /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */ - const val XK_Racute = 0x01c0 /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */ - const val XK_Abreve = 0x01c3 /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */ - const val XK_Lacute = 0x01c5 /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */ - const val XK_Cacute = 0x01c6 /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */ - const val XK_Ccaron = 0x01c8 /* U+010C LATIN CAPITAL LETTER C WITH CARON */ - const val XK_Eogonek = 0x01ca /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */ - const val XK_Ecaron = 0x01cc /* U+011A LATIN CAPITAL LETTER E WITH CARON */ - const val XK_Dcaron = 0x01cf /* U+010E LATIN CAPITAL LETTER D WITH CARON */ - const val XK_Dstroke = 0x01d0 /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */ - const val XK_Nacute = 0x01d1 /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */ - const val XK_Ncaron = 0x01d2 /* U+0147 LATIN CAPITAL LETTER N WITH CARON */ - const val XK_Odoubleacute = 0x01d5 /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ - const val XK_Rcaron = 0x01d8 /* U+0158 LATIN CAPITAL LETTER R WITH CARON */ - const val XK_Uring = 0x01d9 /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */ - const val XK_Udoubleacute = 0x01db /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ - const val XK_Tcedilla = 0x01de /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */ - const val XK_racute = 0x01e0 /* U+0155 LATIN SMALL LETTER R WITH ACUTE */ - const val XK_abreve = 0x01e3 /* U+0103 LATIN SMALL LETTER A WITH BREVE */ - const val XK_lacute = 0x01e5 /* U+013A LATIN SMALL LETTER L WITH ACUTE */ - const val XK_cacute = 0x01e6 /* U+0107 LATIN SMALL LETTER C WITH ACUTE */ - const val XK_ccaron = 0x01e8 /* U+010D LATIN SMALL LETTER C WITH CARON */ - const val XK_eogonek = 0x01ea /* U+0119 LATIN SMALL LETTER E WITH OGONEK */ - const val XK_ecaron = 0x01ec /* U+011B LATIN SMALL LETTER E WITH CARON */ - const val XK_dcaron = 0x01ef /* U+010F LATIN SMALL LETTER D WITH CARON */ - const val XK_dstroke = 0x01f0 /* U+0111 LATIN SMALL LETTER D WITH STROKE */ - const val XK_nacute = 0x01f1 /* U+0144 LATIN SMALL LETTER N WITH ACUTE */ - const val XK_ncaron = 0x01f2 /* U+0148 LATIN SMALL LETTER N WITH CARON */ - const val XK_odoubleacute = 0x01f5 /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */ - const val XK_rcaron = 0x01f8 /* U+0159 LATIN SMALL LETTER R WITH CARON */ - const val XK_uring = 0x01f9 /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */ - const val XK_udoubleacute = 0x01fb /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */ - const val XK_tcedilla = 0x01fe /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */ - const val XK_abovedot = 0x01ff /* U+02D9 DOT ABOVE */ - // #endif /* XK_LATIN2 */ - - /* - * Latin 3 - * Byte 3 = 2 - */ - - // #ifdef XK_LATIN3 - const val XK_Hstroke = 0x02a1 /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */ - const val XK_Hcircumflex = 0x02a6 /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ - const val XK_Iabovedot = 0x02a9 /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */ - const val XK_Gbreve = 0x02ab /* U+011E LATIN CAPITAL LETTER G WITH BREVE */ - const val XK_Jcircumflex = 0x02ac /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ - const val XK_hstroke = 0x02b1 /* U+0127 LATIN SMALL LETTER H WITH STROKE */ - const val XK_hcircumflex = 0x02b6 /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */ - const val XK_idotless = 0x02b9 /* U+0131 LATIN SMALL LETTER DOTLESS I */ - const val XK_gbreve = 0x02bb /* U+011F LATIN SMALL LETTER G WITH BREVE */ - const val XK_jcircumflex = 0x02bc /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */ - const val XK_Cabovedot = 0x02c5 /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */ - const val XK_Ccircumflex = 0x02c6 /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ - const val XK_Gabovedot = 0x02d5 /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */ - const val XK_Gcircumflex = 0x02d8 /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ - const val XK_Ubreve = 0x02dd /* U+016C LATIN CAPITAL LETTER U WITH BREVE */ - const val XK_Scircumflex = 0x02de /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ - const val XK_cabovedot = 0x02e5 /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */ - const val XK_ccircumflex = 0x02e6 /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */ - const val XK_gabovedot = 0x02f5 /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */ - const val XK_gcircumflex = 0x02f8 /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */ - const val XK_ubreve = 0x02fd /* U+016D LATIN SMALL LETTER U WITH BREVE */ - const val XK_scircumflex = 0x02fe /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */ - // #endif /* XK_LATIN3 */ - - - /* - * Latin 4 - * Byte 3 = 3 - */ - - // #ifdef XK_LATIN4 - const val XK_kra = 0x03a2 /* U+0138 LATIN SMALL LETTER KRA */ - const val XK_kappa = 0x03a2 /* deprecated */ - const val XK_Rcedilla = 0x03a3 /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */ - const val XK_Itilde = 0x03a5 /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */ - const val XK_Lcedilla = 0x03a6 /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */ - const val XK_Emacron = 0x03aa /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */ - const val XK_Gcedilla = 0x03ab /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */ - const val XK_Tslash = 0x03ac /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */ - const val XK_rcedilla = 0x03b3 /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */ - const val XK_itilde = 0x03b5 /* U+0129 LATIN SMALL LETTER I WITH TILDE */ - const val XK_lcedilla = 0x03b6 /* U+013C LATIN SMALL LETTER L WITH CEDILLA */ - const val XK_emacron = 0x03ba /* U+0113 LATIN SMALL LETTER E WITH MACRON */ - const val XK_gcedilla = 0x03bb /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */ - const val XK_tslash = 0x03bc /* U+0167 LATIN SMALL LETTER T WITH STROKE */ - const val XK_ENG = 0x03bd /* U+014A LATIN CAPITAL LETTER ENG */ - const val XK_eng = 0x03bf /* U+014B LATIN SMALL LETTER ENG */ - const val XK_Amacron = 0x03c0 /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */ - const val XK_Iogonek = 0x03c7 /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */ - const val XK_Eabovedot = 0x03cc /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */ - const val XK_Imacron = 0x03cf /* U+012A LATIN CAPITAL LETTER I WITH MACRON */ - const val XK_Ncedilla = 0x03d1 /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */ - const val XK_Omacron = 0x03d2 /* U+014C LATIN CAPITAL LETTER O WITH MACRON */ - const val XK_Kcedilla = 0x03d3 /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */ - const val XK_Uogonek = 0x03d9 /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */ - const val XK_Utilde = 0x03dd /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */ - const val XK_Umacron = 0x03de /* U+016A LATIN CAPITAL LETTER U WITH MACRON */ - const val XK_amacron = 0x03e0 /* U+0101 LATIN SMALL LETTER A WITH MACRON */ - const val XK_iogonek = 0x03e7 /* U+012F LATIN SMALL LETTER I WITH OGONEK */ - const val XK_eabovedot = 0x03ec /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */ - const val XK_imacron = 0x03ef /* U+012B LATIN SMALL LETTER I WITH MACRON */ - const val XK_ncedilla = 0x03f1 /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */ - const val XK_omacron = 0x03f2 /* U+014D LATIN SMALL LETTER O WITH MACRON */ - const val XK_kcedilla = 0x03f3 /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */ - const val XK_uogonek = 0x03f9 /* U+0173 LATIN SMALL LETTER U WITH OGONEK */ - const val XK_utilde = 0x03fd /* U+0169 LATIN SMALL LETTER U WITH TILDE */ - const val XK_umacron = 0x03fe /* U+016B LATIN SMALL LETTER U WITH MACRON */ - // #endif /* XK_LATIN4 */ - - /* - * Latin 8 - */ - // #ifdef XK_LATIN8 - const val XK_Wcircumflex = 0x1000174 /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ - const val XK_wcircumflex = 0x1000175 /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */ - const val XK_Ycircumflex = 0x1000176 /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ - const val XK_ycircumflex = 0x1000177 /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */ - const val XK_Babovedot = 0x1001e02 /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */ - const val XK_babovedot = 0x1001e03 /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */ - const val XK_Dabovedot = 0x1001e0a /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */ - const val XK_dabovedot = 0x1001e0b /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */ - const val XK_Fabovedot = 0x1001e1e /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */ - const val XK_fabovedot = 0x1001e1f /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */ - const val XK_Mabovedot = 0x1001e40 /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */ - const val XK_mabovedot = 0x1001e41 /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */ - const val XK_Pabovedot = 0x1001e56 /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */ - const val XK_pabovedot = 0x1001e57 /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */ - const val XK_Sabovedot = 0x1001e60 /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */ - const val XK_sabovedot = 0x1001e61 /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */ - const val XK_Tabovedot = 0x1001e6a /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */ - const val XK_tabovedot = 0x1001e6b /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */ - const val XK_Wgrave = 0x1001e80 /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */ - const val XK_wgrave = 0x1001e81 /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */ - const val XK_Wacute = 0x1001e82 /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */ - const val XK_wacute = 0x1001e83 /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */ - const val XK_Wdiaeresis = 0x1001e84 /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */ - const val XK_wdiaeresis = 0x1001e85 /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */ - const val XK_Ygrave = 0x1001ef2 /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */ - const val XK_ygrave = 0x1001ef3 /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */ - // #endif /* XK_LATIN8 */ - - /* - * Latin 9 - * Byte 3 = 0x13 - */ - - // #ifdef XK_LATIN9 - const val XK_OE = 0x13bc /* U+0152 LATIN CAPITAL LIGATURE OE */ - const val XK_oe = 0x13bd /* U+0153 LATIN SMALL LIGATURE OE */ - const val XK_Ydiaeresis = 0x13be /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */ - // #endif /* XK_LATIN9 */ - - /* - * Katakana - * Byte 3 = 4 - */ - - // #ifdef XK_KATAKANA - const val XK_overline = 0x047e /* U+203E OVERLINE */ - const val XK_kana_fullstop = 0x04a1 /* U+3002 IDEOGRAPHIC FULL STOP */ - const val XK_kana_openingbracket = 0x04a2 /* U+300C LEFT CORNER BRACKET */ - const val XK_kana_closingbracket = 0x04a3 /* U+300D RIGHT CORNER BRACKET */ - const val XK_kana_comma = 0x04a4 /* U+3001 IDEOGRAPHIC COMMA */ - const val XK_kana_conjunctive = 0x04a5 /* U+30FB KATAKANA MIDDLE DOT */ - const val XK_kana_middledot = 0x04a5 /* deprecated */ - const val XK_kana_WO = 0x04a6 /* U+30F2 KATAKANA LETTER WO */ - const val XK_kana_a = 0x04a7 /* U+30A1 KATAKANA LETTER SMALL A */ - const val XK_kana_i = 0x04a8 /* U+30A3 KATAKANA LETTER SMALL I */ - const val XK_kana_u = 0x04a9 /* U+30A5 KATAKANA LETTER SMALL U */ - const val XK_kana_e = 0x04aa /* U+30A7 KATAKANA LETTER SMALL E */ - const val XK_kana_o = 0x04ab /* U+30A9 KATAKANA LETTER SMALL O */ - const val XK_kana_ya = 0x04ac /* U+30E3 KATAKANA LETTER SMALL YA */ - const val XK_kana_yu = 0x04ad /* U+30E5 KATAKANA LETTER SMALL YU */ - const val XK_kana_yo = 0x04ae /* U+30E7 KATAKANA LETTER SMALL YO */ - const val XK_kana_tsu = 0x04af /* U+30C3 KATAKANA LETTER SMALL TU */ - const val XK_kana_tu = 0x04af /* deprecated */ - const val XK_prolongedsound = 0x04b0 /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */ - const val XK_kana_A = 0x04b1 /* U+30A2 KATAKANA LETTER A */ - const val XK_kana_I = 0x04b2 /* U+30A4 KATAKANA LETTER I */ - const val XK_kana_U = 0x04b3 /* U+30A6 KATAKANA LETTER U */ - const val XK_kana_E = 0x04b4 /* U+30A8 KATAKANA LETTER E */ - const val XK_kana_O = 0x04b5 /* U+30AA KATAKANA LETTER O */ - const val XK_kana_KA = 0x04b6 /* U+30AB KATAKANA LETTER KA */ - const val XK_kana_KI = 0x04b7 /* U+30AD KATAKANA LETTER KI */ - const val XK_kana_KU = 0x04b8 /* U+30AF KATAKANA LETTER KU */ - const val XK_kana_KE = 0x04b9 /* U+30B1 KATAKANA LETTER KE */ - const val XK_kana_KO = 0x04ba /* U+30B3 KATAKANA LETTER KO */ - const val XK_kana_SA = 0x04bb /* U+30B5 KATAKANA LETTER SA */ - const val XK_kana_SHI = 0x04bc /* U+30B7 KATAKANA LETTER SI */ - const val XK_kana_SU = 0x04bd /* U+30B9 KATAKANA LETTER SU */ - const val XK_kana_SE = 0x04be /* U+30BB KATAKANA LETTER SE */ - const val XK_kana_SO = 0x04bf /* U+30BD KATAKANA LETTER SO */ - const val XK_kana_TA = 0x04c0 /* U+30BF KATAKANA LETTER TA */ - const val XK_kana_CHI = 0x04c1 /* U+30C1 KATAKANA LETTER TI */ - const val XK_kana_TI = 0x04c1 /* deprecated */ - const val XK_kana_TSU = 0x04c2 /* U+30C4 KATAKANA LETTER TU */ - const val XK_kana_TU = 0x04c2 /* deprecated */ - const val XK_kana_TE = 0x04c3 /* U+30C6 KATAKANA LETTER TE */ - const val XK_kana_TO = 0x04c4 /* U+30C8 KATAKANA LETTER TO */ - const val XK_kana_NA = 0x04c5 /* U+30CA KATAKANA LETTER NA */ - const val XK_kana_NI = 0x04c6 /* U+30CB KATAKANA LETTER NI */ - const val XK_kana_NU = 0x04c7 /* U+30CC KATAKANA LETTER NU */ - const val XK_kana_NE = 0x04c8 /* U+30CD KATAKANA LETTER NE */ - const val XK_kana_NO = 0x04c9 /* U+30CE KATAKANA LETTER NO */ - const val XK_kana_HA = 0x04ca /* U+30CF KATAKANA LETTER HA */ - const val XK_kana_HI = 0x04cb /* U+30D2 KATAKANA LETTER HI */ - const val XK_kana_FU = 0x04cc /* U+30D5 KATAKANA LETTER HU */ - const val XK_kana_HU = 0x04cc /* deprecated */ - const val XK_kana_HE = 0x04cd /* U+30D8 KATAKANA LETTER HE */ - const val XK_kana_HO = 0x04ce /* U+30DB KATAKANA LETTER HO */ - const val XK_kana_MA = 0x04cf /* U+30DE KATAKANA LETTER MA */ - const val XK_kana_MI = 0x04d0 /* U+30DF KATAKANA LETTER MI */ - const val XK_kana_MU = 0x04d1 /* U+30E0 KATAKANA LETTER MU */ - const val XK_kana_ME = 0x04d2 /* U+30E1 KATAKANA LETTER ME */ - const val XK_kana_MO = 0x04d3 /* U+30E2 KATAKANA LETTER MO */ - const val XK_kana_YA = 0x04d4 /* U+30E4 KATAKANA LETTER YA */ - const val XK_kana_YU = 0x04d5 /* U+30E6 KATAKANA LETTER YU */ - const val XK_kana_YO = 0x04d6 /* U+30E8 KATAKANA LETTER YO */ - const val XK_kana_RA = 0x04d7 /* U+30E9 KATAKANA LETTER RA */ - const val XK_kana_RI = 0x04d8 /* U+30EA KATAKANA LETTER RI */ - const val XK_kana_RU = 0x04d9 /* U+30EB KATAKANA LETTER RU */ - const val XK_kana_RE = 0x04da /* U+30EC KATAKANA LETTER RE */ - const val XK_kana_RO = 0x04db /* U+30ED KATAKANA LETTER RO */ - const val XK_kana_WA = 0x04dc /* U+30EF KATAKANA LETTER WA */ - const val XK_kana_N = 0x04dd /* U+30F3 KATAKANA LETTER N */ - const val XK_voicedsound = 0x04de /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */ - const val XK_semivoicedsound = 0x04df /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ - const val XK_kana_switch = 0xff7e /* Alias for mode_switch */ - // #endif /* XK_KATAKANA */ - - /* - * Arabic - * Byte 3 = 5 - */ - - // #ifdef XK_ARABIC - const val XK_Farsi_0 = 0x10006f0 /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */ - const val XK_Farsi_1 = 0x10006f1 /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */ - const val XK_Farsi_2 = 0x10006f2 /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */ - const val XK_Farsi_3 = 0x10006f3 /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */ - const val XK_Farsi_4 = 0x10006f4 /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */ - const val XK_Farsi_5 = 0x10006f5 /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */ - const val XK_Farsi_6 = 0x10006f6 /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */ - const val XK_Farsi_7 = 0x10006f7 /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */ - const val XK_Farsi_8 = 0x10006f8 /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */ - const val XK_Farsi_9 = 0x10006f9 /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */ - const val XK_Arabic_percent = 0x100066a /* U+066A ARABIC PERCENT SIGN */ - const val XK_Arabic_superscript_alef = 0x1000670 /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */ - const val XK_Arabic_tteh = 0x1000679 /* U+0679 ARABIC LETTER TTEH */ - const val XK_Arabic_peh = 0x100067e /* U+067E ARABIC LETTER PEH */ - const val XK_Arabic_tcheh = 0x1000686 /* U+0686 ARABIC LETTER TCHEH */ - const val XK_Arabic_ddal = 0x1000688 /* U+0688 ARABIC LETTER DDAL */ - const val XK_Arabic_rreh = 0x1000691 /* U+0691 ARABIC LETTER RREH */ - const val XK_Arabic_comma = 0x05ac /* U+060C ARABIC COMMA */ - const val XK_Arabic_fullstop = 0x10006d4 /* U+06D4 ARABIC FULL STOP */ - const val XK_Arabic_0 = 0x1000660 /* U+0660 ARABIC-INDIC DIGIT ZERO */ - const val XK_Arabic_1 = 0x1000661 /* U+0661 ARABIC-INDIC DIGIT ONE */ - const val XK_Arabic_2 = 0x1000662 /* U+0662 ARABIC-INDIC DIGIT TWO */ - const val XK_Arabic_3 = 0x1000663 /* U+0663 ARABIC-INDIC DIGIT THREE */ - const val XK_Arabic_4 = 0x1000664 /* U+0664 ARABIC-INDIC DIGIT FOUR */ - const val XK_Arabic_5 = 0x1000665 /* U+0665 ARABIC-INDIC DIGIT FIVE */ - const val XK_Arabic_6 = 0x1000666 /* U+0666 ARABIC-INDIC DIGIT SIX */ - const val XK_Arabic_7 = 0x1000667 /* U+0667 ARABIC-INDIC DIGIT SEVEN */ - const val XK_Arabic_8 = 0x1000668 /* U+0668 ARABIC-INDIC DIGIT EIGHT */ - const val XK_Arabic_9 = 0x1000669 /* U+0669 ARABIC-INDIC DIGIT NINE */ - const val XK_Arabic_semicolon = 0x05bb /* U+061B ARABIC SEMICOLON */ - const val XK_Arabic_question_mark = 0x05bf /* U+061F ARABIC QUESTION MARK */ - const val XK_Arabic_hamza = 0x05c1 /* U+0621 ARABIC LETTER HAMZA */ - const val XK_Arabic_maddaonalef = 0x05c2 /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */ - const val XK_Arabic_hamzaonalef = 0x05c3 /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */ - const val XK_Arabic_hamzaonwaw = 0x05c4 /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */ - const val XK_Arabic_hamzaunderalef = 0x05c5 /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */ - const val XK_Arabic_hamzaonyeh = 0x05c6 /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */ - const val XK_Arabic_alef = 0x05c7 /* U+0627 ARABIC LETTER ALEF */ - const val XK_Arabic_beh = 0x05c8 /* U+0628 ARABIC LETTER BEH */ - const val XK_Arabic_tehmarbuta = 0x05c9 /* U+0629 ARABIC LETTER TEH MARBUTA */ - const val XK_Arabic_teh = 0x05ca /* U+062A ARABIC LETTER TEH */ - const val XK_Arabic_theh = 0x05cb /* U+062B ARABIC LETTER THEH */ - const val XK_Arabic_jeem = 0x05cc /* U+062C ARABIC LETTER JEEM */ - const val XK_Arabic_hah = 0x05cd /* U+062D ARABIC LETTER HAH */ - const val XK_Arabic_khah = 0x05ce /* U+062E ARABIC LETTER KHAH */ - const val XK_Arabic_dal = 0x05cf /* U+062F ARABIC LETTER DAL */ - const val XK_Arabic_thal = 0x05d0 /* U+0630 ARABIC LETTER THAL */ - const val XK_Arabic_ra = 0x05d1 /* U+0631 ARABIC LETTER REH */ - const val XK_Arabic_zain = 0x05d2 /* U+0632 ARABIC LETTER ZAIN */ - const val XK_Arabic_seen = 0x05d3 /* U+0633 ARABIC LETTER SEEN */ - const val XK_Arabic_sheen = 0x05d4 /* U+0634 ARABIC LETTER SHEEN */ - const val XK_Arabic_sad = 0x05d5 /* U+0635 ARABIC LETTER SAD */ - const val XK_Arabic_dad = 0x05d6 /* U+0636 ARABIC LETTER DAD */ - const val XK_Arabic_tah = 0x05d7 /* U+0637 ARABIC LETTER TAH */ - const val XK_Arabic_zah = 0x05d8 /* U+0638 ARABIC LETTER ZAH */ - const val XK_Arabic_ain = 0x05d9 /* U+0639 ARABIC LETTER AIN */ - const val XK_Arabic_ghain = 0x05da /* U+063A ARABIC LETTER GHAIN */ - const val XK_Arabic_tatweel = 0x05e0 /* U+0640 ARABIC TATWEEL */ - const val XK_Arabic_feh = 0x05e1 /* U+0641 ARABIC LETTER FEH */ - const val XK_Arabic_qaf = 0x05e2 /* U+0642 ARABIC LETTER QAF */ - const val XK_Arabic_kaf = 0x05e3 /* U+0643 ARABIC LETTER KAF */ - const val XK_Arabic_lam = 0x05e4 /* U+0644 ARABIC LETTER LAM */ - const val XK_Arabic_meem = 0x05e5 /* U+0645 ARABIC LETTER MEEM */ - const val XK_Arabic_noon = 0x05e6 /* U+0646 ARABIC LETTER NOON */ - const val XK_Arabic_ha = 0x05e7 /* U+0647 ARABIC LETTER HEH */ - const val XK_Arabic_heh = 0x05e7 /* deprecated */ - const val XK_Arabic_waw = 0x05e8 /* U+0648 ARABIC LETTER WAW */ - const val XK_Arabic_alefmaksura = 0x05e9 /* U+0649 ARABIC LETTER ALEF MAKSURA */ - const val XK_Arabic_yeh = 0x05ea /* U+064A ARABIC LETTER YEH */ - const val XK_Arabic_fathatan = 0x05eb /* U+064B ARABIC FATHATAN */ - const val XK_Arabic_dammatan = 0x05ec /* U+064C ARABIC DAMMATAN */ - const val XK_Arabic_kasratan = 0x05ed /* U+064D ARABIC KASRATAN */ - const val XK_Arabic_fatha = 0x05ee /* U+064E ARABIC FATHA */ - const val XK_Arabic_damma = 0x05ef /* U+064F ARABIC DAMMA */ - const val XK_Arabic_kasra = 0x05f0 /* U+0650 ARABIC KASRA */ - const val XK_Arabic_shadda = 0x05f1 /* U+0651 ARABIC SHADDA */ - const val XK_Arabic_sukun = 0x05f2 /* U+0652 ARABIC SUKUN */ - const val XK_Arabic_madda_above = 0x1000653 /* U+0653 ARABIC MADDAH ABOVE */ - const val XK_Arabic_hamza_above = 0x1000654 /* U+0654 ARABIC HAMZA ABOVE */ - const val XK_Arabic_hamza_below = 0x1000655 /* U+0655 ARABIC HAMZA BELOW */ - const val XK_Arabic_jeh = 0x1000698 /* U+0698 ARABIC LETTER JEH */ - const val XK_Arabic_veh = 0x10006a4 /* U+06A4 ARABIC LETTER VEH */ - const val XK_Arabic_keheh = 0x10006a9 /* U+06A9 ARABIC LETTER KEHEH */ - const val XK_Arabic_gaf = 0x10006af /* U+06AF ARABIC LETTER GAF */ - const val XK_Arabic_noon_ghunna = 0x10006ba /* U+06BA ARABIC LETTER NOON GHUNNA */ - const val XK_Arabic_heh_doachashmee = 0x10006be /* U+06BE ARABIC LETTER HEH DOACHASHMEE */ - const val XK_Farsi_yeh = 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ - const val XK_Arabic_farsi_yeh = 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ - const val XK_Arabic_yeh_baree = 0x10006d2 /* U+06D2 ARABIC LETTER YEH BARREE */ - const val XK_Arabic_heh_goal = 0x10006c1 /* U+06C1 ARABIC LETTER HEH GOAL */ - const val XK_Arabic_switch = 0xff7e /* Alias for mode_switch */ - // #endif /* XK_ARABIC */ - - /* - * Cyrillic - * Byte 3 = 6 - */ - // #ifdef XK_CYRILLIC - const val XK_Cyrillic_GHE_bar = 0x1000492 /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */ - const val XK_Cyrillic_ghe_bar = 0x1000493 /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */ - const val XK_Cyrillic_ZHE_descender = 0x1000496 /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */ - const val XK_Cyrillic_zhe_descender = 0x1000497 /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */ - const val XK_Cyrillic_KA_descender = 0x100049a /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */ - const val XK_Cyrillic_ka_descender = 0x100049b /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */ - const val XK_Cyrillic_KA_vertstroke = 0x100049c /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */ - const val XK_Cyrillic_ka_vertstroke = 0x100049d /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */ - const val XK_Cyrillic_EN_descender = 0x10004a2 /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */ - const val XK_Cyrillic_en_descender = 0x10004a3 /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */ - const val XK_Cyrillic_U_straight = 0x10004ae /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */ - const val XK_Cyrillic_u_straight = 0x10004af /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */ - const val XK_Cyrillic_U_straight_bar = 0x10004b0 /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */ - const val XK_Cyrillic_u_straight_bar = 0x10004b1 /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */ - const val XK_Cyrillic_HA_descender = 0x10004b2 /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */ - const val XK_Cyrillic_ha_descender = 0x10004b3 /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */ - const val XK_Cyrillic_CHE_descender = 0x10004b6 /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */ - const val XK_Cyrillic_che_descender = 0x10004b7 /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */ - const val XK_Cyrillic_CHE_vertstroke = 0x10004b8 /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */ - const val XK_Cyrillic_che_vertstroke = 0x10004b9 /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */ - const val XK_Cyrillic_SHHA = 0x10004ba /* U+04BA CYRILLIC CAPITAL LETTER SHHA */ - const val XK_Cyrillic_shha = 0x10004bb /* U+04BB CYRILLIC SMALL LETTER SHHA */ - - const val XK_Cyrillic_SCHWA = 0x10004d8 /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */ - const val XK_Cyrillic_schwa = 0x10004d9 /* U+04D9 CYRILLIC SMALL LETTER SCHWA */ - const val XK_Cyrillic_I_macron = 0x10004e2 /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */ - const val XK_Cyrillic_i_macron = 0x10004e3 /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */ - const val XK_Cyrillic_O_bar = 0x10004e8 /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */ - const val XK_Cyrillic_o_bar = 0x10004e9 /* U+04E9 CYRILLIC SMALL LETTER BARRED O */ - const val XK_Cyrillic_U_macron = 0x10004ee /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */ - const val XK_Cyrillic_u_macron = 0x10004ef /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */ - - const val XK_Serbian_dje = 0x06a1 /* U+0452 CYRILLIC SMALL LETTER DJE */ - const val XK_Macedonia_gje = 0x06a2 /* U+0453 CYRILLIC SMALL LETTER GJE */ - const val XK_Cyrillic_io = 0x06a3 /* U+0451 CYRILLIC SMALL LETTER IO */ - const val XK_Ukrainian_ie = 0x06a4 /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */ - const val XK_Ukranian_je = 0x06a4 /* deprecated */ - const val XK_Macedonia_dse = 0x06a5 /* U+0455 CYRILLIC SMALL LETTER DZE */ - const val XK_Ukrainian_i = 0x06a6 /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ - const val XK_Ukranian_i = 0x06a6 /* deprecated */ - const val XK_Ukrainian_yi = 0x06a7 /* U+0457 CYRILLIC SMALL LETTER YI */ - const val XK_Ukranian_yi = 0x06a7 /* deprecated */ - const val XK_Cyrillic_je = 0x06a8 /* U+0458 CYRILLIC SMALL LETTER JE */ - const val XK_Serbian_je = 0x06a8 /* deprecated */ - const val XK_Cyrillic_lje = 0x06a9 /* U+0459 CYRILLIC SMALL LETTER LJE */ - const val XK_Serbian_lje = 0x06a9 /* deprecated */ - const val XK_Cyrillic_nje = 0x06aa /* U+045A CYRILLIC SMALL LETTER NJE */ - const val XK_Serbian_nje = 0x06aa /* deprecated */ - const val XK_Serbian_tshe = 0x06ab /* U+045B CYRILLIC SMALL LETTER TSHE */ - const val XK_Macedonia_kje = 0x06ac /* U+045C CYRILLIC SMALL LETTER KJE */ - const val XK_Ukrainian_ghe_with_upturn = 0x06ad /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */ - const val XK_Byelorussian_shortu = 0x06ae /* U+045E CYRILLIC SMALL LETTER SHORT U */ - const val XK_Cyrillic_dzhe = 0x06af /* U+045F CYRILLIC SMALL LETTER DZHE */ - const val XK_Serbian_dze = 0x06af /* deprecated */ - const val XK_numerosign = 0x06b0 /* U+2116 NUMERO SIGN */ - const val XK_Serbian_DJE = 0x06b1 /* U+0402 CYRILLIC CAPITAL LETTER DJE */ - const val XK_Macedonia_GJE = 0x06b2 /* U+0403 CYRILLIC CAPITAL LETTER GJE */ - const val XK_Cyrillic_IO = 0x06b3 /* U+0401 CYRILLIC CAPITAL LETTER IO */ - const val XK_Ukrainian_IE = 0x06b4 /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */ - const val XK_Ukranian_JE = 0x06b4 /* deprecated */ - const val XK_Macedonia_DSE = 0x06b5 /* U+0405 CYRILLIC CAPITAL LETTER DZE */ - const val XK_Ukrainian_I = 0x06b6 /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ - const val XK_Ukranian_I = 0x06b6 /* deprecated */ - const val XK_Ukrainian_YI = 0x06b7 /* U+0407 CYRILLIC CAPITAL LETTER YI */ - const val XK_Ukranian_YI = 0x06b7 /* deprecated */ - const val XK_Cyrillic_JE = 0x06b8 /* U+0408 CYRILLIC CAPITAL LETTER JE */ - const val XK_Serbian_JE = 0x06b8 /* deprecated */ - const val XK_Cyrillic_LJE = 0x06b9 /* U+0409 CYRILLIC CAPITAL LETTER LJE */ - const val XK_Serbian_LJE = 0x06b9 /* deprecated */ - const val XK_Cyrillic_NJE = 0x06ba /* U+040A CYRILLIC CAPITAL LETTER NJE */ - const val XK_Serbian_NJE = 0x06ba /* deprecated */ - const val XK_Serbian_TSHE = 0x06bb /* U+040B CYRILLIC CAPITAL LETTER TSHE */ - const val XK_Macedonia_KJE = 0x06bc /* U+040C CYRILLIC CAPITAL LETTER KJE */ - const val XK_Ukrainian_GHE_WITH_UPTURN = 0x06bd /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ - const val XK_Byelorussian_SHORTU = 0x06be /* U+040E CYRILLIC CAPITAL LETTER SHORT U */ - const val XK_Cyrillic_DZHE = 0x06bf /* U+040F CYRILLIC CAPITAL LETTER DZHE */ - const val XK_Serbian_DZE = 0x06bf /* deprecated */ - const val XK_Cyrillic_yu = 0x06c0 /* U+044E CYRILLIC SMALL LETTER YU */ - const val XK_Cyrillic_a = 0x06c1 /* U+0430 CYRILLIC SMALL LETTER A */ - const val XK_Cyrillic_be = 0x06c2 /* U+0431 CYRILLIC SMALL LETTER BE */ - const val XK_Cyrillic_tse = 0x06c3 /* U+0446 CYRILLIC SMALL LETTER TSE */ - const val XK_Cyrillic_de = 0x06c4 /* U+0434 CYRILLIC SMALL LETTER DE */ - const val XK_Cyrillic_ie = 0x06c5 /* U+0435 CYRILLIC SMALL LETTER IE */ - const val XK_Cyrillic_ef = 0x06c6 /* U+0444 CYRILLIC SMALL LETTER EF */ - const val XK_Cyrillic_ghe = 0x06c7 /* U+0433 CYRILLIC SMALL LETTER GHE */ - const val XK_Cyrillic_ha = 0x06c8 /* U+0445 CYRILLIC SMALL LETTER HA */ - const val XK_Cyrillic_i = 0x06c9 /* U+0438 CYRILLIC SMALL LETTER I */ - const val XK_Cyrillic_shorti = 0x06ca /* U+0439 CYRILLIC SMALL LETTER SHORT I */ - const val XK_Cyrillic_ka = 0x06cb /* U+043A CYRILLIC SMALL LETTER KA */ - const val XK_Cyrillic_el = 0x06cc /* U+043B CYRILLIC SMALL LETTER EL */ - const val XK_Cyrillic_em = 0x06cd /* U+043C CYRILLIC SMALL LETTER EM */ - const val XK_Cyrillic_en = 0x06ce /* U+043D CYRILLIC SMALL LETTER EN */ - const val XK_Cyrillic_o = 0x06cf /* U+043E CYRILLIC SMALL LETTER O */ - const val XK_Cyrillic_pe = 0x06d0 /* U+043F CYRILLIC SMALL LETTER PE */ - const val XK_Cyrillic_ya = 0x06d1 /* U+044F CYRILLIC SMALL LETTER YA */ - const val XK_Cyrillic_er = 0x06d2 /* U+0440 CYRILLIC SMALL LETTER ER */ - const val XK_Cyrillic_es = 0x06d3 /* U+0441 CYRILLIC SMALL LETTER ES */ - const val XK_Cyrillic_te = 0x06d4 /* U+0442 CYRILLIC SMALL LETTER TE */ - const val XK_Cyrillic_u = 0x06d5 /* U+0443 CYRILLIC SMALL LETTER U */ - const val XK_Cyrillic_zhe = 0x06d6 /* U+0436 CYRILLIC SMALL LETTER ZHE */ - const val XK_Cyrillic_ve = 0x06d7 /* U+0432 CYRILLIC SMALL LETTER VE */ - const val XK_Cyrillic_softsign = 0x06d8 /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */ - const val XK_Cyrillic_yeru = 0x06d9 /* U+044B CYRILLIC SMALL LETTER YERU */ - const val XK_Cyrillic_ze = 0x06da /* U+0437 CYRILLIC SMALL LETTER ZE */ - const val XK_Cyrillic_sha = 0x06db /* U+0448 CYRILLIC SMALL LETTER SHA */ - const val XK_Cyrillic_e = 0x06dc /* U+044D CYRILLIC SMALL LETTER E */ - const val XK_Cyrillic_shcha = 0x06dd /* U+0449 CYRILLIC SMALL LETTER SHCHA */ - const val XK_Cyrillic_che = 0x06de /* U+0447 CYRILLIC SMALL LETTER CHE */ - const val XK_Cyrillic_hardsign = 0x06df /* U+044A CYRILLIC SMALL LETTER HARD SIGN */ - const val XK_Cyrillic_YU = 0x06e0 /* U+042E CYRILLIC CAPITAL LETTER YU */ - const val XK_Cyrillic_A = 0x06e1 /* U+0410 CYRILLIC CAPITAL LETTER A */ - const val XK_Cyrillic_BE = 0x06e2 /* U+0411 CYRILLIC CAPITAL LETTER BE */ - const val XK_Cyrillic_TSE = 0x06e3 /* U+0426 CYRILLIC CAPITAL LETTER TSE */ - const val XK_Cyrillic_DE = 0x06e4 /* U+0414 CYRILLIC CAPITAL LETTER DE */ - const val XK_Cyrillic_IE = 0x06e5 /* U+0415 CYRILLIC CAPITAL LETTER IE */ - const val XK_Cyrillic_EF = 0x06e6 /* U+0424 CYRILLIC CAPITAL LETTER EF */ - const val XK_Cyrillic_GHE = 0x06e7 /* U+0413 CYRILLIC CAPITAL LETTER GHE */ - const val XK_Cyrillic_HA = 0x06e8 /* U+0425 CYRILLIC CAPITAL LETTER HA */ - const val XK_Cyrillic_I = 0x06e9 /* U+0418 CYRILLIC CAPITAL LETTER I */ - const val XK_Cyrillic_SHORTI = 0x06ea /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */ - const val XK_Cyrillic_KA = 0x06eb /* U+041A CYRILLIC CAPITAL LETTER KA */ - const val XK_Cyrillic_EL = 0x06ec /* U+041B CYRILLIC CAPITAL LETTER EL */ - const val XK_Cyrillic_EM = 0x06ed /* U+041C CYRILLIC CAPITAL LETTER EM */ - const val XK_Cyrillic_EN = 0x06ee /* U+041D CYRILLIC CAPITAL LETTER EN */ - const val XK_Cyrillic_O = 0x06ef /* U+041E CYRILLIC CAPITAL LETTER O */ - const val XK_Cyrillic_PE = 0x06f0 /* U+041F CYRILLIC CAPITAL LETTER PE */ - const val XK_Cyrillic_YA = 0x06f1 /* U+042F CYRILLIC CAPITAL LETTER YA */ - const val XK_Cyrillic_ER = 0x06f2 /* U+0420 CYRILLIC CAPITAL LETTER ER */ - const val XK_Cyrillic_ES = 0x06f3 /* U+0421 CYRILLIC CAPITAL LETTER ES */ - const val XK_Cyrillic_TE = 0x06f4 /* U+0422 CYRILLIC CAPITAL LETTER TE */ - const val XK_Cyrillic_U = 0x06f5 /* U+0423 CYRILLIC CAPITAL LETTER U */ - const val XK_Cyrillic_ZHE = 0x06f6 /* U+0416 CYRILLIC CAPITAL LETTER ZHE */ - const val XK_Cyrillic_VE = 0x06f7 /* U+0412 CYRILLIC CAPITAL LETTER VE */ - const val XK_Cyrillic_SOFTSIGN = 0x06f8 /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */ - const val XK_Cyrillic_YERU = 0x06f9 /* U+042B CYRILLIC CAPITAL LETTER YERU */ - const val XK_Cyrillic_ZE = 0x06fa /* U+0417 CYRILLIC CAPITAL LETTER ZE */ - const val XK_Cyrillic_SHA = 0x06fb /* U+0428 CYRILLIC CAPITAL LETTER SHA */ - const val XK_Cyrillic_E = 0x06fc /* U+042D CYRILLIC CAPITAL LETTER E */ - const val XK_Cyrillic_SHCHA = 0x06fd /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */ - const val XK_Cyrillic_CHE = 0x06fe /* U+0427 CYRILLIC CAPITAL LETTER CHE */ - const val XK_Cyrillic_HARDSIGN = 0x06ff /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */ - // #endif /* XK_CYRILLIC */ - - /* - * Greek - * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7) - * Byte 3 = 7 - */ - - // #ifdef XK_GREEK - const val XK_Greek_ALPHAaccent = 0x07a1 /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */ - const val XK_Greek_EPSILONaccent = 0x07a2 /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */ - const val XK_Greek_ETAaccent = 0x07a3 /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */ - const val XK_Greek_IOTAaccent = 0x07a4 /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */ - const val XK_Greek_IOTAdieresis = 0x07a5 /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ - const val XK_Greek_IOTAdiaeresis = 0x07a5 /* old typo */ - const val XK_Greek_OMICRONaccent = 0x07a7 /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */ - const val XK_Greek_UPSILONaccent = 0x07a8 /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */ - const val XK_Greek_UPSILONdieresis = 0x07a9 /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ - const val XK_Greek_OMEGAaccent = 0x07ab /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */ - const val XK_Greek_accentdieresis = 0x07ae /* U+0385 GREEK DIALYTIKA TONOS */ - const val XK_Greek_horizbar = 0x07af /* U+2015 HORIZONTAL BAR */ - const val XK_Greek_alphaaccent = 0x07b1 /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */ - const val XK_Greek_epsilonaccent = 0x07b2 /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */ - const val XK_Greek_etaaccent = 0x07b3 /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */ - const val XK_Greek_iotaaccent = 0x07b4 /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */ - const val XK_Greek_iotadieresis = 0x07b5 /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */ - const val XK_Greek_iotaaccentdieresis = 0x07b6 /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ - const val XK_Greek_omicronaccent = 0x07b7 /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */ - const val XK_Greek_upsilonaccent = 0x07b8 /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */ - const val XK_Greek_upsilondieresis = 0x07b9 /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ - const val XK_Greek_upsilonaccentdieresis = 0x07ba /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ - const val XK_Greek_omegaaccent = 0x07bb /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */ - const val XK_Greek_ALPHA = 0x07c1 /* U+0391 GREEK CAPITAL LETTER ALPHA */ - const val XK_Greek_BETA = 0x07c2 /* U+0392 GREEK CAPITAL LETTER BETA */ - const val XK_Greek_GAMMA = 0x07c3 /* U+0393 GREEK CAPITAL LETTER GAMMA */ - const val XK_Greek_DELTA = 0x07c4 /* U+0394 GREEK CAPITAL LETTER DELTA */ - const val XK_Greek_EPSILON = 0x07c5 /* U+0395 GREEK CAPITAL LETTER EPSILON */ - const val XK_Greek_ZETA = 0x07c6 /* U+0396 GREEK CAPITAL LETTER ZETA */ - const val XK_Greek_ETA = 0x07c7 /* U+0397 GREEK CAPITAL LETTER ETA */ - const val XK_Greek_THETA = 0x07c8 /* U+0398 GREEK CAPITAL LETTER THETA */ - const val XK_Greek_IOTA = 0x07c9 /* U+0399 GREEK CAPITAL LETTER IOTA */ - const val XK_Greek_KAPPA = 0x07ca /* U+039A GREEK CAPITAL LETTER KAPPA */ - const val XK_Greek_LAMDA = 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ - const val XK_Greek_LAMBDA = 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ - const val XK_Greek_MU = 0x07cc /* U+039C GREEK CAPITAL LETTER MU */ - const val XK_Greek_NU = 0x07cd /* U+039D GREEK CAPITAL LETTER NU */ - const val XK_Greek_XI = 0x07ce /* U+039E GREEK CAPITAL LETTER XI */ - const val XK_Greek_OMICRON = 0x07cf /* U+039F GREEK CAPITAL LETTER OMICRON */ - const val XK_Greek_PI = 0x07d0 /* U+03A0 GREEK CAPITAL LETTER PI */ - const val XK_Greek_RHO = 0x07d1 /* U+03A1 GREEK CAPITAL LETTER RHO */ - const val XK_Greek_SIGMA = 0x07d2 /* U+03A3 GREEK CAPITAL LETTER SIGMA */ - const val XK_Greek_TAU = 0x07d4 /* U+03A4 GREEK CAPITAL LETTER TAU */ - const val XK_Greek_UPSILON = 0x07d5 /* U+03A5 GREEK CAPITAL LETTER UPSILON */ - const val XK_Greek_PHI = 0x07d6 /* U+03A6 GREEK CAPITAL LETTER PHI */ - const val XK_Greek_CHI = 0x07d7 /* U+03A7 GREEK CAPITAL LETTER CHI */ - const val XK_Greek_PSI = 0x07d8 /* U+03A8 GREEK CAPITAL LETTER PSI */ - const val XK_Greek_OMEGA = 0x07d9 /* U+03A9 GREEK CAPITAL LETTER OMEGA */ - const val XK_Greek_alpha = 0x07e1 /* U+03B1 GREEK SMALL LETTER ALPHA */ - const val XK_Greek_beta = 0x07e2 /* U+03B2 GREEK SMALL LETTER BETA */ - const val XK_Greek_gamma = 0x07e3 /* U+03B3 GREEK SMALL LETTER GAMMA */ - const val XK_Greek_delta = 0x07e4 /* U+03B4 GREEK SMALL LETTER DELTA */ - const val XK_Greek_epsilon = 0x07e5 /* U+03B5 GREEK SMALL LETTER EPSILON */ - const val XK_Greek_zeta = 0x07e6 /* U+03B6 GREEK SMALL LETTER ZETA */ - const val XK_Greek_eta = 0x07e7 /* U+03B7 GREEK SMALL LETTER ETA */ - const val XK_Greek_theta = 0x07e8 /* U+03B8 GREEK SMALL LETTER THETA */ - const val XK_Greek_iota = 0x07e9 /* U+03B9 GREEK SMALL LETTER IOTA */ - const val XK_Greek_kappa = 0x07ea /* U+03BA GREEK SMALL LETTER KAPPA */ - const val XK_Greek_lamda = 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ - const val XK_Greek_lambda = 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ - const val XK_Greek_mu = 0x07ec /* U+03BC GREEK SMALL LETTER MU */ - const val XK_Greek_nu = 0x07ed /* U+03BD GREEK SMALL LETTER NU */ - const val XK_Greek_xi = 0x07ee /* U+03BE GREEK SMALL LETTER XI */ - const val XK_Greek_omicron = 0x07ef /* U+03BF GREEK SMALL LETTER OMICRON */ - const val XK_Greek_pi = 0x07f0 /* U+03C0 GREEK SMALL LETTER PI */ - const val XK_Greek_rho = 0x07f1 /* U+03C1 GREEK SMALL LETTER RHO */ - const val XK_Greek_sigma = 0x07f2 /* U+03C3 GREEK SMALL LETTER SIGMA */ - const val XK_Greek_finalsmallsigma = 0x07f3 /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */ - const val XK_Greek_tau = 0x07f4 /* U+03C4 GREEK SMALL LETTER TAU */ - const val XK_Greek_upsilon = 0x07f5 /* U+03C5 GREEK SMALL LETTER UPSILON */ - const val XK_Greek_phi = 0x07f6 /* U+03C6 GREEK SMALL LETTER PHI */ - const val XK_Greek_chi = 0x07f7 /* U+03C7 GREEK SMALL LETTER CHI */ - const val XK_Greek_psi = 0x07f8 /* U+03C8 GREEK SMALL LETTER PSI */ - const val XK_Greek_omega = 0x07f9 /* U+03C9 GREEK SMALL LETTER OMEGA */ - const val XK_Greek_switch = 0xff7e /* Alias for mode_switch */ - // #endif /* XK_GREEK */ - - /* - * Technical - * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html) - * Byte 3 = 8 - */ - - // #ifdef XK_TECHNICAL - const val XK_leftradical = 0x08a1 /* U+23B7 RADICAL SYMBOL BOTTOM */ - const val XK_topleftradical = 0x08a2 /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/ - const val XK_horizconnector = 0x08a3 /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/ - const val XK_topintegral = 0x08a4 /* U+2320 TOP HALF INTEGRAL */ - const val XK_botintegral = 0x08a5 /* U+2321 BOTTOM HALF INTEGRAL */ - const val XK_vertconnector = 0x08a6 /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/ - const val XK_topleftsqbracket = 0x08a7 /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */ - const val XK_botleftsqbracket = 0x08a8 /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */ - const val XK_toprightsqbracket = 0x08a9 /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */ - const val XK_botrightsqbracket = 0x08aa /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */ - const val XK_topleftparens = 0x08ab /* U+239B LEFT PARENTHESIS UPPER HOOK */ - const val XK_botleftparens = 0x08ac /* U+239D LEFT PARENTHESIS LOWER HOOK */ - const val XK_toprightparens = 0x08ad /* U+239E RIGHT PARENTHESIS UPPER HOOK */ - const val XK_botrightparens = 0x08ae /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */ - const val XK_leftmiddlecurlybrace = 0x08af /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */ - const val XK_rightmiddlecurlybrace = 0x08b0 /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */ - const val XK_topleftsummation = 0x08b1 - const val XK_botleftsummation = 0x08b2 - const val XK_topvertsummationconnector = 0x08b3 - const val XK_botvertsummationconnector = 0x08b4 - const val XK_toprightsummation = 0x08b5 - const val XK_botrightsummation = 0x08b6 - const val XK_rightmiddlesummation = 0x08b7 - const val XK_lessthanequal = 0x08bc /* U+2264 LESS-THAN OR EQUAL TO */ - const val XK_notequal = 0x08bd /* U+2260 NOT EQUAL TO */ - const val XK_greaterthanequal = 0x08be /* U+2265 GREATER-THAN OR EQUAL TO */ - const val XK_integral = 0x08bf /* U+222B INTEGRAL */ - const val XK_therefore = 0x08c0 /* U+2234 THEREFORE */ - const val XK_variation = 0x08c1 /* U+221D PROPORTIONAL TO */ - const val XK_infinity = 0x08c2 /* U+221E INFINITY */ - const val XK_nabla = 0x08c5 /* U+2207 NABLA */ - const val XK_approximate = 0x08c8 /* U+223C TILDE OPERATOR */ - const val XK_similarequal = 0x08c9 /* U+2243 ASYMPTOTICALLY EQUAL TO */ - const val XK_ifonlyif = 0x08cd /* U+21D4 LEFT RIGHT DOUBLE ARROW */ - const val XK_implies = 0x08ce /* U+21D2 RIGHTWARDS DOUBLE ARROW */ - const val XK_identical = 0x08cf /* U+2261 IDENTICAL TO */ - const val XK_radical = 0x08d6 /* U+221A SQUARE ROOT */ - const val XK_includedin = 0x08da /* U+2282 SUBSET OF */ - const val XK_includes = 0x08db /* U+2283 SUPERSET OF */ - const val XK_intersection = 0x08dc /* U+2229 INTERSECTION */ - const val XK_union = 0x08dd /* U+222A UNION */ - const val XK_logicaland = 0x08de /* U+2227 LOGICAL AND */ - const val XK_logicalor = 0x08df /* U+2228 LOGICAL OR */ - const val XK_partialderivative = 0x08ef /* U+2202 PARTIAL DIFFERENTIAL */ - const val XK_function = 0x08f6 /* U+0192 LATIN SMALL LETTER F WITH HOOK */ - const val XK_leftarrow = 0x08fb /* U+2190 LEFTWARDS ARROW */ - const val XK_uparrow = 0x08fc /* U+2191 UPWARDS ARROW */ - const val XK_rightarrow = 0x08fd /* U+2192 RIGHTWARDS ARROW */ - const val XK_downarrow = 0x08fe /* U+2193 DOWNWARDS ARROW */ - // #endif /* XK_TECHNICAL */ - - /* - * Special - * (from the DEC VT100 Special Graphics Character Set) - * Byte 3 = 9 - */ - - // #ifdef XK_SPECIAL - const val XK_blank = 0x09df - const val XK_soliddiamond = 0x09e0 /* U+25C6 BLACK DIAMOND */ - const val XK_checkerboard = 0x09e1 /* U+2592 MEDIUM SHADE */ - const val XK_ht = 0x09e2 /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */ - const val XK_ff = 0x09e3 /* U+240C SYMBOL FOR FORM FEED */ - const val XK_cr = 0x09e4 /* U+240D SYMBOL FOR CARRIAGE RETURN */ - const val XK_lf = 0x09e5 /* U+240A SYMBOL FOR LINE FEED */ - const val XK_nl = 0x09e8 /* U+2424 SYMBOL FOR NEWLINE */ - const val XK_vt = 0x09e9 /* U+240B SYMBOL FOR VERTICAL TABULATION */ - const val XK_lowrightcorner = 0x09ea /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */ - const val XK_uprightcorner = 0x09eb /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */ - const val XK_upleftcorner = 0x09ec /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */ - const val XK_lowleftcorner = 0x09ed /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */ - const val XK_crossinglines = 0x09ee /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ - const val XK_horizlinescan1 = 0x09ef /* U+23BA HORIZONTAL SCAN LINE-1 */ - const val XK_horizlinescan3 = 0x09f0 /* U+23BB HORIZONTAL SCAN LINE-3 */ - const val XK_horizlinescan5 = 0x09f1 /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */ - const val XK_horizlinescan7 = 0x09f2 /* U+23BC HORIZONTAL SCAN LINE-7 */ - const val XK_horizlinescan9 = 0x09f3 /* U+23BD HORIZONTAL SCAN LINE-9 */ - const val XK_leftt = 0x09f4 /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ - const val XK_rightt = 0x09f5 /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */ - const val XK_bott = 0x09f6 /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */ - const val XK_topt = 0x09f7 /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ - const val XK_vertbar = 0x09f8 /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ - // #endif /* XK_SPECIAL */ - - /* - * Publishing - * (these are probably from a long forgotten DEC Publishing - * font that once shipped with DECwrite) - * Byte 3 = 0x0a - */ - - // #ifdef XK_PUBLISHING - const val XK_emspace = 0x0aa1 /* U+2003 EM SPACE */ - const val XK_enspace = 0x0aa2 /* U+2002 EN SPACE */ - const val XK_em3space = 0x0aa3 /* U+2004 THREE-PER-EM SPACE */ - const val XK_em4space = 0x0aa4 /* U+2005 FOUR-PER-EM SPACE */ - const val XK_digitspace = 0x0aa5 /* U+2007 FIGURE SPACE */ - const val XK_punctspace = 0x0aa6 /* U+2008 PUNCTUATION SPACE */ - const val XK_thinspace = 0x0aa7 /* U+2009 THIN SPACE */ - const val XK_hairspace = 0x0aa8 /* U+200A HAIR SPACE */ - const val XK_emdash = 0x0aa9 /* U+2014 EM DASH */ - const val XK_endash = 0x0aaa /* U+2013 EN DASH */ - const val XK_signifblank = 0x0aac /*(U+2423 OPEN BOX)*/ - const val XK_ellipsis = 0x0aae /* U+2026 HORIZONTAL ELLIPSIS */ - const val XK_doubbaselinedot = 0x0aaf /* U+2025 TWO DOT LEADER */ - const val XK_onethird = 0x0ab0 /* U+2153 VULGAR FRACTION ONE THIRD */ - const val XK_twothirds = 0x0ab1 /* U+2154 VULGAR FRACTION TWO THIRDS */ - const val XK_onefifth = 0x0ab2 /* U+2155 VULGAR FRACTION ONE FIFTH */ - const val XK_twofifths = 0x0ab3 /* U+2156 VULGAR FRACTION TWO FIFTHS */ - const val XK_threefifths = 0x0ab4 /* U+2157 VULGAR FRACTION THREE FIFTHS */ - const val XK_fourfifths = 0x0ab5 /* U+2158 VULGAR FRACTION FOUR FIFTHS */ - const val XK_onesixth = 0x0ab6 /* U+2159 VULGAR FRACTION ONE SIXTH */ - const val XK_fivesixths = 0x0ab7 /* U+215A VULGAR FRACTION FIVE SIXTHS */ - const val XK_careof = 0x0ab8 /* U+2105 CARE OF */ - const val XK_figdash = 0x0abb /* U+2012 FIGURE DASH */ - const val XK_leftanglebracket = 0x0abc /*(U+2329 LEFT-POINTING ANGLE BRACKET)*/ - const val XK_decimalpoint = 0x0abd /*(U+002E FULL STOP)*/ - const val XK_rightanglebracket = 0x0abe /*(U+232A RIGHT-POINTING ANGLE BRACKET)*/ - const val XK_marker = 0x0abf - const val XK_oneeighth = 0x0ac3 /* U+215B VULGAR FRACTION ONE EIGHTH */ - const val XK_threeeighths = 0x0ac4 /* U+215C VULGAR FRACTION THREE EIGHTHS */ - const val XK_fiveeighths = 0x0ac5 /* U+215D VULGAR FRACTION FIVE EIGHTHS */ - const val XK_seveneighths = 0x0ac6 /* U+215E VULGAR FRACTION SEVEN EIGHTHS */ - const val XK_trademark = 0x0ac9 /* U+2122 TRADE MARK SIGN */ - const val XK_signaturemark = 0x0aca /*(U+2613 SALTIRE)*/ - const val XK_trademarkincircle = 0x0acb - const val XK_leftopentriangle = 0x0acc /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/ - const val XK_rightopentriangle = 0x0acd /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/ - const val XK_emopencircle = 0x0ace /*(U+25CB WHITE CIRCLE)*/ - const val XK_emopenrectangle = 0x0acf /*(U+25AF WHITE VERTICAL RECTANGLE)*/ - const val XK_leftsinglequotemark = 0x0ad0 /* U+2018 LEFT SINGLE QUOTATION MARK */ - const val XK_rightsinglequotemark = 0x0ad1 /* U+2019 RIGHT SINGLE QUOTATION MARK */ - const val XK_leftdoublequotemark = 0x0ad2 /* U+201C LEFT DOUBLE QUOTATION MARK */ - const val XK_rightdoublequotemark = 0x0ad3 /* U+201D RIGHT DOUBLE QUOTATION MARK */ - const val XK_prescription = 0x0ad4 /* U+211E PRESCRIPTION TAKE */ - const val XK_permille = 0x0ad5 /* U+2030 PER MILLE SIGN */ - const val XK_minutes = 0x0ad6 /* U+2032 PRIME */ - const val XK_seconds = 0x0ad7 /* U+2033 DOUBLE PRIME */ - const val XK_latincross = 0x0ad9 /* U+271D LATIN CROSS */ - const val XK_hexagram = 0x0ada - const val XK_filledrectbullet = 0x0adb /*(U+25AC BLACK RECTANGLE)*/ - const val XK_filledlefttribullet = 0x0adc /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/ - const val XK_filledrighttribullet = 0x0add /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/ - const val XK_emfilledcircle = 0x0ade /*(U+25CF BLACK CIRCLE)*/ - const val XK_emfilledrect = 0x0adf /*(U+25AE BLACK VERTICAL RECTANGLE)*/ - const val XK_enopencircbullet = 0x0ae0 /*(U+25E6 WHITE BULLET)*/ - const val XK_enopensquarebullet = 0x0ae1 /*(U+25AB WHITE SMALL SQUARE)*/ - const val XK_openrectbullet = 0x0ae2 /*(U+25AD WHITE RECTANGLE)*/ - const val XK_opentribulletup = 0x0ae3 /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/ - const val XK_opentribulletdown = 0x0ae4 /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/ - const val XK_openstar = 0x0ae5 /*(U+2606 WHITE STAR)*/ - const val XK_enfilledcircbullet = 0x0ae6 /*(U+2022 BULLET)*/ - const val XK_enfilledsqbullet = 0x0ae7 /*(U+25AA BLACK SMALL SQUARE)*/ - const val XK_filledtribulletup = 0x0ae8 /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/ - const val XK_filledtribulletdown = 0x0ae9 /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/ - const val XK_leftpointer = 0x0aea /*(U+261C WHITE LEFT POINTING INDEX)*/ - const val XK_rightpointer = 0x0aeb /*(U+261E WHITE RIGHT POINTING INDEX)*/ - const val XK_club = 0x0aec /* U+2663 BLACK CLUB SUIT */ - const val XK_diamond = 0x0aed /* U+2666 BLACK DIAMOND SUIT */ - const val XK_heart = 0x0aee /* U+2665 BLACK HEART SUIT */ - const val XK_maltesecross = 0x0af0 /* U+2720 MALTESE CROSS */ - const val XK_dagger = 0x0af1 /* U+2020 DAGGER */ - const val XK_doubledagger = 0x0af2 /* U+2021 DOUBLE DAGGER */ - const val XK_checkmark = 0x0af3 /* U+2713 CHECK MARK */ - const val XK_ballotcross = 0x0af4 /* U+2717 BALLOT X */ - const val XK_musicalsharp = 0x0af5 /* U+266F MUSIC SHARP SIGN */ - const val XK_musicalflat = 0x0af6 /* U+266D MUSIC FLAT SIGN */ - const val XK_malesymbol = 0x0af7 /* U+2642 MALE SIGN */ - const val XK_femalesymbol = 0x0af8 /* U+2640 FEMALE SIGN */ - const val XK_telephone = 0x0af9 /* U+260E BLACK TELEPHONE */ - const val XK_telephonerecorder = 0x0afa /* U+2315 TELEPHONE RECORDER */ - const val XK_phonographcopyright = 0x0afb /* U+2117 SOUND RECORDING COPYRIGHT */ - const val XK_caret = 0x0afc /* U+2038 CARET */ - const val XK_singlelowquotemark = 0x0afd /* U+201A SINGLE LOW-9 QUOTATION MARK */ - const val XK_doublelowquotemark = 0x0afe /* U+201E DOUBLE LOW-9 QUOTATION MARK */ - const val XK_cursor = 0x0aff - // #endif /* XK_PUBLISHING */ - - /* - * APL - * Byte 3 = 0x0b - */ - - // #ifdef XK_APL - const val XK_leftcaret = 0x0ba3 /*(U+003C LESS-THAN SIGN)*/ - const val XK_rightcaret = 0x0ba6 /*(U+003E GREATER-THAN SIGN)*/ - const val XK_downcaret = 0x0ba8 /*(U+2228 LOGICAL OR)*/ - const val XK_upcaret = 0x0ba9 /*(U+2227 LOGICAL AND)*/ - const val XK_overbar = 0x0bc0 /*(U+00AF MACRON)*/ - const val XK_downtack = 0x0bc2 /* U+22A4 DOWN TACK */ - const val XK_upshoe = 0x0bc3 /*(U+2229 INTERSECTION)*/ - const val XK_downstile = 0x0bc4 /* U+230A LEFT FLOOR */ - const val XK_underbar = 0x0bc6 /*(U+005F LOW LINE)*/ - const val XK_jot = 0x0bca /* U+2218 RING OPERATOR */ - const val XK_quad = 0x0bcc /* U+2395 APL FUNCTIONAL SYMBOL QUAD */ - const val XK_uptack = 0x0bce /* U+22A5 UP TACK */ - const val XK_circle = 0x0bcf /* U+25CB WHITE CIRCLE */ - const val XK_upstile = 0x0bd3 /* U+2308 LEFT CEILING */ - const val XK_downshoe = 0x0bd6 /*(U+222A UNION)*/ - const val XK_rightshoe = 0x0bd8 /*(U+2283 SUPERSET OF)*/ - const val XK_leftshoe = 0x0bda /*(U+2282 SUBSET OF)*/ - const val XK_lefttack = 0x0bdc /* U+22A3 LEFT TACK */ - const val XK_righttack = 0x0bfc /* U+22A2 RIGHT TACK */ - // #endif /* XK_APL */ - - /* - * Hebrew - * Byte 3 = 0x0c - */ - - // #ifdef XK_HEBREW - const val XK_hebrew_doublelowline = 0x0cdf /* U+2017 DOUBLE LOW LINE */ - const val XK_hebrew_aleph = 0x0ce0 /* U+05D0 HEBREW LETTER ALEF */ - const val XK_hebrew_bet = 0x0ce1 /* U+05D1 HEBREW LETTER BET */ - const val XK_hebrew_beth = 0x0ce1 /* deprecated */ - const val XK_hebrew_gimel = 0x0ce2 /* U+05D2 HEBREW LETTER GIMEL */ - const val XK_hebrew_gimmel = 0x0ce2 /* deprecated */ - const val XK_hebrew_dalet = 0x0ce3 /* U+05D3 HEBREW LETTER DALET */ - const val XK_hebrew_daleth = 0x0ce3 /* deprecated */ - const val XK_hebrew_he = 0x0ce4 /* U+05D4 HEBREW LETTER HE */ - const val XK_hebrew_waw = 0x0ce5 /* U+05D5 HEBREW LETTER VAV */ - const val XK_hebrew_zain = 0x0ce6 /* U+05D6 HEBREW LETTER ZAYIN */ - const val XK_hebrew_zayin = 0x0ce6 /* deprecated */ - const val XK_hebrew_chet = 0x0ce7 /* U+05D7 HEBREW LETTER HET */ - const val XK_hebrew_het = 0x0ce7 /* deprecated */ - const val XK_hebrew_tet = 0x0ce8 /* U+05D8 HEBREW LETTER TET */ - const val XK_hebrew_teth = 0x0ce8 /* deprecated */ - const val XK_hebrew_yod = 0x0ce9 /* U+05D9 HEBREW LETTER YOD */ - const val XK_hebrew_finalkaph = 0x0cea /* U+05DA HEBREW LETTER FINAL KAF */ - const val XK_hebrew_kaph = 0x0ceb /* U+05DB HEBREW LETTER KAF */ - const val XK_hebrew_lamed = 0x0cec /* U+05DC HEBREW LETTER LAMED */ - const val XK_hebrew_finalmem = 0x0ced /* U+05DD HEBREW LETTER FINAL MEM */ - const val XK_hebrew_mem = 0x0cee /* U+05DE HEBREW LETTER MEM */ - const val XK_hebrew_finalnun = 0x0cef /* U+05DF HEBREW LETTER FINAL NUN */ - const val XK_hebrew_nun = 0x0cf0 /* U+05E0 HEBREW LETTER NUN */ - const val XK_hebrew_samech = 0x0cf1 /* U+05E1 HEBREW LETTER SAMEKH */ - const val XK_hebrew_samekh = 0x0cf1 /* deprecated */ - const val XK_hebrew_ayin = 0x0cf2 /* U+05E2 HEBREW LETTER AYIN */ - const val XK_hebrew_finalpe = 0x0cf3 /* U+05E3 HEBREW LETTER FINAL PE */ - const val XK_hebrew_pe = 0x0cf4 /* U+05E4 HEBREW LETTER PE */ - const val XK_hebrew_finalzade = 0x0cf5 /* U+05E5 HEBREW LETTER FINAL TSADI */ - const val XK_hebrew_finalzadi = 0x0cf5 /* deprecated */ - const val XK_hebrew_zade = 0x0cf6 /* U+05E6 HEBREW LETTER TSADI */ - const val XK_hebrew_zadi = 0x0cf6 /* deprecated */ - const val XK_hebrew_qoph = 0x0cf7 /* U+05E7 HEBREW LETTER QOF */ - const val XK_hebrew_kuf = 0x0cf7 /* deprecated */ - const val XK_hebrew_resh = 0x0cf8 /* U+05E8 HEBREW LETTER RESH */ - const val XK_hebrew_shin = 0x0cf9 /* U+05E9 HEBREW LETTER SHIN */ - const val XK_hebrew_taw = 0x0cfa /* U+05EA HEBREW LETTER TAV */ - const val XK_hebrew_taf = 0x0cfa /* deprecated */ - const val XK_Hebrew_switch = 0xff7e /* Alias for mode_switch */ - // #endif /* XK_HEBREW */ - - /* - * Thai - * Byte 3 = 0x0d - */ - - // #ifdef XK_THAI - const val XK_Thai_kokai = 0x0da1 /* U+0E01 THAI CHARACTER KO KAI */ - const val XK_Thai_khokhai = 0x0da2 /* U+0E02 THAI CHARACTER KHO KHAI */ - const val XK_Thai_khokhuat = 0x0da3 /* U+0E03 THAI CHARACTER KHO KHUAT */ - const val XK_Thai_khokhwai = 0x0da4 /* U+0E04 THAI CHARACTER KHO KHWAI */ - const val XK_Thai_khokhon = 0x0da5 /* U+0E05 THAI CHARACTER KHO KHON */ - const val XK_Thai_khorakhang = 0x0da6 /* U+0E06 THAI CHARACTER KHO RAKHANG */ - const val XK_Thai_ngongu = 0x0da7 /* U+0E07 THAI CHARACTER NGO NGU */ - const val XK_Thai_chochan = 0x0da8 /* U+0E08 THAI CHARACTER CHO CHAN */ - const val XK_Thai_choching = 0x0da9 /* U+0E09 THAI CHARACTER CHO CHING */ - const val XK_Thai_chochang = 0x0daa /* U+0E0A THAI CHARACTER CHO CHANG */ - const val XK_Thai_soso = 0x0dab /* U+0E0B THAI CHARACTER SO SO */ - const val XK_Thai_chochoe = 0x0dac /* U+0E0C THAI CHARACTER CHO CHOE */ - const val XK_Thai_yoying = 0x0dad /* U+0E0D THAI CHARACTER YO YING */ - const val XK_Thai_dochada = 0x0dae /* U+0E0E THAI CHARACTER DO CHADA */ - const val XK_Thai_topatak = 0x0daf /* U+0E0F THAI CHARACTER TO PATAK */ - const val XK_Thai_thothan = 0x0db0 /* U+0E10 THAI CHARACTER THO THAN */ - const val XK_Thai_thonangmontho = 0x0db1 /* U+0E11 THAI CHARACTER THO NANGMONTHO */ - const val XK_Thai_thophuthao = 0x0db2 /* U+0E12 THAI CHARACTER THO PHUTHAO */ - const val XK_Thai_nonen = 0x0db3 /* U+0E13 THAI CHARACTER NO NEN */ - const val XK_Thai_dodek = 0x0db4 /* U+0E14 THAI CHARACTER DO DEK */ - const val XK_Thai_totao = 0x0db5 /* U+0E15 THAI CHARACTER TO TAO */ - const val XK_Thai_thothung = 0x0db6 /* U+0E16 THAI CHARACTER THO THUNG */ - const val XK_Thai_thothahan = 0x0db7 /* U+0E17 THAI CHARACTER THO THAHAN */ - const val XK_Thai_thothong = 0x0db8 /* U+0E18 THAI CHARACTER THO THONG */ - const val XK_Thai_nonu = 0x0db9 /* U+0E19 THAI CHARACTER NO NU */ - const val XK_Thai_bobaimai = 0x0dba /* U+0E1A THAI CHARACTER BO BAIMAI */ - const val XK_Thai_popla = 0x0dbb /* U+0E1B THAI CHARACTER PO PLA */ - const val XK_Thai_phophung = 0x0dbc /* U+0E1C THAI CHARACTER PHO PHUNG */ - const val XK_Thai_fofa = 0x0dbd /* U+0E1D THAI CHARACTER FO FA */ - const val XK_Thai_phophan = 0x0dbe /* U+0E1E THAI CHARACTER PHO PHAN */ - const val XK_Thai_fofan = 0x0dbf /* U+0E1F THAI CHARACTER FO FAN */ - const val XK_Thai_phosamphao = 0x0dc0 /* U+0E20 THAI CHARACTER PHO SAMPHAO */ - const val XK_Thai_moma = 0x0dc1 /* U+0E21 THAI CHARACTER MO MA */ - const val XK_Thai_yoyak = 0x0dc2 /* U+0E22 THAI CHARACTER YO YAK */ - const val XK_Thai_rorua = 0x0dc3 /* U+0E23 THAI CHARACTER RO RUA */ - const val XK_Thai_ru = 0x0dc4 /* U+0E24 THAI CHARACTER RU */ - const val XK_Thai_loling = 0x0dc5 /* U+0E25 THAI CHARACTER LO LING */ - const val XK_Thai_lu = 0x0dc6 /* U+0E26 THAI CHARACTER LU */ - const val XK_Thai_wowaen = 0x0dc7 /* U+0E27 THAI CHARACTER WO WAEN */ - const val XK_Thai_sosala = 0x0dc8 /* U+0E28 THAI CHARACTER SO SALA */ - const val XK_Thai_sorusi = 0x0dc9 /* U+0E29 THAI CHARACTER SO RUSI */ - const val XK_Thai_sosua = 0x0dca /* U+0E2A THAI CHARACTER SO SUA */ - const val XK_Thai_hohip = 0x0dcb /* U+0E2B THAI CHARACTER HO HIP */ - const val XK_Thai_lochula = 0x0dcc /* U+0E2C THAI CHARACTER LO CHULA */ - const val XK_Thai_oang = 0x0dcd /* U+0E2D THAI CHARACTER O ANG */ - const val XK_Thai_honokhuk = 0x0dce /* U+0E2E THAI CHARACTER HO NOKHUK */ - const val XK_Thai_paiyannoi = 0x0dcf /* U+0E2F THAI CHARACTER PAIYANNOI */ - const val XK_Thai_saraa = 0x0dd0 /* U+0E30 THAI CHARACTER SARA A */ - const val XK_Thai_maihanakat = 0x0dd1 /* U+0E31 THAI CHARACTER MAI HAN-AKAT */ - const val XK_Thai_saraaa = 0x0dd2 /* U+0E32 THAI CHARACTER SARA AA */ - const val XK_Thai_saraam = 0x0dd3 /* U+0E33 THAI CHARACTER SARA AM */ - const val XK_Thai_sarai = 0x0dd4 /* U+0E34 THAI CHARACTER SARA I */ - const val XK_Thai_saraii = 0x0dd5 /* U+0E35 THAI CHARACTER SARA II */ - const val XK_Thai_saraue = 0x0dd6 /* U+0E36 THAI CHARACTER SARA UE */ - const val XK_Thai_sarauee = 0x0dd7 /* U+0E37 THAI CHARACTER SARA UEE */ - const val XK_Thai_sarau = 0x0dd8 /* U+0E38 THAI CHARACTER SARA U */ - const val XK_Thai_sarauu = 0x0dd9 /* U+0E39 THAI CHARACTER SARA UU */ - const val XK_Thai_phinthu = 0x0dda /* U+0E3A THAI CHARACTER PHINTHU */ - const val XK_Thai_maihanakat_maitho = 0x0dde - const val XK_Thai_baht = 0x0ddf /* U+0E3F THAI CURRENCY SYMBOL BAHT */ - const val XK_Thai_sarae = 0x0de0 /* U+0E40 THAI CHARACTER SARA E */ - const val XK_Thai_saraae = 0x0de1 /* U+0E41 THAI CHARACTER SARA AE */ - const val XK_Thai_sarao = 0x0de2 /* U+0E42 THAI CHARACTER SARA O */ - const val XK_Thai_saraaimaimuan = 0x0de3 /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */ - const val XK_Thai_saraaimaimalai = 0x0de4 /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */ - const val XK_Thai_lakkhangyao = 0x0de5 /* U+0E45 THAI CHARACTER LAKKHANGYAO */ - const val XK_Thai_maiyamok = 0x0de6 /* U+0E46 THAI CHARACTER MAIYAMOK */ - const val XK_Thai_maitaikhu = 0x0de7 /* U+0E47 THAI CHARACTER MAITAIKHU */ - const val XK_Thai_maiek = 0x0de8 /* U+0E48 THAI CHARACTER MAI EK */ - const val XK_Thai_maitho = 0x0de9 /* U+0E49 THAI CHARACTER MAI THO */ - const val XK_Thai_maitri = 0x0dea /* U+0E4A THAI CHARACTER MAI TRI */ - const val XK_Thai_maichattawa = 0x0deb /* U+0E4B THAI CHARACTER MAI CHATTAWA */ - const val XK_Thai_thanthakhat = 0x0dec /* U+0E4C THAI CHARACTER THANTHAKHAT */ - const val XK_Thai_nikhahit = 0x0ded /* U+0E4D THAI CHARACTER NIKHAHIT */ - const val XK_Thai_leksun = 0x0df0 /* U+0E50 THAI DIGIT ZERO */ - const val XK_Thai_leknung = 0x0df1 /* U+0E51 THAI DIGIT ONE */ - const val XK_Thai_leksong = 0x0df2 /* U+0E52 THAI DIGIT TWO */ - const val XK_Thai_leksam = 0x0df3 /* U+0E53 THAI DIGIT THREE */ - const val XK_Thai_leksi = 0x0df4 /* U+0E54 THAI DIGIT FOUR */ - const val XK_Thai_lekha = 0x0df5 /* U+0E55 THAI DIGIT FIVE */ - const val XK_Thai_lekhok = 0x0df6 /* U+0E56 THAI DIGIT SIX */ - const val XK_Thai_lekchet = 0x0df7 /* U+0E57 THAI DIGIT SEVEN */ - const val XK_Thai_lekpaet = 0x0df8 /* U+0E58 THAI DIGIT EIGHT */ - const val XK_Thai_lekkao = 0x0df9 /* U+0E59 THAI DIGIT NINE */ - // #endif /* XK_THAI */ - - /* - * Korean - * Byte 3 = 0x0e - */ - - // #ifdef XK_KOREAN - - const val XK_Hangul = 0xff31 /* Hangul start/stop(toggle) */ - const val XK_Hangul_Start = 0xff32 /* Hangul start */ - const val XK_Hangul_End = 0xff33 /* Hangul end, English start */ - const val XK_Hangul_Hanja = 0xff34 /* Start Hangul->Hanja Conversion */ - const val XK_Hangul_Jamo = 0xff35 /* Hangul Jamo mode */ - const val XK_Hangul_Romaja = 0xff36 /* Hangul Romaja mode */ - const val XK_Hangul_Codeinput = 0xff37 /* Hangul code input mode */ - const val XK_Hangul_Jeonja = 0xff38 /* Jeonja mode */ - const val XK_Hangul_Banja = 0xff39 /* Banja mode */ - const val XK_Hangul_PreHanja = 0xff3a /* Pre Hanja conversion */ - const val XK_Hangul_PostHanja = 0xff3b /* Post Hanja conversion */ - const val XK_Hangul_SingleCandidate = 0xff3c /* Single candidate */ - const val XK_Hangul_MultipleCandidate = 0xff3d /* Multiple candidate */ - const val XK_Hangul_PreviousCandidate = 0xff3e /* Previous candidate */ - const val XK_Hangul_Special = 0xff3f /* Special symbols */ - const val XK_Hangul_switch = 0xff7e /* Alias for mode_switch */ - - /* Hangul Consonant Characters */ - const val XK_Hangul_Kiyeog = 0x0ea1 /* U+3131 HANGUL LETTER KIYEOK */ - const val XK_Hangul_SsangKiyeog = 0x0ea2 /* U+3132 HANGUL LETTER SSANGKIYEOK */ - const val XK_Hangul_KiyeogSios = 0x0ea3 /* U+3133 HANGUL LETTER KIYEOK-SIOS */ - const val XK_Hangul_Nieun = 0x0ea4 /* U+3134 HANGUL LETTER NIEUN */ - const val XK_Hangul_NieunJieuj = 0x0ea5 /* U+3135 HANGUL LETTER NIEUN-CIEUC */ - const val XK_Hangul_NieunHieuh = 0x0ea6 /* U+3136 HANGUL LETTER NIEUN-HIEUH */ - const val XK_Hangul_Dikeud = 0x0ea7 /* U+3137 HANGUL LETTER TIKEUT */ - const val XK_Hangul_SsangDikeud = 0x0ea8 /* U+3138 HANGUL LETTER SSANGTIKEUT */ - const val XK_Hangul_Rieul = 0x0ea9 /* U+3139 HANGUL LETTER RIEUL */ - const val XK_Hangul_RieulKiyeog = 0x0eaa /* U+313A HANGUL LETTER RIEUL-KIYEOK */ - const val XK_Hangul_RieulMieum = 0x0eab /* U+313B HANGUL LETTER RIEUL-MIEUM */ - const val XK_Hangul_RieulPieub = 0x0eac /* U+313C HANGUL LETTER RIEUL-PIEUP */ - const val XK_Hangul_RieulSios = 0x0ead /* U+313D HANGUL LETTER RIEUL-SIOS */ - const val XK_Hangul_RieulTieut = 0x0eae /* U+313E HANGUL LETTER RIEUL-THIEUTH */ - const val XK_Hangul_RieulPhieuf = 0x0eaf /* U+313F HANGUL LETTER RIEUL-PHIEUPH */ - const val XK_Hangul_RieulHieuh = 0x0eb0 /* U+3140 HANGUL LETTER RIEUL-HIEUH */ - const val XK_Hangul_Mieum = 0x0eb1 /* U+3141 HANGUL LETTER MIEUM */ - const val XK_Hangul_Pieub = 0x0eb2 /* U+3142 HANGUL LETTER PIEUP */ - const val XK_Hangul_SsangPieub = 0x0eb3 /* U+3143 HANGUL LETTER SSANGPIEUP */ - const val XK_Hangul_PieubSios = 0x0eb4 /* U+3144 HANGUL LETTER PIEUP-SIOS */ - const val XK_Hangul_Sios = 0x0eb5 /* U+3145 HANGUL LETTER SIOS */ - const val XK_Hangul_SsangSios = 0x0eb6 /* U+3146 HANGUL LETTER SSANGSIOS */ - const val XK_Hangul_Ieung = 0x0eb7 /* U+3147 HANGUL LETTER IEUNG */ - const val XK_Hangul_Jieuj = 0x0eb8 /* U+3148 HANGUL LETTER CIEUC */ - const val XK_Hangul_SsangJieuj = 0x0eb9 /* U+3149 HANGUL LETTER SSANGCIEUC */ - const val XK_Hangul_Cieuc = 0x0eba /* U+314A HANGUL LETTER CHIEUCH */ - const val XK_Hangul_Khieuq = 0x0ebb /* U+314B HANGUL LETTER KHIEUKH */ - const val XK_Hangul_Tieut = 0x0ebc /* U+314C HANGUL LETTER THIEUTH */ - const val XK_Hangul_Phieuf = 0x0ebd /* U+314D HANGUL LETTER PHIEUPH */ - const val XK_Hangul_Hieuh = 0x0ebe /* U+314E HANGUL LETTER HIEUH */ - - /* Hangul Vowel Characters */ - const val XK_Hangul_A = 0x0ebf /* U+314F HANGUL LETTER A */ - const val XK_Hangul_AE = 0x0ec0 /* U+3150 HANGUL LETTER AE */ - const val XK_Hangul_YA = 0x0ec1 /* U+3151 HANGUL LETTER YA */ - const val XK_Hangul_YAE = 0x0ec2 /* U+3152 HANGUL LETTER YAE */ - const val XK_Hangul_EO = 0x0ec3 /* U+3153 HANGUL LETTER EO */ - const val XK_Hangul_E = 0x0ec4 /* U+3154 HANGUL LETTER E */ - const val XK_Hangul_YEO = 0x0ec5 /* U+3155 HANGUL LETTER YEO */ - const val XK_Hangul_YE = 0x0ec6 /* U+3156 HANGUL LETTER YE */ - const val XK_Hangul_O = 0x0ec7 /* U+3157 HANGUL LETTER O */ - const val XK_Hangul_WA = 0x0ec8 /* U+3158 HANGUL LETTER WA */ - const val XK_Hangul_WAE = 0x0ec9 /* U+3159 HANGUL LETTER WAE */ - const val XK_Hangul_OE = 0x0eca /* U+315A HANGUL LETTER OE */ - const val XK_Hangul_YO = 0x0ecb /* U+315B HANGUL LETTER YO */ - const val XK_Hangul_U = 0x0ecc /* U+315C HANGUL LETTER U */ - const val XK_Hangul_WEO = 0x0ecd /* U+315D HANGUL LETTER WEO */ - const val XK_Hangul_WE = 0x0ece /* U+315E HANGUL LETTER WE */ - const val XK_Hangul_WI = 0x0ecf /* U+315F HANGUL LETTER WI */ - const val XK_Hangul_YU = 0x0ed0 /* U+3160 HANGUL LETTER YU */ - const val XK_Hangul_EU = 0x0ed1 /* U+3161 HANGUL LETTER EU */ - const val XK_Hangul_YI = 0x0ed2 /* U+3162 HANGUL LETTER YI */ - const val XK_Hangul_I = 0x0ed3 /* U+3163 HANGUL LETTER I */ - - /* Hangul syllable-final (JongSeong) Characters */ - const val XK_Hangul_J_Kiyeog = 0x0ed4 /* U+11A8 HANGUL JONGSEONG KIYEOK */ - const val XK_Hangul_J_SsangKiyeog = 0x0ed5 /* U+11A9 HANGUL JONGSEONG SSANGKIYEOK */ - const val XK_Hangul_J_KiyeogSios = 0x0ed6 /* U+11AA HANGUL JONGSEONG KIYEOK-SIOS */ - const val XK_Hangul_J_Nieun = 0x0ed7 /* U+11AB HANGUL JONGSEONG NIEUN */ - const val XK_Hangul_J_NieunJieuj = 0x0ed8 /* U+11AC HANGUL JONGSEONG NIEUN-CIEUC */ - const val XK_Hangul_J_NieunHieuh = 0x0ed9 /* U+11AD HANGUL JONGSEONG NIEUN-HIEUH */ - const val XK_Hangul_J_Dikeud = 0x0eda /* U+11AE HANGUL JONGSEONG TIKEUT */ - const val XK_Hangul_J_Rieul = 0x0edb /* U+11AF HANGUL JONGSEONG RIEUL */ - const val XK_Hangul_J_RieulKiyeog = 0x0edc /* U+11B0 HANGUL JONGSEONG RIEUL-KIYEOK */ - const val XK_Hangul_J_RieulMieum = 0x0edd /* U+11B1 HANGUL JONGSEONG RIEUL-MIEUM */ - const val XK_Hangul_J_RieulPieub = 0x0ede /* U+11B2 HANGUL JONGSEONG RIEUL-PIEUP */ - const val XK_Hangul_J_RieulSios = 0x0edf /* U+11B3 HANGUL JONGSEONG RIEUL-SIOS */ - const val XK_Hangul_J_RieulTieut = 0x0ee0 /* U+11B4 HANGUL JONGSEONG RIEUL-THIEUTH */ - const val XK_Hangul_J_RieulPhieuf = 0x0ee1 /* U+11B5 HANGUL JONGSEONG RIEUL-PHIEUPH */ - const val XK_Hangul_J_RieulHieuh = 0x0ee2 /* U+11B6 HANGUL JONGSEONG RIEUL-HIEUH */ - const val XK_Hangul_J_Mieum = 0x0ee3 /* U+11B7 HANGUL JONGSEONG MIEUM */ - const val XK_Hangul_J_Pieub = 0x0ee4 /* U+11B8 HANGUL JONGSEONG PIEUP */ - const val XK_Hangul_J_PieubSios = 0x0ee5 /* U+11B9 HANGUL JONGSEONG PIEUP-SIOS */ - const val XK_Hangul_J_Sios = 0x0ee6 /* U+11BA HANGUL JONGSEONG SIOS */ - const val XK_Hangul_J_SsangSios = 0x0ee7 /* U+11BB HANGUL JONGSEONG SSANGSIOS */ - const val XK_Hangul_J_Ieung = 0x0ee8 /* U+11BC HANGUL JONGSEONG IEUNG */ - const val XK_Hangul_J_Jieuj = 0x0ee9 /* U+11BD HANGUL JONGSEONG CIEUC */ - const val XK_Hangul_J_Cieuc = 0x0eea /* U+11BE HANGUL JONGSEONG CHIEUCH */ - const val XK_Hangul_J_Khieuq = 0x0eeb /* U+11BF HANGUL JONGSEONG KHIEUKH */ - const val XK_Hangul_J_Tieut = 0x0eec /* U+11C0 HANGUL JONGSEONG THIEUTH */ - const val XK_Hangul_J_Phieuf = 0x0eed /* U+11C1 HANGUL JONGSEONG PHIEUPH */ - const val XK_Hangul_J_Hieuh = 0x0eee /* U+11C2 HANGUL JONGSEONG HIEUH */ - - /* Ancient Hangul Consonant Characters */ - const val XK_Hangul_RieulYeorinHieuh = 0x0eef /* U+316D HANGUL LETTER RIEUL-YEORINHIEUH */ - const val XK_Hangul_SunkyeongeumMieum = 0x0ef0 /* U+3171 HANGUL LETTER KAPYEOUNMIEUM */ - const val XK_Hangul_SunkyeongeumPieub = 0x0ef1 /* U+3178 HANGUL LETTER KAPYEOUNPIEUP */ - const val XK_Hangul_PanSios = 0x0ef2 /* U+317F HANGUL LETTER PANSIOS */ - const val XK_Hangul_KkogjiDalrinIeung = 0x0ef3 /* U+3181 HANGUL LETTER YESIEUNG */ - const val XK_Hangul_SunkyeongeumPhieuf = 0x0ef4 /* U+3184 HANGUL LETTER KAPYEOUNPHIEUPH */ - const val XK_Hangul_YeorinHieuh = 0x0ef5 /* U+3186 HANGUL LETTER YEORINHIEUH */ - - /* Ancient Hangul Vowel Characters */ - const val XK_Hangul_AraeA = 0x0ef6 /* U+318D HANGUL LETTER ARAEA */ - const val XK_Hangul_AraeAE = 0x0ef7 /* U+318E HANGUL LETTER ARAEAE */ - - /* Ancient Hangul syllable-final (JongSeong) Characters */ - const val XK_Hangul_J_PanSios = 0x0ef8 /* U+11EB HANGUL JONGSEONG PANSIOS */ - const val XK_Hangul_J_KkogjiDalrinIeung = 0x0ef9 /* U+11F0 HANGUL JONGSEONG YESIEUNG */ - const val XK_Hangul_J_YeorinHieuh = 0x0efa /* U+11F9 HANGUL JONGSEONG YEORINHIEUH */ - - /* Korean currency symbol */ - const val XK_Korean_Won = 0x0eff /*(U+20A9 WON SIGN)*/ - - // #endif /* XK_KOREAN */ - - /* - * Armenian - */ - - // #ifdef XK_ARMENIAN - const val XK_Armenian_ligature_ew = 0x1000587 /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */ - const val XK_Armenian_full_stop = 0x1000589 /* U+0589 ARMENIAN FULL STOP */ - const val XK_Armenian_verjaket = 0x1000589 /* U+0589 ARMENIAN FULL STOP */ - const val XK_Armenian_separation_mark = 0x100055d /* U+055D ARMENIAN COMMA */ - const val XK_Armenian_but = 0x100055d /* U+055D ARMENIAN COMMA */ - const val XK_Armenian_hyphen = 0x100058a /* U+058A ARMENIAN HYPHEN */ - const val XK_Armenian_yentamna = 0x100058a /* U+058A ARMENIAN HYPHEN */ - const val XK_Armenian_exclam = 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ - const val XK_Armenian_amanak = 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ - const val XK_Armenian_accent = 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ - const val XK_Armenian_shesht = 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ - const val XK_Armenian_question = 0x100055e /* U+055E ARMENIAN QUESTION MARK */ - const val XK_Armenian_paruyk = 0x100055e /* U+055E ARMENIAN QUESTION MARK */ - const val XK_Armenian_AYB = 0x1000531 /* U+0531 ARMENIAN CAPITAL LETTER AYB */ - const val XK_Armenian_ayb = 0x1000561 /* U+0561 ARMENIAN SMALL LETTER AYB */ - const val XK_Armenian_BEN = 0x1000532 /* U+0532 ARMENIAN CAPITAL LETTER BEN */ - const val XK_Armenian_ben = 0x1000562 /* U+0562 ARMENIAN SMALL LETTER BEN */ - const val XK_Armenian_GIM = 0x1000533 /* U+0533 ARMENIAN CAPITAL LETTER GIM */ - const val XK_Armenian_gim = 0x1000563 /* U+0563 ARMENIAN SMALL LETTER GIM */ - const val XK_Armenian_DA = 0x1000534 /* U+0534 ARMENIAN CAPITAL LETTER DA */ - const val XK_Armenian_da = 0x1000564 /* U+0564 ARMENIAN SMALL LETTER DA */ - const val XK_Armenian_YECH = 0x1000535 /* U+0535 ARMENIAN CAPITAL LETTER ECH */ - const val XK_Armenian_yech = 0x1000565 /* U+0565 ARMENIAN SMALL LETTER ECH */ - const val XK_Armenian_ZA = 0x1000536 /* U+0536 ARMENIAN CAPITAL LETTER ZA */ - const val XK_Armenian_za = 0x1000566 /* U+0566 ARMENIAN SMALL LETTER ZA */ - const val XK_Armenian_E = 0x1000537 /* U+0537 ARMENIAN CAPITAL LETTER EH */ - const val XK_Armenian_e = 0x1000567 /* U+0567 ARMENIAN SMALL LETTER EH */ - const val XK_Armenian_AT = 0x1000538 /* U+0538 ARMENIAN CAPITAL LETTER ET */ - const val XK_Armenian_at = 0x1000568 /* U+0568 ARMENIAN SMALL LETTER ET */ - const val XK_Armenian_TO = 0x1000539 /* U+0539 ARMENIAN CAPITAL LETTER TO */ - const val XK_Armenian_to = 0x1000569 /* U+0569 ARMENIAN SMALL LETTER TO */ - const val XK_Armenian_ZHE = 0x100053a /* U+053A ARMENIAN CAPITAL LETTER ZHE */ - const val XK_Armenian_zhe = 0x100056a /* U+056A ARMENIAN SMALL LETTER ZHE */ - const val XK_Armenian_INI = 0x100053b /* U+053B ARMENIAN CAPITAL LETTER INI */ - const val XK_Armenian_ini = 0x100056b /* U+056B ARMENIAN SMALL LETTER INI */ - const val XK_Armenian_LYUN = 0x100053c /* U+053C ARMENIAN CAPITAL LETTER LIWN */ - const val XK_Armenian_lyun = 0x100056c /* U+056C ARMENIAN SMALL LETTER LIWN */ - const val XK_Armenian_KHE = 0x100053d /* U+053D ARMENIAN CAPITAL LETTER XEH */ - const val XK_Armenian_khe = 0x100056d /* U+056D ARMENIAN SMALL LETTER XEH */ - const val XK_Armenian_TSA = 0x100053e /* U+053E ARMENIAN CAPITAL LETTER CA */ - const val XK_Armenian_tsa = 0x100056e /* U+056E ARMENIAN SMALL LETTER CA */ - const val XK_Armenian_KEN = 0x100053f /* U+053F ARMENIAN CAPITAL LETTER KEN */ - const val XK_Armenian_ken = 0x100056f /* U+056F ARMENIAN SMALL LETTER KEN */ - const val XK_Armenian_HO = 0x1000540 /* U+0540 ARMENIAN CAPITAL LETTER HO */ - const val XK_Armenian_ho = 0x1000570 /* U+0570 ARMENIAN SMALL LETTER HO */ - const val XK_Armenian_DZA = 0x1000541 /* U+0541 ARMENIAN CAPITAL LETTER JA */ - const val XK_Armenian_dza = 0x1000571 /* U+0571 ARMENIAN SMALL LETTER JA */ - const val XK_Armenian_GHAT = 0x1000542 /* U+0542 ARMENIAN CAPITAL LETTER GHAD */ - const val XK_Armenian_ghat = 0x1000572 /* U+0572 ARMENIAN SMALL LETTER GHAD */ - const val XK_Armenian_TCHE = 0x1000543 /* U+0543 ARMENIAN CAPITAL LETTER CHEH */ - const val XK_Armenian_tche = 0x1000573 /* U+0573 ARMENIAN SMALL LETTER CHEH */ - const val XK_Armenian_MEN = 0x1000544 /* U+0544 ARMENIAN CAPITAL LETTER MEN */ - const val XK_Armenian_men = 0x1000574 /* U+0574 ARMENIAN SMALL LETTER MEN */ - const val XK_Armenian_HI = 0x1000545 /* U+0545 ARMENIAN CAPITAL LETTER YI */ - const val XK_Armenian_hi = 0x1000575 /* U+0575 ARMENIAN SMALL LETTER YI */ - const val XK_Armenian_NU = 0x1000546 /* U+0546 ARMENIAN CAPITAL LETTER NOW */ - const val XK_Armenian_nu = 0x1000576 /* U+0576 ARMENIAN SMALL LETTER NOW */ - const val XK_Armenian_SHA = 0x1000547 /* U+0547 ARMENIAN CAPITAL LETTER SHA */ - const val XK_Armenian_sha = 0x1000577 /* U+0577 ARMENIAN SMALL LETTER SHA */ - const val XK_Armenian_VO = 0x1000548 /* U+0548 ARMENIAN CAPITAL LETTER VO */ - const val XK_Armenian_vo = 0x1000578 /* U+0578 ARMENIAN SMALL LETTER VO */ - const val XK_Armenian_CHA = 0x1000549 /* U+0549 ARMENIAN CAPITAL LETTER CHA */ - const val XK_Armenian_cha = 0x1000579 /* U+0579 ARMENIAN SMALL LETTER CHA */ - const val XK_Armenian_PE = 0x100054a /* U+054A ARMENIAN CAPITAL LETTER PEH */ - const val XK_Armenian_pe = 0x100057a /* U+057A ARMENIAN SMALL LETTER PEH */ - const val XK_Armenian_JE = 0x100054b /* U+054B ARMENIAN CAPITAL LETTER JHEH */ - const val XK_Armenian_je = 0x100057b /* U+057B ARMENIAN SMALL LETTER JHEH */ - const val XK_Armenian_RA = 0x100054c /* U+054C ARMENIAN CAPITAL LETTER RA */ - const val XK_Armenian_ra = 0x100057c /* U+057C ARMENIAN SMALL LETTER RA */ - const val XK_Armenian_SE = 0x100054d /* U+054D ARMENIAN CAPITAL LETTER SEH */ - const val XK_Armenian_se = 0x100057d /* U+057D ARMENIAN SMALL LETTER SEH */ - const val XK_Armenian_VEV = 0x100054e /* U+054E ARMENIAN CAPITAL LETTER VEW */ - const val XK_Armenian_vev = 0x100057e /* U+057E ARMENIAN SMALL LETTER VEW */ - const val XK_Armenian_TYUN = 0x100054f /* U+054F ARMENIAN CAPITAL LETTER TIWN */ - const val XK_Armenian_tyun = 0x100057f /* U+057F ARMENIAN SMALL LETTER TIWN */ - const val XK_Armenian_RE = 0x1000550 /* U+0550 ARMENIAN CAPITAL LETTER REH */ - const val XK_Armenian_re = 0x1000580 /* U+0580 ARMENIAN SMALL LETTER REH */ - const val XK_Armenian_TSO = 0x1000551 /* U+0551 ARMENIAN CAPITAL LETTER CO */ - const val XK_Armenian_tso = 0x1000581 /* U+0581 ARMENIAN SMALL LETTER CO */ - const val XK_Armenian_VYUN = 0x1000552 /* U+0552 ARMENIAN CAPITAL LETTER YIWN */ - const val XK_Armenian_vyun = 0x1000582 /* U+0582 ARMENIAN SMALL LETTER YIWN */ - const val XK_Armenian_PYUR = 0x1000553 /* U+0553 ARMENIAN CAPITAL LETTER PIWR */ - const val XK_Armenian_pyur = 0x1000583 /* U+0583 ARMENIAN SMALL LETTER PIWR */ - const val XK_Armenian_KE = 0x1000554 /* U+0554 ARMENIAN CAPITAL LETTER KEH */ - const val XK_Armenian_ke = 0x1000584 /* U+0584 ARMENIAN SMALL LETTER KEH */ - const val XK_Armenian_O = 0x1000555 /* U+0555 ARMENIAN CAPITAL LETTER OH */ - const val XK_Armenian_o = 0x1000585 /* U+0585 ARMENIAN SMALL LETTER OH */ - const val XK_Armenian_FE = 0x1000556 /* U+0556 ARMENIAN CAPITAL LETTER FEH */ - const val XK_Armenian_fe = 0x1000586 /* U+0586 ARMENIAN SMALL LETTER FEH */ - const val XK_Armenian_apostrophe = 0x100055a /* U+055A ARMENIAN APOSTROPHE */ - // #endif /* XK_ARMENIAN */ - - /* - * Georgian - */ - - // #ifdef XK_GEORGIAN - const val XK_Georgian_an = 0x10010d0 /* U+10D0 GEORGIAN LETTER AN */ - const val XK_Georgian_ban = 0x10010d1 /* U+10D1 GEORGIAN LETTER BAN */ - const val XK_Georgian_gan = 0x10010d2 /* U+10D2 GEORGIAN LETTER GAN */ - const val XK_Georgian_don = 0x10010d3 /* U+10D3 GEORGIAN LETTER DON */ - const val XK_Georgian_en = 0x10010d4 /* U+10D4 GEORGIAN LETTER EN */ - const val XK_Georgian_vin = 0x10010d5 /* U+10D5 GEORGIAN LETTER VIN */ - const val XK_Georgian_zen = 0x10010d6 /* U+10D6 GEORGIAN LETTER ZEN */ - const val XK_Georgian_tan = 0x10010d7 /* U+10D7 GEORGIAN LETTER TAN */ - const val XK_Georgian_in = 0x10010d8 /* U+10D8 GEORGIAN LETTER IN */ - const val XK_Georgian_kan = 0x10010d9 /* U+10D9 GEORGIAN LETTER KAN */ - const val XK_Georgian_las = 0x10010da /* U+10DA GEORGIAN LETTER LAS */ - const val XK_Georgian_man = 0x10010db /* U+10DB GEORGIAN LETTER MAN */ - const val XK_Georgian_nar = 0x10010dc /* U+10DC GEORGIAN LETTER NAR */ - const val XK_Georgian_on = 0x10010dd /* U+10DD GEORGIAN LETTER ON */ - const val XK_Georgian_par = 0x10010de /* U+10DE GEORGIAN LETTER PAR */ - const val XK_Georgian_zhar = 0x10010df /* U+10DF GEORGIAN LETTER ZHAR */ - const val XK_Georgian_rae = 0x10010e0 /* U+10E0 GEORGIAN LETTER RAE */ - const val XK_Georgian_san = 0x10010e1 /* U+10E1 GEORGIAN LETTER SAN */ - const val XK_Georgian_tar = 0x10010e2 /* U+10E2 GEORGIAN LETTER TAR */ - const val XK_Georgian_un = 0x10010e3 /* U+10E3 GEORGIAN LETTER UN */ - const val XK_Georgian_phar = 0x10010e4 /* U+10E4 GEORGIAN LETTER PHAR */ - const val XK_Georgian_khar = 0x10010e5 /* U+10E5 GEORGIAN LETTER KHAR */ - const val XK_Georgian_ghan = 0x10010e6 /* U+10E6 GEORGIAN LETTER GHAN */ - const val XK_Georgian_qar = 0x10010e7 /* U+10E7 GEORGIAN LETTER QAR */ - const val XK_Georgian_shin = 0x10010e8 /* U+10E8 GEORGIAN LETTER SHIN */ - const val XK_Georgian_chin = 0x10010e9 /* U+10E9 GEORGIAN LETTER CHIN */ - const val XK_Georgian_can = 0x10010ea /* U+10EA GEORGIAN LETTER CAN */ - const val XK_Georgian_jil = 0x10010eb /* U+10EB GEORGIAN LETTER JIL */ - const val XK_Georgian_cil = 0x10010ec /* U+10EC GEORGIAN LETTER CIL */ - const val XK_Georgian_char = 0x10010ed /* U+10ED GEORGIAN LETTER CHAR */ - const val XK_Georgian_xan = 0x10010ee /* U+10EE GEORGIAN LETTER XAN */ - const val XK_Georgian_jhan = 0x10010ef /* U+10EF GEORGIAN LETTER JHAN */ - const val XK_Georgian_hae = 0x10010f0 /* U+10F0 GEORGIAN LETTER HAE */ - const val XK_Georgian_he = 0x10010f1 /* U+10F1 GEORGIAN LETTER HE */ - const val XK_Georgian_hie = 0x10010f2 /* U+10F2 GEORGIAN LETTER HIE */ - const val XK_Georgian_we = 0x10010f3 /* U+10F3 GEORGIAN LETTER WE */ - const val XK_Georgian_har = 0x10010f4 /* U+10F4 GEORGIAN LETTER HAR */ - const val XK_Georgian_hoe = 0x10010f5 /* U+10F5 GEORGIAN LETTER HOE */ - const val XK_Georgian_fi = 0x10010f6 /* U+10F6 GEORGIAN LETTER FI */ - // #endif /* XK_GEORGIAN */ - - /* - * Azeri (and other Turkic or Caucasian languages) - */ - - // #ifdef XK_CAUCASUS - /* latin */ - const val XK_Xabovedot = 0x1001e8a /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */ - const val XK_Ibreve = 0x100012c /* U+012C LATIN CAPITAL LETTER I WITH BREVE */ - const val XK_Zstroke = 0x10001b5 /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */ - const val XK_Gcaron = 0x10001e6 /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */ - const val XK_Ocaron = 0x10001d1 /* U+01D1 LATIN CAPITAL LETTER O WITH CARON */ - const val XK_Obarred = 0x100019f /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */ - const val XK_xabovedot = 0x1001e8b /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */ - const val XK_ibreve = 0x100012d /* U+012D LATIN SMALL LETTER I WITH BREVE */ - const val XK_zstroke = 0x10001b6 /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */ - const val XK_gcaron = 0x10001e7 /* U+01E7 LATIN SMALL LETTER G WITH CARON */ - const val XK_ocaron = 0x10001d2 /* U+01D2 LATIN SMALL LETTER O WITH CARON */ - const val XK_obarred = 0x1000275 /* U+0275 LATIN SMALL LETTER BARRED O */ - const val XK_SCHWA = 0x100018f /* U+018F LATIN CAPITAL LETTER SCHWA */ - const val XK_schwa = 0x1000259 /* U+0259 LATIN SMALL LETTER SCHWA */ - const val XK_EZH = 0x10001b7 /* U+01B7 LATIN CAPITAL LETTER EZH */ - const val XK_ezh = 0x1000292 /* U+0292 LATIN SMALL LETTER EZH */ - /* those are not really Caucasus */ - /* For Inupiak */ - const val XK_Lbelowdot = 0x1001e36 /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */ - const val XK_lbelowdot = 0x1001e37 /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */ - // #endif /* XK_CAUCASUS */ - - /* - * Vietnamese - */ - - // #ifdef XK_VIETNAMESE - const val XK_Abelowdot = 0x1001ea0 /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */ - const val XK_abelowdot = 0x1001ea1 /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */ - const val XK_Ahook = 0x1001ea2 /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */ - const val XK_ahook = 0x1001ea3 /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */ - const val XK_Acircumflexacute = 0x1001ea4 /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ - const val XK_acircumflexacute = 0x1001ea5 /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ - const val XK_Acircumflexgrave = 0x1001ea6 /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ - const val XK_acircumflexgrave = 0x1001ea7 /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ - const val XK_Acircumflexhook = 0x1001ea8 /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ - const val XK_acircumflexhook = 0x1001ea9 /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ - const val XK_Acircumflextilde = 0x1001eaa /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ - const val XK_acircumflextilde = 0x1001eab /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ - const val XK_Acircumflexbelowdot = 0x1001eac /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ - const val XK_acircumflexbelowdot = 0x1001ead /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ - const val XK_Abreveacute = 0x1001eae /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ - const val XK_abreveacute = 0x1001eaf /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */ - const val XK_Abrevegrave = 0x1001eb0 /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ - const val XK_abrevegrave = 0x1001eb1 /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */ - const val XK_Abrevehook = 0x1001eb2 /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ - const val XK_abrevehook = 0x1001eb3 /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ - const val XK_Abrevetilde = 0x1001eb4 /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ - const val XK_abrevetilde = 0x1001eb5 /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */ - const val XK_Abrevebelowdot = 0x1001eb6 /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ - const val XK_abrevebelowdot = 0x1001eb7 /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ - const val XK_Ebelowdot = 0x1001eb8 /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */ - const val XK_ebelowdot = 0x1001eb9 /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */ - const val XK_Ehook = 0x1001eba /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */ - const val XK_ehook = 0x1001ebb /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */ - const val XK_Etilde = 0x1001ebc /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */ - const val XK_etilde = 0x1001ebd /* U+1EBD LATIN SMALL LETTER E WITH TILDE */ - const val XK_Ecircumflexacute = 0x1001ebe /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ - const val XK_ecircumflexacute = 0x1001ebf /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ - const val XK_Ecircumflexgrave = 0x1001ec0 /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ - const val XK_ecircumflexgrave = 0x1001ec1 /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ - const val XK_Ecircumflexhook = 0x1001ec2 /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ - const val XK_ecircumflexhook = 0x1001ec3 /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ - const val XK_Ecircumflextilde = 0x1001ec4 /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ - const val XK_ecircumflextilde = 0x1001ec5 /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ - const val XK_Ecircumflexbelowdot = 0x1001ec6 /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ - const val XK_ecircumflexbelowdot = 0x1001ec7 /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ - const val XK_Ihook = 0x1001ec8 /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */ - const val XK_ihook = 0x1001ec9 /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */ - const val XK_Ibelowdot = 0x1001eca /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */ - const val XK_ibelowdot = 0x1001ecb /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */ - const val XK_Obelowdot = 0x1001ecc /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */ - const val XK_obelowdot = 0x1001ecd /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */ - const val XK_Ohook = 0x1001ece /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */ - const val XK_ohook = 0x1001ecf /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */ - const val XK_Ocircumflexacute = 0x1001ed0 /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ - const val XK_ocircumflexacute = 0x1001ed1 /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ - const val XK_Ocircumflexgrave = 0x1001ed2 /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ - const val XK_ocircumflexgrave = 0x1001ed3 /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ - const val XK_Ocircumflexhook = 0x1001ed4 /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ - const val XK_ocircumflexhook = 0x1001ed5 /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ - const val XK_Ocircumflextilde = 0x1001ed6 /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ - const val XK_ocircumflextilde = 0x1001ed7 /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ - const val XK_Ocircumflexbelowdot = 0x1001ed8 /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ - const val XK_ocircumflexbelowdot = 0x1001ed9 /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ - const val XK_Ohornacute = 0x1001eda /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ - const val XK_ohornacute = 0x1001edb /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */ - const val XK_Ohorngrave = 0x1001edc /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ - const val XK_ohorngrave = 0x1001edd /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */ - const val XK_Ohornhook = 0x1001ede /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ - const val XK_ohornhook = 0x1001edf /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ - const val XK_Ohorntilde = 0x1001ee0 /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */ - const val XK_ohorntilde = 0x1001ee1 /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */ - const val XK_Ohornbelowdot = 0x1001ee2 /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ - const val XK_ohornbelowdot = 0x1001ee3 /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ - const val XK_Ubelowdot = 0x1001ee4 /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */ - const val XK_ubelowdot = 0x1001ee5 /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */ - const val XK_Uhook = 0x1001ee6 /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */ - const val XK_uhook = 0x1001ee7 /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */ - const val XK_Uhornacute = 0x1001ee8 /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ - const val XK_uhornacute = 0x1001ee9 /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */ - const val XK_Uhorngrave = 0x1001eea /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ - const val XK_uhorngrave = 0x1001eeb /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */ - const val XK_Uhornhook = 0x1001eec /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ - const val XK_uhornhook = 0x1001eed /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ - const val XK_Uhorntilde = 0x1001eee /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */ - const val XK_uhorntilde = 0x1001eef /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */ - const val XK_Uhornbelowdot = 0x1001ef0 /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ - const val XK_uhornbelowdot = 0x1001ef1 /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ - const val XK_Ybelowdot = 0x1001ef4 /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */ - const val XK_ybelowdot = 0x1001ef5 /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */ - const val XK_Yhook = 0x1001ef6 /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ - const val XK_yhook = 0x1001ef7 /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */ - const val XK_Ytilde = 0x1001ef8 /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */ - const val XK_ytilde = 0x1001ef9 /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */ - const val XK_Ohorn = 0x10001a0 /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */ - const val XK_ohorn = 0x10001a1 /* U+01A1 LATIN SMALL LETTER O WITH HORN */ - const val XK_Uhorn = 0x10001af /* U+01AF LATIN CAPITAL LETTER U WITH HORN */ - const val XK_uhorn = 0x10001b0 /* U+01B0 LATIN SMALL LETTER U WITH HORN */ - const val XK_combining_tilde = 0x1000303 /* U+0303 COMBINING TILDE */ - const val XK_combining_grave = 0x1000300 /* U+0300 COMBINING GRAVE ACCENT */ - const val XK_combining_acute = 0x1000301 /* U+0301 COMBINING ACUTE ACCENT */ - const val XK_combining_hook = 0x1000309 /* U+0309 COMBINING HOOK ABOVE */ - const val XK_combining_belowdot = 0x1000323 /* U+0323 COMBINING DOT BELOW */ - - // #endif /* XK_VIETNAMESE */ - - // #ifdef XK_CURRENCY - const val XK_EcuSign = 0x10020a0 /* U+20A0 EURO-CURRENCY SIGN */ - const val XK_ColonSign = 0x10020a1 /* U+20A1 COLON SIGN */ - const val XK_CruzeiroSign = 0x10020a2 /* U+20A2 CRUZEIRO SIGN */ - const val XK_FFrancSign = 0x10020a3 /* U+20A3 FRENCH FRANC SIGN */ - const val XK_LiraSign = 0x10020a4 /* U+20A4 LIRA SIGN */ - const val XK_MillSign = 0x10020a5 /* U+20A5 MILL SIGN */ - const val XK_NairaSign = 0x10020a6 /* U+20A6 NAIRA SIGN */ - const val XK_PesetaSign = 0x10020a7 /* U+20A7 PESETA SIGN */ - const val XK_RupeeSign = 0x10020a8 /* U+20A8 RUPEE SIGN */ - const val XK_WonSign = 0x10020a9 /* U+20A9 WON SIGN */ - const val XK_NewSheqelSign = 0x10020aa /* U+20AA NEW SHEQEL SIGN */ - const val XK_DongSign = 0x10020ab /* U+20AB DONG SIGN */ - const val XK_EuroSign = 0x20ac /* U+20AC EURO SIGN */ - // #endif /* XK_CURRENCY */ - - // #ifdef XK_MATHEMATICAL - /* one, two and three are defined above. */ - const val XK_zerosuperior = 0x1002070 /* U+2070 SUPERSCRIPT ZERO */ - const val XK_foursuperior = 0x1002074 /* U+2074 SUPERSCRIPT FOUR */ - const val XK_fivesuperior = 0x1002075 /* U+2075 SUPERSCRIPT FIVE */ - const val XK_sixsuperior = 0x1002076 /* U+2076 SUPERSCRIPT SIX */ - const val XK_sevensuperior = 0x1002077 /* U+2077 SUPERSCRIPT SEVEN */ - const val XK_eightsuperior = 0x1002078 /* U+2078 SUPERSCRIPT EIGHT */ - const val XK_ninesuperior = 0x1002079 /* U+2079 SUPERSCRIPT NINE */ - const val XK_zerosubscript = 0x1002080 /* U+2080 SUBSCRIPT ZERO */ - const val XK_onesubscript = 0x1002081 /* U+2081 SUBSCRIPT ONE */ - const val XK_twosubscript = 0x1002082 /* U+2082 SUBSCRIPT TWO */ - const val XK_threesubscript = 0x1002083 /* U+2083 SUBSCRIPT THREE */ - const val XK_foursubscript = 0x1002084 /* U+2084 SUBSCRIPT FOUR */ - const val XK_fivesubscript = 0x1002085 /* U+2085 SUBSCRIPT FIVE */ - const val XK_sixsubscript = 0x1002086 /* U+2086 SUBSCRIPT SIX */ - const val XK_sevensubscript = 0x1002087 /* U+2087 SUBSCRIPT SEVEN */ - const val XK_eightsubscript = 0x1002088 /* U+2088 SUBSCRIPT EIGHT */ - const val XK_ninesubscript = 0x1002089 /* U+2089 SUBSCRIPT NINE */ - const val XK_partdifferential = 0x1002202 /* U+2202 PARTIAL DIFFERENTIAL */ - const val XK_emptyset = 0x1002205 /* U+2205 NULL SET */ - const val XK_elementof = 0x1002208 /* U+2208 ELEMENT OF */ - const val XK_notelementof = 0x1002209 /* U+2209 NOT AN ELEMENT OF */ - const val XK_containsas = 0x100220B /* U+220B CONTAINS AS MEMBER */ - const val XK_squareroot = 0x100221A /* U+221A SQUARE ROOT */ - const val XK_cuberoot = 0x100221B /* U+221B CUBE ROOT */ - const val XK_fourthroot = 0x100221C /* U+221C FOURTH ROOT */ - const val XK_dintegral = 0x100222C /* U+222C DOUBLE INTEGRAL */ - const val XK_tintegral = 0x100222D /* U+222D TRIPLE INTEGRAL */ - const val XK_because = 0x1002235 /* U+2235 BECAUSE */ - const val XK_approxeq = 0x1002248 /*(U+2248 ALMOST EQUAL TO)*/ - const val XK_notapproxeq = 0x1002247 /*(U+2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO)*/ - const val XK_notidentical = 0x1002262 /* U+2262 NOT IDENTICAL TO */ - const val XK_stricteq = 0x1002263 /* U+2263 STRICTLY EQUIVALENT TO */ - // #endif /* XK_MATHEMATICAL */ - - // #ifdef XK_BRAILLE - const val XK_braille_dot_1 = 0xfff1 - const val XK_braille_dot_2 = 0xfff2 - const val XK_braille_dot_3 = 0xfff3 - const val XK_braille_dot_4 = 0xfff4 - const val XK_braille_dot_5 = 0xfff5 - const val XK_braille_dot_6 = 0xfff6 - const val XK_braille_dot_7 = 0xfff7 - const val XK_braille_dot_8 = 0xfff8 - const val XK_braille_dot_9 = 0xfff9 - const val XK_braille_dot_10 = 0xfffa - const val XK_braille_blank = 0x1002800 /* U+2800 BRAILLE PATTERN BLANK */ - const val XK_braille_dots_1 = 0x1002801 /* U+2801 BRAILLE PATTERN DOTS-1 */ - const val XK_braille_dots_2 = 0x1002802 /* U+2802 BRAILLE PATTERN DOTS-2 */ - const val XK_braille_dots_12 = 0x1002803 /* U+2803 BRAILLE PATTERN DOTS-12 */ - const val XK_braille_dots_3 = 0x1002804 /* U+2804 BRAILLE PATTERN DOTS-3 */ - const val XK_braille_dots_13 = 0x1002805 /* U+2805 BRAILLE PATTERN DOTS-13 */ - const val XK_braille_dots_23 = 0x1002806 /* U+2806 BRAILLE PATTERN DOTS-23 */ - const val XK_braille_dots_123 = 0x1002807 /* U+2807 BRAILLE PATTERN DOTS-123 */ - const val XK_braille_dots_4 = 0x1002808 /* U+2808 BRAILLE PATTERN DOTS-4 */ - const val XK_braille_dots_14 = 0x1002809 /* U+2809 BRAILLE PATTERN DOTS-14 */ - const val XK_braille_dots_24 = 0x100280a /* U+280a BRAILLE PATTERN DOTS-24 */ - const val XK_braille_dots_124 = 0x100280b /* U+280b BRAILLE PATTERN DOTS-124 */ - const val XK_braille_dots_34 = 0x100280c /* U+280c BRAILLE PATTERN DOTS-34 */ - const val XK_braille_dots_134 = 0x100280d /* U+280d BRAILLE PATTERN DOTS-134 */ - const val XK_braille_dots_234 = 0x100280e /* U+280e BRAILLE PATTERN DOTS-234 */ - const val XK_braille_dots_1234 = 0x100280f /* U+280f BRAILLE PATTERN DOTS-1234 */ - const val XK_braille_dots_5 = 0x1002810 /* U+2810 BRAILLE PATTERN DOTS-5 */ - const val XK_braille_dots_15 = 0x1002811 /* U+2811 BRAILLE PATTERN DOTS-15 */ - const val XK_braille_dots_25 = 0x1002812 /* U+2812 BRAILLE PATTERN DOTS-25 */ - const val XK_braille_dots_125 = 0x1002813 /* U+2813 BRAILLE PATTERN DOTS-125 */ - const val XK_braille_dots_35 = 0x1002814 /* U+2814 BRAILLE PATTERN DOTS-35 */ - const val XK_braille_dots_135 = 0x1002815 /* U+2815 BRAILLE PATTERN DOTS-135 */ - const val XK_braille_dots_235 = 0x1002816 /* U+2816 BRAILLE PATTERN DOTS-235 */ - const val XK_braille_dots_1235 = 0x1002817 /* U+2817 BRAILLE PATTERN DOTS-1235 */ - const val XK_braille_dots_45 = 0x1002818 /* U+2818 BRAILLE PATTERN DOTS-45 */ - const val XK_braille_dots_145 = 0x1002819 /* U+2819 BRAILLE PATTERN DOTS-145 */ - const val XK_braille_dots_245 = 0x100281a /* U+281a BRAILLE PATTERN DOTS-245 */ - const val XK_braille_dots_1245 = 0x100281b /* U+281b BRAILLE PATTERN DOTS-1245 */ - const val XK_braille_dots_345 = 0x100281c /* U+281c BRAILLE PATTERN DOTS-345 */ - const val XK_braille_dots_1345 = 0x100281d /* U+281d BRAILLE PATTERN DOTS-1345 */ - const val XK_braille_dots_2345 = 0x100281e /* U+281e BRAILLE PATTERN DOTS-2345 */ - const val XK_braille_dots_12345 = 0x100281f /* U+281f BRAILLE PATTERN DOTS-12345 */ - const val XK_braille_dots_6 = 0x1002820 /* U+2820 BRAILLE PATTERN DOTS-6 */ - const val XK_braille_dots_16 = 0x1002821 /* U+2821 BRAILLE PATTERN DOTS-16 */ - const val XK_braille_dots_26 = 0x1002822 /* U+2822 BRAILLE PATTERN DOTS-26 */ - const val XK_braille_dots_126 = 0x1002823 /* U+2823 BRAILLE PATTERN DOTS-126 */ - const val XK_braille_dots_36 = 0x1002824 /* U+2824 BRAILLE PATTERN DOTS-36 */ - const val XK_braille_dots_136 = 0x1002825 /* U+2825 BRAILLE PATTERN DOTS-136 */ - const val XK_braille_dots_236 = 0x1002826 /* U+2826 BRAILLE PATTERN DOTS-236 */ - const val XK_braille_dots_1236 = 0x1002827 /* U+2827 BRAILLE PATTERN DOTS-1236 */ - const val XK_braille_dots_46 = 0x1002828 /* U+2828 BRAILLE PATTERN DOTS-46 */ - const val XK_braille_dots_146 = 0x1002829 /* U+2829 BRAILLE PATTERN DOTS-146 */ - const val XK_braille_dots_246 = 0x100282a /* U+282a BRAILLE PATTERN DOTS-246 */ - const val XK_braille_dots_1246 = 0x100282b /* U+282b BRAILLE PATTERN DOTS-1246 */ - const val XK_braille_dots_346 = 0x100282c /* U+282c BRAILLE PATTERN DOTS-346 */ - const val XK_braille_dots_1346 = 0x100282d /* U+282d BRAILLE PATTERN DOTS-1346 */ - const val XK_braille_dots_2346 = 0x100282e /* U+282e BRAILLE PATTERN DOTS-2346 */ - const val XK_braille_dots_12346 = 0x100282f /* U+282f BRAILLE PATTERN DOTS-12346 */ - const val XK_braille_dots_56 = 0x1002830 /* U+2830 BRAILLE PATTERN DOTS-56 */ - const val XK_braille_dots_156 = 0x1002831 /* U+2831 BRAILLE PATTERN DOTS-156 */ - const val XK_braille_dots_256 = 0x1002832 /* U+2832 BRAILLE PATTERN DOTS-256 */ - const val XK_braille_dots_1256 = 0x1002833 /* U+2833 BRAILLE PATTERN DOTS-1256 */ - const val XK_braille_dots_356 = 0x1002834 /* U+2834 BRAILLE PATTERN DOTS-356 */ - const val XK_braille_dots_1356 = 0x1002835 /* U+2835 BRAILLE PATTERN DOTS-1356 */ - const val XK_braille_dots_2356 = 0x1002836 /* U+2836 BRAILLE PATTERN DOTS-2356 */ - const val XK_braille_dots_12356 = 0x1002837 /* U+2837 BRAILLE PATTERN DOTS-12356 */ - const val XK_braille_dots_456 = 0x1002838 /* U+2838 BRAILLE PATTERN DOTS-456 */ - const val XK_braille_dots_1456 = 0x1002839 /* U+2839 BRAILLE PATTERN DOTS-1456 */ - const val XK_braille_dots_2456 = 0x100283a /* U+283a BRAILLE PATTERN DOTS-2456 */ - const val XK_braille_dots_12456 = 0x100283b /* U+283b BRAILLE PATTERN DOTS-12456 */ - const val XK_braille_dots_3456 = 0x100283c /* U+283c BRAILLE PATTERN DOTS-3456 */ - const val XK_braille_dots_13456 = 0x100283d /* U+283d BRAILLE PATTERN DOTS-13456 */ - const val XK_braille_dots_23456 = 0x100283e /* U+283e BRAILLE PATTERN DOTS-23456 */ - const val XK_braille_dots_123456 = 0x100283f /* U+283f BRAILLE PATTERN DOTS-123456 */ - const val XK_braille_dots_7 = 0x1002840 /* U+2840 BRAILLE PATTERN DOTS-7 */ - const val XK_braille_dots_17 = 0x1002841 /* U+2841 BRAILLE PATTERN DOTS-17 */ - const val XK_braille_dots_27 = 0x1002842 /* U+2842 BRAILLE PATTERN DOTS-27 */ - const val XK_braille_dots_127 = 0x1002843 /* U+2843 BRAILLE PATTERN DOTS-127 */ - const val XK_braille_dots_37 = 0x1002844 /* U+2844 BRAILLE PATTERN DOTS-37 */ - const val XK_braille_dots_137 = 0x1002845 /* U+2845 BRAILLE PATTERN DOTS-137 */ - const val XK_braille_dots_237 = 0x1002846 /* U+2846 BRAILLE PATTERN DOTS-237 */ - const val XK_braille_dots_1237 = 0x1002847 /* U+2847 BRAILLE PATTERN DOTS-1237 */ - const val XK_braille_dots_47 = 0x1002848 /* U+2848 BRAILLE PATTERN DOTS-47 */ - const val XK_braille_dots_147 = 0x1002849 /* U+2849 BRAILLE PATTERN DOTS-147 */ - const val XK_braille_dots_247 = 0x100284a /* U+284a BRAILLE PATTERN DOTS-247 */ - const val XK_braille_dots_1247 = 0x100284b /* U+284b BRAILLE PATTERN DOTS-1247 */ - const val XK_braille_dots_347 = 0x100284c /* U+284c BRAILLE PATTERN DOTS-347 */ - const val XK_braille_dots_1347 = 0x100284d /* U+284d BRAILLE PATTERN DOTS-1347 */ - const val XK_braille_dots_2347 = 0x100284e /* U+284e BRAILLE PATTERN DOTS-2347 */ - const val XK_braille_dots_12347 = 0x100284f /* U+284f BRAILLE PATTERN DOTS-12347 */ - const val XK_braille_dots_57 = 0x1002850 /* U+2850 BRAILLE PATTERN DOTS-57 */ - const val XK_braille_dots_157 = 0x1002851 /* U+2851 BRAILLE PATTERN DOTS-157 */ - const val XK_braille_dots_257 = 0x1002852 /* U+2852 BRAILLE PATTERN DOTS-257 */ - const val XK_braille_dots_1257 = 0x1002853 /* U+2853 BRAILLE PATTERN DOTS-1257 */ - const val XK_braille_dots_357 = 0x1002854 /* U+2854 BRAILLE PATTERN DOTS-357 */ - const val XK_braille_dots_1357 = 0x1002855 /* U+2855 BRAILLE PATTERN DOTS-1357 */ - const val XK_braille_dots_2357 = 0x1002856 /* U+2856 BRAILLE PATTERN DOTS-2357 */ - const val XK_braille_dots_12357 = 0x1002857 /* U+2857 BRAILLE PATTERN DOTS-12357 */ - const val XK_braille_dots_457 = 0x1002858 /* U+2858 BRAILLE PATTERN DOTS-457 */ - const val XK_braille_dots_1457 = 0x1002859 /* U+2859 BRAILLE PATTERN DOTS-1457 */ - const val XK_braille_dots_2457 = 0x100285a /* U+285a BRAILLE PATTERN DOTS-2457 */ - const val XK_braille_dots_12457 = 0x100285b /* U+285b BRAILLE PATTERN DOTS-12457 */ - const val XK_braille_dots_3457 = 0x100285c /* U+285c BRAILLE PATTERN DOTS-3457 */ - const val XK_braille_dots_13457 = 0x100285d /* U+285d BRAILLE PATTERN DOTS-13457 */ - const val XK_braille_dots_23457 = 0x100285e /* U+285e BRAILLE PATTERN DOTS-23457 */ - const val XK_braille_dots_123457 = 0x100285f /* U+285f BRAILLE PATTERN DOTS-123457 */ - const val XK_braille_dots_67 = 0x1002860 /* U+2860 BRAILLE PATTERN DOTS-67 */ - const val XK_braille_dots_167 = 0x1002861 /* U+2861 BRAILLE PATTERN DOTS-167 */ - const val XK_braille_dots_267 = 0x1002862 /* U+2862 BRAILLE PATTERN DOTS-267 */ - const val XK_braille_dots_1267 = 0x1002863 /* U+2863 BRAILLE PATTERN DOTS-1267 */ - const val XK_braille_dots_367 = 0x1002864 /* U+2864 BRAILLE PATTERN DOTS-367 */ - const val XK_braille_dots_1367 = 0x1002865 /* U+2865 BRAILLE PATTERN DOTS-1367 */ - const val XK_braille_dots_2367 = 0x1002866 /* U+2866 BRAILLE PATTERN DOTS-2367 */ - const val XK_braille_dots_12367 = 0x1002867 /* U+2867 BRAILLE PATTERN DOTS-12367 */ - const val XK_braille_dots_467 = 0x1002868 /* U+2868 BRAILLE PATTERN DOTS-467 */ - const val XK_braille_dots_1467 = 0x1002869 /* U+2869 BRAILLE PATTERN DOTS-1467 */ - const val XK_braille_dots_2467 = 0x100286a /* U+286a BRAILLE PATTERN DOTS-2467 */ - const val XK_braille_dots_12467 = 0x100286b /* U+286b BRAILLE PATTERN DOTS-12467 */ - const val XK_braille_dots_3467 = 0x100286c /* U+286c BRAILLE PATTERN DOTS-3467 */ - const val XK_braille_dots_13467 = 0x100286d /* U+286d BRAILLE PATTERN DOTS-13467 */ - const val XK_braille_dots_23467 = 0x100286e /* U+286e BRAILLE PATTERN DOTS-23467 */ - const val XK_braille_dots_123467 = 0x100286f /* U+286f BRAILLE PATTERN DOTS-123467 */ - const val XK_braille_dots_567 = 0x1002870 /* U+2870 BRAILLE PATTERN DOTS-567 */ - const val XK_braille_dots_1567 = 0x1002871 /* U+2871 BRAILLE PATTERN DOTS-1567 */ - const val XK_braille_dots_2567 = 0x1002872 /* U+2872 BRAILLE PATTERN DOTS-2567 */ - const val XK_braille_dots_12567 = 0x1002873 /* U+2873 BRAILLE PATTERN DOTS-12567 */ - const val XK_braille_dots_3567 = 0x1002874 /* U+2874 BRAILLE PATTERN DOTS-3567 */ - const val XK_braille_dots_13567 = 0x1002875 /* U+2875 BRAILLE PATTERN DOTS-13567 */ - const val XK_braille_dots_23567 = 0x1002876 /* U+2876 BRAILLE PATTERN DOTS-23567 */ - const val XK_braille_dots_123567 = 0x1002877 /* U+2877 BRAILLE PATTERN DOTS-123567 */ - const val XK_braille_dots_4567 = 0x1002878 /* U+2878 BRAILLE PATTERN DOTS-4567 */ - const val XK_braille_dots_14567 = 0x1002879 /* U+2879 BRAILLE PATTERN DOTS-14567 */ - const val XK_braille_dots_24567 = 0x100287a /* U+287a BRAILLE PATTERN DOTS-24567 */ - const val XK_braille_dots_124567 = 0x100287b /* U+287b BRAILLE PATTERN DOTS-124567 */ - const val XK_braille_dots_34567 = 0x100287c /* U+287c BRAILLE PATTERN DOTS-34567 */ - const val XK_braille_dots_134567 = 0x100287d /* U+287d BRAILLE PATTERN DOTS-134567 */ - const val XK_braille_dots_234567 = 0x100287e /* U+287e BRAILLE PATTERN DOTS-234567 */ - const val XK_braille_dots_1234567 = 0x100287f /* U+287f BRAILLE PATTERN DOTS-1234567 */ - const val XK_braille_dots_8 = 0x1002880 /* U+2880 BRAILLE PATTERN DOTS-8 */ - const val XK_braille_dots_18 = 0x1002881 /* U+2881 BRAILLE PATTERN DOTS-18 */ - const val XK_braille_dots_28 = 0x1002882 /* U+2882 BRAILLE PATTERN DOTS-28 */ - const val XK_braille_dots_128 = 0x1002883 /* U+2883 BRAILLE PATTERN DOTS-128 */ - const val XK_braille_dots_38 = 0x1002884 /* U+2884 BRAILLE PATTERN DOTS-38 */ - const val XK_braille_dots_138 = 0x1002885 /* U+2885 BRAILLE PATTERN DOTS-138 */ - const val XK_braille_dots_238 = 0x1002886 /* U+2886 BRAILLE PATTERN DOTS-238 */ - const val XK_braille_dots_1238 = 0x1002887 /* U+2887 BRAILLE PATTERN DOTS-1238 */ - const val XK_braille_dots_48 = 0x1002888 /* U+2888 BRAILLE PATTERN DOTS-48 */ - const val XK_braille_dots_148 = 0x1002889 /* U+2889 BRAILLE PATTERN DOTS-148 */ - const val XK_braille_dots_248 = 0x100288a /* U+288a BRAILLE PATTERN DOTS-248 */ - const val XK_braille_dots_1248 = 0x100288b /* U+288b BRAILLE PATTERN DOTS-1248 */ - const val XK_braille_dots_348 = 0x100288c /* U+288c BRAILLE PATTERN DOTS-348 */ - const val XK_braille_dots_1348 = 0x100288d /* U+288d BRAILLE PATTERN DOTS-1348 */ - const val XK_braille_dots_2348 = 0x100288e /* U+288e BRAILLE PATTERN DOTS-2348 */ - const val XK_braille_dots_12348 = 0x100288f /* U+288f BRAILLE PATTERN DOTS-12348 */ - const val XK_braille_dots_58 = 0x1002890 /* U+2890 BRAILLE PATTERN DOTS-58 */ - const val XK_braille_dots_158 = 0x1002891 /* U+2891 BRAILLE PATTERN DOTS-158 */ - const val XK_braille_dots_258 = 0x1002892 /* U+2892 BRAILLE PATTERN DOTS-258 */ - const val XK_braille_dots_1258 = 0x1002893 /* U+2893 BRAILLE PATTERN DOTS-1258 */ - const val XK_braille_dots_358 = 0x1002894 /* U+2894 BRAILLE PATTERN DOTS-358 */ - const val XK_braille_dots_1358 = 0x1002895 /* U+2895 BRAILLE PATTERN DOTS-1358 */ - const val XK_braille_dots_2358 = 0x1002896 /* U+2896 BRAILLE PATTERN DOTS-2358 */ - const val XK_braille_dots_12358 = 0x1002897 /* U+2897 BRAILLE PATTERN DOTS-12358 */ - const val XK_braille_dots_458 = 0x1002898 /* U+2898 BRAILLE PATTERN DOTS-458 */ - const val XK_braille_dots_1458 = 0x1002899 /* U+2899 BRAILLE PATTERN DOTS-1458 */ - const val XK_braille_dots_2458 = 0x100289a /* U+289a BRAILLE PATTERN DOTS-2458 */ - const val XK_braille_dots_12458 = 0x100289b /* U+289b BRAILLE PATTERN DOTS-12458 */ - const val XK_braille_dots_3458 = 0x100289c /* U+289c BRAILLE PATTERN DOTS-3458 */ - const val XK_braille_dots_13458 = 0x100289d /* U+289d BRAILLE PATTERN DOTS-13458 */ - const val XK_braille_dots_23458 = 0x100289e /* U+289e BRAILLE PATTERN DOTS-23458 */ - const val XK_braille_dots_123458 = 0x100289f /* U+289f BRAILLE PATTERN DOTS-123458 */ - const val XK_braille_dots_68 = 0x10028a0 /* U+28a0 BRAILLE PATTERN DOTS-68 */ - const val XK_braille_dots_168 = 0x10028a1 /* U+28a1 BRAILLE PATTERN DOTS-168 */ - const val XK_braille_dots_268 = 0x10028a2 /* U+28a2 BRAILLE PATTERN DOTS-268 */ - const val XK_braille_dots_1268 = 0x10028a3 /* U+28a3 BRAILLE PATTERN DOTS-1268 */ - const val XK_braille_dots_368 = 0x10028a4 /* U+28a4 BRAILLE PATTERN DOTS-368 */ - const val XK_braille_dots_1368 = 0x10028a5 /* U+28a5 BRAILLE PATTERN DOTS-1368 */ - const val XK_braille_dots_2368 = 0x10028a6 /* U+28a6 BRAILLE PATTERN DOTS-2368 */ - const val XK_braille_dots_12368 = 0x10028a7 /* U+28a7 BRAILLE PATTERN DOTS-12368 */ - const val XK_braille_dots_468 = 0x10028a8 /* U+28a8 BRAILLE PATTERN DOTS-468 */ - const val XK_braille_dots_1468 = 0x10028a9 /* U+28a9 BRAILLE PATTERN DOTS-1468 */ - const val XK_braille_dots_2468 = 0x10028aa /* U+28aa BRAILLE PATTERN DOTS-2468 */ - const val XK_braille_dots_12468 = 0x10028ab /* U+28ab BRAILLE PATTERN DOTS-12468 */ - const val XK_braille_dots_3468 = 0x10028ac /* U+28ac BRAILLE PATTERN DOTS-3468 */ - const val XK_braille_dots_13468 = 0x10028ad /* U+28ad BRAILLE PATTERN DOTS-13468 */ - const val XK_braille_dots_23468 = 0x10028ae /* U+28ae BRAILLE PATTERN DOTS-23468 */ - const val XK_braille_dots_123468 = 0x10028af /* U+28af BRAILLE PATTERN DOTS-123468 */ - const val XK_braille_dots_568 = 0x10028b0 /* U+28b0 BRAILLE PATTERN DOTS-568 */ - const val XK_braille_dots_1568 = 0x10028b1 /* U+28b1 BRAILLE PATTERN DOTS-1568 */ - const val XK_braille_dots_2568 = 0x10028b2 /* U+28b2 BRAILLE PATTERN DOTS-2568 */ - const val XK_braille_dots_12568 = 0x10028b3 /* U+28b3 BRAILLE PATTERN DOTS-12568 */ - const val XK_braille_dots_3568 = 0x10028b4 /* U+28b4 BRAILLE PATTERN DOTS-3568 */ - const val XK_braille_dots_13568 = 0x10028b5 /* U+28b5 BRAILLE PATTERN DOTS-13568 */ - const val XK_braille_dots_23568 = 0x10028b6 /* U+28b6 BRAILLE PATTERN DOTS-23568 */ - const val XK_braille_dots_123568 = 0x10028b7 /* U+28b7 BRAILLE PATTERN DOTS-123568 */ - const val XK_braille_dots_4568 = 0x10028b8 /* U+28b8 BRAILLE PATTERN DOTS-4568 */ - const val XK_braille_dots_14568 = 0x10028b9 /* U+28b9 BRAILLE PATTERN DOTS-14568 */ - const val XK_braille_dots_24568 = 0x10028ba /* U+28ba BRAILLE PATTERN DOTS-24568 */ - const val XK_braille_dots_124568 = 0x10028bb /* U+28bb BRAILLE PATTERN DOTS-124568 */ - const val XK_braille_dots_34568 = 0x10028bc /* U+28bc BRAILLE PATTERN DOTS-34568 */ - const val XK_braille_dots_134568 = 0x10028bd /* U+28bd BRAILLE PATTERN DOTS-134568 */ - const val XK_braille_dots_234568 = 0x10028be /* U+28be BRAILLE PATTERN DOTS-234568 */ - const val XK_braille_dots_1234568 = 0x10028bf /* U+28bf BRAILLE PATTERN DOTS-1234568 */ - const val XK_braille_dots_78 = 0x10028c0 /* U+28c0 BRAILLE PATTERN DOTS-78 */ - const val XK_braille_dots_178 = 0x10028c1 /* U+28c1 BRAILLE PATTERN DOTS-178 */ - const val XK_braille_dots_278 = 0x10028c2 /* U+28c2 BRAILLE PATTERN DOTS-278 */ - const val XK_braille_dots_1278 = 0x10028c3 /* U+28c3 BRAILLE PATTERN DOTS-1278 */ - const val XK_braille_dots_378 = 0x10028c4 /* U+28c4 BRAILLE PATTERN DOTS-378 */ - const val XK_braille_dots_1378 = 0x10028c5 /* U+28c5 BRAILLE PATTERN DOTS-1378 */ - const val XK_braille_dots_2378 = 0x10028c6 /* U+28c6 BRAILLE PATTERN DOTS-2378 */ - const val XK_braille_dots_12378 = 0x10028c7 /* U+28c7 BRAILLE PATTERN DOTS-12378 */ - const val XK_braille_dots_478 = 0x10028c8 /* U+28c8 BRAILLE PATTERN DOTS-478 */ - const val XK_braille_dots_1478 = 0x10028c9 /* U+28c9 BRAILLE PATTERN DOTS-1478 */ - const val XK_braille_dots_2478 = 0x10028ca /* U+28ca BRAILLE PATTERN DOTS-2478 */ - const val XK_braille_dots_12478 = 0x10028cb /* U+28cb BRAILLE PATTERN DOTS-12478 */ - const val XK_braille_dots_3478 = 0x10028cc /* U+28cc BRAILLE PATTERN DOTS-3478 */ - const val XK_braille_dots_13478 = 0x10028cd /* U+28cd BRAILLE PATTERN DOTS-13478 */ - const val XK_braille_dots_23478 = 0x10028ce /* U+28ce BRAILLE PATTERN DOTS-23478 */ - const val XK_braille_dots_123478 = 0x10028cf /* U+28cf BRAILLE PATTERN DOTS-123478 */ - const val XK_braille_dots_578 = 0x10028d0 /* U+28d0 BRAILLE PATTERN DOTS-578 */ - const val XK_braille_dots_1578 = 0x10028d1 /* U+28d1 BRAILLE PATTERN DOTS-1578 */ - const val XK_braille_dots_2578 = 0x10028d2 /* U+28d2 BRAILLE PATTERN DOTS-2578 */ - const val XK_braille_dots_12578 = 0x10028d3 /* U+28d3 BRAILLE PATTERN DOTS-12578 */ - const val XK_braille_dots_3578 = 0x10028d4 /* U+28d4 BRAILLE PATTERN DOTS-3578 */ - const val XK_braille_dots_13578 = 0x10028d5 /* U+28d5 BRAILLE PATTERN DOTS-13578 */ - const val XK_braille_dots_23578 = 0x10028d6 /* U+28d6 BRAILLE PATTERN DOTS-23578 */ - const val XK_braille_dots_123578 = 0x10028d7 /* U+28d7 BRAILLE PATTERN DOTS-123578 */ - const val XK_braille_dots_4578 = 0x10028d8 /* U+28d8 BRAILLE PATTERN DOTS-4578 */ - const val XK_braille_dots_14578 = 0x10028d9 /* U+28d9 BRAILLE PATTERN DOTS-14578 */ - const val XK_braille_dots_24578 = 0x10028da /* U+28da BRAILLE PATTERN DOTS-24578 */ - const val XK_braille_dots_124578 = 0x10028db /* U+28db BRAILLE PATTERN DOTS-124578 */ - const val XK_braille_dots_34578 = 0x10028dc /* U+28dc BRAILLE PATTERN DOTS-34578 */ - const val XK_braille_dots_134578 = 0x10028dd /* U+28dd BRAILLE PATTERN DOTS-134578 */ - const val XK_braille_dots_234578 = 0x10028de /* U+28de BRAILLE PATTERN DOTS-234578 */ - const val XK_braille_dots_1234578 = 0x10028df /* U+28df BRAILLE PATTERN DOTS-1234578 */ - const val XK_braille_dots_678 = 0x10028e0 /* U+28e0 BRAILLE PATTERN DOTS-678 */ - const val XK_braille_dots_1678 = 0x10028e1 /* U+28e1 BRAILLE PATTERN DOTS-1678 */ - const val XK_braille_dots_2678 = 0x10028e2 /* U+28e2 BRAILLE PATTERN DOTS-2678 */ - const val XK_braille_dots_12678 = 0x10028e3 /* U+28e3 BRAILLE PATTERN DOTS-12678 */ - const val XK_braille_dots_3678 = 0x10028e4 /* U+28e4 BRAILLE PATTERN DOTS-3678 */ - const val XK_braille_dots_13678 = 0x10028e5 /* U+28e5 BRAILLE PATTERN DOTS-13678 */ - const val XK_braille_dots_23678 = 0x10028e6 /* U+28e6 BRAILLE PATTERN DOTS-23678 */ - const val XK_braille_dots_123678 = 0x10028e7 /* U+28e7 BRAILLE PATTERN DOTS-123678 */ - const val XK_braille_dots_4678 = 0x10028e8 /* U+28e8 BRAILLE PATTERN DOTS-4678 */ - const val XK_braille_dots_14678 = 0x10028e9 /* U+28e9 BRAILLE PATTERN DOTS-14678 */ - const val XK_braille_dots_24678 = 0x10028ea /* U+28ea BRAILLE PATTERN DOTS-24678 */ - const val XK_braille_dots_124678 = 0x10028eb /* U+28eb BRAILLE PATTERN DOTS-124678 */ - const val XK_braille_dots_34678 = 0x10028ec /* U+28ec BRAILLE PATTERN DOTS-34678 */ - const val XK_braille_dots_134678 = 0x10028ed /* U+28ed BRAILLE PATTERN DOTS-134678 */ - const val XK_braille_dots_234678 = 0x10028ee /* U+28ee BRAILLE PATTERN DOTS-234678 */ - const val XK_braille_dots_1234678 = 0x10028ef /* U+28ef BRAILLE PATTERN DOTS-1234678 */ - const val XK_braille_dots_5678 = 0x10028f0 /* U+28f0 BRAILLE PATTERN DOTS-5678 */ - const val XK_braille_dots_15678 = 0x10028f1 /* U+28f1 BRAILLE PATTERN DOTS-15678 */ - const val XK_braille_dots_25678 = 0x10028f2 /* U+28f2 BRAILLE PATTERN DOTS-25678 */ - const val XK_braille_dots_125678 = 0x10028f3 /* U+28f3 BRAILLE PATTERN DOTS-125678 */ - const val XK_braille_dots_35678 = 0x10028f4 /* U+28f4 BRAILLE PATTERN DOTS-35678 */ - const val XK_braille_dots_135678 = 0x10028f5 /* U+28f5 BRAILLE PATTERN DOTS-135678 */ - const val XK_braille_dots_235678 = 0x10028f6 /* U+28f6 BRAILLE PATTERN DOTS-235678 */ - const val XK_braille_dots_1235678 = 0x10028f7 /* U+28f7 BRAILLE PATTERN DOTS-1235678 */ - const val XK_braille_dots_45678 = 0x10028f8 /* U+28f8 BRAILLE PATTERN DOTS-45678 */ - const val XK_braille_dots_145678 = 0x10028f9 /* U+28f9 BRAILLE PATTERN DOTS-145678 */ - const val XK_braille_dots_245678 = 0x10028fa /* U+28fa BRAILLE PATTERN DOTS-245678 */ - const val XK_braille_dots_1245678 = 0x10028fb /* U+28fb BRAILLE PATTERN DOTS-1245678 */ - const val XK_braille_dots_345678 = 0x10028fc /* U+28fc BRAILLE PATTERN DOTS-345678 */ - const val XK_braille_dots_1345678 = 0x10028fd /* U+28fd BRAILLE PATTERN DOTS-1345678 */ - const val XK_braille_dots_2345678 = 0x10028fe /* U+28fe BRAILLE PATTERN DOTS-2345678 */ - const val XK_braille_dots_12345678 = 0x10028ff /* U+28ff BRAILLE PATTERN DOTS-12345678 */ - // #endif /* XK_BRAILLE */ - - /* - * Sinhala (http://unicode.org/charts/PDF/U0D80.pdf) - * http://www.nongnu.org/sinhala/doc/transliteration/sinhala-transliteration_6.html - */ - - // #ifdef XK_SINHALA - const val XK_Sinh_ng = 0x1000d82 /* U+0D82 SINHALA ANUSVARAYA */ - const val XK_Sinh_h2 = 0x1000d83 /* U+0D83 SINHALA VISARGAYA */ - const val XK_Sinh_a = 0x1000d85 /* U+0D85 SINHALA AYANNA */ - const val XK_Sinh_aa = 0x1000d86 /* U+0D86 SINHALA AAYANNA */ - const val XK_Sinh_ae = 0x1000d87 /* U+0D87 SINHALA AEYANNA */ - const val XK_Sinh_aee = 0x1000d88 /* U+0D88 SINHALA AEEYANNA */ - const val XK_Sinh_i = 0x1000d89 /* U+0D89 SINHALA IYANNA */ - const val XK_Sinh_ii = 0x1000d8a /* U+0D8A SINHALA IIYANNA */ - const val XK_Sinh_u = 0x1000d8b /* U+0D8B SINHALA UYANNA */ - const val XK_Sinh_uu = 0x1000d8c /* U+0D8C SINHALA UUYANNA */ - const val XK_Sinh_ri = 0x1000d8d /* U+0D8D SINHALA IRUYANNA */ - const val XK_Sinh_rii = 0x1000d8e /* U+0D8E SINHALA IRUUYANNA */ - const val XK_Sinh_lu = 0x1000d8f /* U+0D8F SINHALA ILUYANNA */ - const val XK_Sinh_luu = 0x1000d90 /* U+0D90 SINHALA ILUUYANNA */ - const val XK_Sinh_e = 0x1000d91 /* U+0D91 SINHALA EYANNA */ - const val XK_Sinh_ee = 0x1000d92 /* U+0D92 SINHALA EEYANNA */ - const val XK_Sinh_ai = 0x1000d93 /* U+0D93 SINHALA AIYANNA */ - const val XK_Sinh_o = 0x1000d94 /* U+0D94 SINHALA OYANNA */ - const val XK_Sinh_oo = 0x1000d95 /* U+0D95 SINHALA OOYANNA */ - const val XK_Sinh_au = 0x1000d96 /* U+0D96 SINHALA AUYANNA */ - const val XK_Sinh_ka = 0x1000d9a /* U+0D9A SINHALA KAYANNA */ - const val XK_Sinh_kha = 0x1000d9b /* U+0D9B SINHALA MAHA. KAYANNA */ - const val XK_Sinh_ga = 0x1000d9c /* U+0D9C SINHALA GAYANNA */ - const val XK_Sinh_gha = 0x1000d9d /* U+0D9D SINHALA MAHA. GAYANNA */ - const val XK_Sinh_ng2 = 0x1000d9e /* U+0D9E SINHALA KANTAJA NAASIKYAYA */ - const val XK_Sinh_nga = 0x1000d9f /* U+0D9F SINHALA SANYAKA GAYANNA */ - const val XK_Sinh_ca = 0x1000da0 /* U+0DA0 SINHALA CAYANNA */ - const val XK_Sinh_cha = 0x1000da1 /* U+0DA1 SINHALA MAHA. CAYANNA */ - const val XK_Sinh_ja = 0x1000da2 /* U+0DA2 SINHALA JAYANNA */ - const val XK_Sinh_jha = 0x1000da3 /* U+0DA3 SINHALA MAHA. JAYANNA */ - const val XK_Sinh_nya = 0x1000da4 /* U+0DA4 SINHALA TAALUJA NAASIKYAYA */ - const val XK_Sinh_jnya = 0x1000da5 /* U+0DA5 SINHALA TAALUJA SANYOOGA NAASIKYAYA */ - const val XK_Sinh_nja = 0x1000da6 /* U+0DA6 SINHALA SANYAKA JAYANNA */ - const val XK_Sinh_tta = 0x1000da7 /* U+0DA7 SINHALA TTAYANNA */ - const val XK_Sinh_ttha = 0x1000da8 /* U+0DA8 SINHALA MAHA. TTAYANNA */ - const val XK_Sinh_dda = 0x1000da9 /* U+0DA9 SINHALA DDAYANNA */ - const val XK_Sinh_ddha = 0x1000daa /* U+0DAA SINHALA MAHA. DDAYANNA */ - const val XK_Sinh_nna = 0x1000dab /* U+0DAB SINHALA MUURDHAJA NAYANNA */ - const val XK_Sinh_ndda = 0x1000dac /* U+0DAC SINHALA SANYAKA DDAYANNA */ - const val XK_Sinh_tha = 0x1000dad /* U+0DAD SINHALA TAYANNA */ - const val XK_Sinh_thha = 0x1000dae /* U+0DAE SINHALA MAHA. TAYANNA */ - const val XK_Sinh_dha = 0x1000daf /* U+0DAF SINHALA DAYANNA */ - const val XK_Sinh_dhha = 0x1000db0 /* U+0DB0 SINHALA MAHA. DAYANNA */ - const val XK_Sinh_na = 0x1000db1 /* U+0DB1 SINHALA DANTAJA NAYANNA */ - const val XK_Sinh_ndha = 0x1000db3 /* U+0DB3 SINHALA SANYAKA DAYANNA */ - const val XK_Sinh_pa = 0x1000db4 /* U+0DB4 SINHALA PAYANNA */ - const val XK_Sinh_pha = 0x1000db5 /* U+0DB5 SINHALA MAHA. PAYANNA */ - const val XK_Sinh_ba = 0x1000db6 /* U+0DB6 SINHALA BAYANNA */ - const val XK_Sinh_bha = 0x1000db7 /* U+0DB7 SINHALA MAHA. BAYANNA */ - const val XK_Sinh_ma = 0x1000db8 /* U+0DB8 SINHALA MAYANNA */ - const val XK_Sinh_mba = 0x1000db9 /* U+0DB9 SINHALA AMBA BAYANNA */ - const val XK_Sinh_ya = 0x1000dba /* U+0DBA SINHALA YAYANNA */ - const val XK_Sinh_ra = 0x1000dbb /* U+0DBB SINHALA RAYANNA */ - const val XK_Sinh_la = 0x1000dbd /* U+0DBD SINHALA DANTAJA LAYANNA */ - const val XK_Sinh_va = 0x1000dc0 /* U+0DC0 SINHALA VAYANNA */ - const val XK_Sinh_sha = 0x1000dc1 /* U+0DC1 SINHALA TAALUJA SAYANNA */ - const val XK_Sinh_ssha = 0x1000dc2 /* U+0DC2 SINHALA MUURDHAJA SAYANNA */ - const val XK_Sinh_sa = 0x1000dc3 /* U+0DC3 SINHALA DANTAJA SAYANNA */ - const val XK_Sinh_ha = 0x1000dc4 /* U+0DC4 SINHALA HAYANNA */ - const val XK_Sinh_lla = 0x1000dc5 /* U+0DC5 SINHALA MUURDHAJA LAYANNA */ - const val XK_Sinh_fa = 0x1000dc6 /* U+0DC6 SINHALA FAYANNA */ - const val XK_Sinh_al = 0x1000dca /* U+0DCA SINHALA AL-LAKUNA */ - const val XK_Sinh_aa2 = 0x1000dcf /* U+0DCF SINHALA AELA-PILLA */ - const val XK_Sinh_ae2 = 0x1000dd0 /* U+0DD0 SINHALA AEDA-PILLA */ - const val XK_Sinh_aee2 = 0x1000dd1 /* U+0DD1 SINHALA DIGA AEDA-PILLA */ - const val XK_Sinh_i2 = 0x1000dd2 /* U+0DD2 SINHALA IS-PILLA */ - const val XK_Sinh_ii2 = 0x1000dd3 /* U+0DD3 SINHALA DIGA IS-PILLA */ - const val XK_Sinh_u2 = 0x1000dd4 /* U+0DD4 SINHALA PAA-PILLA */ - const val XK_Sinh_uu2 = 0x1000dd6 /* U+0DD6 SINHALA DIGA PAA-PILLA */ - const val XK_Sinh_ru2 = 0x1000dd8 /* U+0DD8 SINHALA GAETTA-PILLA */ - const val XK_Sinh_e2 = 0x1000dd9 /* U+0DD9 SINHALA KOMBUVA */ - const val XK_Sinh_ee2 = 0x1000dda /* U+0DDA SINHALA DIGA KOMBUVA */ - const val XK_Sinh_ai2 = 0x1000ddb /* U+0DDB SINHALA KOMBU DEKA */ - const val XK_Sinh_o2 = 0x1000ddc /* U+0DDC SINHALA KOMBUVA HAA AELA-PILLA*/ - const val XK_Sinh_oo2 = 0x1000ddd /* U+0DDD SINHALA KOMBUVA HAA DIGA AELA-PILLA*/ - const val XK_Sinh_au2 = 0x1000dde /* U+0DDE SINHALA KOMBUVA HAA GAYANUKITTA */ - const val XK_Sinh_lu2 = 0x1000ddf /* U+0DDF SINHALA GAYANUKITTA */ - const val XK_Sinh_ruu2 = 0x1000df2 /* U+0DF2 SINHALA DIGA GAETTA-PILLA */ - const val XK_Sinh_luu2 = 0x1000df3 /* U+0DF3 SINHALA DIGA GAYANUKITTA */ - const val XK_Sinh_kunddaliya = 0x1000df4 /* U+0DF4 SINHALA KUNDDALIYA */ - // #endif /* XK_SINHALA */ - - /* - * XFree86 Extensions - */ - const val XF86XK_AudioLowerVolume = 0x1008FF11 - const val XF86XK_AudioRaiseVolume = 0x1008FF13 - const val XF86XK_AudioMute = 0x1008FF12 -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymAndroid.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymAndroid.kt deleted file mode 100644 index 6d62087..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymAndroid.kt +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -import android.view.KeyEvent - -/** - * Implements mapping between [KeyEvent] key codes & X KeySyms. - */ -object XKeySymAndroid { - - /** - * Returns X KeySym for given [keyCode]. - * Returns 0 if no mapping is found. - */ - fun getKeySymForAndroidKeyCode(keyCode: Int): Int { - if (keyCode >= 0 && keyCode < AndroidKeyCodeToXKeySym.size) - return AndroidKeyCodeToXKeySym[keyCode] - else - return 0 - } - - fun updateKeyMap(keyCode: Int, xKeySym: Int) { - if (keyCode >= 0 && keyCode < AndroidKeyCodeToXKeySym.size) - AndroidKeyCodeToXKeySym[keyCode] = xKeySym - } - - /** - * Lookup table for X KeySym. - * - * Each index represents a keycode from [KeyEvent] and - * value at that index represents the corresponding X KeySym. - */ - private val AndroidKeyCodeToXKeySym = intArrayOf( - 0, // KEYCODE_UNKNOWN = 0 - 0, // KEYCODE_SOFT_LEFT = 1 - 0, // KEYCODE_SOFT_RIGHT = 2 - 0, // KEYCODE_HOME = 3 - 0, // KEYCODE_BACK = 4 - 0, // KEYCODE_CALL = 5 - 0, // KEYCODE_ENDCALL = 6 - XKeySym.XK_0, // KEYCODE_0 = 7 - XKeySym.XK_1, // KEYCODE_1 = 8 - XKeySym.XK_2, // KEYCODE_2 = 9 - XKeySym.XK_3, // KEYCODE_3 = 10 - XKeySym.XK_4, // KEYCODE_4 = 11 - XKeySym.XK_5, // KEYCODE_5 = 12 - XKeySym.XK_6, // KEYCODE_6 = 13 - XKeySym.XK_7, // KEYCODE_7 = 14 - XKeySym.XK_8, // KEYCODE_8 = 15 - XKeySym.XK_9, // KEYCODE_9 = 16 - XKeySym.XK_asterisk, // KEYCODE_STAR = 17 - XKeySym.XK_numbersign, // KEYCODE_POUND = 18 - XKeySym.XK_Up, // KEYCODE_DPAD_UP = 19 - XKeySym.XK_Down, // KEYCODE_DPAD_DOWN = 20 - XKeySym.XK_Left, // KEYCODE_DPAD_LEFT = 21 - XKeySym.XK_Right, // KEYCODE_DPAD_RIGHT = 22 - 0, // KEYCODE_DPAD_CENTER = 23 - XKeySym.XF86XK_AudioRaiseVolume, // KEYCODE_VOLUME_UP = 24 - XKeySym.XF86XK_AudioLowerVolume, // KEYCODE_VOLUME_DOWN = 25 - 0, // KEYCODE_POWER = 26 - 0, // KEYCODE_CAMERA = 27 - 0, // KEYCODE_CLEAR = 28 - XKeySym.XK_a, // KEYCODE_A = 29 - XKeySym.XK_b, // KEYCODE_B = 30 - XKeySym.XK_c, // KEYCODE_C = 31 - XKeySym.XK_d, // KEYCODE_D = 32 - XKeySym.XK_e, // KEYCODE_E = 33 - XKeySym.XK_f, // KEYCODE_F = 34 - XKeySym.XK_g, // KEYCODE_G = 35 - XKeySym.XK_h, // KEYCODE_H = 36 - XKeySym.XK_i, // KEYCODE_I = 37 - XKeySym.XK_j, // KEYCODE_J = 38 - XKeySym.XK_k, // KEYCODE_K = 39 - XKeySym.XK_l, // KEYCODE_L = 40 - XKeySym.XK_m, // KEYCODE_M = 41 - XKeySym.XK_n, // KEYCODE_N = 42 - XKeySym.XK_o, // KEYCODE_O = 43 - XKeySym.XK_p, // KEYCODE_P = 44 - XKeySym.XK_q, // KEYCODE_Q = 45 - XKeySym.XK_r, // KEYCODE_R = 46 - XKeySym.XK_s, // KEYCODE_S = 47 - XKeySym.XK_t, // KEYCODE_T = 48 - XKeySym.XK_u, // KEYCODE_U = 49 - XKeySym.XK_v, // KEYCODE_V = 50 - XKeySym.XK_w, // KEYCODE_W = 51 - XKeySym.XK_x, // KEYCODE_X = 52 - XKeySym.XK_y, // KEYCODE_Y = 53 - XKeySym.XK_z, // KEYCODE_Z = 54 - XKeySym.XK_comma, // KEYCODE_COMMA = 55 - XKeySym.XK_period, // KEYCODE_PERIOD = 56 - XKeySym.XK_Alt_L, // KEYCODE_ALT_LEFT = 57 - XKeySym.XK_Alt_R, // KEYCODE_ALT_RIGHT = 58 - XKeySym.XK_Shift_L, // KEYCODE_SHIFT_LEFT = 59 - XKeySym.XK_Shift_R, // KEYCODE_SHIFT_RIGHT = 60 - XKeySym.XK_Tab, // KEYCODE_TAB = 61 - XKeySym.XK_space, // KEYCODE_SPACE = 62 - 0, // KEYCODE_SYM = 63 - 0, // KEYCODE_EXPLORER = 64 - 0, // KEYCODE_ENVELOPE = 65 - XKeySym.XK_Return, // KEYCODE_ENTER = 66 - XKeySym.XK_BackSpace, // KEYCODE_DEL = 67 - XKeySym.XK_grave, // KEYCODE_GRAVE = 68 - XKeySym.XK_minus, // KEYCODE_MINUS = 69 - XKeySym.XK_equal, // KEYCODE_EQUALS = 70 - XKeySym.XK_bracketleft, // KEYCODE_LEFT_BRACKET = 71 - XKeySym.XK_bracketright, // KEYCODE_RIGHT_BRACKET = 72 - XKeySym.XK_backslash, // KEYCODE_BACKSLASH = 73 - XKeySym.XK_semicolon, // KEYCODE_SEMICOLON = 74 - XKeySym.XK_apostrophe, // KEYCODE_APOSTROPHE = 75 - XKeySym.XK_slash, // KEYCODE_SLASH = 76 - XKeySym.XK_at, // KEYCODE_AT = 77 - 0, // KEYCODE_NUM = 78 - 0, // KEYCODE_HEADSETHOOK = 79 - 0, // KEYCODE_FOCUS = 80 - XKeySym.XK_plus, // KEYCODE_PLUS = 81 - XKeySym.XK_Menu, // KEYCODE_MENU = 82 - 0, // KEYCODE_NOTIFICATION = 83 - 0, // KEYCODE_SEARCH = 84 - 0, // KEYCODE_MEDIA_PLAY_PAUSE = 85 - 0, // KEYCODE_MEDIA_STOP = 86 - 0, // KEYCODE_MEDIA_NEXT = 87 - 0, // KEYCODE_MEDIA_PREVIOUS = 88 - 0, // KEYCODE_MEDIA_REWIND = 89 - 0, // KEYCODE_MEDIA_FAST_FORWARD = 90 - 0, // KEYCODE_MUTE = 91 - XKeySym.XK_Page_Up, // KEYCODE_PAGE_UP = 92 - XKeySym.XK_Page_Down, // KEYCODE_PAGE_DOWN = 93 - 0, // KEYCODE_PICTSYMBOLS = 94 - 0, // KEYCODE_SWITCH_CHARSET = 95 - 0, // KEYCODE_BUTTON_A = 96 - 0, // KEYCODE_BUTTON_B = 97 - 0, // KEYCODE_BUTTON_C = 98 - 0, // KEYCODE_BUTTON_X = 99 - 0, // KEYCODE_BUTTON_Y = 100 - 0, // KEYCODE_BUTTON_Z = 101 - 0, // KEYCODE_BUTTON_L1 = 102 - 0, // KEYCODE_BUTTON_R1 = 103 - 0, // KEYCODE_BUTTON_L2 = 104 - 0, // KEYCODE_BUTTON_R2 = 105 - 0, // KEYCODE_BUTTON_THUMBL = 106 - 0, // KEYCODE_BUTTON_THUMBR = 107 - 0, // KEYCODE_BUTTON_START = 108 - 0, // KEYCODE_BUTTON_SELECT = 109 - 0, // KEYCODE_BUTTON_MODE = 110 - XKeySym.XK_Escape, // KEYCODE_ESCAPE = 111 - XKeySym.XK_Delete, // KEYCODE_FORWARD_DEL = 112 - XKeySym.XK_Control_L, // KEYCODE_CTRL_LEFT = 113 - XKeySym.XK_Control_R, // KEYCODE_CTRL_RIGHT = 114 - XKeySym.XK_Caps_Lock, // KEYCODE_CAPS_LOCK = 115 - XKeySym.XK_Scroll_Lock, // KEYCODE_SCROLL_LOCK = 116 - XKeySym.XK_Super_L, // KEYCODE_META_LEFT = 117 - XKeySym.XK_Super_R, // KEYCODE_META_RIGHT = 118 - 0, // KEYCODE_FUNCTION = 119 - XKeySym.XK_Sys_Req, // KEYCODE_SYSRQ = 120 - XKeySym.XK_Break, // KEYCODE_BREAK = 121 - XKeySym.XK_Home, // KEYCODE_MOVE_HOME = 122 - XKeySym.XK_End, // KEYCODE_MOVE_END = 123 - XKeySym.XK_Insert, // KEYCODE_INSERT = 124 - 0, // KEYCODE_FORWARD = 125 - 0, // KEYCODE_MEDIA_PLAY = 126 - 0, // KEYCODE_MEDIA_PAUSE = 127 - 0, // KEYCODE_MEDIA_CLOSE = 128 - 0, // KEYCODE_MEDIA_EJECT = 129 - 0, // KEYCODE_MEDIA_RECORD = 130 - XKeySym.XK_F1, // KEYCODE_F1 = 131 - XKeySym.XK_F2, // KEYCODE_F2 = 132 - XKeySym.XK_F3, // KEYCODE_F3 = 133 - XKeySym.XK_F4, // KEYCODE_F4 = 134 - XKeySym.XK_F5, // KEYCODE_F5 = 135 - XKeySym.XK_F6, // KEYCODE_F6 = 136 - XKeySym.XK_F7, // KEYCODE_F7 = 137 - XKeySym.XK_F8, // KEYCODE_F8 = 138 - XKeySym.XK_F9, // KEYCODE_F9 = 139 - XKeySym.XK_F10, // KEYCODE_F10 = 140 - XKeySym.XK_F11, // KEYCODE_F11 = 141 - XKeySym.XK_F12, // KEYCODE_F12 = 142 - XKeySym.XK_Num_Lock, // KEYCODE_NUM_LOCK = 143 - XKeySym.XK_KP_0, // KEYCODE_NUMPAD_0 = 144 - XKeySym.XK_KP_1, // KEYCODE_NUMPAD_1 = 145 - XKeySym.XK_KP_2, // KEYCODE_NUMPAD_2 = 146 - XKeySym.XK_KP_3, // KEYCODE_NUMPAD_3 = 147 - XKeySym.XK_KP_4, // KEYCODE_NUMPAD_4 = 148 - XKeySym.XK_KP_5, // KEYCODE_NUMPAD_5 = 149 - XKeySym.XK_KP_6, // KEYCODE_NUMPAD_6 = 150 - XKeySym.XK_KP_7, // KEYCODE_NUMPAD_7 = 151 - XKeySym.XK_KP_8, // KEYCODE_NUMPAD_8 = 152 - XKeySym.XK_KP_9, // KEYCODE_NUMPAD_9 = 153 - XKeySym.XK_KP_Divide, // KEYCODE_NUMPAD_DIVIDE = 154 - XKeySym.XK_KP_Multiply, // KEYCODE_NUMPAD_MULTIPLY = 155 - XKeySym.XK_KP_Subtract, // KEYCODE_NUMPAD_SUBTRACT = 156 - XKeySym.XK_KP_Add, // KEYCODE_NUMPAD_ADD = 157 - XKeySym.XK_KP_Decimal, // KEYCODE_NUMPAD_DOT = 158 - XKeySym.XK_KP_Separator, // KEYCODE_NUMPAD_COMMA = 159 - XKeySym.XK_KP_Enter, // KEYCODE_NUMPAD_ENTER = 160 - XKeySym.XK_KP_Equal, // KEYCODE_NUMPAD_EQUALS = 161 - 0, // KEYCODE_NUMPAD_LEFT_PAREN = 162 - 0, // KEYCODE_NUMPAD_RIGHT_PAREN = 163 - XKeySym.XF86XK_AudioMute, // KEYCODE_VOLUME_MUTE = 164 - 0, // KEYCODE_INFO = 165 - 0, // KEYCODE_CHANNEL_UP = 166 - 0, // KEYCODE_CHANNEL_DOWN = 167 - 0, // KEYCODE_ZOOM_IN = 168 - 0, // KEYCODE_ZOOM_OUT = 169 - 0, // KEYCODE_TV = 170 - 0, // KEYCODE_WINDOW = 171 - 0, // KEYCODE_GUIDE = 172 - 0, // KEYCODE_DVR = 173 - 0, // KEYCODE_BOOKMARK = 174 - 0, // KEYCODE_CAPTIONS = 175 - 0, // KEYCODE_SETTINGS = 176 - 0, // KEYCODE_TV_POWER = 177 - 0, // KEYCODE_TV_INPUT = 178 - 0, // KEYCODE_STB_POWER = 179 - 0, // KEYCODE_STB_INPUT = 180 - 0, // KEYCODE_AVR_POWER = 181 - 0, // KEYCODE_AVR_INPUT = 182 - 0, // KEYCODE_PROG_RED = 183 - 0, // KEYCODE_PROG_GREEN = 184 - 0, // KEYCODE_PROG_YELLOW = 185 - 0, // KEYCODE_PROG_BLUE = 186 - 0, // KEYCODE_APP_SWITCH = 187 - 0, // KEYCODE_BUTTON_1 = 188 - 0, // KEYCODE_BUTTON_2 = 189 - 0, // KEYCODE_BUTTON_3 = 190 - 0, // KEYCODE_BUTTON_4 = 191 - 0, // KEYCODE_BUTTON_5 = 192 - 0, // KEYCODE_BUTTON_6 = 193 - 0, // KEYCODE_BUTTON_7 = 194 - 0, // KEYCODE_BUTTON_8 = 195 - 0, // KEYCODE_BUTTON_9 = 196 - 0, // KEYCODE_BUTTON_10 = 197 - 0, // KEYCODE_BUTTON_11 = 198 - 0, // KEYCODE_BUTTON_12 = 199 - 0, // KEYCODE_BUTTON_13 = 200 - 0, // KEYCODE_BUTTON_14 = 201 - 0, // KEYCODE_BUTTON_15 = 202 - 0, // KEYCODE_BUTTON_16 = 203 - 0, // KEYCODE_LANGUAGE_SWITCH = 204 - - /* We currently have no mapping for rest of the key codes. - So these are commented to reduce the lookup table size. - - 0, // KEYCODE_MANNER_MODE = 205 - 0, // KEYCODE_3D_MODE = 206 - 0, // KEYCODE_CONTACTS = 207 - 0, // KEYCODE_CALENDAR = 208 - 0, // KEYCODE_MUSIC = 209 - 0, // KEYCODE_CALCULATOR = 210 - 0, // KEYCODE_ZENKAKU_HANKAKU = 211 - 0, // KEYCODE_EISU = 212 - 0, // KEYCODE_MUHENKAN = 213 - 0, // KEYCODE_HENKAN = 214 - 0, // KEYCODE_KATAKANA_HIRAGANA = 215 - 0, // KEYCODE_YEN = 216 - 0, // KEYCODE_RO = 217 - 0, // KEYCODE_KANA = 218 - 0, // KEYCODE_ASSIST = 219 - 0, // KEYCODE_BRIGHTNESS_DOWN = 220 - 0, // KEYCODE_BRIGHTNESS_UP = 221 - 0, // KEYCODE_MEDIA_AUDIO_TRACK = 222 - 0, // KEYCODE_SLEEP = 223 - 0, // KEYCODE_WAKEUP = 224 - 0, // KEYCODE_PAIRING = 225 - 0, // KEYCODE_MEDIA_TOP_MENU = 226 - 0, // KEYCODE_11 = 227 - 0, // KEYCODE_12 = 228 - 0, // KEYCODE_LAST_CHANNEL = 229 - 0, // KEYCODE_TV_DATA_SERVICE = 230 - 0, // KEYCODE_VOICE_ASSIST = 231 - 0, // KEYCODE_TV_RADIO_SERVICE = 232 - 0, // KEYCODE_TV_TELETEXT = 233 - 0, // KEYCODE_TV_NUMBER_ENTRY = 234 - 0, // KEYCODE_TV_TERRESTRIAL_ANALOG = 235 - 0, // KEYCODE_TV_TERRESTRIAL_DIGITAL = 236 - 0, // KEYCODE_TV_SATELLITE = 237 - 0, // KEYCODE_TV_SATELLITE_BS = 238 - 0, // KEYCODE_TV_SATELLITE_CS = 239 - 0, // KEYCODE_TV_SATELLITE_SERVICE = 240 - 0, // KEYCODE_TV_NETWORK = 241 - 0, // KEYCODE_TV_ANTENNA_CABLE = 242 - 0, // KEYCODE_TV_INPUT_HDMI_1 = 243 - 0, // KEYCODE_TV_INPUT_HDMI_2 = 244 - 0, // KEYCODE_TV_INPUT_HDMI_3 = 245 - 0, // KEYCODE_TV_INPUT_HDMI_4 = 246 - 0, // KEYCODE_TV_INPUT_COMPOSITE_1 = 247 - 0, // KEYCODE_TV_INPUT_COMPOSITE_2 = 248 - 0, // KEYCODE_TV_INPUT_COMPONENT_1 = 249 - 0, // KEYCODE_TV_INPUT_COMPONENT_2 = 250 - 0, // KEYCODE_TV_INPUT_VGA_1 = 251 - 0, // KEYCODE_TV_AUDIO_DESCRIPTION = 252 - 0, // KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP = 253 - 0, // KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN = 254 - 0, // KEYCODE_TV_ZOOM_MODE = 255 - 0, // KEYCODE_TV_CONTENTS_MENU = 256 - 0, // KEYCODE_TV_MEDIA_CONTEXT_MENU = 257 - 0, // KEYCODE_TV_TIMER_PROGRAMMING = 258 - 0, // KEYCODE_HELP = 259 - 0, // KEYCODE_NAVIGATE_PREVIOUS = 260 - 0, // KEYCODE_NAVIGATE_NEXT = 261 - 0, // KEYCODE_NAVIGATE_IN = 262 - 0, // KEYCODE_NAVIGATE_OUT = 263 - 0, // KEYCODE_STEM_PRIMARY = 264 - 0, // KEYCODE_STEM_1 = 265 - 0, // KEYCODE_STEM_2 = 266 - 0, // KEYCODE_STEM_3 = 267 - 0, // KEYCODE_DPAD_UP_LEFT = 268 - 0, // KEYCODE_DPAD_DOWN_LEFT = 269 - 0, // KEYCODE_DPAD_UP_RIGHT = 270 - 0, // KEYCODE_DPAD_DOWN_RIGHT = 271 - 0, // KEYCODE_MEDIA_SKIP_FORWARD = 272 - 0, // KEYCODE_MEDIA_SKIP_BACKWARD = 273 - 0, // KEYCODE_MEDIA_STEP_FORWARD = 274 - 0, // KEYCODE_MEDIA_STEP_BACKWARD = 275 - 0, // KEYCODE_SOFT_SLEEP = 276 - 0, // KEYCODE_CUT = 277 - 0, // KEYCODE_COPY = 278 - 0, // KEYCODE_PASTE = 279 - 0, // KEYCODE_SYSTEM_NAVIGATION_UP = 280 - 0, // KEYCODE_SYSTEM_NAVIGATION_DOWN = 281 - 0, // KEYCODE_SYSTEM_NAVIGATION_LEFT = 282 - 0, // KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283 - 0, // KEYCODE_ALL_APPS = 284 - 0, // KEYCODE_REFRESH = 285 - 0, // KEYCODE_THUMBS_UP = 286 - 0, // KEYCODE_THUMBS_DOWN = 287 - 0 // KEYCODE_PROFILE_SWITCH = 288 - - */ - ) -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymUnicode.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymUnicode.kt deleted file mode 100644 index 170c910..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XKeySymUnicode.kt +++ /dev/null @@ -1,819 +0,0 @@ -/* - * Copyright (c) 2021 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -/** - * Implements mapping between Unicode code-points and X KeySyms. - */ -object XKeySymUnicode { - - /** - * Returns X KeySym for [uChar]. - */ - fun getKeySymForUnicodeChar(uChar: Int): Int { - return if (uChar < 0x100) uChar else uChar + 0x01000000 - } - - /** - * Returns legacy X KeySym for given [uChar]. - * Returns 0 if no legacy KeySym is found. - */ - fun getLegacyKeySymForUnicodeChar(uChar: Int): Int { - - // Check if character is outside of our map - if (uChar < UnicodeToLegacyKeysym[0] || uChar > UnicodeToLegacyKeysym[UnicodeToLegacyKeysym.size - 2]) - return 0 - - // Binary Search on the 'first column' of map - var low = 0 - var high = (UnicodeToLegacyKeysym.size / 2) - 1 - - while (low <= high) { - val mid = (low + high) / 2 - val midChar = UnicodeToLegacyKeysym[mid * 2] - - when { - uChar == midChar -> return UnicodeToLegacyKeysym[mid * 2 + 1] - uChar < midChar -> high = mid - 1 - uChar > midChar -> low = mid + 1 - } - } - - return 0 - } - - /** - * This array maps Unicode code points to X KeySyms that were used before the - * introduction of Unicode KeySyms to X Windows System Protocol. - * - * - * Source of the map: https://www.cl.cam.ac.uk/~mgk25/ucs/keysym2ucs.c - * - * - * This array is used as 2D array with stride = 2. - * First column is kept sorted to allow binary search. - */ - private val UnicodeToLegacyKeysym = intArrayOf( - // Unicode, X KeySym - 0x100, 0x3C0, - 0x101, 0x3E0, - 0x102, 0x1C3, - 0x103, 0x1E3, - 0x104, 0x1A1, - 0x105, 0x1B1, - 0x106, 0x1C6, - 0x107, 0x1E6, - 0x108, 0x2C6, - 0x109, 0x2E6, - 0x10A, 0x2C5, - 0x10B, 0x2E5, - 0x10C, 0x1C8, - 0x10D, 0x1E8, - 0x10E, 0x1CF, - 0x10F, 0x1EF, - 0x110, 0x1D0, - 0x111, 0x1F0, - 0x112, 0x3AA, - 0x113, 0x3BA, - 0x116, 0x3CC, - 0x117, 0x3EC, - 0x118, 0x1CA, - 0x119, 0x1EA, - 0x11A, 0x1CC, - 0x11B, 0x1EC, - 0x11C, 0x2D8, - 0x11D, 0x2F8, - 0x11E, 0x2AB, - 0x11F, 0x2BB, - 0x120, 0x2D5, - 0x121, 0x2F5, - 0x122, 0x3AB, - 0x123, 0x3BB, - 0x124, 0x2A6, - 0x125, 0x2B6, - 0x126, 0x2A1, - 0x127, 0x2B1, - 0x128, 0x3A5, - 0x129, 0x3B5, - 0x12A, 0x3CF, - 0x12B, 0x3EF, - 0x12E, 0x3C7, - 0x12F, 0x3E7, - 0x130, 0x2A9, - 0x131, 0x2B9, - 0x134, 0x2AC, - 0x135, 0x2BC, - 0x136, 0x3D3, - 0x137, 0x3F3, - 0x138, 0x3A2, - 0x139, 0x1C5, - 0x13A, 0x1E5, - 0x13B, 0x3A6, - 0x13C, 0x3B6, - 0x13D, 0x1A5, - 0x13E, 0x1B5, - 0x141, 0x1A3, - 0x142, 0x1B3, - 0x143, 0x1D1, - 0x144, 0x1F1, - 0x145, 0x3D1, - 0x146, 0x3F1, - 0x147, 0x1D2, - 0x148, 0x1F2, - 0x14A, 0x3BD, - 0x14B, 0x3BF, - 0x14C, 0x3D2, - 0x14D, 0x3F2, - 0x150, 0x1D5, - 0x151, 0x1F5, - 0x152, 0x13BC, - 0x153, 0x13BD, - 0x154, 0x1C0, - 0x155, 0x1E0, - 0x156, 0x3A3, - 0x157, 0x3B3, - 0x158, 0x1D8, - 0x159, 0x1F8, - 0x15A, 0x1A6, - 0x15B, 0x1B6, - 0x15C, 0x2DE, - 0x15D, 0x2FE, - 0x15E, 0x1AA, - 0x15F, 0x1BA, - 0x160, 0x1A9, - 0x161, 0x1B9, - 0x162, 0x1DE, - 0x163, 0x1FE, - 0x164, 0x1AB, - 0x165, 0x1BB, - 0x166, 0x3AC, - 0x167, 0x3BC, - 0x168, 0x3DD, - 0x169, 0x3FD, - 0x16A, 0x3DE, - 0x16B, 0x3FE, - 0x16C, 0x2DD, - 0x16D, 0x2FD, - 0x16E, 0x1D9, - 0x16F, 0x1F9, - 0x170, 0x1DB, - 0x171, 0x1FB, - 0x172, 0x3D9, - 0x173, 0x3F9, - 0x178, 0x13BE, - 0x179, 0x1AC, - 0x17A, 0x1BC, - 0x17B, 0x1AF, - 0x17C, 0x1BF, - 0x17D, 0x1AE, - 0x17E, 0x1BE, - 0x192, 0x8F6, - 0x2C7, 0x1B7, - 0x2D8, 0x1A2, - 0x2D9, 0x1FF, - 0x2DB, 0x1B2, - 0x2DD, 0x1BD, - 0x385, 0x7AE, - 0x386, 0x7A1, - 0x388, 0x7A2, - 0x389, 0x7A3, - 0x38A, 0x7A4, - 0x38C, 0x7A7, - 0x38E, 0x7A8, - 0x38F, 0x7AB, - 0x390, 0x7B6, - 0x391, 0x7C1, - 0x392, 0x7C2, - 0x393, 0x7C3, - 0x394, 0x7C4, - 0x395, 0x7C5, - 0x396, 0x7C6, - 0x397, 0x7C7, - 0x398, 0x7C8, - 0x399, 0x7C9, - 0x39A, 0x7CA, - 0x39B, 0x7CB, - 0x39C, 0x7CC, - 0x39D, 0x7CD, - 0x39E, 0x7CE, - 0x39F, 0x7CF, - 0x3A0, 0x7D0, - 0x3A1, 0x7D1, - 0x3A3, 0x7D2, - 0x3A4, 0x7D4, - 0x3A5, 0x7D5, - 0x3A6, 0x7D6, - 0x3A7, 0x7D7, - 0x3A8, 0x7D8, - 0x3A9, 0x7D9, - 0x3AA, 0x7A5, - 0x3AB, 0x7A9, - 0x3AC, 0x7B1, - 0x3AD, 0x7B2, - 0x3AE, 0x7B3, - 0x3AF, 0x7B4, - 0x3B0, 0x7BA, - 0x3B1, 0x7E1, - 0x3B2, 0x7E2, - 0x3B3, 0x7E3, - 0x3B4, 0x7E4, - 0x3B5, 0x7E5, - 0x3B6, 0x7E6, - 0x3B7, 0x7E7, - 0x3B8, 0x7E8, - 0x3B9, 0x7E9, - 0x3BA, 0x7EA, - 0x3BB, 0x7EB, - 0x3BC, 0x7EC, - 0x3BD, 0x7ED, - 0x3BE, 0x7EE, - 0x3BF, 0x7EF, - 0x3C0, 0x7F0, - 0x3C1, 0x7F1, - 0x3C2, 0x7F3, - 0x3C3, 0x7F2, - 0x3C4, 0x7F4, - 0x3C5, 0x7F5, - 0x3C6, 0x7F6, - 0x3C7, 0x7F7, - 0x3C8, 0x7F8, - 0x3C9, 0x7F9, - 0x3CA, 0x7B5, - 0x3CB, 0x7B9, - 0x3CC, 0x7B7, - 0x3CD, 0x7B8, - 0x3CE, 0x7BB, - 0x401, 0x6B3, - 0x402, 0x6B1, - 0x403, 0x6B2, - 0x404, 0x6B4, - 0x405, 0x6B5, - 0x406, 0x6B6, - 0x407, 0x6B7, - 0x408, 0x6B8, - 0x409, 0x6B9, - 0x40A, 0x6BA, - 0x40B, 0x6BB, - 0x40C, 0x6BC, - 0x40E, 0x6BE, - 0x40F, 0x6BF, - 0x410, 0x6E1, - 0x411, 0x6E2, - 0x412, 0x6F7, - 0x413, 0x6E7, - 0x414, 0x6E4, - 0x415, 0x6E5, - 0x416, 0x6F6, - 0x417, 0x6FA, - 0x418, 0x6E9, - 0x419, 0x6EA, - 0x41A, 0x6EB, - 0x41B, 0x6EC, - 0x41C, 0x6ED, - 0x41D, 0x6EE, - 0x41E, 0x6EF, - 0x41F, 0x6F0, - 0x420, 0x6F2, - 0x421, 0x6F3, - 0x422, 0x6F4, - 0x423, 0x6F5, - 0x424, 0x6E6, - 0x425, 0x6E8, - 0x426, 0x6E3, - 0x427, 0x6FE, - 0x428, 0x6FB, - 0x429, 0x6FD, - 0x42A, 0x6FF, - 0x42B, 0x6F9, - 0x42C, 0x6F8, - 0x42D, 0x6FC, - 0x42E, 0x6E0, - 0x42F, 0x6F1, - 0x430, 0x6C1, - 0x431, 0x6C2, - 0x432, 0x6D7, - 0x433, 0x6C7, - 0x434, 0x6C4, - 0x435, 0x6C5, - 0x436, 0x6D6, - 0x437, 0x6DA, - 0x438, 0x6C9, - 0x439, 0x6CA, - 0x43A, 0x6CB, - 0x43B, 0x6CC, - 0x43C, 0x6CD, - 0x43D, 0x6CE, - 0x43E, 0x6CF, - 0x43F, 0x6D0, - 0x440, 0x6D2, - 0x441, 0x6D3, - 0x442, 0x6D4, - 0x443, 0x6D5, - 0x444, 0x6C6, - 0x445, 0x6C8, - 0x446, 0x6C3, - 0x447, 0x6DE, - 0x448, 0x6DB, - 0x449, 0x6DD, - 0x44A, 0x6DF, - 0x44B, 0x6D9, - 0x44C, 0x6D8, - 0x44D, 0x6DC, - 0x44E, 0x6C0, - 0x44F, 0x6D1, - 0x451, 0x6A3, - 0x452, 0x6A1, - 0x453, 0x6A2, - 0x454, 0x6A4, - 0x455, 0x6A5, - 0x456, 0x6A6, - 0x457, 0x6A7, - 0x458, 0x6A8, - 0x459, 0x6A9, - 0x45A, 0x6AA, - 0x45B, 0x6AB, - 0x45C, 0x6AC, - 0x45E, 0x6AE, - 0x45F, 0x6AF, - 0x5D0, 0xCE0, - 0x5D1, 0xCE1, - 0x5D2, 0xCE2, - 0x5D3, 0xCE3, - 0x5D4, 0xCE4, - 0x5D5, 0xCE5, - 0x5D6, 0xCE6, - 0x5D7, 0xCE7, - 0x5D8, 0xCE8, - 0x5D9, 0xCE9, - 0x5DA, 0xCEA, - 0x5DB, 0xCEB, - 0x5DC, 0xCEC, - 0x5DD, 0xCED, - 0x5DE, 0xCEE, - 0x5DF, 0xCEF, - 0x5E0, 0xCF0, - 0x5E1, 0xCF1, - 0x5E2, 0xCF2, - 0x5E3, 0xCF3, - 0x5E4, 0xCF4, - 0x5E5, 0xCF5, - 0x5E6, 0xCF6, - 0x5E7, 0xCF7, - 0x5E8, 0xCF8, - 0x5E9, 0xCF9, - 0x5EA, 0xCFA, - 0x60C, 0x5AC, - 0x61B, 0x5BB, - 0x61F, 0x5BF, - 0x621, 0x5C1, - 0x622, 0x5C2, - 0x623, 0x5C3, - 0x624, 0x5C4, - 0x625, 0x5C5, - 0x626, 0x5C6, - 0x627, 0x5C7, - 0x628, 0x5C8, - 0x629, 0x5C9, - 0x62A, 0x5CA, - 0x62B, 0x5CB, - 0x62C, 0x5CC, - 0x62D, 0x5CD, - 0x62E, 0x5CE, - 0x62F, 0x5CF, - 0x630, 0x5D0, - 0x631, 0x5D1, - 0x632, 0x5D2, - 0x633, 0x5D3, - 0x634, 0x5D4, - 0x635, 0x5D5, - 0x636, 0x5D6, - 0x637, 0x5D7, - 0x638, 0x5D8, - 0x639, 0x5D9, - 0x63A, 0x5DA, - 0x640, 0x5E0, - 0x641, 0x5E1, - 0x642, 0x5E2, - 0x643, 0x5E3, - 0x644, 0x5E4, - 0x645, 0x5E5, - 0x646, 0x5E6, - 0x647, 0x5E7, - 0x648, 0x5E8, - 0x649, 0x5E9, - 0x64A, 0x5EA, - 0x64B, 0x5EB, - 0x64C, 0x5EC, - 0x64D, 0x5ED, - 0x64E, 0x5EE, - 0x64F, 0x5EF, - 0x650, 0x5F0, - 0x651, 0x5F1, - 0x652, 0x5F2, - 0xE01, 0xDA1, - 0xE02, 0xDA2, - 0xE03, 0xDA3, - 0xE04, 0xDA4, - 0xE05, 0xDA5, - 0xE06, 0xDA6, - 0xE07, 0xDA7, - 0xE08, 0xDA8, - 0xE09, 0xDA9, - 0xE0A, 0xDAA, - 0xE0B, 0xDAB, - 0xE0C, 0xDAC, - 0xE0D, 0xDAD, - 0xE0E, 0xDAE, - 0xE0F, 0xDAF, - 0xE10, 0xDB0, - 0xE11, 0xDB1, - 0xE12, 0xDB2, - 0xE13, 0xDB3, - 0xE14, 0xDB4, - 0xE15, 0xDB5, - 0xE16, 0xDB6, - 0xE17, 0xDB7, - 0xE18, 0xDB8, - 0xE19, 0xDB9, - 0xE1A, 0xDBA, - 0xE1B, 0xDBB, - 0xE1C, 0xDBC, - 0xE1D, 0xDBD, - 0xE1E, 0xDBE, - 0xE1F, 0xDBF, - 0xE20, 0xDC0, - 0xE21, 0xDC1, - 0xE22, 0xDC2, - 0xE23, 0xDC3, - 0xE24, 0xDC4, - 0xE25, 0xDC5, - 0xE26, 0xDC6, - 0xE27, 0xDC7, - 0xE28, 0xDC8, - 0xE29, 0xDC9, - 0xE2A, 0xDCA, - 0xE2B, 0xDCB, - 0xE2C, 0xDCC, - 0xE2D, 0xDCD, - 0xE2E, 0xDCE, - 0xE2F, 0xDCF, - 0xE30, 0xDD0, - 0xE31, 0xDD1, - 0xE32, 0xDD2, - 0xE33, 0xDD3, - 0xE34, 0xDD4, - 0xE35, 0xDD5, - 0xE36, 0xDD6, - 0xE37, 0xDD7, - 0xE38, 0xDD8, - 0xE39, 0xDD9, - 0xE3A, 0xDDA, - 0xE3F, 0xDDF, - 0xE40, 0xDE0, - 0xE41, 0xDE1, - 0xE42, 0xDE2, - 0xE43, 0xDE3, - 0xE44, 0xDE4, - 0xE45, 0xDE5, - 0xE46, 0xDE6, - 0xE47, 0xDE7, - 0xE48, 0xDE8, - 0xE49, 0xDE9, - 0xE4A, 0xDEA, - 0xE4B, 0xDEB, - 0xE4C, 0xDEC, - 0xE4D, 0xDED, - 0xE50, 0xDF0, - 0xE51, 0xDF1, - 0xE52, 0xDF2, - 0xE53, 0xDF3, - 0xE54, 0xDF4, - 0xE55, 0xDF5, - 0xE56, 0xDF6, - 0xE57, 0xDF7, - 0xE58, 0xDF8, - 0xE59, 0xDF9, - 0x11A8, 0xED4, - 0x11A9, 0xED5, - 0x11AA, 0xED6, - 0x11AB, 0xED7, - 0x11AC, 0xED8, - 0x11AD, 0xED9, - 0x11AE, 0xEDA, - 0x11AF, 0xEDB, - 0x11B0, 0xEDC, - 0x11B1, 0xEDD, - 0x11B2, 0xEDE, - 0x11B3, 0xEDF, - 0x11B4, 0xEE0, - 0x11B5, 0xEE1, - 0x11B6, 0xEE2, - 0x11B7, 0xEE3, - 0x11B8, 0xEE4, - 0x11B9, 0xEE5, - 0x11BA, 0xEE6, - 0x11BB, 0xEE7, - 0x11BC, 0xEE8, - 0x11BD, 0xEE9, - 0x11BE, 0xEEA, - 0x11BF, 0xEEB, - 0x11C0, 0xEEC, - 0x11C1, 0xEED, - 0x11C2, 0xEEE, - 0x11EB, 0xEF8, - 0x11F0, 0xEF9, - 0x11F9, 0xEFA, - 0x2002, 0xAA2, - 0x2003, 0xAA1, - 0x2004, 0xAA3, - 0x2005, 0xAA4, - 0x2007, 0xAA5, - 0x2008, 0xAA6, - 0x2009, 0xAA7, - 0x200A, 0xAA8, - 0x2012, 0xABB, - 0x2013, 0xAAA, - 0x2014, 0xAA9, - 0x2015, 0x7AF, - 0x2017, 0xCDF, - 0x2018, 0xAD0, - 0x2019, 0xAD1, - 0x201A, 0xAFD, - 0x201C, 0xAD2, - 0x201D, 0xAD3, - 0x201E, 0xAFE, - 0x2020, 0xAF1, - 0x2021, 0xAF2, - 0x2022, 0xAE6, - 0x2025, 0xAAF, - 0x2026, 0xAAE, - 0x2032, 0xAD6, - 0x2033, 0xAD7, - 0x2038, 0xAFC, - 0x203E, 0x47E, - 0x20A9, 0xEFF, - 0x20AC, 0x20AC, - 0x20AC, 0x13A4, - 0x2105, 0xAB8, - 0x2116, 0x6B0, - 0x2117, 0xAFB, - 0x211E, 0xAD4, - 0x2122, 0xAC9, - 0x2153, 0xAB0, - 0x2154, 0xAB1, - 0x2155, 0xAB2, - 0x2156, 0xAB3, - 0x2157, 0xAB4, - 0x2158, 0xAB5, - 0x2159, 0xAB6, - 0x215A, 0xAB7, - 0x215B, 0xAC3, - 0x215C, 0xAC4, - 0x215D, 0xAC5, - 0x215E, 0xAC6, - 0x2190, 0x8FB, - 0x2191, 0x8FC, - 0x2192, 0x8FD, - 0x2193, 0x8FE, - 0x21D2, 0x8CE, - 0x21D4, 0x8CD, - 0x2202, 0x8EF, - 0x2207, 0x8C5, - 0x2218, 0xBCA, - 0x221A, 0x8D6, - 0x221D, 0x8C1, - 0x221E, 0x8C2, - 0x2227, 0x8DE, - 0x2227, 0xBA9, - 0x2228, 0x8DF, - 0x2228, 0xBA8, - 0x2229, 0x8DC, - 0x2229, 0xBC3, - 0x222A, 0xBD6, - 0x222A, 0x8DD, - 0x222B, 0x8BF, - 0x2234, 0x8C0, - 0x223C, 0x8C8, - 0x2243, 0x8C9, - 0x2260, 0x8BD, - 0x2261, 0x8CF, - 0x2264, 0x8BC, - 0x2265, 0x8BE, - 0x2282, 0xBDA, - 0x2282, 0x8DA, - 0x2283, 0xBD8, - 0x2283, 0x8DB, - 0x22A2, 0xBDC, - 0x22A3, 0xBFC, - 0x22A4, 0xBCE, - 0x22A5, 0xBC2, - 0x2308, 0xBD3, - 0x230A, 0xBC4, - 0x2315, 0xAFA, - 0x2320, 0x8A4, - 0x2321, 0x8A5, - 0x2329, 0xABC, - 0x232A, 0xABE, - 0x2395, 0xBCC, - 0x239B, 0x8AB, - 0x239D, 0x8AC, - 0x239E, 0x8AD, - 0x23A0, 0x8AE, - 0x23A1, 0x8A7, - 0x23A3, 0x8A8, - 0x23A4, 0x8A9, - 0x23A6, 0x8AA, - 0x23A8, 0x8AF, - 0x23AC, 0x8B0, - 0x23B7, 0x8A1, - 0x23BA, 0x9EF, - 0x23BB, 0x9F0, - 0x23BC, 0x9F2, - 0x23BD, 0x9F3, - 0x2409, 0x9E2, - 0x240A, 0x9E5, - 0x240B, 0x9E9, - 0x240C, 0x9E3, - 0x240D, 0x9E4, - 0x2424, 0x9E8, - 0x2500, 0x9F1, - 0x2500, 0x8A3, - 0x2502, 0x8A6, - 0x2502, 0x9F8, - 0x250C, 0x9EC, - 0x250C, 0x8A2, - 0x2510, 0x9EB, - 0x2514, 0x9ED, - 0x2518, 0x9EA, - 0x251C, 0x9F4, - 0x2524, 0x9F5, - 0x252C, 0x9F7, - 0x2534, 0x9F6, - 0x253C, 0x9EE, - 0x2592, 0x9E1, - 0x25AA, 0xAE7, - 0x25AB, 0xAE1, - 0x25AC, 0xADB, - 0x25AD, 0xAE2, - 0x25AE, 0xADF, - 0x25AF, 0xACF, - 0x25B2, 0xAE8, - 0x25B3, 0xAE3, - 0x25B6, 0xADD, - 0x25B7, 0xACD, - 0x25BC, 0xAE9, - 0x25BD, 0xAE4, - 0x25C0, 0xADC, - 0x25C1, 0xACC, - 0x25C6, 0x9E0, - 0x25CB, 0xBCF, - 0x25CB, 0xACE, - 0x25CF, 0xADE, - 0x25E6, 0xAE0, - 0x2606, 0xAE5, - 0x260E, 0xAF9, - 0x2613, 0xACA, - 0x261C, 0xAEA, - 0x261E, 0xAEB, - 0x2640, 0xAF8, - 0x2642, 0xAF7, - 0x2663, 0xAEC, - 0x2665, 0xAEE, - 0x2666, 0xAED, - 0x266D, 0xAF6, - 0x266F, 0xAF5, - 0x2713, 0xAF3, - 0x2717, 0xAF4, - 0x271D, 0xAD9, - 0x2720, 0xAF0, - 0x3001, 0x4A4, - 0x3002, 0x4A1, - 0x300C, 0x4A2, - 0x300D, 0x4A3, - 0x309B, 0x4DE, - 0x309C, 0x4DF, - 0x30A1, 0x4A7, - 0x30A2, 0x4B1, - 0x30A3, 0x4A8, - 0x30A4, 0x4B2, - 0x30A5, 0x4A9, - 0x30A6, 0x4B3, - 0x30A7, 0x4AA, - 0x30A8, 0x4B4, - 0x30A9, 0x4AB, - 0x30AA, 0x4B5, - 0x30AB, 0x4B6, - 0x30AD, 0x4B7, - 0x30AF, 0x4B8, - 0x30B1, 0x4B9, - 0x30B3, 0x4BA, - 0x30B5, 0x4BB, - 0x30B7, 0x4BC, - 0x30B9, 0x4BD, - 0x30BB, 0x4BE, - 0x30BD, 0x4BF, - 0x30BF, 0x4C0, - 0x30C1, 0x4C1, - 0x30C3, 0x4AF, - 0x30C4, 0x4C2, - 0x30C6, 0x4C3, - 0x30C8, 0x4C4, - 0x30CA, 0x4C5, - 0x30CB, 0x4C6, - 0x30CC, 0x4C7, - 0x30CD, 0x4C8, - 0x30CE, 0x4C9, - 0x30CF, 0x4CA, - 0x30D2, 0x4CB, - 0x30D5, 0x4CC, - 0x30D8, 0x4CD, - 0x30DB, 0x4CE, - 0x30DE, 0x4CF, - 0x30DF, 0x4D0, - 0x30E0, 0x4D1, - 0x30E1, 0x4D2, - 0x30E2, 0x4D3, - 0x30E3, 0x4AC, - 0x30E4, 0x4D4, - 0x30E5, 0x4AD, - 0x30E6, 0x4D5, - 0x30E7, 0x4AE, - 0x30E8, 0x4D6, - 0x30E9, 0x4D7, - 0x30EA, 0x4D8, - 0x30EB, 0x4D9, - 0x30EC, 0x4DA, - 0x30ED, 0x4DB, - 0x30EF, 0x4DC, - 0x30F2, 0x4A6, - 0x30F3, 0x4DD, - 0x30FB, 0x4A5, - 0x30FC, 0x4B0, - 0x3131, 0xEA1, - 0x3132, 0xEA2, - 0x3133, 0xEA3, - 0x3134, 0xEA4, - 0x3135, 0xEA5, - 0x3136, 0xEA6, - 0x3137, 0xEA7, - 0x3138, 0xEA8, - 0x3139, 0xEA9, - 0x313A, 0xEAA, - 0x313B, 0xEAB, - 0x313C, 0xEAC, - 0x313D, 0xEAD, - 0x313E, 0xEAE, - 0x313F, 0xEAF, - 0x3140, 0xEB0, - 0x3141, 0xEB1, - 0x3142, 0xEB2, - 0x3143, 0xEB3, - 0x3144, 0xEB4, - 0x3145, 0xEB5, - 0x3146, 0xEB6, - 0x3147, 0xEB7, - 0x3148, 0xEB8, - 0x3149, 0xEB9, - 0x314A, 0xEBA, - 0x314B, 0xEBB, - 0x314C, 0xEBC, - 0x314D, 0xEBD, - 0x314E, 0xEBE, - 0x314F, 0xEBF, - 0x3150, 0xEC0, - 0x3151, 0xEC1, - 0x3152, 0xEC2, - 0x3153, 0xEC3, - 0x3154, 0xEC4, - 0x3155, 0xEC5, - 0x3156, 0xEC6, - 0x3157, 0xEC7, - 0x3158, 0xEC8, - 0x3159, 0xEC9, - 0x315A, 0xECA, - 0x315B, 0xECB, - 0x315C, 0xECC, - 0x315D, 0xECD, - 0x315E, 0xECE, - 0x315F, 0xECF, - 0x3160, 0xED0, - 0x3161, 0xED1, - 0x3162, 0xED2, - 0x3163, 0xED3, - 0x316D, 0xEEF, - 0x3171, 0xEF0, - 0x3178, 0xEF1, - 0x317F, 0xEF2, - 0x3181, 0xEF3, - 0x3184, 0xEF4, - 0x3186, 0xEF5, - 0x318D, 0xEF6, - 0x318E, 0xEF7 - ) -} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XTKeyCode.kt b/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XTKeyCode.kt deleted file mode 100644 index 3327563..0000000 --- a/android/app/src/main/kotlin/com/gaurav/avnc/vnc/XTKeyCode.kt +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) 2023 Gaurav Ujjwal. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * See COPYING.txt for more details. - */ - -package com.gaurav.avnc.vnc - -/** - * From [1]: - * "An XT keycode is an XT make scancode sequence encoded to fit in a single U32 quantity. - * Single byte XT scancodes with a byte value less than 0x7f are encoded as is. - * 2-byte XT scancodes whose first byte is 0xe0 and second byte is less than 0x7f - * are encoded with the high bit of the first byte set." - * - * [1] https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#qemu-extended-key-event-message - */ -object XTKeyCode { - - /** - * Maps KeyEvent scancodes to XT keycode. - * - * KeyEvent scancodes are simply Linux kernel keycodes. Although Android doesn't - * explicitly states this, it can confirmed by looking through Android source code. - * In any case, all devices tested so far returns Linux keycodes. - * - * Returns 0 if no mapping exist. - */ - fun fromAndroidScancode(scancode: Int) = LinuxToQnum.getOrNull(scancode) ?: 0 - - /** - * This mapping table is generated using output from the following command: - * - * keymap-gen code-map --lang stdc++ keymaps.csv linux qnum - * - * qnum refers to XT keycode described above. - * Source: https://github.com/qemu/keycodemapdb - */ - private val LinuxToQnum = intArrayOf( - 0, /* linux:0 (KEY_RESERVED) -> linux:0 (KEY_RESERVED) -> qnum:None */ - 0x1, /* linux:1 (KEY_ESC) -> linux:1 (KEY_ESC) -> qnum:1 */ - 0x2, /* linux:2 (KEY_1) -> linux:2 (KEY_1) -> qnum:2 */ - 0x3, /* linux:3 (KEY_2) -> linux:3 (KEY_2) -> qnum:3 */ - 0x4, /* linux:4 (KEY_3) -> linux:4 (KEY_3) -> qnum:4 */ - 0x5, /* linux:5 (KEY_4) -> linux:5 (KEY_4) -> qnum:5 */ - 0x6, /* linux:6 (KEY_5) -> linux:6 (KEY_5) -> qnum:6 */ - 0x7, /* linux:7 (KEY_6) -> linux:7 (KEY_6) -> qnum:7 */ - 0x8, /* linux:8 (KEY_7) -> linux:8 (KEY_7) -> qnum:8 */ - 0x9, /* linux:9 (KEY_8) -> linux:9 (KEY_8) -> qnum:9 */ - 0xa, /* linux:10 (KEY_9) -> linux:10 (KEY_9) -> qnum:10 */ - 0xb, /* linux:11 (KEY_0) -> linux:11 (KEY_0) -> qnum:11 */ - 0xc, /* linux:12 (KEY_MINUS) -> linux:12 (KEY_MINUS) -> qnum:12 */ - 0xd, /* linux:13 (KEY_EQUAL) -> linux:13 (KEY_EQUAL) -> qnum:13 */ - 0xe, /* linux:14 (KEY_BACKSPACE) -> linux:14 (KEY_BACKSPACE) -> qnum:14 */ - 0xf, /* linux:15 (KEY_TAB) -> linux:15 (KEY_TAB) -> qnum:15 */ - 0x10, /* linux:16 (KEY_Q) -> linux:16 (KEY_Q) -> qnum:16 */ - 0x11, /* linux:17 (KEY_W) -> linux:17 (KEY_W) -> qnum:17 */ - 0x12, /* linux:18 (KEY_E) -> linux:18 (KEY_E) -> qnum:18 */ - 0x13, /* linux:19 (KEY_R) -> linux:19 (KEY_R) -> qnum:19 */ - 0x14, /* linux:20 (KEY_T) -> linux:20 (KEY_T) -> qnum:20 */ - 0x15, /* linux:21 (KEY_Y) -> linux:21 (KEY_Y) -> qnum:21 */ - 0x16, /* linux:22 (KEY_U) -> linux:22 (KEY_U) -> qnum:22 */ - 0x17, /* linux:23 (KEY_I) -> linux:23 (KEY_I) -> qnum:23 */ - 0x18, /* linux:24 (KEY_O) -> linux:24 (KEY_O) -> qnum:24 */ - 0x19, /* linux:25 (KEY_P) -> linux:25 (KEY_P) -> qnum:25 */ - 0x1a, /* linux:26 (KEY_LEFTBRACE) -> linux:26 (KEY_LEFTBRACE) -> qnum:26 */ - 0x1b, /* linux:27 (KEY_RIGHTBRACE) -> linux:27 (KEY_RIGHTBRACE) -> qnum:27 */ - 0x1c, /* linux:28 (KEY_ENTER) -> linux:28 (KEY_ENTER) -> qnum:28 */ - 0x1d, /* linux:29 (KEY_LEFTCTRL) -> linux:29 (KEY_LEFTCTRL) -> qnum:29 */ - 0x1e, /* linux:30 (KEY_A) -> linux:30 (KEY_A) -> qnum:30 */ - 0x1f, /* linux:31 (KEY_S) -> linux:31 (KEY_S) -> qnum:31 */ - 0x20, /* linux:32 (KEY_D) -> linux:32 (KEY_D) -> qnum:32 */ - 0x21, /* linux:33 (KEY_F) -> linux:33 (KEY_F) -> qnum:33 */ - 0x22, /* linux:34 (KEY_G) -> linux:34 (KEY_G) -> qnum:34 */ - 0x23, /* linux:35 (KEY_H) -> linux:35 (KEY_H) -> qnum:35 */ - 0x24, /* linux:36 (KEY_J) -> linux:36 (KEY_J) -> qnum:36 */ - 0x25, /* linux:37 (KEY_K) -> linux:37 (KEY_K) -> qnum:37 */ - 0x26, /* linux:38 (KEY_L) -> linux:38 (KEY_L) -> qnum:38 */ - 0x27, /* linux:39 (KEY_SEMICOLON) -> linux:39 (KEY_SEMICOLON) -> qnum:39 */ - 0x28, /* linux:40 (KEY_APOSTROPHE) -> linux:40 (KEY_APOSTROPHE) -> qnum:40 */ - 0x29, /* linux:41 (KEY_GRAVE) -> linux:41 (KEY_GRAVE) -> qnum:41 */ - 0x2a, /* linux:42 (KEY_LEFTSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> qnum:42 */ - 0x2b, /* linux:43 (KEY_BACKSLASH) -> linux:43 (KEY_BACKSLASH) -> qnum:43 */ - 0x2c, /* linux:44 (KEY_Z) -> linux:44 (KEY_Z) -> qnum:44 */ - 0x2d, /* linux:45 (KEY_X) -> linux:45 (KEY_X) -> qnum:45 */ - 0x2e, /* linux:46 (KEY_C) -> linux:46 (KEY_C) -> qnum:46 */ - 0x2f, /* linux:47 (KEY_V) -> linux:47 (KEY_V) -> qnum:47 */ - 0x30, /* linux:48 (KEY_B) -> linux:48 (KEY_B) -> qnum:48 */ - 0x31, /* linux:49 (KEY_N) -> linux:49 (KEY_N) -> qnum:49 */ - 0x32, /* linux:50 (KEY_M) -> linux:50 (KEY_M) -> qnum:50 */ - 0x33, /* linux:51 (KEY_COMMA) -> linux:51 (KEY_COMMA) -> qnum:51 */ - 0x34, /* linux:52 (KEY_DOT) -> linux:52 (KEY_DOT) -> qnum:52 */ - 0x35, /* linux:53 (KEY_SLASH) -> linux:53 (KEY_SLASH) -> qnum:53 */ - 0x36, /* linux:54 (KEY_RIGHTSHIFT) -> linux:54 (KEY_RIGHTSHIFT) -> qnum:54 */ - 0x37, /* linux:55 (KEY_KPASTERISK) -> linux:55 (KEY_KPASTERISK) -> qnum:55 */ - 0x38, /* linux:56 (KEY_LEFTALT) -> linux:56 (KEY_LEFTALT) -> qnum:56 */ - 0x39, /* linux:57 (KEY_SPACE) -> linux:57 (KEY_SPACE) -> qnum:57 */ - 0x3a, /* linux:58 (KEY_CAPSLOCK) -> linux:58 (KEY_CAPSLOCK) -> qnum:58 */ - 0x3b, /* linux:59 (KEY_F1) -> linux:59 (KEY_F1) -> qnum:59 */ - 0x3c, /* linux:60 (KEY_F2) -> linux:60 (KEY_F2) -> qnum:60 */ - 0x3d, /* linux:61 (KEY_F3) -> linux:61 (KEY_F3) -> qnum:61 */ - 0x3e, /* linux:62 (KEY_F4) -> linux:62 (KEY_F4) -> qnum:62 */ - 0x3f, /* linux:63 (KEY_F5) -> linux:63 (KEY_F5) -> qnum:63 */ - 0x40, /* linux:64 (KEY_F6) -> linux:64 (KEY_F6) -> qnum:64 */ - 0x41, /* linux:65 (KEY_F7) -> linux:65 (KEY_F7) -> qnum:65 */ - 0x42, /* linux:66 (KEY_F8) -> linux:66 (KEY_F8) -> qnum:66 */ - 0x43, /* linux:67 (KEY_F9) -> linux:67 (KEY_F9) -> qnum:67 */ - 0x44, /* linux:68 (KEY_F10) -> linux:68 (KEY_F10) -> qnum:68 */ - 0x45, /* linux:69 (KEY_NUMLOCK) -> linux:69 (KEY_NUMLOCK) -> qnum:69 */ - 0x46, /* linux:70 (KEY_SCROLLLOCK) -> linux:70 (KEY_SCROLLLOCK) -> qnum:70 */ - 0x47, /* linux:71 (KEY_KP7) -> linux:71 (KEY_KP7) -> qnum:71 */ - 0x48, /* linux:72 (KEY_KP8) -> linux:72 (KEY_KP8) -> qnum:72 */ - 0x49, /* linux:73 (KEY_KP9) -> linux:73 (KEY_KP9) -> qnum:73 */ - 0x4a, /* linux:74 (KEY_KPMINUS) -> linux:74 (KEY_KPMINUS) -> qnum:74 */ - 0x4b, /* linux:75 (KEY_KP4) -> linux:75 (KEY_KP4) -> qnum:75 */ - 0x4c, /* linux:76 (KEY_KP5) -> linux:76 (KEY_KP5) -> qnum:76 */ - 0x4d, /* linux:77 (KEY_KP6) -> linux:77 (KEY_KP6) -> qnum:77 */ - 0x4e, /* linux:78 (KEY_KPPLUS) -> linux:78 (KEY_KPPLUS) -> qnum:78 */ - 0x4f, /* linux:79 (KEY_KP1) -> linux:79 (KEY_KP1) -> qnum:79 */ - 0x50, /* linux:80 (KEY_KP2) -> linux:80 (KEY_KP2) -> qnum:80 */ - 0x51, /* linux:81 (KEY_KP3) -> linux:81 (KEY_KP3) -> qnum:81 */ - 0x52, /* linux:82 (KEY_KP0) -> linux:82 (KEY_KP0) -> qnum:82 */ - 0x53, /* linux:83 (KEY_KPDOT) -> linux:83 (KEY_KPDOT) -> qnum:83 */ - 0x54, /* linux:84 (unnamed) -> linux:84 (unnamed) -> qnum:84 */ - 0x76, /* linux:85 (KEY_ZENKAKUHANKAKU) -> linux:85 (KEY_ZENKAKUHANKAKU) -> qnum:118 */ - 0x56, /* linux:86 (KEY_102ND) -> linux:86 (KEY_102ND) -> qnum:86 */ - 0x57, /* linux:87 (KEY_F11) -> linux:87 (KEY_F11) -> qnum:87 */ - 0x58, /* linux:88 (KEY_F12) -> linux:88 (KEY_F12) -> qnum:88 */ - 0x73, /* linux:89 (KEY_RO) -> linux:89 (KEY_RO) -> qnum:115 */ - 0x78, /* linux:90 (KEY_KATAKANA) -> linux:90 (KEY_KATAKANA) -> qnum:120 */ - 0x77, /* linux:91 (KEY_HIRAGANA) -> linux:91 (KEY_HIRAGANA) -> qnum:119 */ - 0x79, /* linux:92 (KEY_HENKAN) -> linux:92 (KEY_HENKAN) -> qnum:121 */ - 0x70, /* linux:93 (KEY_KATAKANAHIRAGANA) -> linux:93 (KEY_KATAKANAHIRAGANA) -> qnum:112 */ - 0x7b, /* linux:94 (KEY_MUHENKAN) -> linux:94 (KEY_MUHENKAN) -> qnum:123 */ - 0x5c, /* linux:95 (KEY_KPJPCOMMA) -> linux:95 (KEY_KPJPCOMMA) -> qnum:92 */ - 0x9c, /* linux:96 (KEY_KPENTER) -> linux:96 (KEY_KPENTER) -> qnum:156 */ - 0x9d, /* linux:97 (KEY_RIGHTCTRL) -> linux:97 (KEY_RIGHTCTRL) -> qnum:157 */ - 0xb5, /* linux:98 (KEY_KPSLASH) -> linux:98 (KEY_KPSLASH) -> qnum:181 */ - 0x54, /* linux:99 (KEY_SYSRQ) -> linux:99 (KEY_SYSRQ) -> qnum:84 */ - 0xb8, /* linux:100 (KEY_RIGHTALT) -> linux:100 (KEY_RIGHTALT) -> qnum:184 */ - 0x5b, /* linux:101 (KEY_LINEFEED) -> linux:101 (KEY_LINEFEED) -> qnum:91 */ - 0xc7, /* linux:102 (KEY_HOME) -> linux:102 (KEY_HOME) -> qnum:199 */ - 0xc8, /* linux:103 (KEY_UP) -> linux:103 (KEY_UP) -> qnum:200 */ - 0xc9, /* linux:104 (KEY_PAGEUP) -> linux:104 (KEY_PAGEUP) -> qnum:201 */ - 0xcb, /* linux:105 (KEY_LEFT) -> linux:105 (KEY_LEFT) -> qnum:203 */ - 0xcd, /* linux:106 (KEY_RIGHT) -> linux:106 (KEY_RIGHT) -> qnum:205 */ - 0xcf, /* linux:107 (KEY_END) -> linux:107 (KEY_END) -> qnum:207 */ - 0xd0, /* linux:108 (KEY_DOWN) -> linux:108 (KEY_DOWN) -> qnum:208 */ - 0xd1, /* linux:109 (KEY_PAGEDOWN) -> linux:109 (KEY_PAGEDOWN) -> qnum:209 */ - 0xd2, /* linux:110 (KEY_INSERT) -> linux:110 (KEY_INSERT) -> qnum:210 */ - 0xd3, /* linux:111 (KEY_DELETE) -> linux:111 (KEY_DELETE) -> qnum:211 */ - 0xef, /* linux:112 (KEY_MACRO) -> linux:112 (KEY_MACRO) -> qnum:239 */ - 0xa0, /* linux:113 (KEY_MUTE) -> linux:113 (KEY_MUTE) -> qnum:160 */ - 0xae, /* linux:114 (KEY_VOLUMEDOWN) -> linux:114 (KEY_VOLUMEDOWN) -> qnum:174 */ - 0xb0, /* linux:115 (KEY_VOLUMEUP) -> linux:115 (KEY_VOLUMEUP) -> qnum:176 */ - 0xde, /* linux:116 (KEY_POWER) -> linux:116 (KEY_POWER) -> qnum:222 */ - 0x59, /* linux:117 (KEY_KPEQUAL) -> linux:117 (KEY_KPEQUAL) -> qnum:89 */ - 0xce, /* linux:118 (KEY_KPPLUSMINUS) -> linux:118 (KEY_KPPLUSMINUS) -> qnum:206 */ - 0xc6, /* linux:119 (KEY_PAUSE) -> linux:119 (KEY_PAUSE) -> qnum:198 */ - 0x8b, /* linux:120 (KEY_SCALE) -> linux:120 (KEY_SCALE) -> qnum:139 */ - 0x7e, /* linux:121 (KEY_KPCOMMA) -> linux:121 (KEY_KPCOMMA) -> qnum:126 */ - 0x72, /* linux:122 (KEY_HANGEUL) -> linux:122 (KEY_HANGEUL) -> qnum:114 */ - 0x71, /* linux:123 (KEY_HANJA) -> linux:123 (KEY_HANJA) -> qnum:113 */ - 0x7d, /* linux:124 (KEY_YEN) -> linux:124 (KEY_YEN) -> qnum:125 */ - 0xdb, /* linux:125 (KEY_LEFTMETA) -> linux:125 (KEY_LEFTMETA) -> qnum:219 */ - 0xdc, /* linux:126 (KEY_RIGHTMETA) -> linux:126 (KEY_RIGHTMETA) -> qnum:220 */ - 0xdd, /* linux:127 (KEY_COMPOSE) -> linux:127 (KEY_COMPOSE) -> qnum:221 */ - 0xe8, /* linux:128 (KEY_STOP) -> linux:128 (KEY_STOP) -> qnum:232 */ - 0x85, /* linux:129 (KEY_AGAIN) -> linux:129 (KEY_AGAIN) -> qnum:133 */ - 0x86, /* linux:130 (KEY_PROPS) -> linux:130 (KEY_PROPS) -> qnum:134 */ - 0x87, /* linux:131 (KEY_UNDO) -> linux:131 (KEY_UNDO) -> qnum:135 */ - 0x8c, /* linux:132 (KEY_FRONT) -> linux:132 (KEY_FRONT) -> qnum:140 */ - 0xf8, /* linux:133 (KEY_COPY) -> linux:133 (KEY_COPY) -> qnum:248 */ - 0x64, /* linux:134 (KEY_OPEN) -> linux:134 (KEY_OPEN) -> qnum:100 */ - 0x65, /* linux:135 (KEY_PASTE) -> linux:135 (KEY_PASTE) -> qnum:101 */ - 0xc1, /* linux:136 (KEY_FIND) -> linux:136 (KEY_FIND) -> qnum:193 */ - 0xbc, /* linux:137 (KEY_CUT) -> linux:137 (KEY_CUT) -> qnum:188 */ - 0xf5, /* linux:138 (KEY_HELP) -> linux:138 (KEY_HELP) -> qnum:245 */ - 0x9e, /* linux:139 (KEY_MENU) -> linux:139 (KEY_MENU) -> qnum:158 */ - 0xa1, /* linux:140 (KEY_CALC) -> linux:140 (KEY_CALC) -> qnum:161 */ - 0x66, /* linux:141 (KEY_SETUP) -> linux:141 (KEY_SETUP) -> qnum:102 */ - 0xdf, /* linux:142 (KEY_SLEEP) -> linux:142 (KEY_SLEEP) -> qnum:223 */ - 0xe3, /* linux:143 (KEY_WAKEUP) -> linux:143 (KEY_WAKEUP) -> qnum:227 */ - 0x67, /* linux:144 (KEY_FILE) -> linux:144 (KEY_FILE) -> qnum:103 */ - 0x68, /* linux:145 (KEY_SENDFILE) -> linux:145 (KEY_SENDFILE) -> qnum:104 */ - 0x69, /* linux:146 (KEY_DELETEFILE) -> linux:146 (KEY_DELETEFILE) -> qnum:105 */ - 0x93, /* linux:147 (KEY_XFER) -> linux:147 (KEY_XFER) -> qnum:147 */ - 0x9f, /* linux:148 (KEY_PROG1) -> linux:148 (KEY_PROG1) -> qnum:159 */ - 0x97, /* linux:149 (KEY_PROG2) -> linux:149 (KEY_PROG2) -> qnum:151 */ - 0x82, /* linux:150 (KEY_WWW) -> linux:150 (KEY_WWW) -> qnum:130 */ - 0x6a, /* linux:151 (KEY_MSDOS) -> linux:151 (KEY_MSDOS) -> qnum:106 */ - 0x92, /* linux:152 (KEY_SCREENLOCK) -> linux:152 (KEY_SCREENLOCK) -> qnum:146 */ - 0x6b, /* linux:153 (KEY_DIRECTION) -> linux:153 (KEY_DIRECTION) -> qnum:107 */ - 0xa6, /* linux:154 (KEY_CYCLEWINDOWS) -> linux:154 (KEY_CYCLEWINDOWS) -> qnum:166 */ - 0xec, /* linux:155 (KEY_MAIL) -> linux:155 (KEY_MAIL) -> qnum:236 */ - 0xe6, /* linux:156 (KEY_BOOKMARKS) -> linux:156 (KEY_BOOKMARKS) -> qnum:230 */ - 0xeb, /* linux:157 (KEY_COMPUTER) -> linux:157 (KEY_COMPUTER) -> qnum:235 */ - 0xea, /* linux:158 (KEY_BACK) -> linux:158 (KEY_BACK) -> qnum:234 */ - 0xe9, /* linux:159 (KEY_FORWARD) -> linux:159 (KEY_FORWARD) -> qnum:233 */ - 0xa3, /* linux:160 (KEY_CLOSECD) -> linux:160 (KEY_CLOSECD) -> qnum:163 */ - 0x6c, /* linux:161 (KEY_EJECTCD) -> linux:161 (KEY_EJECTCD) -> qnum:108 */ - 0xfd, /* linux:162 (KEY_EJECTCLOSECD) -> linux:162 (KEY_EJECTCLOSECD) -> qnum:253 */ - 0x99, /* linux:163 (KEY_NEXTSONG) -> linux:163 (KEY_NEXTSONG) -> qnum:153 */ - 0xa2, /* linux:164 (KEY_PLAYPAUSE) -> linux:164 (KEY_PLAYPAUSE) -> qnum:162 */ - 0x90, /* linux:165 (KEY_PREVIOUSSONG) -> linux:165 (KEY_PREVIOUSSONG) -> qnum:144 */ - 0xa4, /* linux:166 (KEY_STOPCD) -> linux:166 (KEY_STOPCD) -> qnum:164 */ - 0xb1, /* linux:167 (KEY_RECORD) -> linux:167 (KEY_RECORD) -> qnum:177 */ - 0x98, /* linux:168 (KEY_REWIND) -> linux:168 (KEY_REWIND) -> qnum:152 */ - 0x63, /* linux:169 (KEY_PHONE) -> linux:169 (KEY_PHONE) -> qnum:99 */ - 0, /* linux:170 (KEY_ISO) -> linux:170 (KEY_ISO) -> qnum:None */ - 0x81, /* linux:171 (KEY_CONFIG) -> linux:171 (KEY_CONFIG) -> qnum:129 */ - 0xb2, /* linux:172 (KEY_HOMEPAGE) -> linux:172 (KEY_HOMEPAGE) -> qnum:178 */ - 0xe7, /* linux:173 (KEY_REFRESH) -> linux:173 (KEY_REFRESH) -> qnum:231 */ - 0, /* linux:174 (KEY_EXIT) -> linux:174 (KEY_EXIT) -> qnum:None */ - 0, /* linux:175 (KEY_MOVE) -> linux:175 (KEY_MOVE) -> qnum:None */ - 0x88, /* linux:176 (KEY_EDIT) -> linux:176 (KEY_EDIT) -> qnum:136 */ - 0x75, /* linux:177 (KEY_SCROLLUP) -> linux:177 (KEY_SCROLLUP) -> qnum:117 */ - 0x8f, /* linux:178 (KEY_SCROLLDOWN) -> linux:178 (KEY_SCROLLDOWN) -> qnum:143 */ - 0xf6, /* linux:179 (KEY_KPLEFTPAREN) -> linux:179 (KEY_KPLEFTPAREN) -> qnum:246 */ - 0xfb, /* linux:180 (KEY_KPRIGHTPAREN) -> linux:180 (KEY_KPRIGHTPAREN) -> qnum:251 */ - 0x89, /* linux:181 (KEY_NEW) -> linux:181 (KEY_NEW) -> qnum:137 */ - 0x8a, /* linux:182 (KEY_REDO) -> linux:182 (KEY_REDO) -> qnum:138 */ - 0x5d, /* linux:183 (KEY_F13) -> linux:183 (KEY_F13) -> qnum:93 */ - 0x5e, /* linux:184 (KEY_F14) -> linux:184 (KEY_F14) -> qnum:94 */ - 0x5f, /* linux:185 (KEY_F15) -> linux:185 (KEY_F15) -> qnum:95 */ - 0x55, /* linux:186 (KEY_F16) -> linux:186 (KEY_F16) -> qnum:85 */ - 0x83, /* linux:187 (KEY_F17) -> linux:187 (KEY_F17) -> qnum:131 */ - 0xf7, /* linux:188 (KEY_F18) -> linux:188 (KEY_F18) -> qnum:247 */ - 0x84, /* linux:189 (KEY_F19) -> linux:189 (KEY_F19) -> qnum:132 */ - 0x5a, /* linux:190 (KEY_F20) -> linux:190 (KEY_F20) -> qnum:90 */ - 0x74, /* linux:191 (KEY_F21) -> linux:191 (KEY_F21) -> qnum:116 */ - 0xf9, /* linux:192 (KEY_F22) -> linux:192 (KEY_F22) -> qnum:249 */ - 0x6d, /* linux:193 (KEY_F23) -> linux:193 (KEY_F23) -> qnum:109 */ - 0x6f, /* linux:194 (KEY_F24) -> linux:194 (KEY_F24) -> qnum:111 */ - 0x95, /* linux:195 (unnamed) -> linux:195 (unnamed) -> qnum:149 */ - 0x96, /* linux:196 (unnamed) -> linux:196 (unnamed) -> qnum:150 */ - 0x9a, /* linux:197 (unnamed) -> linux:197 (unnamed) -> qnum:154 */ - 0x9b, /* linux:198 (unnamed) -> linux:198 (unnamed) -> qnum:155 */ - 0xa7, /* linux:199 (unnamed) -> linux:199 (unnamed) -> qnum:167 */ - 0xa8, /* linux:200 (KEY_PLAYCD) -> linux:200 (KEY_PLAYCD) -> qnum:168 */ - 0xa9, /* linux:201 (KEY_PAUSECD) -> linux:201 (KEY_PAUSECD) -> qnum:169 */ - 0xab, /* linux:202 (KEY_PROG3) -> linux:202 (KEY_PROG3) -> qnum:171 */ - 0xac, /* linux:203 (KEY_PROG4) -> linux:203 (KEY_PROG4) -> qnum:172 */ - 0xad, /* linux:204 (KEY_DASHBOARD) -> linux:204 (KEY_DASHBOARD) -> qnum:173 */ - 0xa5, /* linux:205 (KEY_SUSPEND) -> linux:205 (KEY_SUSPEND) -> qnum:165 */ - 0xaf, /* linux:206 (KEY_CLOSE) -> linux:206 (KEY_CLOSE) -> qnum:175 */ - 0xb3, /* linux:207 (KEY_PLAY) -> linux:207 (KEY_PLAY) -> qnum:179 */ - 0xb4, /* linux:208 (KEY_FASTFORWARD) -> linux:208 (KEY_FASTFORWARD) -> qnum:180 */ - 0xb6, /* linux:209 (KEY_BASSBOOST) -> linux:209 (KEY_BASSBOOST) -> qnum:182 */ - 0xb9, /* linux:210 (KEY_PRINT) -> linux:210 (KEY_PRINT) -> qnum:185 */ - 0xba, /* linux:211 (KEY_HP) -> linux:211 (KEY_HP) -> qnum:186 */ - 0xbb, /* linux:212 (KEY_CAMERA) -> linux:212 (KEY_CAMERA) -> qnum:187 */ - 0xbd, /* linux:213 (KEY_SOUND) -> linux:213 (KEY_SOUND) -> qnum:189 */ - 0xbe, /* linux:214 (KEY_QUESTION) -> linux:214 (KEY_QUESTION) -> qnum:190 */ - 0xbf, /* linux:215 (KEY_EMAIL) -> linux:215 (KEY_EMAIL) -> qnum:191 */ - 0xc0, /* linux:216 (KEY_CHAT) -> linux:216 (KEY_CHAT) -> qnum:192 */ - 0xe5, /* linux:217 (KEY_SEARCH) -> linux:217 (KEY_SEARCH) -> qnum:229 */ - 0xc2, /* linux:218 (KEY_CONNECT) -> linux:218 (KEY_CONNECT) -> qnum:194 */ - 0xc3, /* linux:219 (KEY_FINANCE) -> linux:219 (KEY_FINANCE) -> qnum:195 */ - 0xc4, /* linux:220 (KEY_SPORT) -> linux:220 (KEY_SPORT) -> qnum:196 */ - 0xc5, /* linux:221 (KEY_SHOP) -> linux:221 (KEY_SHOP) -> qnum:197 */ - 0x94, /* linux:222 (KEY_ALTERASE) -> linux:222 (KEY_ALTERASE) -> qnum:148 */ - 0xca, /* linux:223 (KEY_CANCEL) -> linux:223 (KEY_CANCEL) -> qnum:202 */ - 0xcc, /* linux:224 (KEY_BRIGHTNESSDOWN) -> linux:224 (KEY_BRIGHTNESSDOWN) -> qnum:204 */ - 0xd4, /* linux:225 (KEY_BRIGHTNESSUP) -> linux:225 (KEY_BRIGHTNESSUP) -> qnum:212 */ - 0xed, /* linux:226 (KEY_MEDIA) -> linux:226 (KEY_MEDIA) -> qnum:237 */ - 0xd6, /* linux:227 (KEY_SWITCHVIDEOMODE) -> linux:227 (KEY_SWITCHVIDEOMODE) -> qnum:214 */ - 0xd7, /* linux:228 (KEY_KBDILLUMTOGGLE) -> linux:228 (KEY_KBDILLUMTOGGLE) -> qnum:215 */ - 0xd8, /* linux:229 (KEY_KBDILLUMDOWN) -> linux:229 (KEY_KBDILLUMDOWN) -> qnum:216 */ - 0xd9, /* linux:230 (KEY_KBDILLUMUP) -> linux:230 (KEY_KBDILLUMUP) -> qnum:217 */ - 0xda, /* linux:231 (KEY_SEND) -> linux:231 (KEY_SEND) -> qnum:218 */ - 0xe4, /* linux:232 (KEY_REPLY) -> linux:232 (KEY_REPLY) -> qnum:228 */ - 0x8e, /* linux:233 (KEY_FORWARDMAIL) -> linux:233 (KEY_FORWARDMAIL) -> qnum:142 */ - 0xd5, /* linux:234 (KEY_SAVE) -> linux:234 (KEY_SAVE) -> qnum:213 */ - 0xf0, /* linux:235 (KEY_DOCUMENTS) -> linux:235 (KEY_DOCUMENTS) -> qnum:240 */ - 0xf1, /* linux:236 (KEY_BATTERY) -> linux:236 (KEY_BATTERY) -> qnum:241 */ - 0xf2, /* linux:237 (KEY_BLUETOOTH) -> linux:237 (KEY_BLUETOOTH) -> qnum:242 */ - 0xf3, /* linux:238 (KEY_WLAN) -> linux:238 (KEY_WLAN) -> qnum:243 */ - 0xf4, /* linux:239 (KEY_UWB) -> linux:239 (KEY_UWB) -> qnum:244 */ - - - /* Rest of the keycodes have no mapping so far - - 0, /* linux:240 (KEY_UNKNOWN) -> linux:240 (KEY_UNKNOWN) -> qnum:None */ - 0, /* linux:241 (KEY_VIDEO_NEXT) -> linux:241 (KEY_VIDEO_NEXT) -> qnum:None */ - 0, /* linux:242 (KEY_VIDEO_PREV) -> linux:242 (KEY_VIDEO_PREV) -> qnum:None */ - 0, /* linux:243 (KEY_BRIGHTNESS_CYCLE) -> linux:243 (KEY_BRIGHTNESS_CYCLE) -> qnum:None */ - 0, /* linux:244 (KEY_BRIGHTNESS_ZERO) -> linux:244 (KEY_BRIGHTNESS_ZERO) -> qnum:None */ - 0, /* linux:245 (KEY_DISPLAY_OFF) -> linux:245 (KEY_DISPLAY_OFF) -> qnum:None */ - 0, /* linux:246 (KEY_WIMAX) -> linux:246 (KEY_WIMAX) -> qnum:None */ - 0, /* linux:247 (unnamed) -> linux:247 (unnamed) -> qnum:None */ - 0, /* linux:248 (unnamed) -> linux:248 (unnamed) -> qnum:None */ - 0, /* linux:249 (unnamed) -> linux:249 (unnamed) -> qnum:None */ - 0, /* linux:250 (unnamed) -> linux:250 (unnamed) -> qnum:None */ - 0, /* linux:251 (unnamed) -> linux:251 (unnamed) -> qnum:None */ - 0, /* linux:252 (unnamed) -> linux:252 (unnamed) -> qnum:None */ - 0, /* linux:253 (unnamed) -> linux:253 (unnamed) -> qnum:None */ - 0, /* linux:254 (unnamed) -> linux:254 (unnamed) -> qnum:None */ - 0, /* linux:255 (unnamed) -> linux:255 (unnamed) -> qnum:None */ - 0, /* linux:256 (BTN_0) -> linux:256 (BTN_0) -> qnum:None */ - 0, /* linux:257 (BTN_1) -> linux:257 (BTN_1) -> qnum:None */ - 0, /* linux:258 (BTN_2) -> linux:258 (BTN_2) -> qnum:None */ - 0, /* linux:259 (BTN_3) -> linux:259 (BTN_3) -> qnum:None */ - 0, /* linux:260 (BTN_4) -> linux:260 (BTN_4) -> qnum:None */ - 0, /* linux:261 (BTN_5) -> linux:261 (BTN_5) -> qnum:None */ - 0, /* linux:262 (BTN_6) -> linux:262 (BTN_6) -> qnum:None */ - 0, /* linux:263 (BTN_7) -> linux:263 (BTN_7) -> qnum:None */ - 0, /* linux:264 (BTN_8) -> linux:264 (BTN_8) -> qnum:None */ - 0, /* linux:265 (BTN_9) -> linux:265 (BTN_9) -> qnum:None */ - 0, /* linux:266 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:267 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:268 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:269 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:270 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:271 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:272 (BTN_LEFT) -> linux:272 (BTN_LEFT) -> qnum:None */ - 0, /* linux:273 (BTN_RIGHT) -> linux:273 (BTN_RIGHT) -> qnum:None */ - 0, /* linux:274 (BTN_MIDDLE) -> linux:274 (BTN_MIDDLE) -> qnum:None */ - 0, /* linux:275 (BTN_SIDE) -> linux:275 (BTN_SIDE) -> qnum:None */ - 0, /* linux:276 (BTN_EXTRA) -> linux:276 (BTN_EXTRA) -> qnum:None */ - 0, /* linux:277 (BTN_FORWARD) -> linux:277 (BTN_FORWARD) -> qnum:None */ - 0, /* linux:278 (BTN_BACK) -> linux:278 (BTN_BACK) -> qnum:None */ - 0, /* linux:279 (BTN_TASK) -> linux:279 (BTN_TASK) -> qnum:None */ - 0, /* linux:280 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:281 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:282 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:283 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:284 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:285 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:286 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:287 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:288 (BTN_TRIGGER) -> linux:288 (BTN_TRIGGER) -> qnum:None */ - 0, /* linux:289 (BTN_THUMB) -> linux:289 (BTN_THUMB) -> qnum:None */ - 0, /* linux:290 (BTN_THUMB2) -> linux:290 (BTN_THUMB2) -> qnum:None */ - 0, /* linux:291 (BTN_TOP) -> linux:291 (BTN_TOP) -> qnum:None */ - 0, /* linux:292 (BTN_TOP2) -> linux:292 (BTN_TOP2) -> qnum:None */ - 0, /* linux:293 (BTN_PINKIE) -> linux:293 (BTN_PINKIE) -> qnum:None */ - 0, /* linux:294 (BTN_BASE) -> linux:294 (BTN_BASE) -> qnum:None */ - 0, /* linux:295 (BTN_BASE2) -> linux:295 (BTN_BASE2) -> qnum:None */ - 0, /* linux:296 (BTN_BASE3) -> linux:296 (BTN_BASE3) -> qnum:None */ - 0, /* linux:297 (BTN_BASE4) -> linux:297 (BTN_BASE4) -> qnum:None */ - 0, /* linux:298 (BTN_BASE5) -> linux:298 (BTN_BASE5) -> qnum:None */ - 0, /* linux:299 (BTN_BASE6) -> linux:299 (BTN_BASE6) -> qnum:None */ - 0, /* linux:300 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:301 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:302 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:303 (BTN_DEAD) -> linux:303 (BTN_DEAD) -> qnum:None */ - 0, /* linux:304 (BTN_A) -> linux:304 (BTN_A) -> qnum:None */ - 0, /* linux:305 (BTN_B) -> linux:305 (BTN_B) -> qnum:None */ - 0, /* linux:306 (BTN_C) -> linux:306 (BTN_C) -> qnum:None */ - 0, /* linux:307 (BTN_X) -> linux:307 (BTN_X) -> qnum:None */ - 0, /* linux:308 (BTN_Y) -> linux:308 (BTN_Y) -> qnum:None */ - 0, /* linux:309 (BTN_Z) -> linux:309 (BTN_Z) -> qnum:None */ - 0, /* linux:310 (BTN_TL) -> linux:310 (BTN_TL) -> qnum:None */ - 0, /* linux:311 (BTN_TR) -> linux:311 (BTN_TR) -> qnum:None */ - 0, /* linux:312 (BTN_TL2) -> linux:312 (BTN_TL2) -> qnum:None */ - 0, /* linux:313 (BTN_TR2) -> linux:313 (BTN_TR2) -> qnum:None */ - 0, /* linux:314 (BTN_SELECT) -> linux:314 (BTN_SELECT) -> qnum:None */ - 0, /* linux:315 (BTN_START) -> linux:315 (BTN_START) -> qnum:None */ - 0, /* linux:316 (BTN_MODE) -> linux:316 (BTN_MODE) -> qnum:None */ - 0, /* linux:317 (BTN_THUMBL) -> linux:317 (BTN_THUMBL) -> qnum:None */ - 0, /* linux:318 (BTN_THUMBR) -> linux:318 (BTN_THUMBR) -> qnum:None */ - 0, /* linux:319 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:320 (BTN_TOOL_PEN) -> linux:320 (BTN_TOOL_PEN) -> qnum:None */ - 0, /* linux:321 (BTN_TOOL_RUBBER) -> linux:321 (BTN_TOOL_RUBBER) -> qnum:None */ - 0, /* linux:322 (BTN_TOOL_BRUSH) -> linux:322 (BTN_TOOL_BRUSH) -> qnum:None */ - 0, /* linux:323 (BTN_TOOL_PENCIL) -> linux:323 (BTN_TOOL_PENCIL) -> qnum:None */ - 0, /* linux:324 (BTN_TOOL_AIRBRUSH) -> linux:324 (BTN_TOOL_AIRBRUSH) -> qnum:None */ - 0, /* linux:325 (BTN_TOOL_FINGER) -> linux:325 (BTN_TOOL_FINGER) -> qnum:None */ - 0, /* linux:326 (BTN_TOOL_MOUSE) -> linux:326 (BTN_TOOL_MOUSE) -> qnum:None */ - 0, /* linux:327 (BTN_TOOL_LENS) -> linux:327 (BTN_TOOL_LENS) -> qnum:None */ - 0, /* linux:328 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:329 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:330 (BTN_TOUCH) -> linux:330 (BTN_TOUCH) -> qnum:None */ - 0, /* linux:331 (BTN_STYLUS) -> linux:331 (BTN_STYLUS) -> qnum:None */ - 0, /* linux:332 (BTN_STYLUS2) -> linux:332 (BTN_STYLUS2) -> qnum:None */ - 0, /* linux:333 (BTN_TOOL_DOUBLETAP) -> linux:333 (BTN_TOOL_DOUBLETAP) -> qnum:None */ - 0, /* linux:334 (BTN_TOOL_TRIPLETAP) -> linux:334 (BTN_TOOL_TRIPLETAP) -> qnum:None */ - 0, /* linux:335 (BTN_TOOL_QUADTAP) -> linux:335 (BTN_TOOL_QUADTAP) -> qnum:None */ - 0, /* linux:336 (BTN_GEAR_DOWN) -> linux:336 (BTN_GEAR_DOWN) -> qnum:None */ - 0, /* linux:337 (BTN_GEAR_UP) -> linux:337 (BTN_GEAR_UP) -> qnum:None */ - 0, /* linux:338 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:339 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:340 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:341 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:342 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:343 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:344 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:345 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:346 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:347 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:348 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:349 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:350 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:351 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:352 (KEY_OK) -> linux:352 (KEY_OK) -> qnum:None */ - 0, /* linux:353 (KEY_SELECT) -> linux:353 (KEY_SELECT) -> qnum:None */ - 0, /* linux:354 (KEY_GOTO) -> linux:354 (KEY_GOTO) -> qnum:None */ - 0, /* linux:355 (KEY_CLEAR) -> linux:355 (KEY_CLEAR) -> qnum:None */ - 0, /* linux:356 (KEY_POWER2) -> linux:356 (KEY_POWER2) -> qnum:None */ - 0, /* linux:357 (KEY_OPTION) -> linux:357 (KEY_OPTION) -> qnum:None */ - 0, /* linux:358 (KEY_INFO) -> linux:358 (KEY_INFO) -> qnum:None */ - 0, /* linux:359 (KEY_TIME) -> linux:359 (KEY_TIME) -> qnum:None */ - 0, /* linux:360 (KEY_VENDOR) -> linux:360 (KEY_VENDOR) -> qnum:None */ - 0, /* linux:361 (KEY_ARCHIVE) -> linux:361 (KEY_ARCHIVE) -> qnum:None */ - 0, /* linux:362 (KEY_PROGRAM) -> linux:362 (KEY_PROGRAM) -> qnum:None */ - 0, /* linux:363 (KEY_CHANNEL) -> linux:363 (KEY_CHANNEL) -> qnum:None */ - 0, /* linux:364 (KEY_FAVORITES) -> linux:364 (KEY_FAVORITES) -> qnum:None */ - 0, /* linux:365 (KEY_EPG) -> linux:365 (KEY_EPG) -> qnum:None */ - 0, /* linux:366 (KEY_PVR) -> linux:366 (KEY_PVR) -> qnum:None */ - 0, /* linux:367 (KEY_MHP) -> linux:367 (KEY_MHP) -> qnum:None */ - 0, /* linux:368 (KEY_LANGUAGE) -> linux:368 (KEY_LANGUAGE) -> qnum:None */ - 0, /* linux:369 (KEY_TITLE) -> linux:369 (KEY_TITLE) -> qnum:None */ - 0, /* linux:370 (KEY_SUBTITLE) -> linux:370 (KEY_SUBTITLE) -> qnum:None */ - 0, /* linux:371 (KEY_ANGLE) -> linux:371 (KEY_ANGLE) -> qnum:None */ - 0, /* linux:372 (KEY_ZOOM) -> linux:372 (KEY_ZOOM) -> qnum:None */ - 0, /* linux:373 (KEY_MODE) -> linux:373 (KEY_MODE) -> qnum:None */ - 0, /* linux:374 (KEY_KEYBOARD) -> linux:374 (KEY_KEYBOARD) -> qnum:None */ - 0, /* linux:375 (KEY_SCREEN) -> linux:375 (KEY_SCREEN) -> qnum:None */ - 0, /* linux:376 (KEY_PC) -> linux:376 (KEY_PC) -> qnum:None */ - 0, /* linux:377 (KEY_TV) -> linux:377 (KEY_TV) -> qnum:None */ - 0, /* linux:378 (KEY_TV2) -> linux:378 (KEY_TV2) -> qnum:None */ - 0, /* linux:379 (KEY_VCR) -> linux:379 (KEY_VCR) -> qnum:None */ - 0, /* linux:380 (KEY_VCR2) -> linux:380 (KEY_VCR2) -> qnum:None */ - 0, /* linux:381 (KEY_SAT) -> linux:381 (KEY_SAT) -> qnum:None */ - 0, /* linux:382 (KEY_SAT2) -> linux:382 (KEY_SAT2) -> qnum:None */ - 0, /* linux:383 (KEY_CD) -> linux:383 (KEY_CD) -> qnum:None */ - 0, /* linux:384 (KEY_TAPE) -> linux:384 (KEY_TAPE) -> qnum:None */ - 0, /* linux:385 (KEY_RADIO) -> linux:385 (KEY_RADIO) -> qnum:None */ - 0, /* linux:386 (KEY_TUNER) -> linux:386 (KEY_TUNER) -> qnum:None */ - 0, /* linux:387 (KEY_PLAYER) -> linux:387 (KEY_PLAYER) -> qnum:None */ - 0, /* linux:388 (KEY_TEXT) -> linux:388 (KEY_TEXT) -> qnum:None */ - 0, /* linux:389 (KEY_DVD) -> linux:389 (KEY_DVD) -> qnum:None */ - 0, /* linux:390 (KEY_AUX) -> linux:390 (KEY_AUX) -> qnum:None */ - 0, /* linux:391 (KEY_MP3) -> linux:391 (KEY_MP3) -> qnum:None */ - 0, /* linux:392 (KEY_AUDIO) -> linux:392 (KEY_AUDIO) -> qnum:None */ - 0, /* linux:393 (KEY_VIDEO) -> linux:393 (KEY_VIDEO) -> qnum:None */ - 0, /* linux:394 (KEY_DIRECTORY) -> linux:394 (KEY_DIRECTORY) -> qnum:None */ - 0, /* linux:395 (KEY_LIST) -> linux:395 (KEY_LIST) -> qnum:None */ - 0, /* linux:396 (KEY_MEMO) -> linux:396 (KEY_MEMO) -> qnum:None */ - 0, /* linux:397 (KEY_CALENDAR) -> linux:397 (KEY_CALENDAR) -> qnum:None */ - 0, /* linux:398 (KEY_RED) -> linux:398 (KEY_RED) -> qnum:None */ - 0, /* linux:399 (KEY_GREEN) -> linux:399 (KEY_GREEN) -> qnum:None */ - 0, /* linux:400 (KEY_YELLOW) -> linux:400 (KEY_YELLOW) -> qnum:None */ - 0, /* linux:401 (KEY_BLUE) -> linux:401 (KEY_BLUE) -> qnum:None */ - 0, /* linux:402 (KEY_CHANNELUP) -> linux:402 (KEY_CHANNELUP) -> qnum:None */ - 0, /* linux:403 (KEY_CHANNELDOWN) -> linux:403 (KEY_CHANNELDOWN) -> qnum:None */ - 0, /* linux:404 (KEY_FIRST) -> linux:404 (KEY_FIRST) -> qnum:None */ - 0, /* linux:405 (KEY_LAST) -> linux:405 (KEY_LAST) -> qnum:None */ - 0, /* linux:406 (KEY_AB) -> linux:406 (KEY_AB) -> qnum:None */ - 0, /* linux:407 (KEY_NEXT) -> linux:407 (KEY_NEXT) -> qnum:None */ - 0, /* linux:408 (KEY_RESTART) -> linux:408 (KEY_RESTART) -> qnum:None */ - 0, /* linux:409 (KEY_SLOW) -> linux:409 (KEY_SLOW) -> qnum:None */ - 0, /* linux:410 (KEY_SHUFFLE) -> linux:410 (KEY_SHUFFLE) -> qnum:None */ - 0, /* linux:411 (KEY_BREAK) -> linux:411 (KEY_BREAK) -> qnum:None */ - 0, /* linux:412 (KEY_PREVIOUS) -> linux:412 (KEY_PREVIOUS) -> qnum:None */ - 0, /* linux:413 (KEY_DIGITS) -> linux:413 (KEY_DIGITS) -> qnum:None */ - 0, /* linux:414 (KEY_TEEN) -> linux:414 (KEY_TEEN) -> qnum:None */ - 0, /* linux:415 (KEY_TWEN) -> linux:415 (KEY_TWEN) -> qnum:None */ - 0, /* linux:416 (KEY_VIDEOPHONE) -> linux:416 (KEY_VIDEOPHONE) -> qnum:None */ - 0, /* linux:417 (KEY_GAMES) -> linux:417 (KEY_GAMES) -> qnum:None */ - 0, /* linux:418 (KEY_ZOOMIN) -> linux:418 (KEY_ZOOMIN) -> qnum:None */ - 0, /* linux:419 (KEY_ZOOMOUT) -> linux:419 (KEY_ZOOMOUT) -> qnum:None */ - 0, /* linux:420 (KEY_ZOOMRESET) -> linux:420 (KEY_ZOOMRESET) -> qnum:None */ - 0, /* linux:421 (KEY_WORDPROCESSOR) -> linux:421 (KEY_WORDPROCESSOR) -> qnum:None */ - 0, /* linux:422 (KEY_EDITOR) -> linux:422 (KEY_EDITOR) -> qnum:None */ - 0, /* linux:423 (KEY_SPREADSHEET) -> linux:423 (KEY_SPREADSHEET) -> qnum:None */ - 0, /* linux:424 (KEY_GRAPHICSEDITOR) -> linux:424 (KEY_GRAPHICSEDITOR) -> qnum:None */ - 0, /* linux:425 (KEY_PRESENTATION) -> linux:425 (KEY_PRESENTATION) -> qnum:None */ - 0, /* linux:426 (KEY_DATABASE) -> linux:426 (KEY_DATABASE) -> qnum:None */ - 0, /* linux:427 (KEY_NEWS) -> linux:427 (KEY_NEWS) -> qnum:None */ - 0, /* linux:428 (KEY_VOICEMAIL) -> linux:428 (KEY_VOICEMAIL) -> qnum:None */ - 0, /* linux:429 (KEY_ADDRESSBOOK) -> linux:429 (KEY_ADDRESSBOOK) -> qnum:None */ - 0, /* linux:430 (KEY_MESSENGER) -> linux:430 (KEY_MESSENGER) -> qnum:None */ - 0, /* linux:431 (KEY_DISPLAYTOGGLE) -> linux:431 (KEY_DISPLAYTOGGLE) -> qnum:None */ - 0, /* linux:432 (KEY_SPELLCHECK) -> linux:432 (KEY_SPELLCHECK) -> qnum:None */ - 0, /* linux:433 (KEY_LOGOFF) -> linux:433 (KEY_LOGOFF) -> qnum:None */ - 0, /* linux:434 (KEY_DOLLAR) -> linux:434 (KEY_DOLLAR) -> qnum:None */ - 0, /* linux:435 (KEY_EURO) -> linux:435 (KEY_EURO) -> qnum:None */ - 0, /* linux:436 (KEY_FRAMEBACK) -> linux:436 (KEY_FRAMEBACK) -> qnum:None */ - 0, /* linux:437 (KEY_FRAMEFORWARD) -> linux:437 (KEY_FRAMEFORWARD) -> qnum:None */ - 0, /* linux:438 (KEY_CONTEXT_MENU) -> linux:438 (KEY_CONTEXT_MENU) -> qnum:None */ - 0, /* linux:439 (KEY_MEDIA_REPEAT) -> linux:439 (KEY_MEDIA_REPEAT) -> qnum:None */ - 0, /* linux:440 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:441 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:442 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:443 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:444 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:445 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:446 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:447 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:448 (KEY_DEL_EOL) -> linux:448 (KEY_DEL_EOL) -> qnum:None */ - 0, /* linux:449 (KEY_DEL_EOS) -> linux:449 (KEY_DEL_EOS) -> qnum:None */ - 0, /* linux:450 (KEY_INS_LINE) -> linux:450 (KEY_INS_LINE) -> qnum:None */ - 0, /* linux:451 (KEY_DEL_LINE) -> linux:451 (KEY_DEL_LINE) -> qnum:None */ - 0, /* linux:452 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:453 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:454 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:455 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:456 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:457 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:458 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:459 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:460 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:461 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:462 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:463 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:464 (KEY_FN) -> linux:464 (KEY_FN) -> qnum:None */ - 0, /* linux:465 (KEY_FN_ESC) -> linux:465 (KEY_FN_ESC) -> qnum:None */ - 0, /* linux:466 (KEY_FN_F1) -> linux:466 (KEY_FN_F1) -> qnum:None */ - 0, /* linux:467 (KEY_FN_F2) -> linux:467 (KEY_FN_F2) -> qnum:None */ - 0, /* linux:468 (KEY_FN_F3) -> linux:468 (KEY_FN_F3) -> qnum:None */ - 0, /* linux:469 (KEY_FN_F4) -> linux:469 (KEY_FN_F4) -> qnum:None */ - 0, /* linux:470 (KEY_FN_F5) -> linux:470 (KEY_FN_F5) -> qnum:None */ - 0, /* linux:471 (KEY_FN_F6) -> linux:471 (KEY_FN_F6) -> qnum:None */ - 0, /* linux:472 (KEY_FN_F7) -> linux:472 (KEY_FN_F7) -> qnum:None */ - 0, /* linux:473 (KEY_FN_F8) -> linux:473 (KEY_FN_F8) -> qnum:None */ - 0, /* linux:474 (KEY_FN_F9) -> linux:474 (KEY_FN_F9) -> qnum:None */ - 0, /* linux:475 (KEY_FN_F10) -> linux:475 (KEY_FN_F10) -> qnum:None */ - 0, /* linux:476 (KEY_FN_F11) -> linux:476 (KEY_FN_F11) -> qnum:None */ - 0, /* linux:477 (KEY_FN_F12) -> linux:477 (KEY_FN_F12) -> qnum:None */ - 0, /* linux:478 (KEY_FN_1) -> linux:478 (KEY_FN_1) -> qnum:None */ - 0, /* linux:479 (KEY_FN_2) -> linux:479 (KEY_FN_2) -> qnum:None */ - 0, /* linux:480 (KEY_FN_D) -> linux:480 (KEY_FN_D) -> qnum:None */ - 0, /* linux:481 (KEY_FN_E) -> linux:481 (KEY_FN_E) -> qnum:None */ - 0, /* linux:482 (KEY_FN_F) -> linux:482 (KEY_FN_F) -> qnum:None */ - 0, /* linux:483 (KEY_FN_S) -> linux:483 (KEY_FN_S) -> qnum:None */ - 0, /* linux:484 (KEY_FN_B) -> linux:484 (KEY_FN_B) -> qnum:None */ - 0, /* linux:485 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:486 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:487 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:488 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:489 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:490 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:491 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:492 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:493 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:494 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:495 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:496 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:497 (KEY_BRL_DOT1) -> linux:497 (KEY_BRL_DOT1) -> qnum:None */ - 0, /* linux:498 (KEY_BRL_DOT2) -> linux:498 (KEY_BRL_DOT2) -> qnum:None */ - 0, /* linux:499 (KEY_BRL_DOT3) -> linux:499 (KEY_BRL_DOT3) -> qnum:None */ - 0, /* linux:500 (KEY_BRL_DOT4) -> linux:500 (KEY_BRL_DOT4) -> qnum:None */ - 0, /* linux:501 (KEY_BRL_DOT5) -> linux:501 (KEY_BRL_DOT5) -> qnum:None */ - 0, /* linux:502 (KEY_BRL_DOT6) -> linux:502 (KEY_BRL_DOT6) -> qnum:None */ - 0, /* linux:503 (KEY_BRL_DOT7) -> linux:503 (KEY_BRL_DOT7) -> qnum:None */ - 0, /* linux:504 (KEY_BRL_DOT8) -> linux:504 (KEY_BRL_DOT8) -> qnum:None */ - 0, /* linux:505 (KEY_BRL_DOT9) -> linux:505 (KEY_BRL_DOT9) -> qnum:None */ - 0, /* linux:506 (KEY_BRL_DOT10) -> linux:506 (KEY_BRL_DOT10) -> qnum:None */ - 0, /* linux:507 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:508 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:509 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:510 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:511 (unnamed) -> linux:None (unnamed) -> qnum:None */ - 0, /* linux:512 (KEY_NUMERIC_0) -> linux:512 (KEY_NUMERIC_0) -> qnum:None */ - 0, /* linux:513 (KEY_NUMERIC_1) -> linux:513 (KEY_NUMERIC_1) -> qnum:None */ - 0, /* linux:514 (KEY_NUMERIC_2) -> linux:514 (KEY_NUMERIC_2) -> qnum:None */ - 0, /* linux:515 (KEY_NUMERIC_3) -> linux:515 (KEY_NUMERIC_3) -> qnum:None */ - 0, /* linux:516 (KEY_NUMERIC_4) -> linux:516 (KEY_NUMERIC_4) -> qnum:None */ - 0, /* linux:517 (KEY_NUMERIC_5) -> linux:517 (KEY_NUMERIC_5) -> qnum:None */ - 0, /* linux:518 (KEY_NUMERIC_6) -> linux:518 (KEY_NUMERIC_6) -> qnum:None */ - 0, /* linux:519 (KEY_NUMERIC_7) -> linux:519 (KEY_NUMERIC_7) -> qnum:None */ - 0, /* linux:520 (KEY_NUMERIC_8) -> linux:520 (KEY_NUMERIC_8) -> qnum:None */ - 0, /* linux:521 (KEY_NUMERIC_9) -> linux:521 (KEY_NUMERIC_9) -> qnum:None */ - 0, /* linux:522 (KEY_NUMERIC_STAR) -> linux:522 (KEY_NUMERIC_STAR) -> qnum:None */ - 0, /* linux:523 (KEY_NUMERIC_POUND) -> linux:523 (KEY_NUMERIC_POUND) -> qnum:None */ - 0, /* linux:524 (KEY_RFKILL) -> linux:524 (KEY_RFKILL) -> qnum:None */ - */ - ) -} \ No newline at end of file diff --git a/android/app/src/main/res/color/control_icon.xml b/android/app/src/main/res/color/control_icon.xml deleted file mode 100644 index 2041289..0000000 --- a/android/app/src/main/res/color/control_icon.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/bg_circular_button.xml b/android/app/src/main/res/drawable/bg_circular_button.xml deleted file mode 100644 index 69aec86..0000000 --- a/android/app/src/main/res/drawable/bg_circular_button.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/bg_frame_view.xml b/android/app/src/main/res/drawable/bg_frame_view.xml deleted file mode 100644 index 964a13d..0000000 --- a/android/app/src/main/res/drawable/bg_frame_view.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/bg_round_rect.xml b/android/app/src/main/res/drawable/bg_round_rect.xml deleted file mode 100644 index 48c4348..0000000 --- a/android/app/src/main/res/drawable/bg_round_rect.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/bg_toggle_button.xml b/android/app/src/main/res/drawable/bg_toggle_button.xml deleted file mode 100644 index 145bf64..0000000 --- a/android/app/src/main/res/drawable/bg_toggle_button.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/bg_urlbar.xml b/android/app/src/main/res/drawable/bg_urlbar.xml deleted file mode 100644 index f06e506..0000000 --- a/android/app/src/main/res/drawable/bg_urlbar.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_arrow_back.xml b/android/app/src/main/res/drawable/ic_arrow_back.xml deleted file mode 100644 index a250af3..0000000 --- a/android/app/src/main/res/drawable/ic_arrow_back.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_bookmark.xml b/android/app/src/main/res/drawable/ic_bookmark.xml deleted file mode 100644 index b718b9d..0000000 --- a/android/app/src/main/res/drawable/ic_bookmark.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_bug.xml b/android/app/src/main/res/drawable/ic_bug.xml deleted file mode 100644 index 53a5e0c..0000000 --- a/android/app/src/main/res/drawable/ic_bug.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_clear.xml b/android/app/src/main/res/drawable/ic_clear.xml deleted file mode 100644 index d619d84..0000000 --- a/android/app/src/main/res/drawable/ic_clear.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_computer.xml b/android/app/src/main/res/drawable/ic_computer.xml deleted file mode 100644 index a9ebb1a..0000000 --- a/android/app/src/main/res/drawable/ic_computer.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_computer_shortcut.xml b/android/app/src/main/res/drawable/ic_computer_shortcut.xml deleted file mode 100644 index c91142f..0000000 --- a/android/app/src/main/res/drawable/ic_computer_shortcut.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_download.xml b/android/app/src/main/res/drawable/ic_download.xml deleted file mode 100644 index 52204b6..0000000 --- a/android/app/src/main/res/drawable/ic_download.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_experimental.xml b/android/app/src/main/res/drawable/ic_experimental.xml deleted file mode 100644 index 6f9d6c1..0000000 --- a/android/app/src/main/res/drawable/ic_experimental.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_file.xml b/android/app/src/main/res/drawable/ic_file.xml deleted file mode 100644 index 72495dd..0000000 --- a/android/app/src/main/res/drawable/ic_file.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_gesture.xml b/android/app/src/main/res/drawable/ic_gesture.xml deleted file mode 100644 index 5932c89..0000000 --- a/android/app/src/main/res/drawable/ic_gesture.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_github.xml b/android/app/src/main/res/drawable/ic_github.xml deleted file mode 100644 index 08a6117..0000000 --- a/android/app/src/main/res/drawable/ic_github.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_gpl.xml b/android/app/src/main/res/drawable/ic_gpl.xml deleted file mode 100644 index a9a1d41..0000000 --- a/android/app/src/main/res/drawable/ic_gpl.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/drawable/ic_help.xml b/android/app/src/main/res/drawable/ic_help.xml deleted file mode 100644 index 68b4eda..0000000 --- a/android/app/src/main/res/drawable/ic_help.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_info.xml b/android/app/src/main/res/drawable/ic_info.xml deleted file mode 100644 index 4a5ddac..0000000 --- a/android/app/src/main/res/drawable/ic_info.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_key.xml b/android/app/src/main/res/drawable/ic_key.xml deleted file mode 100644 index f20820f..0000000 --- a/android/app/src/main/res/drawable/ic_key.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_keyboard.xml b/android/app/src/main/res/drawable/ic_keyboard.xml deleted file mode 100644 index cbfec15..0000000 --- a/android/app/src/main/res/drawable/ic_keyboard.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml b/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml deleted file mode 100644 index 436996f..0000000 --- a/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_keyboard_arrow_left.xml b/android/app/src/main/res/drawable/ic_keyboard_arrow_left.xml deleted file mode 100644 index 96f0115..0000000 --- a/android/app/src/main/res/drawable/ic_keyboard_arrow_left.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_keyboard_arrow_right.xml b/android/app/src/main/res/drawable/ic_keyboard_arrow_right.xml deleted file mode 100644 index 94ebaee..0000000 --- a/android/app/src/main/res/drawable/ic_keyboard_arrow_right.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_keyboard_arrow_up.xml b/android/app/src/main/res/drawable/ic_keyboard_arrow_up.xml deleted file mode 100644 index 9795820..0000000 --- a/android/app/src/main/res/drawable/ic_keyboard_arrow_up.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_keyboard_mini.xml b/android/app/src/main/res/drawable/ic_keyboard_mini.xml deleted file mode 100644 index 8dff512..0000000 --- a/android/app/src/main/res/drawable/ic_keyboard_mini.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_launcher_background.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 55a7e5d..0000000 --- a/android/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index ed173b8..0000000 --- a/android/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - diff --git a/android/app/src/main/res/drawable/ic_launcher_monochrome.xml b/android/app/src/main/res/drawable/ic_launcher_monochrome.xml deleted file mode 100644 index d659c94..0000000 --- a/android/app/src/main/res/drawable/ic_launcher_monochrome.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - diff --git a/android/app/src/main/res/drawable/ic_lightbulb.xml b/android/app/src/main/res/drawable/ic_lightbulb.xml deleted file mode 100644 index 5ec3bde..0000000 --- a/android/app/src/main/res/drawable/ic_lightbulb.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_lock.xml b/android/app/src/main/res/drawable/ic_lock.xml deleted file mode 100644 index 4ec272f..0000000 --- a/android/app/src/main/res/drawable/ic_lock.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_menu.xml b/android/app/src/main/res/drawable/ic_menu.xml deleted file mode 100644 index de66a35..0000000 --- a/android/app/src/main/res/drawable/ic_menu.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_mouse.xml b/android/app/src/main/res/drawable/ic_mouse.xml deleted file mode 100644 index c9ca128..0000000 --- a/android/app/src/main/res/drawable/ic_mouse.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_palette.xml b/android/app/src/main/res/drawable/ic_palette.xml deleted file mode 100644 index 2779b03..0000000 --- a/android/app/src/main/res/drawable/ic_palette.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_password.xml b/android/app/src/main/res/drawable/ic_password.xml deleted file mode 100644 index 1423089..0000000 --- a/android/app/src/main/res/drawable/ic_password.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_person.xml b/android/app/src/main/res/drawable/ic_person.xml deleted file mode 100644 index be808d0..0000000 --- a/android/app/src/main/res/drawable/ic_person.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_plus.xml b/android/app/src/main/res/drawable/ic_plus.xml deleted file mode 100644 index c7ae64c..0000000 --- a/android/app/src/main/res/drawable/ic_plus.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/android/app/src/main/res/drawable/ic_refresh.xml b/android/app/src/main/res/drawable/ic_refresh.xml deleted file mode 100644 index 8aad580..0000000 --- a/android/app/src/main/res/drawable/ic_refresh.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_save.xml b/android/app/src/main/res/drawable/ic_save.xml deleted file mode 100644 index 1a152e6..0000000 --- a/android/app/src/main/res/drawable/ic_save.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_screen_rotation.xml b/android/app/src/main/res/drawable/ic_screen_rotation.xml deleted file mode 100644 index dddec5c..0000000 --- a/android/app/src/main/res/drawable/ic_screen_rotation.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_search.xml b/android/app/src/main/res/drawable/ic_search.xml deleted file mode 100644 index b92a08b..0000000 --- a/android/app/src/main/res/drawable/ic_search.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_settings.xml b/android/app/src/main/res/drawable/ic_settings.xml deleted file mode 100644 index d05850c..0000000 --- a/android/app/src/main/res/drawable/ic_settings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_shield.xml b/android/app/src/main/res/drawable/ic_shield.xml deleted file mode 100644 index f6dbbf0..0000000 --- a/android/app/src/main/res/drawable/ic_shield.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_ssh.xml b/android/app/src/main/res/drawable/ic_ssh.xml deleted file mode 100644 index b20e374..0000000 --- a/android/app/src/main/res/drawable/ic_ssh.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - diff --git a/android/app/src/main/res/drawable/ic_star.xml b/android/app/src/main/res/drawable/ic_star.xml deleted file mode 100644 index a4c675b..0000000 --- a/android/app/src/main/res/drawable/ic_star.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_super_key.xml b/android/app/src/main/res/drawable/ic_super_key.xml deleted file mode 100644 index 3124183..0000000 --- a/android/app/src/main/res/drawable/ic_super_key.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_swap.xml b/android/app/src/main/res/drawable/ic_swap.xml deleted file mode 100644 index 3041271..0000000 --- a/android/app/src/main/res/drawable/ic_swap.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_toggle_more.xml b/android/app/src/main/res/drawable/ic_toggle_more.xml deleted file mode 100644 index 493d57f..0000000 --- a/android/app/src/main/res/drawable/ic_toggle_more.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_toolbar.xml b/android/app/src/main/res/drawable/ic_toolbar.xml deleted file mode 100644 index 3d05110..0000000 --- a/android/app/src/main/res/drawable/ic_toolbar.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - diff --git a/android/app/src/main/res/drawable/ic_tools.xml b/android/app/src/main/res/drawable/ic_tools.xml deleted file mode 100644 index db3d386..0000000 --- a/android/app/src/main/res/drawable/ic_tools.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_upload.xml b/android/app/src/main/res/drawable/ic_upload.xml deleted file mode 100644 index edbbdf9..0000000 --- a/android/app/src/main/res/drawable/ic_upload.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_video.xml b/android/app/src/main/res/drawable/ic_video.xml deleted file mode 100644 index 055871b..0000000 --- a/android/app/src/main/res/drawable/ic_video.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_visibility.xml b/android/app/src/main/res/drawable/ic_visibility.xml deleted file mode 100644 index 6bca848..0000000 --- a/android/app/src/main/res/drawable/ic_visibility.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_warning.xml b/android/app/src/main/res/drawable/ic_warning.xml deleted file mode 100644 index bb070a7..0000000 --- a/android/app/src/main/res/drawable/ic_warning.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_wordmark.xml b/android/app/src/main/res/drawable/ic_wordmark.xml deleted file mode 100644 index 413f6cc..0000000 --- a/android/app/src/main/res/drawable/ic_wordmark.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/drawable/ic_zoom_in.xml b/android/app/src/main/res/drawable/ic_zoom_in.xml deleted file mode 100644 index 2ff797e..0000000 --- a/android/app/src/main/res/drawable/ic_zoom_in.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/android/app/src/main/res/drawable/ic_zoom_options.xml b/android/app/src/main/res/drawable/ic_zoom_options.xml deleted file mode 100644 index b92a08b..0000000 --- a/android/app/src/main/res/drawable/ic_zoom_options.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/android/app/src/main/res/drawable/ic_zoom_reset.xml b/android/app/src/main/res/drawable/ic_zoom_reset.xml deleted file mode 100644 index a31c9a1..0000000 --- a/android/app/src/main/res/drawable/ic_zoom_reset.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - \ No newline at end of file diff --git a/android/app/src/main/res/drawable/indicator.xml b/android/app/src/main/res/drawable/indicator.xml deleted file mode 100644 index a98f60c..0000000 --- a/android/app/src/main/res/drawable/indicator.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_about.xml b/android/app/src/main/res/layout/activity_about.xml deleted file mode 100644 index aadb608..0000000 --- a/android/app/src/main/res/layout/activity_about.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/layout/activity_settings.xml b/android/app/src/main/res/layout/activity_settings.xml deleted file mode 100644 index 3d44164..0000000 --- a/android/app/src/main/res/layout/activity_settings.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/activity_vnc.xml b/android/app/src/main/res/layout/activity_vnc.xml deleted file mode 100644 index 47ee45f..0000000 --- a/android/app/src/main/res/layout/activity_vnc.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/fragment_about.xml b/android/app/src/main/res/layout/fragment_about.xml deleted file mode 100644 index ec91dc4..0000000 --- a/android/app/src/main/res/layout/fragment_about.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - -