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/foreground_helper.h"
6
7 #include "base/logging.h"
8 #include "ui/gfx/win/window_impl.h"
9
10 namespace ui {
11
12 // static
SetForeground(HWND window)13 HRESULT ForegroundHelper::SetForeground(HWND window) {
14 DCHECK(::IsWindow(window));
15 ForegroundHelper foreground_helper;
16 return foreground_helper.ForegroundHotKey(window);
17 }
18
ForegroundHotKey(HWND window)19 HRESULT ForegroundHelper::ForegroundHotKey(HWND window) {
20 // This implementation registers a hot key (F22) and then
21 // triggers the hot key. When receiving the hot key, we'll
22 // be in the foreground and allowed to move the target window
23 // into the foreground too.
24
25 set_window_style(WS_POPUP);
26 Init(NULL, gfx::Rect());
27
28 static const int kHotKeyId = 0x0000baba;
29 static const int kHotKeyWaitTimeout = 2000;
30
31 // Store the target window into our USERDATA for use in our
32 // HotKey handler.
33 window_ = window;
34 RegisterHotKey(hwnd(), kHotKeyId, 0, VK_F22);
35
36 // If the calling thread is not yet a UI thread, call PeekMessage
37 // to ensure creation of its message queue.
38 MSG msg = {0};
39 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
40
41 // Send the Hotkey.
42 INPUT hotkey = {0};
43 hotkey.type = INPUT_KEYBOARD;
44 hotkey.ki.wVk = VK_F22;
45 if (1 != SendInput(1, &hotkey, sizeof(hotkey))) {
46 LOG(WARNING) << "Failed to send input; GetLastError(): " << GetLastError();
47 return E_FAIL;
48 }
49
50 // There are scenarios where the WM_HOTKEY is not dispatched by the
51 // the corresponding foreground thread. To prevent us from indefinitely
52 // waiting for the hotkey, we set a timer and exit the loop.
53 SetTimer(hwnd(), kHotKeyId, kHotKeyWaitTimeout, NULL);
54
55 // Loop until we get the key or the timer fires.
56 while (GetMessage(&msg, NULL, 0, 0)) {
57 TranslateMessage(&msg);
58 DispatchMessage(&msg);
59
60 if (WM_HOTKEY == msg.message)
61 break;
62 if (WM_TIMER == msg.message) {
63 SetForegroundWindow(window);
64 break;
65 }
66 }
67
68 UnregisterHotKey(hwnd(), kHotKeyId);
69 KillTimer(hwnd(), kHotKeyId);
70 DestroyWindow(hwnd());
71
72 return S_OK;
73 }
74
75 // Handle the registered Hotkey being pressed.
OnHotKey(int id,UINT vcode,UINT modifiers)76 void ForegroundHelper::OnHotKey(int id, UINT vcode, UINT modifiers) {
77 SetForegroundWindow(window_);
78 }
79
80 } // namespace ui
81