Home | History | Annotate | Download | only in win
      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:
     17   TestWindow() : saw_message(false) {}
     18   virtual ~TestWindow() {}
     19 
     20   bool saw_message;
     21 
     22  private:
     23    // Overridden from gfx::WindowImpl:
     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:
     41   TestMessageFilter() : consume_messages(false), saw_message(false) {}
     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:
     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 
     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 
     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 
    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