diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-25 21:10:32 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-25 21:10:32 +0000 |
commit | f5cb25824d8c48b0d79ac7ebc1726d135d8f1966 (patch) | |
tree | 0779ea31b9a7c377f6a02e508a27c76843f50810 | |
parent | a19b192312a88561389ce827765e92c1ece16bf7 (diff) | |
download | chromium_src-f5cb25824d8c48b0d79ac7ebc1726d135d8f1966.zip chromium_src-f5cb25824d8c48b0d79ac7ebc1726d135d8f1966.tar.gz chromium_src-f5cb25824d8c48b0d79ac7ebc1726d135d8f1966.tar.bz2 |
Review URL: http://codereview.chromium.org/12434
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5990 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/win_util.cc | 6 | ||||
-rw-r--r-- | base/win_util.h | 3 | ||||
-rw-r--r-- | chrome/views/focus_manager.cc | 29 |
3 files changed, 36 insertions, 2 deletions
diff --git a/base/win_util.cc b/base/win_util.cc index 37c5075..cfd7f2b 100644 --- a/base/win_util.cc +++ b/base/win_util.cc @@ -257,6 +257,12 @@ void* GetWindowUserData(HWND hwnd) { // installed. static const wchar_t* const kHandlerKey = L"__ORIGINAL_MESSAGE_HANDLER__"; +bool IsSubclassed(HWND window, WNDPROC subclass_proc) { + WNDPROC original_handler = + reinterpret_cast<WNDPROC>(GetWindowLongPtr(window, GWLP_WNDPROC)); + return original_handler == subclass_proc; +} + bool Subclass(HWND window, WNDPROC subclass_proc) { WNDPROC original_handler = reinterpret_cast<WNDPROC>(GetWindowLongPtr(window, GWLP_WNDPROC)); diff --git a/base/win_util.h b/base/win_util.h index 2165e62..317c332 100644 --- a/base/win_util.h +++ b/base/win_util.h @@ -50,6 +50,9 @@ bool GetLogonSessionOnlyDACL(SECURITY_DESCRIPTOR** security_descriptor); // Useful for subclassing a HWND. Returns the previous window procedure. WNDPROC SetWindowProc(HWND hwnd, WNDPROC wndproc); +// Returns true if the existing window procedure is the same as |subclass_proc|. +bool IsSubclassed(HWND window, WNDPROC subclass_proc); + // Subclasses a window, replacing its existing window procedure with the // specified one. Returns true if the current window procedure was replaced, // false if the window has already been subclassed with the specified diff --git a/chrome/views/focus_manager.cc b/chrome/views/focus_manager.cc index da23bda..b48fe594 100644 --- a/chrome/views/focus_manager.cc +++ b/chrome/views/focus_manager.cc @@ -4,6 +4,7 @@ #include <algorithm> +#include "base/histogram.h" #include "base/logging.h" #include "base/win_util.h" #include "chrome/browser/render_widget_host_view_win.h" @@ -30,6 +31,16 @@ static const wchar_t* const kFocusManagerKey = L"__VIEW_CONTAINER__"; // - prevent tab key events from being sent to views. static const wchar_t* const kViewKey = L"__CHROME_VIEW__"; +// A property set to 1 to indicate whether the focus manager has subclassed that +// window. We are doing this to ensure we are not subclassing several times. +// Subclassing twice is not a problem if no one is subclassing the HWND between +// the 2 subclassings (the 2nd subclassing is ignored since the WinProc is the +// same as the current one). However if some other app goes and subclasses the +// HWND between the 2 subclassings, we will end up subclassing twice. +// This flag lets us test that whether we have or not subclassed yet. +static const wchar_t* const kFocusSubclassInstalled = + L"__FOCUS_SUBCLASS_INSTALLED__"; + namespace views { static bool IsCompatibleWithMouseWheelRedirection(HWND window) { @@ -209,15 +220,29 @@ FocusManager* FocusManager::CreateFocusManager(HWND window, // static void FocusManager::InstallFocusSubclass(HWND window, View* view) { DCHECK(window); - win_util::Subclass(window, &FocusWindowCallback); + + bool already_subclassed = + reinterpret_cast<bool>(GetProp(window, + kFocusSubclassInstalled)); + if (already_subclassed && + !win_util::IsSubclassed(window, &FocusWindowCallback)) { + NOTREACHED() << "window sub-classed by someone other than the FocusManager"; + // Track in UMA so we know if this case happens. + UMA_HISTOGRAM_COUNTS(L"FocusManager.MultipleSubclass", 1); + } else { + win_util::Subclass(window, &FocusWindowCallback); + SetProp(window, kFocusSubclassInstalled, reinterpret_cast<HANDLE>(true)); + } if (view) SetProp(window, kViewKey, view); } void FocusManager::UninstallFocusSubclass(HWND window) { DCHECK(window); - if (win_util::Unsubclass(window, &FocusWindowCallback)) + if (win_util::Unsubclass(window, &FocusWindowCallback)) { RemoveProp(window, kViewKey); + RemoveProp(window, kFocusSubclassInstalled); + } } // static |