// Copyright 2014 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.

#include "ui/views/widget/native_widget_mac.h"

#include <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
#include <CoreFoundation/CoreFoundation.h>

#include <utility>

#include "base/base64.h"
#include "base/bind.h"
#include "base/mac/scoped_nsobject.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/crash/core/common/crash_key.h"
#import "components/remote_cocoa/app_shim/bridged_content_view.h"
#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h"
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#import "ui/base/cocoa/window_size_constants.h"
#include "ui/base/ime/init/input_method_factory.h"
#include "ui/base/ime/input_method.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/gestures/gesture_recognizer_impl_mac.h"
#include "ui/gfx/font_list.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_mac.h"
#import "ui/views/cocoa/drag_drop_client_mac.h"
#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/cocoa/text_input_host.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/native_frame_view.h"

using remote_cocoa::mojom::WindowVisibilityState;

namespace views {

namespace {

static base::RepeatingCallback<void(NativeWidgetMac*)>*
    g_init_native_widget_callback = nullptr;

NSInteger StyleMaskForParams(const Widget::InitParams& params) {
  // If the Widget is modal, it will be displayed as a sheet. This works best if
  // it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the
  // parent window still accepts input.
  // NSFullSizeContentViewWindowMask ensures that calculating the modal's
  // content rect doesn't account for a nonexistent title bar.
  if (params.delegate &&
      params.delegate->GetModalType() == ui::MODAL_TYPE_WINDOW)
    return NSTitledWindowMask | NSFullSizeContentViewWindowMask;

  // TODO(tapted): Determine better masks when there are use cases for it.
  if (params.remove_standard_frame)
    return NSBorderlessWindowMask;

  if (params.type == Widget::InitParams::TYPE_WINDOW) {
    return NSTitledWindowMask | NSClosableWindowMask |
           NSMiniaturizableWindowMask | NSResizableWindowMask |
           NSTexturedBackgroundWindowMask;
  }
  return NSBorderlessWindowMask;
}

CGWindowLevel CGWindowLevelForZOrderLevel(ui::ZOrderLevel level,
                                          Widget::InitParams::Type type) {
  switch (level) {
    case ui::ZOrderLevel::kNormal:
      return kCGNormalWindowLevel;
    case ui::ZOrderLevel::kFloatingWindow:
      if (type == Widget::InitParams::TYPE_MENU)
        return kCGPopUpMenuWindowLevel;
      else
        return kCGFloatingWindowLevel;
    case ui::ZOrderLevel::kFloatingUIElement:
      if (type == Widget::InitParams::TYPE_DRAG)
        return kCGDraggingWindowLevel;
      else
        return kCGStatusWindowLevel;
    case ui::ZOrderLevel::kSecuritySurface:
      return kCGScreenSaverWindowLevel - 1;
  }
}

}  // namespace

// Implements zoom following focus for macOS accessibility zoom.
class NativeWidgetMac::ZoomFocusMonitor : public FocusChangeListener {
 public:
  ZoomFocusMonitor() = default;
  ~ZoomFocusMonitor() override {}
  void OnWillChangeFocus(View* focused_before, View* focused_now) override {}
  void OnDidChangeFocus(View* focused_before, View* focused_now) override {
    if (!focused_now || !UAZoomEnabled())
      return;
    // Web content handles its own zooming.
    if (strcmp("WebView", focused_now->GetClassName()) == 0)
      return;
    NSRect rect = NSRectFromCGRect(focused_now->GetBoundsInScreen().ToCGRect());
    UAZoomChangeFocus(&rect, nullptr, kUAZoomFocusTypeOther);
  }
};

////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMac:

NativeWidgetMac::NativeWidgetMac(internal::NativeWidgetDelegate* delegate)
    : delegate_(delegate),
      ns_window_host_(new NativeWidgetMacNSWindowHost(this)),
      ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) {}

NativeWidgetMac::~NativeWidgetMac() {
  if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
    delete delegate_;
  else
    CloseNow();
}

void NativeWidgetMac::WindowDestroying() {
  OnWindowDestroying(GetNativeWindow());
  delegate_->OnNativeWidgetDestroying();
}

void NativeWidgetMac::WindowDestroyed() {
  DCHECK(GetNSWindowMojo());
  SetFocusManager(nullptr);
  ns_window_host_.reset();
  // |OnNativeWidgetDestroyed| may delete |this| if the object does not own
  // itself.
  bool should_delete_this =
      (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET);
  delegate_->OnNativeWidgetDestroyed();
  if (should_delete_this)
    delete this;
}

void NativeWidgetMac::OnWindowKeyStatusChanged(
    bool is_key,
    bool is_content_first_responder) {
  Widget* widget = GetWidget();
  if (!widget->OnNativeWidgetActivationChanged(is_key))
    return;
  // The contentView is the BridgedContentView hosting the views::RootView. The
  // focus manager will already know if a native subview has focus.
  if (!is_content_first_responder)
    return;

  if (is_key) {
    widget->OnNativeFocus();
    widget->GetFocusManager()->RestoreFocusedView();
    if (NativeWidgetMacNSWindowHost* parent_host = ns_window_host_->parent()) {
      // Unclear under what circumstances this would be null, but speculatively
      // working around https://crbug/1050430
      if (Widget* top_widget =
              parent_host->native_widget_mac()->GetTopLevelWidget()) {
        parent_key_lock_ = top_widget->LockPaintAsActive();
      }
    }
  } else {
    widget->OnNativeBlur();
    widget->GetFocusManager()->StoreFocusedView(true);
    parent_key_lock_.reset();
  }
}

int32_t NativeWidgetMac::SheetOffsetY() {
  return 0;
}

void NativeWidgetMac::GetWindowFrameTitlebarHeight(
    bool* override_titlebar_height,
    float* titlebar_height) {
  *override_titlebar_height = false;
  *titlebar_height = 0;
}

bool NativeWidgetMac::ExecuteCommand(
    int32_t command,
    WindowOpenDisposition window_open_disposition,
    bool is_before_first_responder) {
  // This is supported only by subclasses in chrome/browser/ui.
  NOTIMPLEMENTED();
  return false;
}

void NativeWidgetMac::InitNativeWidget(Widget::InitParams params) {
  ownership_ = params.ownership;
  name_ = params.name;
  type_ = params.type;
  NativeWidgetMacNSWindowHost* parent_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(params.parent);

  // Determine the factory through which to create the bridge
  remote_cocoa::ApplicationHost* application_host =
      parent_host ? parent_host->application_host()
                  : GetRemoteCocoaApplicationHost();

  // Compute the parameters to describe the NSWindow.
  auto create_window_params = remote_cocoa::mojom::CreateWindowParams::New();
  create_window_params->window_class =
      remote_cocoa::mojom::WindowClass::kDefault;
  create_window_params->style_mask = StyleMaskForParams(params);
  create_window_params->titlebar_appears_transparent = false;
  create_window_params->window_title_hidden = false;
  PopulateCreateWindowParams(params, create_window_params.get());

  if (application_host) {
    ns_window_host_->CreateRemoteNSWindow(application_host,
                                          std::move(create_window_params));
  } else {
    base::scoped_nsobject<NativeWidgetMacNSWindow> window(
        [CreateNSWindow(create_window_params.get()) retain]);
    ns_window_host_->CreateInProcessNSWindowBridge(std::move(window));
  }
  ns_window_host_->SetParent(parent_host);
  ns_window_host_->InitWindow(params,
                              ConvertBoundsToScreenIfNeeded(params.bounds));
  OnWindowInitialized();

  // Only set the z-order here if it is non-default since setting it may affect
  // how the window is treated by Expose.
  if (params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal)
    SetZOrderLevel(params.EffectiveZOrderLevel());

  GetNSWindowMojo()->SetIgnoresMouseEvents(!params.accept_events);

  delegate_->OnNativeWidgetCreated();

  DCHECK(GetWidget()->GetRootView());
  ns_window_host_->SetRootView(GetWidget()->GetRootView());
  GetNSWindowMojo()->CreateContentView(ns_window_host_->GetRootViewNSViewId(),
                                       GetWidget()->GetRootView()->bounds());
  if (auto* focus_manager = GetWidget()->GetFocusManager()) {
    GetNSWindowMojo()->MakeFirstResponder();
    // Only one ZoomFocusMonitor is needed per FocusManager, so create one only
    // for top-level widgets.
    if (GetWidget()->is_top_level())
      zoom_focus_monitor_ = std::make_unique<ZoomFocusMonitor>();
    SetFocusManager(focus_manager);
  }
  ns_window_host_->CreateCompositor(params);

  if (g_init_native_widget_callback)
    g_init_native_widget_callback->Run(this);
}

void NativeWidgetMac::OnWidgetInitDone() {
  OnSizeConstraintsChanged();
  ns_window_host_->OnWidgetInitDone();
}

std::unique_ptr<NonClientFrameView>
NativeWidgetMac::CreateNonClientFrameView() {
  return std::make_unique<NativeFrameView>(GetWidget());
}

bool NativeWidgetMac::ShouldUseNativeFrame() const {
  return true;
}

bool NativeWidgetMac::ShouldWindowContentsBeTransparent() const {
  // On Windows, this returns true when Aero is enabled which draws the titlebar
  // with translucency.
  return false;
}

void NativeWidgetMac::FrameTypeChanged() {
  // This is called when the Theme has changed; forward the event to the root
  // widget.
  GetWidget()->ThemeChanged();
  GetWidget()->GetRootView()->SchedulePaint();
}

Widget* NativeWidgetMac::GetWidget() {
  return delegate_->AsWidget();
}

const Widget* NativeWidgetMac::GetWidget() const {
  return delegate_->AsWidget();
}

gfx::NativeView NativeWidgetMac::GetNativeView() const {
  // Returns a BridgedContentView, unless there is no views::RootView set.
  return [GetNativeWindow().GetNativeNSWindow() contentView];
}

gfx::NativeWindow NativeWidgetMac::GetNativeWindow() const {
  return ns_window_host_ ? ns_window_host_->GetInProcessNSWindow() : nil;
}

Widget* NativeWidgetMac::GetTopLevelWidget() {
  NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView());
  return native_widget ? native_widget->GetWidget() : nullptr;
}

const ui::Compositor* NativeWidgetMac::GetCompositor() const {
  return ns_window_host_ && ns_window_host_->layer()
             ? ns_window_host_->layer()->GetCompositor()
             : nullptr;
}

const ui::Layer* NativeWidgetMac::GetLayer() const {
  return ns_window_host_ ? ns_window_host_->layer() : nullptr;
}

void NativeWidgetMac::ReorderNativeViews() {
  if (ns_window_host_)
    ns_window_host_->ReorderChildViews();
}

void NativeWidgetMac::ViewRemoved(View* view) {
  DragDropClientMac* client =
      ns_window_host_ ? ns_window_host_->drag_drop_client() : nullptr;
  if (client)
    client->drop_helper()->ResetTargetViewIfEquals(view);
}

void NativeWidgetMac::SetNativeWindowProperty(const char* name, void* value) {
  if (ns_window_host_)
    ns_window_host_->SetNativeWindowProperty(name, value);
}

void* NativeWidgetMac::GetNativeWindowProperty(const char* name) const {
  if (ns_window_host_)
    return ns_window_host_->GetNativeWindowProperty(name);

  return nullptr;
}

TooltipManager* NativeWidgetMac::GetTooltipManager() const {
  if (ns_window_host_)
    return ns_window_host_->tooltip_manager();

  return nullptr;
}

void NativeWidgetMac::SetCapture() {
  if (GetNSWindowMojo())
    GetNSWindowMojo()->AcquireCapture();
}

void NativeWidgetMac::ReleaseCapture() {
  if (GetNSWindowMojo())
    GetNSWindowMojo()->ReleaseCapture();
}

bool NativeWidgetMac::HasCapture() const {
  return ns_window_host_ && ns_window_host_->IsMouseCaptureActive();
}

ui::InputMethod* NativeWidgetMac::GetInputMethod() {
  if (!input_method_) {
    input_method_ = ui::CreateInputMethod(this, gfx::kNullAcceleratedWidget);
    // For now, use always-focused mode on Mac for the input method.
    // TODO(tapted): Move this to OnWindowKeyStatusChangedTo() and balance.
    input_method_->OnFocus();
  }
  return input_method_.get();
}

void NativeWidgetMac::CenterWindow(const gfx::Size& size) {
  GetNSWindowMojo()->SetSizeAndCenter(size, GetWidget()->GetMinimumSize());
}

void NativeWidgetMac::GetWindowPlacement(
    gfx::Rect* bounds,
    ui::WindowShowState* show_state) const {
  *bounds = GetRestoredBounds();
  if (IsFullscreen())
    *show_state = ui::SHOW_STATE_FULLSCREEN;
  else if (IsMinimized())
    *show_state = ui::SHOW_STATE_MINIMIZED;
  else
    *show_state = ui::SHOW_STATE_NORMAL;
}

bool NativeWidgetMac::SetWindowTitle(const base::string16& title) {
  if (!ns_window_host_)
    return false;
  return ns_window_host_->SetWindowTitle(title);
}

void NativeWidgetMac::SetWindowIcons(const gfx::ImageSkia& window_icon,
                                     const gfx::ImageSkia& app_icon) {
  // Per-window icons are not really a thing on Mac, so do nothing.
  // TODO(tapted): Investigate whether to use NSWindowDocumentIconButton to set
  // an icon next to the window title. See http://crbug.com/766897.
}

void NativeWidgetMac::InitModalType(ui::ModalType modal_type) {
  if (modal_type == ui::MODAL_TYPE_NONE)
    return;

  // System modal windows not implemented (or used) on Mac.
  DCHECK_NE(ui::MODAL_TYPE_SYSTEM, modal_type);

  // A peculiarity of the constrained window framework is that it permits a
  // dialog of MODAL_TYPE_WINDOW to have a null parent window; falling back to
  // a non-modal window in this case.
  DCHECK(ns_window_host_->parent() || modal_type == ui::MODAL_TYPE_WINDOW);

  // Everything happens upon show.
}

gfx::Rect NativeWidgetMac::GetWindowBoundsInScreen() const {
  return ns_window_host_ ? ns_window_host_->GetWindowBoundsInScreen()
                         : gfx::Rect();
}

gfx::Rect NativeWidgetMac::GetClientAreaBoundsInScreen() const {
  return ns_window_host_ ? ns_window_host_->GetContentBoundsInScreen()
                         : gfx::Rect();
}

gfx::Rect NativeWidgetMac::GetRestoredBounds() const {
  return ns_window_host_ ? ns_window_host_->GetRestoredBounds() : gfx::Rect();
}

std::string NativeWidgetMac::GetWorkspace() const {
  return ns_window_host_ ? base::Base64Encode(
                               ns_window_host_->GetWindowStateRestorationData())
                         : std::string();
}

gfx::Rect NativeWidgetMac::ConvertBoundsToScreenIfNeeded(
    const gfx::Rect& bounds) const {
  // If there isn't a parent widget, then bounds cannot be relative to the
  // parent.
  if (!ns_window_host_ || !ns_window_host_->parent() || !GetWidget())
    return bounds;

  // Replicate the logic in desktop_aura/desktop_screen_position_client.cc.
  if (GetAuraWindowTypeForWidgetType(type_) ==
          aura::client::WINDOW_TYPE_POPUP ||
      GetWidget()->is_top_level()) {
    return bounds;
  }

  // Empty bounds are only allowed to be specified at initialization and are
  // expected not to be translated.
  if (bounds.IsEmpty())
    return bounds;

  gfx::Rect bounds_in_screen = bounds;
  bounds_in_screen.Offset(
      ns_window_host_->parent()->GetWindowBoundsInScreen().OffsetFromOrigin());
  return bounds_in_screen;
}

void NativeWidgetMac::SetBounds(const gfx::Rect& bounds) {
  if (!ns_window_host_)
    return;
  ns_window_host_->SetBoundsInScreen(ConvertBoundsToScreenIfNeeded(bounds));
}

void NativeWidgetMac::SetBoundsConstrained(const gfx::Rect& bounds) {
  if (!ns_window_host_)
    return;
  gfx::Rect new_bounds(bounds);
  if (ns_window_host_->parent()) {
    new_bounds.AdjustToFit(
        gfx::Rect(ns_window_host_->parent()->GetWindowBoundsInScreen().size()));
  } else {
    new_bounds = ConstrainBoundsToDisplayWorkArea(new_bounds);
  }
  SetBounds(new_bounds);
}

void NativeWidgetMac::SetSize(const gfx::Size& size) {
  if (!ns_window_host_)
    return;
  // Ensure the top-left corner stays in-place (rather than the bottom-left,
  // which -[NSWindow setContentSize:] would do).
  ns_window_host_->SetBoundsInScreen(
      gfx::Rect(GetWindowBoundsInScreen().origin(), size));
}

void NativeWidgetMac::StackAbove(gfx::NativeView native_view) {
  if (!GetNSWindowMojo())
    return;

  auto* sibling_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);

  if (!sibling_host) {
    // This will only work if |this| is in-process.
    DCHECK(!ns_window_host_->application_host());
    NSInteger view_parent = native_view.GetNativeNSView().window.windowNumber;
    [GetNativeWindow().GetNativeNSWindow() orderWindow:NSWindowAbove
                                            relativeTo:view_parent];
    return;
  }

  if (ns_window_host_->application_host() == sibling_host->application_host()) {
    // Check if |native_view|'s NativeWidgetMacNSWindowHost corresponds to the
    // same process as |this|.
    GetNSWindowMojo()->StackAbove(sibling_host->bridged_native_widget_id());
    return;
  }

  NOTREACHED() << "|native_view|'s NativeWidgetMacNSWindowHost isn't same "
                  "process |this|";
}

void NativeWidgetMac::StackAtTop() {
  if (GetNSWindowMojo())
    GetNSWindowMojo()->StackAtTop();
}

void NativeWidgetMac::SetShape(std::unique_ptr<Widget::ShapeRects> shape) {
  NOTIMPLEMENTED();
}

void NativeWidgetMac::Close() {
  if (GetNSWindowMojo())
    GetNSWindowMojo()->CloseWindow();
}

void NativeWidgetMac::CloseNow() {
  if (ns_window_host_)
    ns_window_host_->CloseWindowNow();
  // Note: |ns_window_host_| will be deleted here, and |this| will be deleted
  // here when ownership_ == NATIVE_WIDGET_OWNS_WIDGET,
}

void NativeWidgetMac::Show(ui::WindowShowState show_state,
                           const gfx::Rect& restore_bounds) {
  if (!GetNSWindowMojo())
    return;

  switch (show_state) {
    case ui::SHOW_STATE_DEFAULT:
    case ui::SHOW_STATE_NORMAL:
    case ui::SHOW_STATE_INACTIVE:
    case ui::SHOW_STATE_MINIMIZED:
      break;
    case ui::SHOW_STATE_MAXIMIZED:
    case ui::SHOW_STATE_FULLSCREEN:
      NOTIMPLEMENTED();
      break;
    case ui::SHOW_STATE_END:
      NOTREACHED();
      break;
  }
  auto window_state = WindowVisibilityState::kShowAndActivateWindow;
  if (show_state == ui::SHOW_STATE_INACTIVE)
    window_state = WindowVisibilityState::kShowInactive;
  else if (show_state == ui::SHOW_STATE_MINIMIZED)
    window_state = WindowVisibilityState::kHideWindow;
  GetNSWindowMojo()->SetVisibilityState(window_state);

  // Ignore the SetInitialFocus() result. BridgedContentView should get
  // firstResponder status regardless.
  delegate_->SetInitialFocus(show_state);
}

void NativeWidgetMac::Hide() {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetVisibilityState(WindowVisibilityState::kHideWindow);
}

bool NativeWidgetMac::IsVisible() const {
  return ns_window_host_ && ns_window_host_->IsVisible();
}

void NativeWidgetMac::Activate() {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetVisibilityState(
      WindowVisibilityState::kShowAndActivateWindow);
}

void NativeWidgetMac::Deactivate() {
  NOTIMPLEMENTED();
}

bool NativeWidgetMac::IsActive() const {
  return ns_window_host_ ? ns_window_host_->IsWindowKey() : false;
}

void NativeWidgetMac::SetZOrderLevel(ui::ZOrderLevel order) {
  if (!GetNSWindowMojo())
    return;
  z_order_level_ = order;
  GetNSWindowMojo()->SetWindowLevel(CGWindowLevelForZOrderLevel(order, type_));
}

ui::ZOrderLevel NativeWidgetMac::GetZOrderLevel() const {
  return z_order_level_;
}

void NativeWidgetMac::SetVisibleOnAllWorkspaces(bool always_visible) {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetVisibleOnAllSpaces(always_visible);
}

bool NativeWidgetMac::IsVisibleOnAllWorkspaces() const {
  return false;
}

void NativeWidgetMac::Maximize() {
  NOTIMPLEMENTED();  // See IsMaximized().
}

void NativeWidgetMac::Minimize() {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetMiniaturized(true);
}

bool NativeWidgetMac::IsMaximized() const {
  // The window frame isn't altered on Mac unless going fullscreen. The green
  // "+" button just makes the window bigger. So, always false.
  return false;
}

bool NativeWidgetMac::IsMinimized() const {
  if (!ns_window_host_)
    return false;
  return ns_window_host_->IsMiniaturized();
}

void NativeWidgetMac::Restore() {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetFullscreen(false);
  GetNSWindowMojo()->SetMiniaturized(false);
}

void NativeWidgetMac::SetFullscreen(bool fullscreen) {
  if (!ns_window_host_)
    return;
  ns_window_host_->SetFullscreen(fullscreen);
}

bool NativeWidgetMac::IsFullscreen() const {
  return ns_window_host_ && ns_window_host_->target_fullscreen_state();
}

void NativeWidgetMac::SetCanAppearInExistingFullscreenSpaces(
    bool can_appear_in_existing_fullscreen_spaces) {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetCanAppearInExistingFullscreenSpaces(
      can_appear_in_existing_fullscreen_spaces);
}

void NativeWidgetMac::SetOpacity(float opacity) {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetOpacity(opacity);
}

void NativeWidgetMac::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->SetContentAspectRatio(aspect_ratio);
}

void NativeWidgetMac::FlashFrame(bool flash_frame) {
  NOTIMPLEMENTED();
}

void NativeWidgetMac::RunShellDrag(View* view,
                                   std::unique_ptr<ui::OSExchangeData> data,
                                   const gfx::Point& location,
                                   int operation,
                                   ui::mojom::DragEventSource source) {
  ns_window_host_->drag_drop_client()->StartDragAndDrop(view, std::move(data),
                                                        operation, source);
}

void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
  // |rect| is relative to client area of the window.
  NSWindow* window = GetNativeWindow().GetNativeNSWindow();
  NSRect client_rect = [window contentRectForFrameRect:[window frame]];
  NSRect target_rect = rect.ToCGRect();

  // Convert to Appkit coordinate system (origin at bottom left).
  target_rect.origin.y =
      NSHeight(client_rect) - target_rect.origin.y - NSHeight(target_rect);
  [GetNativeView().GetNativeNSView() setNeedsDisplayInRect:target_rect];
  if (ns_window_host_ && ns_window_host_->layer())
    ns_window_host_->layer()->SchedulePaint(rect);
}

void NativeWidgetMac::ScheduleLayout() {
  ui::Compositor* compositor = GetCompositor();
  if (compositor)
    compositor->ScheduleDraw();
}

void NativeWidgetMac::SetCursor(gfx::NativeCursor cursor) {
  if (GetInProcessNSWindowBridge())
    GetInProcessNSWindowBridge()->SetCursor(cursor);
}

void NativeWidgetMac::ShowEmojiPanel() {
  // We must plumb the call to ui::ShowEmojiPanel() over the bridge so that it
  // is called from the correct process.
  if (GetNSWindowMojo())
    GetNSWindowMojo()->ShowEmojiPanel();
}

bool NativeWidgetMac::IsMouseEventsEnabled() const {
  // On platforms with touch, mouse events get disabled and calls to this method
  // can affect hover states. Since there is no touch on desktop Mac, this is
  // always true. Touch on Mac is tracked in http://crbug.com/445520.
  return true;
}

bool NativeWidgetMac::IsMouseButtonDown() const {
  return [NSEvent pressedMouseButtons] != 0;
}

void NativeWidgetMac::ClearNativeFocus() {
  // To quote DesktopWindowTreeHostX11, "This method is weird and misnamed."
  // The goal is to set focus to the content window, thereby removing focus from
  // any NSView in the window that doesn't belong to toolkit-views.
  if (!GetNSWindowMojo())
    return;
  GetNSWindowMojo()->MakeFirstResponder();
}

gfx::Rect NativeWidgetMac::GetWorkAreaBoundsInScreen() const {
  return ns_window_host_ ? ns_window_host_->GetCurrentDisplay().work_area()
                         : gfx::Rect();
}

Widget::MoveLoopResult NativeWidgetMac::RunMoveLoop(
    const gfx::Vector2d& drag_offset,
    Widget::MoveLoopSource source,
    Widget::MoveLoopEscapeBehavior escape_behavior) {
  if (!GetInProcessNSWindowBridge())
    return Widget::MOVE_LOOP_CANCELED;

  ReleaseCapture();
  return GetInProcessNSWindowBridge()->RunMoveLoop(drag_offset)
             ? Widget::MOVE_LOOP_SUCCESSFUL
             : Widget::MOVE_LOOP_CANCELED;
}

void NativeWidgetMac::EndMoveLoop() {
  if (GetInProcessNSWindowBridge())
    GetInProcessNSWindowBridge()->EndMoveLoop();
}

void NativeWidgetMac::SetVisibilityChangedAnimationsEnabled(bool value) {
  if (GetNSWindowMojo())
    GetNSWindowMojo()->SetAnimationEnabled(value);
}

void NativeWidgetMac::SetVisibilityAnimationDuration(
    const base::TimeDelta& duration) {
  NOTIMPLEMENTED();
}

void NativeWidgetMac::SetVisibilityAnimationTransition(
    Widget::VisibilityTransition widget_transitions) {
  remote_cocoa::mojom::VisibilityTransition transitions =
      remote_cocoa::mojom::VisibilityTransition::kNone;
  switch (widget_transitions) {
    case Widget::ANIMATE_NONE:
      transitions = remote_cocoa::mojom::VisibilityTransition::kNone;
      break;
    case Widget::ANIMATE_SHOW:
      transitions = remote_cocoa::mojom::VisibilityTransition::kShow;
      break;
    case Widget::ANIMATE_HIDE:
      transitions = remote_cocoa::mojom::VisibilityTransition::kHide;
      break;
    case Widget::ANIMATE_BOTH:
      transitions = remote_cocoa::mojom::VisibilityTransition::kBoth;
      break;
  }
  if (GetNSWindowMojo())
    GetNSWindowMojo()->SetTransitionsToAnimate(transitions);
}

bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
  return false;
}

ui::GestureRecognizer* NativeWidgetMac::GetGestureRecognizer() {
  static base::NoDestructor<ui::GestureRecognizerImplMac> recognizer;
  return recognizer.get();
}

void NativeWidgetMac::OnSizeConstraintsChanged() {
  Widget* widget = GetWidget();
  GetNSWindowMojo()->SetSizeConstraints(
      widget->GetMinimumSize(), widget->GetMaximumSize(),
      widget->widget_delegate()->CanResize(),
      widget->widget_delegate()->CanMaximize());
}

void NativeWidgetMac::OnNativeViewHierarchyWillChange() {
  // If this is not top-level, then the FocusManager may change, so remove our
  // listeners.
  if (!GetWidget()->is_top_level())
    SetFocusManager(nullptr);
  parent_key_lock_.reset();
}

void NativeWidgetMac::OnNativeViewHierarchyChanged() {
  if (!GetWidget()->is_top_level())
    SetFocusManager(GetWidget()->GetFocusManager());
}

std::string NativeWidgetMac::GetName() const {
  return name_;
}

// static
void NativeWidgetMac::SetInitNativeWidgetCallback(
    base::RepeatingCallback<void(NativeWidgetMac*)> callback) {
  DCHECK(!g_init_native_widget_callback || callback.is_null());
  if (callback.is_null()) {
    if (g_init_native_widget_callback) {
      delete g_init_native_widget_callback;
      g_init_native_widget_callback = nullptr;
    }
    return;
  }
  g_init_native_widget_callback =
      new base::RepeatingCallback<void(NativeWidgetMac*)>(std::move(callback));
}

NativeWidgetMacNSWindow* NativeWidgetMac::CreateNSWindow(
    const remote_cocoa::mojom::CreateWindowParams* params) {
  return remote_cocoa::NativeWidgetNSWindowBridge::CreateNSWindow(params)
      .autorelease();
}

remote_cocoa::ApplicationHost*
NativeWidgetMac::GetRemoteCocoaApplicationHost() {
  return nullptr;
}

remote_cocoa::mojom::NativeWidgetNSWindow* NativeWidgetMac::GetNSWindowMojo()
    const {
  return ns_window_host_ ? ns_window_host_->GetNSWindowMojo() : nullptr;
}

remote_cocoa::NativeWidgetNSWindowBridge*
NativeWidgetMac::GetInProcessNSWindowBridge() const {
  return ns_window_host_ ? ns_window_host_->GetInProcessNSWindowBridge()
                         : nullptr;
}

void NativeWidgetMac::SetFocusManager(FocusManager* new_focus_manager) {
  if (focus_manager_) {
    if (View* old_focus = focus_manager_->GetFocusedView())
      OnDidChangeFocus(old_focus, nullptr);
    focus_manager_->RemoveFocusChangeListener(this);
    if (zoom_focus_monitor_)
      focus_manager_->RemoveFocusChangeListener(zoom_focus_monitor_.get());
  }
  focus_manager_ = new_focus_manager;
  if (focus_manager_) {
    if (View* new_focus = focus_manager_->GetFocusedView())
      OnDidChangeFocus(nullptr, new_focus);
    focus_manager_->AddFocusChangeListener(this);
    if (zoom_focus_monitor_)
      focus_manager_->AddFocusChangeListener(zoom_focus_monitor_.get());
  }
}

void NativeWidgetMac::OnWillChangeFocus(View* focused_before,
                                        View* focused_now) {}

void NativeWidgetMac::OnDidChangeFocus(View* focused_before,
                                       View* focused_now) {
  ui::InputMethod* input_method = GetWidget()->GetInputMethod();
  if (!input_method)
    return;

  ui::TextInputClient* new_text_input_client =
      input_method->GetTextInputClient();
  // Sanity check: When focus moves away from the widget (i.e. |focused_now|
  // is nil), then the textInputClient will be cleared.
  DCHECK(!!focused_now || !new_text_input_client);
  if (ns_window_host_) {
    ns_window_host_->text_input_host()->SetTextInputClient(
        new_text_input_client);
  }
}

ui::EventDispatchDetails NativeWidgetMac::DispatchKeyEventPostIME(
    ui::KeyEvent* key) {
  DCHECK(focus_manager_);
  if (!focus_manager_->OnKeyEvent(*key))
    key->StopPropagation();
  else
    GetWidget()->OnKeyEvent(key);
  return ui::EventDispatchDetails();
}

////////////////////////////////////////////////////////////////////////////////
// Widget:

// static
void Widget::CloseAllSecondaryWidgets() {
  NSArray* starting_windows = [NSApp windows];  // Creates an autoreleased copy.
  for (NSWindow* window in starting_windows) {
    // Ignore any windows that couldn't have been created by NativeWidgetMac or
    // a subclass. GetNativeWidgetForNativeWindow() will later interrogate the
    // NSWindow delegate, but we can't trust that delegate to be a valid object.
    if (![window isKindOfClass:[NativeWidgetMacNSWindow class]])
      continue;

    // Record a crash key to detect when client code may destroy a
    // WidgetObserver without removing it (possibly leaking the Widget).
    // A crash can occur in generic Widget teardown paths when trying to notify.
    // See http://crbug.com/808318.
    static crash_reporter::CrashKeyString<256> window_info_key("windowInfo");
    std::string value = base::SysNSStringToUTF8(
        [NSString stringWithFormat:@"Closing %@ (%@)", [window title],
                                   [window className]]);
    crash_reporter::ScopedCrashKeyString scopedWindowKey(&window_info_key,
                                                         value);

    Widget* widget = GetWidgetForNativeWindow(window);
    if (widget && widget->is_secondary_widget())
      [window close];
  }
}

const ui::NativeTheme* Widget::GetNativeTheme() const {
  return ui::NativeTheme::GetInstanceForNativeUi();
}

namespace internal {

////////////////////////////////////////////////////////////////////////////////
// internal::NativeWidgetPrivate:

// static
NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
    internal::NativeWidgetDelegate* delegate) {
  return new NativeWidgetMac(delegate);
}

// static
NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
    gfx::NativeView native_view) {
  return GetNativeWidgetForNativeWindow([native_view.GetNativeNSView() window]);
}

// static
NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
    gfx::NativeWindow window) {
  if (NativeWidgetMacNSWindowHost* ns_window_host_impl =
          NativeWidgetMacNSWindowHost::GetFromNativeWindow(window)) {
    return ns_window_host_impl->native_widget_mac();
  }
  return nullptr;  // Not created by NativeWidgetMac.
}

// static
NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
    gfx::NativeView native_view) {
  NativeWidgetMacNSWindowHost* window_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
  if (!window_host)
    return nullptr;
  while (window_host->parent())
    window_host = window_host->parent();
  return window_host->native_widget_mac();
}

// static
void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
                                             Widget::Widgets* children) {
  NativeWidgetMacNSWindowHost* window_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
  if (!window_host) {
    NSView* ns_view = native_view.GetNativeNSView();
    // The NSWindow is not itself a views::Widget, but it may have children that
    // are. Support returning Widgets that are parented to the NSWindow, except:
    // - Ignore requests for children of an NSView that is not a contentView.
    // - We do not add a Widget for |native_view| to |children| (there is none).
    if ([[ns_view window] contentView] != ns_view)
      return;

    // Collect -sheets and -childWindows. A window should never appear in both,
    // since that causes AppKit to glitch.
    NSArray* sheet_children = [[ns_view window] sheets];
    for (NSWindow* native_child in sheet_children)
      GetAllChildWidgets([native_child contentView], children);

    for (NSWindow* native_child in [[ns_view window] childWindows]) {
      DCHECK(![sheet_children containsObject:native_child]);
      GetAllChildWidgets([native_child contentView], children);
    }
    return;
  }

  // If |native_view| is a subview of the contentView, it will share an
  // NSWindow, but will itself be a native child of the Widget. That is, adding
  // window_host->..->GetWidget() to |children| would be adding the _parent_ of
  // |native_view|, not the Widget for |native_view|. |native_view| doesn't have
  // a corresponding Widget of its own in this case (and so can't have Widget
  // children of its own on Mac).
  if (window_host->native_widget_mac()->GetNativeView() != native_view)
    return;

  // Code expects widget for |native_view| to be added to |children|.
  if (window_host->native_widget_mac()->GetWidget())
    children->insert(window_host->native_widget_mac()->GetWidget());

  // When the NSWindow *is* a Widget, only consider children(). I.e. do not
  // look through -[NSWindow childWindows] as done for the (!window_host) case
  // above. -childWindows does not support hidden windows, and anything in there
  // which is not in children() would have been added by AppKit.
  for (NativeWidgetMacNSWindowHost* child : window_host->children())
    GetAllChildWidgets(child->native_widget_mac()->GetNativeView(), children);
}

// static
void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
                                             Widget::Widgets* owned) {
  NativeWidgetMacNSWindowHost* window_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
  if (!window_host) {
    GetAllChildWidgets(native_view, owned);
    return;
  }
  if (window_host->native_widget_mac()->GetNativeView() != native_view)
    return;
  for (NativeWidgetMacNSWindowHost* child : window_host->children())
    GetAllChildWidgets(child->native_widget_mac()->GetNativeView(), owned);
}

// static
void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView child,
                                             gfx::NativeView new_parent) {
  DCHECK_NE(child, new_parent);
  DCHECK([new_parent.GetNativeNSView() window]);
  if (!new_parent ||
      [child.GetNativeNSView() superview] == new_parent.GetNativeNSView()) {
    NOTREACHED();
    return;
  }

  NativeWidgetMacNSWindowHost* child_window_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(child);
  DCHECK(child_window_host);
  gfx::NativeView widget_view =
      child_window_host->native_widget_mac()->GetNativeView();
  DCHECK_EQ(child, widget_view);
  gfx::NativeWindow widget_window =
      child_window_host->native_widget_mac()->GetNativeWindow();
  DCHECK(
      [child.GetNativeNSView() isDescendantOf:widget_view.GetNativeNSView()]);
  DCHECK(widget_window && ![widget_window.GetNativeNSWindow() isSheet]);

  NativeWidgetMacNSWindowHost* parent_window_host =
      NativeWidgetMacNSWindowHost::GetFromNativeView(new_parent);

  // Early out for no-op changes.
  if (child == widget_view &&
      child_window_host->parent() == parent_window_host) {
    return;
  }

  // First notify all the widgets that they are being disassociated from their
  // previous parent.
  Widget::Widgets widgets;
  GetAllChildWidgets(child, &widgets);
  for (auto* widget : widgets)
    widget->NotifyNativeViewHierarchyWillChange();

  child_window_host->SetParent(parent_window_host);

  // And now, notify them that they have a brand new parent.
  for (auto* widget : widgets)
    widget->NotifyNativeViewHierarchyChanged();
}

// static
gfx::NativeView NativeWidgetPrivate::GetGlobalCapture(
    gfx::NativeView native_view) {
  return NativeWidgetMacNSWindowHost::GetGlobalCaptureView();
}

}  // namespace internal
}  // namespace views
