diff --git a/.github/actions/setup-harmony-toolchain/action.yml b/.github/actions/setup-harmony-toolchain/action.yml new file mode 100644 index 0000000000..ae00be8c69 --- /dev/null +++ b/.github/actions/setup-harmony-toolchain/action.yml @@ -0,0 +1,33 @@ +name: 'Setup Harmony toolchain' +inputs: + version: + description: 'Harmony version' + default: '6.0-Release' +runs: + using: 'composite' + steps: + - uses: actions/cache/restore@v4 + id: restore-cache + with: + path: /opt/native + key: harmony-${{ inputs.version }} + + - name: Download Harmony toolchain + if: ${{ !steps.restore-cache.outputs.cache-hit }} + shell: bash + run: | + wget https://repo.huaweicloud.com/openharmony/os/${{ inputs.version }}/ohos-sdk-windows_linux-public.tar.gz + tar -zxvf ohos-sdk-windows_linux-public.tar.gz + mkdir -p /opt + + unzip linux/native*.zip -d /opt + - uses: actions/cache/save@v4 + if: ${{ !steps.restore-cache.outputs.cache-hit }} + with: + path: /opt/native + key: harmony-${{ inputs.version }} + - name: 'Set output vars' + id: final + shell: bash + run: | + echo "HARMONY_NATIVE_SDK=/opt/native" >> $GITHUB_OUTPUT diff --git a/.github/workflows/create-test-plan.py b/.github/workflows/create-test-plan.py index 26c6949df1..da3e53a21c 100755 --- a/.github/workflows/create-test-plan.py +++ b/.github/workflows/create-test-plan.py @@ -61,6 +61,7 @@ class SdlPlatform(Enum): OpenBSD = "openbsd" NGage = "ngage" DJGPP = "djgpp" + Harmony = "harmony" class Msys2Platform(Enum): @@ -105,6 +106,7 @@ class JobSpec: gdk: bool = False vita_gles: Optional[VitaGLES] = None more_hard_deps: bool = False + harmony_arch: Optional[str] = None JOB_SPECS = { @@ -153,6 +155,9 @@ JOB_SPECS = { "freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ), "ngage": JobSpec(name="N-Gage", os=JobOs.WindowsLatest, platform=SdlPlatform.NGage, artifact="SDL-ngage", ), "djgpp": JobSpec(name="DOS (DJGPP)", os=JobOs.UbuntuLatest, platform=SdlPlatform.DJGPP, artifact="SDL-djgpp", ), + "harmony-arm64": JobSpec(name="Harmony (Arm64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-arm64", harmony_arch="arm64-v8a"), + "harmony-arm32": JobSpec(name="Harmony (Arm32)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-arm32", harmony_arch="armeabi-v7a"), + "harmony-x86_64": JobSpec(name="Harmony (x86-64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Harmony, artifact="SDL-harmony-x86_64", harmony_arch="x86_64"), } @@ -868,6 +873,17 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool, ctest_args job.run_tests = False job.test_pkg_config = False job.cmake_toolchain_file = "$GITHUB_WORKSPACE/build-scripts/i586-pc-msdosdjgpp.cmake" + case SdlPlatform.Harmony: + job.cmake_arguments.extend(( + f"-DOHOS_ARCH={spec.harmony_arch}", + "-DCMAKE_TOOLCHAIN_FILE=/opt/native/build/cmake/ohos.toolchain.cmake", + "-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=1" + )) + job.shared_lib = SharedLibType.SO + job.static_lib = StaticLibType.A + job.run_tests = False + job.test_pkg_config = False + job.werror = False case _: raise ValueError(f"Unsupported platform={spec.platform}") diff --git a/.github/workflows/generic.yml b/.github/workflows/generic.yml index 928ee1f9e0..faa4c4e317 100644 --- a/.github/workflows/generic.yml +++ b/.github/workflows/generic.yml @@ -53,6 +53,9 @@ jobs: if: ${{ matrix.platform.platform == 'emscripten' }} with: version: 3.1.35 + - name: 'Set up Harmony toolchain' + if: ${{ matrix.platform.platform == 'harmony' }} + uses: ./.github/actions/setup-harmony-toolchain - uses: browser-actions/setup-chrome@v2 id: setup-chrome if: ${{ matrix.platform.platform == 'emscripten' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 51542b8ba6..b1c20572d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1709,6 +1709,84 @@ if(ANDROID) target_link_options(SDL3-static INTERFACE "-Wl,-u,JNI_OnLoad") endif() +if(TARGET SDL3-shared) + target_link_options(SDL3-shared PRIVATE "-Wl,-z,max-page-size=16384") + target_link_options(SDL3-shared PRIVATE "-Wl,-z,common-page-size=16384") +endif() + +elseif(OHOS) + # disable warnings from the toolchain + sdl_compile_options(PRIVATE "-Wno-unused-command-line-argument") + + sdl_link_dependency(ohos LIBS ace_napi.z hilog_ndk.z ace_ndk.z rawfile.z pixelmap_ndk.z ohsensor) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/ohos/*.c") + + if(SDL_VIDEO) + set(SDL_VIDEO_DRIVER_OHOS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/ohos/*.c") + set(HAVE_SDL_VIDEO TRUE) + set(HAVE_VULKAN ON) + set(SDL_VIDEO_VULKAN ON) + set(SDL_VIDEO_RENDER_VULKAN 1) + set(HAVE_RENDER_VULKAN TRUE) + + if(SDL_OPENGLES) + set(SDL_VIDEO_OPENGL_EGL 1) + set(HAVE_OPENGLES TRUE) + set(SDL_VIDEO_OPENGL_ES2 1) + set(SDL_VIDEO_RENDER_OGL_ES2 1) + + sdl_link_dependency(opengles LIBS GLESv2) + endif() + endif() + + sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/misc/ohos/*.c" + ) + set(HAVE_SDL_MISC TRUE) + + if(SDL_POWER) + set(SDL_POWER_OHOS 1) + sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/power/ohos/*.c" + "${SDL3_SOURCE_DIR}/src/power/ohos/*.h" + ) + set(HAVE_SDL_POWER TRUE) + endif() + + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/ohos/*.c") + set(HAVE_SDL_LOCALE TRUE) + + set(SDL_LOADSO_DLOPEN 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/loadso/dlopen/*.c") + set(HAVE_SDL_LOADSO TRUE) + + set(SDL_TIME_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/unix/*.c") + set(HAVE_SDL_TIME TRUE) + + set(SDL_TIMER_UNIX 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c") + set(HAVE_SDL_TIMERS TRUE) + + set(SDL_FILESYSTEM_OHOS 1) + sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/filesystem/ohos/*.c" + "${SDL3_SOURCE_DIR}/src/filesystem/ohos/*.h" + ) + set(HAVE_SDL_FILESYSTEM TRUE) + if(SDL_SENSOR) + set(SDL_SENSOR_OHOS 1) + sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/sensor/ohos/*.c" + "${SDL3_SOURCE_DIR}/src/sensor/ohos/*.h" + ) + set(HAVE_SDL_SENSOR TRUE) + endif() + + set(SDL_PTHREADS 1) + + CheckPTHREAD() elseif(EMSCRIPTEN) # Hide noisy warnings that intend to aid mostly during initial stages of porting a new # project. Uncomment at will for verbose cross-compiling -I/../ path info. @@ -3522,6 +3600,9 @@ if (SDL_DIALOG) if(ANDROID) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/android/SDL_androiddialog.c) set(HAVE_SDL_DIALOG TRUE) + elseif (OHOS) + sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/ohos/SDL_ohosdialog.c) + set(HAVE_SDL_DIALOG TRUE) elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_unixdialog.c) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_portaldialog.c) diff --git a/cmake/macros.cmake b/cmake/macros.cmake index 3a651fcb91..65e621f630 100644 --- a/cmake/macros.cmake +++ b/cmake/macros.cmake @@ -425,7 +425,7 @@ function(SDL_PrintSummary) message(STATUS "") endif() - if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN OR HAIKU OR RISCOS OR DJGPP OR CYGWIN)) + if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN OR HAIKU OR RISCOS OR OHOS OR DJGPP OR CYGWIN)) if(NOT (HAVE_X11 OR HAVE_WAYLAND)) if(NOT SDL_UNIX_CONSOLE_BUILD) message(FATAL_ERROR diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 8074c4b933..fcc546f3b0 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -970,7 +970,7 @@ macro(CheckPTHREAD) if(ANDROID OR SDL_PTHREADS_PRIVATE) # the android libc provides built-in support for pthreads, so no # additional linking or compile flags are necessary - elseif(LINUX) + elseif(LINUX OR OHOS) set(PTHREAD_CFLAGS "-D_REENTRANT") set(PTHREAD_LDFLAGS "-pthread") elseif(BSDI) diff --git a/docs/README-ohos.md b/docs/README-ohos.md new file mode 100644 index 0000000000..5b184300a9 --- /dev/null +++ b/docs/README-ohos.md @@ -0,0 +1,28 @@ +OpenHarmony / HarmonyOS +================================================================================ + +Requirements +================================================================================ + +DevEco Studio 5.0.0 or later +https://developer.huawei.com/consumer/en/download + +Harmony OS Development Toolchain 5.0.0 (API 12) or later (Bundled in the DevEco Studio) + + +How the port works +================================================================================ + +- OpenHarmony / Harmony OS apps are based on ArkTS/JS running on the Ark JS runtime, optionally with parts written in C +- We can use the napi and ndk provided by the Harmony SDK to fetch the app window, context and so on. We wrote a simple Harmony shell for SDL, simpily initialize the basic application and the context for SDL library, then runs your app in another thread. (Harmony JS apps only contains one thread, if we runs your app main loop directly in JS, the whole app just freezes) +- This produces a .hap or .app package which can be installed in OpenHarmony and HarmonyOS Emulators (you will need to apply for a certificate to sign the app before testing it on a real HarmonyOS machine) + + +Building the example app and test it (HarmonyOS Emulator) +================================================================================ + +Download the DevEco Studio, and open the ohos-project folder in this repo + +Then, download a emulator in the Device Manager tab, and runs it. + +Click the run button, the IDE will automatically build the app and run it for you, you can act with your app in the emulator window. diff --git a/include/SDL3/SDL_platform_defines.h b/include/SDL3/SDL_platform_defines.h index 71dbd53fec..8135c60f12 100644 --- a/include/SDL3/SDL_platform_defines.h +++ b/include/SDL3/SDL_platform_defines.h @@ -112,6 +112,11 @@ #undef SDL_PLATFORM_LINUX #endif +#if defined(OHOS) || defined(__OHOS__) +#define SDL_PLATFORM_OHOS 1 +#undef SDL_PLATFORM_LINUX +#endif + #if defined(__unix__) || defined(__unix) || defined(unix) /** diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 7b608323dc..97929b65e9 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -277,6 +277,7 @@ #cmakedefine SDL_AUDIO_DRIVER_JACK 1 #cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@ #cmakedefine SDL_AUDIO_DRIVER_NETBSD 1 +#cmakedefine SDL_VIDEO_DRIVER_OHOS 1 #cmakedefine SDL_AUDIO_DRIVER_OSS 1 #cmakedefine SDL_AUDIO_DRIVER_PIPEWIRE 1 #cmakedefine SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC @SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC@ @@ -343,6 +344,7 @@ /* Enable various sensor drivers */ #cmakedefine SDL_SENSOR_ANDROID 1 +#cmakedefine SDL_SENSOR_OHOS 1 #cmakedefine SDL_SENSOR_COREMOTION 1 #cmakedefine SDL_SENSOR_WINDOWS 1 #cmakedefine SDL_SENSOR_DUMMY 1 @@ -409,6 +411,7 @@ #cmakedefine SDL_VIDEO_DRIVER_N3DS 1 #cmakedefine SDL_VIDEO_DRIVER_NGAGE 1 #cmakedefine SDL_VIDEO_DRIVER_OFFSCREEN 1 +#cmakedefine SDL_VIDEO_DRIVER_OHOS 1 #cmakedefine SDL_VIDEO_DRIVER_PS2 1 #cmakedefine SDL_VIDEO_DRIVER_PSP 1 #cmakedefine SDL_VIDEO_DRIVER_RISCOS 1 @@ -498,6 +501,7 @@ /* Enable system power support */ #cmakedefine SDL_POWER_ANDROID 1 +#cmakedefine SDL_POWER_OHOS 1 #cmakedefine SDL_POWER_LINUX 1 #cmakedefine SDL_POWER_WINDOWS 1 #cmakedefine SDL_POWER_MACOSX 1 @@ -513,6 +517,7 @@ /* Enable system filesystem support */ #cmakedefine SDL_FILESYSTEM_ANDROID 1 +#cmakedefine SDL_FILESYSTEM_OHOS 1 #cmakedefine SDL_FILESYSTEM_HAIKU 1 #cmakedefine SDL_FILESYSTEM_COCOA 1 #cmakedefine SDL_FILESYSTEM_DUMMY 1 diff --git a/ohos-project/.gitignore b/ohos-project/.gitignore new file mode 100644 index 0000000000..d2ff20141c --- /dev/null +++ b/ohos-project/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/ohos-project/AppScope/app.json5 b/ohos-project/AppScope/app.json5 new file mode 100644 index 0000000000..a65624e4b6 --- /dev/null +++ b/ohos-project/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "org.libsdl.SdlShell", + "vendor": "libsdl-org", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ohos-project/AppScope/resources/base/element/string.json b/ohos-project/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000..2b6cf61a6d --- /dev/null +++ b/ohos-project/AppScope/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "SDL Demo" + }, + { + "name": "perm_reason", + "value": "Subsystem for SDL / SDL 子系统" + } + ] +} diff --git a/ohos-project/AppScope/resources/base/media/background.png b/ohos-project/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000..923f2b3f27 Binary files /dev/null and b/ohos-project/AppScope/resources/base/media/background.png differ diff --git a/ohos-project/AppScope/resources/base/media/foreground.png b/ohos-project/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000..97014d3e10 Binary files /dev/null and b/ohos-project/AppScope/resources/base/media/foreground.png differ diff --git a/ohos-project/AppScope/resources/base/media/foreground0.png b/ohos-project/AppScope/resources/base/media/foreground0.png new file mode 100644 index 0000000000..959c384b08 Binary files /dev/null and b/ohos-project/AppScope/resources/base/media/foreground0.png differ diff --git a/ohos-project/AppScope/resources/base/media/layered_image.json b/ohos-project/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000..fb49920440 --- /dev/null +++ b/ohos-project/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ohos-project/build-profile.json5 b/ohos-project/build-profile.json5 new file mode 100644 index 0000000000..3a6faaef1e --- /dev/null +++ b/ohos-project/build-profile.json5 @@ -0,0 +1,43 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "nativeCompiler": "BiSheng", + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ohos-project/code-linter.json5 b/ohos-project/code-linter.json5 new file mode 100644 index 0000000000..073990fa45 --- /dev/null +++ b/ohos-project/code-linter.json5 @@ -0,0 +1,32 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ohos-project/entry/.gitignore b/ohos-project/entry/.gitignore new file mode 100644 index 0000000000..e2713a2779 --- /dev/null +++ b/ohos-project/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ohos-project/entry/build-profile.json5 b/ohos-project/entry/build-profile.json5 new file mode 100644 index 0000000000..7f9f0fddcb --- /dev/null +++ b/ohos-project/entry/build-profile.json5 @@ -0,0 +1,45 @@ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + }, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=1", + "cppFlags": "", + "abiFilters": ["arm64-v8a", "x86_64"] + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/hvigorfile.ts b/ohos-project/entry/hvigorfile.ts new file mode 100644 index 0000000000..b0e3a1ab98 --- /dev/null +++ b/ohos-project/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ohos-project/entry/obfuscation-rules.txt b/ohos-project/entry/obfuscation-rules.txt new file mode 100644 index 0000000000..272efb6ca3 --- /dev/null +++ b/ohos-project/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ohos-project/entry/oh-package-lock.json5 b/ohos-project/entry/oh-package-lock.json5 new file mode 100644 index 0000000000..2967845e7e --- /dev/null +++ b/ohos-project/entry/oh-package-lock.json5 @@ -0,0 +1,19 @@ +{ + "meta": { + "stableOrder": true, + "enableUnifiedLockfile": false + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "libSDL3.so@src/main/cpp/sdl": "libSDL3.so@src/main/cpp/sdl" + }, + "packages": { + "libSDL3.so@src/main/cpp/sdl": { + "name": "libSDL3.so", + "version": "1.0.0", + "resolved": "", + "registryType": "local" + } + } +} \ No newline at end of file diff --git a/ohos-project/entry/oh-package.json5 b/ohos-project/entry/oh-package.json5 new file mode 100644 index 0000000000..5fb886710d --- /dev/null +++ b/ohos-project/entry/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libSDL3.so": "file:./src/main/cpp/sdl" + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/cpp/CMakeLists.txt b/ohos-project/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000..1b8714f992 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,21 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(MyApplication10) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +add_subdirectory(../../../../.. external/sdlbin) + +link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) +add_definitions(-DVK_USE_PLATFORM_OHOS=1) +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include + ${SDL3_SOURCE_DIR}/include) + +add_library(entry SHARED entrypoint.cpp) +add_dependencies(entry SDL3::SDL3-shared) +target_link_libraries(entry PUBLIC libace_napi.z.so libSDL3.so libvulkan.so libGLESv2.so libohaudio.so libohsensor.so) diff --git a/ohos-project/entry/src/main/cpp/entrypoint.cpp b/ohos-project/entry/src/main/cpp/entrypoint.cpp new file mode 100644 index 0000000000..08922b3e57 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/entrypoint.cpp @@ -0,0 +1,177 @@ +#include "SDL3/SDL_assert.h" +#include "SDL3/SDL_init.h" +#include "SDL3/SDL_messagebox.h" +#include "SDL3/SDL_misc.h" +#include "SDL3/SDL_render.h" +#include "SDL3/SDL_timer.h" +#include "SDL3/SDL_video.h" +#include "SDL3/SDL_vulkan.h" +#include "SDL3/SDL_locale.h" +#include "SDL3/SDL_clipboard.h" +#include "SDL3/SDL_log.h" +#include "SDL3/SDL_hints.h" +#include "SDL3/SDL_power.h" +#include "SDL3/SDL_dialog.h" +#include "SDL3/SDL_sensor.h" +#include +#include +#include +#include +#include +#include +#include +#include + +float vtxdata[] = { + -0.5f, -0.5f, 0.f, + 0.5f, -0.5f, 0.0f, + 0.0f, 0.5f, 0.0f +}; + +float vtxdata2[] = { + 0.f, 0.f, 1.f, + 0.f, 1.f, 0.f, + 1.f, 0.f, 0.f +}; + +int main() +{ + /*OH_AudioStreamBuilder* builder; + OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER); + + OH_AudioStreamBuilder_SetSamplingRate(builder, 48000); + OH_AudioStreamBuilder_SetChannelCount(builder, 2); + OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_U8); + OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW); + OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC); + // OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST); + + OH_AudioRenderer_Callbacks callbacks; + + srand(time(nullptr)); + callbacks.OH_AudioRenderer_OnStreamEvent = nullptr; + callbacks.OH_AudioRenderer_OnInterruptEvent = nullptr; + callbacks.OH_AudioRenderer_OnError = nullptr; + callbacks.OH_AudioRenderer_OnWriteData = [](OH_AudioRenderer* renderer, void* userData, void* buffer, int32_t length) { + auto p = (uint8_t *)buffer; + int t = length; + while (t > 0) { + *p = rand() % 255; + p++; + t--; + } + return 0; + }; + + OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr); + + OH_AudioRenderer* audioRenderer; + OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer); + OH_AudioRenderer_Start(audioRenderer); + OH_AudioStreamBuilder_Destroy(builder);*/ + + SDL_SetHint(SDL_HINT_EGL_LIBRARY, "libEGL.so"); + SDL_SetHint(SDL_HINT_OPENGL_LIBRARY, "libGLESv2.so"); + SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "libGLESv2.so"); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_SENSOR); + int i = 0; + auto t = SDL_GetPreferredLocales(&i); + SDL_Log("Main func invoke !!! %s %s", t[0]->country, t[0]->language); + // SDL_GL_LoadLibrary("libGLESv2.so"); + SDL_Log("sdl error: %s", SDL_GetError()); + SDL_Window* win = SDL_CreateWindow("test", 1024, 1024, SDL_WINDOW_OPENGL); + + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "SDL Application", "test!", win); + + auto context = SDL_GL_CreateContext(win); + SDL_GL_MakeCurrent(win, context); + + int frgshader = ((PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"))(GL_FRAGMENT_SHADER); + int vexshader = ((PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"))(GL_VERTEX_SHADER); + + auto frag = "varying vec4 v_color;void main() {gl_FragColor = v_color;}"; + ((PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"))(frgshader, 1, &frag, nullptr); + ((PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"))(frgshader); + int status = 1; + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(frgshader, GL_COMPILE_STATUS, &status); + int status2 = 1; + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(frgshader, GL_INFO_LOG_LENGTH, &status2); + std::string log(status2, '\0'); + ((PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"))(frgshader, status2, nullptr, (char*)log.c_str()); + + SDL_Log("test: %d %d %s", status, status2, log.c_str()); + + auto vert = "attribute vec3 pos;attribute vec3 color;varying vec4 v_color;void main() {gl_Position=vec4(pos,1.0);v_color=vec4(color, 1.0);}"; + ((PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"))(vexshader, 1, &vert, nullptr); + ((PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"))(vexshader); + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(vexshader, GL_COMPILE_STATUS, &status); + ((PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"))(vexshader, GL_INFO_LOG_LENGTH, &status2); + std::string log2(status2, '\0'); + ((PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"))(vexshader, status2, nullptr, (char*)log2.c_str()); + + SDL_Log("test: %d %d %s", status, status2, log2.c_str()); + + auto prog = ((PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram"))(); + ((PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"))(prog, vexshader); + ((PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"))(prog, frgshader); + ((PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram"))(prog); + ((PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv"))(prog, GL_LINK_STATUS, &status); + SDL_Log("link: %d", status); + + ((PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"))(vexshader); + ((PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"))(frgshader); + ((PFNGLCLEARCOLORPROC)SDL_GL_GetProcAddress("glClearColor"))(0, 0, 0, 0); + + while (true) { + SDL_StartTextInput(win); + int w, h; + SDL_GetWindowSize(win, &w, &h); + + ((PFNGLVIEWPORTPROC)SDL_GL_GetProcAddress("glViewport"))(0, 0, w, h); + ((PFNGLCLEARPROC)SDL_GL_GetProcAddress("glClear"))(GL_COLOR_BUFFER_BIT); + ((PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"))(prog); + for (int i = 0; i < 9; i++) { + vtxdata2[i] = SDL_randf(); + /*vtxdata2[i] += 0.01f; + if (vtxdata2[i] >= 1.f) { + vtxdata2[i] = 0.f; + }*/ + } + ((PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"))(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)vtxdata); + ((PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"))(0); + ((PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer"))(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)vtxdata2); + ((PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray"))(1); + + ((PFNGLDRAWARRAYSPROC)SDL_GL_GetProcAddress("glDrawArrays"))(GL_TRIANGLES, 0, 3); + + SDL_GL_SwapWindow(win); + + SDL_Event event; + if (SDL_PollEvent(&event)) { + SDL_Log("event type: %d", event.type); + + if (event.type == SDL_EVENT_FINGER_DOWN || event.type == SDL_EVENT_FINGER_UP || event.type == SDL_EVENT_FINGER_MOTION) { + SDL_Log("finger %f %f", event.tfinger.x, event.tfinger.y); + } + + if (event.type == SDL_EVENT_QUIT) { + break; + } + + if (event.type == SDL_EVENT_TEXT_INPUT) { + SDL_Log("text %s", event.text.text); + } + } + } + + SDL_Log("glversion: %s", ((PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString"))(GL_VERSION)); + + SDL_GL_DestroyContext(context); + + SDL_DestroyWindow(win); + + return 0; +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/cpp/sdl/Index.d.ts b/ohos-project/entry/src/main/cpp/sdl/Index.d.ts new file mode 100644 index 0000000000..826606cef7 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/sdl/Index.d.ts @@ -0,0 +1,14 @@ +export const sdlCallbackInit: (d) => void; +export const sdlLaunchMain: (lib: string, func: string) => number; +export const sdlKeyEvent: (scancode: number, type: number) => number; +export const sdlTextAppend: (str: string) => number; +export const sdlTextEditing: (str: string, loc: number, length: number) => number; +export const sdlDialogExecCallback: () => void; +export const sdlDialogClearSelection: () => void; +export const sdlDialogFileSelected: (path: string) => void; +export const sdlSendDialogStatus: (idx: number) => void; +export const sdlOnBackground: () => void; +export const sdlOnForeground: () => void; +export const sdlOnLowMemory: () => void; +export const sdlOnTerminate: () => void; +export const sdlOnConfigUpdate: () => void; \ No newline at end of file diff --git a/ohos-project/entry/src/main/cpp/sdl/oh-package.json5 b/ohos-project/entry/src/main/cpp/sdl/oh-package.json5 new file mode 100644 index 0000000000..3a8ac3e1b5 --- /dev/null +++ b/ohos-project/entry/src/main/cpp/sdl/oh-package.json5 @@ -0,0 +1,6 @@ +{ + "name": "libSDL3.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} diff --git a/ohos-project/entry/src/main/ets/entryability/EntryAbility.ets b/ohos-project/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000..022255cf25 --- /dev/null +++ b/ohos-project/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,93 @@ +import { abilityAccessCtrl, AbilityConstant, + common, + Configuration, + ConfigurationConstant, + Permissions, + UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import { KeyboardAvoidMode } from '@ohos.arkui.UIContext'; +import { BusinessError } from '@kit.BasicServicesKit'; +import sdl from 'libSDL3.so'; + +const DOMAIN = 0x0000; + +const permissions: Array = ['ohos.permission.INPUT_KEYBOARD_CONTROLLER', 'ohos.permission.READ_PASTEBOARD']; +function reqPermissionsFromUser(permissions: Array, context: common.UIAbilityContext): void { + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); + atManager.requestPermissionsFromUser(context, permissions).then((data) => { + let grantStatus: Array = data.authResults; + let length: number = grantStatus.length; + for (let i = 0; i < length; i++) { + if (grantStatus[i] === 0) { + // promptAction.showDialog({title: "permissions", message: "granted", buttons: [{text: 'Ok', color: '#999999'}]}); + } else { + // promptAction.showDialog({title: "permissions", message: "not granted", buttons: [{text: 'Ok', color: '#999999'}]}); + return; + } + } + // 授权成功 + }).catch((err: BusinessError) => { + console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); + }) +} + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onDestroy'); + } + + async onWindowStageCreate(windowStage: window.WindowStage): Promise { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + reqPermissionsFromUser(permissions, this.context); + + windowStage.getMainWindow().then(async (win) => { + try { + win.getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET) + } catch (error) { + let ll: BusinessError = error; + hilog.error(DOMAIN, 'surfaceLayer', 'Failed to load the content. Cause: %{public}s', JSON.stringify(ll)); + } + }) + + if (err.code) { + hilog.error(DOMAIN, 'surfaceLayer', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'surfaceLayer', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onWindowStageDestroy'); + sdl.sdlOnTerminate(); + } + + onForeground(): void { + hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onForeground'); + sdl.sdlOnForeground(); + } + + onBackground(): void { + hilog.info(DOMAIN, 'surfaceLayer', '%{public}s', 'Ability onBackground'); + sdl.sdlOnBackground(); + } + + onMemoryLevel(level: AbilityConstant.MemoryLevel): void { + if (level == AbilityConstant.MemoryLevel.MEMORY_LEVEL_LOW || level == AbilityConstant.MemoryLevel.MEMORY_LEVEL_CRITICAL) { + sdl.sdlOnLowMemory(); + } + } + + onConfigurationUpdate(newConfig: Configuration): void { + sdl.sdlOnConfigUpdate(); + } +} diff --git a/ohos-project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ohos-project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000..8e9efdda96 --- /dev/null +++ b/ohos-project/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,16 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'surfaceLayer', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'surfaceLayer', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/ets/pages/Index.ets b/ohos-project/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000..5b94ed296a --- /dev/null +++ b/ohos-project/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,212 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import sdl from 'libSDL3.so'; +import { intl } from '@kit.LocalizationKit'; +import { promptAction, ShowDialogSuccessResponse } from '@kit.ArkUI'; +import { inputMethod } from '@kit.IMEKit' +import { deviceInfo, pasteboard } from '@kit.BasicServicesKit'; +import { common, ConfigurationConstant } from '@kit.AbilityKit'; +import { batteryInfo } from '@kit.BasicServicesKit'; + +import { picker } from '@kit.CoreFileKit'; +import { BusinessError } from '@kit.BasicServicesKit'; + +const DOMAIN = 0x0000; + +let controller = inputMethod.getController() +let input = false +let targetText = "" +let context: UIContext + +export class ArkNapiCallback { + onMainLaunch() { + sdl.sdlLaunchMain("libentry.so", "main") + } + + showDialog(title: string, message: string, indexMapping: number[], names: string[]) { + let target: promptAction.Button[] = [] + for (let i = 0; i < names.length; i++) + { + target.push({ text: names[i], color: '#999999' }) + } + promptAction.showDialog({ title: title, message: message, buttons: target }).then((a) => { + sdl.sdlSendDialogStatus(indexMapping[a.index]) + }) + } + fetchLocale(): string { + let locale = new intl.Locale() + return locale.language + "_" + locale.region + } + firstCall() { + hilog.info(DOMAIN, 'surfaceLayer', 'Native binding finished.') + sdl.sdlOnConfigUpdate(); + } + + openLink(url: string) { + let con = context.getHostContext() as common.UIAbilityContext + con.openLink(url) + } + + hasBattery(): number { + return batteryInfo.isBatteryPresent ? 1 : 0 + } + batteryCharging(): number { + return batteryInfo.chargingStatus == batteryInfo.BatteryChargeState.ENABLE ? 1 : 0 + } + batteryCharged(): number { + return batteryInfo.chargingStatus == batteryInfo.BatteryChargeState.FULL ? 1 : 0 + } + batteryPercent(): number { + return batteryInfo.batterySOC + } + + setPasteboardString(text: string) { + let pasteData: pasteboard.PasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text); + let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard(); + systemPasteboard.setData(pasteData, (err, data) => { + if (err) { + hilog.error(DOMAIN, 'surfaceLayer', 'Failed to set PasteData. Cause: ' + err.message); + return; + } + + hilog.info(DOMAIN, 'surfaceLayer', 'Succeed in setting PasteData.'); + }); + } + + textEditing(): number { + return input ? 1 : 0; + } + + startTextInput() { + input = true + controller.showTextInput() + hilog.info(DOMAIN, 'surfaceLayer', 'text input start') + } + stopTextInput() { + input = false + controller.hideTextInput() + hilog.info(DOMAIN, 'surfaceLayer', 'text input stop') + targetText = "" + } + + openFileDialog(id: number, defpath: string, itemcount: number, filter: string) { + const documentSelectOptions = new picker.DocumentSelectOptions(); + documentSelectOptions.maxSelectNumber = itemcount; + documentSelectOptions.defaultFilePathUri = defpath; + + if (id == 0 || id == 1) + { + documentSelectOptions.selectMode = picker.DocumentSelectMode.FILE; + } + if (id == 2) + { + documentSelectOptions.selectMode = picker.DocumentSelectMode.FOLDER; + } + + let targetfilter: string[] = [] + let temp = filter.split('\u0002') + for (let index = 0; index < temp.length; index++) { + const element = temp[index]; + + let temp2 = element.split("|") + + // broken filter! + if (temp2.length == 1) + { + targetfilter.push(element + "|.*") + } + else + { + let targettemp = temp2[0] + "|"; + + let temp3 = temp2[1].split(";") + for (let index1 = 0; index1 < temp3.length; index1++) { + targettemp += "." + temp3[index1] + ","; + } + targetfilter.push(targettemp) + } + } + + documentSelectOptions.fileSuffixFilters = targetfilter; + documentSelectOptions.authMode = false; + documentSelectOptions.mergeMode = picker.MergeTypeMode.DEFAULT; + documentSelectOptions.isEncryptionSupported = false; + + let uris: string[] = []; + let contextt = context.getHostContext() as common.UIAbilityContext; + const documentViewPicker = new picker.DocumentViewPicker(contextt); + documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array) => { + uris = documentSelectResult; + sdl.sdlDialogClearSelection() + for (let idx = 0; idx < uris.length; idx++) + { + let target = uris[idx].replace("file://docs", "") + sdl.sdlDialogFileSelected(target) + console.info('documentViewPicker.select to file succeed and uris are: ' + target); + } + sdl.sdlDialogExecCallback() + }).catch((err: BusinessError) => { + console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`); + }) + } + + getInternalPath(): string { + let contextt = context.getHostContext() as common.UIAbilityContext + return contextt.filesDir + } + + themeIsDark(): number { + let contextt = context.getHostContext() as common.UIAbilityContext + return (contextt.config.colorMode == ConfigurationConstant.ColorMode.COLOR_MODE_DARK) ? 1 : 0; + } + + isPhone(): number { + return deviceInfo.deviceType == "phone" ? 1 : 0; + } +} + +let callbackRef: ArkNapiCallback = new ArkNapiCallback() + +@Entry +@Component +struct Index { + async aboutToAppear(): Promise { + context = this.getUIContext() + + sdl.sdlCallbackInit(callbackRef) + focusControl.requestFocus('mainView') + await controller.attach(true, { + inputAttribute: { + textInputType: inputMethod.TextInputType.TEXT, + enterKeyType: inputMethod.EnterKeyType.DONE + } + }); + controller.on('insertText', (text) => { + targetText += text; + sdl.sdlTextAppend(text) + }) + controller.on('deleteLeft', (i) => { + sdl.sdlTextEditing(targetText, targetText.length - 1 - i, i); + + if (targetText.length > 0) { + targetText = targetText.substring(0, targetText.length - i) + } + }) + controller.on('deleteRight', (i) => { + sdl.sdlTextEditing(targetText, 0, i); + + if (targetText.length > 0) { + targetText = targetText.substring(i, targetText.length) + } + }) + } + + build() { + Column() { + XComponent({ id: 'mainView', type: 'surface', libraryname: 'SDL3' }) + .id('mainView') + } + .onKeyEvent((keyevent) => { + sdl.sdlKeyEvent(keyevent.keyCode, keyevent.type); + }) + } +} diff --git a/ohos-project/entry/src/main/module.json5 b/ohos-project/entry/src/main/module.json5 new file mode 100644 index 0000000000..679de172c8 --- /dev/null +++ b/ohos-project/entry/src/main/module.json5 @@ -0,0 +1,76 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "requestPermissions": [ + { + "name": "ohos.permission.INPUT_KEYBOARD_CONTROLLER", + "reason": "$string:perm_reason", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when":"inuse" + } + }, + { + "name": "ohos.permission.INTERNET" + }, + { + "name": "ohos.permission.ACCELEROMETER" + }, + { + "name": "ohos.permission.GYROSCOPE" + } + ], + + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "orientation": "landscape", + "exported": true, + "supportWindowMode": ["floating", "fullscreen", "split"], + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/element/color.json b/ohos-project/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000..3c712962da --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/element/float.json b/ohos-project/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000..33ea22304f --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/ohos-project/entry/src/main/resources/base/element/string.json b/ohos-project/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000..3f04948b12 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "SDL Demo" + } + ] +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/media/background.png b/ohos-project/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000..923f2b3f27 Binary files /dev/null and b/ohos-project/entry/src/main/resources/base/media/background.png differ diff --git a/ohos-project/entry/src/main/resources/base/media/foreground.png b/ohos-project/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000..97014d3e10 Binary files /dev/null and b/ohos-project/entry/src/main/resources/base/media/foreground.png differ diff --git a/ohos-project/entry/src/main/resources/base/media/layered_image.json b/ohos-project/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000..fb49920440 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/media/startIcon.png b/ohos-project/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000..205ad8b5a8 Binary files /dev/null and b/ohos-project/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ohos-project/entry/src/main/resources/base/profile/backup_config.json b/ohos-project/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000..78f40ae7c4 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ohos-project/entry/src/main/resources/base/profile/main_pages.json b/ohos-project/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000..1898d94f58 --- /dev/null +++ b/ohos-project/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ohos-project/entry/src/main/resources/dark/element/color.json b/ohos-project/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000..79b11c2747 --- /dev/null +++ b/ohos-project/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/ohos-project/hvigor/hvigor-config.json5 b/ohos-project/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000..7a7ab8914d --- /dev/null +++ b/ohos-project/hvigor/hvigor-config.json5 @@ -0,0 +1,23 @@ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ohos-project/hvigorfile.ts b/ohos-project/hvigorfile.ts new file mode 100644 index 0000000000..47113e2e36 --- /dev/null +++ b/ohos-project/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/ohos-project/oh-package-lock.json5 b/ohos-project/oh-package-lock.json5 new file mode 100644 index 0000000000..35c2f794fa --- /dev/null +++ b/ohos-project/oh-package-lock.json5 @@ -0,0 +1,28 @@ +{ + "meta": { + "stableOrder": true, + "enableUnifiedLockfile": false + }, + "lockfileVersion": 3, + "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", + "specifiers": { + "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0", + "@ohos/hypium@1.0.24": "@ohos/hypium@1.0.24" + }, + "packages": { + "@ohos/hamock@1.0.0": { + "name": "", + "version": "1.0.0", + "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har", + "registryType": "ohpm" + }, + "@ohos/hypium@1.0.24": { + "name": "", + "version": "1.0.24", + "integrity": "sha512-3dCqc+BAR5LqEGG2Vtzi8O3r7ci/3fYU+FWjwvUobbfko7DUnXGOccaror0yYuUhJfXzFK0aZNMGSnXaTwEnbw==", + "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.24.har", + "registryType": "ohpm" + } + } +} \ No newline at end of file diff --git a/ohos-project/oh-package.json5 b/ohos-project/oh-package.json5 new file mode 100644 index 0000000000..c72aa05d54 --- /dev/null +++ b/ohos-project/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.24", + "@ohos/hamock": "1.0.0" + } +} diff --git a/src/SDL.c b/src/SDL.c index 61d14bbff7..a6ade32263 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -61,6 +61,10 @@ #include "core/android/SDL_android.h" #endif +#ifdef SDL_PLATFORM_OHOS +#include "core/ohos/SDL_ohos.h" +#endif + #define SDL_ALL_SUBSYSTEM_FLAGS ~0U // Initialization/Cleanup routines @@ -824,6 +828,8 @@ const char *SDL_GetPlatform(void) return "GNU/Hurd"; #elif defined(__managarm__) return "Managarm"; +#elif defined(SDL_PLATFORM_OHOS) + return "OpenHarmony/HarmonyOS"; #else return "Unknown (see SDL_platform.h)"; #endif @@ -836,6 +842,8 @@ bool SDL_IsPhone(void) if (!SDL_IsTablet() && !SDL_IsTV()) { return true; } +#elif defined(SDL_PLATFORM_OHOS) + return OHOS_IsPhone(); #endif return false; } diff --git a/src/SDL_log.c b/src/SDL_log.c index 6295fc68ef..5838b33a56 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -40,6 +40,10 @@ #include #endif +#ifdef SDL_PLATFORM_OHOS +#include +#endif + #include "stdlib/SDL_vacopy.h" // The size of the stack buffer to use for rendering log messages. @@ -124,6 +128,19 @@ static int SDL_android_priority[] = { SDL_COMPILE_TIME_ASSERT(android_priority, SDL_arraysize(SDL_android_priority) == SDL_LOG_PRIORITY_COUNT); #endif // SDL_PLATFORM_ANDROID +#ifdef SDL_PLATFORM_OHOS +static int SDL_ohos_priority[] = { + LOG_DEBUG, + LOG_DEBUG, + LOG_DEBUG, + LOG_DEBUG, + LOG_INFO, + LOG_WARN, + LOG_ERROR, + LOG_FATAL +}; +#endif + static void SDLCALL SDL_LoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_ResetLogPriorities(); @@ -583,7 +600,7 @@ void SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_ST va_end(ap); } -#ifdef SDL_PLATFORM_ANDROID +#if defined(SDL_PLATFORM_ANDROID) || defined(SDL_PLATFORM_OHOS) static const char *GetCategoryPrefix(int category) { if (category < SDL_LOG_CATEGORY_RESERVED2) { @@ -594,7 +611,7 @@ static const char *GetCategoryPrefix(int category) } return "CUSTOM"; } -#endif // SDL_PLATFORM_ANDROID +#endif void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { @@ -765,6 +782,13 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); __android_log_write(SDL_android_priority[priority], tag, message); } + #elif defined(SDL_PLATFORM_OHOS) + { + char tag[32]; + + SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); + OH_LOG_Print(LOG_APP, SDL_ohos_priority[priority], 0, tag, "%{public}s", message); + } #elif defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT)) /* Technically we don't need Cocoa/UIKit, but that's where this function is defined for now. */ diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c index 2566a22048..fc30067760 100644 --- a/src/audio/SDL_audiotypecvt.c +++ b/src/audio/SDL_audiotypecvt.c @@ -530,6 +530,9 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32 *dst, const U } #endif +#ifndef SDL_PLATFORM_OHOS +#undef SDL_NEON_INTRINSICS +#endif #ifdef SDL_NEON_INTRINSICS // C99 requires that all code modifying floating point environment should diff --git a/src/core/ohos/SDL_ohos.c b/src/core/ohos/SDL_ohos.c new file mode 100644 index 0000000000..c2082467a0 --- /dev/null +++ b/src/core/ohos/SDL_ohos.c @@ -0,0 +1,1020 @@ +#include "SDL_internal.h" +#include "events/SDL_events_c.h" +#include "events/SDL_keyboard_c.h" +#include "video/ohos/SDL_ohosmouse.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SDL_PLATFORM_OHOS + +#include "../../video/ohos/SDL_ohoskeyboard.h" +#include "../../video/ohos/SDL_ohostouch.h" +#include "../../video/ohos/SDL_ohosvideo.h" +#include "SDL3/SDL_mutex.h" +#include "SDL_ohos.h" +#include "napi/native_api.h" +#include + +static OHNativeWindow *g_ohosNativeWindow; +static SDL_Mutex *g_ohosPageMutex = NULL; +static OH_NativeXComponent_Callback callback; +static OH_NativeXComponent_MouseEvent_Callback mouseCallback; +static int x, y, wid, hei; +static struct +{ + napi_env env; + napi_threadsafe_function func; + napi_ref interface; +} napiEnv; + +typedef enum +{ + Int, + Long, + Double, + String, + IntArray, + StringArray +} napiArgType; + +typedef struct +{ + napiArgType type; + bool enabled; + union + { + int i; + long long l; + double d; + const char *str; + + struct { + int *ia; + int ial; + }; + + struct { + const char * const *sa; + int sal; + }; + } data; +} napiCallbackArg; +typedef struct +{ + const char *func; + int argCount; + napiCallbackArg arg[16]; + napiArgType type; + napiCallbackArg ret; + bool returned; +} napiCallbackData; + +void OHOS_windowUpdateAttributes(SDL_Window *w) +{ + w->x = x; + w->y = y; + w->w = wid; + w->h = hei; + + SDL_SetWindowSize(w, wid, hei); +} + +void OHOS_windowDataFill(SDL_Window *w) +{ + w->internal = SDL_calloc(1, sizeof(SDL_WindowData)); + OHOS_windowUpdateAttributes(w); + w->internal->native_window = g_ohosNativeWindow; + + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + + if (_this->windows == NULL) { + _this->windows = w; + } else { + _this->windows->next = w; + w->prev = _this->windows; + } + +#ifdef SDL_VIDEO_OPENGL_EGL + if (w->flags & SDL_WINDOW_OPENGL) { + SDL_LockMutex(g_ohosPageMutex); + if (w->internal->egl_surface == EGL_NO_SURFACE) { + w->internal->egl_surface = SDL_EGL_CreateSurface(_this, w, (NativeWindowType)g_ohosNativeWindow); + } + SDL_UnlockMutex(g_ohosPageMutex); + } +#endif +} +void OHOS_removeWindow(SDL_Window *w) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (_this->windows == w) { + _this->windows = _this->windows->next; + } else { + SDL_Window *curWin = _this->windows; + while (curWin != NULL) { + if (curWin == w) { + if (curWin->next == NULL) { + curWin->prev->next = NULL; + } else { + curWin->prev->next = curWin->next; + curWin->next->prev = curWin->prev; + } + break; + } + curWin = curWin->next; + } + } + +#ifdef SDL_VIDEO_OPENGL_EGL + if (w->flags & SDL_WINDOW_OPENGL) { + SDL_LockMutex(g_ohosPageMutex); + if (w->internal->egl_context) { + SDL_EGL_DestroyContext(_this, w->internal->egl_context); + } + if (w->internal->egl_surface != EGL_NO_SURFACE) { + SDL_EGL_DestroySurface(_this, w->internal->egl_surface); + } + SDL_UnlockMutex(g_ohosPageMutex); + } + SDL_free(w->internal); +#endif +} + +void OHOS_LockPage() +{ + // SDL_LockMutex(g_ohosPageMutex); +} +void OHOS_UnlockPage() +{ + // SDL_UnlockMutex(g_ohosPageMutex); +} +int OHOS_FetchWidth() +{ + return wid; +} +int OHOS_FetchHeight() +{ + return hei; +} + +static void sdlJSCallback(napi_env env, napi_value jsCb, void *content, void *data) +{ + napiCallbackData *ar = (napiCallbackData *)data; + + napi_value callb = NULL; + napi_get_reference_value(env, napiEnv.interface, &callb); + napi_value jsMethod = NULL; + napi_get_named_property(env, callb, ar->func, &jsMethod); + + napi_value args[16]; + SDL_Log("[SDL] calling js function %s with %d args", ar->func, ar->argCount); + for (int i = 0; i < ar->argCount; i++) { + if (!ar->arg[i].enabled) { + continue; + } + switch (ar->arg[i].type) { + case Int: + { + napi_create_int32(env, ar->arg[i].data.i, args + i); + break; + } + case Long: + { + napi_create_int64(env, ar->arg[i].data.l, args + i); + break; + } + case Double: + { + napi_create_double(env, ar->arg[i].data.d, args + i); + break; + } + case String: + { + const char* p = ar->arg[i].data.str; + napi_create_string_utf8(env, ar->arg[i].data.str, SDL_strlen(p), args + i); + break; + } + case IntArray: + { + napi_create_array_with_length(env, ar->arg[i].data.ial, args + i); + for (int ii = 0; ii < ar->arg[i].data.ial; ii++) { + napi_value itt; + napi_create_int32(env, ar->arg[i].data.ia[ii], &itt); + napi_set_element(env, *(args + i), ii, itt); + } + break; + } + case StringArray: + { + napi_create_array_with_length(env, ar->arg[i].data.sal, args + i); + for (int ii = 0; ii < ar->arg[i].data.sal; ii++) { + napi_value itt; + napi_create_string_utf8(env, ar->arg[i].data.sa[ii], SDL_strlen(ar->arg[i].data.sa[ii]), &itt); + napi_set_element(env, *(args + i), ii, itt); + } + break; + } + } + } + + napi_value v; + napi_call_function(env, NULL, jsMethod, ar->argCount, args, &v); + switch (ar->type) { + case Int: + { + napi_get_value_int32(env, v, &ar->ret.data.i); + break; + } + case Long: + { + napi_get_value_int64(env, v, (int64_t *)&ar->ret.data.l); + break; + } + case String: + { + size_t stringSize = 0; + napi_get_value_string_utf8(env, v, NULL, 0, &stringSize); + char *value = SDL_malloc(stringSize + 1); + napi_get_value_string_utf8(env, v, value, stringSize + 1, &stringSize); + ar->ret.data.str = value; + break; + } + case Double: + { + napi_get_value_double(env, v, &ar->ret.data.d); + break; + } + } + ar->returned = true; +} + +void OHOS_FileDialog(int id, const char* defpath, int allowmany, const char* filter) +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "openFileDialog"; + data->argCount = 4; + data->arg[0].type = Int; + data->arg[0].enabled = true; + data->arg[0].data.i = id; + data->arg[1].type = String; + data->arg[1].enabled = true; + data->arg[1].data.str = defpath; + data->arg[2].type = Int; + data->arg[2].enabled = true; + data->arg[2].data.i = allowmany; + data->arg[3].type = String; + data->arg[3].enabled = true; + data->arg[3].data.str = filter; + + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_blocking); + while (!data->returned) {} + SDL_free((void *)filter); +} + +void OHOS_SetClipboardText(const char* c) +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "setPasteboardString"; + data->argCount = 1; + data->arg[0].type = String; + data->arg[0].enabled = true; + data->arg[0].data.str = c; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); +} + +bool OHOS_IsScreenKeyboardShown() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "textEditing"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + bool d = data->ret.data.i == 1; + SDL_free(data); + return d; +} + +bool OHOS_IsBatteryPresent() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "hasBattery"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + bool d = data->ret.data.i == 1; + SDL_free(data); + return d; +} + +bool OHOS_IsBatteryCharging() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "batteryCharging"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + bool d = data->ret.data.i == 1; + SDL_free(data); + return d; +} + +bool OHOS_IsBatteryCharged() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "batteryCharged"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + bool d = data->ret.data.i == 1; + SDL_free(data); + return d; +} + +int OHOS_GetBatteryPercent() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "batteryPercent"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + int d = data->ret.data.i; + SDL_free(data); + return d; +} +void OHOS_StartTextInput() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "startTextInput"; + data->argCount = 0; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_blocking); + while (!data->returned) {} +} +void OHOS_StopTextInput() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "stopTextInput"; + data->argCount = 0; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_blocking); + while (!data->returned) {} +} + +static bool dialogBoxFinished = false; +static int dialogBoxChoice = -1; + +int OHOS_MessageBox(const char* title, const char* message, int ml, int* mapping, int bl, const char * const *buttons) +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "showDialog"; + data->argCount = 4; + data->arg[0].type = String; + data->arg[0].enabled = true; + data->arg[0].data.str = title; + data->arg[1].type = String; + data->arg[1].enabled = true; + data->arg[1].data.str = message; + data->arg[2].type = IntArray; + data->arg[2].enabled = true; + data->arg[2].data.ia = mapping; + data->arg[2].data.ial = ml; + data->arg[3].type = StringArray; + data->arg[3].enabled = true; + data->arg[3].data.sa = buttons; + data->arg[3].data.sal = bl; + + data->type = Int; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_blocking); + while (!data->returned) {} + SDL_free(data); + while (!dialogBoxFinished) {} + dialogBoxFinished = false; + return dialogBoxChoice; +} + +void OHOS_OpenLink(const char* url) +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "openLink"; + data->argCount = 1; + data->arg[0].type = String; + data->arg[0].enabled = true; + data->arg[0].data.str = url; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_blocking); +} + +bool OHOS_ThemeDark() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "themeIsDark"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + return data->ret.data.i; +} + +bool OHOS_IsPhone() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "isPhone"; + data->argCount = 0; + data->type = Int; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + int d = data->ret.data.i; + SDL_free(data); + return d; +} + +const char* OHOS_Locale() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "fetchLocale"; + data->argCount = 0; + data->type = String; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + const char* d = data->ret.data.str; + SDL_free(data); + return d; +} + +char* OHOS_GetStoragePath() +{ + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "getInternalPath"; + data->argCount = 0; + data->type = String; + data->returned = false; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + while (!data->returned) {} + + const char* d = data->ret.data.str; + SDL_free(data); + return (char *)d; +} + +static napi_value sdlCallbackInit(napi_env env, napi_callback_info info) +{ + napiEnv.env = env; + size_t argc = 1; + napi_value args[1] = { NULL }; + + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + napi_create_reference(env, args[0], 1, &napiEnv.interface); + + napi_value resName = NULL; + napi_create_string_utf8(env, "SDLThreadSafe", NAPI_AUTO_LENGTH, &resName); + napi_create_threadsafe_function(env, args[0], NULL, resName, 0, 1, NULL, NULL, NULL, sdlJSCallback, &napiEnv.func); + + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + SDL_memset(data, 0, sizeof(napiCallbackData)); + data->func = "firstCall"; + data->argCount = 0; + data->type = Int; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +typedef struct entrypoint_info_ { + char* libname; + char* func; +} entrypoint_info; +static int sdlLaunchMainInternal(void* reserved) +{ + if (!reserved) { + return -1; + } + entrypoint_info *data = (entrypoint_info*)reserved; + void *lib = dlopen(data->libname, RTLD_LAZY); + void *func = dlsym(lib, data->func); + typedef int (*test)(); + int d = ((test)func)(); + dlclose(lib); + SDL_free(reserved); + + return d; +} + +static SDL_Thread *mainThread; + +static napi_value sdlLaunchMain(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = { NULL, NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + size_t libstringSize = 0; + napi_get_value_string_utf8(env, args[0], NULL, 0, &libstringSize); + char *libname = SDL_malloc(libstringSize + 1); + napi_get_value_string_utf8(env, args[0], libname, libstringSize + 1, &libstringSize); + + size_t fstringSize = 0; + napi_get_value_string_utf8(env, args[1], NULL, 0, &fstringSize); + char *fname = SDL_malloc(fstringSize + 1); + napi_get_value_string_utf8(env, args[1], fname, fstringSize + 1, &fstringSize); + + entrypoint_info *entry = (entrypoint_info*)SDL_malloc(sizeof(entrypoint_info)); + entry->func = fname; + entry->libname = libname; + mainThread = SDL_CreateThread(sdlLaunchMainInternal, "SDL App Thread", entry); + SDL_SetMainReady(); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) +{ + SDL_Log("Native window: %p", window); + g_ohosNativeWindow = (OHNativeWindow *)window; + + uint64_t width; + uint64_t height; + double offsetX; + double offsetY; + OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); + OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY); + + SDL_LockMutex(g_ohosPageMutex); + wid = width; + hei = height; + x = (int)offsetX; + y = (int)offsetY; + SDL_UnlockMutex(g_ohosPageMutex); + + napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData)); + data->func = "onMainLaunch"; + data->argCount = 0; + + napi_call_threadsafe_function(napiEnv.func, data, napi_tsfn_nonblocking); +} +static void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) +{ + g_ohosNativeWindow = (OHNativeWindow *)window; + + uint64_t width; + uint64_t height; + double offsetX; + double offsetY; + OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); + OH_NativeXComponent_GetXComponentOffset(component, window, &offsetX, &offsetY); + + SDL_LockMutex(g_ohosPageMutex); + wid = width; + hei = height; + x = (int)offsetX; + y = (int)offsetY; + SDL_UnlockMutex(g_ohosPageMutex); + + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (_this && _this->windows) { + SDL_Window *win = _this->windows; + OHOS_windowUpdateAttributes(win); + } +} +static void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *win = _this->windows; + while (win != NULL) { +#ifdef SDL_VIDEO_OPENGL_EGL + if (win->flags & SDL_WINDOW_OPENGL) { + if (win->internal->egl_context) { + SDL_EGL_DestroyContext(_this, win->internal->egl_context); + } + if (win->internal->egl_surface) { + SDL_EGL_DestroySurface(_this, win->internal->egl_surface); + } + } +#endif + win = win->next; + } +} +static void onKeyEvent(OH_NativeXComponent *component, void *window) +{ + OH_NativeXComponent_KeyEvent *keyEvent = NULL; + SDL_Log("key!"); + if (OH_NativeXComponent_GetKeyEvent(component, &keyEvent) >= 0) { + OH_NativeXComponent_KeyAction action; + OH_NativeXComponent_KeyCode code; + OH_NativeXComponent_EventSourceType sourceType; + + OH_NativeXComponent_GetKeyEventAction(keyEvent, &action); + OH_NativeXComponent_GetKeyEventCode(keyEvent, &code); + OH_NativeXComponent_GetKeyEventSourceType(keyEvent, &sourceType); + + if (sourceType == OH_NATIVEXCOMPONENT_SOURCE_TYPE_KEYBOARD) { + if (OH_NATIVEXCOMPONENT_KEY_ACTION_DOWN == action) { + OHOS_OnKeyDown(code); + } else if (OH_NATIVEXCOMPONENT_KEY_ACTION_UP == action) { + OHOS_OnKeyUp(code); + } + } + } +} + +static void onNativeTouch(OH_NativeXComponent *component, void *window) +{ + OH_NativeXComponent_TouchEvent touchEvent; + OH_NativeXComponent_TouchPointToolType toolType = OH_NATIVEXCOMPONENT_TOOL_TYPE_UNKNOWN; + + OHOS_LockPage(); + OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent); + OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType); + + // Only process the finger that triggered this event (touchEvent.id). + // The touchPoints array contains current state of all fingers, not just the changed one. + int targetIndex = -1; + for (int i = 0; i < touchEvent.numPoints; i++) { + if (touchEvent.touchPoints[i].id == touchEvent.id) { + targetIndex = i; + break; + } + } + + if (targetIndex < 0) { + OHOS_UnlockPage(); + return; + } + + SDL_OHOSTouchEvent e; + e.timestamp = touchEvent.timeStamp; + e.deviceId = touchEvent.deviceId + 1; + e.fingerId = touchEvent.touchPoints[targetIndex].id + 1; + e.area = touchEvent.touchPoints[targetIndex].size; + e.x = touchEvent.touchPoints[targetIndex].x / (float)wid; + e.y = touchEvent.touchPoints[targetIndex].y / (float)hei; + e.p = touchEvent.touchPoints[targetIndex].force; + + switch (touchEvent.touchPoints[targetIndex].type) { + case OH_NATIVEXCOMPONENT_DOWN: + e.type = SDL_EVENT_FINGER_DOWN; + break; + case OH_NATIVEXCOMPONENT_MOVE: + e.type = SDL_EVENT_FINGER_MOTION; + break; + case OH_NATIVEXCOMPONENT_UP: + e.type = SDL_EVENT_FINGER_UP; + break; + case OH_NATIVEXCOMPONENT_CANCEL: + case OH_NATIVEXCOMPONENT_UNKNOWN: + e.type = SDL_EVENT_FINGER_CANCELED; + break; + } + + OHOS_OnTouch(e); + + OHOS_UnlockPage(); +} +// TODO mouse data +static void onNativeMouse(OH_NativeXComponent *component, void *window) { + OH_NativeXComponent_MouseEvent event; + OHOS_LockPage(); + OH_NativeXComponent_GetMouseEvent(component, window, &event); + if (event.button == OH_NATIVEXCOMPONENT_NONE_BUTTON || event.action == OH_NATIVEXCOMPONENT_MOUSE_NONE) { + return; + } + SDL_OHOSMouseEvent e; + e.x = event.x; + e.y = event.y; + e.timestamp = event.timestamp; + switch (event.button) + { + case OH_NATIVEXCOMPONENT_LEFT_BUTTON: + e.button = SDL_BUTTON_LEFT; + break; + case OH_NATIVEXCOMPONENT_RIGHT_BUTTON: + e.button = SDL_BUTTON_RIGHT; + break; + case OH_NATIVEXCOMPONENT_MIDDLE_BUTTON: + e.button = SDL_BUTTON_MIDDLE; + break; + case OH_NATIVEXCOMPONENT_BACK_BUTTON: + e.button = SDL_BUTTON_X1; + break; + case OH_NATIVEXCOMPONENT_FORWARD_BUTTON: + e.button = SDL_BUTTON_X2; + break; + } + + if (event.action == OH_NATIVEXCOMPONENT_MOUSE_MOVE) { + e.motion = true; + } + else { + e.down = event.action == OH_NATIVEXCOMPONENT_MOUSE_PRESS; + } + OHOS_OnMouse(e); + + OHOS_UnlockPage(); +} + +static napi_value sdlKeyEvent(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = { NULL, NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + int keycode, type; + napi_get_value_int32(env, args[0], &keycode); + napi_get_value_int32(env, args[1], &type); + + if (type == 0) { + OHOS_OnKeyDown(keycode); + } + else { + OHOS_OnKeyUp(keycode); + } + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlTextAppend(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + size_t fstringSize = 0; + napi_get_value_string_utf8(env, args[0], NULL, 0, &fstringSize); + char *fname = SDL_malloc(fstringSize + 1); + napi_get_value_string_utf8(env, args[0], fname, fstringSize + 1, &fstringSize); + + SDL_SendKeyboardText(fname); + + SDL_free(fname); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlTextEditing(napi_env env, napi_callback_info info) +{ + size_t argc = 3; + napi_value args[3] = { NULL, NULL, NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + size_t fstringSize = 0; + napi_get_value_string_utf8(env, args[0], NULL, 0, &fstringSize); + char *fname = SDL_malloc(fstringSize + 1); + napi_get_value_string_utf8(env, args[0], fname, fstringSize + 1, &fstringSize); + + int start, len; + napi_get_value_int32(env, args[1], &start); + napi_get_value_int32(env, args[2], &len); + + SDL_SendEditingText(fname, start, len); + + SDL_free(fname); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +void SDL_OHOS_FileSelected(const char* data); +void SDL_OHOS_ClearSelection(); +void SDL_OHOS_ExecCallback(); + +static napi_value sdlDialogClearSelection(napi_env env, napi_callback_info info) +{ + SDL_OHOS_ClearSelection(); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlDialogExecCallback(napi_env env, napi_callback_info info) +{ + SDL_OHOS_ExecCallback(); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlDialogFileSelected(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + size_t stringSize = 0; + napi_get_value_string_utf8(env, args[0], NULL, 0, &stringSize); + char *value = (char *)SDL_malloc(stringSize + 1); + napi_get_value_string_utf8(env, args[0], value, stringSize + 1, &stringSize); + + SDL_OHOS_FileSelected(value); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlSendDialogStatus(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { NULL }; + napi_get_cb_info(env, info, &argc, args, NULL, NULL); + + napi_get_value_int32(env, args[0], &dialogBoxChoice); + dialogBoxFinished = true; + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlOnBackground(napi_env env, napi_callback_info info) +{ + SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND); + SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlOnForeground(napi_env env, napi_callback_info info) +{ + SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); + SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlOnLowMemory(napi_env env, napi_callback_info info) +{ + SDL_SendAppEvent(SDL_EVENT_LOW_MEMORY); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlOnTerminate(napi_env env, napi_callback_info info) +{ + SDL_SendAppEvent(SDL_EVENT_TERMINATING); + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value sdlOnConfigUpdate(napi_env env, napi_callback_info info) +{ + SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED); + SDL_SendAppEvent(SDL_EVENT_SYSTEM_THEME_CHANGED); + + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (_this) + { + _this->system_theme = OHOS_ThemeDark() ? SDL_SYSTEM_THEME_DARK : SDL_SYSTEM_THEME_LIGHT; + } + + napi_value result; + napi_create_int32(env, 0, &result); + return result; +} + +static napi_value SDL_OHOS_NAPI_Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "sdlCallbackInit", NULL, sdlCallbackInit, NULL, NULL, NULL, napi_default, NULL }, + { "sdlLaunchMain", NULL, sdlLaunchMain, NULL, NULL, NULL, napi_default, NULL }, + { "sdlKeyEvent", NULL, sdlKeyEvent, NULL, NULL, NULL, napi_default, NULL }, + { "sdlTextAppend", NULL, sdlTextAppend, NULL, NULL, NULL, napi_default, NULL }, + { "sdlTextEditing", NULL, sdlTextEditing, NULL, NULL, NULL, napi_default, NULL }, + { "sdlDialogClearSelection", NULL, sdlDialogClearSelection, NULL, NULL, NULL, napi_default, NULL }, + { "sdlDialogExecCallback", NULL, sdlDialogExecCallback, NULL, NULL, NULL, napi_default, NULL }, + { "sdlDialogFileSelected", NULL, sdlDialogFileSelected, NULL, NULL, NULL, napi_default, NULL }, + { "sdlSendDialogStatus", NULL, sdlSendDialogStatus, NULL, NULL, NULL, napi_default, NULL }, + { "sdlOnBackground", NULL, sdlOnBackground, NULL, NULL, NULL, napi_default, NULL }, + { "sdlOnForeground", NULL, sdlOnForeground, NULL, NULL, NULL, napi_default, NULL }, + { "sdlOnLowMemory", NULL, sdlOnLowMemory, NULL, NULL, NULL, napi_default, NULL }, + { "sdlOnTerminate", NULL, sdlOnTerminate, NULL, NULL, NULL, napi_default, NULL }, + { "sdlOnConfigUpdate", NULL, sdlOnConfigUpdate, NULL, NULL, NULL, napi_default, NULL } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + + napi_value exportInstance = NULL; + if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) { + return exports; + } + OH_NativeXComponent *nativeXComponent; + if (napi_unwrap(env, exportInstance, (void **)(&nativeXComponent)) != napi_ok) { + return exports; + } + + callback.OnSurfaceCreated = OnSurfaceCreatedCB; + callback.OnSurfaceChanged = OnSurfaceChangedCB; + callback.OnSurfaceDestroyed = OnSurfaceDestroyedCB; + callback.DispatchTouchEvent = onNativeTouch; + OH_NativeXComponent_RegisterCallback(nativeXComponent, &callback); + + mouseCallback.DispatchMouseEvent = onNativeMouse; + OH_NativeXComponent_RegisterMouseEventCallback(nativeXComponent, &mouseCallback); + + OH_NativeXComponent_RegisterKeyEventCallback(nativeXComponent, onKeyEvent); + + g_ohosPageMutex = SDL_CreateMutex(); + + return exports; +} + +napi_module OHOS_NAPI_Module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = NULL, + .nm_register_func = SDL_OHOS_NAPI_Init, + .nm_modname = "SDL3", + .nm_priv = ((void *)0), + .reserved = { 0 }, +}; + +__attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&OHOS_NAPI_Module); +} + +#endif diff --git a/src/core/ohos/SDL_ohos.h b/src/core/ohos/SDL_ohos.h new file mode 100644 index 0000000000..fa2788af8b --- /dev/null +++ b/src/core/ohos/SDL_ohos.h @@ -0,0 +1,40 @@ +#ifndef SDL_OHOS_H +#define SDL_OHOS_H + +#include "SDL3/SDL_video.h" +#include "video/SDL_sysvideo.h" +#include + +void OHOS_windowDataFill(SDL_Window* w); +void OHOS_removeWindow(SDL_Window* w); +void OHOS_LockPage(); +void OHOS_UnlockPage(); +int OHOS_FetchWidth(); +int OHOS_FetchHeight(); + +int OHOS_MessageBox(const char* title, const char* message, int ml, int* mapping, int bl, const char * const *buttons); +const char* OHOS_Locale(); +void OHOS_OpenLink(const char* url); +bool OHOS_IsBatteryPresent(); +bool OHOS_IsBatteryCharging(); +bool OHOS_IsBatteryCharged(); +int OHOS_GetBatteryPercent(); +void OHOS_SetClipboardText(const char* data); +char* OHOS_GetStoragePath(); +bool OHOS_ThemeDark(); + +bool OHOS_IsPhone(); + +void OHOS_FileDialog(int id, const char* defpath, int allowmany, const char* filter); + +bool OHOS_IsScreenKeyboardShown(); +void OHOS_StartTextInput(); +void OHOS_StopTextInput(); + +typedef struct SDL_VideoData { + SDL_Rect textRect; + int isPaused; + int isPausing; +} SDL_VideoData; + +#endif diff --git a/src/dialog/ohos/SDL_ohosdialog.c b/src/dialog/ohos/SDL_ohosdialog.c new file mode 100644 index 0000000000..ec6d00c818 --- /dev/null +++ b/src/dialog/ohos/SDL_ohosdialog.c @@ -0,0 +1,92 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "../SDL_dialog.h" +#include "../../core/ohos/SDL_ohos.h" + +#define MAX_FILENUM 256 +static SDL_DialogFileCallback current = NULL; +static void* userdatad = NULL; +static const char* paths[MAX_FILENUM]; +static int idxCurrent = 0; + +void SDL_OHOS_FileSelected(const char* data) +{ + if (idxCurrent >= MAX_FILENUM) { + return; + } + paths[idxCurrent] = data; + idxCurrent++; +} + +void SDL_OHOS_ClearSelection() +{ + for (int i = 0; i < MAX_FILENUM; i++) { + paths[i] = NULL; + } + idxCurrent = 0; +} + +void SDL_OHOS_ExecCallback() +{ + if (current) { + current(userdatad, (const char * const *)paths, 0); + } +} + +void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props) +{ + current = callback; + userdatad = userdata; + const char* defpath = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_LOCATION_STRING, ""); + bool allowmany = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false); + + void* rawfilters = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_FILTERS_POINTER, NULL); + int filterscount = SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0); + + char* filterstring = (char*)SDL_malloc(1024); + + if (rawfilters && filterscount > 0) { + SDL_DialogFileFilter *data = (SDL_DialogFileFilter*)rawfilters; + char *begin = filterstring; + for (int idx = 0; idx < filterscount; idx++) + { + SDL_DialogFileFilter filter = data[idx]; + + if (begin - filterstring + SDL_strlen(filter.name) >= 1024) break; + SDL_memcpy(begin, filter.name, SDL_strlen(filter.name)); + begin += SDL_strlen(filter.name); + if (begin - filterstring + 1 >= 1024) break; + *begin = '|'; + begin++; + if (begin - filterstring + SDL_strlen(filter.pattern) >= 1024) break; + SDL_memcpy(begin, filter.pattern, SDL_strlen(filter.pattern)); + begin += SDL_strlen(filter.pattern); + + if (begin - filterstring + 1 >= 1024) break; + *begin = (char)0x2; + begin++; + } + } + + OHOS_FileDialog(type, defpath, allowmany ? MAX_FILENUM : 1, filterstring); +} diff --git a/src/filesystem/ohos/SDL_sysfilesystem.c b/src/filesystem/ohos/SDL_sysfilesystem.c new file mode 100644 index 0000000000..b75aa8314e --- /dev/null +++ b/src/filesystem/ohos/SDL_sysfilesystem.c @@ -0,0 +1,58 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#if defined(SDL_FILESYSTEM_OHOS) + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" +#include "../../core/ohos/SDL_ohos.h" + +char *SDL_SYS_GetBasePath(void) +{ + SDL_Unsupported(); + return NULL; +} + +char *SDL_SYS_GetPrefPath(const char *org, const char *app) +{ + return OHOS_GetStoragePath(); +} + +char *SDL_SYS_GetUserFolder(SDL_Folder folder) +{ + SDL_Unsupported(); + return NULL; +} + +char *SDL_SYS_GetCurrentDirectory(void) +{ + const char *base = SDL_GetBasePath(); + if (!base) { + return NULL; + } + + return SDL_strdup(base); +} + +#endif // SDL_FILESYSTEM_OHOS diff --git a/src/locale/ohos/SDL_syslocale.c b/src/locale/ohos/SDL_syslocale.c new file mode 100644 index 0000000000..49f1270e2b --- /dev/null +++ b/src/locale/ohos/SDL_syslocale.c @@ -0,0 +1,11 @@ +#include "SDL_internal.h" +#include "../SDL_syslocale.h" +#include "../../core/ohos/SDL_ohos.h" + +bool SDL_SYS_GetPreferredLocales(char *buf, size_t buflen) +{ + const char* result = OHOS_Locale(); + SDL_memcpy(buf, result, buflen); + SDL_Log("target %s", buf); + return true; +} diff --git a/src/misc/ohos/SDL_sysurl.c b/src/misc/ohos/SDL_sysurl.c new file mode 100644 index 0000000000..f2f65c744b --- /dev/null +++ b/src/misc/ohos/SDL_sysurl.c @@ -0,0 +1,10 @@ +#include "SDL_internal.h" +#include "../../core/ohos/SDL_ohos.h" + +#include "../SDL_sysurl.h" + +bool SDL_SYS_OpenURL(const char *url) +{ + OHOS_OpenLink(url); + return true; +} diff --git a/src/power/SDL_power.c b/src/power/SDL_power.c index 8308890934..99a51fceb5 100644 --- a/src/power/SDL_power.c +++ b/src/power/SDL_power.c @@ -74,6 +74,9 @@ static SDL_GetPowerInfo_Impl implementations[] = { #ifdef SDL_POWER_EMSCRIPTEN // handles Emscripten SDL_GetPowerInfo_Emscripten, #endif +#ifdef SDL_POWER_OHOS + SDL_GetPowerInfo_OHOS +#endif #ifdef SDL_POWER_HARDWIRED SDL_GetPowerInfo_Hardwired, diff --git a/src/power/SDL_syspower.h b/src/power/SDL_syspower.h index 6ef3e26b2c..ac009bf7bb 100644 --- a/src/power/SDL_syspower.h +++ b/src/power/SDL_syspower.h @@ -35,6 +35,7 @@ bool SDL_GetPowerInfo_UIKit(SDL_PowerState *, int *, int *); bool SDL_GetPowerInfo_MacOSX(SDL_PowerState *, int *, int *); bool SDL_GetPowerInfo_Haiku(SDL_PowerState *, int *, int *); bool SDL_GetPowerInfo_Android(SDL_PowerState *, int *, int *); +bool SDL_GetPowerInfo_OHOS(SDL_PowerState *, int *, int *); bool SDL_GetPowerInfo_PSP(SDL_PowerState *, int *, int *); bool SDL_GetPowerInfo_VITA(SDL_PowerState *, int *, int *); bool SDL_GetPowerInfo_N3DS(SDL_PowerState *, int *, int *); diff --git a/src/power/ohos/SDL_syspower.c b/src/power/ohos/SDL_syspower.c new file mode 100644 index 0000000000..1a995de3e3 --- /dev/null +++ b/src/power/ohos/SDL_syspower.c @@ -0,0 +1,46 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_POWER_DISABLED +#ifdef SDL_POWER_OHOS + +#include "../SDL_syspower.h" + +#include "../../core/ohos/SDL_ohos.h" + +bool SDL_GetPowerInfo_OHOS(SDL_PowerState *state, int *seconds, int *percent) +{ + if (!OHOS_IsBatteryPresent()) { + *state = SDL_POWERSTATE_NO_BATTERY; + return true; + } + else { + *seconds = -1; + *percent = OHOS_GetBatteryPercent(); + + *state = OHOS_IsBatteryCharging() ? SDL_POWERSTATE_CHARGING : (OHOS_IsBatteryCharged() ? SDL_POWERSTATE_CHARGED : SDL_POWERSTATE_ON_BATTERY); + } + return true; +} + +#endif // SDL_POWER_OHOS +#endif // SDL_POWER_DISABLED diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 9091fb44c6..63cc4884b6 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -46,6 +46,9 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = { #ifdef SDL_SENSOR_EMSCRIPTEN &SDL_EMSCRIPTEN_SensorDriver, #endif +#ifdef SDL_SENSOR_OHOS + &SDL_OHOS_SensorDriver, +#endif #if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED) &SDL_DUMMY_SensorDriver #endif diff --git a/src/sensor/SDL_syssensor.h b/src/sensor/SDL_syssensor.h index 7452d9d6ea..30f46975f9 100644 --- a/src/sensor/SDL_syssensor.h +++ b/src/sensor/SDL_syssensor.h @@ -108,5 +108,6 @@ extern SDL_SensorDriver SDL_DUMMY_SensorDriver; extern SDL_SensorDriver SDL_VITA_SensorDriver; extern SDL_SensorDriver SDL_N3DS_SensorDriver; extern SDL_SensorDriver SDL_EMSCRIPTEN_SensorDriver; +extern SDL_SensorDriver SDL_OHOS_SensorDriver; #endif // SDL_syssensor_h_ diff --git a/src/sensor/ohos/SDL_ohossensor.c b/src/sensor/ohos/SDL_ohossensor.c new file mode 100644 index 0000000000..12fe3dfb54 --- /dev/null +++ b/src/sensor/ohos/SDL_ohossensor.c @@ -0,0 +1,226 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef SDL_SENSOR_OHOS + +#include "../SDL_syssensor.h" +#include "sensors/oh_sensor.h" +#include "sensors/oh_sensor_type.h" + +typedef struct { + Sensor_Info *info; + Sensor_Subscriber *subs; + Sensor_SubscriptionId *subid; + Sensor_SubscriptionAttribute *subattr; + SDL_Sensor *sensor; + SDL_SensorID id; +} OHSensorMapping; + +static uint32_t sensorCount; +static OHSensorMapping *mapping; + +static bool SDL_OHOS_SensorInit(void) +{ + Sensor_Info **infobase; + uint32_t s; + if (OH_Sensor_GetInfos(NULL, &s) != SENSOR_SUCCESS) { + return false; + } + sensorCount = s; + + infobase = OH_Sensor_CreateInfos(s); + mapping = (OHSensorMapping *)SDL_calloc(sizeof(OHSensorMapping), s); + + if (OH_Sensor_GetInfos(infobase, &s) != SENSOR_SUCCESS) { + return false; + } + + for (int i = 0; i < s; i++) + { + mapping[i].sensor = NULL; + mapping[i].info = infobase[i]; + mapping[i].id = SDL_GetNextObjectID(); + } + + return true; +} + +static int SDL_OHOS_SensorGetCount(void) +{ + return sensorCount; +} + +static void SDL_OHOS_SensorDetect(void) +{ +} + +static const char *SDL_OHOS_SensorGetDeviceName(int device_index) +{ + char *data; + uint32_t length; + OH_SensorInfo_GetName(mapping[device_index].info, NULL, &length); + data = (char*)SDL_malloc(length); + OH_SensorInfo_GetName(mapping[device_index].info, data, &length); + + return data; +} + +static SDL_SensorType SDL_OHOS_SensorGetDeviceType(int device_index) +{ + Sensor_Type type; + if (OH_SensorInfo_GetType(mapping[device_index].info, &type) != SENSOR_SUCCESS) { + return SDL_SENSOR_INVALID; + } + switch (type) { + case SENSOR_TYPE_ACCELEROMETER: + return SDL_SENSOR_ACCEL; + case SENSOR_TYPE_GYROSCOPE: + return SDL_SENSOR_GYRO; + default: + return SDL_SENSOR_UNKNOWN; + } +} + +static int SDL_OHOS_SensorGetDeviceNonPortableType(int device_index) +{ + Sensor_Type type; + if (OH_SensorInfo_GetType(mapping[device_index].info, &type) != SENSOR_SUCCESS) { + return -1; + } + return type; +} + +static SDL_SensorID SDL_OHOS_SensorGetDeviceInstanceID(int device_index) +{ + return mapping[device_index].id; +} + +static void SDL_OHOS_EventSub(Sensor_Event *event) +{ + Sensor_Type type; + if (OH_SensorEvent_GetType(event, &type) != SENSOR_SUCCESS) { + return; + } + int64_t timestamp; + if (OH_SensorEvent_GetTimestamp(event, ×tamp) != SENSOR_SUCCESS) { + return; + } + + for (int i = 0; i < sensorCount; i++) { + if (mapping[i].sensor && SDL_OHOS_SensorGetDeviceNonPortableType(i) == type) { + uint32_t length; + if (OH_SensorEvent_GetData(event, NULL, &length) != SENSOR_SUCCESS) { + return; + } + float *data = (float *)SDL_malloc(sizeof(float) * length); + if (OH_SensorEvent_GetData(event, &data, &length) != SENSOR_SUCCESS) { + return; + } + SDL_SendSensorUpdate(timestamp, mapping[i].sensor, timestamp, data, length); + SDL_free(data); + break; + } + } +} + +static bool SDL_OHOS_SensorOpen(SDL_Sensor *sensor, int device_index) +{ + if (device_index >= sensorCount) { + return false; + } + mapping[device_index].sensor = sensor; + + mapping[device_index].subs = OH_Sensor_CreateSubscriber(); + if (OH_SensorSubscriber_SetCallback(mapping[device_index].subs, SDL_OHOS_EventSub) != SENSOR_SUCCESS) { + return false; + } + + mapping[device_index].subid = OH_Sensor_CreateSubscriptionId(); + if (OH_SensorSubscriptionId_SetType(mapping[device_index].subid, (Sensor_Type)SDL_OHOS_SensorGetDeviceNonPortableType(device_index)) != SENSOR_SUCCESS) { + return false; + } + + mapping[device_index].subattr = OH_Sensor_CreateSubscriptionAttribute(); + if (OH_SensorSubscriptionAttribute_SetSamplingInterval(mapping[device_index].subattr, 10000000) != SENSOR_SUCCESS) { + return false; + } + + if (OH_Sensor_Subscribe(mapping[device_index].subid, mapping[device_index].subattr, mapping[device_index].subs) != SENSOR_SUCCESS) { + return false; + } + + return true; +} + +static void SDL_OHOS_SensorUpdate(SDL_Sensor *sensor) +{ +} + +static void SDL_OHOS_SensorClose(SDL_Sensor *sensor) +{ + for (int i = 0; i < sensorCount; i++) { + if (mapping[i].sensor == sensor) { + mapping[i].sensor = NULL; + OH_Sensor_Unsubscribe(mapping[i].subid, mapping[i].subs); + if (mapping[i].subattr) { + OH_Sensor_DestroySubscriptionAttribute(mapping[i].subattr); + mapping[i].subattr = NULL; + } + if (mapping[i].subid) { + OH_Sensor_DestroySubscriptionId(mapping[i].subid); + mapping[i].subid = NULL; + } + if (mapping[i].subs) { + OH_Sensor_DestroySubscriber(mapping[i].subs); + mapping[i].subs = NULL; + } + break; + } + } +} + +static void SDL_OHOS_SensorQuit(void) +{ + for (int i = 0; i < sensorCount; i++) { + if (mapping[i].sensor) { + SDL_OHOS_SensorClose(mapping[i].sensor); + } + } + sensorCount = 0; + SDL_free(mapping); +} + +SDL_SensorDriver SDL_OHOS_SensorDriver = { + SDL_OHOS_SensorInit, + SDL_OHOS_SensorGetCount, + SDL_OHOS_SensorDetect, + SDL_OHOS_SensorGetDeviceName, + SDL_OHOS_SensorGetDeviceType, + SDL_OHOS_SensorGetDeviceNonPortableType, + SDL_OHOS_SensorGetDeviceInstanceID, + SDL_OHOS_SensorOpen, + SDL_OHOS_SensorUpdate, + SDL_OHOS_SensorClose, + SDL_OHOS_SensorQuit, +}; + +#endif // SDL_SENSOR_DUMMY || SDL_SENSOR_DISABLED diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index eb13d02490..53e535a7b7 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -171,7 +171,7 @@ void SDL_SYS_SetupThread(const char *name) pthread_sigmask(SIG_BLOCK, &mask, NULL); #endif -#ifdef PTHREAD_CANCEL_ASYNCHRONOUS +#if defined(PTHREAD_CANCEL_ASYNCHRONOUS) && !defined(SDL_PLATFORM_OHOS) // Allow ourselves to be asynchronously cancelled { int oldstate; diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 76d924c25d..e75fc40190 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -547,6 +547,7 @@ extern VideoBootStrap OFFSCREEN_bootstrap; extern VideoBootStrap QNX_bootstrap; extern VideoBootStrap OPENVR_bootstrap; extern VideoBootStrap DOSVESA_bootstrap; +extern VideoBootStrap OHOS_bootstrap; extern bool SDL_UninitializedVideo(void); // Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 98fd06d2b3..873ce784ab 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -110,6 +110,9 @@ static VideoBootStrap *bootstrap[] = { #ifdef SDL_VIDEO_DRIVER_ANDROID &Android_bootstrap, #endif +#ifdef SDL_VIDEO_DRIVER_OHOS + &OHOS_bootstrap, +#endif #ifdef SDL_VIDEO_DRIVER_PS2 &PS2_bootstrap, #endif diff --git a/src/video/ohos/SDL_ohosgl.c b/src/video/ohos/SDL_ohosgl.c new file mode 100644 index 0000000000..27f09a6f85 --- /dev/null +++ b/src/video/ohos/SDL_ohosgl.c @@ -0,0 +1,47 @@ +#include "SDL_internal.h" +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../../core/ohos/SDL_ohos.h" +#include "SDL_ohosvideo.h" + +bool OHOS_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context) +{ + if (window && context) { + return SDL_EGL_MakeCurrent(_this, window->internal->egl_surface, context); + } else { + return SDL_EGL_MakeCurrent(_this, NULL, NULL); + } +} + +SDL_GLContext OHOS_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window) +{ + SDL_GLContext result; + + OHOS_LockPage(); + + OHOS_windowDataFill(window); + result = SDL_EGL_CreateContext(_this, window->internal->egl_surface); + + OHOS_UnlockPage(); + + return result; +} + +bool OHOS_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + bool result; + + OHOS_LockPage(); + + result = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface); + + OHOS_UnlockPage(); + + return result; +} + +bool OHOS_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) +{ + return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType)0); +} + +#endif diff --git a/src/video/ohos/SDL_ohosgl.h b/src/video/ohos/SDL_ohosgl.h new file mode 100644 index 0000000000..b168dbeb3d --- /dev/null +++ b/src/video/ohos/SDL_ohosgl.h @@ -0,0 +1,9 @@ +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "SDL_ohosvideo.h" + +bool OHOS_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context); +SDL_GLContext OHOS_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window); +bool OHOS_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); +bool OHOS_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path); + +#endif diff --git a/src/video/ohos/SDL_ohoskeyboard.c b/src/video/ohos/SDL_ohoskeyboard.c new file mode 100644 index 0000000000..86ee21685d --- /dev/null +++ b/src/video/ohos/SDL_ohoskeyboard.c @@ -0,0 +1,3148 @@ +#include "SDL3/SDL_scancode.h" +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_OHOS + +#include "../../events/SDL_events_c.h" + +static SDL_Scancode OHOS_Keycodes[] = { + SDL_SCANCODE_UNKNOWN, // KEY_FN + SDL_SCANCODE_AC_HOME, + SDL_SCANCODE_AC_BACK, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_MEDIA_PAUSE, + SDL_SCANCODE_MEDIA_STOP, + SDL_SCANCODE_MEDIA_NEXT_TRACK, + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, + SDL_SCANCODE_MEDIA_REWIND, + SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_FAST_FORWARD + SDL_SCANCODE_VOLUMEUP, + SDL_SCANCODE_VOLUMEDOWN, + SDL_SCANCODE_POWER, + SDL_SCANCODE_UNKNOWN, // KEY_CAMERA + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_MUTE, + SDL_SCANCODE_MUTE, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_UP + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_DOWN + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_0, + SDL_SCANCODE_1, + SDL_SCANCODE_2, + SDL_SCANCODE_3, + SDL_SCANCODE_4, + SDL_SCANCODE_5, + SDL_SCANCODE_6, + SDL_SCANCODE_7, + SDL_SCANCODE_8, + SDL_SCANCODE_9, + SDL_SCANCODE_UNKNOWN, // KEY_STAR + SDL_SCANCODE_UNKNOWN, // KEY_POUND + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, // KEY_DPAD_DOWN + SDL_SCANCODE_LEFT, // KEY_DPAD_LEFT + SDL_SCANCODE_RIGHT, // KEY_DPAD_RIGHT + SDL_SCANCODE_SELECT, // KEY_DPAD_CENTER + SDL_SCANCODE_A, + SDL_SCANCODE_B, + SDL_SCANCODE_C, + SDL_SCANCODE_D, + SDL_SCANCODE_E, + SDL_SCANCODE_F, + SDL_SCANCODE_G, + SDL_SCANCODE_H, + SDL_SCANCODE_I, + SDL_SCANCODE_J, + SDL_SCANCODE_K, + SDL_SCANCODE_L, + SDL_SCANCODE_M, + SDL_SCANCODE_N, + SDL_SCANCODE_O, + SDL_SCANCODE_P, + SDL_SCANCODE_Q, + SDL_SCANCODE_R, + SDL_SCANCODE_S, + SDL_SCANCODE_T, + SDL_SCANCODE_U, + SDL_SCANCODE_V, + SDL_SCANCODE_W, + SDL_SCANCODE_X, + SDL_SCANCODE_Y, + SDL_SCANCODE_Z, + SDL_SCANCODE_COMMA, + SDL_SCANCODE_PERIOD, + SDL_SCANCODE_LALT, + SDL_SCANCODE_RALT, + SDL_SCANCODE_LSHIFT, + SDL_SCANCODE_RSHIFT, + SDL_SCANCODE_TAB, + SDL_SCANCODE_SPACE, + SDL_SCANCODE_UNKNOWN, // KEY_SYM + SDL_SCANCODE_UNKNOWN, // KEY_EXPLORER + SDL_SCANCODE_UNKNOWN, // KEY_ENVELOPE + SDL_SCANCODE_RETURN, + SDL_SCANCODE_BACKSPACE, + SDL_SCANCODE_GRAVE, + SDL_SCANCODE_MINUS, + SDL_SCANCODE_EQUALS, + SDL_SCANCODE_LEFTBRACKET, + SDL_SCANCODE_RIGHTBRACKET, + SDL_SCANCODE_BACKSLASH, + SDL_SCANCODE_SEMICOLON, + SDL_SCANCODE_APOSTROPHE, + SDL_SCANCODE_SLASH, + SDL_SCANCODE_UNKNOWN, // KEY_AT + SDL_SCANCODE_UNKNOWN, // KEY_PLUS + SDL_SCANCODE_MENU, + SDL_SCANCODE_PAGEUP, + SDL_SCANCODE_PAGEDOWN, + SDL_SCANCODE_ESCAPE, + SDL_SCANCODE_DELETE, + SDL_SCANCODE_LCTRL, + SDL_SCANCODE_RCTRL, + SDL_SCANCODE_CAPSLOCK, + SDL_SCANCODE_SCROLLLOCK, + SDL_SCANCODE_LGUI, // KEY_META_LEFT + SDL_SCANCODE_RGUI, // KEY_META_RIGHT + SDL_SCANCODE_UNKNOWN, // KEY_FUNCTION + SDL_SCANCODE_SYSREQ, + SDL_SCANCODE_PAUSE, // KEY_BREAK + SDL_SCANCODE_HOME, + SDL_SCANCODE_END, + SDL_SCANCODE_INSERT, + SDL_SCANCODE_AC_FORWARD, + SDL_SCANCODE_MEDIA_PLAY, + SDL_SCANCODE_MEDIA_PAUSE, + SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_CLOSE + SDL_SCANCODE_MEDIA_EJECT, + SDL_SCANCODE_MEDIA_RECORD, + SDL_SCANCODE_F1, + SDL_SCANCODE_F2, + SDL_SCANCODE_F3, + SDL_SCANCODE_F4, + SDL_SCANCODE_F5, + SDL_SCANCODE_F6, + SDL_SCANCODE_F7, + SDL_SCANCODE_F8, + SDL_SCANCODE_F9, + SDL_SCANCODE_F10, + SDL_SCANCODE_F11, + SDL_SCANCODE_F12, + SDL_SCANCODE_NUMLOCKCLEAR, + SDL_SCANCODE_KP_0, + SDL_SCANCODE_KP_1, + SDL_SCANCODE_KP_2, + SDL_SCANCODE_KP_3, + SDL_SCANCODE_KP_4, + SDL_SCANCODE_KP_5, + SDL_SCANCODE_KP_6, + SDL_SCANCODE_KP_7, + SDL_SCANCODE_KP_8, + SDL_SCANCODE_KP_9, + SDL_SCANCODE_KP_DIVIDE, + SDL_SCANCODE_KP_MULTIPLY, + SDL_SCANCODE_KP_MINUS, + SDL_SCANCODE_KP_PLUS, + SDL_SCANCODE_KP_PERIOD, + SDL_SCANCODE_KP_COMMA, + SDL_SCANCODE_KP_ENTER, + SDL_SCANCODE_KP_EQUALS, + SDL_SCANCODE_KP_LEFTPAREN, + SDL_SCANCODE_KP_RIGHTPAREN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_VIRTUAL_MULTITASK + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_SLEEP, + SDL_SCANCODE_LANG5, + SDL_SCANCODE_UNKNOWN, // KEY_102ND + SDL_SCANCODE_UNKNOWN, // KEY_RO + SDL_SCANCODE_UNKNOWN, // KEY_KATAKANA + SDL_SCANCODE_UNKNOWN, // KEY_HIRAGANA + SDL_SCANCODE_INTERNATIONAL4, + SDL_SCANCODE_LANG3, + SDL_SCANCODE_INTERNATIONAL5, + SDL_SCANCODE_UNKNOWN, // KEY_LINEFEED + SDL_SCANCODE_UNKNOWN, // KEY_MACRO + SDL_SCANCODE_UNKNOWN, // KEY_PLUSMINUS + SDL_SCANCODE_UNKNOWN, // KEY_SCALE + SDL_SCANCODE_UNKNOWN, // KEY_HANGUEL + SDL_SCANCODE_UNKNOWN, // KEY_HANJA + SDL_SCANCODE_INTERNATIONAL3, + SDL_SCANCODE_UNKNOWN, // KEY_STOP + SDL_SCANCODE_UNKNOWN, // KEY_AGAIN + SDL_SCANCODE_UNKNOWN, // KEY_PROPS + SDL_SCANCODE_UNDO, + SDL_SCANCODE_COPY, + SDL_SCANCODE_UNKNOWN, // KEY_OPEN + SDL_SCANCODE_PASTE, + SDL_SCANCODE_FIND, + SDL_SCANCODE_CUT, + SDL_SCANCODE_HELP, + SDL_SCANCODE_UNKNOWN, // KEY_CALC + SDL_SCANCODE_UNKNOWN, // KEY_FILE + SDL_SCANCODE_AC_BOOKMARKS, + SDL_SCANCODE_MEDIA_NEXT_TRACK, + SDL_SCANCODE_MEDIA_PLAY_PAUSE, + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, + SDL_SCANCODE_MEDIA_STOP, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_CONFIG + SDL_SCANCODE_UNKNOWN, // KEY_REFRESH + SDL_SCANCODE_UNKNOWN, // KEY_EXIT + SDL_SCANCODE_UNKNOWN, // KEY_EDIT + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, + SDL_SCANCODE_UNKNOWN, // KEY_NEW + SDL_SCANCODE_UNKNOWN, // KEY_REDO + SDL_SCANCODE_UNKNOWN, // KEY_CLOSE + SDL_SCANCODE_MEDIA_PLAY, + SDL_SCANCODE_UNKNOWN, // KEY_BASSBOOST + SDL_SCANCODE_PRINTSCREEN, + SDL_SCANCODE_UNKNOWN, // KEY_CHAT + SDL_SCANCODE_UNKNOWN, // KEY_FINANCE + SDL_SCANCODE_UNKNOWN, // KEY_CANCEL + SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUM_TOGGLE + SDL_SCANCODE_DOWN, + SDL_SCANCODE_UP, + SDL_SCANCODE_UNKNOWN, // KEY_SEND + SDL_SCANCODE_UNKNOWN, // KEY_REPLY + SDL_SCANCODE_UNKNOWN, // KEY_FORWARDMAIL + SDL_SCANCODE_UNKNOWN, // KEY_SAVE + SDL_SCANCODE_UNKNOWN, // KEY_DOCUMENTS + SDL_SCANCODE_MEDIA_NEXT_TRACK, + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_CYCLE + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_ZERO + SDL_SCANCODE_UNKNOWN, // KEY_DISPLAY_OFF + SDL_SCANCODE_UNKNOWN, // KEY_BTN_MISC + SDL_SCANCODE_UNKNOWN, // KEY_GOTO + SDL_SCANCODE_UNKNOWN, // KEY_INFO + SDL_SCANCODE_UNKNOWN, // KEY_PROGRAM + SDL_SCANCODE_UNKNOWN, // KEY_PVR + SDL_SCANCODE_UNKNOWN, // KEY_SUBTITLE + SDL_SCANCODE_UNKNOWN, // KEY_FULLSCREEN + SDL_SCANCODE_UNKNOWN, // KEY_KEYBOARD + SDL_SCANCODE_UNKNOWN, // KEY_ASPECT_RATIO + SDL_SCANCODE_UNKNOWN, // KEY_PC + SDL_SCANCODE_UNKNOWN, // KEY_TV + SDL_SCANCODE_UNKNOWN, // KEY_TV2 + SDL_SCANCODE_UNKNOWN, // KEY_VCR + SDL_SCANCODE_UNKNOWN, // KEY_VCR2 + SDL_SCANCODE_UNKNOWN, // KEY_SAT + SDL_SCANCODE_UNKNOWN, // KEY_CD + SDL_SCANCODE_UNKNOWN, // KEY_TAPE + SDL_SCANCODE_UNKNOWN, // KEY_TUNER + SDL_SCANCODE_UNKNOWN, // KEY_PLAYER + SDL_SCANCODE_UNKNOWN, // KEY_DVD + SDL_SCANCODE_UNKNOWN, // KEY_AUDIO + SDL_SCANCODE_UNKNOWN, // KEY_VIDEO + SDL_SCANCODE_UNKNOWN, // KEY_MEMO + SDL_SCANCODE_UNKNOWN, // KEY_CALENDER + SDL_SCANCODE_UNKNOWN, // KEY_RED + SDL_SCANCODE_UNKNOWN, // KEY_GREEN + SDL_SCANCODE_UNKNOWN, // KEY_YELLOW + SDL_SCANCODE_UNKNOWN, // KEY_BLUE + SDL_SCANCODE_CHANNEL_INCREMENT, + SDL_SCANCODE_CHANNEL_DECREMENT, + SDL_SCANCODE_UNKNOWN, // KEY_LAST + SDL_SCANCODE_UNKNOWN, // KEY_RESTART + SDL_SCANCODE_UNKNOWN, // KEY_SLOW + SDL_SCANCODE_UNKNOWN, // KEY_SHUFFLE + SDL_SCANCODE_UNKNOWN, // KEY_VIDEOPHONE + SDL_SCANCODE_UNKNOWN, // KEY_GAMES + SDL_SCANCODE_UNKNOWN, // KEY_ZOOMIN + SDL_SCANCODE_UNKNOWN, // KEY_ZOOMOUT + SDL_SCANCODE_UNKNOWN, // KEY_ZOOMRESET + SDL_SCANCODE_UNKNOWN, // KEY_WORDPROCESSOR + SDL_SCANCODE_UNKNOWN, // KEY_EDITOR + SDL_SCANCODE_UNKNOWN, // KEY_SPREADSHEET + SDL_SCANCODE_UNKNOWN, // KEY_GRAPHICSEDITOR + SDL_SCANCODE_UNKNOWN, // KEY_PRESENTATION + SDL_SCANCODE_UNKNOWN, // KEY_DATABASE + SDL_SCANCODE_UNKNOWN, // KEY_NEWS + SDL_SCANCODE_UNKNOWN, // KEY_VOICEMAIL + SDL_SCANCODE_UNKNOWN, // KEY_ADDRESSBOOK + SDL_SCANCODE_UNKNOWN, // KEY_MESSENGER + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_TOGGLE + SDL_SCANCODE_UNKNOWN, // KEY_SPELLCHECK + SDL_SCANCODE_UNKNOWN, // KEY_COFFEE + SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_REPEAT + SDL_SCANCODE_UNKNOWN, // KEY_IMAGES + SDL_SCANCODE_UNKNOWN, // KEY_BUTTONCONFIG + SDL_SCANCODE_UNKNOWN, // KEY_TASKMANAGER + SDL_SCANCODE_UNKNOWN, // KEY_JOURNAL + SDL_SCANCODE_UNKNOWN, // KEY_CONTROLPANEL + SDL_SCANCODE_UNKNOWN, // KEY_APPSELECT + SDL_SCANCODE_UNKNOWN, // KEY_SCREENSAVER + SDL_SCANCODE_UNKNOWN, // KEY_ASSISTANT + SDL_SCANCODE_UNKNOWN, // KEY_KBD_LAYOUT_NEXT + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MIN + SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MAX + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_PREV + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_NEXT + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_PREVGROUP + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_NEXTGROUP + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_ACCEPT + SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSISTANT_CANCEL + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_FRONT + SDL_SCANCODE_UNKNOWN, // KEY_SETUP + SDL_SCANCODE_UNKNOWN, // KEY_WAKEUP + SDL_SCANCODE_UNKNOWN, // KEY_SENDFILE + SDL_SCANCODE_UNKNOWN, // KEY_XFER + SDL_SCANCODE_UNKNOWN, // KEY_PROG1 + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_PROG2 + SDL_SCANCODE_UNKNOWN, // KEY_MSDOS + SDL_SCANCODE_UNKNOWN, // KEY_SCREENLOCK + SDL_SCANCODE_UNKNOWN, // KEY_DIRECTION_ROTATE_DISPLAY + SDL_SCANCODE_UNKNOWN, // KEY_CYCLEWINDOWS + SDL_SCANCODE_UNKNOWN, // KEY_COMPUTER + SDL_SCANCODE_UNKNOWN, // KEY_EJECTCLOSECD + SDL_SCANCODE_UNKNOWN, // KEY_ISO + SDL_SCANCODE_UNKNOWN, // KEY_MOVE + SDL_SCANCODE_F13, + SDL_SCANCODE_F14, + SDL_SCANCODE_F15, + SDL_SCANCODE_F16, + SDL_SCANCODE_F17, + SDL_SCANCODE_F18, + SDL_SCANCODE_F19, + SDL_SCANCODE_F20, + SDL_SCANCODE_F21, + SDL_SCANCODE_F22, + SDL_SCANCODE_F23, + SDL_SCANCODE_F24, + SDL_SCANCODE_UNKNOWN, // KEY_PROG3 + SDL_SCANCODE_UNKNOWN, // KEY_PROG4 + SDL_SCANCODE_UNKNOWN, // KEY_DASHBOARD + SDL_SCANCODE_UNKNOWN, // KEY_SUSPEND + SDL_SCANCODE_UNKNOWN, // KEY_HP + SDL_SCANCODE_UNKNOWN, // KEY_SOUND + SDL_SCANCODE_UNKNOWN, // KEY_QUESTION + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_CONNECT + SDL_SCANCODE_UNKNOWN, // KEY_SPORT + SDL_SCANCODE_UNKNOWN, // KEY_SHOP + SDL_SCANCODE_UNKNOWN, // KEY_ALTERASE + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_SWITCHVIDEOMODE + SDL_SCANCODE_UNKNOWN, // KEY_BATTERY + SDL_SCANCODE_UNKNOWN, // KEY_BLUETOOTH + SDL_SCANCODE_UNKNOWN, // KEY_WLAN + SDL_SCANCODE_UNKNOWN, // KEY_UWB + SDL_SCANCODE_UNKNOWN, // KEY_WWAN_WIMAX + SDL_SCANCODE_UNKNOWN, // KEY_RFKILL + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_CHANNEL + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, + SDL_SCANCODE_UNKNOWN, // KEY_BTN_0 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_1 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_2 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_3 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_4 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_5 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_6 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_7 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_8 + SDL_SCANCODE_UNKNOWN, // KEY_BTN_9 +}; + +// static bool SDL_screen_keyboard_shown; + +static SDL_Scancode TranslateKeycode(int keycode) +{ + SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; + if (keycode <= -1) { + return SDL_SCANCODE_UNKNOWN; + } + if (keycode < SDL_arraysize(OHOS_Keycodes)) { + scancode = OHOS_Keycodes[keycode]; + } + if (scancode == SDL_SCANCODE_UNKNOWN) { + SDL_Log("Unknown keycode %d", keycode); + } + return scancode; +} + +void OHOS_OnKeyDown(int keycode) +{ + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, keycode, TranslateKeycode(keycode), true); +} + +void OHOS_OnKeyUp(int keycode) +{ + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, keycode, TranslateKeycode(keycode), false); +} + +#endif diff --git a/src/video/ohos/SDL_ohoskeyboard.h b/src/video/ohos/SDL_ohoskeyboard.h new file mode 100644 index 0000000000..5dd55f39c4 --- /dev/null +++ b/src/video/ohos/SDL_ohoskeyboard.h @@ -0,0 +1,4 @@ +#ifdef SDL_VIDEO_DRIVER_OHOS +void OHOS_OnKeyDown(int keycode); +void OHOS_OnKeyUp(int keycode); +#endif diff --git a/src/video/ohos/SDL_ohosmouse.c b/src/video/ohos/SDL_ohosmouse.c new file mode 100644 index 0000000000..b2d075d601 --- /dev/null +++ b/src/video/ohos/SDL_ohosmouse.c @@ -0,0 +1,11 @@ +#include "SDL_internal.h" +#include "events/SDL_mouse_c.h" +#include "SDL_ohosmouse.h" + +void OHOS_OnMouse(SDL_OHOSMouseEvent event) +{ + SDL_SendMouseMotion(event.timestamp, NULL, SDL_DEFAULT_MOUSE_ID, false, event.x, event.y); + if (!event.motion) { + SDL_SendMouseButton(event.timestamp, NULL, SDL_DEFAULT_MOUSE_ID, event.button, event.down); + } +} \ No newline at end of file diff --git a/src/video/ohos/SDL_ohosmouse.h b/src/video/ohos/SDL_ohosmouse.h new file mode 100644 index 0000000000..56310e335c --- /dev/null +++ b/src/video/ohos/SDL_ohosmouse.h @@ -0,0 +1,15 @@ +#ifndef SDL_OHOSMOUSE_H +#define SDL_OHOSMOUSE_H + +typedef struct SDL_OHOSMouseEvent { + float x; + float y; + long long timestamp; + int button; + bool motion; + bool down; +} SDL_OHOSMouseEvent; + +void OHOS_OnMouse(SDL_OHOSMouseEvent event); + +#endif diff --git a/src/video/ohos/SDL_ohostouch.c b/src/video/ohos/SDL_ohostouch.c new file mode 100644 index 0000000000..a7f16bfedc --- /dev/null +++ b/src/video/ohos/SDL_ohostouch.c @@ -0,0 +1,34 @@ +#include "SDL_ohostouch.h" +#include "../../events/SDL_touch_c.h" +#include "SDL_internal.h" + +void OHOS_OnTouch(SDL_OHOSTouchEvent event) +{ + if (SDL_AddTouch(event.deviceId, SDL_TOUCH_DEVICE_DIRECT, "") < 0) { + SDL_Log("Cannot add touch"); + return; + } + + switch (event.type) { + case SDL_EVENT_FINGER_DOWN: + { + SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_DOWN, event.x, event.y, event.p); + break; + } + case SDL_EVENT_FINGER_MOTION: + { + SDL_SendTouchMotion(event.timestamp, event.deviceId, event.fingerId, NULL, event.x, event.y, event.p); + break; + } + case SDL_EVENT_FINGER_UP: + { + SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_UP, event.x, event.y, event.p); + break; + } + case SDL_EVENT_FINGER_CANCELED: + { + SDL_SendTouch(event.timestamp, event.deviceId, event.fingerId, NULL, SDL_EVENT_FINGER_CANCELED, event.x, event.y, event.p); + break; + } + } +} diff --git a/src/video/ohos/SDL_ohostouch.h b/src/video/ohos/SDL_ohostouch.h new file mode 100644 index 0000000000..de33e45316 --- /dev/null +++ b/src/video/ohos/SDL_ohostouch.h @@ -0,0 +1,17 @@ +#ifndef SDL_OHOSTOUCH_H +#define SDL_OHOSTOUCH_H + +typedef struct SDL_OHOSTouchEvent { + long long deviceId; + int fingerId; + int type; + float x; + float y; + float p; + float area; + long long timestamp; +} SDL_OHOSTouchEvent; + +void OHOS_OnTouch(SDL_OHOSTouchEvent event); + +#endif diff --git a/src/video/ohos/SDL_ohosvideo.c b/src/video/ohos/SDL_ohosvideo.c new file mode 100644 index 0000000000..44f1f4f5cd --- /dev/null +++ b/src/video/ohos/SDL_ohosvideo.c @@ -0,0 +1,141 @@ +#include "../SDL_sysvideo.h" +#include "SDL_internal.h" +#include "dynapi/SDL_dynapi_overrides.h" + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../../core/ohos/SDL_ohos.h" +#include "SDL_ohosgl.h" +#include "SDL_ohosvulkan.h" +#include "SDL_ohoswindow.h" + +bool OHOS_VideoInit(SDL_VideoDevice *_this) +{ + SDL_DisplayMode mode; + SDL_zero(mode); + mode.format = SDL_PIXELFORMAT_RGBA32; + mode.w = OHOS_FetchWidth(); + mode.h = OHOS_FetchHeight(); + mode.refresh_rate = 60; + + SDL_AddBasicVideoDisplay(&mode); + return true; +} +void OHOS_VideoQuit(SDL_VideoDevice *_this) +{ +} +void OHOS_DeviceFree(SDL_VideoDevice *device) +{ + SDL_free(device); +} +bool OHOS_SetClipboardTextImpl(SDL_VideoDevice *, const char *data) +{ + OHOS_SetClipboardText(data); + return true; +} +bool OHOS_HasClipboardText(SDL_VideoDevice *) +{ + return false; +} +bool OHOS_HasScreenKeyboardSupport(SDL_VideoDevice *) +{ + return true; +} +bool OHOS_IsScreenKeyboardShownImpl(SDL_VideoDevice *, SDL_Window *) +{ + return OHOS_IsScreenKeyboardShown(); +} +bool OHOS_StartTextInputImpl(SDL_VideoDevice *, SDL_Window *, SDL_PropertiesID) +{ + OHOS_StartTextInput(); + return true; +} +bool OHOS_StopTextInputImpl(SDL_VideoDevice *, SDL_Window *) +{ + OHOS_StopTextInput(); + return true; +} +void OHOS_PumpEvents(SDL_VideoDevice *) +{ + +} +static SDL_VideoDevice *OHOS_CreateDevice(void) +{ + SDL_VideoDevice *device; + SDL_VideoData *data; + + device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (!device) { + return NULL; + } + + data = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); + if (!data) { + return NULL; + } + + device->internal = data; + device->free = OHOS_DeviceFree; + + device->VideoInit = OHOS_VideoInit; + device->VideoQuit = OHOS_VideoQuit; +#ifdef SDL_VIDEO_VULKAN + device->Vulkan_LoadLibrary = OHOS_Vulkan_LoadLibrary; + device->Vulkan_UnloadLibrary = OHOS_Vulkan_UnloadLibrary; + device->Vulkan_GetInstanceExtensions = OHOS_Vulkan_GetInstanceExtensions; + device->Vulkan_CreateSurface = OHOS_Vulkan_CreateSurface; + device->Vulkan_DestroySurface = OHOS_Vulkan_DestroySurface; +#endif + device->CreateSDLWindow = OHOS_CreateWindow; + device->DestroyWindow = OHOS_DestroyWindow; + +#ifdef SDL_VIDEO_OPENGL_EGL + device->GL_LoadLibrary = OHOS_GLES_LoadLibrary; + device->GL_MakeCurrent = OHOS_GLES_MakeCurrent; + device->GL_CreateContext = OHOS_GLES_CreateContext; + device->GL_SwapWindow = OHOS_GLES_SwapWindow; + device->GL_GetProcAddress = SDL_EGL_GetProcAddressInternal; + device->GL_UnloadLibrary = SDL_EGL_UnloadLibrary; + device->GL_SetSwapInterval = SDL_EGL_SetSwapInterval; + device->GL_GetSwapInterval = SDL_EGL_GetSwapInterval; + device->GL_DestroyContext = SDL_EGL_DestroyContext; +#endif + + device->SetClipboardText = OHOS_SetClipboardTextImpl; + device->HasClipboardText = OHOS_HasClipboardText; + + device->HasScreenKeyboardSupport = OHOS_HasScreenKeyboardSupport; + device->StartTextInput = OHOS_StartTextInputImpl; + device->StopTextInput = OHOS_StopTextInputImpl; + + device->PumpEvents = OHOS_PumpEvents; + + return device; +} +bool OHOS_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) +{ + int length1 = SDL_strlen(messageboxdata->title) + 1; + char* titlecopy = (char*)SDL_malloc(length1); + SDL_memcpy(titlecopy, messageboxdata->title, length1); + length1 = SDL_strlen(messageboxdata->message) + 1; + char* messagecopy = (char*)SDL_malloc(length1); + SDL_memcpy(messagecopy, messageboxdata->message, length1); + + int* mapping = (int *)SDL_malloc(sizeof(int) * messageboxdata->numbuttons); + const char ** btns = (const char **)SDL_malloc(sizeof(void*) * messageboxdata->numbuttons); + + for (int i = 0; i < messageboxdata->numbuttons; i++) + { + mapping[i] = messageboxdata->buttons[i].buttonID; + btns[i] = messageboxdata->buttons[i].text; + } + + *buttonID = OHOS_MessageBox(titlecopy, messagecopy, messageboxdata->numbuttons, mapping, messageboxdata->numbuttons, btns); + return true; +} +VideoBootStrap OHOS_bootstrap = { + "ohos", "OpenHarmony video driver", + OHOS_CreateDevice, + OHOS_ShowMessageBox, + false +}; +#endif diff --git a/src/video/ohos/SDL_ohosvideo.h b/src/video/ohos/SDL_ohosvideo.h new file mode 100644 index 0000000000..a27ee2e226 --- /dev/null +++ b/src/video/ohos/SDL_ohosvideo.h @@ -0,0 +1,17 @@ +#ifndef SDL_OHOSVIDEO_H +#define SDL_OHOSVIDEO_H + +#include "../SDL_egl_c.h" +#include "../../core/ohos/SDL_ohos.h" +struct SDL_WindowData { +#ifdef SDL_VIDEO_OPENGL_EGL + EGLSurface egl_surface; + EGLContext egl_context; +#endif + bool backup_done; + OHNativeWindow *native_window; + uint64_t width; + uint64_t height; +}; + +#endif diff --git a/src/video/ohos/SDL_ohosvulkan.c b/src/video/ohos/SDL_ohosvulkan.c new file mode 100644 index 0000000000..e33aece5a7 --- /dev/null +++ b/src/video/ohos/SDL_ohosvulkan.c @@ -0,0 +1,130 @@ +#include "SDL_ohosvulkan.h" +#include "SDL_internal.h" +#include + +#ifdef SDL_VIDEO_DRIVER_OHOS +#define VK_USE_PLATFORM_OHOS 1 +#include "../../core/ohos/SDL_ohos.h" +#include "../SDL_sysvideo.h" +#include "SDL_ohosvideo.h" +#include "vulkan/vulkan.h" +#include "vulkan/vulkan_ohos.h" +#include + +static int loadedCount = 0; +bool OHOS_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) +{ + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; + if (_this->vulkan_config.loader_handle) { + return SDL_SetError("Vulkan already loaded"); + } + + /* Load the Vulkan loader library */ + if (!path) { + path = SDL_getenv("SDL_VULKAN_LIBRARY"); + } + if (!path) { + path = "libvulkan.so"; + } + _this->vulkan_config.loader_handle = SDL_LoadObject(path); + if (!_this->vulkan_config.loader_handle) { + return false; + } + SDL_strlcpy(_this->vulkan_config.loader_path, path, + SDL_arraysize(_this->vulkan_config.loader_path)); + vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction( + _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr"); + if (!vkGetInstanceProcAddr) { + goto fail; + } + _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr; + _this->vulkan_config.vkEnumerateInstanceExtensionProperties = + (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)( + VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"); + if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) { + goto fail; + } + loadedCount++; + return true; + +fail: + SDL_UnloadObject(_this->vulkan_config.loader_handle); + _this->vulkan_config.loader_handle = NULL; + return false; +} + +void OHOS_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) +{ + if (loadedCount == 0) { + return; + } + loadedCount--; + if (_this->vulkan_config.loader_handle && loadedCount == 0) { + SDL_UnloadObject(_this->vulkan_config.loader_handle); + _this->vulkan_config.loader_handle = NULL; + } +} + +char const *const *OHOS_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count) +{ + static const char *const extensionsForOHOS[] = { + VK_KHR_SURFACE_EXTENSION_NAME, VK_OHOS_SURFACE_EXTENSION_NAME + }; + if (count) { + *count = SDL_arraysize(extensionsForOHOS); + } + return extensionsForOHOS; +} + +bool OHOS_Vulkan_CreateSurface(SDL_VideoDevice *_this, + SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface) +{ + VkResult result; + + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkCreateSurfaceOHOS vkCreateSurfaceOHOS = + (PFN_vkCreateSurfaceOHOS)vkGetInstanceProcAddr(instance, "vkCreateSurfaceOHOS"); + VkSurfaceCreateInfoOHOS createInfo; + + if (!_this->vulkan_config.loader_handle) { + SDL_SetError("Vulkan is not loaded"); + return false; + } + + if (!vkCreateSurfaceOHOS) { + SDL_SetError(VK_OHOS_SURFACE_EXTENSION_NAME + " extension is not enabled in the Vulkan instance."); + return false; + } + + SDL_zero(createInfo); + createInfo.sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.window = window->internal->native_window; + result = vkCreateSurfaceOHOS(instance, &createInfo, NULL, surface); + if (result != VK_SUCCESS) { + SDL_SetError("vkCreateSurfaceOHOS failed: %d", result); + return false; + } + return true; +} + +void OHOS_Vulkan_DestroySurface(SDL_VideoDevice *_this, + VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator) +{ + if (_this->vulkan_config.loader_handle) { + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = + (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR"); + vkDestroySurfaceKHR(instance, surface, allocator); + } +} + +#endif diff --git a/src/video/ohos/SDL_ohosvulkan.h b/src/video/ohos/SDL_ohosvulkan.h new file mode 100644 index 0000000000..5700c29866 --- /dev/null +++ b/src/video/ohos/SDL_ohosvulkan.h @@ -0,0 +1,21 @@ +#ifndef SDL_OHOSVULKAN_H +#define SDL_OHOSVULKAN_H + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../SDL_sysvideo.h" + +bool OHOS_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); +void OHOS_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); +char const* const* OHOS_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count); +bool OHOS_Vulkan_CreateSurface(SDL_VideoDevice *_this, + SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR *surface); +void OHOS_Vulkan_DestroySurface(SDL_VideoDevice *_this, + VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator); +#endif + +#endif diff --git a/src/video/ohos/SDL_ohoswindow.c b/src/video/ohos/SDL_ohoswindow.c new file mode 100644 index 0000000000..b74c725558 --- /dev/null +++ b/src/video/ohos/SDL_ohoswindow.c @@ -0,0 +1,20 @@ +#include "SDL_ohoswindow.h" +#include "SDL_internal.h" +#include + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../../core/ohos/SDL_ohos.h" +#include "SDL_ohosvideo.h" +bool OHOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) +{ + OHOS_windowDataFill(window); + + return true; +} + +void OHOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) +{ + OHOS_removeWindow(window); +} + +#endif diff --git a/src/video/ohos/SDL_ohoswindow.h b/src/video/ohos/SDL_ohoswindow.h new file mode 100644 index 0000000000..b611951a79 --- /dev/null +++ b/src/video/ohos/SDL_ohoswindow.h @@ -0,0 +1,8 @@ +#include "SDL_internal.h" + +#ifdef SDL_VIDEO_DRIVER_OHOS +#include "../SDL_sysvideo.h" +bool OHOS_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); +void OHOS_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); + +#endif