blob: 5e4b79d98d7a5c66e42bdc8b64572b04ee473087 [file] [log] [blame]
// 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