Skip to content

fix: Ctrlキーの組み合わせを適切に処理できるように修正#324

Merged
ensan-hcl merged 3 commits into
azooKey:mainfrom
mjun0812:fix/ctrl-shortcut
May 9, 2026
Merged

fix: Ctrlキーの組み合わせを適切に処理できるように修正#324
ensan-hcl merged 3 commits into
azooKey:mainfrom
mjun0812:fix/ctrl-shortcut

Conversation

@mjun0812
Copy link
Copy Markdown
Contributor

@mjun0812 mjun0812 commented May 8, 2026

概要・背景

PR #310 では未定義のCtrl系キーをIMEで処理しないようにしましたが、処理が不十分で一部のCtrlの組み合わせの入力に影響が出てしまいました。

このPRでは、既知のCtrlショートカットをlogicalKey側で処理した後、未定義のCtrl系キーをkeyCodeでの処理へ落とさず 早期に.unknown で返すことで、ホストアプリ側へ渡すようにして、アプリのショートカットが適切に動作するように修正します。

加えて、composing中(変換中の入力がある状態)に未定義のCtrl修飾付きキー(例: Ctrl+Shift+O)が発火されると、Discordなどの一部アプリで変換中の入力が消失する問題があったため、composing系状態ではIME側で .consume して入力を保護します。

関連Issue

Related to #310

変更内容

  • logicalKeyで既知のCtrlショートカットを処理した後に、未定義のCtrl系キーを .unknown に分類
  • Ctrl+Delete は既存仕様の .forget として維持
  • Ctrl+数字 が数字入力として扱われないよう、数字キー分岐でも .control を明示的に除外
  • InputState の composing / previewing / selecting / replaceSuggestion で .unknown 分岐を分離し、Ctrl修飾を含む場合は .consume を返して入力テキストを保護
  • 未定義Ctrl系、既知Ctrlショートカット、.unknown のfallthrough/consumeを検証するテストを追加

詳細

処理の流れ

変更前は、UserAction.getUserAction の処理が大きく次の流れになっていました。

段階 内容
1 charactersIgnoringModifiers から logicalKey を取得する
2 logicalKey ブロック内で既知のショートカットや記号入力を判定する(PR #310 で追加された control 修飾を含む未定義キーを .unknown にする)
3 logicalKey で処理されなかった場合、keyCode ブロックで Space / Delete / 矢印 / 数字などの物理キーを判定する
4 最後に printable な文字を .input として扱う

この構造では、control 修飾を含む未定義キーの判定が logicalKey ブロック内にありました。

変更後は、処理の流れを次のように整理しています。

段階 内容
1 charactersIgnoringModifiers から logicalKey を取得する
2 logicalKey ブロック内で、azooKey が明示的に対応している Ctrl+H, Ctrl+J, Ctrl+;, Ctrl+Shift+U などを処理する
3 logicalKey ブロックで処理されなかった control 修飾付きキーを、keyCode ブロックへ入る前に .unknown にする(ただし Ctrl+Delete は既存仕様の .forget として扱うため、4へ通す)
4 control 修飾を含まない通常キーを keyCode ブロックで処理する
5 最後に printable な文字を .input として扱う

これにより、既存の logicalKey -> keyCode -> fallback という大枠は維持しつつ、未定義の control 系キーがkeyCode処理へ落ちないようにしています。

発生していた問題と解決方法

Ctrl + Deleteが動作しなくなっていた

1つ目は、control 修飾付きキーを logicalKey ブロック内でまとめて .unknown にしていたため、後続の keyCode ブロックにある Ctrl+Delete の処理まで到達できなくなったことです。
Ctrl+Delete は既存仕様として .forget に対応していましたが、logicalKey ブロックで先に .unknown になってしまうと、下記の Delete 分岐へ到達できていませんでした。
このPRでは、明示的にCtrl + Deleteを分岐で扱うことで修正しました。

一部のCtrl +系のキーが適切に処理されていなかった

2つ目は、charactersIgnoringModifiers が取得できないキーや、logicalKey ブロックで処理されずにkeyCode側で処理されるキーでは、未定義の control 系キーが Space、矢印、数字などとして処理される可能性が残っていたことです。

例えば以下のようなケースです。

入力 望ましい動作 問題がある場合の動作
Ctrl+Space ホストアプリへ渡す .space として処理され、スペース入力や変換操作になる
Ctrl+Left ホストアプリへ渡す .navigation(.left) として azooKey 側で消費される
Ctrl+1 ホストアプリへ渡す .number(.one) として処理される
Ctrl+Shift+O ホストアプリへ渡す .input.unknown の扱いが処理位置に依存する

今回の修正では、まず logicalKey ブロックで azooKey が明示的に対応している control 系ショートカットだけを処理します。その後、keyCode ブロックに入る前に、未定義の control 系キーを .unknown として返します。
これにより、Ctrl+SpaceCtrl+LeftCtrl+数字 などがkeyCode処理へ落ちず、ホストアプリへ fallthrough されるようになります。

さらに、数字キー分岐でも .control を明示的に除外しています。

変換中にCtrl系が入力されるとテキストが破棄されてしまった

3つ目は、composing中(変換中の入力がある状態)に未定義のCtrl修飾付きキー(例: Ctrl+Shift+O)が押されたとき、.unknown がホストアプリへ fallthrough される過程で、Discordなどの一部アプリがテキストを破棄してしまい、変換中の入力が消失する問題です。

UserAction 側で .unknown に分類してホストへ委譲する方針を維持しつつも、composing系状態では入力を保護したいので、InputStatecomposing / previewing / selecting / replaceSuggestion の各状態で .unknown 分岐を他のケースから分離し、.control 修飾を含むイベントは .consume を返すようにしました。

これにより、

  • composing系状態でCtrl修飾付きの .unknown が来た場合: IME側で .consume して変換文字列を保持
  • .none 状態でCtrl修飾付きの .unknown が来た場合: 従来通り .fallthrough してアプリ側のショートカットを発火
  • modifier を含まない .unknown が来た場合: 従来通り .fallthrough

という動作になります。

追加したテスト

テスト 入力 期待結果 目的
未定義Controlキー Ctrl+` .unknown 未定義のControl系キーを文字入力にしないことを確認
未定義Control+Shiftキー Ctrl+Shift+O .unknown Discordなどで問題になったControl+Shift+文字をIME側で消費しないことを確認
Control+数字 Ctrl+0Ctrl+9 .unknown 数字入力や候補選択として扱われないことを確認
Control+Space Ctrl+Space .unknown .space として処理されず、ホストアプリへ渡ることを確認
Control+矢印 Ctrl+Left .unknown .navigation(.left) として消費されないことを確認
既存Controlショートカット Ctrl+Delete .forget 既存のforget動作が維持されることを確認
既存Controlショートカット Ctrl+H .backspace 既存のbackspace動作が維持されることを確認
既存Controlショートカット Ctrl+J .function(.six) 既存のF6相当の変換動作が維持されることを確認
既存Controlショートカット Ctrl+; .function(.eight) 既存のF8相当の変換動作が維持されることを確認
既存Control+Shiftショートカット Ctrl+Shift+U .startUnicodeInput Unicode入力モード開始が維持されることを確認
fallthrough .unknown in InputState.none .fallthrough 未定義Controlキーがホストアプリへ渡ることを確認
consume Ctrl+` / Ctrl+Shift+O in composing / previewing / selecting / replaceSuggestion .consume composing系状態でCtrl修飾付き .unknown がIME側で消費されmarked textを保護することを確認
fallthrough Ctrl+Shift+O in InputState.none .fallthrough composing中でない場合はアプリ側のショートカットへ渡ることを確認
fallthrough modifierなし .unknown in InputState.composing .fallthrough Ctrlを伴わない .unknown は従来通りfallthroughされることを確認(既存挙動の回帰防止)

テスト方法

swift test --package-path Core

@mjun0812 mjun0812 marked this pull request as draft May 8, 2026 13:41
@ensan-hcl ensan-hcl marked this pull request as ready for review May 8, 2026 13:54
@ensan-hcl ensan-hcl self-requested a review May 8, 2026 13:54
@ensan-hcl ensan-hcl added the bug Something isn't working label May 8, 2026
@mjun0812 mjun0812 marked this pull request as draft May 8, 2026 13:55
@mjun0812
Copy link
Copy Markdown
Contributor Author

mjun0812 commented May 8, 2026

すみません、もう1つ直さなければならない箇所を見つけたので、一旦draftにさせていただきます。少々お待ちください!

- InputState.composing/previewing/selecting/replaceSuggestionの`.unknown`分岐を分離
- Ctrl修飾を含むイベントは`.consume`を返してmarked textを保護する
- それ以外の`.unknown`は従来通り`.fallthrough`させてホストアプリに委譲する
- ControlShortcutRoutingTestsにcomposing系状態でのconsume確認とnone状態のfallthrough確認を追加
Comment thread Core/Sources/Core/InputUtils/InputState.swift
@mjun0812
Copy link
Copy Markdown
Contributor Author

mjun0812 commented May 8, 2026

#315 (comment)

composingじゃない状態での切り替えは成立してる。ただ、それ以外がちょっと変。

Spotlightで

  1. 日本語IMで「a」を入力→composingで「あ」が出る
  2. 英語IMに英数キーで切り替えて「a」を入力→composingで「あa」になる

と同じ動作になるのが期待なんだけど

  1. 日本語IMで「a」を入力→composingで「あ」が出る
  2. ctrl+shift+;を入力して「a」を入力→composingで「ああ」になる

#310 に言及しているこのコメントですが、このPRのスコープ以外の修正も必要そうなので、別のPRで出そうと思います。後ほどよろしくお願いします。

@mjun0812
Copy link
Copy Markdown
Contributor Author

mjun0812 commented May 8, 2026

不具合例として挙げていただいた、Discodeでの入力中にctrl + shift + oで入力がクリアされている問題、下記動画で修正されていることが確認できるかと思います!

ScreenShot.2026-05-09.0.53.18.mov

@mjun0812 mjun0812 marked this pull request as ready for review May 8, 2026 15:57
@mjun0812
Copy link
Copy Markdown
Contributor Author

mjun0812 commented May 8, 2026

@ensan-hcl
おまたせしました、前回の変更( #310 )では、多大な迷惑をおかけしました...
レビューお願いいたします。

Copy link
Copy Markdown
Member

@ensan-hcl ensan-hcl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ensan-hcl ensan-hcl merged commit 0dd51f0 into azooKey:main May 9, 2026
4 checks passed
@mjun0812 mjun0812 deleted the fix/ctrl-shortcut branch May 9, 2026 04:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants