forked from youtube/cobalt_sandbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathui_navigation.h
318 lines (282 loc) · 14.7 KB
/
ui_navigation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Module Overview: User Interface Navigation module
//
// API to allow applications to take advantage of the platform's native UI
// engine. This is mainly to drive the animation of visual elements and to
// signal which of those elements have focus. The implementation should not
// render any visual elements; instead, it will be used to guide the app in
// where these elements should be drawn.
//
// When the application creates the user interface, it will create SbUiNavItems
// for interactable elements. Additionally, the app must specify the position
// and size of these navigation items. As the app's user interface changes, it
// will create and destroy navigation items as appropriate.
//
// For each render frame, the app will query the local transform for each
// SbUiNavItem in case the native UI engine moves individual items in response
// to user interaction. If the navigation item is a container, then the content
// offset will also be queried to determine the placement of its content items.
#ifndef STARBOARD_UI_NAVIGATION_H_
#define STARBOARD_UI_NAVIGATION_H_
#include "starboard/configuration.h"
#include "starboard/export.h"
#include "starboard/types.h"
#include "starboard/window.h"
#ifdef __cplusplus
extern "C" {
#endif
// --- Types -----------------------------------------------------------------
// An opaque handle to an implementation-private structure representing a
// navigation item.
typedef struct SbUiNavItemPrivate* SbUiNavItem;
// Navigation items may be one of the following types. This must be specified
// upon item creation and may not change during the item's lifespan.
typedef enum SbUiNavItemType {
// This is a single focusable item.
kSbUiNavItemTypeFocus,
// This is a container of navigation items which can also be containers
// themselves or focusable items. Containers themselves cannot be focused.
kSbUiNavItemTypeContainer,
} SbUiNavItemType;
// Navigation items of type kSbUiNavItemTypeContainer have directionality. If
// directionality is not specified for a container, it should default to
// left-to-right and top-to-bottom.
// @verbatim
// For left-to-right, content offset x = 0 shows the leftmost content.
// |<--Container Size-->|
// +--------------------+--------------------+--------------------+
// | Not selectable. | Selectable. | Selectable. |
// | Offscreen. | Onscreen. | Offscreen. |
// | Negative position. | Positive position. | Positive position. |
// +--------------------+--------------------+--------------------+
// ^
// Content Offset X = 0.
//
// For right-to-left, content offset x = 0 shows the rightmost content.
// |<--Container Size-->|
// +--------------------+--------------------+--------------------+
// | Selectable. | Selectable. | Not selectable. |
// | Offscreen. | Onscreen. | Offscreen. |
// | Negative position. | Positive position. | Positive position. |
// +--------------------+--------------------+--------------------+
// ^
// Content Offset X = 0. @endverbatim
//
// Top-to-bottom is similar to left-to-right, but for the Y position.
// Bottom-to-top is similar to right-to-left, but for the Y position.
typedef struct SbUiNavItemDir {
bool is_left_to_right;
bool is_top_to_bottom;
} SbUiNavItemDir;
// This represents a 2x3 transform matrix in row-major order.
// @verbatim
// | a b tx |
// | c d ty | @endverbatim
typedef struct SbUiNavMatrix2x3 { float m[6]; } SbUiNavMatrix2x3;
// This represents a 4x4 transform matrix in row-major order.
typedef struct SbUiNavMatrix4 { float m[16]; } SbUiNavMatrix4;
// This structure specifies all the callbacks which the platform UI engine
// should invoke for various interaction events on navigation items. These
// callbacks may be invoked from any thread at any frequency. The
// |callback_context| is the value that was passed on creation of the
// relevant SbUiNavItem.
typedef struct SbUiNavCallbacks {
// Invoke when an item has lost focus. This is only used with focus items.
void (*onblur)(SbUiNavItem item, void* callback_context);
// Invoke when an item has gained focus. This is only used with focus items.
void (*onfocus)(SbUiNavItem item, void* callback_context);
// Invoke when an item's content offset is changed. This is only used with
// container items.
void (*onscroll)(SbUiNavItem item, void* callback_context);
} SbUiNavCallbacks;
// This structure declares the interface to the UI navigation implementation.
// All function pointers must be specified if the platform supports UI
// navigation.
typedef struct SbUiNavInterface {
// Create a new navigation item. When the user interacts with this item
// the appropriate SbUiNavCallbacks function will be invoked with the
// provided |callback_context|. An item is not interactable until it is
// enabled.
SbUiNavItem (*create_item)(SbUiNavItemType type,
const SbUiNavCallbacks* callbacks,
void* callback_context);
// Destroy the given navigation item. If this is a content of another item,
// then it will first be unregistered. Additionally, if this item contains
// other items, then those will be unregistered as well, but they will not
// be automatically destroyed.
void (*destroy_item)(SbUiNavItem item);
// This is used to manually force focus on a navigation item of type
// kSbUiNavItemTypeFocus. Any previously focused navigation item should
// receive the blur event. If the item is not transitively a content of the
// root item, then this does nothing.
#if SB_API_VERSION >= 13
//
// Specifying kSbUiNavItemInvalid should remove focus from the UI navigation
// system.
#endif
void (*set_focus)(SbUiNavItem item);
// This is used to enable or disable user interaction with the specified
// navigation item. All navigation items are disabled when created, and
// they must be explicitly enabled to allow user interaction. If a container
// is disabled, then all of its contents are not interactable even though
// they remain enabled. If |enabled| is false, it must be guaranteed that
// once this function returns, no callbacks associated with this item will
// be invoked until the item is re-enabled.
void (*set_item_enabled)(SbUiNavItem item, bool enabled);
// This specifies directionality for container items. Containers within
// containers do not inherit directionality. Directionality must be specified
// for each container explicitly.
#if SB_API_VERSION >= 13
//
// This should work even if |item| is disabled.
#endif
void (*set_item_dir)(SbUiNavItem item, SbUiNavItemDir dir);
#if SB_API_VERSION >= 13
// Set the minimum amount of time the focus item should remain focused once
// it becomes focused. This may be used to make important focus items harder
// to navigate over. Focus may still be moved before |seconds| has elapsed by
// using the set_focus() function.
// By default, item focus duration is 0 seconds.
void (*set_item_focus_duration)(SbUiNavItem item, float seconds);
#endif
// Set the interactable size of the specified navigation item. By default,
// an item's size is (0,0).
void (*set_item_size)(SbUiNavItem item, float width, float height);
// Set the transform for the navigation item and its contents if the item is
// a container. This specifies the placement of the item's center within its
// container. The transform origin is the center of the item. Distance is
// measured in pixels with the origin being the top-left of the item's
// container. By default, an item's transform is identity.
void (*set_item_transform)(SbUiNavItem item,
const SbUiNavMatrix2x3* transform);
// Retrieve the focus transform matrix for the navigation item. The UI
// engine may translate, rotate, and/or tilt focus items to reflect user
// interaction. This transform should be multiplied with the item's transform
// to get its position inside its container. The transform origin is the
// center of the item. Return false if the item position should not be
// changed (i.e. the transform should be treated as identity).
bool (*get_item_focus_transform)(SbUiNavItem item,
SbUiNavMatrix4* out_transform);
// Retrieve a vector representing the focus location within a focused item.
// This is used to provide feedback about user input that is too small to
// result in a focus change. If there is no focus vector for the navigation
// item, then return false and leave |out_x| and |out_y| unchanged. Otherwise,
// return true and set the output values in the range of [-1, +1] with
// (out_x, out_y) of (-1, -1) being the top-left corner of the navigation
// item and (0, 0) being the center.
bool (*get_item_focus_vector)(SbUiNavItem item, float* out_x, float* out_y);
// This attaches the given navigation item (which must be a container) to
// the specified window. Navigation items are only interactable if they are
// transitively attached to a window.
//
#if SB_API_VERSION >= 13
// The native UI engine should never change this navigation item's content
// offset. It is assumed to be used as a proxy for the system window.
//
#endif
// A navigation item may only have a SbUiNavItem or SbWindow as its direct
// container. The navigation item hierarchy is established using
// set_item_container_item() with the root container attached to a SbWindow
// using set_item_container_window() to enable interaction with all enabled
// items in the hierarchy.
//
// If |item| is already registered with a different window, then this will
// unregister it from that window then attach it to the given |window|. It
// is an error to register more than one navigation item with any given
// window. If |window| is kSbWindowInvalid, then this will unregister the
// |item| from its current window if any. Upon destruction of |item| or
// |window|, the |item| is automatically unregistered from the |window|.
void (*set_item_container_window)(SbUiNavItem item, SbWindow window);
// A container navigation item may contain other navigation items. However,
// it is an error to have circular containment or for |container| to not
// be of type kSbUiNavItemTypeContainer. If |item| already has a different
// container, then this first serves that connection. If |container| is
// kSbUiNavItemInvalid, then this removes |item| from its current container.
// Upon destruction of |item| or |container|, the |item| is automatically
// removed from the |container|.
//
// The position of items within a container are specified relative to the
// container's position. The position of these content items are further
// modified by the container's "content offset".
//
// For example, consider item A with position (5,5) and content offset (0,0).
// Given item B with position (10,10) is registered as a content of item A.
//
// 1) Item B should be drawn at position (15,15).
//
// 2) If item A's content offset is changed to (10,0), then item B should be
// drawn at position (5,15).
//
// Essentially, content items should be drawn at:
// [container position] + [content position] - [container content offset]
#if SB_API_VERSION >= 13
//
// Content items may overlap within a container. This can cause obscured items
// to be unfocusable. The only rule that needs to be followed is that contents
// which are focus items can obscure other contents which are containers, but
// not vice versa. The caller must ensure that content focus items do not
// overlap other content focus items and content container items do not
// overlap other content container items.
#endif
void (*set_item_container_item)(SbUiNavItem item, SbUiNavItem container);
// Set the current content offset for the given container. This may be used
// to force scrolling to make certain content items visible. A container
// item's content offset helps determine where its content items should be
// drawn. Essentially, a content item should be drawn at:
// [container position] + [content position] - [container content offset]
// If |item| is not a container, then this does nothing.
// By default, the content offset is (0,0).
#if SB_API_VERSION >= 13
//
// This should update the values returned by get_item_content_offset() even
// if the |item| is disabled.
#endif
void (*set_item_content_offset)(SbUiNavItem item,
float content_offset_x,
float content_offset_y);
// Retrieve the current content offset for the navigation item. If |item| is
// not a container, then the content offset is (0,0).
#if SB_API_VERSION >= 13
//
// The native UI engine should not change the content offset of a container
// unless one of its contents (possibly recursively) is focused. This is to
// allow seamlessly disabling then re-enabling focus items without having
// their containers change offsets.
#endif
void (*get_item_content_offset)(SbUiNavItem item,
float* out_content_offset_x,
float* out_content_offset_y);
#if SB_API_VERSION >= 13
// Call |update_function| with |context| to perform a series of UI navigation
// changes atomically before returning.
void (*do_batch_update)(void (*update_function)(void*), void* context);
#endif
} SbUiNavInterface;
// --- Constants -------------------------------------------------------------
// Well-defined value for an invalid navigation item.
#define kSbUiNavItemInvalid ((SbUiNavItem)NULL)
// --- Functions -------------------------------------------------------------
// Returns whether the given navigation item handle is valid.
static SB_C_INLINE bool SbUiNavItemIsValid(SbUiNavItem item) {
return item != kSbUiNavItemInvalid;
}
// Retrieve the platform's UI navigation implementation. If the platform does
// not provide one, then return false without modifying |out_interface|.
// Otherwise, initialize all members of |out_interface| and return true.
SB_EXPORT bool SbUiNavGetInterface(SbUiNavInterface* out_interface);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // STARBOARD_UI_NAVIGATION_H_