Files
ppsspp/Common/UI/Screen.h
T
Henrik RydgårdandClaude Opus 5.5 c51bcd458c Input: Let the key mapping dialog see volume keys, mapped or not
The volume key filter in NativeKey left unmapped volume keys to the OS, so
they never reached the dialog and couldn't be mapped. A new InputMode::AllKeys
lets a screen ask for them; the dialog consumes them so the volume doesn't
change while mapping.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 00:01:34 +02:00

158 lines
4.3 KiB
C++

// Super basic screen manager. Let's you, well, switch between screens. Can also be used
// to pop one screen in front for a bit while keeping another one running, it's basically
// a native "activity stack". Well actually that part is still a TODO.
//
// Semantics
//
// switchScreen: When you call this, on a newed screen, the ScreenManager takes ownership.
// On the next update, it switches to the new screen and deletes the previous screen.
//
// TODO: A way to do smooth transitions between screens. Will probably involve screenshotting
// the previous screen and then animating it on top of the current screen with transparency
// and/or other similar effects.
#pragma once
#include <cstdint>
#include <string>
#include "Common/Common.h"
#include "Common/Input/InputState.h"
#include "Common/System/System.h"
namespace UI {
class View;
}
namespace Draw {
class DrawContext;
}
enum DialogResult {
DR_NONE,
DR_OK,
DR_CANCEL,
DR_YES,
DR_NO,
DR_BACK,
};
const char *DialogResultToString(DialogResult result);
class ScreenManager;
class UIContext;
enum class ScreenFocusChange {
FOCUS_LOST_TOP, // Another screen was pushed on top
FOCUS_BECAME_TOP, // Became the top screen again
};
enum class ScreenRenderMode {
DEFAULT = 0,
FIRST = 1,
BEHIND = 4,
TOP = 8,
};
ENUM_CLASS_BITOPS(ScreenRenderMode);
enum class ScreenRenderRole {
NONE = 0,
CAN_BE_BACKGROUND = 1,
MUST_BE_FIRST = 2,
};
ENUM_CLASS_BITOPS(ScreenRenderRole);
enum class ViewLayoutMode {
ApplyInsets = 0, // For gameplay, option #1
IgnoreInsets, // For gameplay, option #2
IgnoreBottomInset,
};
enum class QueuedEventType : u8 {
KEY,
AXIS,
TOUCH,
};
struct QueuedEvent {
QueuedEventType type;
union {
TouchInput touch;
KeyInput key;
AxisInput axis;
};
};
enum class ScreenRenderFlags {
NONE = 0,
HANDLED_THROTTLING = 1,
};
ENUM_CLASS_BITOPS(ScreenRenderFlags);
enum class InputMode {
None = 0,
Keyboard = 1,
Mouse = 2,
Other = 4,
ImDebuggerToggle = 8, // ugly hack. debugger and pause goes through.
AllKeys = 16, // The screen gets keys that are normally left to the OS, like volume. For key mapping.
};
ENUM_CLASS_BITOPS(InputMode);
class Screen {
public:
Screen() = default;
virtual ~Screen();
virtual void onFinish(DialogResult reason) {}
virtual void update() {}
virtual ScreenRenderFlags PreRender(ScreenRenderMode mode) { return ScreenRenderFlags::NONE; }
virtual ScreenRenderFlags render(ScreenRenderMode mode) = 0;
virtual void resized() {}
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
virtual void sendMessage(UIMessage message, const char *value) {}
virtual void deviceLost() {}
virtual void deviceRestored(Draw::DrawContext *draw) {}
virtual ScreenRenderRole renderRole(bool isTop) const { return ScreenRenderRole::NONE; }
virtual bool wantBrightBackground() const { return false; } // special hack for DisplayLayoutScreen.
virtual void focusChanged(ScreenFocusChange focusChange);
virtual bool touch(const TouchInput &touch) = 0;
virtual bool key(const KeyInput &key) = 0;
virtual void axis(const AxisInput &axis) = 0;
virtual void RecreateViews() {}
// NOTE: This is polled every frame, not called on every input event.
virtual InputMode PassInputToMapper() const { return InputMode::None; }
ScreenManager *screenManager() { return screenManager_; }
const ScreenManager *screenManager() const { return screenManager_; }
void setScreenManager(ScreenManager *sm) { screenManager_ = sm; }
virtual const char *tag() const = 0;
virtual bool isTransparent() const { return false; }
virtual bool isTopLevel() const { return false; }
virtual TouchInput transformTouch(const TouchInput &touch) { return touch; }
virtual bool WantsTextInput() const { return false; }
protected:
// Requests made while creating views (by the views themselves, or with callbacks that capture them) get a separate
// token, so they can be forgotten when the views are deleted, while the screen's own requests stay alive.
int GetRequesterToken();
void SetCreatingViews(bool creating) { creatingViews_ = creating; }
bool IsCreatingViews() const { return creatingViews_; }
// Drops the callbacks of pending requests made by the views, which are about to be deleted.
void ForgetViewRequests();
private:
ScreenManager *screenManager_ = nullptr;
int token_ = -1;
int viewsToken_ = -1;
bool creatingViews_ = false;
DISALLOW_COPY_AND_ASSIGN(Screen);
};