• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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