Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: remoting/host/capturer_win.cc

Issue 10699046: Support remoting of all monitors on multi-monitor Windows systems (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Nitpick picnic. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/capturer.h" 5 #include "remoting/host/capturer.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/scoped_native_library.h" 12 #include "base/scoped_native_library.h"
13 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "base/win/scoped_gdi_object.h" 14 #include "base/win/scoped_gdi_object.h"
15 #include "base/win/scoped_hdc.h"
15 #include "remoting/base/capture_data.h" 16 #include "remoting/base/capture_data.h"
16 #include "remoting/host/capturer_helper.h" 17 #include "remoting/host/capturer_helper.h"
17 #include "remoting/host/desktop_win.h" 18 #include "remoting/host/desktop_win.h"
18 #include "remoting/host/differ.h" 19 #include "remoting/host/differ.h"
19 #include "remoting/host/scoped_thread_desktop_win.h" 20 #include "remoting/host/scoped_thread_desktop_win.h"
20 #include "remoting/proto/control.pb.h" 21 #include "remoting/proto/control.pb.h"
21 22
22 namespace remoting { 23 namespace remoting {
23 24
24 namespace { 25 namespace {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 VideoFrameBuffer() { 69 VideoFrameBuffer() {
69 data = 0; 70 data = 0;
70 size = SkISize::Make(0, 0); 71 size = SkISize::Make(0, 0);
71 bytes_per_pixel = 0; 72 bytes_per_pixel = 0;
72 bytes_per_row = 0; 73 bytes_per_row = 0;
73 } 74 }
74 void* data; 75 void* data;
75 SkISize size; 76 SkISize size;
76 int bytes_per_pixel; 77 int bytes_per_pixel;
77 int bytes_per_row; 78 int bytes_per_row;
79 int resource_generation;
78 }; 80 };
79 81
80 // Make sure that the current buffer has the same size as the screen. 82 // Make sure that the device contexts and the current bufffer match the screen
81 void UpdateBufferCapture(const SkISize& size); 83 // configuration.
84 void PrepareCaptureResources();
82 85
83 // Allocate memory for a buffer of a given size, freeing any memory previously 86 // Allocates the specified capture buffer using the current device contexts
84 // allocated for that buffer. 87 // and desktop dimensions, releasing any pre-existing buffer.
85 void ReallocateBuffer(int buffer_index, const SkISize& size); 88 void AllocateBuffer(int buffer_index);
86 89
87 void CalculateInvalidRegion(); 90 void CalculateInvalidRegion();
88 void CaptureRegion(const SkRegion& region, 91 void CaptureRegion(const SkRegion& region,
89 const CaptureCompletedCallback& callback); 92 const CaptureCompletedCallback& callback);
90 93
91 void ReleaseBuffers();
92 // Generates an image in the current buffer. 94 // Generates an image in the current buffer.
93 void CaptureImage(); 95 void CaptureImage();
94 96
95 // Expand the cursor shape to add a white outline for visibility against 97 // Expand the cursor shape to add a white outline for visibility against
96 // dark backgrounds. 98 // dark backgrounds.
97 void AddCursorOutline(int width, int height, uint32* dst); 99 void AddCursorOutline(int width, int height, uint32* dst);
98 100
99 // Capture the current cursor shape. 101 // Capture the current cursor shape.
100 void CaptureCursor(); 102 void CaptureCursor();
101 103
102 // Gets the screen size.
103 SkISize GetScreenSize();
104
105 // A thread-safe list of invalid rectangles, and the size of the most 104 // A thread-safe list of invalid rectangles, and the size of the most
106 // recently captured screen. 105 // recently captured screen.
107 CapturerHelper helper_; 106 CapturerHelper helper_;
108 107
109 // Callback notified whenever the cursor shape is changed. 108 // Callback notified whenever the cursor shape is changed.
110 CursorShapeChangedCallback cursor_shape_changed_callback_; 109 CursorShapeChangedCallback cursor_shape_changed_callback_;
111 110
112 // Snapshot of the last cursor bitmap we sent to the client. This is used 111 // Snapshot of the last cursor bitmap we sent to the client. This is used
113 // to diff against the current cursor so we only send a cursor-change 112 // to diff against the current cursor so we only send a cursor-change
114 // message when the shape has changed. 113 // message when the shape has changed.
115 scoped_array<uint8> last_cursor_; 114 scoped_array<uint8> last_cursor_;
116 SkISize last_cursor_size_; 115 SkISize last_cursor_size_;
117 116
118 // There are two buffers for the screen images, as required by Capturer. 117 // There are two buffers for the screen images, as required by Capturer.
119 static const int kNumBuffers = 2; 118 static const int kNumBuffers = 2;
120 VideoFrameBuffer buffers_[kNumBuffers]; 119 VideoFrameBuffer buffers_[kNumBuffers];
121 120
122 ScopedThreadDesktopWin desktop_; 121 ScopedThreadDesktopWin desktop_;
123 122
124 // Gdi specific information about screen. 123 // GDI resources used for screen capture.
125 HWND desktop_window_; 124 scoped_ptr<base::win::ScopedGetDC> desktop_dc_;
126 HDC desktop_dc_; 125 base::win::ScopedCreateDC memory_dc_;
127 HDC memory_dc_; 126 base::win::ScopedBitmap target_bitmap_[kNumBuffers];
128 HBITMAP target_bitmap_[kNumBuffers]; 127 int resource_generation_;
129 128
130 // The screen size attached to the device contexts through which the screen 129 // Rectangle describing the bounds of the desktop device context.
131 // is captured. 130 SkIRect desktop_dc_rect_;
132 SkISize dc_size_;
133 131
134 // The current buffer with valid data for reading. 132 // The current buffer with valid data for reading.
135 int current_buffer_; 133 int current_buffer_;
136 134
137 // Format of pixels returned in buffer. 135 // Format of pixels returned in buffer.
138 media::VideoFrame::Format pixel_format_; 136 media::VideoFrame::Format pixel_format_;
139 137
140 // Class to calculate the difference between two screen bitmaps. 138 // Class to calculate the difference between two screen bitmaps.
141 scoped_ptr<Differ> differ_; 139 scoped_ptr<Differ> differ_;
142 140
143 base::ScopedNativeLibrary dwmapi_library_; 141 base::ScopedNativeLibrary dwmapi_library_;
144 DwmEnableCompositionFunc composition_func_; 142 DwmEnableCompositionFunc composition_func_;
145 143
146 DISALLOW_COPY_AND_ASSIGN(CapturerGdi); 144 DISALLOW_COPY_AND_ASSIGN(CapturerGdi);
147 }; 145 };
148 146
149 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors. 147 // 3780 pixels per meter is equivalent to 96 DPI, typical on desktop monitors.
150 static const int kPixelsPerMeter = 3780; 148 static const int kPixelsPerMeter = 3780;
151 // 32 bit RGBA is 4 bytes per pixel. 149 // 32 bit RGBA is 4 bytes per pixel.
152 static const int kBytesPerPixel = 4; 150 static const int kBytesPerPixel = 4;
153 151
154 CapturerGdi::CapturerGdi() 152 CapturerGdi::CapturerGdi()
155 : last_cursor_size_(SkISize::Make(0, 0)), 153 : last_cursor_size_(SkISize::Make(0, 0)),
156 desktop_window_(NULL), 154 desktop_dc_rect_(SkIRect::MakeEmpty()),
157 desktop_dc_(NULL), 155 resource_generation_(0),
158 memory_dc_(NULL),
159 dc_size_(SkISize::Make(0, 0)),
160 current_buffer_(0), 156 current_buffer_(0),
161 pixel_format_(media::VideoFrame::RGB32), 157 pixel_format_(media::VideoFrame::RGB32),
162 composition_func_(NULL) { 158 composition_func_(NULL) {
163 memset(target_bitmap_, 0, sizeof(target_bitmap_));
164 memset(buffers_, 0, sizeof(buffers_));
165 ScreenConfigurationChanged(); 159 ScreenConfigurationChanged();
166 } 160 }
167 161
168 CapturerGdi::~CapturerGdi() { 162 CapturerGdi::~CapturerGdi() {
169 ReleaseBuffers();
170 } 163 }
171 164
172 media::VideoFrame::Format CapturerGdi::pixel_format() const { 165 media::VideoFrame::Format CapturerGdi::pixel_format() const {
173 return pixel_format_; 166 return pixel_format_;
174 } 167 }
175 168
176 void CapturerGdi::ClearInvalidRegion() { 169 void CapturerGdi::ClearInvalidRegion() {
177 helper_.ClearInvalidRegion(); 170 helper_.ClearInvalidRegion();
178 } 171 }
179 172
(...skipping 21 matching lines...) Expand all
201 CaptureRegion(invalid_region, callback); 194 CaptureRegion(invalid_region, callback);
202 195
203 // Check for cursor shape update. 196 // Check for cursor shape update.
204 CaptureCursor(); 197 CaptureCursor();
205 } 198 }
206 199
207 const SkISize& CapturerGdi::size_most_recent() const { 200 const SkISize& CapturerGdi::size_most_recent() const {
208 return helper_.size_most_recent(); 201 return helper_.size_most_recent();
209 } 202 }
210 203
211 void CapturerGdi::ReleaseBuffers() {
212 for (int i = kNumBuffers - 1; i >= 0; i--) {
213 if (target_bitmap_[i]) {
214 DeleteObject(target_bitmap_[i]);
215 target_bitmap_[i] = NULL;
216 }
217 if (buffers_[i].data) {
218 DeleteObject(buffers_[i].data);
219 buffers_[i].data = NULL;
220 }
221 }
222
223 if (desktop_dc_) {
224 ReleaseDC(desktop_window_, desktop_dc_);
225 desktop_window_ = NULL;
226 desktop_dc_ = NULL;
227 }
228
229 if (memory_dc_) {
230 DeleteDC(memory_dc_);
231 memory_dc_ = NULL;
232 }
233 }
234
235 void CapturerGdi::Start( 204 void CapturerGdi::Start(
236 const CursorShapeChangedCallback& callback) { 205 const CursorShapeChangedCallback& callback) {
237 cursor_shape_changed_callback_ = callback; 206 cursor_shape_changed_callback_ = callback;
238 207
239 // Load dwmapi.dll dynamically since it is not available on XP. 208 // Load dwmapi.dll dynamically since it is not available on XP.
240 if (!dwmapi_library_.is_valid()) { 209 if (!dwmapi_library_.is_valid()) {
241 FilePath path(base::GetNativeLibraryName(UTF8ToUTF16(kDwmapiLibraryName))); 210 FilePath path(base::GetNativeLibraryName(UTF8ToUTF16(kDwmapiLibraryName)));
242 dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL)); 211 dwmapi_library_.Reset(base::LoadNativeLibrary(path, NULL));
243 } 212 }
244 213
(...skipping 14 matching lines...) Expand all
259 // Restore Aero. 228 // Restore Aero.
260 if (composition_func_ != NULL) { 229 if (composition_func_ != NULL) {
261 (*composition_func_)(DWM_EC_ENABLECOMPOSITION); 230 (*composition_func_)(DWM_EC_ENABLECOMPOSITION);
262 } 231 }
263 } 232 }
264 233
265 void CapturerGdi::ScreenConfigurationChanged() { 234 void CapturerGdi::ScreenConfigurationChanged() {
266 // We poll for screen configuration changes, so ignore notifications. 235 // We poll for screen configuration changes, so ignore notifications.
267 } 236 }
268 237
269 void CapturerGdi::UpdateBufferCapture(const SkISize& size) { 238 void CapturerGdi::PrepareCaptureResources() {
270 // Switch to the desktop receiving user input if different from the current 239 // Switch to the desktop receiving user input if different from the current
271 // one. 240 // one.
272 scoped_ptr<DesktopWin> input_desktop = DesktopWin::GetInputDesktop(); 241 scoped_ptr<DesktopWin> input_desktop = DesktopWin::GetInputDesktop();
273 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { 242 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
274 // Release GDI resources otherwise SetThreadDesktop will fail. 243 // Release GDI resources otherwise SetThreadDesktop will fail.
275 if (desktop_dc_) { 244 desktop_dc_.reset();
276 ReleaseDC(desktop_window_, desktop_dc_); 245 memory_dc_.Set(NULL);
277 desktop_window_ = NULL;
278 desktop_dc_ = NULL;
279 }
280
281 if (memory_dc_) {
282 DeleteDC(memory_dc_);
283 memory_dc_ = NULL;
284 }
285
286 ReleaseBuffers();
287 246
288 // If SetThreadDesktop() fails, the thread is still assigned a desktop. 247 // If SetThreadDesktop() fails, the thread is still assigned a desktop.
289 // So we can continue capture screen bits, just from a diffented desktop. 248 // So we can continue capture screen bits, just from the wrong desktop.
290 desktop_.SetThreadDesktop(input_desktop.Pass()); 249 desktop_.SetThreadDesktop(input_desktop.Pass());
291 } 250 }
292 251
293 // Make sure the DCs have the correct dimensions. 252 // If the display bounds have changed then recreate GDI resources.
294 if (size != dc_size_) { 253 // TODO(wez): Also check for pixel format changes.
295 // TODO(simonmorris): screen dimensions changing isn't equivalent to needing 254 SkIRect screen_rect(SkIRect::MakeXYWH(
296 // a new DC, but it's good enough for now. 255 GetSystemMetrics(SM_XVIRTUALSCREEN),
297 if (desktop_dc_) { 256 GetSystemMetrics(SM_YVIRTUALSCREEN),
298 ReleaseDC(desktop_window_, desktop_dc_); 257 GetSystemMetrics(SM_CXVIRTUALSCREEN),
299 desktop_window_ = NULL; 258 GetSystemMetrics(SM_CYVIRTUALSCREEN)));
300 desktop_dc_ = NULL; 259 if (screen_rect != desktop_dc_rect_) {
301 } 260 desktop_dc_.reset();
302 261 memory_dc_.Set(NULL);
303 if (memory_dc_) { 262 desktop_dc_rect_.setEmpty();
304 DeleteDC(memory_dc_);
305 memory_dc_ = NULL;
306 }
307 } 263 }
308 264
309 if (desktop_dc_ == NULL) { 265 // Create GDI device contexts to capture from the desktop into memory, and
310 DCHECK(desktop_window_ == NULL); 266 // allocate buffers to capture into.
311 DCHECK(memory_dc_ == NULL); 267 if (desktop_dc_.get() == NULL) {
268 DCHECK(memory_dc_.Get() == NULL);
312 269
313 desktop_window_ = GetDesktopWindow(); 270 desktop_dc_.reset(new base::win::ScopedGetDC(NULL));
314 desktop_dc_ = GetDC(desktop_window_); 271 memory_dc_.Set(CreateCompatibleDC(*desktop_dc_));
315 memory_dc_ = CreateCompatibleDC(desktop_dc_); 272 desktop_dc_rect_ = screen_rect;
316 dc_size_ = size; 273
274 ++resource_generation_;
317 } 275 }
318 276
319 // Make sure the current bitmap has the correct dimensions. 277 // If the current buffer is from an older generation then allocate a new one.
320 if (buffers_[current_buffer_].data == NULL || 278 // Note that we can't reallocate other buffers at this point, since the caller
321 size != buffers_[current_buffer_].size) { 279 // may still be reading from them.
322 ReallocateBuffer(current_buffer_, size); 280 if (resource_generation_ != buffers_[current_buffer_].resource_generation) {
281 AllocateBuffer(current_buffer_);
323 InvalidateFullScreen(); 282 InvalidateFullScreen();
324 } 283 }
325 } 284 }
326 285
327 void CapturerGdi::ReallocateBuffer(int buffer_index, const SkISize& size) { 286 void CapturerGdi::AllocateBuffer(int buffer_index) {
328 // Delete any previously constructed bitmap. 287 DCHECK(desktop_dc_.get() != NULL);
329 if (target_bitmap_[buffer_index]) { 288 DCHECK(memory_dc_.Get() != NULL);
330 DeleteObject(target_bitmap_[buffer_index]);
331 target_bitmap_[buffer_index] = NULL;
332 }
333 if (buffers_[buffer_index].data) {
334 DeleteObject(buffers_[buffer_index].data);
335 buffers_[buffer_index].data = NULL;
336 }
337 289
338 // Create a bitmap to keep the desktop image. 290 // Windows requires DIB sections' rows to start DWORD-aligned, which is
339 int rounded_width = (size.width() + 3) & (~3); 291 // implicit when working with RGB32 pixels.
292 DCHECK_EQ(pixel_format_, media::VideoFrame::RGB32);
340 293
341 // Dimensions of screen. 294 // Describe a device independent bitmap (DIB) that is the size of the desktop.
342 pixel_format_ = media::VideoFrame::RGB32;
343 int bytes_per_row = rounded_width * kBytesPerPixel;
344
345 // Create a device independent bitmap (DIB) that is the same size.
346 BITMAPINFO bmi; 295 BITMAPINFO bmi;
347 memset(&bmi, 0, sizeof(bmi)); 296 memset(&bmi, 0, sizeof(bmi));
348 bmi.bmiHeader.biHeight = -size.height(); 297 bmi.bmiHeader.biHeight = -desktop_dc_rect_.height();
349 bmi.bmiHeader.biWidth = rounded_width; 298 bmi.bmiHeader.biWidth = desktop_dc_rect_.width();
350 bmi.bmiHeader.biPlanes = 1; 299 bmi.bmiHeader.biPlanes = 1;
351 bmi.bmiHeader.biBitCount = kBytesPerPixel * 8; 300 bmi.bmiHeader.biBitCount = kBytesPerPixel * 8;
352 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); 301 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
353 bmi.bmiHeader.biSizeImage = bytes_per_row * size.height(); 302 int bytes_per_row = desktop_dc_rect_.width() * kBytesPerPixel;
303 bmi.bmiHeader.biSizeImage = bytes_per_row * desktop_dc_rect_.height();
354 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter; 304 bmi.bmiHeader.biXPelsPerMeter = kPixelsPerMeter;
355 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter; 305 bmi.bmiHeader.biYPelsPerMeter = kPixelsPerMeter;
356 306
357 // Create memory for the buffers. 307 // Create the DIB, and store a pointer to its pixel buffer.
358 target_bitmap_[buffer_index] = 308 target_bitmap_[buffer_index] =
359 CreateDIBSection(desktop_dc_, &bmi, DIB_RGB_COLORS, 309 CreateDIBSection(*desktop_dc_, &bmi, DIB_RGB_COLORS,
360 static_cast<void**>(&buffers_[buffer_index].data), 310 static_cast<void**>(&buffers_[buffer_index].data),
361 NULL, 0); 311 NULL, 0);
362 buffers_[buffer_index].size = SkISize::Make(bmi.bmiHeader.biWidth, 312 buffers_[buffer_index].size = SkISize::Make(bmi.bmiHeader.biWidth,
363 std::abs(bmi.bmiHeader.biHeight)); 313 std::abs(bmi.bmiHeader.biHeight));
364 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8; 314 buffers_[buffer_index].bytes_per_pixel = bmi.bmiHeader.biBitCount / 8;
365 buffers_[buffer_index].bytes_per_row = 315 buffers_[buffer_index].bytes_per_row =
366 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight); 316 bmi.bmiHeader.biSizeImage / std::abs(bmi.bmiHeader.biHeight);
367 } 317 }
368 318
369 void CapturerGdi::CalculateInvalidRegion() { 319 void CapturerGdi::CalculateInvalidRegion() {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 buffer.size, 366 buffer.size,
417 pixel_format_)); 367 pixel_format_));
418 data->mutable_dirty_region() = region; 368 data->mutable_dirty_region() = region;
419 369
420 helper_.set_size_most_recent(data->size()); 370 helper_.set_size_most_recent(data->size());
421 371
422 callback.Run(data); 372 callback.Run(data);
423 } 373 }
424 374
425 void CapturerGdi::CaptureImage() { 375 void CapturerGdi::CaptureImage() {
426 // Make sure the structures we use to capture the image have the correct size. 376 // Make sure the GDI capture resources are up-to-date.
427 UpdateBufferCapture(GetScreenSize()); 377 PrepareCaptureResources();
428 378
429 // Select the target bitmap into the memory dc. 379 // Select the target bitmap into the memory dc.
430 SelectObject(memory_dc_, target_bitmap_[current_buffer_]); 380 SelectObject(memory_dc_, target_bitmap_[current_buffer_]);
431 381
432 // And then copy the rect from desktop to memory. 382 // And then copy the rect from desktop to memory.
433 BitBlt(memory_dc_, 0, 0, buffers_[current_buffer_].size.width(), 383 BitBlt(memory_dc_, 0, 0, buffers_[current_buffer_].size.width(),
434 buffers_[current_buffer_].size.height(), desktop_dc_, 0, 0, 384 buffers_[current_buffer_].size.height(), *desktop_dc_,
385 desktop_dc_rect_.x(), desktop_dc_rect_.y(),
435 SRCCOPY | CAPTUREBLT); 386 SRCCOPY | CAPTUREBLT);
436 } 387 }
437 388
438 void CapturerGdi::AddCursorOutline(int width, int height, uint32* dst) { 389 void CapturerGdi::AddCursorOutline(int width, int height, uint32* dst) {
439 for (int y = 0; y < height; y++) { 390 for (int y = 0; y < height; y++) {
440 for (int x = 0; x < width; x++) { 391 for (int x = 0; x < width; x++) {
441 // If this is a transparent pixel (bgr == 0 and alpha = 0), check the 392 // If this is a transparent pixel (bgr == 0 and alpha = 0), check the
442 // neighbor pixels to see if this should be changed to an outline pixel. 393 // neighbor pixels to see if this should be changed to an outline pixel.
443 if (*dst == kPixelBgraTransparent) { 394 if (*dst == kPixelBgraTransparent) {
444 // Change to white pixel if any neighbors (top, bottom, left, right) 395 // Change to white pixel if any neighbors (top, bottom, left, right)
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 cursor_proto->set_hotspot_y(hotspot_y); 552 cursor_proto->set_hotspot_y(hotspot_y);
602 553
603 // Record the last cursor image that we sent to the client. 554 // Record the last cursor image that we sent to the client.
604 last_cursor_.reset(new uint8[data_size]); 555 last_cursor_.reset(new uint8[data_size]);
605 memcpy(last_cursor_.get(), cursor_dst_data, data_size); 556 memcpy(last_cursor_.get(), cursor_dst_data, data_size);
606 last_cursor_size_ = SkISize::Make(width, height); 557 last_cursor_size_ = SkISize::Make(width, height);
607 558
608 cursor_shape_changed_callback_.Run(cursor_proto.Pass()); 559 cursor_shape_changed_callback_.Run(cursor_proto.Pass());
609 } 560 }
610 561
611 SkISize CapturerGdi::GetScreenSize() {
612 return SkISize::Make(GetSystemMetrics(SM_CXSCREEN),
613 GetSystemMetrics(SM_CYSCREEN));
614 }
615
616 } // namespace 562 } // namespace
617 563
618 // static 564 // static
619 Capturer* Capturer::Create() { 565 Capturer* Capturer::Create() {
620 return new CapturerGdi(); 566 return new CapturerGdi();
621 } 567 }
622 568
623 } // namespace remoting 569 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698