Index: src/engine/state/SKKEvent.h =================================================================== --- src/engine/state/SKKEvent.h (revision 157) +++ src/engine/state/SKKEvent.h (working copy) @@ -71,7 +71,8 @@ PrevCandidate = (1 << 11), RemoveTrigger = (1 << 12), InputChars = (1 << 13), - CompConversion = (1 << 14) + CompConversion = (1 << 14), + StickyKey = (1 << 15) }; // 処理オプション @@ -108,6 +109,7 @@ bool IsRemoveTrigger() const { return attribute & RemoveTrigger; } bool IsInputChars() const { return attribute & InputChars; } bool IsCompConversion() const { return attribute & CompConversion; } + bool IsStickyKey() const { return attribute & StickyKey; } const static SKKEvent& Null() { static SKKEvent obj(SKK_NULL, 0, 0); Index: src/engine/state/SKKStatePrimary-inl.h =================================================================== --- src/engine/state/SKKStatePrimary-inl.h (revision 157) +++ src/engine/state/SKKStatePrimary-inl.h (working copy) @@ -152,6 +152,10 @@ } } + if(param.IsStickyKey()) { + return State::Transition(&SKKState::KanaEntry); + } + if(param.IsUpperCases()) { return State::Forward(&SKKState::KanaEntry); } Index: src/engine/state/SKKStateComposing-inl.h =================================================================== --- src/engine/state/SKKStateComposing-inl.h (revision 157) +++ src/engine/state/SKKStateComposing-inl.h (working copy) @@ -169,6 +169,19 @@ return State::Transition(&SKKState::KanaInput); } + // Sticky key + if(param.IsStickyKey()) { + if(context_->entry.IsEmpty()) { + if(param.IsInputChars()) { + editor_->HandleChar(param.code, param.IsDirect()); + } + editor_->Commit(); + return State::Transition(&SKKState::KanaInput); + } else { + return State::Transition(&SKKState::OkuriInput); + } + } + // 送りあり if(param.IsUpperCases() && !context_->entry.IsEmpty()) { return State::Forward(&SKKState::OkuriInput); Index: src/engine/tests/test.dat =================================================================== --- src/engine/tests/test.dat (revision 157) +++ src/engine/tests/test.dat (working copy) @@ -621,3 +621,16 @@ ctrl::g mode=J,fixed=蝙蝠 ctrl::/,sel=蝙蝠 mode=J,marked=▽こうもり ctrl::m mode=J,fixed=こうもり + +# sticky shift +# ---------------------------------------------------------------------- +; mode=J,marked=▽ +a mode=J,marked=▽あ +; mode=J,marked=▽あ* +r mode=J,marked=▽あ*r +i mode=J,marked=▼有り +ctrl::m mode=J,fixed=有り +ctrl::j mode=J +; mode=J,marked=▽ +; mode=J,fixed=; + Index: src/engine/tests/keymap.conf =================================================================== --- src/engine/tests/keymap.conf (revision 157) +++ src/engine/tests/keymap.conf (working copy) @@ -44,3 +44,5 @@ Direct group::keycode::0x41,0x43,0x45,0x4b,0x4e,0x51-0x59,0x5b,0x5c,0x5f InputChars group::hex::0x20-0x7e CompConversion alt::hex::0x20||shift::hex::0x20 + +StickyKey ; Index: src/engine/keymap/SKKKeymapEntry.cpp =================================================================== --- src/engine/keymap/SKKKeymapEntry.cpp (revision 157) +++ src/engine/keymap/SKKKeymapEntry.cpp (working copy) @@ -72,6 +72,7 @@ { "RemoveTrigger", RemoveTrigger, TYPE_ATTRIBUTE }, { "InputChars", InputChars, TYPE_ATTRIBUTE }, { "CompConversion", CompConversion, TYPE_ATTRIBUTE }, + { "StickyKey", StickyKey, TYPE_ATTRIBUTE }, { "AlwaysHandled", AlwaysHandled, TYPE_HANDLE_OPTION }, { "PseudoHandled", PseudoHandled, TYPE_HANDLE_OPTION },