// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gl/child_window_win.h"

#include "base/compiler_specific.h"
#include "base/debug/alias.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/win/wrapped_window_proc.h"
#include "ui/gfx/win/hwnd_util.h"
#include "ui/gfx/win/window_impl.h"

namespace gl {

namespace {

ATOM g_window_class;

// This runs on the window owner thread.
void InitializeWindowClass() {
  if (g_window_class)
    return;

  WNDCLASSEX intermediate_class;
  base::win::InitializeWindowClass(
      L"Intermediate D3D Window",
      &base::win::WrappedWindowProc<::DefWindowProc>, CS_OWNDC, 0, 0, nullptr,
      reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), nullptr, nullptr,
      nullptr, &intermediate_class);
  g_window_class = RegisterClassEx(&intermediate_class);
  if (!g_window_class) {
    LOG(ERROR) << "RegisterClass failed.";
    return;
  }
}

// Hidden popup window  used as a parent for the child surface window.
// Must be created and destroyed on the thread.
class HiddenPopupWindow : public gfx::WindowImpl {
 public:
  static HWND Create() {
    gfx::WindowImpl* window = new HiddenPopupWindow;

    window->set_window_style(WS_POPUP);
    window->set_window_ex_style(WS_EX_TOOLWINDOW);
    window->Init(GetDesktopWindow(), gfx::Rect());
    EnableWindow(window->hwnd(), FALSE);
    // The |window| instance is now owned by the window user data.
    DCHECK_EQ(window, gfx::GetWindowUserData(window->hwnd()));
    return window->hwnd();
  }

  static void Destroy(HWND window) {
    // This uses the fact that the window user data contains a pointer
    // to gfx::WindowImpl instance.
    gfx::WindowImpl* window_data =
        reinterpret_cast<gfx::WindowImpl*>(gfx::GetWindowUserData(window));
    DCHECK_EQ(window, window_data->hwnd());
    DestroyWindow(window);
    delete window_data;
  }

 private:
  // Explicitly do nothing in Close. We do this as some external apps may get a
  // handle to this window and attempt to close it.
  void OnClose() {}

  CR_BEGIN_MSG_MAP_EX(HiddenPopupWindow)
    CR_MSG_WM_CLOSE(OnClose)
  CR_END_MSG_MAP()

  CR_MSG_MAP_CLASS_DECLARATIONS(HiddenPopupWindow)
};

// This runs on the window owner thread.
void CreateWindowsOnThread(base::WaitableEvent* event,
                           HWND* child_window,
                           HWND* parent_window) {
  InitializeWindowClass();
  DCHECK(g_window_class);

  // Create hidden parent window on the current thread.
  *parent_window = HiddenPopupWindow::Create();
  // Create child window.
  // WS_EX_NOPARENTNOTIFY and WS_EX_LAYERED make the window transparent for
  // input. WS_EX_NOREDIRECTIONBITMAP avoids allocating a
  // bitmap that would otherwise be allocated with WS_EX_LAYERED, the bitmap is
  // only necessary if using Gdi objects with the window.
  // Using a size of 1x1 is fine because the window will be subsequently resized
  // using SetWindowPos whenever the parent window size changes.
  const HWND window = CreateWindowEx(
      WS_EX_NOPARENTNOTIFY | WS_EX_LAYERED | WS_EX_TRANSPARENT |
          WS_EX_NOREDIRECTIONBITMAP,
      reinterpret_cast<wchar_t*>(g_window_class), L"",
      WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0, /*width*/ 1,
      /*height*/ 1, *parent_window, nullptr, nullptr, nullptr);
  if (!window) {
    logging::SystemErrorCode error = logging::GetLastSystemErrorCode();
    base::debug::Alias(&error);
    CHECK(false);
  }
  *child_window = window;
  event->Signal();
}

// This runs on the window owner thread.
void DestroyWindowsOnThread(HWND child_window, HWND hidden_popup_window) {
  DestroyWindow(child_window);
  HiddenPopupWindow::Destroy(hidden_popup_window);
}

#if DCHECK_IS_ON()
base::ThreadChecker& GetThreadChecker() {
  static base::ThreadChecker thread_checker;
  return thread_checker;
}
#endif

}  // namespace

class ChildWindowWin::ChildWindowThread
    : public base::RefCounted<ChildWindowThread> {
 public:
  // Returns the singleton instance of the thread.
  static scoped_refptr<ChildWindowThread> GetInstance() {
    DCHECK_CALLED_ON_VALID_THREAD(GetThreadChecker());
    static base::WeakPtr<ChildWindowThread> weak_instance;

    auto instance = base::WrapRefCounted(weak_instance.get());
    if (!instance) {
      instance = base::WrapRefCounted(new ChildWindowThread);
      weak_instance = instance->weak_ptr_factory_.GetWeakPtr();
    }

    return instance;
  }

  scoped_refptr<base::TaskRunner> task_runner() {
    DCHECK_CALLED_ON_VALID_THREAD(GetThreadChecker());
    return thread_.task_runner();
  }

 private:
  friend class base::RefCounted<ChildWindowThread>;

  ChildWindowThread() : thread_("Window owner thread") {
    DCHECK_CALLED_ON_VALID_THREAD(GetThreadChecker());
    base::Thread::Options options(base::MessagePumpType::UI, 0);
    thread_.StartWithOptions(std::move(options));
  }

  ~ChildWindowThread() {
    DCHECK_CALLED_ON_VALID_THREAD(GetThreadChecker());
    thread_.Stop();
  }

  base::Thread thread_;
  base::WeakPtrFactory<ChildWindowThread> weak_ptr_factory_{this};
};

ChildWindowWin::ChildWindowWin() = default;

void ChildWindowWin::Initialize() {
  if (window_)
    return;

  thread_ = ChildWindowThread::GetInstance();

  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                            base::WaitableEvent::InitialState::NOT_SIGNALED);

  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CreateWindowsOnThread, &event, &window_,
                                &initial_parent_window_));
  event.Wait();
}

ChildWindowWin::~ChildWindowWin() {
  if (thread_) {
    scoped_refptr<base::TaskRunner> task_runner = thread_->task_runner();
    task_runner->PostTaskAndReply(
        FROM_HERE,
        base::BindOnce(&DestroyWindowsOnThread, window_,
                       initial_parent_window_),
        base::DoNothingWithBoundArgs(std::move(thread_)));
  }
}

bool ChildWindowWin::Resize(const gfx::Size& size) {
  // Force a resize and redraw (but not a move, activate, etc.).
  constexpr UINT kFlags = SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE |
                          SWP_NOOWNERZORDER | SWP_NOREDRAW |
                          SWP_NOSENDCHANGING | SWP_NOZORDER;
  return SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(),
                      kFlags);
}

scoped_refptr<base::TaskRunner> ChildWindowWin::GetTaskRunnerForTesting() {
  DCHECK(thread_);
  return thread_->task_runner();
}

}  // namespace gl
