15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/win/hwnd_subclass.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/win/dpi.h" 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/win/hwnd_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHWNDSubclassKey[] = "__UI_BASE_WIN_HWND_SUBCLASS_PROC__"; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LRESULT CALLBACK WndProc(HWND hwnd, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT message, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM w_param, 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPARAM l_param) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::HWNDSubclass* wrapped_wnd_proc = 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<ui::HWNDSubclass*>( 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ViewProp::GetValue(hwnd, kHWNDSubclassKey)); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wrapped_wnd_proc ? wrapped_wnd_proc->OnWndProc(hwnd, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) w_param, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l_param) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : DefWindowProc(hwnd, message, w_param, l_param); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WNDPROC GetCurrentWndProc(HWND target) { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return reinterpret_cast<WNDPROC>(GetWindowLongPtr(target, GWLP_WNDPROC)); 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Not defined before Win7 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BOOL GetTouchInputInfoWrapper(HTOUCHINPUT handle, UINT count, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PTOUCHINPUT pointer, int size) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef BOOL(WINAPI *GetTouchInputInfoPtr)(HTOUCHINPUT, UINT, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PTOUCHINPUT, int); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetTouchInputInfoPtr get_touch_input_info_func = 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<GetTouchInputInfoPtr>( 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetProcAddress(GetModuleHandleA("user32.dll"), "GetTouchInputInfo")); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (get_touch_input_info_func) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return get_touch_input_info_func(handle, count, pointer, size); 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Singleton factory that creates and manages the lifetime of all 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ui::HWNDSubclass objects. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HWNDSubclass::HWNDSubclassFactory { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static HWNDSubclassFactory* GetInstance() { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<HWNDSubclassFactory, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeakySingletonTraits<HWNDSubclassFactory> >::get(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns a non-null HWNDSubclass corresponding to the HWND |target|. Creates 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one if none exists. Retains ownership of the returned pointer. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWNDSubclass* GetHwndSubclassForTarget(HWND target) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(target); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWNDSubclass* subclass = reinterpret_cast<HWNDSubclass*>( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ViewProp::GetValue(target, kHWNDSubclassKey)); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!subclass) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subclass = new ui::HWNDSubclass(target); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hwnd_subclasses_.push_back(subclass); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return subclass; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ScopedVector<HWNDSubclass>& hwnd_subclasses() { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hwnd_subclasses_; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<HWNDSubclassFactory>; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWNDSubclassFactory() {} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<HWNDSubclass> hwnd_subclasses_; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(HWNDSubclassFactory); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HWNDSubclass::AddFilterToTarget(HWND target, HWNDMessageFilter* filter) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWNDSubclassFactory::GetInstance()->GetHwndSubclassForTarget( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target)->AddFilter(filter); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HWNDSubclass::RemoveFilterFromAllTargets(HWNDMessageFilter* filter) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWNDSubclassFactory* factory = HWNDSubclassFactory::GetInstance(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<ui::HWNDSubclass>::const_iterator it; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = factory->hwnd_subclasses().begin(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != factory->hwnd_subclasses().end(); ++it) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*it)->RemoveFilter(filter); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWNDSubclass* HWNDSubclass::GetHwndSubclassForTarget(HWND target) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HWNDSubclassFactory::GetInstance()->GetHwndSubclassForTarget(target); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HWNDSubclass::AddFilter(HWNDMessageFilter* filter) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(filter); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (std::find(filters_.begin(), filters_.end(), filter) == filters_.end()) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filters_.push_back(filter); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HWNDSubclass::RemoveFilter(HWNDMessageFilter* filter) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<HWNDMessageFilter*>::iterator it = 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(filters_.begin(), filters_.end(), filter); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != filters_.end()) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filters_.erase(it); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWNDSubclass::HWNDSubclass(HWND target) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : target_(target), 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_wnd_proc_(GetCurrentWndProc(target)), 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prop_(target, kHWNDSubclassKey, this) { 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) gfx::SetWindowProc(target_, &WndProc); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWNDSubclass::~HWNDSubclass() { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LRESULT HWNDSubclass::OnWndProc(HWND hwnd, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT message, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WPARAM w_param, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LPARAM l_param) { 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Touch messages are always passed in screen coordinates. If the OS is 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // scaled, but the app is not DPI aware, then then WM_TOUCH might be 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // intended for a different window. 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (message == WM_TOUCH) { 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TOUCHINPUT point; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param), 1, 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &point, sizeof(TOUCHINPUT))) { 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) POINT touch_location = {TOUCH_COORD_TO_PIXEL(point.x), 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) TOUCH_COORD_TO_PIXEL(point.y)}; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HWND actual_target = WindowFromPoint(touch_location); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (actual_target != hwnd) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SendMessage(actual_target, message, w_param, l_param); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<HWNDMessageFilter*>::iterator it = filters_.begin(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != filters_.end(); ++it) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LRESULT l_result = 0; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*it)->FilterMessage(hwnd, message, w_param, l_param, &l_result)) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l_result; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In most cases, |original_wnd_proc_| will take care of calling 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DefWindowProc. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CallWindowProc(original_wnd_proc_, hwnd, message, w_param, l_param); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HWNDMessageFilter::~HWNDMessageFilter() { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWNDSubclass::RemoveFilterFromAllTargets(this); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui 171