15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Copyright 2010 Google Inc. All Rights Reserved
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/win32windowpicker.h"
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <string>
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <vector>
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h"
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base {
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace {
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Window class names that we want to filter out.
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kProgramManagerClass[] = "Progman";
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst char kButtonClass[] = "Button";
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgBOOL CALLBACK Win32WindowPicker::EnumProc(HWND hwnd, LPARAM l_param) {
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  WindowDescriptionList* descriptions =
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      reinterpret_cast<WindowDescriptionList*>(l_param);
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Skip windows that are invisible, minimized, have no title, or are owned,
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // unless they have the app window style set. Except for minimized windows,
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // this is what Alt-Tab does.
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO: Figure out how to grab a thumbnail of a minimized window and
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // include them in the list.
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int len = GetWindowTextLength(hwnd);
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  HWND owner = GetWindow(hwnd, GW_OWNER);
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) ||
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      (owner && !(exstyle & WS_EX_APPWINDOW))) {
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // TODO: Investigate if windows without title still could be
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // interesting to share. We could use the name of the process as title:
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    //
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // GetWindowThreadProcessId()
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // OpenProcess()
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // QueryFullProcessImageName()
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return TRUE;
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Skip the Program Manager window and the Start button.
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  TCHAR class_name_w[500];
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ::GetClassName(hwnd, class_name_w, 500);
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string class_name = ToUtf8(class_name_w);
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (class_name == kProgramManagerClass || class_name == kButtonClass) {
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // We don't want the Program Manager window nor the Start button.
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return TRUE;
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  TCHAR window_title[500];
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GetWindowText(hwnd, window_title, ARRAY_SIZE(window_title));
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string title = ToUtf8(window_title);
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  WindowId id(hwnd);
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  WindowDescription desc(id, title);
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  descriptions->push_back(desc);
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return TRUE;
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgBOOL CALLBACK Win32WindowPicker::MonitorEnumProc(HMONITOR h_monitor,
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                 HDC hdc_monitor,
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                 LPRECT lprc_monitor,
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                 LPARAM l_param) {
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DesktopDescriptionList* desktop_desc =
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      reinterpret_cast<DesktopDescriptionList*>(l_param);
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DesktopId id(h_monitor, static_cast<int>(desktop_desc->size()));
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO: Figure out an appropriate desktop title.
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DesktopDescription desc(id, "");
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Determine whether it's the primary monitor.
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MONITORINFO monitor_info = {0};
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  monitor_info.cbSize = sizeof(monitor_info);
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool primary = (GetMonitorInfo(h_monitor, &monitor_info) &&
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      (monitor_info.dwFlags & MONITORINFOF_PRIMARY) != 0);
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  desc.set_primary(primary);
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  desktop_desc->push_back(desc);
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return TRUE;
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgWin32WindowPicker::Win32WindowPicker() {
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32WindowPicker::Init() {
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// TODO: Consider changing enumeration to clear() descriptions
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// before append().
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32WindowPicker::GetWindowList(WindowDescriptionList* descriptions) {
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LPARAM desc = reinterpret_cast<LPARAM>(descriptions);
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return EnumWindows(Win32WindowPicker::EnumProc, desc) != FALSE;
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32WindowPicker::GetDesktopList(DesktopDescriptionList* descriptions) {
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Create a fresh WindowDescriptionList so that we can use desktop_desc.size()
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // in MonitorEnumProc to compute the desktop index.
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DesktopDescriptionList desktop_desc;
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  HDC hdc = GetDC(NULL);
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool success = false;
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (EnumDisplayMonitors(hdc, NULL, Win32WindowPicker::MonitorEnumProc,
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      reinterpret_cast<LPARAM>(&desktop_desc)) != FALSE) {
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Append the desktop descriptions to the end of the returned descriptions.
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    descriptions->insert(descriptions->end(), desktop_desc.begin(),
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         desktop_desc.end());
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    success = true;
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ReleaseDC(NULL, hdc);
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return success;
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32WindowPicker::GetDesktopDimensions(const DesktopId& id,
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                             int* width,
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                             int* height) {
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MONITORINFOEX monitor_info;
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  monitor_info.cbSize = sizeof(MONITORINFOEX);
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!GetMonitorInfo(id.id(), &monitor_info)) {
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  *width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  *height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32WindowPicker::IsVisible(const WindowId& id) {
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (::IsWindow(id.id()) != FALSE && ::IsWindowVisible(id.id()) != FALSE);
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool Win32WindowPicker::MoveToFront(const WindowId& id) {
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return SetForegroundWindow(id.id()) != FALSE;
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace talk_base
138