--- nono/vm/keyboard.cpp 2026/04/29 17:05:06 1.1.1.9 +++ nono/vm/keyboard.cpp 2026/04/29 17:05:11 1.1.1.10 @@ -4,6 +4,10 @@ // Licensed under nono-license.txt // +// +// キーボード (基本クラス) +// + // 物理キーボードとソフトウェアキーボードについて // // 物理キーボード入力 ---------->+ @@ -83,8 +87,7 @@ // v // MakeKey()/BreakKey() : // | -// | inputqueue + : -// | keyinput_event +// | KEY_INPUT Message : // | - - - - - - - - - - - -> KeyInputCallback() // o | // : MD::KeyInput() @@ -96,63 +99,102 @@ // 機種ごとに接続先に送信 #include "keyboard.h" +#include "config.h" #include "scheduler.h" +#include "sync.h" #include "uimessage.h" -std::unique_ptr gKeyboard; +// グローバル参照用 +Keyboard *gKeyboard; // コンストラクタ Keyboard::Keyboard() : inherited("Keyboard") { pressed.resize(KC_max); - - keyinput_event.func = (DeviceCallback_t)&Keyboard::KeyInputCallback; - keyinput_event.time = 0; - keyinput_event.SetName("Keyboard Input"); } // デストラクタ Keyboard::~Keyboard() { + gKeyboard = NULL; } -// リセット +// 初期化 +bool +Keyboard::Init() +{ + gScheduler->ConnectMessage(MessageID::KEY_INPUT, this, + ToMessageCallback(&Keyboard::KeyInputCallback)); + return true; +} + +// 電源オン/リセット void -Keyboard::ResetHard() +Keyboard::ResetHard(bool poweron) { - // 内部状態を全部リセット + if (poweron) { + is_connected = gConfig->Find("keyboard-connect").AsInt(); + + if (is_connected) { + DoConnect(); + } else { + DoDisconnect(); + } + + // キー通知 + gSync->RequestKeyPressed(active != 0); + } - inputqueue.Clear(); + // 内部状態をリセット sendqueue.Clear(); +} + +// 電源オフ +void +Keyboard::PowerOff() +{ + // LED は全部消灯 + std::fill(led.begin(), led.end(), false); + + // キーボードから手を離したことにする std::fill(pressed.begin(), pressed.end(), false); active = 0; + // キーが全部解放されたので通知 - gScheduler->RequestKeyPressed(false); + gSync->RequestKeyPressed(false); + + DoDisconnect(); +} + +// キーボードを接続する (外部から呼ばれる) +void +Keyboard::Connect(bool connect) +{ + uint code = connect ? CC_connect : CC_disconnect; + + // ここは UI スレッドからも呼ばれるのでメッセージを送る + gScheduler->SendMessage(MessageID::KEY_INPUT, code); } // キーを押した (外部から、共通キーコードで呼ばれる) void Keyboard::MakeKey(uint keycode) { - // ここは UI スレッドからも呼ばれるのでキューに突っ込むだけ - { - std::unique_lock lock(mtx); - inputqueue.Enqueue(keycode | KC_FLAG_MAKE); - } - keyinput_event.Start(); + keycode |= KC_FLAG_MAKE; + + // ここは UI スレッドからも呼ばれるのでメッセージを送る + gScheduler->SendMessage(MessageID::KEY_INPUT, keycode); } // キーを離した (外部から、共通キーコードで呼ばれる) void Keyboard::BreakKey(uint keycode) { - // ここは UI スレッドからも呼ばれるのでキューに突っ込むだけ - { - std::unique_lock lock(mtx); - inputqueue.Enqueue(keycode | KC_FLAG_BREAK); - } - keyinput_event.Start(); + keycode |= KC_FLAG_BREAK; + + // ここは UI スレッドからも呼ばれるのでメッセージを送る + gScheduler->SendMessage(MessageID::KEY_INPUT, keycode); } // 文字による入力 @@ -190,21 +232,59 @@ Keyboard::CharInput(uint charcode) } } -// キー入力コールバック +// キー入力メッセージコールバック void -Keyboard::KeyInputCallback(Event& ev) +Keyboard::KeyInputCallback(MessageID msgid, uint32 arg) { - for (;;) { - uint keystat; - { - std::unique_lock lock(mtx); - if (inputqueue.Empty()) { - return; - } - keystat = inputqueue.Dequeue(); - } + uint keystat = arg; + switch (keystat) { + case CC_connect: + DoConnect(); + break; + case CC_disconnect: + DoDisconnect(); + break; + default: KeyInput(keystat); + break; + } +} + +// キーボードの接続処理の実体。 +void +Keyboard::DoConnect() +{ + is_connected = true; + + MDConnect(); + + // LED は全部消灯で初期化 + std::fill(led.begin(), led.end(), false); + + // 接続されたので押しっぱなしになっているキーをスキャンして送る + for (int i = 0; i < pressed.size(); i++) { + if (pressed[i]) { + KeyInput(i | KC_FLAG_BREAK); + KeyInput(i); + } } + + // UI に通知する + UIMessage::Post(UIMessage::KEYBOARD); +} + +void +Keyboard::DoDisconnect() +{ + is_connected = false; + + // 電源が切れたので LED は全部消す + std::fill(led.begin(), led.end(), false); + + MDDisconnect(); + + // UI に通知する + UIMessage::Post(UIMessage::KEYBOARD); } // キー入力を1つ処理する。 @@ -258,8 +338,8 @@ Keyboard::KeyInputCommon(uint keystat) } } - // キーが押されてる間は VM の高速実行を抑制する - // すべてのキーが離されたら高速モードを許可する + // キーが押されてる間は VM の高速実行を抑制する。 + // すべてのキーが離されたら高速モードを許可する。 pressed[keycode] = ismake; if (ismake) { Acquire(); @@ -285,6 +365,11 @@ Keyboard::KeyInputCommon(uint keystat) keystat |= KC_FLAG_BREAK; } + // キーボードが接続されていなければここまで処理して false を返す + if (is_connected == false) { + return false; + } + if (ledflag != KC_FLAG_LED_DROP) { // 送信キューに登録 @@ -305,7 +390,7 @@ void Keyboard::Acquire() { if (active++ == 0) { - gScheduler->RequestKeyPressed(true); + gSync->RequestKeyPressed(true); } } @@ -315,7 +400,7 @@ void Keyboard::Release() { if (--active == 0) { - gScheduler->RequestKeyPressed(false); + gSync->RequestKeyPressed(false); } }