feat(input): 完成阶段 1 输入采集与规范化
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
/*******************************************************************************
|
||||
* StellarX native keyboard, text, IME, and activation event model.
|
||||
* Stage 1 only captures, normalizes, queues, and observes these events.
|
||||
* Focus, routing, and control behavior are intentionally out of scope.
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
namespace StellarX
|
||||
{
|
||||
enum class KeyAction : std::uint8_t
|
||||
{
|
||||
Down,
|
||||
Up
|
||||
};
|
||||
|
||||
// Snapshot modifiers in WndProc; delayed consumers must not reread global state.
|
||||
struct KeyModifiers
|
||||
{
|
||||
bool leftControl = false;
|
||||
bool rightControl = false;
|
||||
bool leftShift = false;
|
||||
bool rightShift = false;
|
||||
bool leftAlt = false;
|
||||
bool rightAlt = false;
|
||||
|
||||
bool control() const noexcept { return leftControl || rightControl; }
|
||||
bool shift() const noexcept { return leftShift || rightShift; }
|
||||
bool alt() const noexcept { return leftAlt || rightAlt; }
|
||||
};
|
||||
|
||||
struct KeyEvent
|
||||
{
|
||||
KeyAction action = KeyAction::Down;
|
||||
|
||||
UINT virtualKey = 0; // Raw WndProc VK; VK_PROCESSKEY is never rewritten.
|
||||
UINT physicalVirtualKey = 0; // Left/right-normalized modifier VK.
|
||||
UINT scanCode = 0;
|
||||
|
||||
std::uint16_t repeatCount = 0;
|
||||
bool extended = false;
|
||||
bool wasDown = false;
|
||||
bool altContext = false; // Raw lParam bit 29; modifiers.alt() is the semantic snapshot.
|
||||
bool systemKey = false;
|
||||
|
||||
// Snapshot of the standard IME lifecycle axis at capture time.
|
||||
// It never overrides the per-key ownership expressed by VK_PROCESSKEY.
|
||||
bool imeComposingAtCapture = false;
|
||||
|
||||
KeyModifiers modifiers{};
|
||||
|
||||
bool isAutoRepeat() const noexcept
|
||||
{
|
||||
return action == KeyAction::Down && wasDown;
|
||||
}
|
||||
|
||||
bool isImeOwnedAtCapture() const noexcept
|
||||
{
|
||||
// Per-key ownership and IME lifecycle are intentionally independent axes.
|
||||
// A normal key captured during a standard composition remains a normal key;
|
||||
// routing may suppress it because of the lifecycle snapshot, but must not
|
||||
// rewrite its ownership.
|
||||
return virtualKey == VK_PROCESSKEY;
|
||||
}
|
||||
};
|
||||
|
||||
enum class TextSource : std::uint8_t
|
||||
{
|
||||
ImeResult,
|
||||
UnicodeChar,
|
||||
UnicodeScalar,
|
||||
AnsiCharFallback,
|
||||
Clipboard
|
||||
};
|
||||
|
||||
struct TextInputEvent
|
||||
{
|
||||
std::wstring text;
|
||||
TextSource source = TextSource::UnicodeChar;
|
||||
std::uint64_t compositionId = 0; // Zero for non-IME input.
|
||||
};
|
||||
|
||||
enum class CompositionStage : std::uint8_t
|
||||
{
|
||||
Start,
|
||||
Update,
|
||||
Commit,
|
||||
Cancel,
|
||||
End
|
||||
};
|
||||
|
||||
struct CompositionEvent
|
||||
{
|
||||
CompositionStage stage = CompositionStage::Start;
|
||||
std::uint64_t compositionId = 0;
|
||||
std::wstring compositionText;
|
||||
std::uint32_t caretOffset = 0;
|
||||
};
|
||||
|
||||
struct WindowActivationEvent
|
||||
{
|
||||
bool keyboardFocusActive = false;
|
||||
HWND otherWindow = nullptr;
|
||||
};
|
||||
|
||||
using NativeInputPayload = std::variant<
|
||||
KeyEvent,
|
||||
TextInputEvent,
|
||||
CompositionEvent,
|
||||
WindowActivationEvent>;
|
||||
|
||||
struct NativeInputEvent
|
||||
{
|
||||
std::uint64_t sequence = 0;
|
||||
DWORD messageTime = 0;
|
||||
HWND hwnd = nullptr;
|
||||
NativeInputPayload payload{};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user