Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 #include "webrtc/base/win32windowpicker.h"
     11 
     12 #include <string>
     13 #include <vector>
     14 
     15 #include "webrtc/base/arraysize.h"
     16 #include "webrtc/base/common.h"
     17 #include "webrtc/base/logging.h"
     18 
     19 namespace rtc {
     20 
     21 namespace {
     22 
     23 // Window class names that we want to filter out.
     24 const char kProgramManagerClass[] = "Progman";
     25 const char kButtonClass[] = "Button";
     26 
     27 }  // namespace
     28 
     29 BOOL CALLBACK Win32WindowPicker::EnumProc(HWND hwnd, LPARAM l_param) {
     30   WindowDescriptionList* descriptions =
     31       reinterpret_cast<WindowDescriptionList*>(l_param);
     32 
     33   // Skip windows that are invisible, minimized, have no title, or are owned,
     34   // unless they have the app window style set. Except for minimized windows,
     35   // this is what Alt-Tab does.
     36   // TODO: Figure out how to grab a thumbnail of a minimized window and
     37   // include them in the list.
     38   int len = GetWindowTextLength(hwnd);
     39   HWND owner = GetWindow(hwnd, GW_OWNER);
     40   LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
     41   if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
     42       (owner && !(exstyle & WS_EX_APPWINDOW))) {
     43     // TODO: Investigate if windows without title still could be
     44     // interesting to share. We could use the name of the process as title:
     45     //
     46     // GetWindowThreadProcessId()
     47     // OpenProcess()
     48     // QueryFullProcessImageName()
     49     return TRUE;
     50   }
     51 
     52   // Skip the Program Manager window and the Start button.
     53   TCHAR class_name_w[500];
     54   ::GetClassName(hwnd, class_name_w, 500);
     55   std::string class_name = ToUtf8(class_name_w);
     56   if (class_name == kProgramManagerClass || class_name == kButtonClass) {
     57     // We don't want the Program Manager window nor the Start button.
     58     return TRUE;
     59   }
     60 
     61   TCHAR window_title[500];
     62   GetWindowText(hwnd, window_title, arraysize(window_title));
     63   std::string title = ToUtf8(window_title);
     64 
     65   WindowId id(hwnd);
     66   WindowDescription desc(id, title);
     67   descriptions->push_back(desc);
     68   return TRUE;
     69 }
     70 
     71 BOOL CALLBACK Win32WindowPicker::MonitorEnumProc(HMONITOR h_monitor,
     72                                                  HDC hdc_monitor,
     73                                                  LPRECT lprc_monitor,
     74                                                  LPARAM l_param) {
     75   DesktopDescriptionList* desktop_desc =
     76       reinterpret_cast<DesktopDescriptionList*>(l_param);
     77 
     78   DesktopId id(h_monitor, static_cast<int>(desktop_desc->size()));
     79   // TODO: Figure out an appropriate desktop title.
     80   DesktopDescription desc(id, "");
     81 
     82   // Determine whether it's the primary monitor.
     83   MONITORINFO monitor_info = {0};
     84   monitor_info.cbSize = sizeof(monitor_info);
     85   bool primary = (GetMonitorInfo(h_monitor, &monitor_info) &&
     86       (monitor_info.dwFlags & MONITORINFOF_PRIMARY) != 0);
     87   desc.set_primary(primary);
     88 
     89   desktop_desc->push_back(desc);
     90   return TRUE;
     91 }
     92 
     93 Win32WindowPicker::Win32WindowPicker() {
     94 }
     95 
     96 bool Win32WindowPicker::Init() {
     97   return true;
     98 }
     99 // TODO: Consider changing enumeration to clear() descriptions
    100 // before append().
    101 bool Win32WindowPicker::GetWindowList(WindowDescriptionList* descriptions) {
    102   LPARAM desc = reinterpret_cast<LPARAM>(descriptions);
    103   return EnumWindows(Win32WindowPicker::EnumProc, desc) != FALSE;
    104 }
    105 
    106 bool Win32WindowPicker::GetDesktopList(DesktopDescriptionList* descriptions) {
    107   // Create a fresh WindowDescriptionList so that we can use desktop_desc.size()
    108   // in MonitorEnumProc to compute the desktop index.
    109   DesktopDescriptionList desktop_desc;
    110   HDC hdc = GetDC(NULL);
    111   bool success = false;
    112   if (EnumDisplayMonitors(hdc, NULL, Win32WindowPicker::MonitorEnumProc,
    113       reinterpret_cast<LPARAM>(&desktop_desc)) != FALSE) {
    114     // Append the desktop descriptions to the end of the returned descriptions.
    115     descriptions->insert(descriptions->end(), desktop_desc.begin(),
    116                          desktop_desc.end());
    117     success = true;
    118   }
    119   ReleaseDC(NULL, hdc);
    120   return success;
    121 }
    122 
    123 bool Win32WindowPicker::GetDesktopDimensions(const DesktopId& id,
    124                                              int* width,
    125                                              int* height) {
    126   MONITORINFOEX monitor_info;
    127   monitor_info.cbSize = sizeof(MONITORINFOEX);
    128   if (!GetMonitorInfo(id.id(), &monitor_info)) {
    129     return false;
    130   }
    131   *width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
    132   *height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
    133   return true;
    134 }
    135 
    136 bool Win32WindowPicker::IsVisible(const WindowId& id) {
    137   return (::IsWindow(id.id()) != FALSE && ::IsWindowVisible(id.id()) != FALSE);
    138 }
    139 
    140 bool Win32WindowPicker::MoveToFront(const WindowId& id) {
    141   return SetForegroundWindow(id.id()) != FALSE;
    142 }
    143 
    144 }  // namespace rtc
    145