// Copyright (c) 2015 The Chromium Embedded Framework 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 "tests/cefclient/browser/osr_window_win.h"

#include <windowsx.h>
#if defined(CEF_USE_ATL)
#include <oleacc.h>
#endif

#include "include/base/cef_build.h"
#include "tests/cefclient/browser/main_context.h"
#include "tests/cefclient/browser/osr_accessibility_helper.h"
#include "tests/cefclient/browser/osr_accessibility_node.h"
#include "tests/cefclient/browser/osr_ime_handler_win.h"
#include "tests/cefclient/browser/osr_render_handler_win_d3d11.h"
#include "tests/cefclient/browser/osr_render_handler_win_gl.h"
#include "tests/cefclient/browser/resource.h"
#include "tests/shared/browser/geometry_util.h"
#include "tests/shared/browser/main_message_loop.h"
#include "tests/shared/browser/util_win.h"

namespace client {

namespace {

const wchar_t kWndClass[] = L"Client_OsrWindow";

// Helper funtion to check if it is Windows8 or greater.
// https://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx
inline BOOL IsWindows_8_Or_Newer() {
  OSVERSIONINFOEX osvi = {0};
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  osvi.dwMajorVersion = 6;
  osvi.dwMinorVersion = 2;
  DWORDLONG dwlConditionMask = 0;
  VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
  VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
  return ::VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION,
                             dwlConditionMask);
}

// Helper function to detect mouse messages coming from emulation of touch
// events. These should be ignored.
bool IsMouseEventFromTouch(UINT message) {
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
  return (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) &&
         (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) ==
             MOUSEEVENTF_FROMTOUCH;
}

class CreateBrowserHelper {
 public:
  CreateBrowserHelper(HWND hwnd,
                      const RECT& rect,
                      CefRefPtr<CefClient> handler,
                      const std::string& url,
                      const CefBrowserSettings& settings,
                      CefRefPtr<CefDictionaryValue> extra_info,
                      CefRefPtr<CefRequestContext> request_context,
                      OsrWindowWin* osr_window_win)
      : hwnd_(hwnd),
        rect_(rect),
        handler_(handler),
        url_(url),
        settings_(settings),
        extra_info_(extra_info),
        request_context_(request_context),
        osr_window_win_(osr_window_win) {}

  HWND hwnd_;
  RECT rect_;
  CefRefPtr<CefClient> handler_;
  std::string url_;
  CefBrowserSettings settings_;
  CefRefPtr<CefDictionaryValue> extra_info_;
  CefRefPtr<CefRequestContext> request_context_;
  OsrWindowWin* osr_window_win_;
};

}  // namespace

OsrWindowWin::OsrWindowWin(Delegate* delegate,
                           const OsrRendererSettings& settings)
    : delegate_(delegate),
      settings_(settings),
      hwnd_(NULL),
      device_scale_factor_(0),
      hidden_(false),
      last_mouse_pos_(),
      current_mouse_pos_(),
      mouse_rotation_(false),
      mouse_tracking_(false),
      last_click_x_(0),
      last_click_y_(0),
      last_click_button_(MBT_LEFT),
      last_click_count_(1),
      last_click_time_(0),
      last_mouse_down_on_view_(false) {
  DCHECK(delegate_);
  client_rect_ = {0};
}

OsrWindowWin::~OsrWindowWin() {
  CEF_REQUIRE_UI_THREAD();
  // The native window should have already been destroyed.
  DCHECK(!hwnd_ && !render_handler_.get());
}

void CreateBrowserWithHelper(CreateBrowserHelper* helper) {
  helper->osr_window_win_->CreateBrowser(
      helper->hwnd_, helper->rect_, helper->handler_, helper->settings_,
      helper->extra_info_, helper->request_context_, helper->url_);
  delete helper;
}

void OsrWindowWin::CreateBrowser(HWND parent_hwnd,
                                 const RECT& rect,
                                 CefRefPtr<CefClient> handler,
                                 const CefBrowserSettings& settings,
                                 CefRefPtr<CefDictionaryValue> extra_info,
                                 CefRefPtr<CefRequestContext> request_context,
                                 const std::string& startup_url) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CreateBrowserHelper* helper =
        new CreateBrowserHelper(parent_hwnd, rect, handler, startup_url,
                                settings, extra_info, request_context, this);
    CefPostTask(TID_UI, base::Bind(CreateBrowserWithHelper, helper));
    return;
  }

  // Create the native window.
  Create(parent_hwnd, rect);

  CefWindowInfo window_info;
  window_info.SetAsWindowless(hwnd_);

  if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
    // Don't activate the browser window on creation.
    window_info.ex_style |= WS_EX_NOACTIVATE;
  }

  window_info.shared_texture_enabled = settings_.shared_texture_enabled;
  window_info.external_begin_frame_enabled =
      settings_.external_begin_frame_enabled;

  // Create the browser asynchronously.
  CefBrowserHost::CreateBrowser(window_info, handler, startup_url, settings,
                                extra_info, request_context);
}

void OsrWindowWin::ShowPopup(HWND parent_hwnd,
                             int x,
                             int y,
                             size_t width,
                             size_t height) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::ShowPopup, this, parent_hwnd,
                                   x, y, width, height));
    return;
  }

  DCHECK(browser_.get());

  // Create the native window.
  const RECT rect = {x, y, x + static_cast<int>(width),
                     y + static_cast<int>(height)};
  Create(parent_hwnd, rect);

  // Create the render handler.
  EnsureRenderHandler();
  render_handler_->SetBrowser(browser_);

  // Send resize notification so the compositor is assigned the correct
  // viewport size and begins rendering.
  browser_->GetHost()->WasResized();

  Show();
}

void OsrWindowWin::Show() {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Show, this));
    return;
  }

  if (!browser_)
    return;

  // Show the native window if not currently visible.
  if (hwnd_ && !::IsWindowVisible(hwnd_))
    ShowWindow(hwnd_, SW_SHOW);

  if (hidden_) {
    // Set the browser as visible.
    browser_->GetHost()->WasHidden(false);
    hidden_ = false;
  }

  // Give focus to the browser.
  browser_->GetHost()->SendFocusEvent(true);
}

void OsrWindowWin::Hide() {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Hide, this));
    return;
  }

  if (!browser_)
    return;

  // Remove focus from the browser.
  browser_->GetHost()->SendFocusEvent(false);

  if (!hidden_) {
    // Set the browser as hidden.
    browser_->GetHost()->WasHidden(true);
    hidden_ = true;
  }
}

void OsrWindowWin::SetBounds(int x, int y, size_t width, size_t height) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetBounds, this, x, y, width,
                                   height));
    return;
  }

  if (hwnd_) {
    // Set the browser window bounds.
    ::SetWindowPos(hwnd_, NULL, x, y, static_cast<int>(width),
                   static_cast<int>(height), SWP_NOZORDER);
  }
}

void OsrWindowWin::SetFocus() {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetFocus, this));
    return;
  }

  if (hwnd_) {
    // Give focus to the native window.
    ::SetFocus(hwnd_);
  }
}

void OsrWindowWin::SetDeviceScaleFactor(float device_scale_factor) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute this method on the UI thread.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::SetDeviceScaleFactor, this,
                                   device_scale_factor));
    return;
  }

  if (device_scale_factor == device_scale_factor_)
    return;

  device_scale_factor_ = device_scale_factor;
  if (browser_) {
    browser_->GetHost()->NotifyScreenInfoChanged();
    browser_->GetHost()->WasResized();
  }
}

void OsrWindowWin::Create(HWND parent_hwnd, const RECT& rect) {
  CEF_REQUIRE_UI_THREAD();
  DCHECK(!hwnd_ && !render_handler_.get());
  DCHECK(parent_hwnd);
  DCHECK(!::IsRectEmpty(&rect));

  HINSTANCE hInst = ::GetModuleHandle(NULL);

  const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
  const HBRUSH background_brush = CreateSolidBrush(
      RGB(CefColorGetR(background_color), CefColorGetG(background_color),
          CefColorGetB(background_color)));

  RegisterOsrClass(hInst, background_brush);

  DWORD ex_style = 0;
  if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
    // Don't activate the browser window on creation.
    ex_style |= WS_EX_NOACTIVATE;
  }

  // Create the native window with a border so it's easier to visually identify
  // OSR windows.
  hwnd_ = ::CreateWindowEx(
      ex_style, kWndClass, 0,
      WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
      rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
      parent_hwnd, 0, hInst, 0);
  CHECK(hwnd_);

  client_rect_ = rect;

  // Associate |this| with the window.
  SetUserDataPtr(hwnd_, this);

#if defined(CEF_USE_ATL)
  accessibility_root_ = nullptr;

  // Create/register the drag&drop handler.
  drop_target_ = DropTargetWin::Create(this, hwnd_);
  HRESULT register_res = RegisterDragDrop(hwnd_, drop_target_);
  DCHECK_EQ(register_res, S_OK);
#endif

  ime_handler_.reset(new OsrImeHandlerWin(hwnd_));

  // Enable Touch Events if requested
  if (client::MainContext::Get()->TouchEventsEnabled())
    RegisterTouchWindow(hwnd_, 0);

  // Notify the window owner.
  NotifyNativeWindowCreated(hwnd_);
}

void OsrWindowWin::Destroy() {
  CEF_REQUIRE_UI_THREAD();
  DCHECK(hwnd_ != NULL);

#if defined(CEF_USE_ATL)
  // Revoke/delete the drag&drop handler.
  RevokeDragDrop(hwnd_);
  drop_target_ = nullptr;
#endif

  render_handler_.reset();

  // Destroy the native window.
  ::DestroyWindow(hwnd_);
  ime_handler_.reset();
  hwnd_ = NULL;
}

void OsrWindowWin::NotifyNativeWindowCreated(HWND hwnd) {
  if (!CURRENTLY_ON_MAIN_THREAD()) {
    // Execute this method on the main thread.
    MAIN_POST_CLOSURE(
        base::Bind(&OsrWindowWin::NotifyNativeWindowCreated, this, hwnd));
    return;
  }

  delegate_->OnOsrNativeWindowCreated(hwnd);
}

// static
void OsrWindowWin::RegisterOsrClass(HINSTANCE hInstance,
                                    HBRUSH background_brush) {
  // Only register the class one time.
  static bool class_registered = false;
  if (class_registered)
    return;
  class_registered = true;

  WNDCLASSEX wcex;

  wcex.cbSize = sizeof(WNDCLASSEX);
  wcex.style = CS_OWNDC;
  wcex.lpfnWndProc = OsrWndProc;
  wcex.cbClsExtra = 0;
  wcex.cbWndExtra = 0;
  wcex.hInstance = hInstance;
  wcex.hIcon = NULL;
  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = background_brush;
  wcex.lpszMenuName = NULL;
  wcex.lpszClassName = kWndClass;
  wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

  RegisterClassEx(&wcex);
}

void OsrWindowWin::OnIMESetContext(UINT message, WPARAM wParam, LPARAM lParam) {
  // We handle the IME Composition Window ourselves (but let the IME Candidates
  // Window be handled by IME through DefWindowProc()), so clear the
  // ISC_SHOWUICOMPOSITIONWINDOW flag:
  lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
  ::DefWindowProc(hwnd_, message, wParam, lParam);

  // Create Caret Window if required
  if (ime_handler_) {
    ime_handler_->CreateImeWindow();
    ime_handler_->MoveImeWindow();
  }
}

void OsrWindowWin::OnIMEStartComposition() {
  if (ime_handler_) {
    ime_handler_->CreateImeWindow();
    ime_handler_->MoveImeWindow();
    ime_handler_->ResetComposition();
  }
}

void OsrWindowWin::OnIMEComposition(UINT message,
                                    WPARAM wParam,
                                    LPARAM lParam) {
  if (browser_ && ime_handler_) {
    CefString cTextStr;
    if (ime_handler_->GetResult(lParam, cTextStr)) {
      // Send the text to the browser. The |replacement_range| and
      // |relative_cursor_pos| params are not used on Windows, so provide
      // default invalid values.
      browser_->GetHost()->ImeCommitText(cTextStr,
                                         CefRange(UINT32_MAX, UINT32_MAX), 0);
      ime_handler_->ResetComposition();
      // Continue reading the composition string - Japanese IMEs send both
      // GCS_RESULTSTR and GCS_COMPSTR.
    }

    std::vector<CefCompositionUnderline> underlines;
    int composition_start = 0;

    if (ime_handler_->GetComposition(lParam, cTextStr, underlines,
                                     composition_start)) {
      // Send the composition string to the browser. The |replacement_range|
      // param is not used on Windows, so provide a default invalid value.
      browser_->GetHost()->ImeSetComposition(
          cTextStr, underlines, CefRange(UINT32_MAX, UINT32_MAX),
          CefRange(composition_start,
                   static_cast<int>(composition_start + cTextStr.length())));

      // Update the Candidate Window position. The cursor is at the end so
      // subtract 1. This is safe because IMM32 does not support non-zero-width
      // in a composition. Also,  negative values are safely ignored in
      // MoveImeWindow
      ime_handler_->UpdateCaretPosition(composition_start - 1);
    } else {
      OnIMECancelCompositionEvent();
    }
  }
}

void OsrWindowWin::OnIMECancelCompositionEvent() {
  if (browser_ && ime_handler_) {
    browser_->GetHost()->ImeCancelComposition();
    ime_handler_->ResetComposition();
    ime_handler_->DestroyImeWindow();
  }
}

// static
LRESULT CALLBACK OsrWindowWin::OsrWndProc(HWND hWnd,
                                          UINT message,
                                          WPARAM wParam,
                                          LPARAM lParam) {
  CEF_REQUIRE_UI_THREAD();

  OsrWindowWin* self = GetUserDataPtr<OsrWindowWin*>(hWnd);
  if (!self)
    return DefWindowProc(hWnd, message, wParam, lParam);

  // We want to handle IME events before the OS does any default handling.
  switch (message) {
    case WM_IME_SETCONTEXT:
      self->OnIMESetContext(message, wParam, lParam);
      return 0;
    case WM_IME_STARTCOMPOSITION:
      self->OnIMEStartComposition();
      return 0;
    case WM_IME_COMPOSITION:
      self->OnIMEComposition(message, wParam, lParam);
      return 0;
    case WM_IME_ENDCOMPOSITION:
      self->OnIMECancelCompositionEvent();
      // Let WTL call::DefWindowProc() and release its resources.
      break;
#if defined(CEF_USE_ATL)
    case WM_GETOBJECT: {
      // Only the lower 32 bits of lParam are valid when checking the object id
      // because it sometimes gets sign-extended incorrectly (but not always).
      DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(lParam));

      // Accessibility readers will send an OBJID_CLIENT message.
      if (static_cast<DWORD>(OBJID_CLIENT) == obj_id) {
        if (self->accessibility_root_) {
          return LresultFromObject(
              IID_IAccessible, wParam,
              static_cast<IAccessible*>(self->accessibility_root_));
        } else {
          // Notify the renderer to enable accessibility.
          if (self->browser_ && self->browser_->GetHost())
            self->browser_->GetHost()->SetAccessibilityState(STATE_ENABLED);
        }
      }
    } break;
#endif
    case WM_LBUTTONDOWN:
    case WM_RBUTTONDOWN:
    case WM_MBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MBUTTONUP:
    case WM_MOUSEMOVE:
    case WM_MOUSELEAVE:
    case WM_MOUSEWHEEL:
      self->OnMouseEvent(message, wParam, lParam);
      break;

    case WM_SIZE:
      self->OnSize();
      break;

    case WM_SETFOCUS:
    case WM_KILLFOCUS:
      self->OnFocus(message == WM_SETFOCUS);
      break;

    case WM_CAPTURECHANGED:
    case WM_CANCELMODE:
      self->OnCaptureLost();
      break;

    case WM_SYSCHAR:
    case WM_SYSKEYDOWN:
    case WM_SYSKEYUP:
    case WM_KEYDOWN:
    case WM_KEYUP:
    case WM_CHAR:
      self->OnKeyEvent(message, wParam, lParam);
      break;

    case WM_PAINT:
      self->OnPaint();
      return 0;

    case WM_ERASEBKGND:
      if (self->OnEraseBkgnd())
        break;
      // Don't erase the background.
      return 0;

    // If your application does not require Win7 support, please do consider
    // using WM_POINTER* messages instead of WM_TOUCH. WM_POINTER are more
    // intutive, complete and simpler to code.
    // https://msdn.microsoft.com/en-us/library/hh454903(v=vs.85).aspx
    case WM_TOUCH:
      if (self->OnTouchEvent(message, wParam, lParam))
        return 0;
      break;

    case WM_NCDESTROY:
      // Clear the reference to |self|.
      SetUserDataPtr(hWnd, NULL);
      self->hwnd_ = NULL;
      break;
  }

  return DefWindowProc(hWnd, message, wParam, lParam);
}

void OsrWindowWin::OnMouseEvent(UINT message, WPARAM wParam, LPARAM lParam) {
  if (IsMouseEventFromTouch(message))
    return;

  CefRefPtr<CefBrowserHost> browser_host;
  if (browser_)
    browser_host = browser_->GetHost();

  LONG currentTime = 0;
  bool cancelPreviousClick = false;

  if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ||
      message == WM_MBUTTONDOWN || message == WM_MOUSEMOVE ||
      message == WM_MOUSELEAVE) {
    currentTime = GetMessageTime();
    int x = GET_X_LPARAM(lParam);
    int y = GET_Y_LPARAM(lParam);
    cancelPreviousClick =
        (abs(last_click_x_ - x) > (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) ||
        (abs(last_click_y_ - y) > (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) ||
        ((currentTime - last_click_time_) > GetDoubleClickTime());
    if (cancelPreviousClick &&
        (message == WM_MOUSEMOVE || message == WM_MOUSELEAVE)) {
      last_click_count_ = 1;
      last_click_x_ = 0;
      last_click_y_ = 0;
      last_click_time_ = 0;
    }
  }

  switch (message) {
    case WM_LBUTTONDOWN:
    case WM_RBUTTONDOWN:
    case WM_MBUTTONDOWN: {
      ::SetCapture(hwnd_);
      ::SetFocus(hwnd_);
      int x = GET_X_LPARAM(lParam);
      int y = GET_Y_LPARAM(lParam);
      if (wParam & MK_SHIFT) {
        // Start rotation effect.
        last_mouse_pos_.x = current_mouse_pos_.x = x;
        last_mouse_pos_.y = current_mouse_pos_.y = y;
        mouse_rotation_ = true;
      } else {
        CefBrowserHost::MouseButtonType btnType =
            (message == WM_LBUTTONDOWN
                 ? MBT_LEFT
                 : (message == WM_RBUTTONDOWN ? MBT_RIGHT : MBT_MIDDLE));
        if (!cancelPreviousClick && (btnType == last_click_button_)) {
          ++last_click_count_;
        } else {
          last_click_count_ = 1;
          last_click_x_ = x;
          last_click_y_ = y;
        }
        last_click_time_ = currentTime;
        last_click_button_ = btnType;

        if (browser_host) {
          CefMouseEvent mouse_event;
          mouse_event.x = x;
          mouse_event.y = y;
          last_mouse_down_on_view_ = !IsOverPopupWidget(x, y);
          ApplyPopupOffset(mouse_event.x, mouse_event.y);
          DeviceToLogical(mouse_event, device_scale_factor_);
          mouse_event.modifiers = GetCefMouseModifiers(wParam);
          browser_host->SendMouseClickEvent(mouse_event, btnType, false,
                                            last_click_count_);
        }
      }
    } break;

    case WM_LBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MBUTTONUP:
      if (GetCapture() == hwnd_)
        ReleaseCapture();
      if (mouse_rotation_) {
        // End rotation effect.
        mouse_rotation_ = false;
        render_handler_->SetSpin(0, 0);
      } else {
        int x = GET_X_LPARAM(lParam);
        int y = GET_Y_LPARAM(lParam);
        CefBrowserHost::MouseButtonType btnType =
            (message == WM_LBUTTONUP
                 ? MBT_LEFT
                 : (message == WM_RBUTTONUP ? MBT_RIGHT : MBT_MIDDLE));
        if (browser_host) {
          CefMouseEvent mouse_event;
          mouse_event.x = x;
          mouse_event.y = y;
          if (last_mouse_down_on_view_ && IsOverPopupWidget(x, y) &&
              (GetPopupXOffset() || GetPopupYOffset())) {
            break;
          }
          ApplyPopupOffset(mouse_event.x, mouse_event.y);
          DeviceToLogical(mouse_event, device_scale_factor_);
          mouse_event.modifiers = GetCefMouseModifiers(wParam);
          browser_host->SendMouseClickEvent(mouse_event, btnType, true,
                                            last_click_count_);
        }
      }
      break;

    case WM_MOUSEMOVE: {
      int x = GET_X_LPARAM(lParam);
      int y = GET_Y_LPARAM(lParam);
      if (mouse_rotation_) {
        // Apply rotation effect.
        current_mouse_pos_.x = x;
        current_mouse_pos_.y = y;
        render_handler_->IncrementSpin(
            current_mouse_pos_.x - last_mouse_pos_.x,
            current_mouse_pos_.y - last_mouse_pos_.y);
        last_mouse_pos_.x = current_mouse_pos_.x;
        last_mouse_pos_.y = current_mouse_pos_.y;
      } else {
        if (!mouse_tracking_) {
          // Start tracking mouse leave. Required for the WM_MOUSELEAVE event to
          // be generated.
          TRACKMOUSEEVENT tme;
          tme.cbSize = sizeof(TRACKMOUSEEVENT);
          tme.dwFlags = TME_LEAVE;
          tme.hwndTrack = hwnd_;
          TrackMouseEvent(&tme);
          mouse_tracking_ = true;
        }

        if (browser_host) {
          CefMouseEvent mouse_event;
          mouse_event.x = x;
          mouse_event.y = y;
          ApplyPopupOffset(mouse_event.x, mouse_event.y);
          DeviceToLogical(mouse_event, device_scale_factor_);
          mouse_event.modifiers = GetCefMouseModifiers(wParam);
          browser_host->SendMouseMoveEvent(mouse_event, false);
        }
      }
      break;
    }

    case WM_MOUSELEAVE: {
      if (mouse_tracking_) {
        // Stop tracking mouse leave.
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE & TME_CANCEL;
        tme.hwndTrack = hwnd_;
        TrackMouseEvent(&tme);
        mouse_tracking_ = false;
      }

      if (browser_host) {
        // Determine the cursor position in screen coordinates.
        POINT p;
        ::GetCursorPos(&p);
        ::ScreenToClient(hwnd_, &p);

        CefMouseEvent mouse_event;
        mouse_event.x = p.x;
        mouse_event.y = p.y;
        DeviceToLogical(mouse_event, device_scale_factor_);
        mouse_event.modifiers = GetCefMouseModifiers(wParam);
        browser_host->SendMouseMoveEvent(mouse_event, true);
      }
    } break;

    case WM_MOUSEWHEEL:
      if (browser_host) {
        POINT screen_point = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
        HWND scrolled_wnd = ::WindowFromPoint(screen_point);
        if (scrolled_wnd != hwnd_)
          break;

        ScreenToClient(hwnd_, &screen_point);
        int delta = GET_WHEEL_DELTA_WPARAM(wParam);

        CefMouseEvent mouse_event;
        mouse_event.x = screen_point.x;
        mouse_event.y = screen_point.y;
        ApplyPopupOffset(mouse_event.x, mouse_event.y);
        DeviceToLogical(mouse_event, device_scale_factor_);
        mouse_event.modifiers = GetCefMouseModifiers(wParam);
        browser_host->SendMouseWheelEvent(mouse_event,
                                          IsKeyDown(VK_SHIFT) ? delta : 0,
                                          !IsKeyDown(VK_SHIFT) ? delta : 0);
      }
      break;
  }
}

void OsrWindowWin::OnSize() {
  // Keep |client_rect_| up to date.
  ::GetClientRect(hwnd_, &client_rect_);

  if (browser_)
    browser_->GetHost()->WasResized();
}

void OsrWindowWin::OnFocus(bool setFocus) {
  if (browser_)
    browser_->GetHost()->SendFocusEvent(setFocus);
}

void OsrWindowWin::OnCaptureLost() {
  if (mouse_rotation_)
    return;

  if (browser_)
    browser_->GetHost()->SendCaptureLostEvent();
}

void OsrWindowWin::OnKeyEvent(UINT message, WPARAM wParam, LPARAM lParam) {
  if (!browser_)
    return;

  CefKeyEvent event;
  event.windows_key_code = wParam;
  event.native_key_code = lParam;
  event.is_system_key = message == WM_SYSCHAR || message == WM_SYSKEYDOWN ||
                        message == WM_SYSKEYUP;

  if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
    event.type = KEYEVENT_RAWKEYDOWN;
  else if (message == WM_KEYUP || message == WM_SYSKEYUP)
    event.type = KEYEVENT_KEYUP;
  else
    event.type = KEYEVENT_CHAR;
  event.modifiers = GetCefKeyboardModifiers(wParam, lParam);

  // mimic alt-gr check behaviour from
  // src/ui/events/win/events_win_utils.cc: GetModifiersFromKeyState
  if ((event.type == KEYEVENT_CHAR) && IsKeyDown(VK_RMENU)) {
    // reverse AltGr detection taken from PlatformKeyMap::UsesAltGraph
    // instead of checking all combination for ctrl-alt, just check current char
    HKL current_layout = ::GetKeyboardLayout(0);

    // https://docs.microsoft.com/en-gb/windows/win32/api/winuser/nf-winuser-vkkeyscanexw
    // ... high-order byte contains the shift state,
    // which can be a combination of the following flag bits.
    // 2 Either CTRL key is pressed.
    // 4 Either ALT key is pressed.
    SHORT scan_res = ::VkKeyScanExW(wParam, current_layout);
    if (((scan_res >> 8) & 0xFF) == (2 | 4)) {  // ctrl-alt pressed
      event.modifiers &= ~(EVENTFLAG_CONTROL_DOWN | EVENTFLAG_ALT_DOWN);
      event.modifiers |= EVENTFLAG_ALTGR_DOWN;
    }
  }

  browser_->GetHost()->SendKeyEvent(event);
}

void OsrWindowWin::OnPaint() {
  // Paint nothing here. Invalidate will cause OnPaint to be called for the
  // render handler.
  PAINTSTRUCT ps;
  BeginPaint(hwnd_, &ps);
  EndPaint(hwnd_, &ps);

  if (browser_)
    browser_->GetHost()->Invalidate(PET_VIEW);
}

bool OsrWindowWin::OnEraseBkgnd() {
  // Erase the background when the browser does not exist.
  return (browser_ == nullptr);
}

bool OsrWindowWin::OnTouchEvent(UINT message, WPARAM wParam, LPARAM lParam) {
  // Handle touch events on Windows.
  int num_points = LOWORD(wParam);
  // Chromium only supports upto 16 touch points.
  if (num_points < 0 || num_points > 16)
    return false;
  std::unique_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
  if (GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(lParam), num_points,
                        input.get(), sizeof(TOUCHINPUT))) {
    CefTouchEvent touch_event;
    for (int i = 0; i < num_points; ++i) {
      POINT point;
      point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
      point.y = TOUCH_COORD_TO_PIXEL(input[i].y);

      if (!IsWindows_8_Or_Newer()) {
        // Windows 7 sends touch events for touches in the non-client area,
        // whereas Windows 8 does not. In order to unify the behaviour, always
        // ignore touch events in the non-client area.
        LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
        LRESULT hittest = SendMessage(hwnd_, WM_NCHITTEST, 0, l_param_ht);
        if (hittest != HTCLIENT)
          return false;
      }

      ScreenToClient(hwnd_, &point);
      touch_event.x = DeviceToLogical(point.x, device_scale_factor_);
      touch_event.y = DeviceToLogical(point.y, device_scale_factor_);

      // Touch point identifier stays consistent in a touch contact sequence
      touch_event.id = input[i].dwID;

      if (input[i].dwFlags & TOUCHEVENTF_DOWN) {
        touch_event.type = CEF_TET_PRESSED;
      } else if (input[i].dwFlags & TOUCHEVENTF_MOVE) {
        touch_event.type = CEF_TET_MOVED;
      } else if (input[i].dwFlags & TOUCHEVENTF_UP) {
        touch_event.type = CEF_TET_RELEASED;
      }

      touch_event.radius_x = 0;
      touch_event.radius_y = 0;
      touch_event.rotation_angle = 0;
      touch_event.pressure = 0;
      touch_event.modifiers = 0;

      // Notify the browser of touch event
      if (browser_)
        browser_->GetHost()->SendTouchEvent(touch_event);
    }
    CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(lParam));
    return true;
  }

  return false;
}

bool OsrWindowWin::IsOverPopupWidget(int x, int y) const {
  if (!render_handler_)
    return false;
  return render_handler_->IsOverPopupWidget(x, y);
}

int OsrWindowWin::GetPopupXOffset() const {
  return render_handler_->GetPopupXOffset();
}

int OsrWindowWin::GetPopupYOffset() const {
  return render_handler_->GetPopupYOffset();
}

void OsrWindowWin::ApplyPopupOffset(int& x, int& y) const {
  if (IsOverPopupWidget(x, y)) {
    x += GetPopupXOffset();
    y += GetPopupYOffset();
  }
}

void OsrWindowWin::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();
  DCHECK(!browser_);
  browser_ = browser;

  if (hwnd_) {
    // The native window will already exist for non-popup browsers.
    EnsureRenderHandler();
    render_handler_->SetBrowser(browser);
  }

  if (hwnd_) {
    // Show the browser window. Called asynchronously so that the browser has
    // time to create associated internal objects.
    CefPostTask(TID_UI, base::Bind(&OsrWindowWin::Show, this));
  }
}

void OsrWindowWin::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
  CEF_REQUIRE_UI_THREAD();
  // Detach |this| from the ClientHandlerOsr.
  static_cast<ClientHandlerOsr*>(browser_->GetHost()->GetClient().get())
      ->DetachOsrDelegate();
  browser_ = nullptr;
  render_handler_->SetBrowser(nullptr);
  Destroy();
}

bool OsrWindowWin::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
                                     CefRect& rect) {
  CEF_REQUIRE_UI_THREAD();
  return false;
}

void OsrWindowWin::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
  CEF_REQUIRE_UI_THREAD();
  DCHECK_GT(device_scale_factor_, 0);

  rect.x = rect.y = 0;
  rect.width = DeviceToLogical(client_rect_.right - client_rect_.left,
                               device_scale_factor_);
  if (rect.width == 0)
    rect.width = 1;
  rect.height = DeviceToLogical(client_rect_.bottom - client_rect_.top,
                                device_scale_factor_);
  if (rect.height == 0)
    rect.height = 1;
}

bool OsrWindowWin::GetScreenPoint(CefRefPtr<CefBrowser> browser,
                                  int viewX,
                                  int viewY,
                                  int& screenX,
                                  int& screenY) {
  CEF_REQUIRE_UI_THREAD();
  DCHECK_GT(device_scale_factor_, 0);

  if (!::IsWindow(hwnd_))
    return false;

  // Convert the point from view coordinates to actual screen coordinates.
  POINT screen_pt = {LogicalToDevice(viewX, device_scale_factor_),
                     LogicalToDevice(viewY, device_scale_factor_)};
  ClientToScreen(hwnd_, &screen_pt);
  screenX = screen_pt.x;
  screenY = screen_pt.y;
  return true;
}

bool OsrWindowWin::GetScreenInfo(CefRefPtr<CefBrowser> browser,
                                 CefScreenInfo& screen_info) {
  CEF_REQUIRE_UI_THREAD();
  DCHECK_GT(device_scale_factor_, 0);

  if (!::IsWindow(hwnd_))
    return false;

  CefRect view_rect;
  GetViewRect(browser, view_rect);

  screen_info.device_scale_factor = device_scale_factor_;

  // The screen info rectangles are used by the renderer to create and position
  // popups. Keep popups inside the view rectangle.
  screen_info.rect = view_rect;
  screen_info.available_rect = view_rect;
  return true;
}

void OsrWindowWin::OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) {
  render_handler_->OnPopupShow(browser, show);
}

void OsrWindowWin::OnPopupSize(CefRefPtr<CefBrowser> browser,
                               const CefRect& rect) {
  render_handler_->OnPopupSize(browser,
                               LogicalToDevice(rect, device_scale_factor_));
}

void OsrWindowWin::OnPaint(CefRefPtr<CefBrowser> browser,
                           CefRenderHandler::PaintElementType type,
                           const CefRenderHandler::RectList& dirtyRects,
                           const void* buffer,
                           int width,
                           int height) {
  EnsureRenderHandler();
  render_handler_->OnPaint(browser, type, dirtyRects, buffer, width, height);
}

void OsrWindowWin::OnAcceleratedPaint(
    CefRefPtr<CefBrowser> browser,
    CefRenderHandler::PaintElementType type,
    const CefRenderHandler::RectList& dirtyRects,
    void* share_handle) {
  EnsureRenderHandler();
  render_handler_->OnAcceleratedPaint(browser, type, dirtyRects, share_handle);
}

void OsrWindowWin::OnCursorChange(CefRefPtr<CefBrowser> browser,
                                  CefCursorHandle cursor,
                                  CefRenderHandler::CursorType type,
                                  const CefCursorInfo& custom_cursor_info) {
  CEF_REQUIRE_UI_THREAD();

  if (!::IsWindow(hwnd_))
    return;

  // Change the plugin window's cursor.
  SetClassLongPtr(hwnd_, GCLP_HCURSOR,
                  static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor)));
  SetCursor(cursor);
}

bool OsrWindowWin::StartDragging(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefDragData> drag_data,
    CefRenderHandler::DragOperationsMask allowed_ops,
    int x,
    int y) {
  CEF_REQUIRE_UI_THREAD();

#if defined(CEF_USE_ATL)
  if (!drop_target_)
    return false;

  current_drag_op_ = DRAG_OPERATION_NONE;
  CefBrowserHost::DragOperationsMask result =
      drop_target_->StartDragging(browser, drag_data, allowed_ops, x, y);
  current_drag_op_ = DRAG_OPERATION_NONE;
  POINT pt = {};
  GetCursorPos(&pt);
  ScreenToClient(hwnd_, &pt);

  browser->GetHost()->DragSourceEndedAt(
      DeviceToLogical(pt.x, device_scale_factor_),
      DeviceToLogical(pt.y, device_scale_factor_), result);
  browser->GetHost()->DragSourceSystemDragEnded();
  return true;
#else
  // Cancel the drag. The dragging implementation requires ATL support.
  return false;
#endif
}

void OsrWindowWin::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
                                    CefRenderHandler::DragOperation operation) {
  CEF_REQUIRE_UI_THREAD();

#if defined(CEF_USE_ATL)
  current_drag_op_ = operation;
#endif
}

void OsrWindowWin::OnImeCompositionRangeChanged(
    CefRefPtr<CefBrowser> browser,
    const CefRange& selection_range,
    const CefRenderHandler::RectList& character_bounds) {
  CEF_REQUIRE_UI_THREAD();

  if (ime_handler_) {
    // Convert from view coordinates to device coordinates.
    CefRenderHandler::RectList device_bounds;
    CefRenderHandler::RectList::const_iterator it = character_bounds.begin();
    for (; it != character_bounds.end(); ++it) {
      device_bounds.push_back(LogicalToDevice(*it, device_scale_factor_));
    }

    ime_handler_->ChangeCompositionRange(selection_range, device_bounds);
  }
}

void OsrWindowWin::UpdateAccessibilityTree(CefRefPtr<CefValue> value) {
  CEF_REQUIRE_UI_THREAD();

#if defined(CEF_USE_ATL)
  if (!accessibility_handler_) {
    accessibility_handler_.reset(new OsrAccessibilityHelper(value, browser_));
  } else {
    accessibility_handler_->UpdateAccessibilityTree(value);
  }

  // Update |accessibility_root_| because UpdateAccessibilityTree may have
  // cleared it.
  OsrAXNode* root = accessibility_handler_->GetRootNode();
  accessibility_root_ =
      root ? root->GetNativeAccessibleObject(nullptr) : nullptr;
#endif  // defined(CEF_USE_ATL)
}

void OsrWindowWin::UpdateAccessibilityLocation(CefRefPtr<CefValue> value) {
  CEF_REQUIRE_UI_THREAD();

#if defined(CEF_USE_ATL)
  if (accessibility_handler_) {
    accessibility_handler_->UpdateAccessibilityLocation(value);
  }
#endif  // defined(CEF_USE_ATL)
}

#if defined(CEF_USE_ATL)

CefBrowserHost::DragOperationsMask OsrWindowWin::OnDragEnter(
    CefRefPtr<CefDragData> drag_data,
    CefMouseEvent ev,
    CefBrowserHost::DragOperationsMask effect) {
  if (browser_) {
    DeviceToLogical(ev, device_scale_factor_);
    browser_->GetHost()->DragTargetDragEnter(drag_data, ev, effect);
    browser_->GetHost()->DragTargetDragOver(ev, effect);
  }
  return current_drag_op_;
}

CefBrowserHost::DragOperationsMask OsrWindowWin::OnDragOver(
    CefMouseEvent ev,
    CefBrowserHost::DragOperationsMask effect) {
  if (browser_) {
    DeviceToLogical(ev, device_scale_factor_);
    browser_->GetHost()->DragTargetDragOver(ev, effect);
  }
  return current_drag_op_;
}

void OsrWindowWin::OnDragLeave() {
  if (browser_)
    browser_->GetHost()->DragTargetDragLeave();
}

CefBrowserHost::DragOperationsMask OsrWindowWin::OnDrop(
    CefMouseEvent ev,
    CefBrowserHost::DragOperationsMask effect) {
  if (browser_) {
    DeviceToLogical(ev, device_scale_factor_);
    browser_->GetHost()->DragTargetDragOver(ev, effect);
    browser_->GetHost()->DragTargetDrop(ev);
  }
  return current_drag_op_;
}

#endif  // defined(CEF_USE_ATL)

void OsrWindowWin::EnsureRenderHandler() {
  CEF_REQUIRE_UI_THREAD();
  if (!render_handler_) {
    if (settings_.shared_texture_enabled) {
      // Try to initialize D3D11 rendering.
      auto render_handler = new OsrRenderHandlerWinD3D11(settings_, hwnd_);
      if (render_handler->Initialize(browser_,
                                     client_rect_.right - client_rect_.left,
                                     client_rect_.bottom - client_rect_.top)) {
        render_handler_.reset(render_handler);
      } else {
        LOG(ERROR) << "Failed to initialize D3D11 rendering.";
        delete render_handler;
      }
    }

    // Fall back to GL rendering.
    if (!render_handler_) {
      auto render_handler = new OsrRenderHandlerWinGL(settings_, hwnd_);
      render_handler->Initialize(browser_);
      render_handler_.reset(render_handler);
    }
  }
}

}  // namespace client
