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 13 HRESULT ForegroundHelper::SetForeground(HWND window) { 14 DCHECK(::IsWindow(window)); 15 ForegroundHelper foreground_helper; 16 return foreground_helper.ForegroundHotKey(window); 17 } 18 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. 76 void ForegroundHelper::OnHotKey(int id, UINT vcode, UINT modifiers) { 77 SetForegroundWindow(window_); 78 } 79 80 } // namespace ui 81