window.cc 10.6 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "flutter/lib/ui/window/window.h"
6

7
#include "flutter/lib/ui/compositing/scene.h"
8
#include "flutter/lib/ui/ui_dart_state.h"
A
Adam Barth 已提交
9
#include "flutter/lib/ui/window/platform_message_response_dart.h"
10 11 12 13 14 15
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/dart_microtask_queue.h"
#include "third_party/tonic/logging/dart_invoke.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"
16

17
using tonic::DartInvokeField;
18
using tonic::DartState;
19 20 21
using tonic::StdStringToDart;
using tonic::ToDart;

22 23 24
namespace blink {
namespace {

25
void DefaultRouteName(Dart_NativeArguments args) {
26 27
  std::string routeName =
      UIDartState::Current()->window()->client()->DefaultRouteName();
28 29 30
  Dart_SetReturnValue(args, StdStringToDart(routeName));
}

31
void ScheduleFrame(Dart_NativeArguments args) {
32
  UIDartState::Current()->window()->client()->ScheduleFrame();
33 34 35 36
}

void Render(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;
37 38
  Scene* scene =
      tonic::DartConverter<Scene*>::FromArguments(args, 1, exception);
39 40 41 42
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }
43
  UIDartState::Current()->window()->client()->Render(scene);
44 45
}

46 47 48 49 50 51 52 53 54 55 56
void UpdateSemantics(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;
  SemanticsUpdate* update =
      tonic::DartConverter<SemanticsUpdate*>::FromArguments(args, 1, exception);
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }
  UIDartState::Current()->window()->client()->UpdateSemantics(update);
}

57 58 59 60 61 62 63 64
void SetIsolateDebugName(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;
  const std::string name =
      tonic::DartConverter<std::string>::FromArguments(args, 1, exception);
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }
65
  UIDartState::Current()->SetDebugName(name);
66 67
}

68 69 70 71
Dart_Handle SendPlatformMessage(Dart_Handle window,
                                const std::string& name,
                                Dart_Handle callback,
                                const tonic::DartByteData& data) {
72
  UIDartState* dart_state = UIDartState::Current();
A
Adam Barth 已提交
73

74 75 76 77 78 79
  if (!dart_state->window()) {
    // Must release the TypedData buffer before allocating other Dart objects.
    data.Release();
    return ToDart("Platform messages can only be sent from the main isolate");
  }

80
  fml::RefPtr<PlatformMessageResponse> response;
A
Adam Barth 已提交
81
  if (!Dart_IsNull(callback)) {
82
    response = fml::MakeRefCounted<PlatformMessageResponseDart>(
83 84
        tonic::DartPersistentValue(dart_state, callback),
        dart_state->GetTaskRunners().GetUITaskRunner());
A
Adam Barth 已提交
85
  }
86
  if (Dart_IsNull(data.dart_handle())) {
87
    dart_state->window()->client()->HandlePlatformMessage(
88
        fml::MakeRefCounted<PlatformMessage>(name, response));
89 90 91
  } else {
    const uint8_t* buffer = static_cast<const uint8_t*>(data.data());

92
    dart_state->window()->client()->HandlePlatformMessage(
93
        fml::MakeRefCounted<PlatformMessage>(
94 95 96
            name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
            response));
  }
97 98

  return Dart_Null();
99 100 101 102 103 104
}

void _SendPlatformMessage(Dart_NativeArguments args) {
  tonic::DartCallStatic(&SendPlatformMessage, args);
}

A
Adam Barth 已提交
105 106 107
void RespondToPlatformMessage(Dart_Handle window,
                              int response_id,
                              const tonic::DartByteData& data) {
108 109 110 111
  if (Dart_IsNull(data.dart_handle())) {
    UIDartState::Current()->window()->CompletePlatformMessageEmptyResponse(
        response_id);
  } else {
112
    // TODO(engine): Avoid this copy.
113 114 115 116 117
    const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
    UIDartState::Current()->window()->CompletePlatformMessageResponse(
        response_id,
        std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
  }
A
Adam Barth 已提交
118 119 120 121 122 123
}

void _RespondToPlatformMessage(Dart_NativeArguments args) {
  tonic::DartCallStatic(&RespondToPlatformMessage, args);
}

124 125
}  // namespace

126
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
127 128
  Dart_Handle data_handle =
      Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
129 130 131 132 133 134
  if (Dart_IsError(data_handle))
    return data_handle;

  Dart_TypedData_Type type;
  void* data = nullptr;
  intptr_t num_bytes = 0;
135
  FML_CHECK(!Dart_IsError(
136 137 138 139 140 141 142
      Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));

  memcpy(data, buffer.data(), num_bytes);
  Dart_TypedDataReleaseData(data_handle);
  return data_handle;
}

A
Adam Barth 已提交
143
WindowClient::~WindowClient() {}
144

A
Adam Barth 已提交
145
Window::Window(WindowClient* client) : client_(client) {}
146

A
Adam Barth 已提交
147
Window::~Window() {}
148 149 150 151 152

void Window::DidCreateIsolate() {
  library_.Set(DartState::Current(), Dart_LookupLibrary(ToDart("dart:ui")));
}

153
void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
154 155
  viewport_metrics_ = metrics;

156
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
157 158
  if (!dart_state)
    return;
159
  tonic::DartState::Scope scope(dart_state);
160 161 162 163 164 165 166 167 168 169 170 171 172 173
  DartInvokeField(library_.value(), "_updateWindowMetrics",
                  {
                      ToDart(metrics.device_pixel_ratio),
                      ToDart(metrics.physical_width),
                      ToDart(metrics.physical_height),
                      ToDart(metrics.physical_padding_top),
                      ToDart(metrics.physical_padding_right),
                      ToDart(metrics.physical_padding_bottom),
                      ToDart(metrics.physical_padding_left),
                      ToDart(metrics.physical_view_inset_top),
                      ToDart(metrics.physical_view_inset_right),
                      ToDart(metrics.physical_view_inset_bottom),
                      ToDart(metrics.physical_view_inset_left),
                  });
174 175
}

176
void Window::UpdateLocales(const std::vector<std::string>& locales) {
177
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
178 179
  if (!dart_state)
    return;
180
  tonic::DartState::Scope scope(dart_state);
181
  DartInvokeField(library_.value(), "_updateLocales",
182
                  {
183
                      tonic::ToDart<std::vector<std::string>>(locales),
184
                  });
185 186
}

187
void Window::UpdateUserSettingsData(const std::string& data) {
188
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
189 190 191 192
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

193
  DartInvokeField(library_.value(), "_updateUserSettingsData",
194
                  {
195
                      StdStringToDart(data),
196 197 198
                  });
}

199
void Window::UpdateSemanticsEnabled(bool enabled) {
200
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
201 202 203 204 205 206 207 208
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

  DartInvokeField(library_.value(), "_updateSemanticsEnabled",
                  {ToDart(enabled)});
}

209
void Window::UpdateAccessibilityFeatures(int32_t values) {
210
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
211 212 213 214
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

215 216
  DartInvokeField(library_.value(), "_updateAccessibilityFeatures",
                  {ToDart(values)});
217 218
}

219
void Window::DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) {
220
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
221 222 223
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);
224 225
  Dart_Handle data_handle =
      (message->hasData()) ? ToByteData(message->data()) : Dart_Null();
226 227 228
  if (Dart_IsError(data_handle))
    return;

A
Adam Barth 已提交
229 230 231 232 233
  int response_id = 0;
  if (auto response = message->response()) {
    response_id = next_response_id_++;
    pending_responses_[response_id] = response;
  }
234

235 236 237
  DartInvokeField(
      library_.value(), "_dispatchPlatformMessage",
      {ToDart(message->channel()), data_handle, ToDart(response_id)});
A
Adam Barth 已提交
238
}
239

A
Adam Barth 已提交
240
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
241
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
A
Adam Barth 已提交
242 243 244 245 246 247 248
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

  Dart_Handle data_handle = ToByteData(packet.data());
  if (Dart_IsError(data_handle))
    return;
249 250 251 252
  DartInvokeField(library_.value(), "_dispatchPointerDataPacket",
                  {data_handle});
}

253 254 255
void Window::DispatchSemanticsAction(int32_t id,
                                     SemanticsAction action,
                                     std::vector<uint8_t> args) {
256
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
257 258 259 260
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

261 262 263 264 265 266 267 268
  Dart_Handle args_handle = (args.empty()) ? Dart_Null() : ToByteData(args);

  if (Dart_IsError(args_handle))
    return;

  DartInvokeField(
      library_.value(), "_dispatchSemanticsAction",
      {ToDart(id), ToDart(static_cast<int32_t>(action)), args_handle});
269 270
}

271
void Window::BeginFrame(fml::TimePoint frameTime) {
272
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
273 274
  if (!dart_state)
    return;
275
  tonic::DartState::Scope scope(dart_state);
276

277
  int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
278

A
Adam Barth 已提交
279 280 281 282
  DartInvokeField(library_.value(), "_beginFrame",
                  {
                      Dart_NewInteger(microseconds),
                  });
283

284
  UIDartState::Current()->FlushMicrotasksNow();
285 286

  DartInvokeField(library_.value(), "_drawFrame", {});
287 288
}

289 290 291 292 293 294 295 296 297 298 299
void Window::CompletePlatformMessageEmptyResponse(int response_id) {
  if (!response_id)
    return;
  auto it = pending_responses_.find(response_id);
  if (it == pending_responses_.end())
    return;
  auto response = std::move(it->second);
  pending_responses_.erase(it);
  response->CompleteEmpty();
}

A
Adam Barth 已提交
300
void Window::CompletePlatformMessageResponse(int response_id,
301
                                             std::vector<uint8_t> data) {
A
Adam Barth 已提交
302 303 304 305 306 307 308
  if (!response_id)
    return;
  auto it = pending_responses_.find(response_id);
  if (it == pending_responses_.end())
    return;
  auto response = std::move(it->second);
  pending_responses_.erase(it);
309
  response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
A
Adam Barth 已提交
310 311
}

312
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
313
  natives->Register({
314
      {"Window_defaultRouteName", DefaultRouteName, 1, true},
315 316
      {"Window_scheduleFrame", ScheduleFrame, 1, true},
      {"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
A
Adam Barth 已提交
317
      {"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
318 319
      {"Window_render", Render, 2, true},
      {"Window_updateSemantics", UpdateSemantics, 2, true},
320
      {"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
321
  });
322 323 324
}

}  // namespace blink