| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/desktop_capture/window_capturer.h" | 11 #include "webrtc/modules/desktop_capture/window_capturer.h" |
| 12 | 12 |
| 13 #include <assert.h> | 13 #include <assert.h> |
| 14 | 14 |
| 15 #include <memory> | 15 #include <memory> |
| 16 | 16 |
| 17 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" |
| 18 #include "webrtc/base/constructormagic.h" | 18 #include "webrtc/base/constructormagic.h" |
| 19 #include "webrtc/base/win32.h" | 19 #include "webrtc/base/win32.h" |
| 20 #include "webrtc/modules/desktop_capture/desktop_frame_win.h" | 20 #include "webrtc/modules/desktop_capture/desktop_frame_win.h" |
| 21 #include "webrtc/modules/desktop_capture/win/window_capture_utils.h" | 21 #include "webrtc/modules/desktop_capture/win/window_capture_utils.h" |
| 22 #include "webrtc/system_wrappers/include/logging.h" | 22 #include "webrtc/system_wrappers/include/logging.h" |
| 23 | 23 |
| 24 namespace webrtc { | 24 namespace webrtc { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 void InitializeBitmapHeader(BITMAPV5HEADER* header, int width, int height) { |
| 29 memset(header, 0, sizeof(BITMAPV5HEADER)); |
| 30 header->bV5Size = sizeof(BITMAPV5HEADER); |
| 31 |
| 32 // Note that icons are created using top-down DIBs so we must negate the |
| 33 // value used for the icon's height. |
| 34 header->bV5Width = width; |
| 35 header->bV5Height = -height; |
| 36 header->bV5Planes = 1; |
| 37 header->bV5Compression = BI_RGB; |
| 38 |
| 39 // Initializing the bitmap format to 32 bit ARGB. |
| 40 header->bV5BitCount = 32; |
| 41 header->bV5RedMask = 0x00FF0000; |
| 42 header->bV5GreenMask = 0x0000FF00; |
| 43 header->bV5BlueMask = 0x000000FF; |
| 44 header->bV5AlphaMask = 0xFF000000; |
| 45 |
| 46 // Use the system color space. The default value is LCS_CALIBRATED_RGB, which |
| 47 // causes us to crash if we don't specify the approprite gammas, etc. See |
| 48 // <http://msdn.microsoft.com/en-us/library/ms536531(VS.85).aspx> and |
| 49 // <http://b/1283121>. |
| 50 header->bV5CSType = LCS_WINDOWS_COLOR_SPACE; |
| 51 |
| 52 // Use a valid value for bV5Intent as 0 is not a valid one. |
| 53 // <http://msdn.microsoft.com/en-us/library/dd183381(VS.85).aspx> |
| 54 header->bV5Intent = LCS_GM_IMAGES; |
| 55 } |
| 56 |
| 57 std::unique_ptr<DesktopFrame> GetWindowIcon(HWND hwnd) { |
| 58 HICON icon_handle = |
| 59 reinterpret_cast<HICON>(SendMessage(hwnd, WM_GETICON, ICON_BIG, 0)); |
| 60 if (icon_handle == NULL) |
| 61 icon_handle = (HICON)GetClassLongPtr(hwnd, GCLP_HICON); |
| 62 if (icon_handle == NULL) |
| 63 icon_handle = |
| 64 reinterpret_cast<HICON>(SendMessage(hwnd, WM_GETICON, ICON_SMALL, 0)); |
| 65 if (icon_handle == NULL) |
| 66 icon_handle = |
| 67 reinterpret_cast<HICON>(SendMessage(hwnd, WM_GETICON, ICON_SMALL2, 0)); |
| 68 if (icon_handle == NULL) |
| 69 icon_handle = (HICON)GetClassLongPtr(hwnd, GCLP_HICONSM); |
| 70 |
| 71 if (icon_handle == NULL) |
| 72 return nullptr; |
| 73 |
| 74 ICONINFO icon_info; |
| 75 ::GetIconInfo(icon_handle, &icon_info); |
| 76 |
| 77 BITMAP bitmap_info = {0}; |
| 78 ::GetObject(icon_info.hbmMask, sizeof(bitmap_info), &bitmap_info); |
| 79 |
| 80 std::unique_ptr<DesktopFrame> frame(new BasicDesktopFrame( |
| 81 DesktopSize(bitmap_info.bmWidth, bitmap_info.bmHeight))); |
| 82 |
| 83 BITMAPV5HEADER h; |
| 84 InitializeBitmapHeader(&h, bitmap_info.bmWidth, bitmap_info.bmHeight); |
| 85 HDC hdc = ::GetDC(NULL); |
| 86 uint8_t* bits; |
| 87 HBITMAP dib = |
| 88 ::CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO*>(&h), DIB_RGB_COLORS, |
| 89 reinterpret_cast<void**>(&bits), NULL, 0); |
| 90 HDC dib_dc = CreateCompatibleDC(hdc); |
| 91 ::SelectObject(dib_dc, dib); |
| 92 ::DrawIconEx(dib_dc, 0, 0, icon_handle, bitmap_info.bmWidth, |
| 93 bitmap_info.bmHeight, 0, NULL, DI_NORMAL); |
| 94 for (int y = 0; y < bitmap_info.bmHeight; ++y) { |
| 95 memcpy(frame->data() + frame->stride() * y, |
| 96 bits + bitmap_info.bmWidth * DesktopFrame::kBytesPerPixel * y, |
| 97 DesktopFrame::kBytesPerPixel * bitmap_info.bmWidth); |
| 98 } |
| 99 return frame; |
| 100 } |
| 101 |
| 28 BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) { | 102 BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) { |
| 29 WindowCapturer::WindowList* list = | 103 WindowCapturer::WindowList* list = |
| 30 reinterpret_cast<WindowCapturer::WindowList*>(param); | 104 reinterpret_cast<WindowCapturer::WindowList*>(param); |
| 31 | 105 |
| 32 // Skip windows that are invisible, minimized, have no title, or are owned, | 106 // Skip windows that are invisible, minimized, have no title, or are owned, |
| 33 // unless they have the app window style set. | 107 // unless they have the app window style set. |
| 34 int len = GetWindowTextLength(hwnd); | 108 int len = GetWindowTextLength(hwnd); |
| 35 HWND owner = GetWindow(hwnd, GW_OWNER); | 109 HWND owner = GetWindow(hwnd, GW_OWNER); |
| 36 LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); | 110 LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); |
| 37 if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) || | 111 if (len == 0 || IsIconic(hwnd) || !IsWindowVisible(hwnd) || |
| (...skipping 25 matching lines...) Expand all Loading... |
| 63 } | 137 } |
| 64 | 138 |
| 65 WindowCapturer::Window window; | 139 WindowCapturer::Window window; |
| 66 window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd); | 140 window.id = reinterpret_cast<WindowCapturer::WindowId>(hwnd); |
| 67 | 141 |
| 68 const size_t kTitleLength = 500; | 142 const size_t kTitleLength = 500; |
| 69 WCHAR window_title[kTitleLength]; | 143 WCHAR window_title[kTitleLength]; |
| 70 // Truncate the title if it's longer than kTitleLength. | 144 // Truncate the title if it's longer than kTitleLength. |
| 71 GetWindowText(hwnd, window_title, kTitleLength); | 145 GetWindowText(hwnd, window_title, kTitleLength); |
| 72 window.title = rtc::ToUtf8(window_title); | 146 window.title = rtc::ToUtf8(window_title); |
| 147 window.icon = GetWindowIcon(hwnd); |
| 73 | 148 |
| 74 // Skip windows when we failed to convert the title or it is empty. | 149 // Skip windows when we failed to convert the title or it is empty. |
| 75 if (window.title.empty()) | 150 if (window.title.empty()) |
| 76 return TRUE; | 151 return TRUE; |
| 77 | 152 |
| 78 list->push_back(window); | 153 list->push_back(std::move(window)); |
| 79 | 154 |
| 80 return TRUE; | 155 return TRUE; |
| 81 } | 156 } |
| 82 | 157 |
| 83 class WindowCapturerWin : public WindowCapturer { | 158 class WindowCapturerWin : public WindowCapturer { |
| 84 public: | 159 public: |
| 85 WindowCapturerWin(); | 160 WindowCapturerWin(); |
| 86 virtual ~WindowCapturerWin(); | 161 virtual ~WindowCapturerWin(); |
| 87 | 162 |
| 88 // WindowCapturer interface. | 163 // WindowCapturer interface. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 109 // are interleaved with Capture() calls. | 184 // are interleaved with Capture() calls. |
| 110 std::map<HWND, DesktopSize> window_size_map_; | 185 std::map<HWND, DesktopSize> window_size_map_; |
| 111 | 186 |
| 112 RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin); | 187 RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerWin); |
| 113 }; | 188 }; |
| 114 | 189 |
| 115 WindowCapturerWin::WindowCapturerWin() {} | 190 WindowCapturerWin::WindowCapturerWin() {} |
| 116 WindowCapturerWin::~WindowCapturerWin() {} | 191 WindowCapturerWin::~WindowCapturerWin() {} |
| 117 | 192 |
| 118 bool WindowCapturerWin::GetWindowList(WindowList* windows) { | 193 bool WindowCapturerWin::GetWindowList(WindowList* windows) { |
| 119 WindowList result; | 194 windows->clear(); |
| 120 LPARAM param = reinterpret_cast<LPARAM>(&result); | 195 LPARAM param = reinterpret_cast<LPARAM>(windows); |
| 121 if (!EnumWindows(&WindowsEnumerationHandler, param)) | 196 if (!EnumWindows(&WindowsEnumerationHandler, param)) |
| 122 return false; | 197 return false; |
| 123 windows->swap(result); | |
| 124 | 198 |
| 125 std::map<HWND, DesktopSize> new_map; | 199 std::map<HWND, DesktopSize> new_map; |
| 126 for (const auto& item : *windows) { | 200 for (const auto& item : *windows) { |
| 127 HWND hwnd = reinterpret_cast<HWND>(item.id); | 201 HWND hwnd = reinterpret_cast<HWND>(item.id); |
| 128 new_map[hwnd] = window_size_map_[hwnd]; | 202 new_map[hwnd] = window_size_map_[hwnd]; |
| 129 } | 203 } |
| 130 window_size_map_.swap(new_map); | 204 window_size_map_.swap(new_map); |
| 131 | 205 |
| 132 return true; | 206 return true; |
| 133 } | 207 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 } | 337 } |
| 264 | 338 |
| 265 } // namespace | 339 } // namespace |
| 266 | 340 |
| 267 // static | 341 // static |
| 268 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { | 342 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { |
| 269 return new WindowCapturerWin(); | 343 return new WindowCapturerWin(); |
| 270 } | 344 } |
| 271 | 345 |
| 272 } // namespace webrtc | 346 } // namespace webrtc |
| OLD | NEW |