openharmony: update & merge

This commit is contained in:
Coder2 2026-05-24 18:39:41 +08:00
parent 90fa7317c5
commit 933dbbefc4
No known key found for this signature in database
GPG key ID: 98C112D1F699AA4C
6 changed files with 322 additions and 292 deletions

View file

@ -1,19 +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"
}
}
{
"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"
}
}
}

View file

@ -1,208 +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 { 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<string>) => {
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;
}
}
let callbackRef: ArkNapiCallback = new ArkNapiCallback()
@Entry
@Component
struct Index {
async aboutToAppear(): Promise<void> {
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);
})
}
}
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<string>) => {
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<void> {
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);
})
}
}

View file

@ -1,28 +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"
}
}
{
"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"
}
}
}

View file

@ -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
@ -820,7 +824,7 @@ const char *SDL_GetPlatform(void)
#elif defined(__managarm__)
return "Managarm";
#elif defined(SDL_PLATFORM_OHOS)
return "OpenHarmony/HarmonyOS"
return "OpenHarmony/HarmonyOS";
#else
return "Unknown (see SDL_platform.h)";
#endif
@ -833,6 +837,8 @@ bool SDL_IsPhone(void)
if (!SDL_IsTablet() && !SDL_IsTV()) {
return true;
}
#elif defined(SDL_PLATFORM_OHOS)
return OHOS_IsPhone();
#endif
return false;
}

View file

@ -468,6 +468,24 @@ bool OHOS_ThemeDark()
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));

View file

@ -1,38 +1,40 @@
#ifndef SDL_OHOS_H
#define SDL_OHOS_H
#include "SDL3/SDL_video.h"
#include "video/SDL_sysvideo.h"
#include <native_window/external_window.h>
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();
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
#ifndef SDL_OHOS_H
#define SDL_OHOS_H
#include "SDL3/SDL_video.h"
#include "video/SDL_sysvideo.h"
#include <native_window/external_window.h>
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