Home | History | Annotate | Download | only in win
      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