mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-19 06:47:41 +00:00
feat(common/core): Implement capsAlwaysOff system store
This change implements the core part in a way that makes the tests pass. This still needs corresponding changes in the engine.
This commit is contained in:
parent
84aa50b82f
commit
0eca43d4ea
34 changed files with 566 additions and 419 deletions
2
common/core/desktop/.gitignore
vendored
2
common/core/desktop/.gitignore
vendored
|
|
@ -9,3 +9,5 @@ wasm.build
|
|||
TIER.md
|
||||
VERSION.md
|
||||
shellHelperFunctions.sh
|
||||
|
||||
src/rust/keyman_keyboard_processor/target/
|
||||
|
|
|
|||
|
|
@ -478,6 +478,7 @@ typedef struct {
|
|||
uintptr_t marker; // MARKER type
|
||||
km_kbp_option_item const * option; // OPT types
|
||||
km_kbp_usv character; // CHAR type
|
||||
uint8_t capsLock; // CAPSLOCK type, 1 to turn on, 0 to turn off
|
||||
};
|
||||
} km_kbp_action_item;
|
||||
|
||||
|
|
@ -494,6 +495,7 @@ enum km_kbp_action_type {
|
|||
// for applications where context is cached, this clears the context;
|
||||
// for applications where context is read from the focused text store,
|
||||
// the context is just re-read and markers flushed.
|
||||
KM_KBP_IT_CAPSLOCK = 8, // Enable or disable capsLock
|
||||
KM_KBP_IT_MAX_TYPE_ID
|
||||
};
|
||||
|
||||
|
|
@ -940,7 +942,8 @@ KMN_API
|
|||
km_kbp_status
|
||||
km_kbp_process_event(km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state);
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -12,15 +12,15 @@
|
|||
#include "processor.hpp"
|
||||
#include "state.hpp"
|
||||
|
||||
km_kbp_status
|
||||
km_kbp_status
|
||||
km_kbp_process_event(km_kbp_state *state,
|
||||
km_kbp_virtual_key vk, uint16_t modifier_state)
|
||||
{
|
||||
return state->processor().process_event(state, vk, modifier_state);
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down) {
|
||||
return state->processor().process_event(state, vk, modifier_state, is_key_down);
|
||||
}
|
||||
|
||||
|
||||
km_kbp_attr const *
|
||||
km_kbp_attr const *
|
||||
km_kbp_get_engine_attrs(km_kbp_state const *state)
|
||||
{
|
||||
return &state->processor().attributes();
|
||||
|
|
|
|||
|
|
@ -2,57 +2,80 @@
|
|||
Copyright: Copyright (C) 2003-2018 SIL International.
|
||||
Authors: mcdurdin
|
||||
*/
|
||||
#include <keyman/keyboardprocessor_consts.h>
|
||||
#include <kmx/kmx_processevent.h>
|
||||
|
||||
using namespace km::kbp;
|
||||
using namespace kmx;
|
||||
|
||||
void KMX_ProcessEvent::ResetCapsLock(void)
|
||||
{
|
||||
DebugLog("ResetCapsLock: enter");
|
||||
/**
|
||||
* Set caps lock state.
|
||||
* Called by ProcessEvent.
|
||||
* May update `modifiers` to add or remove `CAPITALFLAG` according to capsLockOn
|
||||
* parameter. May queue actions to set caps lock state.
|
||||
*
|
||||
* @param[in,out] modifiers The modifier key bitmap
|
||||
* @param capsLockOn The desired caps lock state
|
||||
*/
|
||||
void KMX_ProcessEvent::SetCapsLock(KMX_DWORD &modifiers, KMX_BOOL capsLockOn) {
|
||||
KMX_BOOL capsLockCurrentlyOn = IsCapsLockOn(modifiers);
|
||||
if (capsLockCurrentlyOn == capsLockOn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_keyboard.Keyboard->dwFlags & KF_CAPSALWAYSOFF)
|
||||
{
|
||||
DebugLog("Caps lock is %s, switching %s", capsLockCurrentlyOn ? "on" : "off", capsLockOn ? "on" : "off");
|
||||
|
||||
m_actions.QueueAction(QIT_CAPSLOCK, capsLockOn);
|
||||
if (capsLockOn) {
|
||||
modifiers |= CAPITALFLAG;
|
||||
} else {
|
||||
modifiers &= ~CAPITALFLAG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with CapsAlwaysOff store option and turns caps lock off if necessary.
|
||||
* Called by ProcessEvent.
|
||||
* May update `modifiers` to add or remove `CAPITALFLAG` according to keyboard
|
||||
* requirements. May queue actions to set caps lock state.
|
||||
*
|
||||
* @param[in,out] modifiers The modifier key bitmap
|
||||
*/
|
||||
void KMX_ProcessEvent::ResetCapsLock(KMX_DWORD &modifiers) {
|
||||
if (m_keyboard.Keyboard->dwFlags & KF_CAPSALWAYSOFF) {
|
||||
DebugLog("ResetCapsLock: caps lock should be always off");
|
||||
if (m_environment.capsLock())
|
||||
{
|
||||
DebugLog("ResetCapsLock: caps lock is on, switching off caps lock");
|
||||
m_actions.QueueAction(QIT_CAPSLOCK, 0);
|
||||
}
|
||||
}
|
||||
DebugLog("ResetCapsLock: exit");
|
||||
}
|
||||
|
||||
|
||||
void KMX_ProcessEvent::KeyCapsLockPress(KMX_BOOL FIsUp)
|
||||
{
|
||||
if (m_keyboard.Keyboard->dwFlags & KF_CAPSONONLY)
|
||||
{
|
||||
if(FIsUp && !m_environment.capsLock())
|
||||
{
|
||||
m_actions.QueueAction(QIT_CAPSLOCK, 1);
|
||||
}
|
||||
}
|
||||
else if (m_keyboard.Keyboard->dwFlags & KF_CAPSALWAYSOFF)
|
||||
{
|
||||
if(!FIsUp && m_environment.capsLock())
|
||||
{
|
||||
m_actions.QueueAction(QIT_CAPSLOCK, 0);
|
||||
}
|
||||
SetCapsLock(modifiers, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KMX_ProcessEvent::KeyShiftPress(KMX_BOOL FIsUp)
|
||||
{
|
||||
if(!m_environment.capsLock()) return;
|
||||
|
||||
if (m_keyboard.Keyboard->dwFlags & KF_SHIFTFREESCAPS)
|
||||
{
|
||||
if(!FIsUp)
|
||||
{
|
||||
m_actions.QueueAction(QIT_CAPSLOCK, 0);
|
||||
}
|
||||
/**
|
||||
* Deal with CapsLock store options on CapsLock key press. Called by ProcessEvent.
|
||||
* May update `modifiers` to add or remove `CAPITALFLAG` according to keyboard
|
||||
* requirements. May queue actions to set caps lock state.
|
||||
*
|
||||
* @param[in,out] modifiers The modifier key bitmap
|
||||
* @param isKeyDown TRUE if this is called on KeyDown event, FALSE if
|
||||
* called on KeyUp event
|
||||
*/
|
||||
void KMX_ProcessEvent::KeyCapsLockPress(KMX_DWORD &modifiers, KMX_BOOL isKeyDown) {
|
||||
if (m_keyboard.Keyboard->dwFlags & KF_CAPSONONLY && !isKeyDown) {
|
||||
SetCapsLock(modifiers, TRUE);
|
||||
} else if (m_keyboard.Keyboard->dwFlags & KF_CAPSALWAYSOFF && isKeyDown) {
|
||||
SetCapsLock(modifiers, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deal with CapsLock store options on Shift key press. Called by ProcessEvent.
|
||||
* May update `modifiers` to remove `CAPITALFLAG` according to keyboard
|
||||
* requirements. May queue actions to reset caps lock state.
|
||||
*
|
||||
* @param[in,out] modifiers The modifier key bitmap
|
||||
* @param isKeyDown TRUE if this is called on KeyDown event, FALSE if
|
||||
* called on KeyUp event
|
||||
*/
|
||||
void KMX_ProcessEvent::KeyShiftPress(KMX_DWORD &modifiers, KMX_BOOL isKeyDown) {
|
||||
if (m_keyboard.Keyboard->dwFlags & KF_SHIFTFREESCAPS && isKeyDown) {
|
||||
SetCapsLock(modifiers, FALSE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ namespace {
|
|||
*DEFAULT_BASELAYOUT = u"kbdus.dll",
|
||||
*DEFAULT_BASELAYOUTALT = u"en-US",
|
||||
*DEFAULT_SIMULATEALTGR = u"0",
|
||||
*DEFAULT_CAPSLOCK = u"0",
|
||||
*DEFAULT_BASELAYOUTGIVESCTRLRALTFORRALT = u"0";
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +24,6 @@ KMX_Environment::KMX_Environment() {
|
|||
Set(KM_KBP_KMX_ENV_BASELAYOUT, DEFAULT_BASELAYOUT);
|
||||
Set(KM_KBP_KMX_ENV_BASELAYOUTALT, DEFAULT_BASELAYOUTALT);
|
||||
Set(KM_KBP_KMX_ENV_SIMULATEALTGR, DEFAULT_SIMULATEALTGR);
|
||||
Set(KM_KBP_KMX_ENV_CAPSLOCK, DEFAULT_CAPSLOCK);
|
||||
Set(KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT, DEFAULT_BASELAYOUTGIVESCTRLRALTFORRALT);
|
||||
}
|
||||
|
||||
|
|
@ -46,9 +44,6 @@ char16_t const * KMX_Environment::LookUp(std::u16string const & key) const {
|
|||
else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_SIMULATEALTGR)) {
|
||||
return _simulateAltGr ? u"1" : u"0";
|
||||
}
|
||||
else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_CAPSLOCK)) {
|
||||
return _capsLock ? u"1" : u"0";
|
||||
}
|
||||
else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) {
|
||||
return _baseLayoutGivesCtrlRAltForRAlt ? u"1" : u"0";
|
||||
}
|
||||
|
|
@ -74,9 +69,6 @@ void KMX_Environment::Set(std::u16string const & key, std::u16string const & val
|
|||
else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_SIMULATEALTGR)) {
|
||||
_simulateAltGr = value == u"1";
|
||||
}
|
||||
else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_CAPSLOCK)) {
|
||||
_capsLock = value == u"1";
|
||||
}
|
||||
else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) {
|
||||
_baseLayoutGivesCtrlRAltForRAlt = value == u"1";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ class KMX_Environment {
|
|||
private:
|
||||
KMX_BOOL _simulateAltGr, _baseLayoutGivesCtrlRAltForRAlt;
|
||||
std::u16string _baseLayout, _baseLayoutAlt;
|
||||
KMX_BOOL _capsLock;
|
||||
std::u16string _platform;
|
||||
void InitOption(
|
||||
std::vector<option> & default_env,
|
||||
|
|
@ -23,7 +22,6 @@ public:
|
|||
void Set(std::u16string const & key, std::u16string const & value);
|
||||
char16_t const * LookUp(std::u16string const & key) const;
|
||||
|
||||
KMX_BOOL capsLock() const noexcept { return _capsLock; }
|
||||
KMX_BOOL simulateAltGr() const noexcept { return _simulateAltGr; }
|
||||
KMX_BOOL baseLayoutGivesCtrlRAltForRAlt() const noexcept { return _baseLayoutGivesCtrlRAltForRAlt; }
|
||||
const std::u16string & baseLayout() const noexcept { return _baseLayout; }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
#include "kmx_processevent.h"
|
||||
#include "state.hpp"
|
||||
#include <keyman/keyboardprocessor_consts.h>
|
||||
|
||||
using namespace km::kbp;
|
||||
using namespace kmx;
|
||||
|
|
@ -60,19 +61,26 @@ char VKeyToChar(KMX_UINT modifiers, KMX_UINT vk) {
|
|||
}
|
||||
|
||||
/*
|
||||
* KMX_BOOL ProcessEvent();
|
||||
* Process Events
|
||||
*
|
||||
* Parameters: none
|
||||
* ProcessEvent organizes the messages and gives them to the appropriate routines to
|
||||
* process, and checks the state of Windows for the keyboard handling.
|
||||
* Called by FilterFunc.
|
||||
*
|
||||
* Returns: TRUE if keystroke should be eaten
|
||||
* @param state A pointer to the state object.
|
||||
* @param vkey A virtual key to be processed.
|
||||
* @param modifiers The combinations of modifier keys set at the time vkey was pressed,
|
||||
* bitmask from the km_kbp_modifier_state enum.
|
||||
* @param isKeyDown TRUE if this is called on KeyDown event, FALSE if called on KeyUp event
|
||||
*
|
||||
* Called by: FilterFunc
|
||||
*
|
||||
* ProcessEvent organizes the messages and gives them to the appropriate routines to
|
||||
* process, and checks the state of Windows for the keyboard handling.
|
||||
* @return TRUE if keystroke should be eaten
|
||||
*/
|
||||
KMX_BOOL KMX_ProcessEvent::ProcessEvent(km_kbp_state *state, KMX_UINT vkey, KMX_DWORD modifiers)
|
||||
{
|
||||
KMX_BOOL KMX_ProcessEvent::ProcessEvent(
|
||||
km_kbp_state *state,
|
||||
KMX_UINT vkey,
|
||||
KMX_DWORD modifiers,
|
||||
KMX_BOOL isKeyDown
|
||||
) {
|
||||
LPKEYBOARD kbd = m_keyboard.Keyboard;
|
||||
|
||||
m_kbp_state = state;
|
||||
|
|
@ -91,8 +99,7 @@ KMX_BOOL KMX_ProcessEvent::ProcessEvent(km_kbp_state *state, KMX_UINT vkey, KMX_
|
|||
state->debug_items().push_end(m_actions.Length(), 0);
|
||||
}
|
||||
|
||||
if (m_environment.capsLock())
|
||||
modifiers |= CAPITALFLAG;
|
||||
ResetCapsLock(modifiers);
|
||||
|
||||
m_state.vkey = vkey;
|
||||
m_state.charCode = VKeyToChar(modifiers, vkey);
|
||||
|
|
@ -101,6 +108,21 @@ KMX_BOOL KMX_ProcessEvent::ProcessEvent(km_kbp_state *state, KMX_UINT vkey, KMX_
|
|||
|
||||
if (kbd->StartGroup[BEGIN_UNICODE] == (KMX_DWORD) -1) {
|
||||
DebugLog("Non-Unicode keyboards are not supported.");
|
||||
m_kbp_state = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (vkey) {
|
||||
case KM_KBP_VKEY_CAPS:
|
||||
KeyCapsLockPress(modifiers, isKeyDown);
|
||||
break;
|
||||
case KM_KBP_VKEY_SHIFT:
|
||||
KeyShiftPress(modifiers, isKeyDown);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isKeyDown) {
|
||||
m_kbp_state = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +295,7 @@ KMX_BOOL KMX_ProcessEvent::ProcessGroup(LPGROUP gp, KMX_BOOL *pOutputKeystroke)
|
|||
PostString(gp->dpNoMatch, m_keyboard.Keyboard, NULL, pOutputKeystroke);
|
||||
if(m_debug_items) {
|
||||
m_debug_items->push_nomatch_exit(m_actions.Length(), gp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_state.charCode != 0 && m_state.charCode != 0xFFFF && gp->fUsingKeys)
|
||||
{
|
||||
|
|
@ -355,7 +377,7 @@ KMX_BOOL KMX_ProcessEvent::ProcessGroup(LPGROUP gp, KMX_BOOL *pOutputKeystroke)
|
|||
if(m_debug_items) {
|
||||
m_debug_items->push_match_enter(m_actions.Length(), gp);
|
||||
}
|
||||
PostString(gp->dpMatch, m_keyboard.Keyboard, NULL, pOutputKeystroke);
|
||||
PostString(gp->dpMatch, m_keyboard.Keyboard, NULL, pOutputKeystroke);
|
||||
if(m_debug_items) {
|
||||
m_debug_items->push_match_exit(m_actions.Length(), gp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,9 +75,11 @@ private:
|
|||
|
||||
/* Caps Lock and modifier management */
|
||||
|
||||
void ResetCapsLock(void);
|
||||
void KeyCapsLockPress(KMX_BOOL FIsUp);
|
||||
void KeyShiftPress(KMX_BOOL FIsUp);
|
||||
KMX_BOOL IsCapsLockOn(KMX_DWORD modifiers);
|
||||
void SetCapsLock(KMX_DWORD &modifiers, KMX_BOOL capsLockOn);
|
||||
void ResetCapsLock(KMX_DWORD &modifiers);
|
||||
void KeyCapsLockPress(KMX_DWORD &modifiers, KMX_BOOL isKeyDown);
|
||||
void KeyShiftPress(KMX_DWORD &modifiers, KMX_BOOL isKeyDown);
|
||||
|
||||
KMX_BOOL IsEquivalentShift(KMX_UINT rshift, KMX_UINT kshift);
|
||||
|
||||
|
|
@ -86,7 +88,7 @@ public:
|
|||
~KMX_ProcessEvent();
|
||||
|
||||
KMX_BOOL Load(km_kbp_path_name keyboardName);
|
||||
KMX_BOOL ProcessEvent(km_kbp_state *state, KMX_UINT vkey, KMX_DWORD modifiers); // returns FALSE on error or key not matched
|
||||
KMX_BOOL ProcessEvent(km_kbp_state *state, KMX_UINT vkey, KMX_DWORD modifiers, KMX_BOOL isKeyDown); // returns FALSE on error or key not matched
|
||||
|
||||
KMX_Actions *GetActions();
|
||||
KMX_Context *GetContext();
|
||||
|
|
@ -97,6 +99,10 @@ public:
|
|||
LPINTKEYBOARDINFO GetKeyboard();
|
||||
};
|
||||
|
||||
inline KMX_BOOL KMX_ProcessEvent::IsCapsLockOn(KMX_DWORD modifiers) {
|
||||
return modifiers & CAPITALFLAG ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/* Global Constants */
|
||||
|
||||
struct char_to_vkey {
|
||||
|
|
|
|||
|
|
@ -2,188 +2,195 @@
|
|||
#include "state.hpp"
|
||||
#include "kmx/kmx_processor.hpp"
|
||||
|
||||
namespace km {
|
||||
namespace kbp
|
||||
using namespace km::kbp;
|
||||
using namespace kmx;
|
||||
|
||||
km_kbp_status kmx_processor::validate() const {
|
||||
return _valid ? KM_KBP_STATUS_OK : KM_KBP_STATUS_INVALID_KEYBOARD;
|
||||
}
|
||||
|
||||
kmx_processor::kmx_processor(kbp::path p) {
|
||||
p.replace_extension(".kmx");
|
||||
_valid = bool(_kmx.Load(p.c_str()));
|
||||
|
||||
if (!_valid)
|
||||
return;
|
||||
|
||||
keyboard_attributes::options_store defaults;
|
||||
_kmx.GetOptions()->Init(defaults);
|
||||
|
||||
for (auto const & opt: defaults)
|
||||
{
|
||||
if (!opt.empty() && opt.scope == KM_KBP_OPT_KEYBOARD )
|
||||
persisted_store()[opt.key] = opt.value;
|
||||
}
|
||||
// Fill out attributes
|
||||
auto v = _kmx.GetKeyboard()->Keyboard->version;
|
||||
auto vs = std::to_string(v >> 16) + "." + std::to_string(v & 0xffff);
|
||||
|
||||
km_kbp_status kmx_processor::validate() const {
|
||||
return _valid ? KM_KBP_STATUS_OK : KM_KBP_STATUS_INVALID_KEYBOARD;
|
||||
}
|
||||
_attributes = keyboard_attributes(static_cast<std::u16string>(p.stem()),
|
||||
std::u16string(vs.begin(), vs.end()), p.parent(), defaults);
|
||||
}
|
||||
|
||||
kmx_processor::kmx_processor(kbp::path p)
|
||||
{
|
||||
p.replace_extension(".kmx");
|
||||
_valid = bool(_kmx.Load(p.c_str()));
|
||||
char16_t const *
|
||||
kmx_processor::lookup_option(
|
||||
km_kbp_option_scope scope,
|
||||
std::u16string const &key
|
||||
) const {
|
||||
char16_t const *pValue = nullptr;
|
||||
switch (scope) {
|
||||
case KM_KBP_OPT_KEYBOARD:
|
||||
pValue = _kmx.GetOptions()->LookUp(key);
|
||||
break;
|
||||
case KM_KBP_OPT_ENVIRONMENT:
|
||||
pValue = _kmx.GetEnvironment()->LookUp(key);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_valid)
|
||||
return;
|
||||
return pValue ? pValue : nullptr;
|
||||
}
|
||||
|
||||
keyboard_attributes::options_store defaults;
|
||||
_kmx.GetOptions()->Init(defaults);
|
||||
option
|
||||
kmx_processor::update_option(
|
||||
km_kbp_option_scope scope,
|
||||
std::u16string const &key,
|
||||
std::u16string const &value
|
||||
) {
|
||||
switch (scope) {
|
||||
case KM_KBP_OPT_KEYBOARD:
|
||||
_kmx.GetOptions()->Set(key, value);
|
||||
persisted_store()[key] = value;
|
||||
break;
|
||||
case KM_KBP_OPT_ENVIRONMENT:
|
||||
_kmx.GetEnvironment()->Set(key, value);
|
||||
break;
|
||||
default:
|
||||
return option();
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto const & opt: defaults)
|
||||
{
|
||||
if (!opt.empty() && opt.scope == KM_KBP_OPT_KEYBOARD )
|
||||
persisted_store()[opt.key] = opt.value;
|
||||
return option(scope, key, value);
|
||||
}
|
||||
|
||||
km_kbp_status
|
||||
kmx_processor::process_event(
|
||||
km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down
|
||||
) {
|
||||
// Construct a context buffer from the items
|
||||
|
||||
std::u16string ctxt;
|
||||
auto cp = state->context();
|
||||
for (auto c = cp.begin(); c != cp.end(); c++) {
|
||||
switch (c->type) {
|
||||
case KM_KBP_CT_CHAR:
|
||||
if (Uni_IsSMP(c->character)) {
|
||||
ctxt += Uni_UTF32ToSurrogate1(c->character);
|
||||
ctxt += Uni_UTF32ToSurrogate2(c->character);
|
||||
} else {
|
||||
ctxt += (km_kbp_cp)c->character;
|
||||
}
|
||||
// Fill out attributes
|
||||
auto v = _kmx.GetKeyboard()->Keyboard->version;
|
||||
auto vs = std::to_string(v >> 16) + "." + std::to_string(v & 0xffff);
|
||||
|
||||
_attributes = keyboard_attributes(static_cast<std::u16string>(p.stem()),
|
||||
std::u16string(vs.begin(), vs.end()), p.parent(), defaults);
|
||||
break;
|
||||
case KM_KBP_CT_MARKER:
|
||||
assert(c->marker > 0);
|
||||
ctxt += UC_SENTINEL;
|
||||
ctxt += CODE_DEADKEY;
|
||||
ctxt += c->marker;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_kmx.GetContext()->Set(ctxt.c_str());
|
||||
_kmx.GetActions()->ResetQueue();
|
||||
state->actions().clear();
|
||||
|
||||
char16_t const * kmx_processor::lookup_option(km_kbp_option_scope scope, std::u16string const & key) const
|
||||
{
|
||||
char16_t const * pValue = nullptr;
|
||||
switch(scope)
|
||||
{
|
||||
case KM_KBP_OPT_KEYBOARD:
|
||||
pValue = _kmx.GetOptions()->LookUp(key);
|
||||
break;
|
||||
case KM_KBP_OPT_ENVIRONMENT:
|
||||
pValue = _kmx.GetEnvironment()->LookUp(key);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!_kmx.ProcessEvent(state, vk, modifier_state, is_key_down)) {
|
||||
// We need to output the default keystroke
|
||||
state->actions().push_emit_keystroke();
|
||||
}
|
||||
|
||||
return pValue ? pValue : nullptr;
|
||||
}
|
||||
|
||||
option kmx_processor::update_option(km_kbp_option_scope scope, std::u16string const & key, std::u16string const & value)
|
||||
{
|
||||
switch(scope) {
|
||||
case KM_KBP_OPT_KEYBOARD:
|
||||
_kmx.GetOptions()->Set(key, value);
|
||||
persisted_store()[key] = value;
|
||||
break;
|
||||
case KM_KBP_OPT_ENVIRONMENT:
|
||||
_kmx.GetEnvironment()->Set(key, value);
|
||||
break;
|
||||
default:
|
||||
return option();
|
||||
break;
|
||||
}
|
||||
|
||||
return option(scope, key, value);
|
||||
}
|
||||
|
||||
km_kbp_status kmx_processor::process_event(km_kbp_state *state, km_kbp_virtual_key vk, uint16_t modifier_state) {
|
||||
// Construct a context buffer from the items
|
||||
|
||||
std::u16string ctxt;
|
||||
auto cp = state->context();
|
||||
for (auto c = cp.begin(); c != cp.end(); c++) {
|
||||
switch (c->type) {
|
||||
case KM_KBP_CT_CHAR:
|
||||
if (Uni_IsSMP(c->character)) {
|
||||
ctxt += Uni_UTF32ToSurrogate1(c->character);
|
||||
ctxt += Uni_UTF32ToSurrogate2(c->character);
|
||||
}
|
||||
else {
|
||||
ctxt += (km_kbp_cp) c->character;
|
||||
}
|
||||
break;
|
||||
case KM_KBP_CT_MARKER:
|
||||
assert(c->marker > 0);
|
||||
ctxt += UC_SENTINEL;
|
||||
ctxt += CODE_DEADKEY;
|
||||
ctxt += c->marker;
|
||||
break;
|
||||
for (auto i = 0; i < _kmx.GetActions()->Length(); i++) {
|
||||
auto a = _kmx.GetActions()->Get(i);
|
||||
switch (a.ItemType) {
|
||||
case QIT_CAPSLOCK:
|
||||
state->actions().push_capslock(a.dwData);
|
||||
break;
|
||||
case QIT_VKEYDOWN:
|
||||
case QIT_VKEYUP:
|
||||
case QIT_VSHIFTDOWN:
|
||||
case QIT_VSHIFTUP:
|
||||
// TODO: eliminate??
|
||||
break;
|
||||
case QIT_CHAR:
|
||||
state->context().push_character(a.dwData);
|
||||
state->actions().push_character(a.dwData);
|
||||
break;
|
||||
case QIT_DEADKEY:
|
||||
state->context().push_marker(a.dwData);
|
||||
state->actions().push_marker(a.dwData);
|
||||
break;
|
||||
case QIT_BELL:
|
||||
state->actions().push_alert();
|
||||
break;
|
||||
case QIT_BACK:
|
||||
switch (a.dwData) {
|
||||
case BK_DEFAULT:
|
||||
// This only happens if we know we have context to delete. Last item must be a character
|
||||
assert(!state->context().empty() && state->context().back().type != KM_KBP_IT_MARKER);
|
||||
if (!state->context().empty())
|
||||
state->context().pop_back();
|
||||
state->actions().push_backspace();
|
||||
break;
|
||||
case BK_DEADKEY:
|
||||
// This only happens if we know we have context to delete. Last item must be a deadkey
|
||||
assert(!state->context().empty() && state->context().back().type == KM_KBP_IT_MARKER);
|
||||
if (!state->context().empty())
|
||||
state->context().pop_back();
|
||||
break;
|
||||
case BK_BACKSPACE:
|
||||
// User-initiated backspace. We need to delete deadkeys from context, both sides of the character deleted
|
||||
while (!state->context().empty() && state->context().back().type == KM_KBP_IT_MARKER)
|
||||
state->context().pop_back();
|
||||
if (!state->context().empty()) {
|
||||
state->context().pop_back();
|
||||
while (!state->context().empty() && state->context().back().type == KM_KBP_IT_MARKER)
|
||||
state->context().pop_back();
|
||||
}
|
||||
// Even if context is empty, we send the backspace event, because we may not
|
||||
// know the context.
|
||||
state->actions().push_backspace();
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
_kmx.GetContext()->Set(ctxt.c_str());
|
||||
_kmx.GetActions()->ResetQueue();
|
||||
state->actions().clear();
|
||||
|
||||
if (!_kmx.ProcessEvent(state, vk, modifier_state)) {
|
||||
// We need to output the default keystroke
|
||||
state->actions().push_emit_keystroke();
|
||||
}
|
||||
|
||||
for (auto i = 0; i < _kmx.GetActions()->Length(); i++) {
|
||||
auto a = _kmx.GetActions()->Get(i);
|
||||
switch (a.ItemType) {
|
||||
case QIT_CAPSLOCK:
|
||||
//TODO: add Caps Event
|
||||
//dwData = 0 == off; 1 == on
|
||||
//state->actions.emplace_back(km_kbp_action_item{ KM_KBP_IT_CAPSLOCK, {0,}, {0} });
|
||||
break;
|
||||
case QIT_VKEYDOWN:
|
||||
case QIT_VKEYUP:
|
||||
case QIT_VSHIFTDOWN:
|
||||
case QIT_VSHIFTUP:
|
||||
//TODO: eliminate??
|
||||
break;
|
||||
case QIT_CHAR:
|
||||
state->context().push_character(a.dwData);
|
||||
state->actions().push_character(a.dwData);
|
||||
break;
|
||||
case QIT_DEADKEY:
|
||||
state->context().push_marker(a.dwData);
|
||||
state->actions().push_marker(a.dwData);
|
||||
break;
|
||||
case QIT_BELL:
|
||||
state->actions().push_alert();
|
||||
break;
|
||||
case QIT_BACK:
|
||||
switch (a.dwData) {
|
||||
case BK_DEFAULT:
|
||||
// This only happens if we know we have context to delete. Last item must be a character
|
||||
assert(!state->context().empty() && state->context().back().type != KM_KBP_IT_MARKER);
|
||||
if (!state->context().empty()) state->context().pop_back();
|
||||
state->actions().push_backspace();
|
||||
break;
|
||||
case BK_DEADKEY:
|
||||
// This only happens if we know we have context to delete. Last item must be a deadkey
|
||||
assert(!state->context().empty() && state->context().back().type == KM_KBP_IT_MARKER);
|
||||
if (!state->context().empty()) state->context().pop_back();
|
||||
break;
|
||||
case BK_BACKSPACE:
|
||||
// User-initiated backspace. We need to delete deadkeys from context, both sides of the character deleted
|
||||
while (!state->context().empty() && state->context().back().type == KM_KBP_IT_MARKER) state->context().pop_back();
|
||||
if (!state->context().empty()) {
|
||||
state->context().pop_back();
|
||||
while (!state->context().empty() && state->context().back().type == KM_KBP_IT_MARKER) state->context().pop_back();
|
||||
}
|
||||
// Even if context is empty, we send the backspace event, because we may not
|
||||
// know the context.
|
||||
state->actions().push_backspace();
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case QIT_INVALIDATECONTEXT:
|
||||
state->actions().push_invalidate_context();
|
||||
break;
|
||||
default:
|
||||
//std::cout << "Unexpected item type " << a.ItemType << ", " << a.dwData << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
state->actions().commit();
|
||||
|
||||
return KM_KBP_STATUS_OK;
|
||||
break;
|
||||
case QIT_INVALIDATECONTEXT:
|
||||
state->actions().push_invalidate_context();
|
||||
break;
|
||||
default:
|
||||
// std::cout << "Unexpected item type " << a.ItemType << ", " << a.dwData << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr km_kbp_attr const engine_attrs = {
|
||||
256,
|
||||
KM_KBP_LIB_CURRENT,
|
||||
KM_KBP_LIB_AGE,
|
||||
KM_KBP_LIB_REVISION,
|
||||
KM_KBP_TECH_KMX,
|
||||
"SIL International"
|
||||
};
|
||||
state->actions().commit();
|
||||
|
||||
km_kbp_attr const & kmx_processor::attributes() const {
|
||||
return engine_attrs;
|
||||
}
|
||||
return KM_KBP_STATUS_OK;
|
||||
}
|
||||
|
||||
} // namespace kbp
|
||||
} // namespace km
|
||||
constexpr km_kbp_attr const engine_attrs = {
|
||||
256,
|
||||
KM_KBP_LIB_CURRENT,
|
||||
KM_KBP_LIB_AGE,
|
||||
KM_KBP_LIB_REVISION,
|
||||
KM_KBP_TECH_KMX,
|
||||
"SIL International"
|
||||
};
|
||||
|
||||
km_kbp_attr const & kmx_processor::attributes() const {
|
||||
return engine_attrs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,17 +24,30 @@ namespace kbp
|
|||
kmx::KMX_ProcessEvent _kmx;
|
||||
public:
|
||||
kmx_processor(path);
|
||||
km_kbp_status process_event(km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state) override;
|
||||
|
||||
km_kbp_status
|
||||
process_event(
|
||||
km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down
|
||||
) override;
|
||||
|
||||
km_kbp_attr const & attributes() const override;
|
||||
km_kbp_status validate() const override;
|
||||
|
||||
char16_t const * lookup_option(km_kbp_option_scope,
|
||||
std::u16string const & key) const override;
|
||||
option update_option(km_kbp_option_scope scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value) override;
|
||||
char16_t const *
|
||||
lookup_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key
|
||||
) const override;
|
||||
|
||||
option
|
||||
update_option(
|
||||
km_kbp_option_scope scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value
|
||||
) override;
|
||||
};
|
||||
|
||||
} // namespace kbp
|
||||
|
|
|
|||
|
|
@ -103,16 +103,24 @@ namespace km {
|
|||
return option(scope, key, i->second);
|
||||
}
|
||||
|
||||
|
||||
km_kbp_status mock_processor::process_event(km_kbp_state *state, km_kbp_virtual_key vk, uint16_t modifier_state)
|
||||
{
|
||||
km_kbp_status
|
||||
mock_processor::process_event(
|
||||
km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down
|
||||
) {
|
||||
assert(state);
|
||||
if (!state)
|
||||
return KM_KBP_STATUS_INVALID_ARGUMENT;
|
||||
|
||||
try
|
||||
{
|
||||
// At the start of every process_event allways clear the action_items
|
||||
if (!is_key_down) {
|
||||
// TODO: Implement caps lock handling
|
||||
return KM_KBP_STATUS_OK;
|
||||
}
|
||||
|
||||
try {
|
||||
// At the start of every process_event always clear the action_items
|
||||
state->actions().clear();
|
||||
|
||||
switch (vk)
|
||||
|
|
@ -162,15 +170,12 @@ namespace km {
|
|||
}
|
||||
|
||||
state->actions().commit();
|
||||
}
|
||||
catch (std::bad_alloc &)
|
||||
{
|
||||
} catch (std::bad_alloc &) {
|
||||
state->actions().clear();
|
||||
return KM_KBP_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
return KM_KBP_STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
km_kbp_attr const & mock_processor::attributes() const {
|
||||
|
|
|
|||
|
|
@ -26,20 +26,30 @@ namespace kbp
|
|||
mock_processor(km::kbp::path const &);
|
||||
// ~mock_processor() override;
|
||||
|
||||
km_kbp_status process_event(km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state) override;
|
||||
km_kbp_status
|
||||
process_event(
|
||||
km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down
|
||||
) override;
|
||||
|
||||
virtual km_kbp_attr const & attributes() const override;
|
||||
km_kbp_status validate() const override;
|
||||
|
||||
|
||||
char16_t const *
|
||||
lookup_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key
|
||||
) const override;
|
||||
|
||||
char16_t const * lookup_option(km_kbp_option_scope,
|
||||
std::u16string const & key) const override;
|
||||
option update_option(km_kbp_option_scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value) override;
|
||||
option
|
||||
update_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value
|
||||
) override;
|
||||
};
|
||||
|
||||
class null_processor : public mock_processor {
|
||||
|
|
|
|||
|
|
@ -36,18 +36,29 @@ namespace kbp
|
|||
auto & persisted_store() const noexcept { return _persisted; }
|
||||
auto & persisted_store() noexcept { return _persisted; }
|
||||
|
||||
virtual km_kbp_status process_event(km_kbp_state *,
|
||||
km_kbp_virtual_key,
|
||||
uint16_t modifier_state) = 0;
|
||||
virtual km_kbp_status
|
||||
process_event(
|
||||
km_kbp_state *,
|
||||
km_kbp_virtual_key,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down
|
||||
) = 0;
|
||||
|
||||
virtual km_kbp_attr const & attributes() const = 0;
|
||||
virtual km_kbp_status validate() const = 0;
|
||||
|
||||
virtual char16_t const * lookup_option(km_kbp_option_scope,
|
||||
std::u16string const & key) const = 0;
|
||||
virtual option update_option(km_kbp_option_scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value) = 0;
|
||||
virtual char16_t const *
|
||||
lookup_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key
|
||||
) const = 0;
|
||||
|
||||
virtual option
|
||||
update_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value
|
||||
) = 0;
|
||||
|
||||
friend json & operator << (json &j, abstract_processor const &opts);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@
|
|||
return KM_KBP_STATUS_OK;
|
||||
*/
|
||||
|
||||
pub fn rust_mock_process_event(_vk: u16, _modifier: u16) -> u32 {
|
||||
pub fn rust_mock_process_event(_vk: u16, _modifier: u16, _is_key_down: u8) -> u32 {
|
||||
return 0; //KM_KBP_STATUS_OK
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +117,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_rust_mock_process_event() {
|
||||
assert_eq!(0, rust_mock_process_event(0, 0));
|
||||
assert_eq!(0, rust_mock_process_event(0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#[no_mangle]
|
||||
pub extern "C" fn rust_mock_process_event(vk: u16, modifier: u16) -> u32 {
|
||||
return keyman_keyboard_processor::rust_mock_process_event(vk, modifier);
|
||||
pub extern "C" fn rust_mock_process_event(vk: u16, modifier: u16, is_key_down: u8) -> u32 {
|
||||
return keyman_keyboard_processor::rust_mock_process_event(vk, modifier, is_key_down);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,13 +59,15 @@ namespace km {
|
|||
return option(scope, key, i->second);
|
||||
}
|
||||
|
||||
extern "C" uint32_t rust_mock_process_event(uint16_t vk, uint16_t modifier);
|
||||
extern "C" uint32_t rust_mock_process_event(uint16_t vk, uint16_t modifier, uint8_t is_key_down);
|
||||
|
||||
km_kbp_status rust_mock_processor::process_event(km_kbp_state *state, km_kbp_virtual_key vk, uint16_t modifier_state)
|
||||
{
|
||||
km_kbp_status rust_mock_processor::process_event(km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down) {
|
||||
(void)(state);
|
||||
//km_kbd_rust_state rust_state(state);
|
||||
return rust_mock_process_event(vk, modifier_state);
|
||||
// km_kbd_rust_state rust_state(state);
|
||||
return rust_mock_process_event(vk, modifier_state, is_key_down);
|
||||
}
|
||||
|
||||
km_kbp_attr const & rust_mock_processor::attributes() const {
|
||||
|
|
|
|||
|
|
@ -24,20 +24,29 @@ namespace kbp
|
|||
rust_mock_processor(km::kbp::path const &);
|
||||
// ~mock_processor() override;
|
||||
|
||||
km_kbp_status process_event(km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state) override;
|
||||
km_kbp_status
|
||||
process_event(
|
||||
km_kbp_state *state,
|
||||
km_kbp_virtual_key vk,
|
||||
uint16_t modifier_state,
|
||||
uint8_t is_key_down
|
||||
) override;
|
||||
|
||||
virtual km_kbp_attr const & attributes() const override;
|
||||
km_kbp_status validate() const override;
|
||||
|
||||
char16_t const *
|
||||
lookup_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key
|
||||
) const override;
|
||||
|
||||
|
||||
char16_t const * lookup_option(km_kbp_option_scope,
|
||||
std::u16string const & key) const override;
|
||||
option update_option(km_kbp_option_scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value) override;
|
||||
option
|
||||
update_option(
|
||||
km_kbp_option_scope,
|
||||
std::u16string const & key,
|
||||
std::u16string const & value
|
||||
) override;
|
||||
};
|
||||
|
||||
class rust_null_processor : public rust_mock_processor {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ use wasm_bindgen::prelude::*;
|
|||
|
||||
#[wasm_bindgen]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_mock_process_event(vk: u16, modifier: u16) -> u32 {
|
||||
return keyman_keyboard_processor::rust_mock_process_event(vk, modifier);
|
||||
pub extern "C" fn rust_mock_process_event(vk: u16, modifier: u16, is_key_down: u8) -> u32 {
|
||||
return keyman_keyboard_processor::rust_mock_process_event(vk, modifier, is_key_down);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "state.hpp"
|
||||
#include "processor.hpp"
|
||||
#include <keyman/keyboardprocessor_consts.h>
|
||||
|
||||
using namespace km::kbp;
|
||||
|
||||
|
|
@ -26,6 +27,13 @@ void actions::push_persist(option const &&opt) {
|
|||
emplace_back(std::move(ai));
|
||||
}
|
||||
|
||||
void actions::push_capslock(bool turnOn) {
|
||||
assert(empty() || (!empty() && back().type != KM_KBP_IT_END));
|
||||
km_kbp_action_item ai = {KM_KBP_IT_CAPSLOCK, {0,}, {0}};
|
||||
ai.capsLock = turnOn;
|
||||
emplace_back(std::move(ai));
|
||||
}
|
||||
|
||||
|
||||
state::state(km::kbp::abstract_processor & ap, km_kbp_option_item const *env)
|
||||
: _processor(ap)
|
||||
|
|
@ -34,7 +42,7 @@ state::state(km::kbp::abstract_processor & ap, km_kbp_option_item const *env)
|
|||
//assert(env->scope == KM_KBP_OPT_ENVIRONMENT); // todo do we need scope? or can we find a way to eliminate it?
|
||||
ap.update_option(env->scope
|
||||
? km_kbp_option_scope(env->scope)
|
||||
: KM_KBP_OPT_ENVIRONMENT,
|
||||
: KM_KBP_OPT_ENVIRONMENT,
|
||||
env->key,
|
||||
env->value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
void push_persist(option const &);
|
||||
void push_persist(option const &&);
|
||||
void push_emit_keystroke(km_kbp_virtual_key vk=0);
|
||||
void push_capslock(bool);
|
||||
void push_invalidate_context();
|
||||
|
||||
void commit();
|
||||
|
|
@ -93,7 +94,6 @@ void actions::push_emit_keystroke(km_kbp_virtual_key vk) {
|
|||
emplace_back(km_kbp_action_item {KM_KBP_IT_EMIT_KEYSTROKE, {0,}, {vk}});
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void actions::push_invalidate_context() {
|
||||
assert(empty() || (!empty() && back().type != KM_KBP_IT_END));
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ void setup(const char *keyboard) {
|
|||
void test_debugging_disabled() {
|
||||
setup("000 - null keyboard.kmx");
|
||||
try_status(km_kbp_state_debug_set(test_state, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S, KM_KBP_MODIFIER_SHIFT));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S, KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_END}
|
||||
}));
|
||||
|
|
@ -242,7 +242,7 @@ void test_debugging_no_rule_match() {
|
|||
setup("000 - null keyboard.kmx");
|
||||
DEBUG_GROUP gp = {u"Main"};
|
||||
try_status(km_kbp_state_debug_set(test_state, 1));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S, KM_KBP_MODIFIER_SHIFT));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S, KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_S, KM_KBP_MODIFIER_SHIFT, 'S'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -261,7 +261,7 @@ void test_debugging_function_key() {
|
|||
setup("000 - null keyboard.kmx");
|
||||
DEBUG_GROUP gp = {u"Main"};
|
||||
try_status(km_kbp_state_debug_set(test_state, 1));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F1, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F1, 0, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_F1, 0, 0}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -281,7 +281,7 @@ void test_basic_rule_matches() {
|
|||
|
||||
// 'DE' + 'F' > U+0E04 U+0E05 U+0E06
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_D, KM_KBP_MODIFIER_SHIFT));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_D, KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_D, KM_KBP_MODIFIER_SHIFT, 'D'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -289,7 +289,7 @@ void test_basic_rule_matches() {
|
|||
km_kbp_state_debug_item{KM_KBP_DEBUG_END, 0, {}, {u"", nullptr, nullptr, {}, 1}}, // action item will emit a default 'D'
|
||||
}));
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_E, KM_KBP_MODIFIER_SHIFT));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_E, KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_E, KM_KBP_MODIFIER_SHIFT, 'E'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -297,7 +297,7 @@ void test_basic_rule_matches() {
|
|||
km_kbp_state_debug_item{KM_KBP_DEBUG_END, 0, {}, {u"", nullptr, nullptr, {}, 1}}, // action item will emit a default 'E'
|
||||
}));
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F, KM_KBP_MODIFIER_SHIFT));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F, KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_F, KM_KBP_MODIFIER_SHIFT, 'F'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -323,7 +323,7 @@ void test_multiple_groups() {
|
|||
|
||||
// '12' -> 'abc'
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_1, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_1, 0, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_1, 0, '1'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -342,7 +342,7 @@ void test_multiple_groups() {
|
|||
km_kbp_state_debug_item{KM_KBP_DEBUG_END, 0, {}, {u"", nullptr, nullptr, {}, 3}}, // action item will emit a 'b'
|
||||
}));
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_2, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_2, 0, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_2, 0, '2'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -378,7 +378,7 @@ void test_store_offsets() {
|
|||
|
||||
// 'ab' -> 'ex'
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_A, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_A, 0, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_A, 0, 'a'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
@ -390,7 +390,7 @@ void test_store_offsets() {
|
|||
km_kbp_state_debug_item{KM_KBP_DEBUG_END, 0, {}, {u"", nullptr, nullptr, {}, 4}}, // action item will emit a 'exay'
|
||||
}));
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_B, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_B, 0, 1));
|
||||
assert(debug_items(test_state, {
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_B, 0, 'b'}},
|
||||
km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}},
|
||||
|
|
|
|||
|
|
@ -165,20 +165,20 @@ int main(int, char * [])
|
|||
if (attrs->max_context < 16) return __LINE__;
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S,
|
||||
KM_KBP_MODIFIER_SHIFT));
|
||||
KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('S')}}}));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_I,
|
||||
KM_KBP_MODIFIER_SHIFT));
|
||||
KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('I')}}}));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_L, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_L, 0, 1));
|
||||
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('l')}}}));
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_BKSP, 0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_BKSP, 0, 1));
|
||||
assert(action_items(test_state, {{KM_KBP_IT_BACK, {0,}, {0}}}));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_L,
|
||||
KM_KBP_MODIFIER_SHIFT));
|
||||
KM_KBP_MODIFIER_SHIFT, 1));
|
||||
assert(action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('L')}}}));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F2,0));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_F2, 0, 1));
|
||||
assert(action_items(test_state, {{KM_KBP_IT_PERSIST_OPT, {0,},
|
||||
{uintptr_t(&expected_persist_opt)}}}));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
c Description: Tests Caps Lock
|
||||
c keys: [K_1][SHIFT K_2][K_A][SHIFT K_B]
|
||||
c expected: pass.pass.pass.pass.
|
||||
c option: &capsLock=1
|
||||
c context:
|
||||
c capsLock: 1
|
||||
c context:
|
||||
|
||||
store(&version) '10.0'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
c Description: Tests Caps Lock env set
|
||||
c keys: [K_1][K_CAPS][K_2][SHIFT K_3][K_4][K_CAPS][K_5][K_CAPS][K_6]
|
||||
c expected: pass.pass.pass.pass.pass.pass.
|
||||
c option: &capsLock=0
|
||||
c context:
|
||||
c capsLock: 0
|
||||
c context:
|
||||
|
||||
store(&version) '10.0'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
c Description: Tests Caps Lock always off
|
||||
c keys: [K_1][K_CAPS][K_2][K_CAPS][K_3]
|
||||
c expected: pass.pass.pass.
|
||||
c option: &capsLock=0
|
||||
c context:
|
||||
c capsLock: 0
|
||||
c context:
|
||||
|
||||
store(&version) '10.0'
|
||||
|
||||
|
|
|
|||
BIN
common/core/desktop/tests/unit/kmx/033 - caps always off.kmx
Normal file
BIN
common/core/desktop/tests/unit/kmx/033 - caps always off.kmx
Normal file
Binary file not shown.
|
|
@ -0,0 +1,23 @@
|
|||
c Description: Tests Caps Lock always off, entry to the test has Caps Lock
|
||||
c on to test that it is then switched off on first keystroke event.
|
||||
c keys: [K_1][K_CAPS][K_2][K_CAPS][K_3]
|
||||
c expected: pass.pass.pass.
|
||||
c capsLock: 1
|
||||
c context:
|
||||
|
||||
store(&version) '10.0'
|
||||
|
||||
store(&capsalwaysoff) '1'
|
||||
|
||||
begin Unicode > use(Main)
|
||||
|
||||
group(Main) using keys
|
||||
|
||||
+ [CAPS K_1] > 'fail.'
|
||||
+ [NCAPS K_1] > 'pass.'
|
||||
|
||||
+ [CAPS K_2] > 'fail.'
|
||||
+ [NCAPS K_2] > 'pass.'
|
||||
|
||||
+ [CAPS K_3] > 'fail.'
|
||||
+ [NCAPS K_3] > 'pass.'
|
||||
Binary file not shown.
|
|
@ -19,11 +19,18 @@ Following the comments are the normal rules of a Keyman keyboard.
|
|||
c Description: Tests Caps Lock env set
|
||||
```
|
||||
|
||||
- **option**: allows to put the system in a defined state. The example below turns
|
||||
caps-lock off.
|
||||
- **option**: allows to put the system in a defined state. The example below sets the platform.
|
||||
|
||||
```text
|
||||
c option: &capsLock=0
|
||||
c option: &platform=linux
|
||||
```
|
||||
|
||||
- **capsLock**: allows to set the caps lock state. The example below turns
|
||||
caps-lock on at the start of the test. `[K_CAPS]` in the **keys** comment
|
||||
allows toggling of caps lock.
|
||||
|
||||
```text
|
||||
c capsLock: 1
|
||||
```
|
||||
|
||||
- **context**: allows to setup a string which serves as context
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include <kmx/kmx_processevent.h>
|
||||
#include <kmx/kmx_xstring.h>
|
||||
|
||||
#include "path.hpp"
|
||||
#include "state.hpp"
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
namespace
|
||||
{
|
||||
bool g_beep_found = false;
|
||||
bool g_caps_lock_on = false;
|
||||
|
||||
struct key_event {
|
||||
km_kbp_virtual_key vk;
|
||||
|
|
@ -232,13 +234,63 @@ void apply_action(km_kbp_state const *, km_kbp_action_item const & act, std::u16
|
|||
case KM_KBP_IT_EMIT_KEYSTROKE:
|
||||
std::cout << "action: emit keystroke" << std::endl;
|
||||
break;
|
||||
case KM_KBP_IT_CAPSLOCK:
|
||||
std::cout << "action: capsLock " << act.capsLock << std::endl;
|
||||
g_caps_lock_on = act.capsLock;
|
||||
break;
|
||||
default:
|
||||
assert(false); // NOT SUPPORTED
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int run_test(const km::kbp::path & source, const km::kbp::path & compiled) {
|
||||
int caps_lock_state() {
|
||||
return g_caps_lock_on ? KM_KBP_MODIFIER_CAPS : 0;
|
||||
}
|
||||
|
||||
void toggle_caps_lock_state() {
|
||||
g_caps_lock_on = !g_caps_lock_on;
|
||||
}
|
||||
|
||||
km_kbp_option_item *get_keyboard_options(kmx_options options) {
|
||||
km_kbp_option_item *keyboard_opts = new km_kbp_option_item[options.size() + 1];
|
||||
|
||||
int i = 0;
|
||||
for (auto it = options.begin(); it != options.end(); it++) {
|
||||
if (it->type != KOT_INPUT) continue;
|
||||
|
||||
std::cout << "input option-key: " << it->key << std::endl;
|
||||
|
||||
std::u16string key = it->key;
|
||||
if (key[0] == u'&') {
|
||||
// environment value (aka system store)
|
||||
key.erase(0, 1);
|
||||
keyboard_opts[i].scope = KM_KBP_OPT_ENVIRONMENT;
|
||||
}
|
||||
else {
|
||||
keyboard_opts[i].scope = KM_KBP_OPT_KEYBOARD;
|
||||
}
|
||||
|
||||
km_kbp_cp *cp = new km_kbp_cp[key.length() + 1];
|
||||
key.copy(cp, key.length());
|
||||
cp[key.length()] = 0;
|
||||
|
||||
keyboard_opts[i].key = cp;
|
||||
|
||||
cp = new km_kbp_cp[it->value.length() + 1];
|
||||
it->value.copy(cp, it->value.length());
|
||||
cp[it->value.length()] = 0;
|
||||
|
||||
keyboard_opts[i].value = cp;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
keyboard_opts[i] = KM_KBP_OPTIONS_END;
|
||||
return keyboard_opts;
|
||||
}
|
||||
|
||||
int run_test(const km::kbp::path &source, const km::kbp::path &compiled) {
|
||||
std::string keys = "";
|
||||
std::u16string expected = u"", context = u"";
|
||||
kmx_options options;
|
||||
|
|
@ -256,46 +308,11 @@ int run_test(const km::kbp::path & source, const km::kbp::path & compiled) {
|
|||
try_status(km_kbp_keyboard_load(compiled.c_str(), &test_kb));
|
||||
|
||||
// Setup state, environment
|
||||
|
||||
try_status(km_kbp_state_create(test_kb, test_env_opts, &test_state));
|
||||
|
||||
// Setup keyboard options
|
||||
|
||||
if (options.size() > 0) {
|
||||
km_kbp_option_item *keyboard_opts = new km_kbp_option_item[options.size() + 1];
|
||||
|
||||
int i = 0;
|
||||
for (auto it = options.begin(); it != options.end(); it++) {
|
||||
if (it->type != KOT_INPUT) continue;
|
||||
|
||||
std::cout << "input option-key: " << it->key << std::endl;
|
||||
|
||||
std::u16string key = it->key;
|
||||
if (key[0] == u'&') {
|
||||
// environment value (aka system store)
|
||||
key.erase(0, 1);
|
||||
keyboard_opts[i].scope = KM_KBP_OPT_ENVIRONMENT;
|
||||
}
|
||||
else {
|
||||
keyboard_opts[i].scope = KM_KBP_OPT_KEYBOARD;
|
||||
}
|
||||
|
||||
km_kbp_cp *cp = new km_kbp_cp[key.length() + 1];
|
||||
key.copy(cp, key.length());
|
||||
cp[key.length()] = 0;
|
||||
|
||||
keyboard_opts[i].key = cp;
|
||||
|
||||
cp = new km_kbp_cp[it->value.length() + 1];
|
||||
it->value.copy(cp, it->value.length());
|
||||
cp[it->value.length()] = 0;
|
||||
|
||||
keyboard_opts[i].value = cp;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
keyboard_opts[i] = KM_KBP_OPTIONS_END;
|
||||
km_kbp_option_item *keyboard_opts = get_keyboard_options(options);
|
||||
|
||||
try_status(km_kbp_state_options_update(test_state, keyboard_opts));
|
||||
|
||||
|
|
@ -313,10 +330,18 @@ int run_test(const km::kbp::path & source, const km::kbp::path & compiled) {
|
|||
|
||||
// Run through key events, applying output for each event
|
||||
for (auto p = next_key(keys); p.vk != 0; p = next_key(keys)) {
|
||||
try_status(km_kbp_process_event(test_state, p.vk, p.modifier_state));
|
||||
|
||||
for (auto act = km_kbp_state_action_items(test_state, nullptr); act->type != KM_KBP_IT_END; act++) {
|
||||
apply_action(test_state, *act, text_store, options);
|
||||
// Because a normal system tracks caps lock state itself,
|
||||
// we mimic that in the tests. We assume caps lock state is
|
||||
// updated on key_down before the processor receives the
|
||||
// event.
|
||||
if (p.vk == KM_KBP_VKEY_CAPS) {
|
||||
toggle_caps_lock_state();
|
||||
}
|
||||
for (auto key_down = 1; key_down >= 0; key_down--) {
|
||||
try_status(km_kbp_process_event(test_state, p.vk, p.modifier_state | caps_lock_state(), key_down));
|
||||
for (auto act = km_kbp_state_action_items(test_state, nullptr); act->type != KM_KBP_IT_END; act++) {
|
||||
apply_action(test_state, *act, text_store, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +470,8 @@ int load_source(const km::kbp::path & path, std::string & keys, std::u16string &
|
|||
s_context = "c context: ",
|
||||
s_option = "c option: ",
|
||||
s_option_expected = "c expected option: ",
|
||||
s_option_saved = "c saved option: ";
|
||||
s_option_saved = "c saved option: ",
|
||||
s_capsLock = "c capsLock: ";
|
||||
|
||||
// Parse out the header statements in file.kmn that tell us (a) environment, (b) key sequence, (c) start context, (d) expected result
|
||||
std::ifstream kmn(path.native());
|
||||
|
|
@ -482,6 +508,9 @@ int load_source(const km::kbp::path & path, std::string & keys, std::u16string &
|
|||
else if (is_token(s_option_saved, line)) {
|
||||
if (!parse_option_string(line, options, KOT_SAVED)) return __LINE__;
|
||||
}
|
||||
else if (is_token(s_capsLock, line)) {
|
||||
g_caps_lock_on = parse_source_string(line).compare(u"1") == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (keys == "") {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ tests = [
|
|||
'030 - multiple groups',
|
||||
'031 - caps lock',
|
||||
# '032 - caps control', # TODO: support capsononly, capsalwaysoff, shiftfreescaps
|
||||
# '033 - caps alwyas off' # TODO: support capsononly, capsalwaysoff, shiftfreescaps
|
||||
'033 - caps always off',
|
||||
'034 - options double set reset',
|
||||
'035 - options double set staged',
|
||||
'036 - options - double reset staged',
|
||||
|
|
@ -70,7 +70,8 @@ tests = [
|
|||
|
||||
'044 - if and context',
|
||||
'045 - deadkey and context',
|
||||
'046 - deadkey and contextex'
|
||||
'046 - deadkey and contextex',
|
||||
'047 - caps always off initially on'
|
||||
]
|
||||
|
||||
if build_machine.system() == 'windows'
|
||||
|
|
|
|||
|
|
@ -165,7 +165,9 @@ int main(int, char * [])
|
|||
if (attrs->max_context < 16) return __LINE__;
|
||||
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S,
|
||||
KM_KBP_MODIFIER_SHIFT));
|
||||
KM_KBP_MODIFIER_SHIFT, true));
|
||||
try_status(km_kbp_process_event(test_state, KM_KBP_VKEY_S,
|
||||
KM_KBP_MODIFIER_SHIFT, false));
|
||||
|
||||
//TEMP
|
||||
action_items(test_state, {{KM_KBP_IT_CHAR, {0,}, {km_kbp_usv('S')}}});
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
[*]
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
#define KEYMAN_LALT 56
|
||||
#define KEYMAN_RCTRL 97
|
||||
#define KEYMAN_RALT 100
|
||||
#define KEYMAN_CAPS 0x3a
|
||||
|
||||
typedef struct _IBusKeymanEngine IBusKeymanEngine;
|
||||
typedef struct _IBusKeymanEngineClass IBusKeymanEngineClass;
|
||||
|
|
@ -809,52 +810,30 @@ ibus_keyman_engine_process_key_event (IBusEngine *engine,
|
|||
|
||||
g_message("DAR: ibus_keyman_engine_process_key_event - keyval=%02i, keycode=%02i, state=%02x", keyval, keycode, state);
|
||||
|
||||
if (state & IBUS_RELEASE_MASK)
|
||||
{
|
||||
switch(keycode) {
|
||||
case KEYMAN_LCTRL:
|
||||
keyman->lctrl_pressed = FALSE;
|
||||
break;
|
||||
case KEYMAN_RCTRL:
|
||||
keyman->rctrl_pressed = FALSE;
|
||||
break;
|
||||
case KEYMAN_LALT:
|
||||
keyman->lalt_pressed = FALSE;
|
||||
break;
|
||||
case KEYMAN_RALT:
|
||||
keyman->ralt_pressed = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
gboolean isKeyDown = !!(state & IBUS_RELEASE_MASK);
|
||||
|
||||
// REVIEW: why don't we handle these keys?
|
||||
switch (keycode) {
|
||||
case KEYMAN_LCTRL:
|
||||
keyman->lctrl_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_RCTRL:
|
||||
keyman->rctrl_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_LALT:
|
||||
keyman->lalt_pressed = isKeyDown;
|
||||
break;
|
||||
case KEYMAN_RALT:
|
||||
keyman->ralt_pressed = isKeyDown;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keycode < 0 || keycode > 255)
|
||||
{
|
||||
g_warning("keycode %d out of range", keycode);
|
||||
return FALSE;
|
||||
if (keycode < 0 || keycode > 255) {
|
||||
g_warning("keycode %d out of range", keycode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (keycode_to_vk[keycode] == 0) // key we don't handle
|
||||
{
|
||||
//save if a possible Ctrl or Alt modifier
|
||||
switch(keycode) {
|
||||
case KEYMAN_LCTRL:
|
||||
keyman->lctrl_pressed = TRUE;
|
||||
break;
|
||||
case KEYMAN_RCTRL:
|
||||
keyman->rctrl_pressed = TRUE;
|
||||
break;
|
||||
case KEYMAN_LALT:
|
||||
keyman->lalt_pressed = TRUE;
|
||||
break;
|
||||
case KEYMAN_RALT:
|
||||
keyman->ralt_pressed = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (keycode_to_vk[keycode] == 0) { // key we don't handle
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -899,8 +878,8 @@ ibus_keyman_engine_process_key_event (IBusEngine *engine,
|
|||
km_kbp_context *context = km_kbp_state_context(keyman->state);
|
||||
g_free(get_current_context_text(context));
|
||||
g_message("DAR: ibus_keyman_engine_process_key_event - km_mod_state=%x", km_mod_state);
|
||||
km_kbp_status event_status = km_kbp_process_event(keyman->state,
|
||||
keycode_to_vk[keycode], km_mod_state);
|
||||
km_kbp_status event_status =
|
||||
km_kbp_process_event(keyman->state, keycode_to_vk[keycode], km_mod_state, isKeyDown);
|
||||
context = km_kbp_state_context(keyman->state);
|
||||
g_message("after process key event");
|
||||
g_free(get_current_context_text(context));
|
||||
|
|
@ -919,7 +898,7 @@ ibus_keyman_engine_process_key_event (IBusEngine *engine,
|
|||
g_message("after processing all actions");
|
||||
g_free(get_current_context_text(context));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_keyman_engine_set_surrounding_text (IBusEngine *engine,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue