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 |
(...skipping 18 matching lines...) Expand all Loading... | |
29 #include "webrtc/system_wrappers/include/logging.h" | 29 #include "webrtc/system_wrappers/include/logging.h" |
30 | 30 |
31 namespace webrtc { | 31 namespace webrtc { |
32 | 32 |
33 namespace { | 33 namespace { |
34 | 34 |
35 // Convenience wrapper for XGetWindowProperty() results. | 35 // Convenience wrapper for XGetWindowProperty() results. |
36 template <class PropertyType> | 36 template <class PropertyType> |
37 class XWindowProperty { | 37 class XWindowProperty { |
38 public: | 38 public: |
39 XWindowProperty(Display* display, Window window, Atom property) | 39 XWindowProperty(Display* display, Window window, Atom property) { |
40 : is_valid_(false), | |
41 size_(0), | |
42 data_(NULL) { | |
43 const int kBitsPerByte = 8; | 40 const int kBitsPerByte = 8; |
44 Atom actual_type; | 41 Atom actual_type; |
45 int actual_format; | 42 int actual_format; |
46 unsigned long bytes_after; // NOLINT: type required by XGetWindowProperty | 43 unsigned long bytes_after; // NOLINT: type required by XGetWindowProperty |
47 int status = XGetWindowProperty(display, window, property, 0L, ~0L, False, | 44 int status = XGetWindowProperty(display, window, property, 0L, ~0L, False, |
48 AnyPropertyType, &actual_type, | 45 AnyPropertyType, &actual_type, |
49 &actual_format, &size_, | 46 &actual_format, &size_, |
50 &bytes_after, &data_); | 47 &bytes_after, &data_); |
51 if (status != Success) { | 48 if (status != Success) { |
52 data_ = NULL; | 49 data_ = nullptr; |
53 return; | 50 return; |
54 } | 51 } |
55 if (sizeof(PropertyType) * kBitsPerByte != actual_format) { | 52 if (sizeof(PropertyType) * kBitsPerByte != actual_format) { |
56 size_ = 0; | 53 size_ = 0; |
57 return; | 54 return; |
58 } | 55 } |
59 | 56 |
60 is_valid_ = true; | 57 is_valid_ = true; |
61 } | 58 } |
62 | 59 |
63 ~XWindowProperty() { | 60 ~XWindowProperty() { |
64 if (data_) | 61 if (data_) |
65 XFree(data_); | 62 XFree(data_); |
66 } | 63 } |
67 | 64 |
68 // True if we got properly value successfully. | 65 // True if we got properly value successfully. |
69 bool is_valid() const { return is_valid_; } | 66 bool is_valid() const { return is_valid_; } |
70 | 67 |
71 // Size and value of the property. | 68 // Size and value of the property. |
72 size_t size() const { return size_; } | 69 size_t size() const { return size_; } |
73 const PropertyType* data() const { | 70 const PropertyType* data() const { |
74 return reinterpret_cast<PropertyType*>(data_); | 71 return reinterpret_cast<PropertyType*>(data_); |
75 } | 72 } |
76 PropertyType* data() { | 73 PropertyType* data() { |
77 return reinterpret_cast<PropertyType*>(data_); | 74 return reinterpret_cast<PropertyType*>(data_); |
78 } | 75 } |
79 | 76 |
80 private: | 77 private: |
81 bool is_valid_; | 78 bool is_valid_ = false; |
82 unsigned long size_; // NOLINT: type required by XGetWindowProperty | 79 unsigned long size_ = 0; // NOLINT: type required by XGetWindowProperty |
83 unsigned char* data_; | 80 unsigned char* data_ = nullptr; |
84 | 81 |
85 RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty); | 82 RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty); |
86 }; | 83 }; |
87 | 84 |
88 class WindowCapturerLinux : public WindowCapturer, | 85 class WindowCapturerLinux : public WindowCapturer, |
89 public SharedXDisplay::XEventHandler { | 86 public SharedXDisplay::XEventHandler { |
90 public: | 87 public: |
91 WindowCapturerLinux(const DesktopCaptureOptions& options); | 88 WindowCapturerLinux(const DesktopCaptureOptions& options); |
92 virtual ~WindowCapturerLinux(); | 89 virtual ~WindowCapturerLinux(); |
93 | 90 |
(...skipping 16 matching lines...) Expand all Loading... | |
110 // that has WM_STATE property set to NormalState. | 107 // that has WM_STATE property set to NormalState. |
111 // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 . | 108 // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 . |
112 ::Window GetApplicationWindow(::Window window); | 109 ::Window GetApplicationWindow(::Window window); |
113 | 110 |
114 // Returns true if the |window| is a desktop element. | 111 // Returns true if the |window| is a desktop element. |
115 bool IsDesktopElement(::Window window); | 112 bool IsDesktopElement(::Window window); |
116 | 113 |
117 // Returns window title for the specified X |window|. | 114 // Returns window title for the specified X |window|. |
118 bool GetWindowTitle(::Window window, std::string* title); | 115 bool GetWindowTitle(::Window window, std::string* title); |
119 | 116 |
120 Callback* callback_; | 117 Callback* callback_ = nullptr; |
121 | 118 |
122 rtc::scoped_refptr<SharedXDisplay> x_display_; | 119 rtc::scoped_refptr<SharedXDisplay> x_display_; |
123 | 120 |
124 Atom wm_state_atom_; | 121 Atom wm_state_atom_; |
125 Atom window_type_atom_; | 122 Atom window_type_atom_; |
126 Atom normal_window_type_atom_; | 123 Atom normal_window_type_atom_; |
127 bool has_composite_extension_; | 124 bool has_composite_extension_ = false; |
128 | 125 |
129 ::Window selected_window_; | 126 ::Window selected_window_ = 0; |
130 XServerPixelBuffer x_server_pixel_buffer_; | 127 XServerPixelBuffer x_server_pixel_buffer_; |
131 | 128 |
132 RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux); | 129 RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux); |
133 }; | 130 }; |
134 | 131 |
135 WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) | 132 WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) |
136 : callback_(NULL), | 133 : x_display_(options.x_display()) { |
137 x_display_(options.x_display()), | |
138 has_composite_extension_(false), | |
139 selected_window_(0) { | |
140 // Create Atoms so we don't need to do it every time they are used. | 134 // Create Atoms so we don't need to do it every time they are used. |
141 wm_state_atom_ = XInternAtom(display(), "WM_STATE", True); | 135 wm_state_atom_ = XInternAtom(display(), "WM_STATE", True); |
142 window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True); | 136 window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True); |
143 normal_window_type_atom_ = XInternAtom( | 137 normal_window_type_atom_ = XInternAtom( |
144 display(), "_NET_WM_WINDOW_TYPE_NORMAL", True); | 138 display(), "_NET_WM_WINDOW_TYPE_NORMAL", True); |
145 | 139 |
146 int event_base, error_base, major_version, minor_version; | 140 int event_base, error_base, major_version, minor_version; |
147 if (XCompositeQueryExtension(display(), &event_base, &error_base) && | 141 if (XCompositeQueryExtension(display(), &event_base, &error_base) && |
148 XCompositeQueryVersion(display(), &major_version, &minor_version) && | 142 XCompositeQueryVersion(display(), &major_version, &minor_version) && |
149 // XCompositeNameWindowPixmap() requires version 0.2 | 143 // XCompositeNameWindowPixmap() requires version 0.2 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 void WindowCapturerLinux::Start(Callback* callback) { | 267 void WindowCapturerLinux::Start(Callback* callback) { |
274 assert(!callback_); | 268 assert(!callback_); |
275 assert(callback); | 269 assert(callback); |
276 | 270 |
277 callback_ = callback; | 271 callback_ = callback; |
278 } | 272 } |
279 | 273 |
280 void WindowCapturerLinux::Capture(const DesktopRegion& region) { | 274 void WindowCapturerLinux::Capture(const DesktopRegion& region) { |
281 if (!x_server_pixel_buffer_.IsWindowValid()) { | 275 if (!x_server_pixel_buffer_.IsWindowValid()) { |
282 LOG(LS_INFO) << "The window is no longer valid."; | 276 LOG(LS_INFO) << "The window is no longer valid."; |
283 callback_->OnCaptureCompleted(NULL); | 277 callback_->OnCaptureCompleted(std::unique_ptr<DesktopFrame>()); |
Wez
2016/05/18 01:29:51
Why not using nullptr here?
Sergey Ulanov
2016/05/31 12:02:49
same here. Replaced with OnCaptureResult(nullptr)
| |
284 return; | 278 return; |
285 } | 279 } |
286 | 280 |
287 x_display_->ProcessPendingXEvents(); | 281 x_display_->ProcessPendingXEvents(); |
288 | 282 |
289 if (!has_composite_extension_) { | 283 if (!has_composite_extension_) { |
290 // Without the Xcomposite extension we capture when the whole window is | 284 // Without the Xcomposite extension we capture when the whole window is |
291 // visible on screen and not covered by any other window. This is not | 285 // visible on screen and not covered by any other window. This is not |
292 // something we want so instead, just bail out. | 286 // something we want so instead, just bail out. |
293 LOG(LS_INFO) << "No Xcomposite extension detected."; | 287 LOG(LS_INFO) << "No Xcomposite extension detected."; |
294 callback_->OnCaptureCompleted(NULL); | 288 callback_->OnCaptureCompleted(std::unique_ptr<DesktopFrame>()); |
295 return; | 289 return; |
296 } | 290 } |
297 | 291 |
298 DesktopFrame* frame = | 292 std::unique_ptr<DesktopFrame> frame( |
299 new BasicDesktopFrame(x_server_pixel_buffer_.window_size()); | 293 new BasicDesktopFrame(x_server_pixel_buffer_.window_size())); |
300 | 294 |
301 x_server_pixel_buffer_.Synchronize(); | 295 x_server_pixel_buffer_.Synchronize(); |
302 x_server_pixel_buffer_.CaptureRect(DesktopRect::MakeSize(frame->size()), | 296 x_server_pixel_buffer_.CaptureRect(DesktopRect::MakeSize(frame->size()), |
303 frame); | 297 frame.get()); |
304 | 298 |
305 frame->mutable_updated_region()->SetRect( | 299 frame->mutable_updated_region()->SetRect( |
306 DesktopRect::MakeSize(frame->size())); | 300 DesktopRect::MakeSize(frame->size())); |
307 | 301 |
308 callback_->OnCaptureCompleted(frame); | 302 callback_->OnCaptureCompleted(std::move(frame)); |
309 } | 303 } |
310 | 304 |
311 bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { | 305 bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { |
312 if (event.type == ConfigureNotify) { | 306 if (event.type == ConfigureNotify) { |
313 XConfigureEvent xce = event.xconfigure; | 307 XConfigureEvent xce = event.xconfigure; |
314 if (!DesktopSize(xce.width, xce.height).equals( | 308 if (!DesktopSize(xce.width, xce.height).equals( |
315 x_server_pixel_buffer_.window_size())) { | 309 x_server_pixel_buffer_.window_size())) { |
316 if (!x_server_pixel_buffer_.Init(display(), selected_window_)) { | 310 if (!x_server_pixel_buffer_.Init(display(), selected_window_)) { |
317 LOG(LS_ERROR) << "Failed to initialize pixel buffer after resizing."; | 311 LOG(LS_ERROR) << "Failed to initialize pixel buffer after resizing."; |
318 } | 312 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 } | 386 } |
393 XFree(class_hint.res_name); | 387 XFree(class_hint.res_name); |
394 XFree(class_hint.res_class); | 388 XFree(class_hint.res_class); |
395 return result; | 389 return result; |
396 } | 390 } |
397 | 391 |
398 bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) { | 392 bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) { |
399 int status; | 393 int status; |
400 bool result = false; | 394 bool result = false; |
401 XTextProperty window_name; | 395 XTextProperty window_name; |
402 window_name.value = NULL; | 396 window_name.value = nullptr; |
403 if (window) { | 397 if (window) { |
404 status = XGetWMName(display(), window, &window_name); | 398 status = XGetWMName(display(), window, &window_name); |
405 if (status && window_name.value && window_name.nitems) { | 399 if (status && window_name.value && window_name.nitems) { |
406 int cnt; | 400 int cnt; |
407 char **list = NULL; | 401 char **list = nullptr; |
408 status = Xutf8TextPropertyToTextList(display(), &window_name, &list, | 402 status = Xutf8TextPropertyToTextList(display(), &window_name, &list, |
409 &cnt); | 403 &cnt); |
410 if (status >= Success && cnt && *list) { | 404 if (status >= Success && cnt && *list) { |
411 if (cnt > 1) { | 405 if (cnt > 1) { |
412 LOG(LS_INFO) << "Window has " << cnt | 406 LOG(LS_INFO) << "Window has " << cnt |
413 << " text properties, only using the first one."; | 407 << " text properties, only using the first one."; |
414 } | 408 } |
415 *title = *list; | 409 *title = *list; |
416 result = true; | 410 result = true; |
417 } | 411 } |
418 if (list) | 412 if (list) |
419 XFreeStringList(list); | 413 XFreeStringList(list); |
420 } | 414 } |
421 if (window_name.value) | 415 if (window_name.value) |
422 XFree(window_name.value); | 416 XFree(window_name.value); |
423 } | 417 } |
424 return result; | 418 return result; |
425 } | 419 } |
426 | 420 |
427 } // namespace | 421 } // namespace |
428 | 422 |
429 // static | 423 // static |
430 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { | 424 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { |
431 if (!options.x_display()) | 425 if (!options.x_display()) |
432 return NULL; | 426 return nullptr; |
433 return new WindowCapturerLinux(options); | 427 return new WindowCapturerLinux(options); |
434 } | 428 } |
435 | 429 |
436 } // namespace webrtc | 430 } // namespace webrtc |
OLD | NEW |