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

Side by Side Diff: remoting/host/video_frame_capturer_mac.mm

Issue 10833060: Update for OS X 10.6 SDK. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: "Added TODO to clean up the use of private APIs." Created 8 years, 4 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 | « remoting/host/event_executor_mac.cc ('k') | 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/video_frame_capturer.h" 5 #include "remoting/host/video_frame_capturer.h"
6 6
7 #include <ApplicationServices/ApplicationServices.h> 7 #include <ApplicationServices/ApplicationServices.h>
8 #include <Cocoa/Cocoa.h> 8 #include <Cocoa/Cocoa.h>
9 #include <dlfcn.h> 9 #include <dlfcn.h>
10 #include <IOKit/pwr_mgt/IOPMLib.h> 10 #include <IOKit/pwr_mgt/IOPMLib.h>
(...skipping 19 matching lines...) Expand all
30 SkIRect CGRectToSkIRect(const CGRect& rect) { 30 SkIRect CGRectToSkIRect(const CGRect& rect) {
31 SkIRect sk_rect = { 31 SkIRect sk_rect = {
32 SkScalarRound(rect.origin.x), 32 SkScalarRound(rect.origin.x),
33 SkScalarRound(rect.origin.y), 33 SkScalarRound(rect.origin.y),
34 SkScalarRound(rect.origin.x + rect.size.width), 34 SkScalarRound(rect.origin.x + rect.size.width),
35 SkScalarRound(rect.origin.y + rect.size.height) 35 SkScalarRound(rect.origin.y + rect.size.height)
36 }; 36 };
37 return sk_rect; 37 return sk_rect;
38 } 38 }
39 39
40 #if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5)
41 // Possibly remove VideoFrameCapturerMac::CgBlitPreLion as well depending on
42 // performance of VideoFrameCapturerMac::CgBlitPostLion on 10.6.
43 #error No longer need to import CGDisplayCreateImage.
44 #else
45 // Declared here because CGDisplayCreateImage does not exist in the 10.5 SDK,
46 // which we are currently compiling against, and it is required on 10.7 to do
47 // screen capture.
48 typedef CGImageRef (*CGDisplayCreateImageFunc)(CGDirectDisplayID displayID);
49 #endif
50
51 // The amount of time allowed for displays to reconfigure. 40 // The amount of time allowed for displays to reconfigure.
52 const int64 kDisplayReconfigurationTimeoutInSeconds = 10; 41 const int64 kDisplayReconfigurationTimeoutInSeconds = 10;
53 42
54 class scoped_pixel_buffer_object { 43 class scoped_pixel_buffer_object {
55 public: 44 public:
56 scoped_pixel_buffer_object(); 45 scoped_pixel_buffer_object();
57 ~scoped_pixel_buffer_object(); 46 ~scoped_pixel_buffer_object();
58 47
59 bool Init(CGLContextObj cgl_context, int size_in_bytes); 48 bool Init(CGLContextObj cgl_context, int size_in_bytes);
60 void Release(); 49 void Release();
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // Contains an invalid region from the previous capture. 225 // Contains an invalid region from the previous capture.
237 SkRegion last_invalid_region_; 226 SkRegion last_invalid_region_;
238 227
239 // Format of pixels returned in buffer. 228 // Format of pixels returned in buffer.
240 media::VideoFrame::Format pixel_format_; 229 media::VideoFrame::Format pixel_format_;
241 230
242 // Acts as a critical section around our display configuration data 231 // Acts as a critical section around our display configuration data
243 // structures. Specifically cgl_context_ and pixel_buffer_object_. 232 // structures. Specifically cgl_context_ and pixel_buffer_object_.
244 base::WaitableEvent display_configuration_capture_event_; 233 base::WaitableEvent display_configuration_capture_event_;
245 234
246 // Will be non-null on lion.
247 CGDisplayCreateImageFunc display_create_image_func_;
248
249 // Power management assertion to prevent the screen from sleeping. 235 // Power management assertion to prevent the screen from sleeping.
250 IOPMAssertionID power_assertion_id_display_; 236 IOPMAssertionID power_assertion_id_display_;
251 237
252 // Power management assertion to indicate that the user is active. 238 // Power management assertion to indicate that the user is active.
253 IOPMAssertionID power_assertion_id_user_; 239 IOPMAssertionID power_assertion_id_user_;
254 240
255 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac); 241 DISALLOW_COPY_AND_ASSIGN(VideoFrameCapturerMac);
256 }; 242 };
257 243
258 VideoFrameCapturerMac::VideoFrameCapturerMac() 244 VideoFrameCapturerMac::VideoFrameCapturerMac()
259 : cgl_context_(NULL), 245 : cgl_context_(NULL),
260 current_buffer_(0), 246 current_buffer_(0),
261 last_buffer_(NULL), 247 last_buffer_(NULL),
262 pixel_format_(media::VideoFrame::RGB32), 248 pixel_format_(media::VideoFrame::RGB32),
263 display_configuration_capture_event_(false, true), 249 display_configuration_capture_event_(false, true),
264 display_create_image_func_(NULL),
265 power_assertion_id_display_(kIOPMNullAssertionID), 250 power_assertion_id_display_(kIOPMNullAssertionID),
266 power_assertion_id_user_(kIOPMNullAssertionID) { 251 power_assertion_id_user_(kIOPMNullAssertionID) {
267 } 252 }
268 253
269 VideoFrameCapturerMac::~VideoFrameCapturerMac() { 254 VideoFrameCapturerMac::~VideoFrameCapturerMac() {
270 ReleaseBuffers(); 255 ReleaseBuffers();
271 CGUnregisterScreenRefreshCallback( 256 CGUnregisterScreenRefreshCallback(
272 VideoFrameCapturerMac::ScreenRefreshCallback, this); 257 VideoFrameCapturerMac::ScreenRefreshCallback, this);
273 CGScreenUnregisterMoveCallback( 258 CGScreenUnregisterMoveCallback(
274 VideoFrameCapturerMac::ScreenUpdateMoveCallback, this); 259 VideoFrameCapturerMac::ScreenUpdateMoveCallback, this);
(...skipping 18 matching lines...) Expand all
293 LOG(ERROR) << "CGScreenRegisterMoveCallback " << err; 278 LOG(ERROR) << "CGScreenRegisterMoveCallback " << err;
294 return false; 279 return false;
295 } 280 }
296 err = CGDisplayRegisterReconfigurationCallback( 281 err = CGDisplayRegisterReconfigurationCallback(
297 VideoFrameCapturerMac::DisplaysReconfiguredCallback, this); 282 VideoFrameCapturerMac::DisplaysReconfiguredCallback, this);
298 if (err != kCGErrorSuccess) { 283 if (err != kCGErrorSuccess) {
299 LOG(ERROR) << "CGDisplayRegisterReconfigurationCallback " << err; 284 LOG(ERROR) << "CGDisplayRegisterReconfigurationCallback " << err;
300 return false; 285 return false;
301 } 286 }
302 287
303 if (base::mac::IsOSLionOrLater()) {
304 display_create_image_func_ =
305 reinterpret_cast<CGDisplayCreateImageFunc>(
306 dlsym(RTLD_NEXT, "CGDisplayCreateImage"));
307 if (!display_create_image_func_) {
308 LOG(ERROR) << "Unable to load CGDisplayCreateImage on Lion";
309 return false;
310 }
311 }
312 ScreenConfigurationChanged(); 288 ScreenConfigurationChanged();
313 return true; 289 return true;
314 } 290 }
315 291
316 void VideoFrameCapturerMac::ReleaseBuffers() { 292 void VideoFrameCapturerMac::ReleaseBuffers() {
317 if (cgl_context_) { 293 if (cgl_context_) {
318 pixel_buffer_object_.Release(); 294 pixel_buffer_object_.Release();
319 CGLDestroyContext(cgl_context_); 295 CGLDestroyContext(cgl_context_);
320 cgl_context_ = NULL; 296 cgl_context_ = NULL;
321 } 297 }
322 // The buffers might be in use by the encoder, so don't delete them here. 298 // The buffers might be in use by the encoder, so don't delete them here.
323 // Instead, mark them as "needs update"; next time the buffers are used by 299 // Instead, mark them as "needs update"; next time the buffers are used by
324 // the capturer, they will be recreated if necessary. 300 // the capturer, they will be recreated if necessary.
325 for (int i = 0; i < kNumBuffers; ++i) { 301 for (int i = 0; i < kNumBuffers; ++i) {
326 buffers_[i].set_needs_update(); 302 buffers_[i].set_needs_update();
327 } 303 }
328 } 304 }
329 305
330 void VideoFrameCapturerMac::Start(const CursorShapeChangedCallback& callback) { 306 void VideoFrameCapturerMac::Start(const CursorShapeChangedCallback& callback) {
331 cursor_shape_changed_callback_ = callback; 307 cursor_shape_changed_callback_ = callback;
332 308
333 // Create power management assertions to wake the display and prevent it from 309 // Create power management assertions to wake the display and prevent it from
334 // going to sleep on user idle. 310 // going to sleep on user idle.
335 IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep, 311 // TODO(jamiewalch): Use IOPMAssertionDeclareUserActivity on 10.7.3 and above.
336 kIOPMAssertionLevelOn, 312 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
337 &power_assertion_id_display_); 313 kIOPMAssertionLevelOn,
338 IOPMAssertionCreate(CFSTR("UserIsActive"), 314 CFSTR("Chrome Remote Desktop connection active"),
339 kIOPMAssertionLevelOn, 315 &power_assertion_id_display_);
340 &power_assertion_id_user_); 316 IOPMAssertionCreateWithName(CFSTR("UserIsActive"),
Avi (use Gerrit) 2012/07/30 21:04:36 Can you please put in a brief note as to where you
Jamie 2012/07/30 23:47:15 Done.
317 kIOPMAssertionLevelOn,
318 CFSTR("Chrome Remote Desktop connection active"),
319 &power_assertion_id_user_);
341 } 320 }
342 321
343 void VideoFrameCapturerMac::Stop() { 322 void VideoFrameCapturerMac::Stop() {
344 if (power_assertion_id_display_ != kIOPMNullAssertionID) { 323 if (power_assertion_id_display_ != kIOPMNullAssertionID) {
345 IOPMAssertionRelease(power_assertion_id_display_); 324 IOPMAssertionRelease(power_assertion_id_display_);
346 power_assertion_id_display_ = kIOPMNullAssertionID; 325 power_assertion_id_display_ = kIOPMNullAssertionID;
347 } 326 }
348 if (power_assertion_id_user_ != kIOPMNullAssertionID) { 327 if (power_assertion_id_user_ != kIOPMNullAssertionID) {
349 IOPMAssertionRelease(power_assertion_id_user_); 328 IOPMAssertionRelease(power_assertion_id_user_);
350 power_assertion_id_user_ = kIOPMNullAssertionID; 329 power_assertion_id_user_ = kIOPMNullAssertionID;
(...skipping 15 matching lines...) Expand all
366 345
367 // Critical section shared with DisplaysReconfigured(...). 346 // Critical section shared with DisplaysReconfigured(...).
368 CHECK(display_configuration_capture_event_.TimedWait( 347 CHECK(display_configuration_capture_event_.TimedWait(
369 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds))); 348 base::TimeDelta::FromSeconds(kDisplayReconfigurationTimeoutInSeconds)));
370 SkRegion region; 349 SkRegion region;
371 helper_.SwapInvalidRegion(&region); 350 helper_.SwapInvalidRegion(&region);
372 VideoFrameBuffer& current_buffer = buffers_[current_buffer_]; 351 VideoFrameBuffer& current_buffer = buffers_[current_buffer_];
373 current_buffer.Update(); 352 current_buffer.Update();
374 353
375 bool flip = false; // GL capturers need flipping. 354 bool flip = false; // GL capturers need flipping.
376 if (display_create_image_func_ != NULL) { 355 if (base::mac::IsOSLionOrLater()) {
377 // Lion requires us to use their new APIs for doing screen capture. 356 // Lion requires us to use their new APIs for doing screen capture. These
357 // APIS currently crash on 10.6.8 if there is no monitor attached.
378 CgBlitPostLion(current_buffer, region); 358 CgBlitPostLion(current_buffer, region);
379 } else if (cgl_context_) { 359 } else if (cgl_context_) {
380 flip = true; 360 flip = true;
381 if (pixel_buffer_object_.get() != 0) { 361 if (pixel_buffer_object_.get() != 0) {
382 GlBlitFast(current_buffer, region); 362 GlBlitFast(current_buffer, region);
383 } else { 363 } else {
384 // See comment in scoped_pixel_buffer_object::Init about why the slow 364 // See comment in scoped_pixel_buffer_object::Init about why the slow
385 // path is always used on 10.5. 365 // path is always used on 10.5.
386 GlBlitSlow(current_buffer); 366 GlBlitSlow(current_buffer);
387 } 367 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 const int buffer_height = buffer.size().height(); 564 const int buffer_height = buffer.size().height();
585 const int buffer_width = buffer.size().width(); 565 const int buffer_width = buffer.size().width();
586 566
587 // Clip to the size of our current screen. 567 // Clip to the size of our current screen.
588 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); 568 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height);
589 569
590 if (last_buffer_) 570 if (last_buffer_)
591 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); 571 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height);
592 last_buffer_ = buffer.ptr(); 572 last_buffer_ = buffer.ptr();
593 CGDirectDisplayID main_display = CGMainDisplayID(); 573 CGDirectDisplayID main_display = CGMainDisplayID();
574 #pragma clang diagnostic push
575 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
594 uint8* display_base_address = 576 uint8* display_base_address =
595 reinterpret_cast<uint8*>(CGDisplayBaseAddress(main_display)); 577 reinterpret_cast<uint8*>(CGDisplayBaseAddress(main_display));
596 CHECK(display_base_address); 578 CHECK(display_base_address);
597 int src_bytes_per_row = CGDisplayBytesPerRow(main_display); 579 int src_bytes_per_row = CGDisplayBytesPerRow(main_display);
598 int src_bytes_per_pixel = CGDisplayBitsPerPixel(main_display) / 8; 580 int src_bytes_per_pixel = CGDisplayBitsPerPixel(main_display) / 8;
581 #pragma clang diagnostic pop
599 // TODO(hclam): We can reduce the amount of copying here by subtracting 582 // TODO(hclam): We can reduce the amount of copying here by subtracting
600 // |capturer_helper_|s region from |last_invalid_region_|. 583 // |capturer_helper_|s region from |last_invalid_region_|.
601 // http://crbug.com/92354 584 // http://crbug.com/92354
602 for(SkRegion::Iterator i(region); !i.done(); i.next()) { 585 for(SkRegion::Iterator i(region); !i.done(); i.next()) {
603 SkIRect copy_rect = i.rect(); 586 SkIRect copy_rect = i.rect();
604 if (copy_rect.intersect(clip_rect)) { 587 if (copy_rect.intersect(clip_rect)) {
605 CopyRect(display_base_address, 588 CopyRect(display_base_address,
606 src_bytes_per_row, 589 src_bytes_per_row,
607 buffer.ptr(), 590 buffer.ptr(),
608 buffer.bytes_per_row(), 591 buffer.bytes_per_row(),
609 src_bytes_per_pixel, 592 src_bytes_per_pixel,
610 copy_rect); 593 copy_rect);
611 } 594 }
612 } 595 }
613 } 596 }
614 597
615 void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrameBuffer& buffer, 598 void VideoFrameCapturerMac::CgBlitPostLion(const VideoFrameBuffer& buffer,
616 const SkRegion& region) { 599 const SkRegion& region) {
617 const int buffer_height = buffer.size().height(); 600 const int buffer_height = buffer.size().height();
618 const int buffer_width = buffer.size().width(); 601 const int buffer_width = buffer.size().width();
619 602
620 // Clip to the size of our current screen. 603 // Clip to the size of our current screen.
621 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height); 604 SkIRect clip_rect = SkIRect::MakeWH(buffer_width, buffer_height);
622 605
623 if (last_buffer_) 606 if (last_buffer_)
624 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height); 607 memcpy(buffer.ptr(), last_buffer_, buffer.bytes_per_row() * buffer_height);
625 last_buffer_ = buffer.ptr(); 608 last_buffer_ = buffer.ptr();
626 CGDirectDisplayID display = CGMainDisplayID(); 609 CGDirectDisplayID display = CGMainDisplayID();
627 base::mac::ScopedCFTypeRef<CGImageRef> image( 610 base::mac::ScopedCFTypeRef<CGImageRef> image(
628 display_create_image_func_(display)); 611 CGDisplayCreateImage(display));
629 if (image.get() == NULL) 612 if (image.get() == NULL)
630 return; 613 return;
631 CGDataProviderRef provider = CGImageGetDataProvider(image); 614 CGDataProviderRef provider = CGImageGetDataProvider(image);
632 base::mac::ScopedCFTypeRef<CFDataRef> data(CGDataProviderCopyData(provider)); 615 base::mac::ScopedCFTypeRef<CFDataRef> data(CGDataProviderCopyData(provider));
633 if (data.get() == NULL) 616 if (data.get() == NULL)
634 return; 617 return;
635 const uint8* display_base_address = CFDataGetBytePtr(data); 618 const uint8* display_base_address = CFDataGetBytePtr(data);
636 int src_bytes_per_row = CGImageGetBytesPerRow(image); 619 int src_bytes_per_row = CGImageGetBytesPerRow(image);
637 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8; 620 int src_bytes_per_pixel = CGImageGetBitsPerPixel(image) / 8;
638 // TODO(hclam): We can reduce the amount of copying here by subtracting 621 // TODO(hclam): We can reduce the amount of copying here by subtracting
(...skipping 19 matching lines...) Expand all
658 void VideoFrameCapturerMac::ScreenConfigurationChanged() { 641 void VideoFrameCapturerMac::ScreenConfigurationChanged() {
659 ReleaseBuffers(); 642 ReleaseBuffers();
660 helper_.ClearInvalidRegion(); 643 helper_.ClearInvalidRegion();
661 last_buffer_ = NULL; 644 last_buffer_ = NULL;
662 645
663 CGDirectDisplayID mainDevice = CGMainDisplayID(); 646 CGDirectDisplayID mainDevice = CGMainDisplayID();
664 int width = CGDisplayPixelsWide(mainDevice); 647 int width = CGDisplayPixelsWide(mainDevice);
665 int height = CGDisplayPixelsHigh(mainDevice); 648 int height = CGDisplayPixelsHigh(mainDevice);
666 helper_.InvalidateScreen(SkISize::Make(width, height)); 649 helper_.InvalidateScreen(SkISize::Make(width, height));
667 650
668 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) { 651 if (base::mac::IsOSLionOrLater()) {
669 VLOG(3) << "OpenGL support not available."; 652 LOG(INFO) << "Using CgBlitPostLion.";
Robert Sesek 2012/07/30 21:50:37 This will be spammy, along with the other LOG stat
Jamie 2012/07/30 21:55:53 It should only be logged once per Chromoting sessi
670 return;
671 }
672
673 if (display_create_image_func_ != NULL) {
674 // No need for any OpenGL support on Lion 653 // No need for any OpenGL support on Lion
675 return; 654 return;
676 } 655 }
677 656
657 if (!CGDisplayUsesOpenGLAcceleration(mainDevice)) {
658 LOG(INFO) << "Using CgBlitPreLion.";
659 return;
660 }
661
662 LOG(INFO) << "Using GlBlit";
663
678 CGLPixelFormatAttribute attributes[] = { 664 CGLPixelFormatAttribute attributes[] = {
679 kCGLPFAFullScreen, 665 kCGLPFAFullScreen,
680 kCGLPFADisplayMask, 666 kCGLPFADisplayMask,
681 (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice), 667 (CGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(mainDevice),
682 (CGLPixelFormatAttribute)0 668 (CGLPixelFormatAttribute)0
683 }; 669 };
684 CGLPixelFormatObj pixel_format = NULL; 670 CGLPixelFormatObj pixel_format = NULL;
685 GLint matching_pixel_format_count = 0; 671 GLint matching_pixel_format_count = 0;
686 CGLError err = CGLChoosePixelFormat(attributes, 672 CGLError err = CGLChoosePixelFormat(attributes,
687 &pixel_format, 673 &pixel_format,
688 &matching_pixel_format_count); 674 &matching_pixel_format_count);
689 DCHECK_EQ(err, kCGLNoError); 675 DCHECK_EQ(err, kCGLNoError);
690 err = CGLCreateContext(pixel_format, NULL, &cgl_context_); 676 err = CGLCreateContext(pixel_format, NULL, &cgl_context_);
691 DCHECK_EQ(err, kCGLNoError); 677 DCHECK_EQ(err, kCGLNoError);
692 CGLDestroyPixelFormat(pixel_format); 678 CGLDestroyPixelFormat(pixel_format);
693 CGLSetFullScreen(cgl_context_); 679 CGLSetFullScreenOnDisplay(cgl_context_,
680 CGDisplayIDToOpenGLDisplayMask(mainDevice));
694 CGLSetCurrentContext(cgl_context_); 681 CGLSetCurrentContext(cgl_context_);
695 682
696 size_t buffer_size = width * height * sizeof(uint32_t); 683 size_t buffer_size = width * height * sizeof(uint32_t);
697 pixel_buffer_object_.Init(cgl_context_, buffer_size); 684 pixel_buffer_object_.Init(cgl_context_, buffer_size);
698 } 685 }
699 686
700 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count, 687 void VideoFrameCapturerMac::ScreenRefresh(CGRectCount count,
701 const CGRect* rect_array) { 688 const CGRect* rect_array) {
702 SkIRect skirect_array[count]; 689 SkIRect skirect_array[count];
703 for (CGRectCount i = 0; i < count; ++i) { 690 for (CGRectCount i = 0; i < count; ++i) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 VideoFrameCapturer* VideoFrameCapturer::Create() { 761 VideoFrameCapturer* VideoFrameCapturer::Create() {
775 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac(); 762 VideoFrameCapturerMac* capturer = new VideoFrameCapturerMac();
776 if (!capturer->Init()) { 763 if (!capturer->Init()) {
777 delete capturer; 764 delete capturer;
778 capturer = NULL; 765 capturer = NULL;
779 } 766 }
780 return capturer; 767 return capturer;
781 } 768 }
782 769
783 } // namespace remoting 770 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/event_executor_mac.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698