// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/windows/flutter_windows_view.h"

#include <chrono>

#include "flutter/common/constants.h"
#include "flutter/fml/platform/win/wstring_conversion.h"
#include "flutter/shell/platform/common/accessibility_bridge.h"
#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
#include "flutter/shell/platform/windows/text_input_plugin.h"
#include "flutter/third_party/accessibility/ax/platform/ax_platform_node_win.h"

namespace flutter {

namespace {
// The maximum duration to block the platform thread for while waiting
// for a window resize operation to complete.
constexpr std::chrono::milliseconds kWindowResizeTimeout{100};

/// Returns true if the surface will be updated as part of the resize process.
///
/// This is called on window resize to determine if the platform thread needs
/// to be blocked until the frame with the right size has been rendered. It
/// should be kept in-sync with how the engine deals with a new surface request
/// as seen in `CreateOrUpdateSurface` in `GPUSurfaceGL`.
bool SurfaceWillUpdate(size_t cur_width,
                       size_t cur_height,
                       size_t target_width,
                       size_t target_height) {
  // TODO (https://github.com/flutter/flutter/issues/65061) : Avoid special
  // handling for zero dimensions.
  bool non_zero_target_dims = target_height > 0 && target_width > 0;
  bool not_same_size =
      (cur_height != target_height) || (cur_width != target_width);
  return non_zero_target_dims && not_same_size;
}

/// Update the surface's swap interval to block until the v-blank iff
/// the system compositor is disabled.
void UpdateVsync(const FlutterWindowsEngine& engine,
                 egl::WindowSurface* surface,
                 bool needs_vsync) {
  egl::Manager* egl_manager = engine.egl_manager();
  if (!egl_manager) {
    return;
  }

  auto update_vsync = [egl_manager, surface, needs_vsync]() {
    if (!surface || !surface->IsValid()) {
      return;
    }

    if (!surface->MakeCurrent()) {
      FML_LOG(ERROR) << "Unable to make the render surface current to update "
                        "the swap interval";
      return;
    }

    if (!surface->SetVSyncEnabled(needs_vsync)) {
      FML_LOG(ERROR) << "Unable to update the render surface's swap interval";
    }

    if (!egl_manager->render_context()->ClearCurrent()) {
      FML_LOG(ERROR) << "Unable to clear current surface after updating "
                        "the swap interval";
    }
  };

  // Updating the vsync makes the EGL context and render surface current.
  // If the engine is running, the render surface should only be made current on
  // the raster thread. If the engine is initializing, the raster thread doesn't
  // exist yet and the render surface can be made current on the platform
  // thread.
  if (engine.running()) {
    engine.PostRasterThreadTask(update_vsync);
  } else {
    update_vsync();
  }
}

}  // namespace

FlutterWindowsView::FlutterWindowsView(
    FlutterViewId view_id,
    FlutterWindowsEngine* engine,
    std::unique_ptr<WindowBindingHandler> window_binding,
    std::shared_ptr<WindowsProcTable> windows_proc_table)
    : view_id_(view_id),
      engine_(engine),
      windows_proc_table_(std::move(windows_proc_table)) {
  if (windows_proc_table_ == nullptr) {
    windows_proc_table_ = std::make_shared<WindowsProcTable>();
  }

  // Take the binding handler, and give it a pointer back to self.
  binding_handler_ = std::move(window_binding);
  binding_handler_->SetView(this);
}

FlutterWindowsView::~FlutterWindowsView() {
  // The view owns the child window.
  // Notify the engine the view's child window will no longer be visible.
  engine_->OnWindowStateEvent(GetWindowHandle(), WindowStateEvent::kHide);

  // The engine renders into the view's surface. The engine must be
  // shutdown before the view's resources can be destroyed.
  engine_->Stop();

  DestroyRenderSurface();
}

bool FlutterWindowsView::OnEmptyFrameGenerated() {
  // Called on the raster thread.
  std::unique_lock<std::mutex> lock(resize_mutex_);

  if (surface_ == nullptr || !surface_->IsValid()) {
    return false;
  }

  if (resize_status_ != ResizeState::kResizeStarted) {
    return true;
  }

  if (!ResizeRenderSurface(resize_target_height_, resize_target_width_)) {
    return false;
  }

  // Platform thread is blocked for the entire duration until the
  // resize_status_ is set to kDone by |OnFramePresented|.
  resize_status_ = ResizeState::kFrameGenerated;
  return true;
}

bool FlutterWindowsView::OnFrameGenerated(size_t width, size_t height) {
  // Called on the raster thread.
  std::unique_lock<std::mutex> lock(resize_mutex_);

  if (surface_ == nullptr || !surface_->IsValid()) {
    return false;
  }

  if (resize_status_ != ResizeState::kResizeStarted) {
    return true;
  }

  if (resize_target_width_ != width || resize_target_height_ != height) {
    return false;
  }

  if (!ResizeRenderSurface(resize_target_width_, resize_target_height_)) {
    return false;
  }

  // Platform thread is blocked for the entire duration until the
  // resize_status_ is set to kDone by |OnFramePresented|.
  resize_status_ = ResizeState::kFrameGenerated;
  return true;
}

void FlutterWindowsView::UpdateFlutterCursor(const std::string& cursor_name) {
  binding_handler_->UpdateFlutterCursor(cursor_name);
}

void FlutterWindowsView::SetFlutterCursor(HCURSOR cursor) {
  binding_handler_->SetFlutterCursor(cursor);
}

void FlutterWindowsView::ForceRedraw() {
  if (resize_status_ == ResizeState::kDone) {
    // Request new frame.
    engine_->ScheduleFrame();
  }
}

bool FlutterWindowsView::OnWindowSizeChanged(size_t width, size_t height) {
  // Called on the platform thread.
  std::unique_lock<std::mutex> lock(resize_mutex_);

  if (!engine_->egl_manager()) {
    SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
    return true;
  }

  if (!surface_ || !surface_->IsValid()) {
    SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
    return true;
  }

  // We're using OpenGL rendering. Resizing the surface must happen on the
  // raster thread.
  bool surface_will_update =
      SurfaceWillUpdate(surface_->width(), surface_->height(), width, height);
  if (!surface_will_update) {
    SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
    return true;
  }

  resize_status_ = ResizeState::kResizeStarted;
  resize_target_width_ = width;
  resize_target_height_ = height;

  SendWindowMetrics(width, height, binding_handler_->GetDpiScale());

  // Block the platform thread until a frame is presented with the target
  // size. See |OnFrameGenerated|, |OnEmptyFrameGenerated|, and
  // |OnFramePresented|.
  return resize_cv_.wait_for(lock, kWindowResizeTimeout,
                             [&resize_status = resize_status_] {
                               return resize_status == ResizeState::kDone;
                             });
}

void FlutterWindowsView::OnWindowRepaint() {
  ForceRedraw();
}

void FlutterWindowsView::OnPointerMove(double x,
                                       double y,
                                       FlutterPointerDeviceKind device_kind,
                                       int32_t device_id,
                                       int modifiers_state) {
  engine_->keyboard_key_handler()->SyncModifiersIfNeeded(modifiers_state);
  SendPointerMove(x, y, GetOrCreatePointerState(device_kind, device_id));
}

void FlutterWindowsView::OnPointerDown(
    double x,
    double y,
    FlutterPointerDeviceKind device_kind,
    int32_t device_id,
    FlutterPointerMouseButtons flutter_button) {
  if (flutter_button != 0) {
    auto state = GetOrCreatePointerState(device_kind, device_id);
    state->buttons |= flutter_button;
    SendPointerDown(x, y, state);
  }
}

void FlutterWindowsView::OnPointerUp(
    double x,
    double y,
    FlutterPointerDeviceKind device_kind,
    int32_t device_id,
    FlutterPointerMouseButtons flutter_button) {
  if (flutter_button != 0) {
    auto state = GetOrCreatePointerState(device_kind, device_id);
    state->buttons &= ~flutter_button;
    SendPointerUp(x, y, state);
  }
}

void FlutterWindowsView::OnPointerLeave(double x,
                                        double y,
                                        FlutterPointerDeviceKind device_kind,
                                        int32_t device_id) {
  SendPointerLeave(x, y, GetOrCreatePointerState(device_kind, device_id));
}

void FlutterWindowsView::OnPointerPanZoomStart(int32_t device_id) {
  PointerLocation point = binding_handler_->GetPrimaryPointerLocation();
  SendPointerPanZoomStart(device_id, point.x, point.y);
}

void FlutterWindowsView::OnPointerPanZoomUpdate(int32_t device_id,
                                                double pan_x,
                                                double pan_y,
                                                double scale,
                                                double rotation) {
  SendPointerPanZoomUpdate(device_id, pan_x, pan_y, scale, rotation);
}

void FlutterWindowsView::OnPointerPanZoomEnd(int32_t device_id) {
  SendPointerPanZoomEnd(device_id);
}

void FlutterWindowsView::OnText(const std::u16string& text) {
  SendText(text);
}

void FlutterWindowsView::OnKey(int key,
                               int scancode,
                               int action,
                               char32_t character,
                               bool extended,
                               bool was_down,
                               KeyEventCallback callback) {
  SendKey(key, scancode, action, character, extended, was_down, callback);
}

void FlutterWindowsView::OnComposeBegin() {
  SendComposeBegin();
}

void FlutterWindowsView::OnComposeCommit() {
  SendComposeCommit();
}

void FlutterWindowsView::OnComposeEnd() {
  SendComposeEnd();
}

void FlutterWindowsView::OnComposeChange(const std::u16string& text,
                                         int cursor_pos) {
  SendComposeChange(text, cursor_pos);
}

void FlutterWindowsView::OnScroll(double x,
                                  double y,
                                  double delta_x,
                                  double delta_y,
                                  int scroll_offset_multiplier,
                                  FlutterPointerDeviceKind device_kind,
                                  int32_t device_id) {
  SendScroll(x, y, delta_x, delta_y, scroll_offset_multiplier, device_kind,
             device_id);
}

void FlutterWindowsView::OnScrollInertiaCancel(int32_t device_id) {
  PointerLocation point = binding_handler_->GetPrimaryPointerLocation();
  SendScrollInertiaCancel(device_id, point.x, point.y);
}

void FlutterWindowsView::OnUpdateSemanticsEnabled(bool enabled) {
  engine_->UpdateSemanticsEnabled(enabled);
}

gfx::NativeViewAccessible FlutterWindowsView::GetNativeViewAccessible() {
  if (!accessibility_bridge_) {
    return nullptr;
  }

  return accessibility_bridge_->GetChildOfAXFragmentRoot();
}

void FlutterWindowsView::OnCursorRectUpdated(const Rect& rect) {
  binding_handler_->OnCursorRectUpdated(rect);
}

void FlutterWindowsView::OnResetImeComposing() {
  binding_handler_->OnResetImeComposing();
}

// Sends new size  information to FlutterEngine.
void FlutterWindowsView::SendWindowMetrics(size_t width,
                                           size_t height,
                                           double dpiScale) const {
  FlutterWindowMetricsEvent event = {};
  event.struct_size = sizeof(event);
  event.width = width;
  event.height = height;
  event.pixel_ratio = dpiScale;
  engine_->SendWindowMetricsEvent(event);
}

void FlutterWindowsView::SendInitialBounds() {
  PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();

  SendWindowMetrics(bounds.width, bounds.height,
                    binding_handler_->GetDpiScale());
}

FlutterWindowsView::PointerState* FlutterWindowsView::GetOrCreatePointerState(
    FlutterPointerDeviceKind device_kind,
    int32_t device_id) {
  // Create a virtual pointer ID that is unique across all device types
  // to prevent pointers from clashing in the engine's converter
  // (lib/ui/window/pointer_data_packet_converter.cc)
  int32_t pointer_id = (static_cast<int32_t>(device_kind) << 28) | device_id;

  auto [it, added] = pointer_states_.try_emplace(pointer_id, nullptr);
  if (added) {
    auto state = std::make_unique<PointerState>();
    state->device_kind = device_kind;
    state->pointer_id = pointer_id;
    it->second = std::move(state);
  }

  return it->second.get();
}

// Set's |event_data|'s phase to either kMove or kHover depending on the current
// primary mouse button state.
void FlutterWindowsView::SetEventPhaseFromCursorButtonState(
    FlutterPointerEvent* event_data,
    const PointerState* state) const {
  // For details about this logic, see FlutterPointerPhase in the embedder.h
  // file.
  if (state->buttons == 0) {
    event_data->phase = state->flutter_state_is_down
                            ? FlutterPointerPhase::kUp
                            : FlutterPointerPhase::kHover;
  } else {
    event_data->phase = state->flutter_state_is_down
                            ? FlutterPointerPhase::kMove
                            : FlutterPointerPhase::kDown;
  }
}

void FlutterWindowsView::SendPointerMove(double x,
                                         double y,
                                         PointerState* state) {
  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;

  SetEventPhaseFromCursorButtonState(&event, state);
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendPointerDown(double x,
                                         double y,
                                         PointerState* state) {
  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;

  SetEventPhaseFromCursorButtonState(&event, state);
  SendPointerEventWithData(event, state);

  state->flutter_state_is_down = true;
}

void FlutterWindowsView::SendPointerUp(double x,
                                       double y,
                                       PointerState* state) {
  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;

  SetEventPhaseFromCursorButtonState(&event, state);
  SendPointerEventWithData(event, state);
  if (event.phase == FlutterPointerPhase::kUp) {
    state->flutter_state_is_down = false;
  }
}

void FlutterWindowsView::SendPointerLeave(double x,
                                          double y,
                                          PointerState* state) {
  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;
  event.phase = FlutterPointerPhase::kRemove;
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendPointerPanZoomStart(int32_t device_id,
                                                 double x,
                                                 double y) {
  auto state =
      GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
  state->pan_zoom_start_x = x;
  state->pan_zoom_start_y = y;
  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;
  event.phase = FlutterPointerPhase::kPanZoomStart;
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendPointerPanZoomUpdate(int32_t device_id,
                                                  double pan_x,
                                                  double pan_y,
                                                  double scale,
                                                  double rotation) {
  auto state =
      GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
  FlutterPointerEvent event = {};
  event.x = state->pan_zoom_start_x;
  event.y = state->pan_zoom_start_y;
  event.pan_x = pan_x;
  event.pan_y = pan_y;
  event.scale = scale;
  event.rotation = rotation;
  event.phase = FlutterPointerPhase::kPanZoomUpdate;
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendPointerPanZoomEnd(int32_t device_id) {
  auto state =
      GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);
  FlutterPointerEvent event = {};
  event.x = state->pan_zoom_start_x;
  event.y = state->pan_zoom_start_y;
  event.phase = FlutterPointerPhase::kPanZoomEnd;
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendText(const std::u16string& text) {
  engine_->text_input_plugin()->TextHook(text);
}

void FlutterWindowsView::SendKey(int key,
                                 int scancode,
                                 int action,
                                 char32_t character,
                                 bool extended,
                                 bool was_down,
                                 KeyEventCallback callback) {
  engine_->keyboard_key_handler()->KeyboardHook(
      key, scancode, action, character, extended, was_down,
      [=, callback = std::move(callback)](bool handled) {
        if (!handled) {
          engine_->text_input_plugin()->KeyboardHook(
              key, scancode, action, character, extended, was_down);
        }
        callback(handled);
      });
}

void FlutterWindowsView::SendComposeBegin() {
  engine_->text_input_plugin()->ComposeBeginHook();
}

void FlutterWindowsView::SendComposeCommit() {
  engine_->text_input_plugin()->ComposeCommitHook();
}

void FlutterWindowsView::SendComposeEnd() {
  engine_->text_input_plugin()->ComposeEndHook();
}

void FlutterWindowsView::SendComposeChange(const std::u16string& text,
                                           int cursor_pos) {
  engine_->text_input_plugin()->ComposeChangeHook(text, cursor_pos);
}

void FlutterWindowsView::SendScroll(double x,
                                    double y,
                                    double delta_x,
                                    double delta_y,
                                    int scroll_offset_multiplier,
                                    FlutterPointerDeviceKind device_kind,
                                    int32_t device_id) {
  auto state = GetOrCreatePointerState(device_kind, device_id);

  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;
  event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll;
  event.scroll_delta_x = delta_x * scroll_offset_multiplier;
  event.scroll_delta_y = delta_y * scroll_offset_multiplier;
  SetEventPhaseFromCursorButtonState(&event, state);
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendScrollInertiaCancel(int32_t device_id,
                                                 double x,
                                                 double y) {
  auto state =
      GetOrCreatePointerState(kFlutterPointerDeviceKindTrackpad, device_id);

  FlutterPointerEvent event = {};
  event.x = x;
  event.y = y;
  event.signal_kind =
      FlutterPointerSignalKind::kFlutterPointerSignalKindScrollInertiaCancel;
  SetEventPhaseFromCursorButtonState(&event, state);
  SendPointerEventWithData(event, state);
}

void FlutterWindowsView::SendPointerEventWithData(
    const FlutterPointerEvent& event_data,
    PointerState* state) {
  // If sending anything other than an add, and the pointer isn't already added,
  // synthesize an add to satisfy Flutter's expectations about events.
  if (!state->flutter_state_is_added &&
      event_data.phase != FlutterPointerPhase::kAdd) {
    FlutterPointerEvent event = {};
    event.phase = FlutterPointerPhase::kAdd;
    event.x = event_data.x;
    event.y = event_data.y;
    event.buttons = 0;
    SendPointerEventWithData(event, state);
  }

  // Don't double-add (e.g., if events are delivered out of order, so an add has
  // already been synthesized).
  if (state->flutter_state_is_added &&
      event_data.phase == FlutterPointerPhase::kAdd) {
    return;
  }

  FlutterPointerEvent event = event_data;
  event.device_kind = state->device_kind;
  event.device = state->pointer_id;
  event.buttons = state->buttons;
  // TODO(dkwingsmt): Use the correct view ID for pointer events once the
  // Windows embedder supports multiple views.
  // https://github.com/flutter/flutter/issues/138179
  event.view_id = flutter::kFlutterImplicitViewId;

  // Set metadata that's always the same regardless of the event.
  event.struct_size = sizeof(event);
  event.timestamp =
      std::chrono::duration_cast<std::chrono::microseconds>(
          std::chrono::high_resolution_clock::now().time_since_epoch())
          .count();

  engine_->SendPointerEvent(event);

  if (event_data.phase == FlutterPointerPhase::kAdd) {
    state->flutter_state_is_added = true;
  } else if (event_data.phase == FlutterPointerPhase::kRemove) {
    auto it = pointer_states_.find(state->pointer_id);
    if (it != pointer_states_.end()) {
      pointer_states_.erase(it);
    }
  }
}

void FlutterWindowsView::OnFramePresented() {
  // Called on the engine's raster thread.
  std::unique_lock<std::mutex> lock(resize_mutex_);

  switch (resize_status_) {
    case ResizeState::kResizeStarted:
      // The caller must first call |OnFrameGenerated| or
      // |OnEmptyFrameGenerated| before calling this method. This
      // indicates one of the following:
      //
      // 1. The caller did not call these methods.
      // 2. The caller ignored these methods' result.
      // 3. The platform thread started a resize after the caller called these
      //    methods. We might have presented a frame of the wrong size to the
      //    view.
      return;
    case ResizeState::kFrameGenerated: {
      // A frame was generated for a pending resize.
      // Unblock the platform thread.
      resize_status_ = ResizeState::kDone;
      lock.unlock();
      resize_cv_.notify_all();

      // Blocking the raster thread until DWM flushes alleviates glitches where
      // previous size surface is stretched over current size view.
      windows_proc_table_->DwmFlush();
    }
    case ResizeState::kDone:
      return;
  }
}

bool FlutterWindowsView::ClearSoftwareBitmap() {
  return binding_handler_->OnBitmapSurfaceCleared();
}

bool FlutterWindowsView::PresentSoftwareBitmap(const void* allocation,
                                               size_t row_bytes,
                                               size_t height) {
  return binding_handler_->OnBitmapSurfaceUpdated(allocation, row_bytes,
                                                  height);
}

FlutterViewId FlutterWindowsView::view_id() const {
  return view_id_;
}

void FlutterWindowsView::CreateRenderSurface() {
  FML_DCHECK(surface_ == nullptr);

  if (engine_->egl_manager()) {
    PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
    surface_ = engine_->egl_manager()->CreateWindowSurface(
        GetWindowHandle(), bounds.width, bounds.height);

    UpdateVsync(*engine_, surface_.get(), NeedsVsync());

    resize_target_width_ = bounds.width;
    resize_target_height_ = bounds.height;
  }
}

bool FlutterWindowsView::ResizeRenderSurface(size_t width, size_t height) {
  FML_DCHECK(surface_ != nullptr);

  // No-op if the surface is already the desired size.
  if (width == surface_->width() && height == surface_->height()) {
    return true;
  }

  auto const existing_vsync = surface_->vsync_enabled();

  // TODO: Destroying the surface and re-creating it is expensive.
  // Ideally this would use ANGLE's automatic surface sizing instead.
  // See: https://github.com/flutter/flutter/issues/79427
  if (!surface_->Destroy()) {
    FML_LOG(ERROR) << "View resize failed to destroy surface";
    return false;
  }

  std::unique_ptr<egl::WindowSurface> resized_surface =
      engine_->egl_manager()->CreateWindowSurface(GetWindowHandle(), width,
                                                  height);
  if (!resized_surface) {
    FML_LOG(ERROR) << "View resize failed to create surface";
    return false;
  }

  if (!resized_surface->MakeCurrent() ||
      !resized_surface->SetVSyncEnabled(existing_vsync)) {
    // Surfaces block until the v-blank by default.
    // Failing to update the vsync might result in unnecessary blocking.
    // This regresses performance but not correctness.
    FML_LOG(ERROR) << "View resize failed to set vsync";
  }

  surface_ = std::move(resized_surface);
  return true;
}

void FlutterWindowsView::DestroyRenderSurface() {
  if (surface_) {
    surface_->Destroy();
  }
}

egl::WindowSurface* FlutterWindowsView::surface() const {
  return surface_.get();
}

void FlutterWindowsView::OnHighContrastChanged() {
  engine_->UpdateHighContrastMode();
}

HWND FlutterWindowsView::GetWindowHandle() const {
  return binding_handler_->GetWindowHandle();
}

FlutterWindowsEngine* FlutterWindowsView::GetEngine() const {
  return engine_;
}

void FlutterWindowsView::AnnounceAlert(const std::wstring& text) {
  auto alert_delegate = binding_handler_->GetAlertDelegate();
  if (!alert_delegate) {
    return;
  }
  alert_delegate->SetText(fml::WideStringToUtf16(text));
  ui::AXPlatformNodeWin* alert_node = binding_handler_->GetAlert();
  NotifyWinEventWrapper(alert_node, ax::mojom::Event::kAlert);
}

void FlutterWindowsView::NotifyWinEventWrapper(ui::AXPlatformNodeWin* node,
                                               ax::mojom::Event event) {
  if (node) {
    node->NotifyAccessibilityEvent(event);
  }
}

ui::AXFragmentRootDelegateWin* FlutterWindowsView::GetAxFragmentRootDelegate() {
  return accessibility_bridge_.get();
}

ui::AXPlatformNodeWin* FlutterWindowsView::AlertNode() const {
  return binding_handler_->GetAlert();
}

std::shared_ptr<AccessibilityBridgeWindows>
FlutterWindowsView::CreateAccessibilityBridge() {
  return std::make_shared<AccessibilityBridgeWindows>(this);
}

void FlutterWindowsView::UpdateSemanticsEnabled(bool enabled) {
  if (semantics_enabled_ != enabled) {
    semantics_enabled_ = enabled;

    if (!semantics_enabled_ && accessibility_bridge_) {
      accessibility_bridge_.reset();
    } else if (semantics_enabled_ && !accessibility_bridge_) {
      accessibility_bridge_ = CreateAccessibilityBridge();
    }
  }
}

void FlutterWindowsView::OnDwmCompositionChanged() {
  UpdateVsync(*engine_, surface_.get(), NeedsVsync());
}

void FlutterWindowsView::OnWindowStateEvent(HWND hwnd, WindowStateEvent event) {
  engine_->OnWindowStateEvent(hwnd, event);
}

bool FlutterWindowsView::NeedsVsync() const {
  // If the Desktop Window Manager composition is enabled,
  // the system itself synchronizes with vsync.
  // See: https://learn.microsoft.com/windows/win32/dwm/composition-ovw
  return !windows_proc_table_->DwmIsCompositionEnabled();
}

}  // namespace flutter
