Flutter Engine
The Flutter Engine
Public Member Functions | List of all members
flutter_runner::FocusDelegate Class Reference

#include <focus_delegate.h>

Public Member Functions

 FocusDelegate (fuchsia::ui::views::ViewRefFocusedHandle view_ref_focused, fuchsia::ui::views::FocuserHandle focuser)
 
void WatchLoop (std::function< void(bool)> callback)
 
bool HandlePlatformMessage (rapidjson::Value request, fml::RefPtr< flutter::PlatformMessageResponse > response)
 
void OnChildViewViewRef (uint64_t view_id, fuchsia::ui::views::ViewRef view_ref)
 
void OnDisposeChildView (uint64_t view_id)
 

Detailed Description

Definition at line 18 of file focus_delegate.h.

Constructor & Destructor Documentation

◆ FocusDelegate()

flutter_runner::FocusDelegate::FocusDelegate ( fuchsia::ui::views::ViewRefFocusedHandle  view_ref_focused,
fuchsia::ui::views::FocuserHandle  focuser 
)
inline

Definition at line 20 of file focus_delegate.h.

22 : view_ref_focused_(view_ref_focused.Bind()), focuser_(focuser.Bind()) {}

Member Function Documentation

◆ HandlePlatformMessage()

bool flutter_runner::FocusDelegate::HandlePlatformMessage ( rapidjson::Value  request,
fml::RefPtr< flutter::PlatformMessageResponse response 
)

Handles the following focus-related platform message requests: View.focus.getCurrent

  • Completes with the FocusDelegate's most recent focus state, either [true] or [false]. View.focus.getNext
  • Completes with the FocusDelegate's next focus state, either [true] or [false].
  • Only one outstanding request may exist at a time. Any others will be completed with [null]. View.focus.request
  • Attempts to give focus for a given viewRef. Completes with [0] on success, or [fuchsia::ui::views::Error] on failure.

Returns false if a malformed/invalid request needs to be completed empty.

Definition at line 27 of file focus_delegate.cc.

29 {
30 auto method = request.FindMember("method");
31 if (method == request.MemberEnd() || !method->value.IsString()) {
32 return false;
33 }
34
35 if (method->value == "View.focus.getCurrent") {
36 Complete(std::move(response), is_focused_ ? "[true]" : "[false]");
37 } else if (method->value == "View.focus.getNext") {
38 if (next_focus_request_) {
39 FML_LOG(ERROR) << "An outstanding PlatformMessageResponse already exists "
40 "for the next focus state!";
41 Complete(std::move(response), "[null]");
42 } else {
43 next_focus_request_ = std::move(response);
44 }
45 } else if (method->value == "View.focus.request") {
46 auto args_it = request.FindMember("args");
47 if (args_it == request.MemberEnd() || !args_it->value.IsObject()) {
48 FML_LOG(ERROR) << "No arguments found.";
49 return false;
50 }
51 const auto& args = args_it->value;
52
53 auto view_ref = args.FindMember("viewRef");
54 if (!view_ref->value.IsUint64()) {
55 FML_LOG(ERROR) << "Argument 'viewRef' is not a uint64";
56 return false;
57 }
58
59 zx_handle_t handle = view_ref->value.GetUint64();
60 zx_handle_t out_handle;
61 zx_status_t status =
62 zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &out_handle);
63 if (status != ZX_OK) {
64 FML_LOG(ERROR) << "Argument 'viewRef' is not valid";
65 return false;
66 }
67 auto ref = fuchsia::ui::views::ViewRef({
68 .reference = zx::eventpair(out_handle),
69 });
70 return RequestFocusByViewRef(std::move(ref), std::move(response));
71
72 } else if (method->value == "View.focus.requestById") {
73 auto args_it = request.FindMember("args");
74 if (args_it == request.MemberEnd() || !args_it->value.IsObject()) {
75 FML_LOG(ERROR) << "No arguments found.";
76 return false;
77 }
78 const auto& args = args_it->value;
79
80 auto view_id = args.FindMember("viewId");
81 if (!view_id->value.IsUint64()) {
82 FML_LOG(ERROR) << "Argument 'viewId' is not a uint64";
83 return false;
84 }
85
86 auto id = view_id->value.GetUint64();
87 if (child_view_view_refs_.count(id) != 1) {
88 FML_LOG(ERROR) << "Argument 'viewId' (" << id
89 << ") does not refer to a valid ChildView";
90 Complete(std::move(response), "[1]");
91 return true;
92 }
93
94 return RequestFocusById(id, std::move(response));
95 } else {
96 return false;
97 }
98 // All of our methods complete the platform message response.
99 return true;
100}
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_LOG(severity)
Definition: logging.h:82
#define ERROR(message)
Definition: elf_loader.cc:260

◆ OnChildViewViewRef()

void flutter_runner::FocusDelegate::OnChildViewViewRef ( uint64_t  view_id,
fuchsia::ui::views::ViewRef  view_ref 
)

Definition at line 102 of file focus_delegate.cc.

103 {
104 FML_CHECK(child_view_view_refs_.count(view_id) == 0);
105 child_view_view_refs_[view_id] = std::move(view_ref);
106}
#define FML_CHECK(condition)
Definition: logging.h:85

◆ OnDisposeChildView()

void flutter_runner::FocusDelegate::OnDisposeChildView ( uint64_t  view_id)

Definition at line 108 of file focus_delegate.cc.

108 {
109 FML_CHECK(child_view_view_refs_.count(view_id) == 1);
110 child_view_view_refs_.erase(view_id);
111}

◆ WatchLoop()

void flutter_runner::FocusDelegate::WatchLoop ( std::function< void(bool)>  callback)

Continuously watches the host viewRef for focus events, invoking a callback each time.

The callback is invoked on each Watch() call, which consumes the callback argument. Hence, the callback argument must be copyable, so that a copy can be freely moved into the Watch() call.

This method can only be called once.

Definition at line 11 of file focus_delegate.cc.

11 {
12 if (watch_loop_) {
13 FML_LOG(ERROR) << "FocusDelegate::WatchLoop() must be called once.";
14 return;
15 }
16
17 watch_loop_ = [this, /*copy*/ callback](auto focus_state) {
18 callback(is_focused_ = focus_state.focused());
19 Complete(std::exchange(next_focus_request_, nullptr),
20 is_focused_ ? "[true]" : "[false]");
21 view_ref_focused_->Watch(/*copy*/ watch_loop_);
22 };
23
24 view_ref_focused_->Watch(/*copy*/ watch_loop_);
25}
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback

The documentation for this class was generated from the following files: