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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 // that has WM_STATE property set to NormalState. | 104 // that has WM_STATE property set to NormalState. |
105 // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 . | 105 // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 . |
106 ::Window GetApplicationWindow(::Window window); | 106 ::Window GetApplicationWindow(::Window window); |
107 | 107 |
108 // Returns true if the |window| is a desktop element. | 108 // Returns true if the |window| is a desktop element. |
109 bool IsDesktopElement(::Window window); | 109 bool IsDesktopElement(::Window window); |
110 | 110 |
111 // Returns window title for the specified X |window|. | 111 // Returns window title for the specified X |window|. |
112 bool GetWindowTitle(::Window window, std::string* title); | 112 bool GetWindowTitle(::Window window, std::string* title); |
113 | 113 |
| 114 // Return WM_STATE property of the |window|. |
| 115 int32_t GetWindowState(::Window window); |
| 116 |
114 Callback* callback_ = nullptr; | 117 Callback* callback_ = nullptr; |
115 | 118 |
116 rtc::scoped_refptr<SharedXDisplay> x_display_; | 119 rtc::scoped_refptr<SharedXDisplay> x_display_; |
117 | 120 |
118 Atom wm_state_atom_; | 121 Atom wm_state_atom_; |
119 Atom window_type_atom_; | 122 Atom window_type_atom_; |
120 Atom normal_window_type_atom_; | 123 Atom normal_window_type_atom_; |
121 bool has_composite_extension_ = false; | 124 bool has_composite_extension_ = false; |
122 | 125 |
123 ::Window selected_window_ = 0; | 126 ::Window selected_window_ = 0; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 | 282 |
280 if (!has_composite_extension_) { | 283 if (!has_composite_extension_) { |
281 // Without the Xcomposite extension we capture when the whole window is | 284 // Without the Xcomposite extension we capture when the whole window is |
282 // 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 |
283 // something we want so instead, just bail out. | 286 // something we want so instead, just bail out. |
284 LOG(LS_INFO) << "No Xcomposite extension detected."; | 287 LOG(LS_INFO) << "No Xcomposite extension detected."; |
285 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); | 288 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
286 return; | 289 return; |
287 } | 290 } |
288 | 291 |
| 292 if (GetWindowState(selected_window_) == IconicState) { |
| 293 // Window is in minimized. Return a 1x1 frame as same as OSX/Win does. |
| 294 std::unique_ptr<DesktopFrame> frame( |
| 295 new BasicDesktopFrame(DesktopSize(1, 1))); |
| 296 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); |
| 297 return; |
| 298 } |
| 299 |
289 std::unique_ptr<DesktopFrame> frame( | 300 std::unique_ptr<DesktopFrame> frame( |
290 new BasicDesktopFrame(x_server_pixel_buffer_.window_size())); | 301 new BasicDesktopFrame(x_server_pixel_buffer_.window_size())); |
291 | 302 |
292 x_server_pixel_buffer_.Synchronize(); | 303 x_server_pixel_buffer_.Synchronize(); |
293 if (!x_server_pixel_buffer_.CaptureRect(DesktopRect::MakeSize(frame->size()), | 304 if (!x_server_pixel_buffer_.CaptureRect(DesktopRect::MakeSize(frame->size()), |
294 frame.get())) { | 305 frame.get())) { |
295 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); | 306 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
296 return; | 307 return; |
297 } | 308 } |
298 | 309 |
(...skipping 11 matching lines...) Expand all Loading... |
310 if (!x_server_pixel_buffer_.Init(display(), selected_window_)) { | 321 if (!x_server_pixel_buffer_.Init(display(), selected_window_)) { |
311 LOG(LS_ERROR) << "Failed to initialize pixel buffer after resizing."; | 322 LOG(LS_ERROR) << "Failed to initialize pixel buffer after resizing."; |
312 } | 323 } |
313 return true; | 324 return true; |
314 } | 325 } |
315 } | 326 } |
316 return false; | 327 return false; |
317 } | 328 } |
318 | 329 |
319 ::Window WindowCapturerLinux::GetApplicationWindow(::Window window) { | 330 ::Window WindowCapturerLinux::GetApplicationWindow(::Window window) { |
320 // Get WM_STATE property of the window. | 331 int32_t state = GetWindowState(window); |
321 XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_); | |
322 | |
323 // WM_STATE is considered to be set to WithdrawnState when it missing. | |
324 int32_t state = window_state.is_valid() ? | |
325 *window_state.data() : WithdrawnState; | |
326 | |
327 if (state == NormalState) { | 332 if (state == NormalState) { |
328 // Window has WM_STATE==NormalState. Return it. | 333 // Window has WM_STATE==NormalState. Return it. |
329 return window; | 334 return window; |
330 } else if (state == IconicState) { | 335 } else if (state == IconicState) { |
331 // Window is in minimized. Skip it. | 336 // Window is in minimized. Skip it. |
332 return 0; | 337 return 0; |
333 } | 338 } |
334 | 339 |
335 // If the window is in WithdrawnState then look at all of its children. | 340 // If the window is in WithdrawnState then look at all of its children. |
336 ::Window root, parent; | 341 ::Window root, parent; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 } | 416 } |
412 if (list) | 417 if (list) |
413 XFreeStringList(list); | 418 XFreeStringList(list); |
414 } | 419 } |
415 if (window_name.value) | 420 if (window_name.value) |
416 XFree(window_name.value); | 421 XFree(window_name.value); |
417 } | 422 } |
418 return result; | 423 return result; |
419 } | 424 } |
420 | 425 |
| 426 int32_t WindowCapturerLinux::GetWindowState(::Window window) { |
| 427 // Get WM_STATE property of the window. |
| 428 XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_); |
| 429 |
| 430 // WM_STATE is considered to be set to WithdrawnState when it missing. |
| 431 return window_state.is_valid() ? *window_state.data() : WithdrawnState; |
| 432 } |
| 433 |
421 } // namespace | 434 } // namespace |
422 | 435 |
423 // static | 436 // static |
424 std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer( | 437 std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer( |
425 const DesktopCaptureOptions& options) { | 438 const DesktopCaptureOptions& options) { |
426 if (!options.x_display()) | 439 if (!options.x_display()) |
427 return nullptr; | 440 return nullptr; |
428 return std::unique_ptr<DesktopCapturer>(new WindowCapturerLinux(options)); | 441 return std::unique_ptr<DesktopCapturer>(new WindowCapturerLinux(options)); |
429 } | 442 } |
430 | 443 |
431 } // namespace webrtc | 444 } // namespace webrtc |
OLD | NEW |