Input System

Microsoft::Xna::Framework::Input — Keyboard, Mouse, GamePad, TouchPanel, TextInputEXT, Accelerometer

Implementation status: Keyboard, Mouse, GamePad, and TouchPanel are fully implemented — TouchPanel's gesture pipeline (Tap, FreeDrag, Flick, Pinch...PinchComplete) is a byte-faithful FNA port, wired end-to-end and tested with a deterministic clock (~98% behavior). Accelerometer is declared and structurally wired but still requires hardware validation. The underlying OS event layer is provided by SDL3.

Overview

All input classes live in the Microsoft::Xna::Framework::Input namespace and follow a polling model that matches XNA 4.0 exactly: you call GetState() once per frame, store the result, and compare it with the previous frame's state to detect transitions. SDL3 handles the underlying OS events and translates them into the state snapshots that CNA exposes.

The typical per-frame pattern for any device is:

// Declare in your Game class
KeyboardState previousKeyboard;

// In Update()
KeyboardState currentKeyboard = Keyboard::GetState();

if (currentKeyboard.IsKeyDown(Keys::Space) && previousKeyboard.IsKeyUp(Keys::Space)) {
    // Space was just pressed this frame
}

previousKeyboard = currentKeyboard;  // save for next frame

The same pattern applies to MouseState and GamePadState. Because the state objects are plain value types, storing and copying them is cheap.

Keyboard

The Keyboard class provides a snapshot of every key on the physical keyboard. There is no distinction between left and right modifier keys at the KeyboardState level — use Keys::LeftShift / Keys::RightShift etc. when you need that granularity.

MemberDescription
Keyboard::GetState() Returns a KeyboardState snapshot for the current frame. Call once per frame.
state.IsKeyDown(Keys k) Returns true if the specified key is held down.
state.IsKeyUp(Keys k) Returns true if the specified key is not pressed.
state.GetPressedKeys() Returns a collection of all Keys values that are currently down.

The Keys enum covers the full keyboard: alphanumeric keys, function keys (F1F24), numpad keys (NumPad0NumPad9, Multiply, Add, etc.), navigation keys (Home, End, PageUp, PageDown), and modifier keys (LeftShift, RightShift, LeftControl, RightControl, LeftAlt, RightAlt).

Detecting a key press (held last frame, pressed this frame) versus a key release:

// Press: key was up last frame and is down this frame
bool justPressed  = current.IsKeyDown(k) && previous.IsKeyUp(k);

// Release: key was down last frame and is up this frame
bool justReleased = current.IsKeyUp(k)   && previous.IsKeyDown(k);

Example: WASD movement

#include <Microsoft/Xna/Framework/Input/Keyboard.hpp>

using namespace Microsoft::Xna::Framework::Input;

// In Game::Update(GameTime gameTime)
KeyboardState kb = Keyboard::GetState();

Vector2 velocity = Vector2::Zero;
float speed = 200.0f * (float)gameTime.ElapsedGameTime.TotalSeconds();

if (kb.IsKeyDown(Keys::W) || kb.IsKeyDown(Keys::Up))    velocity.Y -= speed;
if (kb.IsKeyDown(Keys::S) || kb.IsKeyDown(Keys::Down))  velocity.Y += speed;
if (kb.IsKeyDown(Keys::A) || kb.IsKeyDown(Keys::Left))  velocity.X -= speed;
if (kb.IsKeyDown(Keys::D) || kb.IsKeyDown(Keys::Right)) velocity.X += speed;

playerPosition += velocity;

Mouse

The Mouse class returns a MouseState containing cursor coordinates in screen pixels, scroll wheel accumulation, and the state of all five buttons. Coordinates are relative to the top-left corner of the game window.

MemberTypeDescription
Mouse::GetState() MouseState Returns the current mouse state snapshot.
state.X int Cursor X position in window pixels.
state.Y int Cursor Y position in window pixels.
state.ScrollWheelValue int Accumulated scroll wheel delta since game start.
state.LeftButton ButtonState Pressed or Released.
state.RightButton ButtonState Pressed or Released.
state.MiddleButton ButtonState Pressed or Released.
state.XButton1 ButtonState First extra side button.
state.XButton2 ButtonState Second extra side button.
Mouse::SetPosition(int x, int y) void Warps the cursor to the given window coordinates.

Example: mouse click detection

#include <Microsoft/Xna/Framework/Input/Mouse.hpp>

using namespace Microsoft::Xna::Framework::Input;

MouseState previousMouse;

// In Game::Update(GameTime gameTime)
MouseState mouse = Mouse::GetState();

// Single click: button was released this frame
if (mouse.LeftButton  == ButtonState::Released &&
    previousMouse.LeftButton == ButtonState::Pressed)
{
    // Left click at (mouse.X, mouse.Y)
    OnLeftClick(mouse.X, mouse.Y);
}

// Track scroll
int scrollDelta = mouse.ScrollWheelValue - previousMouse.ScrollWheelValue;
if (scrollDelta != 0) {
    camera.Zoom(scrollDelta * 0.1f);
}

previousMouse = mouse;

GamePad

The GamePad class supports up to four simultaneously connected controllers via the PlayerIndex enum (One through Four). GamePadState exposes analog sticks, triggers, buttons, and the D-pad. Always check IsConnected before reading state to avoid acting on a zeroed-out snapshot for an absent controller.

MemberTypeDescription
GamePad::GetState(PlayerIndex) GamePadState Returns the state for the specified player slot.
state.IsConnected bool Whether a controller is plugged in for this slot.
state.ThumbSticks.Left Vector2 Left stick, X and Y in −1..1.
state.ThumbSticks.Right Vector2 Right stick, X and Y in −1..1.
state.Triggers.Left float Left trigger, 0..1.
state.Triggers.Right float Right trigger, 0..1.
state.Buttons GamePadButtons A, B, X, Y, Start, Back, LeftShoulder, RightShoulder, LeftStick, RightStick — each is ButtonState::Pressed or Released.
state.DPad GamePadDPad Up, Down, Left, Right — each is ButtonState::Pressed or Released.
GamePad::SetVibration(PlayerIndex, float left, float right) bool Sets rumble motor strength, 0.0–1.0 per motor. Returns false if the controller does not support vibration.

Dead zone handling

Analog sticks rarely rest at exactly (0, 0) due to hardware tolerances. CNA applies a dead zone before returning stick values. The dead zone mode is passed as an optional second argument to GetState():

ModeBehaviour
GamePadDeadZone::IndependentAxes Default. X and Y are clamped and rescaled independently.
GamePadDeadZone::Circular The dead zone is a circle; values inside it are zeroed, the remainder is rescaled radially.
GamePadDeadZone::None Raw values; no dead zone applied. Use when you implement your own dead zone logic.

Example: analog stick movement

#include <Microsoft/Xna/Framework/Input/GamePad.hpp>

using namespace Microsoft::Xna::Framework::Input;

GamePadState previousPad;

// In Game::Update(GameTime gameTime)
GamePadState pad = GamePad::GetState(PlayerIndex::One);

if (pad.IsConnected) {
    float speed = 200.0f * (float)gameTime.ElapsedGameTime.TotalSeconds();

    // Left stick movement
    Vector2 move = pad.ThumbSticks.Left;
    move.Y = -move.Y;  // XNA Y axis: up is positive on stick, down on screen
    playerPosition += move * speed;

    // Right trigger as an accelerator
    speed *= 1.0f + pad.Triggers.Right;

    // A button just pressed
    if (pad.Buttons.A  == ButtonState::Pressed &&
        previousPad.Buttons.A == ButtonState::Released)
    {
        Jump();
    }

    // Vibrate on damage
    if (playerHit) {
        GamePad::SetVibration(PlayerIndex::One, 0.8f, 0.4f);
    }
}

previousPad = pad;

TouchPanel

The TouchPanel class exposes multi-touch and gesture recognition. The SDL3 touch backend and gesture pipeline (Tap through PinchComplete) are a byte-faithful FNA port, fully wired end-to-end and tested with a deterministic clock (~98% behavior). Documented deviations only: GetState() is event-driven rather than poll-based, MaximumTouchCount reports 4, and GetState() caps at 8 touches — all intentionally matching FNA.

MemberTypeDescription
TouchPanel::GetState() TouchCollection Returns all active touch points this frame.
location.Id int Unique identifier for this touch contact.
location.State TouchLocationState Pressed, Moved, or Released.
location.Position Vector2 Screen-space position of this touch point.
TouchPanel::IsGestureAvailable bool Returns true when at least one gesture is queued.
TouchPanel::ReadGesture() GestureSample Dequeues and returns the next gesture sample.

Supported GestureType values: Tap, DoubleTap, Hold, FreeDrag, Flick, Pinch, PinchComplete, DragComplete.

Example: gesture reading

#include <Microsoft/Xna/Framework/Input/Touch/TouchPanel.hpp>

using namespace Microsoft::Xna::Framework::Input::Touch;

// Configure which gestures you want before your game loop
TouchPanel::EnabledGestures = GestureType::Tap | GestureType::FreeDrag | GestureType::Flick;

// In Game::Update(GameTime gameTime)
while (TouchPanel::IsGestureAvailable) {
    GestureSample gesture = TouchPanel::ReadGesture();

    switch (gesture.GestureType) {
        case GestureType::Tap:
            OnTap(gesture.Position);
            break;
        case GestureType::Flick:
            // gesture.Delta holds the flick velocity
            playerVelocity += gesture.Delta * 0.01f;
            break;
        case GestureType::FreeDrag:
            cameraOffset -= gesture.Delta;
            break;
        default:
            break;
    }
}

Physical hardware validation still pending: The TouchPanel SDL3 backend and gesture pipeline are implemented, wired end-to-end, and tested with a deterministic clock — but gesture recognition has not yet been separately confirmed on a physical touchscreen device. Feedback from real-hardware testing is welcome.

TextInputEXT

TextInputEXT is a CNA extension (not in the original XNA 4.0 API) that captures text entry events from the OS input method, including IME composition on platforms that support it. It is the correct way to implement chat boxes, in-game consoles, or any other free-text input — keyboard polling alone will not handle key repeat, modifier combinations, or international characters correctly.

MemberTypeDescription
TextInputEXT::TextInput Event Fires each time the user produces a printable character. The event provides a char32_t Unicode code point.
#include <Microsoft/Xna/Framework/Input/TextInputEXT.hpp>

using namespace Microsoft::Xna::Framework::Input;

// In Game::Initialize() or wherever you set up input
TextInputEXT::TextInput += [this](char32_t c) {
    if (c == U'\b') {          // backspace
        if (!inputBuffer.empty()) inputBuffer.pop_back();
    } else if (c >= U' ') {   // printable
        inputBuffer += c;
    }
};

// To stop receiving events (e.g. when the text field is dismissed)
// TextInputEXT::StopTextInput();

Call TextInputEXT::StartTextInput() to activate text-entry mode (which may show a soft keyboard on mobile) and StopTextInput() when done. On desktop platforms these calls have no visible effect but are still good practice for cross-platform portability.

Accelerometer (Sensors)

The Accelerometer class provides access to the device accelerometer on platforms that expose one (primarily Android and iOS). The API is declared and compiles on all platforms; the Android backend integration needs runtime validation before it can be considered production-ready.

MemberTypeDescription
Accelerometer::GetState() AccelerometerState Returns the current accelerometer reading.
state.Acceleration Vector3 Acceleration in G-force units along X, Y, Z device axes.
state.IsActive bool true if the sensor is available and returning data.

Android runtime validation needed: The Accelerometer API compiles on all target platforms. The Android backend needs validation on a physical device before this class should be relied upon in shipping code.

Implementation status

Class Namespace Status Notes
Keyboard Input Done Full Keys enum; SDL3 scancode mapping complete.
Mouse Input Done All five buttons, scroll wheel, SetPosition.
GamePad Input Done Up to four players; vibration; all three dead zone modes.
TouchPanel Input.Touch Partial API declared; SDL3 backend wired; hardware validation pending.
TextInputEXT Input Done Unicode char32_t events; IME-safe on desktop.
Accelerometer Input Partial API declared; compiles everywhere; Android runtime validation needed.