OpenHarmony port: events

This commit is contained in:
Coder2 2025-09-06 17:04:55 +08:00
parent 2ebb95078e
commit fcbdd08a0f
11 changed files with 380 additions and 19 deletions

View file

@ -8,7 +8,13 @@ if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
add_subdirectory(../../../../.. external/sdlbin)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../SDL_port)
add_subdirectory(../../../../../SDL_port external/sdlbin)
else()
message(FATAL_ERROR "没有找到 SDL 主项目,需要将 OpenMinecraft-Dev/SDL clone 到与本项目同位置的文件夹中")
endif()
# add_subdirectory(../../../../../openal-soft external/openalbin)
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
add_definitions(-DVK_USE_PLATFORM_OHOS=1)
@ -18,4 +24,4 @@ include_directories(${NATIVERENDER_ROOT_PATH}
add_library(entry SHARED napi_init.cpp)
add_dependencies(entry SDL3::SDL3-shared)
target_link_libraries(entry PUBLIC libace_napi.z.so libSDL3.so libvulkan.so libGLESv2.so)
target_link_libraries(entry PUBLIC libace_napi.z.so libSDL3.so libvulkan.so libGLESv2.so libohaudio.so)

View file

@ -6,6 +6,7 @@
#include "SDL3/SDL_video.h"
#include "SDL3/SDL_vulkan.h"
#include "SDL3/SDL_locale.h"
#include "SDL3/SDL_clipboard.h"
#include "napi/native_api.h"
#include "SDL3/SDL_log.h"
#include "SDL3/SDL_hints.h"
@ -14,6 +15,8 @@
#include <thread>
#include <unistd.h>
#include <vulkan/vulkan_core.h>
#include <ohaudio/native_audiorenderer.h>
#include <ohaudio/native_audiostreambuilder.h>
static napi_value Add(napi_env env, napi_callback_info info)
{
@ -67,6 +70,40 @@ float vtxdata2[] = {
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");
@ -82,6 +119,8 @@ int main()
SDL_Window* win = SDL_CreateWindow("test", 1024, 1024, SDL_WINDOW_OPENGL);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "SDL Application", "test!", win);
SDL_StartTextInput(win);
// SDL_StopTextInput();
auto context = SDL_GL_CreateContext(win);
SDL_GL_MakeCurrent(win, context);
@ -129,10 +168,11 @@ int main()
((PFNGLCLEARPROC)SDL_GL_GetProcAddress("glClear"))(GL_COLOR_BUFFER_BIT);
((PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"))(prog);
for (int i = 0; i < 9; i++) {
vtxdata2[i] += 0.01f;
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);
@ -140,8 +180,17 @@ int main()
((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("%f %f", event.tfinger.x, event.tfinger.y);
}
}
}
SDL_Log("glversion: %s", ((PFNGLGETSTRINGPROC)SDL_GL_GetProcAddress("glGetString"))(GL_VERSION));

View file

@ -1,2 +1,5 @@
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;

View file

@ -10,7 +10,7 @@ import { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN = 0x0000;
const permissions: Array<Permissions> = ['ohos.permission.INPUT_KEYBOARD_CONTROLLER'];
const permissions: Array<Permissions> = ['ohos.permission.INPUT_KEYBOARD_CONTROLLER', 'ohos.permission.READ_PASTEBOARD'];
function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
@ -18,9 +18,9 @@ function reqPermissionsFromUser(permissions: Array<Permissions>, context: common
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'}]});
// promptAction.showDialog({title: "permissions", message: "granted", buttons: [{text: 'Ok', color: '#999999'}]});
} else {
promptAction.showDialog({title: "permissions", message: "not granted", buttons: [{text: 'Ok', color: '#999999'}]});
// promptAction.showDialog({title: "permissions", message: "not granted", buttons: [{text: 'Ok', color: '#999999'}]});
return;
}
}

View file

@ -2,9 +2,16 @@ import { hilog } from '@kit.PerformanceAnalysisKit';
import sdltest from 'libSDL3.so';
import { intl } from '@kit.LocalizationKit';
import { promptAction } from '@kit.ArkUI';
import { inputMethod } from '@kit.IMEKit'
import { Action, Key, KeyEvent } from '@kit.InputKit';
import { pasteboard, BusinessError } from '@kit.BasicServicesKit';
const DOMAIN = 0x0000;
let controller = inputMethod.getController()
let input = false
let targetText = ""
export class ArkNapiCallback {
onMainLaunch() {
sdltest.sdlLaunchMain("libentry.so", "main")
@ -20,6 +27,35 @@ export class ArkNapiCallback {
hilog.info(DOMAIN, 'testTag', 'Call from native !!!')
return 1
}
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, 'testTag', 'Failed to set PasteData. Cause: ' + err.message);
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeed in setting PasteData.');
});
}
textEditing(): number {
return input ? 1 : 0;
}
startTextInput() {
input = true
controller.showTextInput()
hilog.info(DOMAIN, 'testTag', 'text input start')
}
stopTextInput() {
input = false
controller.hideTextInput()
hilog.info(DOMAIN, 'testTag', 'text input stop')
targetText = ""
}
}
let callbackRef: ArkNapiCallback = new ArkNapiCallback()
@ -27,21 +63,45 @@ let callbackRef: ArkNapiCallback = new ArkNapiCallback()
@Entry
@Component
struct Index {
aboutToAppear(): void {
async aboutToAppear(): Promise<void> {
sdltest.sdlCallbackInit(callbackRef)
focusControl.requestFocus('mainView')
await controller.attach(true, {
inputAttribute: {
textInputType: inputMethod.TextInputType.TEXT,
enterKeyType: inputMethod.EnterKeyType.DONE
}
});
controller.on('insertText', (text) => {
targetText += text;
sdltest.sdlTextAppend(text)
})
controller.on('deleteLeft', (i) => {
sdltest.sdlTextEditing(targetText, targetText.length - 1 - i, i);
if (targetText.length > 0) {
targetText = targetText.substring(0, targetText.length - i)
}
hilog.info(DOMAIN, 'testTag', targetText)
})
controller.on('deleteRight', (i) => {
sdltest.sdlTextEditing(targetText, 0, i);
if (targetText.length > 0) {
targetText = targetText.substring(i, targetText.length)
}
hilog.info(DOMAIN, 'testTag', targetText)
})
}
build() {
Column() {
XComponent({ id: 'mainView', type: 'surface', libraryname: 'SDL3' })
.id('mainView')
TextInput().id('inputHandler').onChange((value: string) => {
hilog.info(DOMAIN, 'testTag', value)
}).onSubmit(() => {
hilog.info(DOMAIN, 'testTag', "submit")
})
}
.onKeyEvent((keyevent) => {
sdltest.sdlKeyEvent(keyevent.keyCode, keyevent.type);
})
.alignItems(HorizontalAlign.End)
.justifyContent(FlexAlign.End)
}

View file

@ -10,6 +10,19 @@
"2in1"
],
"requestPermissions": [
{
"name": "ohos.permission.INPUT_KEYBOARD_CONTROLLER",
"reason": "$string:perm_reason",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"inuse"
}
},
{
"name": "ohos.permission.INTERNET"
}
],
"deliveryWithInstall": true,

View file

@ -1,4 +1,6 @@
#include "SDL_internal.h"
#include "events/SDL_keyboard_c.h"
#include "video/ohos/SDL_ohosmouse.h"
#include <EGL/egl.h>
#include <EGL/eglplatform.h>
#include <dlfcn.h>
@ -224,6 +226,59 @@ static void sdlJSCallback(napi_env env, napi_value jsCb, void *content, void *da
ar->returned = true;
}
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;
}
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) {}
}
void OHOS_MessageBox(const char* title, const char* message)
{
napiCallbackData *data = SDL_malloc(sizeof(napiCallbackData));
@ -438,7 +493,7 @@ static void onNativeTouch(OH_NativeXComponent *component, void *window)
e.timestamp = touchEvent.timeStamp;
// skip assertions
e.deviceId = touchEvent.deviceId + 1;
e.fingerId = touchEvent.touchPoints[i].id;
e.fingerId = touchEvent.touchPoints[i].id + 1;
e.area = touchEvent.touchPoints[i].size;
e.x = touchEvent.touchPoints[i].x / (float)wid;
e.y = touchEvent.touchPoints[i].y / (float)hei;
@ -459,7 +514,7 @@ static void onNativeTouch(OH_NativeXComponent *component, void *window)
e.type = SDL_EVENT_FINGER_CANCELED;
break;
}
OHOS_OnTouch(e);
}
@ -467,14 +522,116 @@ static void onNativeTouch(OH_NativeXComponent *component, void *window)
}
// TODO mouse data
static void onNativeMouse(OH_NativeXComponent *component, void *window) {
onNativeTouch(component, 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);
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);
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 }
{ "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 }
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);

View file

@ -14,6 +14,11 @@ int OHOS_FetchHeight();
void OHOS_MessageBox(const char* title, const char* message);
const char* OHOS_Locale();
void OHOS_SetClipboardText(const char* data);
bool OHOS_IsScreenKeyboardShown();
void OHOS_StartTextInput();
void OHOS_StopTextInput();
typedef struct SDL_VideoData {
SDL_Rect textRect;

View file

@ -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);
}
}

View file

@ -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

View file

@ -1,5 +1,6 @@
#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"
@ -25,6 +26,37 @@ 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)
{
@ -67,6 +99,16 @@ static SDL_VideoDevice *OHOS_CreateDevice(void)
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->IsScreenKeyboardShown = OHOS_IsScreenKeyboardShownImpl;
device->StartTextInput = OHOS_StartTextInputImpl;
device->StopTextInput = OHOS_StopTextInputImpl;
device->PumpEvents = OHOS_PumpEvents;
return device;
}