Skip to content

Commit

Permalink
refactor!: Decouple in-tree focus from host window/view focus (#278)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwcampbell authored Aug 26, 2023
1 parent 3a7e63a commit d360d20
Show file tree
Hide file tree
Showing 26 changed files with 719 additions and 522 deletions.
73 changes: 36 additions & 37 deletions bindings/c/examples/sdl/hello_world.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ void accesskit_sdl_adapter_init(struct accesskit_sdl_adapter *adapter,
adapter->adapter = accesskit_macos_subclassing_adapter_for_window(
(void *)wmInfo.info.cocoa.window, source, source_userdata, handler);
#elif defined(UNIX)
adapter->adapter = accesskit_unix_adapter_new(app_name, "SDL", "2.0", source,
source_userdata, handler);
adapter->adapter = accesskit_unix_adapter_new(
app_name, "SDL", "2.0", source, source_userdata, false, handler);
#elif defined(_WIN32)
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
Expand Down Expand Up @@ -145,6 +145,24 @@ void accesskit_sdl_adapter_update_if_active(
#endif
}

void accesskit_sdl_adapter_update_window_focus_state(
const struct accesskit_sdl_adapter *adapter, bool is_focused) {
#if defined(__APPLE__)
accesskit_macos_queued_events *events =
accesskit_macos_subclassing_adapter_update_view_focus_state(
adapter->adapter, is_focused);
if (events != NULL) {
accesskit_macos_queued_events_raise(events);
}
#elif defined(UNIX)
if (adapter->adapter != NULL) {
accesskit_unix_adapter_update_window_focus_state(adapter->adapter,
is_focused);
}
#endif
/* On Windows, the subclassing adapter takes care of this. */
}

void accesskit_sdl_adapter_update_root_window_bounds(
const struct accesskit_sdl_adapter *adapter, SDL_Window *window) {
#if defined(UNIX)
Expand All @@ -165,15 +183,13 @@ void accesskit_sdl_adapter_update_root_window_bounds(

struct window_state {
accesskit_node_id focus;
bool is_window_focused;
const char *announcement;
accesskit_node_class_set *node_classes;
SDL_mutex *mutex;
};

void window_state_init(struct window_state *state) {
state->focus = INITIAL_FOCUS;
state->is_window_focused = false;
state->announcement = NULL;
state->node_classes = accesskit_node_class_set_new();
state->mutex = SDL_CreateMutex();
Expand All @@ -192,13 +208,6 @@ void window_state_unlock(struct window_state *state) {
SDL_UnlockMutex(state->mutex);
}

void window_state_set_tree_update_focus(const struct window_state *state,
accesskit_tree_update *update) {
if (state->is_window_focused) {
accesskit_tree_update_set_focus(update, state->focus);
}
}

accesskit_node *window_state_build_root(const struct window_state *state) {
accesskit_node_builder *builder =
accesskit_node_builder_new(ACCESSKIT_ROLE_WINDOW);
Expand All @@ -218,10 +227,9 @@ accesskit_tree_update *window_state_build_initial_tree(
build_button(BUTTON_1_ID, "Button 1", state->node_classes);
accesskit_node *button_2 =
build_button(BUTTON_2_ID, "Button 2", state->node_classes);
accesskit_tree_update *result = accesskit_tree_update_with_capacity(
(state->announcement != NULL) ? 4 : 3);
accesskit_tree_update *result = accesskit_tree_update_with_capacity_and_focus(
(state->announcement != NULL) ? 4 : 3, state->focus);
accesskit_tree_update_set_tree(result, accesskit_tree_new(WINDOW_ID));
window_state_set_tree_update_focus(state, result);
accesskit_tree_update_push_node(result, WINDOW_ID, root);
accesskit_tree_update_push_node(result, BUTTON_1_ID, button_1);
accesskit_tree_update_push_node(result, BUTTON_2_ID, button_2);
Expand All @@ -238,10 +246,10 @@ accesskit_tree_update *build_tree_update_for_button_press(void *userdata) {
accesskit_node *announcement =
build_announcement(state->announcement, state->node_classes);
accesskit_node *root = window_state_build_root(state);
accesskit_tree_update *update = accesskit_tree_update_with_capacity(2);
accesskit_tree_update *update =
accesskit_tree_update_with_capacity_and_focus(2, state->focus);
accesskit_tree_update_push_node(update, ANNOUNCEMENT_ID, announcement);
accesskit_tree_update_push_node(update, WINDOW_ID, root);
accesskit_tree_update_set_focus(update, state->focus);
return update;
}

Expand All @@ -261,13 +269,15 @@ void window_state_press_button(struct window_state *state,

accesskit_tree_update *build_tree_update_for_focus_update(void *userdata) {
struct window_state *state = userdata;
accesskit_tree_update *update = accesskit_tree_update_new();
accesskit_tree_update_set_focus(update, state->focus);
accesskit_tree_update *update =
accesskit_tree_update_with_focus(state->focus);
return update;
}

void window_state_update_focus(struct window_state *state,
const struct accesskit_sdl_adapter *adapter) {
void window_state_set_focus(struct window_state *state,
const struct accesskit_sdl_adapter *adapter,
accesskit_node_id focus) {
state->focus = focus;
accesskit_sdl_adapter_update_if_active(
adapter, build_tree_update_for_focus_update, state);
}
Expand Down Expand Up @@ -345,17 +355,10 @@ int main(int argc, char *argv[]) {
event.window.windowID == window_id) {
switch (event.window.event) {
case SDL_WINDOWEVENT_FOCUS_GAINED:
window_state_lock(&state);
state.is_window_focused = true;
window_state_update_focus(&state, &adapter);
window_state_unlock(&state);
continue;
accesskit_sdl_adapter_update_window_focus_state(&adapter, true);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
window_state_lock(&state);
state.is_window_focused = false;
window_state_update_focus(&state, &adapter);
window_state_unlock(&state);
accesskit_sdl_adapter_update_window_focus_state(&adapter, false);
break;
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_MOVED:
Expand All @@ -370,12 +373,9 @@ int main(int argc, char *argv[]) {
switch (event.key.keysym.sym) {
case SDLK_TAB:
window_state_lock(&state);
if (state.focus == BUTTON_1_ID) {
state.focus = BUTTON_2_ID;
} else {
state.focus = BUTTON_1_ID;
}
window_state_update_focus(&state, &adapter);
accesskit_node_id new_focus =
(state.focus == BUTTON_1_ID) ? BUTTON_2_ID : BUTTON_1_ID;
window_state_set_focus(&state, &adapter, new_focus);
window_state_unlock(&state);
break;
case SDLK_SPACE:
Expand All @@ -391,8 +391,7 @@ int main(int argc, char *argv[]) {
if (target == BUTTON_1_ID || target == BUTTON_2_ID) {
window_state_lock(&state);
if (event.user.code == SET_FOCUS_MSG) {
state.focus = target;
window_state_update_focus(&state, &adapter);
window_state_set_focus(&state, &adapter, target);
} else if (event.user.code == DO_DEFAULT_ACTION_MSG) {
window_state_press_button(&state, &adapter, target);
}
Expand Down
56 changes: 27 additions & 29 deletions bindings/c/examples/windows/hello_world.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,6 @@ void window_state_free(struct window_state *state) {
free(state);
}

void window_state_set_tree_update_focus(struct window_state *state,
accesskit_tree_update *update) {
if (state->is_window_focused) {
accesskit_tree_update_set_focus(update, state->focus);
}
}

accesskit_node *window_state_build_root(struct window_state *state) {
accesskit_node_builder *builder =
accesskit_node_builder_new(ACCESSKIT_ROLE_WINDOW);
Expand All @@ -93,10 +86,9 @@ accesskit_tree_update *window_state_build_initial_tree(
build_button(BUTTON_1_ID, "Button 1", state->node_classes);
accesskit_node *button_2 =
build_button(BUTTON_2_ID, "Button 2", state->node_classes);
accesskit_tree_update *result = accesskit_tree_update_with_capacity(
(state->announcement != NULL) ? 4 : 3);
accesskit_tree_update *result = accesskit_tree_update_with_capacity_and_focus(
(state->announcement != NULL) ? 4 : 3, state->focus);
accesskit_tree_update_set_tree(result, accesskit_tree_new(WINDOW_ID));
window_state_set_tree_update_focus(state, result);
accesskit_tree_update_push_node(result, WINDOW_ID, root);
accesskit_tree_update_push_node(result, BUTTON_1_ID, button_1);
accesskit_tree_update_push_node(result, BUTTON_2_ID, button_2);
Expand Down Expand Up @@ -129,12 +121,24 @@ accesskit_windows_adapter *window_state_get_or_init_accesskit_adapter(
accesskit_action_handler *action_handler =
accesskit_action_handler_new(do_action, (void *)window);
state->adapter = accesskit_windows_adapter_new(
window, initial_tree, action_handler, state->uia_init_marker);
window, initial_tree, state->is_window_focused, action_handler,
state->uia_init_marker);
state->uia_init_marker = NULL;
return state->adapter;
}
}

void window_state_set_focus(struct window_state *state,
accesskit_node_id focus) {
state->focus = focus;
if (state->adapter != NULL) {
accesskit_tree_update *update = accesskit_tree_update_with_focus(focus);
accesskit_windows_queued_events *events =
accesskit_windows_adapter_update(state->adapter, update);
accesskit_windows_queued_events_raise(events);
}
}

void window_state_press_button(struct window_state *state,
accesskit_node_id id) {
const char *text;
Expand All @@ -148,10 +152,10 @@ void window_state_press_button(struct window_state *state,
accesskit_node *announcement =
build_announcement(text, state->node_classes);
accesskit_node *root = window_state_build_root(state);
accesskit_tree_update *update = accesskit_tree_update_with_capacity(2);
accesskit_tree_update *update =
accesskit_tree_update_with_capacity_and_focus(2, state->focus);
accesskit_tree_update_push_node(update, ANNOUNCEMENT_ID, announcement);
accesskit_tree_update_push_node(update, WINDOW_ID, root);
window_state_set_tree_update_focus(state, update);
accesskit_windows_queued_events *events =
accesskit_windows_adapter_update(state->adapter, update);
accesskit_windows_queued_events_raise(events);
Expand All @@ -162,14 +166,13 @@ struct window_state *get_window_state(HWND window) {
return (struct window_state *)(GetWindowLongPtr(window, GWLP_USERDATA));
}

void update_focus(HWND window, bool is_window_focused) {
void update_window_focus_state(HWND window, bool is_focused) {
struct window_state *state = get_window_state(window);
state->is_window_focused = is_window_focused;
state->is_window_focused = is_focused;
if (state->adapter != NULL) {
accesskit_tree_update *update = accesskit_tree_update_new();
window_state_set_tree_update_focus(state, update);
accesskit_windows_queued_events *events =
accesskit_windows_adapter_update(state->adapter, update);
accesskit_windows_adapter_update_window_focus_state(state->adapter,
is_focused);
accesskit_windows_queued_events_raise(events);
}
}
Expand Down Expand Up @@ -220,19 +223,16 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
}
} else if (msg == WM_SETFOCUS || msg == WM_EXITMENULOOP ||
msg == WM_EXITSIZEMOVE) {
update_focus(hwnd, true);
update_window_focus_state(hwnd, true);
} else if (msg == WM_KILLFOCUS || msg == WM_ENTERMENULOOP ||
msg == WM_ENTERSIZEMOVE) {
update_focus(hwnd, false);
update_window_focus_state(hwnd, false);
} else if (msg == WM_KEYDOWN) {
if (wParam == VK_TAB) {
struct window_state *state = get_window_state(hwnd);
if (state->focus == BUTTON_1_ID) {
state->focus = BUTTON_2_ID;
} else {
state->focus = BUTTON_1_ID;
}
update_focus(hwnd, true);
accesskit_node_id new_focus =
(state->focus == BUTTON_1_ID) ? BUTTON_2_ID : BUTTON_1_ID;
window_state_set_focus(state, new_focus);
} else if (wParam == VK_SPACE) {
struct window_state *window_state = get_window_state(hwnd);
accesskit_node_id id = window_state->focus;
Expand All @@ -244,9 +244,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
accesskit_node_id id = (accesskit_node_id)lParam;
if (id == BUTTON_1_ID || id == BUTTON_2_ID) {
struct window_state *state = get_window_state(hwnd);
state->focus = id;
bool is_window_focused = state->is_window_focused;
update_focus(hwnd, is_window_focused);
window_state_set_focus(state, id);
}
} else if (msg == DO_DEFAULT_ACTION_MSG) {
accesskit_node_id id = (accesskit_node_id)lParam;
Expand Down
24 changes: 13 additions & 11 deletions bindings/c/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,16 +907,24 @@ impl BoxCastPtr for tree_update {}

impl tree_update {
#[no_mangle]
pub extern "C" fn accesskit_tree_update_new() -> *mut tree_update {
let update = TreeUpdate::default();
pub extern "C" fn accesskit_tree_update_with_focus(focus: node_id) -> *mut tree_update {
let update = TreeUpdate {
nodes: vec![],
tree: None,
focus: focus.into(),
};
BoxCastPtr::to_mut_ptr(update)
}

#[no_mangle]
pub extern "C" fn accesskit_tree_update_with_capacity(capacity: usize) -> *mut tree_update {
pub extern "C" fn accesskit_tree_update_with_capacity_and_focus(
capacity: usize,
focus: node_id,
) -> *mut tree_update {
let update = TreeUpdate {
nodes: Vec::with_capacity(capacity),
..Default::default()
tree: None,
focus: focus.into(),
};
BoxCastPtr::to_mut_ptr(update)
}
Expand Down Expand Up @@ -954,13 +962,7 @@ impl tree_update {
#[no_mangle]
pub extern "C" fn accesskit_tree_update_set_focus(update: *mut tree_update, focus: node_id) {
let update = mut_from_ptr(update);
update.focus = Some(focus.into());
}

#[no_mangle]
pub extern "C" fn accesskit_tree_update_clear_focus(update: *mut tree_update) {
let update = mut_from_ptr(update);
update.focus = None;
update.focus = focus.into();
}
}

Expand Down
Loading

0 comments on commit d360d20

Please sign in to comment.