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

Side by Side Diff: webrtc/modules/desktop_capture/window_capturer_x11.cc

Issue 2202883003: Icon Capture For Window Capturer (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fix windows crash Created 4 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
OLDNEW
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 13 matching lines...) Expand all
24 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 24 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
25 #include "webrtc/modules/desktop_capture/desktop_frame.h" 25 #include "webrtc/modules/desktop_capture/desktop_frame.h"
26 #include "webrtc/modules/desktop_capture/x11/shared_x_display.h" 26 #include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
27 #include "webrtc/modules/desktop_capture/x11/x_error_trap.h" 27 #include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
28 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" 28 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
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 const uint32_t kAlphaMask = 0xFF000000;
35 const uint32_t kRedMask = 0x00FF0000;
36 const uint32_t kGreenMask = 0x0000FF00;
37 const uint32_t kBlueMask = 0x000000FF;
38
39 const int kAlphaShift = 24;
40 const int kRedShift = 16;
41 const int kGreenShift = 8;
42 const int kBlueShift = 0;
43
44 uint32_t MultiplyAlpha(uint32_t raw_color_component, uint32_t alpha) {
45 uint32_t product = raw_color_component * alpha + 128;
46 return (product + (product >> 8)) >> 8;
47 }
48
49 // Convert a raw ARGB color pixel into a premultiplied ARGB color
50 uint32_t PremultipliedColor(uint32_t raw_color) {
51 uint32_t alpha, red, green, blue;
52 alpha = (raw_color & kAlphaMask) >> kAlphaShift;
53 red = (raw_color & kRedMask) >> kRedShift;
54 green = (raw_color & kGreenMask) >> kGreenShift;
55 blue = (raw_color & kBlueMask) >> kBlueShift;
56
57 red = MultiplyAlpha(red, alpha);
58 green = MultiplyAlpha(green, alpha);
59 blue = MultiplyAlpha(blue, alpha);
60
61 return (alpha << kAlphaShift) | (red << kRedShift) | (green << kGreenShift) |
62 (blue << kBlueShift);
63 }
34 64
35 // Convenience wrapper for XGetWindowProperty() results. 65 // Convenience wrapper for XGetWindowProperty() results.
36 template <class PropertyType> 66 template <class PropertyType>
37 class XWindowProperty { 67 class XWindowProperty {
38 public: 68 public:
39 XWindowProperty(Display* display, Window window, Atom property) { 69 XWindowProperty(Display* display, Window window, Atom property) {
40 const int kBitsPerByte = 8; 70 const int kBitsPerByte = 8;
41 Atom actual_type; 71 Atom actual_type;
42 int actual_format; 72 int actual_format;
43 unsigned long bytes_after; // NOLINT: type required by XGetWindowProperty 73 unsigned long bytes_after; // NOLINT: type required by XGetWindowProperty
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 // that has WM_STATE property set to NormalState. 137 // that has WM_STATE property set to NormalState.
108 // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 . 138 // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
109 ::Window GetApplicationWindow(::Window window); 139 ::Window GetApplicationWindow(::Window window);
110 140
111 // Returns true if the |window| is a desktop element. 141 // Returns true if the |window| is a desktop element.
112 bool IsDesktopElement(::Window window); 142 bool IsDesktopElement(::Window window);
113 143
114 // Returns window title for the specified X |window|. 144 // Returns window title for the specified X |window|.
115 bool GetWindowTitle(::Window window, std::string* title); 145 bool GetWindowTitle(::Window window, std::string* title);
116 146
147 std::unique_ptr<DesktopFrame> GetWindowIcon(::Window window);
148
117 Callback* callback_ = nullptr; 149 Callback* callback_ = nullptr;
118 150
119 rtc::scoped_refptr<SharedXDisplay> x_display_; 151 rtc::scoped_refptr<SharedXDisplay> x_display_;
120 152
121 Atom wm_state_atom_; 153 Atom wm_state_atom_;
122 Atom window_type_atom_; 154 Atom window_type_atom_;
123 Atom normal_window_type_atom_; 155 Atom normal_window_type_atom_;
156 Atom icon_atom_;
124 bool has_composite_extension_ = false; 157 bool has_composite_extension_ = false;
125 158
126 ::Window selected_window_ = 0; 159 ::Window selected_window_ = 0;
127 XServerPixelBuffer x_server_pixel_buffer_; 160 XServerPixelBuffer x_server_pixel_buffer_;
128 161
129 RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux); 162 RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux);
130 }; 163 };
131 164
132 WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) 165 WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options)
133 : x_display_(options.x_display()) { 166 : x_display_(options.x_display()) {
134 // Create Atoms so we don't need to do it every time they are used. 167 // Create Atoms so we don't need to do it every time they are used.
135 wm_state_atom_ = XInternAtom(display(), "WM_STATE", True); 168 wm_state_atom_ = XInternAtom(display(), "WM_STATE", True);
136 window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True); 169 window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True);
137 normal_window_type_atom_ = XInternAtom( 170 normal_window_type_atom_ = XInternAtom(
138 display(), "_NET_WM_WINDOW_TYPE_NORMAL", True); 171 display(), "_NET_WM_WINDOW_TYPE_NORMAL", True);
172 icon_atom_ = XInternAtom(display(), "_NET_WM_ICON", True);
139 173
140 int event_base, error_base, major_version, minor_version; 174 int event_base, error_base, major_version, minor_version;
141 if (XCompositeQueryExtension(display(), &event_base, &error_base) && 175 if (XCompositeQueryExtension(display(), &event_base, &error_base) &&
142 XCompositeQueryVersion(display(), &major_version, &minor_version) && 176 XCompositeQueryVersion(display(), &major_version, &minor_version) &&
143 // XCompositeNameWindowPixmap() requires version 0.2 177 // XCompositeNameWindowPixmap() requires version 0.2
144 (major_version > 0 || minor_version >= 2)) { 178 (major_version > 0 || minor_version >= 2)) {
145 has_composite_extension_ = true; 179 has_composite_extension_ = true;
146 } else { 180 } else {
147 LOG(LS_INFO) << "Xcomposite extension not available or too old."; 181 LOG(LS_INFO) << "Xcomposite extension not available or too old.";
148 } 182 }
149 183
150 x_display_->AddEventHandler(ConfigureNotify, this); 184 x_display_->AddEventHandler(ConfigureNotify, this);
151 } 185 }
152 186
153 WindowCapturerLinux::~WindowCapturerLinux() { 187 WindowCapturerLinux::~WindowCapturerLinux() {
154 x_display_->RemoveEventHandler(ConfigureNotify, this); 188 x_display_->RemoveEventHandler(ConfigureNotify, this);
155 } 189 }
156 190
157 bool WindowCapturerLinux::GetWindowList(WindowList* windows) { 191 bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
158 WindowList result; 192 windows->clear();
159
160 XErrorTrap error_trap(display()); 193 XErrorTrap error_trap(display());
161 194
162 int num_screens = XScreenCount(display()); 195 int num_screens = XScreenCount(display());
163 for (int screen = 0; screen < num_screens; ++screen) { 196 for (int screen = 0; screen < num_screens; ++screen) {
164 ::Window root_window = XRootWindow(display(), screen); 197 ::Window root_window = XRootWindow(display(), screen);
165 ::Window parent; 198 ::Window parent;
166 ::Window *children; 199 ::Window *children;
167 unsigned int num_children; 200 unsigned int num_children;
168 int status = XQueryTree(display(), root_window, &root_window, &parent, 201 int status = XQueryTree(display(), root_window, &root_window, &parent,
169 &children, &num_children); 202 &children, &num_children);
170 if (status == 0) { 203 if (status == 0) {
171 LOG(LS_ERROR) << "Failed to query for child windows for screen " 204 LOG(LS_ERROR) << "Failed to query for child windows for screen "
172 << screen; 205 << screen;
173 continue; 206 continue;
174 } 207 }
175 208
176 for (unsigned int i = 0; i < num_children; ++i) { 209 for (unsigned int i = 0; i < num_children; ++i) {
177 // Iterate in reverse order to return windows from front to back. 210 // Iterate in reverse order to return windows from front to back.
178 ::Window app_window = 211 ::Window app_window =
179 GetApplicationWindow(children[num_children - 1 - i]); 212 GetApplicationWindow(children[num_children - 1 - i]);
180 if (app_window && !IsDesktopElement(app_window)) { 213 if (app_window && !IsDesktopElement(app_window)) {
181 Window w; 214 Window w;
182 w.id = app_window; 215 w.id = app_window;
183 if (GetWindowTitle(app_window, &w.title)) 216 if (!GetWindowTitle(app_window, &w.title))
184 result.push_back(w); 217 continue;
218 w.icon = GetWindowIcon(app_window);
219 windows->push_back(std::move(w));
185 } 220 }
186 } 221 }
187 222
188 if (children) 223 if (children)
189 XFree(children); 224 XFree(children);
190 } 225 }
191 226
192 windows->swap(result);
193
194 return true; 227 return true;
195 } 228 }
196 229
197 bool WindowCapturerLinux::SelectWindow(WindowId id) { 230 bool WindowCapturerLinux::SelectWindow(WindowId id) {
198 if (!x_server_pixel_buffer_.Init(display(), id)) 231 if (!x_server_pixel_buffer_.Init(display(), id))
199 return false; 232 return false;
200 233
201 // Tell the X server to send us window resizing events. 234 // Tell the X server to send us window resizing events.
202 XSelectInput(display(), id, StructureNotifyMask); 235 XSelectInput(display(), id, StructureNotifyMask);
203 236
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 } 444 }
412 if (list) 445 if (list)
413 XFreeStringList(list); 446 XFreeStringList(list);
414 } 447 }
415 if (window_name.value) 448 if (window_name.value)
416 XFree(window_name.value); 449 XFree(window_name.value);
417 } 450 }
418 return result; 451 return result;
419 } 452 }
420 453
454 std::unique_ptr<DesktopFrame> WindowCapturerLinux::GetWindowIcon(
455 ::Window window) {
456 XWindowProperty<uint32_t> icon_property(display(), window, icon_atom_);
457
458 long* data = (long*)icon_property.data();
459
460 uint32_t length = icon_property.size();
461 if (length == 0)
462 return nullptr;
463
464 long width, height;
465 int start = 0;
466 uint32_t i = 0;
467 while (i < length) {
468 if (i == 0 || data[i] * data[i + 1] > width * height) {
469 width = data[i];
470 height = data[i + 1];
471 start = i + 2;
472 }
473 i = i + 2 + data[i] * data[i + 1];
474 }
475
476 std::unique_ptr<DesktopFrame> frame(
477 new BasicDesktopFrame(DesktopSize(width, height)));
478
479 uint32_t* frame_data = (uint32_t*)frame->data();
480 int dest_int_stride = frame->stride() / sizeof(uint32_t);
481 for (int y = 0; y < height; ++y) {
482 for (int x = 0; x < width; ++x) {
483 frame_data[y * dest_int_stride + x] = PremultipliedColor(
484 static_cast<uint32_t>(data[start + y * width + x]));
485 }
486 }
487
488 frame->mutable_updated_region()->SetRect(
489 DesktopRect::MakeSize(frame->size()));
490
491 return frame;
492 }
493
421 } // namespace 494 } // namespace
422 495
423 // static 496 // static
424 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) { 497 WindowCapturer* WindowCapturer::Create(const DesktopCaptureOptions& options) {
425 if (!options.x_display()) 498 if (!options.x_display())
426 return nullptr; 499 return nullptr;
427 return new WindowCapturerLinux(options); 500 return new WindowCapturerLinux(options);
428 } 501 }
429 502
430 } // namespace webrtc 503 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698