Skip to content

Commit

Permalink
Merge pull request #524 from mikke89/keyboard_navigation
Browse files Browse the repository at this point in the history
Keyboard / spatial navigation
  • Loading branch information
mikke89 committed Nov 19, 2023
2 parents e1184fa + 4cacf38 commit f6d2e78
Show file tree
Hide file tree
Showing 37 changed files with 713 additions and 96 deletions.
2 changes: 1 addition & 1 deletion Include/RmlUi/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ class RMLUICORE_API Context : public ScriptInterface {
// Internal callback for when an element is detached or removed from the hierarchy.
void OnElementDetach(Element* element);
// Internal callback for when a new element gains focus.
bool OnFocusChange(Element* element);
bool OnFocusChange(Element* element, bool focus_visible);

// Generates an event for faking clicks on an element.
void GenerateClickEvent(Element* element);
Expand Down
3 changes: 2 additions & 1 deletion Include/RmlUi/Core/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,9 @@ class RMLUICORE_API Element : public ScriptInterface, public EnableObserverPtr<E
//@{

/// Gives focus to the current element.
/// @param[in] focus_visible True to indicate that the focus should be visually indicated by setting the ':focus-visible' pseudo class.
/// @return True if the change focus request was successful
bool Focus();
bool Focus(bool focus_visible = false);
/// Removes focus from from this element.
void Blur();
/// Fakes a mouse click on this element.
Expand Down
3 changes: 3 additions & 0 deletions Include/RmlUi/Core/ElementDocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class DocumentHeader;
class ElementText;
class StyleSheet;
class StyleSheetContainer;
enum class NavigationSearchDirection;

/**
ModalFlag used for controlling the modal state of the document.
Expand Down Expand Up @@ -153,6 +154,8 @@ class RMLUICORE_API ElementDocument : public Element {
Element* FindNextTabElement(Element* current_element, bool forward);
/// Searches forwards or backwards for a focusable element in the given substree
Element* SearchFocusSubtree(Element* element, bool forward);
/// Find the next element to navigate to, starting at the current element.
Element* FindNextNavigationElement(Element* current_element, NavigationSearchDirection direction, const Property& property);

/// Sets the dirty flag on the layout so the document will format its children before the next render.
void DirtyLayout() override;
Expand Down
6 changes: 6 additions & 0 deletions Include/RmlUi/Core/ID.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ enum class ShorthandId : uint8_t {
TransformOrigin,
Flex,
FlexFlow,
Nav,

NumDefinedIds,
FirstCustomId = NumDefinedIds,
Expand Down Expand Up @@ -169,6 +170,11 @@ enum class PropertyId : uint8_t {
FlexWrap,
JustifyContent,

NavUp,
NavRight,
NavDown,
NavLeft,

NumDefinedIds,
FirstCustomId = NumDefinedIds,

Expand Down
2 changes: 2 additions & 0 deletions Include/RmlUi/Core/StyleTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ namespace Style {
enum class FlexWrap : uint8_t { Nowrap, Wrap, WrapReverse };
enum class JustifyContent : uint8_t { FlexStart, FlexEnd, Center, SpaceBetween, SpaceAround };

enum class Nav : uint8_t { None, Auto, Horizontal, Vertical };

class ComputedValues;

} // namespace Style
Expand Down
51 changes: 38 additions & 13 deletions Samples/assets/invader.rcss
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@

text-l: 162px 192px 14px 31px;
text-c: 176px 192px 1px 31px;
text-focus-l: 162px 230px 14px 31px;
text-focus-c: 176px 230px 1px 31px;
textarea: 162px 193px 145px 31px;
textarea-inner: 173px 206px 127px 10px;
textarea-focus: 162px 231px 145px 31px;
textarea-focus-inner: 173px 244px 127px 10px;

selectbox-tl: 281px 275px 11px 9px;
selectbox-t: 292px 275px 1px 9px;
Expand Down Expand Up @@ -113,8 +117,11 @@
sliderarrowinc-hover: 28px 177px 27px 24px;
sliderarrowinc-active: 28px 202px 27px 24px;

range-track: 219px 194px 3px 32px;
range-track-inner: 220px 204px 1px 14px;
range-track: 219px 194px 3px 32px;
range-track-inner: 220px 204px 1px 14px;
range-track-focus: 219px 232px 3px 32px;
range-track-focus-inner: 220px 242px 1px 14px;

range-bar: 127px 191px 34px 32px;
range-dec: 3px 232px 17px 17px;
range-dec-hover: 21px 232px 17px 17px;
Expand All @@ -140,6 +147,7 @@ body
font-style: normal;
font-size: 15dp;
color: white;
nav: auto;
}

body.window
Expand Down Expand Up @@ -252,7 +260,9 @@ input.submit
margin-left: 0;
}


input, button, select {
nav: auto;
}

button,
input.submit
Expand All @@ -276,8 +286,8 @@ input.submit:focus
font-effect: blur(3dp #fff);
}

button:hover,
input.submit:hover
button:hover, button:focus-visible,
input.submit:hover, input.submit:focus-visible
{
decorator: image(button-hover);
}
Expand All @@ -304,6 +314,10 @@ input.text, input.password
cursor: text;
text-align: left;
}
input.text:focus-visible, input.password:focus-visible
{
decorator: tiled-horizontal( text-focus-l, text-focus-c, auto );
}

textarea
{
Expand All @@ -312,6 +326,10 @@ textarea
cursor: text;
text-align: left;
}
textarea:focus-visible
{
decorator: ninepatch( textarea-focus, textarea-focus-inner, 1.0 );
}

input.text,
input.password,
Expand All @@ -336,12 +354,13 @@ table input.text
background-color: white;

font-size: 15dp;

}
table input.text, table input.text:focus-visible
{
decorator: none;
}



select
{
width: 175dp;
Expand All @@ -356,7 +375,10 @@ select selectvalue
height: 25dp;
padding: 12dp 10dp 0dp 10dp;

decorator: image( selectvalue );
decorator: image( selectvalue );
}
select:focus-visible selectvalue {
decorator: image( selectvalue-hover );
}

select selectarrow
Expand All @@ -367,7 +389,7 @@ select selectarrow
decorator: image( selectarrow );
}

select:hover selectarrow
select:hover selectarrow, select:focus-visible selectarrow
{
decorator: image( selectarrow-hover );
}
Expand Down Expand Up @@ -434,7 +456,7 @@ input.radio
decorator: image(radio);
}

input.radio:hover
input.radio:hover, input.radio:focus-visible
{
decorator: image(radio-hover);
}
Expand All @@ -449,7 +471,7 @@ input.radio:checked
decorator: image(radio-checked);
}

input.radio:checked:hover
input.radio:checked:hover, input.radio:checked:focus-visible
{
decorator: image(radio-checked-hover);
}
Expand All @@ -464,7 +486,7 @@ input.checkbox
decorator: image(checkbox);
}

input.checkbox:hover
input.checkbox:hover, input.checkbox:focus-visible
{
decorator: image(checkbox-hover);
}
Expand All @@ -479,7 +501,7 @@ input.checkbox:checked
decorator: image(checkbox-checked);
}

input.checkbox:checked:hover
input.checkbox:checked:hover, input.checkbox:checked:focus-visible
{
decorator: image(checkbox-checked-hover);
}
Expand All @@ -500,6 +522,9 @@ input.range slidertrack {
image-color: #ecc;
decorator: ninepatch( range-track, range-track-inner, 1.0 );
}
input.range:focus-visible slidertrack {
decorator: ninepatch( range-track-focus, range-track-focus-inner, 1.0 );
}
input.range sliderbar {
margin-left: -8dp;
margin-right: -7dp;
Expand Down
16 changes: 12 additions & 4 deletions Samples/basic/demo/data/demo.rml
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,14 @@ progress {
{
height: 12dp;
}
form input, form textarea, form select
{
nav: vertical;
}
form .nav-auto, form input.checkbox, form input.radio
{
nav: auto;
}
</style>
</head>

Expand Down Expand Up @@ -836,21 +844,21 @@ progress {
</div>
<h2>Email and password</h2>
<div>
<input type="text" name="email"/>
<input type="password" name="password"/>
<input type="text" name="email" class="nav-auto"/>
<input type="password" name="password" class="nav-auto"/>
</div>
<h2>Favorite animal</h2>
<div>
<label><input type="radio" name="animal" value="dog" checked/> Dog </label>
<label><input type="radio" name="animal" value="cat"/> Cat </label>
<label><input type="radio" name="animal" value="narwhal"/> Narwhal </label>
<label><input type="radio" name="animal" value="no"/> I don't like animals </label>
<label><input type="radio" name="animal" value="no" style="nav-down: #lasagne"/> I don't like animals </label>
</div>
<h2>Favorite meals</h2>
<div>
<label><input type="checkbox" name="meals" value="pizza" checked/> Pizza </label>
<label><input type="checkbox" name="meals" value="pasta" checked/> Pasta </label>
<label><input type="checkbox" name="meals" value="lasagne" checked/> Lasagne </label>
<label><input type="checkbox" name="meals" value="lasagne" id="lasagne" checked/> Lasagne </label>
</div>
<h2>Rating</h2>
<div>
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/data/game.rml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
}
</style>
</head>
<body id="game_window">
<body id="game_window" onkeyup="onescape load pause">
<game id="game">
<div id="score_div">
<icon />
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/data/help.rml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}
</style>
</head>
<body template="window">
<body template="window" onkeydown="onescape goto main_menu">
<h1>Story</h1>
<p>
One day, without warning, they came for us; endless waves of the invaders, numbers too vast to count, fresh from the Martian foundries. Earth's orbital defences took a heavy toll, but were inevitably overrun, buying enough time only for a single rmlui ship to launch. The prototype X-42 'Defender'-class, not yet tested but piloted by the finest astronaut the Space Corps had to offer.
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/data/high_score.rml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
}
</style>
</head>
<body template="window" onload="add_score">
<body template="window" onload="add_score" onkeydown="onescape goto main_menu">
<table data-model="high_scores">
<thead>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/data/options.rml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
}
</style>
</head>
<body template="window" onload="restore">
<body template="window" onload="restore" onkeydown="onescape goto main_menu">
<form onsubmit="store; goto main_menu" onchange="enable_accept">
<div>
<p>
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/data/pause.rml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
}
</style>
</head>
<body template="window" onload="pause" onunload="unpause">
<body template="window" onload="pause" onunload="unpause" onkeyup="onescape close">
<br />
<p>Are you sure you want to end this game?</p>
<button onclick="goto high_score; close game_window" autofocus>Yes</button>
Expand Down
2 changes: 1 addition & 1 deletion Samples/invaders/data/start_game.rml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}
</style>
</head>
<body template="window">
<body template="window" onkeydown="onescape goto main_menu">
<form onsubmit="start">
<div>
<p>
Expand Down
5 changes: 0 additions & 5 deletions Samples/invaders/src/ElementGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@ void ElementGame::ProcessEvent(Rml::Event& event)
bool key_down = (event == Rml::EventId::Keydown);
Rml::Input::KeyIdentifier key_identifier = (Rml::Input::KeyIdentifier)event.GetParameter<int>("key_identifier", 0);

if (key_identifier == Rml::Input::KI_ESCAPE && !key_down)
{
EventManager::LoadWindow("pause");
}

// Process left and right keys
if (key_down)
{
Expand Down
11 changes: 8 additions & 3 deletions Samples/invaders/src/EventManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,27 @@ void EventManager::ProcessEvent(Rml::Event& event, const Rml::String& value)
Rml::StringUtilities::ExpandString(commands, value, ';');
for (size_t i = 0; i < commands.size(); ++i)
{
// Check for a generic 'load' or 'exit' command.
// Check for custom commands.
Rml::StringList values;
Rml::StringUtilities::ExpandString(values, commands[i], ' ');

if (values.empty())
return;

if (values[0] == "onescape" && values.size() > 1)
{
Rml::Input::KeyIdentifier key_identifier = (Rml::Input::KeyIdentifier)event.GetParameter<int>("key_identifier", 0);
if (key_identifier == Rml::Input::KI_ESCAPE)
values.erase(values.begin());
}

if (values[0] == "goto" && values.size() > 1)
{
// Load the window, and if successful close the old window.
if (LoadWindow(values[1]))
event.GetTargetElement()->GetOwnerDocument()->Close();
}
else if (values[0] == "load" && values.size() > 1)
{
// Load the window.
LoadWindow(values[1]);
}
else if (values[0] == "close")
Expand Down
11 changes: 1 addition & 10 deletions Samples/luainvaders/data/game.rml
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,8 @@
decorator: image( icon-lives );
}
</style>
<script>
Game = Game or {} --namespace for functions

function Game.OnKeyDown(event, document)
if event.parameters['key_identifier'] == rmlui.key_identifier.ESCAPE then
document.context:LoadDocument('luainvaders/data/pause.rml'):Show()
end
end
</script>
</head>
<body id="game_window" onkeydown="Game.OnKeyDown(event, document)" ongameover="Window.LoadMenu('high_score',document)">
<body id="game_window" ongameover="Window.LoadMenu('high_score',document)" onkeydown="if Window.EscapePressed(event) then Window.OpenDocument('pause',document) end">
<game id="game">
<div id="score_div">
<icon />
Expand Down
2 changes: 1 addition & 1 deletion Samples/luainvaders/data/help.rml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}
</style>
</head>
<body template="luawindow">
<body template="luawindow" onkeydown="if Window.EscapePressed(event) then Window.LoadMenu('main_menu',document) end">
<h1>Story</h1>
<p>
One day, without warning, they came for us; endless waves of the invaders, numbers too vast to count, fresh from the Martian foundries. Earth's orbital defences took a heavy toll, but were inevitably overrun, buying enough time only for a single rmlui ship to launch. The prototype X-42 'Defender'-class, not yet tested but piloted by the finest astronaut the Space Corps had to offer.
Expand Down
Loading

0 comments on commit f6d2e78

Please sign in to comment.