#pragma once #include #include // iOS shift semantics: // - tap: shift the next character only // - double-tap: caps lock; tap again to unlock // - hold while typing: every character shifted, off on release // Times are in milliseconds and passed in, so this stays deterministic. class ShiftState { public: enum class Mode { Off, Once, Locked }; static constexpr qint64 DoubleTapMs = 300; Mode mode() const { return m_mode; } bool isUppercase() const { return m_mode != Mode::Off; } void press(qint64 timeMs); void release(); void characterTyped(); // Auto-capitalization hint; ignored while shift is held or locked. void setAutomatic(bool capitalize); private: Mode m_mode = Mode::Off; bool m_held = false; bool m_typedWhileHeld = false; qint64 m_lastPress = std::numeric_limits::min() / 2; };