Input System

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

Implementation status: Input is one of CNA's broadest implemented namespaces. The Keys enum carries the XNA key vocabulary; GamePad provides rumble, trigger rumble, LED control, hot-plug handling and per-device capability probing; and TouchPanel detects all 10 XNA gesture types. Alpha.1 contains 43 input test sources with 490 statically discoverable GoogleTest-family definitions. One known contract bug is documented under TouchPanel.

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.getElapsedGameTimeProperty().getTotalSecondsProperty();

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.

Behind the XNA surface sits a substantial SDL3 bridge. It is not a thin passthrough: it handles hot-plug (controllers connected and disconnected mid-session), per-device capability probing (so GamePadCapabilities reports what the specific pad actually has rather than a fixed assumption), and the full haptics surface — standard rumble, trigger rumble on pads that support it, and LED control.

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.getElapsedGameTimeProperty().getTotalSecondsProperty();

    // 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;

Beyond XNA: GamePad EXT methods

XNA 4.0 was designed around the Xbox 360 controller, so its GamePad API has no vocabulary for anything a modern pad does. CNA adds roughly 17 CNAEXT-tagged extension methods to cover the gap: device GUID, light bar colour, trigger vibration, gyroscope and accelerometer readings, battery/power info, touchpad finger positions, and the Steam input handle. The extra buttons modern pads expose — back paddles, Misc1, and the touchpad click — are available too, alongside six Keyboard scancode methods, MouseCursor, and TextInputEXT.

These are outside the XNA surface by construction. CNA's compile-time CNAEXT purity check will flag every use, which is what you want if the goal is a codebase that could also build against real XNA.

TouchPanel

The TouchPanel class exposes multi-touch and gesture recognition. All 10 XNA gesture types are genuinely detected — not stubbed, not partially wired — by a 474-line state machine that tracks contacts over time and computes flick velocity with exponential smoothing. Documented deviations: GetState() is event-driven rather than poll-based, MaximumTouchCount reports 4, and GetState() caps at 8 touches, all intentionally matching FNA.

Known contract bug: TouchCollection reports IsReadOnly == true, but its mutator methods mutate the collection instead of throwing. Code that trusts IsReadOnly as a guarantee will be misled. Do not rely on the flag to protect a collection you hand out.

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.

All 10 GestureType values are detected: Tap, DoubleTap, Hold, HorizontalDrag, VerticalDrag, 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;
    }
}

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. It is backed by the real SDL3 sensor API on Android, iOS and desktop, with correct m/s²-to-g conversion and substantial concurrency hardening around the sensor callbacks. Its sibling Gyroscope works the same way. See Sensors for the full Microsoft::Devices::Sensors surface, including which sensors are Android-only.

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.

Implementation status

Class Namespace Status Notes
Keyboard Input Done All ~145 Keys members; SDL3 scancode mapping complete.
Mouse Input Done All five buttons, scroll wheel, SetPosition.
GamePad Input Done SDL3 bridge: rumble, trigger rumble, LED, hot-plug, per-device capability probing. All three dead zone modes.
TouchPanel Input.Touch Done All 10 XNA gesture types detected by a 474-line state machine. See the TouchCollection::IsReadOnly bug above.
TextInputEXT Input Done CNA extension (CNAEXT). Unicode char32_t events; IME-safe on desktop.
Accelerometer Devices.Sensors Done Real SDL3 sensor API on Android, iOS and desktop; correct m/s²-to-g conversion.