mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-19 06:07:40 +00:00
feat(core): expose state and event API to WASM
This commit is contained in:
parent
8e8816adc2
commit
c297c66a64
6 changed files with 116 additions and 17 deletions
|
|
@ -1166,7 +1166,7 @@ returned by [km_core_keyboard_load_from_blob].
|
|||
```c */
|
||||
KMN_API
|
||||
void
|
||||
km_core_keyboard_dispose(km_core_keyboard *keyboard);
|
||||
km_core_keyboard_dispose(km_core_keyboard const* keyboard);
|
||||
|
||||
/*
|
||||
```
|
||||
|
|
@ -1384,7 +1384,7 @@ the environment passed.
|
|||
```c */
|
||||
KMN_API
|
||||
km_core_status
|
||||
km_core_state_create(km_core_keyboard *keyboard,
|
||||
km_core_state_create(km_core_keyboard const *keyboard,
|
||||
km_core_option_item const *env,
|
||||
km_core_state **out);
|
||||
|
||||
|
|
@ -1470,7 +1470,7 @@ invalid.
|
|||
```c */
|
||||
KMN_API
|
||||
void
|
||||
km_core_state_dispose(km_core_state *state);
|
||||
km_core_state_dispose(km_core_state const *state);
|
||||
|
||||
/*
|
||||
```
|
||||
|
|
@ -1677,7 +1677,7 @@ the state may also be modified.
|
|||
```c */
|
||||
KMN_API
|
||||
km_core_status
|
||||
km_core_process_event(km_core_state *state,
|
||||
km_core_process_event(km_core_state const *state,
|
||||
km_core_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down,
|
||||
|
|
@ -1733,7 +1733,7 @@ the state may also be modified.
|
|||
KMN_API
|
||||
km_core_status
|
||||
km_core_event(
|
||||
km_core_state *state,
|
||||
km_core_state const *state,
|
||||
uint32_t event,
|
||||
void* data
|
||||
);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ km_core_keyboard_load_from_blob(
|
|||
}
|
||||
|
||||
void
|
||||
km_core_keyboard_dispose(km_core_keyboard *keyboard)
|
||||
km_core_keyboard_dispose(km_core_keyboard const* keyboard)
|
||||
{
|
||||
delete keyboard;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
km_core_status
|
||||
km_core_event(
|
||||
km_core_state *state,
|
||||
km_core_state const *state,
|
||||
uint32_t event,
|
||||
void* data
|
||||
) {
|
||||
|
|
@ -37,19 +37,20 @@ km_core_event(
|
|||
return KM_CORE_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return state->processor().external_event(state, event, data);
|
||||
return const_cast<km_core_state*>(state)->processor().external_event(const_cast<km_core_state*>(state), event, data);
|
||||
}
|
||||
|
||||
km_core_status
|
||||
km_core_process_event(km_core_state *state,
|
||||
km_core_process_event(km_core_state const *state_,
|
||||
km_core_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down,
|
||||
uint16_t event_flags) {
|
||||
assert(state != nullptr);
|
||||
if(state == nullptr) {
|
||||
assert(state_ != nullptr);
|
||||
if(state_ == nullptr) {
|
||||
return KM_CORE_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
km_core_state *state = const_cast<km_core_state*>(state_);
|
||||
km_core_status status = state->processor().process_event(state, vk, modifier_state, is_key_down, event_flags);
|
||||
|
||||
if (state_should_invalidate_context(state, vk, modifier_state, is_key_down, event_flags)) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ using namespace km::core;
|
|||
// Forward declarations
|
||||
class context;
|
||||
|
||||
km_core_status km_core_state_create(km_core_keyboard * keyboard,
|
||||
km_core_status km_core_state_create(km_core_keyboard const *keyboard,
|
||||
km_core_option_item const *env,
|
||||
km_core_state ** out)
|
||||
{
|
||||
|
|
@ -38,7 +38,7 @@ km_core_status km_core_state_create(km_core_keyboard * keyboard,
|
|||
|
||||
try
|
||||
{
|
||||
*out = new km_core_state(static_cast<abstract_processor&>(*keyboard), env);
|
||||
*out = new km_core_state(static_cast<abstract_processor&>(*const_cast<km_core_keyboard*>(keyboard)), env);
|
||||
}
|
||||
catch (std::bad_alloc &)
|
||||
{
|
||||
|
|
@ -60,7 +60,7 @@ km_core_status km_core_state_clone(km_core_state const *state,
|
|||
}
|
||||
|
||||
|
||||
void km_core_state_dispose(km_core_state *state)
|
||||
void km_core_state_dispose(km_core_state const *state)
|
||||
{
|
||||
delete state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@
|
|||
#define EXTERN EMSCRIPTEN_KEEPALIVE
|
||||
#endif
|
||||
|
||||
#include "processor.hpp"
|
||||
#include <keyman_core.h>
|
||||
#include "processor.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
namespace em = emscripten;
|
||||
|
||||
|
|
@ -137,6 +138,30 @@ km_core_keyboard_get_attrs_wasm(const km_core_keyboard* keyboard) {
|
|||
return new CoreReturn<km_core_keyboard_attrs_wasm>(retVal, attrs_wasm);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const CoreReturn<km_core_state>*
|
||||
km_core_state_create_wasm(const km_core_keyboard* keyboard,
|
||||
const std::vector<km_core_option_item_wasm>& env) {
|
||||
km_core_option_item* env_c = new km_core_option_item[env.size() + 1];
|
||||
for (size_t i = 0; i < env.size(); ++i) {
|
||||
env_c[i].key = env[i].key.c_str();
|
||||
env_c[i].value = env[i].value.c_str();
|
||||
env_c[i].scope = env[i].scope;
|
||||
}
|
||||
env_c[env.size()] = {nullptr, nullptr, 0};
|
||||
|
||||
km_core_state* state = nullptr;
|
||||
km_core_status retVal = km_core_state_create(keyboard, env_c, &state);
|
||||
delete[] env_c;
|
||||
return new CoreReturn<km_core_state>(retVal, state);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE const CoreReturn<km_core_state>*
|
||||
km_core_state_clone_wasm(const km_core_state* state) {
|
||||
km_core_state* new_state = nullptr;
|
||||
km_core_status retVal = km_core_state_clone(state, &new_state);
|
||||
return new CoreReturn<km_core_state>(retVal, new_state);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(core_interface) {
|
||||
|
||||
em::value_object<km_core_attr>("km_core_attr")
|
||||
|
|
@ -184,7 +209,17 @@ EMSCRIPTEN_BINDINGS(core_interface) {
|
|||
.property("id", &km_core_keyboard_attrs_wasm::id)
|
||||
.property("default_options", &km_core_keyboard_attrs_wasm::default_options);
|
||||
|
||||
em::class_<km_core_state>("km_core_state");
|
||||
em::class_<CoreReturn<km_core_state>>("CoreStateReturn")
|
||||
.property("status", &CoreReturn<km_core_state>::getStatus)
|
||||
.property("object", &CoreReturn<km_core_state>::getObject, em::allow_raw_pointers());
|
||||
|
||||
em::function("keyboard_load_from_blob", &km_core_keyboard_load_from_blob_wasm, em::allow_raw_pointers());
|
||||
em::function("keyboard_dispose", &km_core_keyboard_dispose, em::allow_raw_pointers());
|
||||
em::function("keyboard_get_attrs", &km_core_keyboard_get_attrs_wasm, em::allow_raw_pointers());
|
||||
em::function("state_create", &km_core_state_create_wasm, em::allow_raw_pointers());
|
||||
em::function("state_clone", &km_core_state_clone_wasm, em::allow_raw_pointers());
|
||||
em::function("state_dispose", &km_core_state_dispose, em::allow_raw_pointers());
|
||||
em::function("process_event", &km_core_process_event, em::allow_raw_pointers());
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,10 +40,25 @@ describe('Unit tests for wasm Core API', function () {
|
|||
assert.isOk(result.object);
|
||||
});
|
||||
|
||||
function loadKeyboard(name) {
|
||||
const kmxdata = fs.readFileSync(path.join(__dirname, `tests/unit/kmx/${name}.kmx`));
|
||||
const result = km_core.keyboard_load_from_blob(name, kmxdata);
|
||||
assert.equal(result.status, 0);
|
||||
assert.isOk(result.object);
|
||||
return result.object;
|
||||
}
|
||||
|
||||
it('can dispose keyboard', function () {
|
||||
// Setup
|
||||
const keyboard = loadKeyboard('k_020___deadkeys_and_backspace');
|
||||
|
||||
// Execute
|
||||
km_core.keyboard_dispose(keyboard);
|
||||
});
|
||||
|
||||
it('can get keyboard attributes', function () {
|
||||
// Setup
|
||||
const kmxdata = fs.readFileSync(path.join(__dirname, 'tests/unit/kmx/k_022___options_with_preset.kmx'));
|
||||
const keyboard = km_core.keyboard_load_from_blob('k_022___options_with_preset', kmxdata).object;
|
||||
const keyboard = loadKeyboard('k_022___options_with_preset');
|
||||
|
||||
// Execute
|
||||
const result = km_core.keyboard_get_attrs(keyboard);
|
||||
|
|
@ -55,4 +70,52 @@ describe('Unit tests for wasm Core API', function () {
|
|||
assert.equal(result.object.version_string, '0.0');
|
||||
assert.deepEqual(result.object.default_options, [{ key: 'foo', value: '0', scope: 1 }]);
|
||||
});
|
||||
|
||||
it('can create the state object', function () {
|
||||
// Setup
|
||||
const keyboard = loadKeyboard('k_020___deadkeys_and_backspace');
|
||||
|
||||
// Execute
|
||||
const result = km_core.state_create(keyboard, []);
|
||||
|
||||
// Verify
|
||||
assert.equal(result.status, 0);
|
||||
assert.isOk(result.object);
|
||||
});
|
||||
|
||||
it('can dispose the state object', function () {
|
||||
// Setup
|
||||
const keyboard = loadKeyboard('k_020___deadkeys_and_backspace');
|
||||
const state = km_core.state_create(keyboard, []);
|
||||
|
||||
// Execute
|
||||
km_core.state_dispose(state.object);
|
||||
});
|
||||
|
||||
it('can clone the state object', function () {
|
||||
// Setup
|
||||
const keyboard = loadKeyboard('k_020___deadkeys_and_backspace');
|
||||
const state = km_core.state_create(keyboard, []);
|
||||
|
||||
// Execute
|
||||
const result = km_core.state_clone(state.object);
|
||||
|
||||
// Verify
|
||||
assert.equal(result.status, 0);
|
||||
assert.isOk(result.object);
|
||||
// TODO-web-core: add deeper tests
|
||||
});
|
||||
|
||||
it('can process event', function () {
|
||||
// Setup
|
||||
const keyboard = loadKeyboard('k_020___deadkeys_and_backspace');
|
||||
const state = km_core.state_create(keyboard, []);
|
||||
|
||||
// Execute
|
||||
const status = km_core.process_event(state.object, 0x20, 0, 1, 0);
|
||||
|
||||
// Verify
|
||||
assert.equal(status, 0);
|
||||
// TODO-web-core: add more asserts
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue