910e62b5创建于 1月15日历史提交
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <algorithm>
#include <memory>

#include "base/containers/contains.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/ime/mock_input_method.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/win/hwnd_message_handler.h"
#include "ui/views/win/hwnd_message_handler_delegate.h"

namespace views {

namespace {

class TestHWNDMessageHandlerDelegate : public HWNDMessageHandlerDelegate {
 public:
  TestHWNDMessageHandlerDelegate() {
    mock_input_method_ = std::make_unique<ui::MockInputMethod>(nullptr);
  }
  TestHWNDMessageHandlerDelegate(const TestHWNDMessageHandlerDelegate&) =
      delete;
  TestHWNDMessageHandlerDelegate& operator=(
      const TestHWNDMessageHandlerDelegate&) = delete;
  ~TestHWNDMessageHandlerDelegate() override = default;

  // HWNDMessageHandlerDelegate:
  ui::InputMethod* GetHWNDMessageDelegateInputMethod() override {
    return mock_input_method_.get();
  }
  bool HasNonClientView() const override { return false; }
  FrameMode GetFrameMode() const override { return FrameMode::SYSTEM_DRAWN; }
  bool HasFrame() const override { return false; }
  bool ShouldPaintAsActive() const override { return false; }
  void SchedulePaint() override {}
  bool CanResize() const override { return false; }
  bool CanMaximize() const override { return false; }
  bool CanMinimize() const override { return false; }
  bool CanActivate() const override { return false; }
  bool WidgetSizeIsClientSize() const override { return false; }
  bool IsModal() const override { return false; }
  int GetInitialShowState() const override { return SW_SHOWNORMAL; }
  int GetNonClientComponent(const gfx::Point& point) const override {
    return HTNOWHERE;
  }
  void GetWindowMask(const gfx::Size& size_px, SkPath* mask) override {}
  bool GetClientAreaInsets(gfx::Insets* insets,
                           int frame_thickness) const override {
    return false;
  }
  bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override {
    return false;
  }
  void GetMinMaxSize(gfx::Size* min_size, gfx::Size* max_size) const override {}
  gfx::Size GetRootViewSize() const override { return gfx::Size(); }
  gfx::Size DIPToScreenSize(const gfx::Size& dip_size) const override {
    return dip_size;
  }
  void ResetWindowControls() override {}
  gfx::NativeViewAccessible GetNativeViewAccessible() override {
    return nullptr;
  }
  gfx::NativeViewAccessible GetParentNativeViewAccessible() override {
    return nullptr;
  }
  void HandleActivationChanged(bool active) override {}
  bool HandleAppCommand(int command) override { return false; }
  void HandleCancelMode() override {}
  void HandleCaptureLost() override {}
  void HandleClose() override {}
  bool HandleCommand(int command) override { return false; }
  void HandleAccelerator(const ui::Accelerator& accelerator) override {}
  void HandleCreate() override {}
  void HandleDestroying() override {}
  void HandleDestroyed() override {}
  bool HandleInitialFocus(ui::mojom::WindowShowState show_state) override {
    return false;
  }
  void HandleDisplayChange() override {}
  void HandleBeginWMSizeMove() override {}
  void HandleEndWMSizeMove() override {}
  void HandleBeginUserResize() override {}
  void HandleEndUserResize() override {}
  void HandleMove() override {}
  void HandleWorkAreaChanged() override {}
  void HandleVisibilityChanged(bool visible) override {}
  void HandleWindowMinimizedOrRestored(bool restored) override {}
  void HandleClientSizeChanged(const gfx::Size& new_size) override {}
  void HandleFrameChanged() override {}
  void HandleNativeFocus(HWND last_focused_window) override {}
  void HandleNativeBlur(HWND focused_window) override {}
  bool HandleMouseEvent(ui::MouseEvent* event) override { return false; }
  void HandleKeyEvent(ui::KeyEvent* event) override {}
  void HandleTouchEvent(ui::TouchEvent* event) override {}
  bool HandleIMEMessage(UINT message,
                        WPARAM w_param,
                        LPARAM l_param,
                        LRESULT* result) override {
    return false;
  }
  void HandleInputLanguageChange(DWORD character_set,
                                 HKL input_language_id) override {}
  void HandlePaintAccelerated(const gfx::Rect& invalid_rect) override {}
  void HandleMenuLoop(bool in_menu_loop) override {}
  bool PreHandleMSG(UINT message,
                    WPARAM w_param,
                    LPARAM l_param,
                    LRESULT* result) override {
    return false;
  }
  void PostHandleMSG(UINT message, WPARAM w_param, LPARAM l_param) override {}
  bool HandleScrollEvent(ui::ScrollEvent* event) override { return false; }
  bool HandleGestureEvent(ui::GestureEvent* event) override { return false; }
  void HandleWindowSizeChanging() override {}
  void HandleWindowSizeUnchanged() override {}
  void HandleWindowScaleFactorChanged(float window_scale_factor) override {}
  void HandleHeadlessWindowBoundsChanged(const gfx::Rect& bounds) override {}
  HBRUSH GetBackgroundPaintBrush() override { return nullptr; }

 private:
  std::unique_ptr<ui::MockInputMethod> mock_input_method_;
};

}  // namespace

using HWNDMessageHandlerTest = test::DesktopWidgetTestInteractive;

TEST_F(HWNDMessageHandlerTest, Init) {
  TestHWNDMessageHandlerDelegate delegate;
  std::unique_ptr<HWNDMessageHandler> handler(
      HWNDMessageHandler::Create(&delegate, "test"));
  ASSERT_TRUE(handler);
  handler->Init(nullptr, gfx::Rect(0, 0, 100, 100));
  ASSERT_TRUE(handler->hwnd());
}

TEST_F(HWNDMessageHandlerTest, GetOwnedWindows) {
  TestHWNDMessageHandlerDelegate parent_delegate;
  std::unique_ptr<HWNDMessageHandler> parent_handler(
      HWNDMessageHandler::Create(&parent_delegate, "parent"));
  ASSERT_TRUE(parent_handler);
  parent_handler->Init(nullptr, gfx::Rect(0, 0, 200, 200));
  ASSERT_TRUE(parent_handler->hwnd());

  TestHWNDMessageHandlerDelegate child_delegate;
  std::unique_ptr<HWNDMessageHandler> child_handler(
      HWNDMessageHandler::Create(&child_delegate, "child"));
  ASSERT_TRUE(child_handler);
  child_handler->set_window_style(WS_POPUP);
  child_handler->Init(parent_handler->hwnd(), gfx::Rect(0, 0, 100, 100));
  ASSERT_TRUE(child_handler->hwnd());

  std::vector<HWND> owned_windows = parent_handler->GetOwnedWindows();
  ASSERT_EQ(1u, owned_windows.size());
  EXPECT_TRUE(base::Contains(owned_windows, child_handler->hwnd()));

  child_handler->CloseNow();
  parent_handler->CloseNow();
}

TEST_F(HWNDMessageHandlerTest, GetOwnedWindows_Depth3) {
  TestHWNDMessageHandlerDelegate grandparent_delegate;
  std::unique_ptr<HWNDMessageHandler> grandparent_handler(
      HWNDMessageHandler::Create(&grandparent_delegate, "grandparent"));
  ASSERT_TRUE(grandparent_handler);
  grandparent_handler->Init(nullptr, gfx::Rect(0, 0, 300, 300));
  ASSERT_TRUE(grandparent_handler->hwnd());

  TestHWNDMessageHandlerDelegate parent1_delegate;
  std::unique_ptr<HWNDMessageHandler> parent1_handler(
      HWNDMessageHandler::Create(&parent1_delegate, "parent1"));
  ASSERT_TRUE(parent1_handler);
  parent1_handler->set_window_style(WS_POPUP);
  parent1_handler->Init(grandparent_handler->hwnd(), gfx::Rect(0, 0, 200, 200));
  ASSERT_TRUE(parent1_handler->hwnd());

  TestHWNDMessageHandlerDelegate parent2_delegate;
  std::unique_ptr<HWNDMessageHandler> parent2_handler(
      HWNDMessageHandler::Create(&parent2_delegate, "parent2"));
  ASSERT_TRUE(parent2_handler);
  parent2_handler->set_window_style(WS_POPUP);
  parent2_handler->Init(grandparent_handler->hwnd(), gfx::Rect(0, 0, 50, 50));
  ASSERT_TRUE(parent2_handler->hwnd());

  TestHWNDMessageHandlerDelegate child_delegate;
  std::unique_ptr<HWNDMessageHandler> child_handler(
      HWNDMessageHandler::Create(&child_delegate, "child"));
  ASSERT_TRUE(child_handler);
  child_handler->set_window_style(WS_POPUP);
  child_handler->Init(parent1_handler->hwnd(), gfx::Rect(0, 0, 100, 100));
  ASSERT_TRUE(child_handler->hwnd());

  std::vector<HWND> owned_windows = grandparent_handler->GetOwnedWindows();
  ASSERT_EQ(3u, owned_windows.size());
  EXPECT_TRUE(base::Contains(owned_windows, parent1_handler->hwnd()));
  EXPECT_TRUE(base::Contains(owned_windows, parent2_handler->hwnd()));
  EXPECT_TRUE(base::Contains(owned_windows, child_handler->hwnd()));

  child_handler->CloseNow();
  parent2_handler->CloseNow();
  parent1_handler->CloseNow();
  grandparent_handler->CloseNow();
}

}  // namespace views