window.cc 12.1 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
namespace flutter {
18 19
namespace {

20
void DefaultRouteName(Dart_NativeArguments args) {
21 22
  std::string routeName =
      UIDartState::Current()->window()->client()->DefaultRouteName();
23
  Dart_SetReturnValue(args, tonic::StdStringToDart(routeName));
24 25
}

26
void ScheduleFrame(Dart_NativeArguments args) {
27
  UIDartState::Current()->window()->client()->ScheduleFrame();
28 29 30 31
}

void Render(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;
32 33
  Scene* scene =
      tonic::DartConverter<Scene*>::FromArguments(args, 1, exception);
34 35 36 37
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }
38
  UIDartState::Current()->window()->client()->Render(scene);
39 40
}

41 42 43 44 45 46 47 48 49 50 51
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);
}

52 53 54 55 56 57 58 59
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;
  }
60
  UIDartState::Current()->SetDebugName(name);
61 62
}

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
void ReportUnhandledException(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;

  auto error_name =
      tonic::DartConverter<std::string>::FromArguments(args, 0, exception);
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }

  auto stack_trace =
      tonic::DartConverter<std::string>::FromArguments(args, 1, exception);
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }

  UIDartState::Current()->ReportUnhandledException(std::move(error_name),
                                                   std::move(stack_trace));
}

84 85 86
Dart_Handle SendPlatformMessage(Dart_Handle window,
                                const std::string& name,
                                Dart_Handle callback,
87
                                Dart_Handle data_handle) {
88
  UIDartState* dart_state = UIDartState::Current();
A
Adam Barth 已提交
89

90
  if (!dart_state->window()) {
91 92
    return tonic::ToDart(
        "Platform messages can only be sent from the main isolate");
93 94
  }

95
  fml::RefPtr<PlatformMessageResponse> response;
A
Adam Barth 已提交
96
  if (!Dart_IsNull(callback)) {
97
    response = fml::MakeRefCounted<PlatformMessageResponseDart>(
98 99
        tonic::DartPersistentValue(dart_state, callback),
        dart_state->GetTaskRunners().GetUITaskRunner());
A
Adam Barth 已提交
100
  }
101
  if (Dart_IsNull(data_handle)) {
102
    dart_state->window()->client()->HandlePlatformMessage(
103
        fml::MakeRefCounted<PlatformMessage>(name, response));
104
  } else {
105
    tonic::DartByteData data(data_handle);
106
    const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
107
    dart_state->window()->client()->HandlePlatformMessage(
108
        fml::MakeRefCounted<PlatformMessage>(
109 110 111
            name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
            response));
  }
112 113

  return Dart_Null();
114 115 116 117 118 119
}

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

A
Adam Barth 已提交
120 121 122
void RespondToPlatformMessage(Dart_Handle window,
                              int response_id,
                              const tonic::DartByteData& data) {
123 124 125 126
  if (Dart_IsNull(data.dart_handle())) {
    UIDartState::Current()->window()->CompletePlatformMessageEmptyResponse(
        response_id);
  } else {
127
    // TODO(engine): Avoid this copy.
128 129 130 131 132
    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 已提交
133 134 135 136 137 138
}

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

139 140
}  // namespace

141
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
142 143
  Dart_Handle data_handle =
      Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
144 145 146 147 148 149
  if (Dart_IsError(data_handle))
    return data_handle;

  Dart_TypedData_Type type;
  void* data = nullptr;
  intptr_t num_bytes = 0;
150
  FML_CHECK(!Dart_IsError(
151 152 153 154 155 156 157
      Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));

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

A
Adam Barth 已提交
158
WindowClient::~WindowClient() {}
159

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

A
Adam Barth 已提交
162
Window::~Window() {}
163 164

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

169
void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
170 171
  viewport_metrics_ = metrics;

172
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
173 174
  if (!dart_state)
    return;
175
  tonic::DartState::Scope scope(dart_state);
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
  tonic::LogIfError(tonic::DartInvokeField(
      library_.value(), "_updateWindowMetrics",
      {
          tonic::ToDart(metrics.device_pixel_ratio),
          tonic::ToDart(metrics.physical_width),
          tonic::ToDart(metrics.physical_height),
          tonic::ToDart(metrics.physical_padding_top),
          tonic::ToDart(metrics.physical_padding_right),
          tonic::ToDart(metrics.physical_padding_bottom),
          tonic::ToDart(metrics.physical_padding_left),
          tonic::ToDart(metrics.physical_view_inset_top),
          tonic::ToDart(metrics.physical_view_inset_right),
          tonic::ToDart(metrics.physical_view_inset_bottom),
          tonic::ToDart(metrics.physical_view_inset_left),
      }));
191 192
}

193
void Window::UpdateLocales(const std::vector<std::string>& locales) {
194
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
195 196
  if (!dart_state)
    return;
197
  tonic::DartState::Scope scope(dart_state);
198 199 200 201 202
  tonic::LogIfError(tonic::DartInvokeField(
      library_.value(), "_updateLocales",
      {
          tonic::ToDart<std::vector<std::string>>(locales),
      }));
203 204
}

205
void Window::UpdateUserSettingsData(const std::string& data) {
206
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
207 208 209 210
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

211 212 213 214 215
  tonic::LogIfError(tonic::DartInvokeField(library_.value(),
                                           "_updateUserSettingsData",
                                           {
                                               tonic::StdStringToDart(data),
                                           }));
216 217
}

218 219 220 221 222 223 224 225 226 227 228 229
void Window::UpdateLifecycleState(const std::string& data) {
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);
  tonic::LogIfError(tonic::DartInvokeField(library_.value(),
                                           "_updateLifecycleState",
                                           {
                                               tonic::StdStringToDart(data),
                                           }));
}

230
void Window::UpdateSemanticsEnabled(bool enabled) {
231
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
232 233 234 235
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

236 237
  tonic::LogIfError(tonic::DartInvokeField(
      library_.value(), "_updateSemanticsEnabled", {tonic::ToDart(enabled)}));
238 239
}

240
void Window::UpdateAccessibilityFeatures(int32_t values) {
241
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
242 243 244 245
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

246 247 248
  tonic::LogIfError(tonic::DartInvokeField(library_.value(),
                                           "_updateAccessibilityFeatures",
                                           {tonic::ToDart(values)}));
249 250
}

251
void Window::DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) {
252
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
253 254 255
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);
256 257
  Dart_Handle data_handle =
      (message->hasData()) ? ToByteData(message->data()) : Dart_Null();
258 259 260
  if (Dart_IsError(data_handle))
    return;

A
Adam Barth 已提交
261 262 263 264 265
  int response_id = 0;
  if (auto response = message->response()) {
    response_id = next_response_id_++;
    pending_responses_[response_id] = response;
  }
266

267 268 269 270
  tonic::LogIfError(
      tonic::DartInvokeField(library_.value(), "_dispatchPlatformMessage",
                             {tonic::ToDart(message->channel()), data_handle,
                              tonic::ToDart(response_id)}));
A
Adam Barth 已提交
271
}
272

A
Adam Barth 已提交
273
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
274
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
A
Adam Barth 已提交
275 276 277 278 279 280 281
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

  Dart_Handle data_handle = ToByteData(packet.data());
  if (Dart_IsError(data_handle))
    return;
282 283
  tonic::LogIfError(tonic::DartInvokeField(
      library_.value(), "_dispatchPointerDataPacket", {data_handle}));
284 285
}

286 287 288
void Window::DispatchSemanticsAction(int32_t id,
                                     SemanticsAction action,
                                     std::vector<uint8_t> args) {
289
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
290 291 292 293
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

294 295 296 297 298
  Dart_Handle args_handle = (args.empty()) ? Dart_Null() : ToByteData(args);

  if (Dart_IsError(args_handle))
    return;

299
  tonic::LogIfError(tonic::DartInvokeField(
300
      library_.value(), "_dispatchSemanticsAction",
301 302
      {tonic::ToDart(id), tonic::ToDart(static_cast<int32_t>(action)),
       args_handle}));
303 304
}

305
void Window::BeginFrame(fml::TimePoint frameTime) {
306
  std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
307 308
  if (!dart_state)
    return;
309
  tonic::DartState::Scope scope(dart_state);
310

311
  int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
312

313 314 315 316
  tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_beginFrame",
                                           {
                                               Dart_NewInteger(microseconds),
                                           }));
317

318
  UIDartState::Current()->FlushMicrotasksNow();
319

320
  tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_drawFrame", {}));
321 322
}

323 324 325 326 327 328 329 330 331 332 333
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 已提交
334
void Window::CompletePlatformMessageResponse(int response_id,
335
                                             std::vector<uint8_t> data) {
A
Adam Barth 已提交
336 337 338 339 340 341 342
  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);
343
  response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
A
Adam Barth 已提交
344 345
}

346
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
347
  natives->Register({
348
      {"Window_defaultRouteName", DefaultRouteName, 1, true},
349 350
      {"Window_scheduleFrame", ScheduleFrame, 1, true},
      {"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
A
Adam Barth 已提交
351
      {"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
352 353
      {"Window_render", Render, 2, true},
      {"Window_updateSemantics", UpdateSemantics, 2, true},
354
      {"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
355
      {"Window_reportUnhandledException", ReportUnhandledException, 2, true},
356
  });
357 358
}

359
}  // namespace flutter