window.cc 8.6 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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
#include "lib/tonic/converter/dart_converter.h"
11
#include "lib/tonic/dart_args.h"
12
#include "lib/tonic/dart_library_natives.h"
13
#include "lib/tonic/dart_microtask_queue.h"
14
#include "lib/tonic/logging/dart_invoke.h"
15
#include "lib/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
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
A
Adam Barth 已提交
26 27 28 29 30 31 32 33
  Dart_Handle data_handle =
      Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
  if (Dart_IsError(data_handle))
    return data_handle;

  Dart_TypedData_Type type;
  void* data = nullptr;
  intptr_t num_bytes = 0;
34
  FXL_CHECK(!Dart_IsError(
A
Adam Barth 已提交
35 36 37 38 39 40 41
      Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));

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

42 43 44 45 46
void DefaultRouteName(Dart_NativeArguments args) {
  std::string routeName = UIDartState::Current()->window()->client()->DefaultRouteName();
  Dart_SetReturnValue(args, StdStringToDart(routeName));
}

47
void ScheduleFrame(Dart_NativeArguments args) {
48
  UIDartState::Current()->window()->client()->ScheduleFrame();
49 50 51 52
}

void Render(Dart_NativeArguments args) {
  Dart_Handle exception = nullptr;
53 54
  Scene* scene =
      tonic::DartConverter<Scene*>::FromArguments(args, 1, exception);
55 56 57 58
  if (exception) {
    Dart_ThrowException(exception);
    return;
  }
59
  UIDartState::Current()->window()->client()->Render(scene);
60 61
}

62 63 64 65 66 67 68 69 70 71 72
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);
}

73 74 75 76 77
void SendPlatformMessage(Dart_Handle window,
                         const std::string& name,
                         Dart_Handle callback,
                         const tonic::DartByteData& data) {
  UIDartState* dart_state = UIDartState::Current();
A
Adam Barth 已提交
78

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

    UIDartState::Current()->window()->client()->HandlePlatformMessage(
91
        fxl::MakeRefCounted<PlatformMessage>(
92 93 94
            name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
            response));
  }
95 96 97 98 99 100
}

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

A
Adam Barth 已提交
101 102 103
void RespondToPlatformMessage(Dart_Handle window,
                              int response_id,
                              const tonic::DartByteData& data) {
104 105 106 107 108 109 110 111 112
  if (Dart_IsNull(data.dart_handle())) {
    UIDartState::Current()->window()->CompletePlatformMessageEmptyResponse(
        response_id);
  } else {
    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 已提交
113 114 115 116 117 118
}

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

119 120
}  // namespace

A
Adam Barth 已提交
121
WindowClient::~WindowClient() {}
122

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

A
Adam Barth 已提交
125
Window::~Window() {}
126 127 128 129 130

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

131
void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
132 133
  viewport_metrics_ = metrics;

134
  tonic::DartState* dart_state = library_.dart_state().get();
135 136
  if (!dart_state)
    return;
137
  tonic::DartState::Scope scope(dart_state);
A
Adam Barth 已提交
138 139 140
  DartInvokeField(
      library_.value(), "_updateWindowMetrics",
      {
141 142 143 144 145 146 147
          ToDart(metrics.device_pixel_ratio),
          ToDart(static_cast<double>(metrics.physical_width)),
          ToDart(static_cast<double>(metrics.physical_height)),
          ToDart(static_cast<double>(metrics.physical_padding_top)),
          ToDart(static_cast<double>(metrics.physical_padding_right)),
          ToDart(static_cast<double>(metrics.physical_padding_bottom)),
          ToDart(static_cast<double>(metrics.physical_padding_left)),
A
Adam Barth 已提交
148
      });
149 150
}

151 152
void Window::UpdateLocale(const std::string& language_code,
                          const std::string& country_code) {
153
  tonic::DartState* dart_state = library_.dart_state().get();
154 155
  if (!dart_state)
    return;
156
  tonic::DartState::Scope scope(dart_state);
157

A
Adam Barth 已提交
158 159 160 161 162
  DartInvokeField(
      library_.value(), "_updateLocale",
      {
          StdStringToDart(language_code), StdStringToDart(country_code),
      });
163 164
}

165 166 167 168 169 170 171 172 173 174
void Window::UpdateSemanticsEnabled(bool enabled) {
  tonic::DartState* dart_state = library_.dart_state().get();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

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

175
void Window::DispatchPlatformMessage(fxl::RefPtr<PlatformMessage> message) {
176 177 178 179
  tonic::DartState* dart_state = library_.dart_state().get();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);
180 181 182
  Dart_Handle data_handle = (message->hasData())
      ? ToByteData(message->data())
      : Dart_Null();
183 184 185
  if (Dart_IsError(data_handle))
    return;

A
Adam Barth 已提交
186 187 188 189 190
  int response_id = 0;
  if (auto response = message->response()) {
    response_id = next_response_id_++;
    pending_responses_[response_id] = response;
  }
191

192 193 194
  DartInvokeField(
      library_.value(), "_dispatchPlatformMessage",
      {ToDart(message->channel()), data_handle, ToDart(response_id)});
A
Adam Barth 已提交
195
}
196

A
Adam Barth 已提交
197 198 199 200 201 202 203 204 205
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
  tonic::DartState* dart_state = library_.dart_state().get();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

  Dart_Handle data_handle = ToByteData(packet.data());
  if (Dart_IsError(data_handle))
    return;
206 207 208 209
  DartInvokeField(library_.value(), "_dispatchPointerDataPacket",
                  {data_handle});
}

210 211 212 213 214 215 216 217 218 219
void Window::DispatchSemanticsAction(int32_t id, SemanticsAction action) {
  tonic::DartState* dart_state = library_.dart_state().get();
  if (!dart_state)
    return;
  tonic::DartState::Scope scope(dart_state);

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

220
void Window::BeginFrame(fxl::TimePoint frameTime) {
221
  tonic::DartState* dart_state = library_.dart_state().get();
222 223
  if (!dart_state)
    return;
224
  tonic::DartState::Scope scope(dart_state);
225

226
  int64_t microseconds = (frameTime - fxl::TimePoint()).ToMicroseconds();
227

A
Adam Barth 已提交
228 229 230 231
  DartInvokeField(library_.value(), "_beginFrame",
                  {
                      Dart_NewInteger(microseconds),
                  });
232

233
  tonic::DartMicrotaskQueue::GetForCurrentThread()->RunMicrotasks();
234 235

  DartInvokeField(library_.value(), "_drawFrame", {});
236 237
}

238 239 240 241 242 243 244 245 246 247 248
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 已提交
249
void Window::CompletePlatformMessageResponse(int response_id,
250
                                             std::vector<uint8_t> data) {
A
Adam Barth 已提交
251 252 253 254 255 256 257 258 259 260
  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->Complete(std::move(data));
}

261
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
262
  natives->Register({
263
      {"Window_defaultRouteName", DefaultRouteName, 1, true},
264 265
      {"Window_scheduleFrame", ScheduleFrame, 1, true},
      {"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
A
Adam Barth 已提交
266
      {"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
267 268 269
      {"Window_render", Render, 2, true},
      {"Window_updateSemantics", UpdateSemantics, 2, true},
  });
270 271 272
}

}  // namespace blink