1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/base/win/hwnd_subclass.h"
6
7 #include "base/basictypes.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/gfx/win/window_impl.h"
10
11 namespace ui {
12
13 namespace {
14
15 class TestWindow : public gfx::WindowImpl {
16 public:
TestWindow()17 TestWindow() : saw_message(false) {}
~TestWindow()18 virtual ~TestWindow() {}
19
20 bool saw_message;
21
22 private:
23 // Overridden from gfx::WindowImpl:
ProcessWindowMessage(HWND window,UINT message,WPARAM w_param,LPARAM l_param,LRESULT & result,DWORD msg_map_id)24 virtual BOOL ProcessWindowMessage(HWND window,
25 UINT message,
26 WPARAM w_param,
27 LPARAM l_param,
28 LRESULT& result,
29 DWORD msg_map_id) OVERRIDE {
30 if (message == WM_NCHITTEST)
31 saw_message = true;
32
33 return FALSE; // Results in DefWindowProc().
34 }
35
36 DISALLOW_COPY_AND_ASSIGN(TestWindow);
37 };
38
39 class TestMessageFilter : public HWNDMessageFilter {
40 public:
TestMessageFilter()41 TestMessageFilter() : consume_messages(false), saw_message(false) {}
~TestMessageFilter()42 virtual ~TestMessageFilter() {}
43
44 // Setting to true causes the filter subclass to stop messages from reaching
45 // the subclassed window procedure.
46 bool consume_messages;
47
48 // True if the message filter saw the message.
49 bool saw_message;
50
51 private:
52 // Overridden from HWNDMessageFilter:
FilterMessage(HWND hwnd,UINT message,WPARAM w_param,LPARAM l_param,LRESULT * l_result)53 virtual bool FilterMessage(HWND hwnd,
54 UINT message,
55 WPARAM w_param,
56 LPARAM l_param,
57 LRESULT* l_result) OVERRIDE {
58 if (message == WM_NCHITTEST) {
59 saw_message = true;
60 return consume_messages;
61 }
62 return false;
63 }
64
65 DISALLOW_COPY_AND_ASSIGN(TestMessageFilter);
66 };
67
68 } // namespace
69
TEST(HWNDSubclassTest,Filtering)70 TEST(HWNDSubclassTest, Filtering) {
71 TestWindow window;
72 window.Init(NULL, gfx::Rect(0, 0, 100, 100));
73 EXPECT_TRUE(window.hwnd() != NULL);
74
75 {
76 TestMessageFilter mf;
77 HWNDSubclass::AddFilterToTarget(window.hwnd(), &mf);
78
79 // We are not filtering, so both the filter and the window should receive
80 // this message:
81 ::SendMessage(window.hwnd(), WM_NCHITTEST, 0, 0);
82
83 EXPECT_TRUE(mf.saw_message);
84 EXPECT_TRUE(window.saw_message);
85
86 mf.saw_message = false;
87 window.saw_message = false;
88
89 mf.consume_messages = true;
90
91 // We are now filtering, so only the filter should see this message:
92 ::SendMessage(window.hwnd(), WM_NCHITTEST, 0, 0);
93
94 EXPECT_TRUE(mf.saw_message);
95 EXPECT_FALSE(window.saw_message);
96 }
97 }
98
TEST(HWNDSubclassTest,FilteringMultipleFilters)99 TEST(HWNDSubclassTest, FilteringMultipleFilters) {
100 TestWindow window;
101 window.Init(NULL, gfx::Rect(0, 0, 100, 100));
102 EXPECT_TRUE(window.hwnd() != NULL);
103
104 {
105 TestMessageFilter mf1;
106 TestMessageFilter mf2;
107 HWNDSubclass::AddFilterToTarget(window.hwnd(), &mf1);
108 HWNDSubclass::AddFilterToTarget(window.hwnd(), &mf2);
109
110 // We are not filtering, so both the filter and the window should receive
111 // this message:
112 ::SendMessage(window.hwnd(), WM_NCHITTEST, 0, 0);
113
114 EXPECT_TRUE(mf1.saw_message);
115 EXPECT_TRUE(mf2.saw_message);
116 EXPECT_TRUE(window.saw_message);
117
118 mf1.saw_message = false;
119 mf2.saw_message = false;
120 window.saw_message = false;
121
122 mf1.consume_messages = true;
123
124 // We are now filtering, so only the filter |mf1| should see this message:
125 ::SendMessage(window.hwnd(), WM_NCHITTEST, 0, 0);
126
127 EXPECT_TRUE(mf1.saw_message);
128 EXPECT_FALSE(mf2.saw_message);
129 EXPECT_FALSE(window.saw_message);
130 }
131 }
132
TEST(HWNDSubclassTest,RemoveFilter)133 TEST(HWNDSubclassTest, RemoveFilter) {
134 TestWindow window;
135 window.Init(NULL, gfx::Rect(0, 0, 100, 100));
136 EXPECT_TRUE(window.hwnd() != NULL);
137
138 {
139 TestMessageFilter mf1;
140 TestMessageFilter mf2;
141 HWNDSubclass::AddFilterToTarget(window.hwnd(), &mf1);
142 HWNDSubclass::AddFilterToTarget(window.hwnd(), &mf2);
143
144 ::SendMessage(window.hwnd(), WM_NCHITTEST, 0, 0);
145 EXPECT_TRUE(mf1.saw_message);
146 EXPECT_TRUE(mf2.saw_message);
147 EXPECT_TRUE(window.saw_message);
148
149 mf1.saw_message = false;
150 mf2.saw_message = false;
151 window.saw_message = false;
152
153 // Remove a filter and try sending message again.
154 HWNDSubclass::RemoveFilterFromAllTargets(&mf1);
155 ::SendMessage(window.hwnd(), WM_NCHITTEST, 0, 0);
156 EXPECT_FALSE(mf1.saw_message);
157 EXPECT_TRUE(mf2.saw_message);
158 EXPECT_TRUE(window.saw_message);
159 }
160 }
161
162 } // namespace ui
163