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