mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
Merge pull request #15961 from keymanapp/fix/windows/clone-state-actions-deep-copy
fix(core): clone state actions deep copy
This commit is contained in:
commit
5cc2444cd6
4 changed files with 96 additions and 3 deletions
|
|
@ -125,8 +125,16 @@ namespace km {
|
|||
{
|
||||
assert(state);
|
||||
assert(action_item);
|
||||
if ((!state) || (!action_item))
|
||||
if ((!state) || (!action_item)) {
|
||||
return false;
|
||||
}
|
||||
// For this mock processor we only support queuing PERSIST_OPT action items.
|
||||
if (action_item->type == KM_CORE_IT_PERSIST_OPT && action_item->option) {
|
||||
state->actions().push_persist(update_option(static_cast<km_core_option_scope>(action_item->option->scope),
|
||||
action_item->option->key,
|
||||
action_item->option->value));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -166,6 +174,18 @@ namespace km {
|
|||
u"F2 pressed test save."));
|
||||
break;
|
||||
}
|
||||
case KM_CORE_VKEY_F3:
|
||||
{
|
||||
state->actions().push_persist(
|
||||
update_option(KM_CORE_OPT_KEYBOARD,
|
||||
u"__test_point_3",
|
||||
u"F3 pressed test save 1."));
|
||||
state->actions().push_persist(
|
||||
update_option(KM_CORE_OPT_KEYBOARD,
|
||||
u"__test_point_4",
|
||||
u"F3 pressed test save 2."));
|
||||
break;
|
||||
}
|
||||
|
||||
case KM_CORE_VKEY_F4:
|
||||
state->context().push_marker(KM_CORE_VKEY_QUOTE);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,23 @@ void actions::push_capslock(bool turnOn) {
|
|||
emplace_back(std::move(ai));
|
||||
}
|
||||
|
||||
actions::actions(actions const &other)
|
||||
: std::vector<action>(other)
|
||||
, _option_items_stack(other._option_items_stack)
|
||||
{
|
||||
// Update all option pointers to point to the new stack.
|
||||
size_t opt_index = 0;
|
||||
for (auto &item : *this) {
|
||||
if (item.type == KM_CORE_IT_PERSIST_OPT) {
|
||||
if (opt_index < _option_items_stack.size()) {
|
||||
item.option = &_option_items_stack[opt_index++];
|
||||
} else {
|
||||
// no matching item in the stack; clear pointer.
|
||||
item.option = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state::state(km::core::abstract_processor & ap, km_core_option_item const *env)
|
||||
: _processor(ap)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
#include "keyman_core.h"
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ using action = km_core_action_item;
|
|||
|
||||
class actions : public std::vector<action>
|
||||
{
|
||||
std::vector<option> _option_items_stack;
|
||||
std::deque<option> _option_items_stack;
|
||||
|
||||
template<km_core_action_type V>
|
||||
void _push_vkey(km_core_virtual_key);
|
||||
|
|
@ -35,6 +36,10 @@ class actions : public std::vector<action>
|
|||
public:
|
||||
template<typename... Args>
|
||||
actions(Args&&... args);
|
||||
actions(actions const &other);
|
||||
// If the operator is needed in the future, it shall be implemented.
|
||||
// Currently blocking accidental use of it for now.
|
||||
actions &operator=(actions const &) = delete;
|
||||
|
||||
void push_character(km_core_usv usv);
|
||||
void push_marker(uint32_t marker);
|
||||
|
|
|
|||
|
|
@ -251,6 +251,24 @@ constexpr km_core_option_item const expected_persist_opt = {
|
|||
KM_CORE_OPT_KEYBOARD
|
||||
};
|
||||
|
||||
constexpr km_core_option_item const clone_persist_opt = {
|
||||
u"__test_clone",
|
||||
u"Not in original",
|
||||
KM_CORE_OPT_KEYBOARD
|
||||
};
|
||||
|
||||
constexpr km_core_option_item const test_point_3_opt = {
|
||||
u"__test_point_3",
|
||||
u"F3 pressed test save 1.",
|
||||
KM_CORE_OPT_KEYBOARD
|
||||
};
|
||||
|
||||
constexpr km_core_option_item const test_point_4_opt = {
|
||||
u"__test_point_4",
|
||||
u"F3 pressed test save 2.",
|
||||
KM_CORE_OPT_KEYBOARD
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
uint8_t test_imx_callback(km_core_state *state, uint32_t imx_id, void *callback_object){
|
||||
|
|
@ -269,7 +287,8 @@ int main(int argc, char * argv[])
|
|||
|
||||
km_core_keyboard * test_kb = nullptr;
|
||||
km_core_state * test_state = nullptr,
|
||||
* test_clone = nullptr;
|
||||
* test_clone = nullptr,
|
||||
* test_clone_2 = nullptr;
|
||||
test_kb = (km_core_keyboard *)new km::core::mock_processor(km::core::path("dummy.mock"));
|
||||
|
||||
// Simple sanity tests.
|
||||
|
|
@ -394,9 +413,41 @@ int main(int argc, char * argv[])
|
|||
clone_state_deleted_text
|
||||
));
|
||||
|
||||
// Add two actions before cloning the state again
|
||||
try_status(km_core_process_event(test_state, KM_CORE_VKEY_F3, 0, 1, KM_CORE_EVENT_FLAG_DEFAULT));
|
||||
try_status(km_core_state_clone(test_state, &test_clone_2));
|
||||
|
||||
// Now put an option in the test_clone_2 state only
|
||||
km_core_action_item action_clone = {KM_CORE_IT_PERSIST_OPT, {0,}, };
|
||||
action_clone.option = &clone_persist_opt;
|
||||
if (test_clone_2->actions().back().type == KM_CORE_IT_END) {
|
||||
test_clone_2->actions().pop_back();
|
||||
}
|
||||
km_core_state_queue_action_items(test_clone_2, &action_clone);
|
||||
test_clone_2->actions().commit();
|
||||
|
||||
// Test debug dump
|
||||
auto doc3 = get_json_doc(*test_state), doc4 = get_json_doc(*test_clone_2);
|
||||
std::cout << "doc3:" << std::endl;
|
||||
std::cout << doc3 << std::endl;
|
||||
std::cout << "doc4:" << std::endl;
|
||||
std::cout << doc4 << std::endl;
|
||||
if (doc3 == doc4) return __LINE__;
|
||||
|
||||
km_core_action_item action_tp3 = {KM_CORE_IT_PERSIST_OPT, {0,}, };
|
||||
action_tp3.option = &test_point_3_opt;
|
||||
|
||||
km_core_action_item action_tp4 = {KM_CORE_IT_PERSIST_OPT, {0,}, };
|
||||
action_tp4.option = &test_point_4_opt;
|
||||
|
||||
test_assert(action_items(test_state, {action_tp3, action_tp4, {KM_CORE_IT_END}}));
|
||||
// Check that test_clone_2 has the same persisted options plus the extra queued option.
|
||||
test_assert(action_items(test_clone_2, {action_tp3, action_tp4, action_clone, {KM_CORE_IT_END}}));
|
||||
|
||||
// Destroy them
|
||||
km_core_state_dispose(test_state);
|
||||
km_core_state_dispose(test_clone);
|
||||
km_core_state_dispose(test_clone_2);
|
||||
km_core_keyboard_dispose(test_kb);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue