diff options
author | scottbyer@chromium.org <scottbyer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-27 19:05:29 +0000 |
---|---|---|
committer | scottbyer@chromium.org <scottbyer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-27 19:05:29 +0000 |
commit | d81d40b5f5f5728238f7743960adf3d1b16ff4aa (patch) | |
tree | a1b5288aec9ea87fc2e9f3c713e867c208624a84 /ui | |
parent | ee47b5069b4b2819b244908d4e640a32c95c6b44 (diff) | |
download | chromium_src-d81d40b5f5f5728238f7743960adf3d1b16ff4aa.zip chromium_src-d81d40b5f5f5728238f7743960adf3d1b16ff4aa.tar.gz chromium_src-d81d40b5f5f5728238f7743960adf3d1b16ff4aa.tar.bz2 |
Refactor out foreground_help to fix BringBrowserWindowToFront on Windows
Refactor out foreground_helper so that regular Chromium tests can use it. Use
it in ShowAndFocusNativeWindow to make sure the browser window is in front,
both when tests ask and when trying to send keyboard events. This should reduce
some flakiness of related tests, and certainly makes it easier to debug those
tests.
The API for SendKeyPress events looks like it changed long ago to add a target
window, only the Windows code simply dropped that on the floor. By returning
false when the event wouldn't go to the right place, it allows for
ui_test_utils::SendKeyPressSync to bring the browser window to the front and
try again.
BUG=106489
TEST=Run browser_tests or interactive_ui_tests and bring another window to the
front. For the tests in question, the browser should now pop in front when it
needs to for the test to complete properly.
Review URL: http://codereview.chromium.org/9431050
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123771 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/base/win/foreground_helper.cc | 84 | ||||
-rw-r--r-- | ui/base/win/foreground_helper.h | 47 | ||||
-rw-r--r-- | ui/ui.gyp | 2 |
3 files changed, 133 insertions, 0 deletions
diff --git a/ui/base/win/foreground_helper.cc b/ui/base/win/foreground_helper.cc new file mode 100644 index 0000000..0b03582 --- /dev/null +++ b/ui/base/win/foreground_helper.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/win/foreground_helper.h" + +#include "base/logging.h" +#include "ui/base/win/window_impl.h" + +namespace ui { + +// static +HRESULT ForegroundHelper::SetForeground(HWND window) { + DCHECK(::IsWindow(window)); + ForegroundHelper foreground_helper; + return foreground_helper.ForegroundHotKey(window); +} + +HRESULT ForegroundHelper::ForegroundHotKey(HWND window) { + // This implementation registers a hot key (F22) and then + // triggers the hot key. When receiving the hot key, we'll + // be in the foreground and allowed to move the target window + // into the foreground too. + + set_window_style(WS_POPUP); + Init(NULL, gfx::Rect()); + + static const int kHotKeyId = 0x0000baba; + static const int kHotKeyWaitTimeout = 2000; + + // Store the target window into our USERDATA for use in our + // HotKey handler. + window_ = window; + RegisterHotKey(hwnd(), kHotKeyId, 0, VK_F22); + + // If the calling thread is not yet a UI thread, call PeekMessage + // to ensure creation of its message queue. + MSG msg = {0}; + PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); + + // Send the Hotkey. + INPUT hotkey = {0}; + hotkey.type = INPUT_KEYBOARD; + hotkey.ki.wVk = VK_F22; + if (1 != SendInput(1, &hotkey, sizeof(hotkey))) { + LOG(WARNING) << "Failed to send input"; + return E_FAIL; + } + + // There are scenarios where the WM_HOTKEY is not dispatched by the + // the corresponding foreground thread. To prevent us from indefinitely + // waiting for the hotkey, we set a timer and exit the loop. + SetTimer(hwnd(), kHotKeyId, kHotKeyWaitTimeout, NULL); + + // Loop until we get the key or the timer fires. + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (WM_HOTKEY == msg.message) + break; + if (WM_TIMER == msg.message) { + SetForegroundWindow(window); + break; + } + } + + UnregisterHotKey(hwnd(), kHotKeyId); + KillTimer(hwnd(), kHotKeyId); + DestroyWindow(hwnd()); + + return S_OK; +} + + // Handle the registered Hotkey being pressed. +LRESULT ForegroundHelper::OnHotKey(UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL& handled) { + SetForegroundWindow(window_); + return 1; +} + +} // namespace ui diff --git a/ui/base/win/foreground_helper.h b/ui/base/win/foreground_helper.h new file mode 100644 index 0000000..a630828 --- /dev/null +++ b/ui/base/win/foreground_helper.h @@ -0,0 +1,47 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_WIN_FOREGROUND_HELPER_H_ +#define UI_BASE_WIN_FOREGROUND_HELPER_H_ +#pragma once + +#include "base/logging.h" +#include "ui/base/win/window_impl.h" + +namespace ui { + +// Helper class for moving a window to the foreground. +// Windows XP and later will not allow a window which is in the background to +// move to the foreground, unless requested by the current window in the +// foreground. For automated testing, we really want some of our windows +// to be capable of moving to the foreground. +// +// This is probably leveraging a windows bug. +class UI_EXPORT ForegroundHelper : public WindowImpl { + public: + ForegroundHelper() : window_(NULL) { } + + BEGIN_MSG_MAP_EX(ForegroundHelper) + MESSAGE_HANDLER(WM_HOTKEY, OnHotKey) + END_MSG_MAP() + + // Brings a window into the foreground. + // Can be called from any window, even if the caller is not the + // foreground window. + static HRESULT SetForeground(HWND window); + + private: + HRESULT ForegroundHotKey(HWND window); + + // Handle the registered Hotkey being pressed. + LRESULT OnHotKey(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled); + + HWND window_; + + DISALLOW_COPY_AND_ASSIGN(ForegroundHelper); +}; + +} // namespace ui + +#endif // UI_BASE_WIN_FOREGROUND_HELPER_H_ @@ -213,6 +213,8 @@ 'base/wayland/events_wayland.cc', 'base/win/atl_module.h', 'base/win/events_win.cc', + 'base/win/foreground_helper.cc', + 'base/win/foreground_helper.h', 'base/win/hwnd_util.cc', 'base/win/hwnd_util.h', 'base/win/ime_input.cc', |