| Index: webrtc/modules/desktop_capture/window_capturer_x11.cc
|
| diff --git a/webrtc/modules/desktop_capture/window_capturer_x11.cc b/webrtc/modules/desktop_capture/window_capturer_x11.cc
|
| index d88585bfa8052d34a0de60b58a8089d6a3992bca..0d9fcef9853c7cd4b1b769355b697105634979bb 100644
|
| --- a/webrtc/modules/desktop_capture/window_capturer_x11.cc
|
| +++ b/webrtc/modules/desktop_capture/window_capturer_x11.cc
|
| @@ -31,6 +31,36 @@
|
| namespace webrtc {
|
|
|
| namespace {
|
| +const uint32_t kAlphaMask = 0xFF000000;
|
| +const uint32_t kRedMask = 0x00FF0000;
|
| +const uint32_t kGreenMask = 0x0000FF00;
|
| +const uint32_t kBlueMask = 0x000000FF;
|
| +
|
| +const int kAlphaShift = 24;
|
| +const int kRedShift = 16;
|
| +const int kGreenShift = 8;
|
| +const int kBlueShift = 0;
|
| +
|
| +uint32_t MultiplyAlpha(uint32_t raw_color_component, uint32_t alpha) {
|
| + uint32_t product = raw_color_component * alpha + 128;
|
| + return (product + (product >> 8)) >> 8;
|
| +}
|
| +
|
| +// Convert a raw ARGB color pixel into a premultiplied ARGB color
|
| +uint32_t PremultipliedColor(uint32_t raw_color) {
|
| + uint32_t alpha, red, green, blue;
|
| + alpha = (raw_color & kAlphaMask) >> kAlphaShift;
|
| + red = (raw_color & kRedMask) >> kRedShift;
|
| + green = (raw_color & kGreenMask) >> kGreenShift;
|
| + blue = (raw_color & kBlueMask) >> kBlueShift;
|
| +
|
| + red = MultiplyAlpha(red, alpha);
|
| + green = MultiplyAlpha(green, alpha);
|
| + blue = MultiplyAlpha(blue, alpha);
|
| +
|
| + return (alpha << kAlphaShift) | (red << kRedShift) | (green << kGreenShift) |
|
| + (blue << kBlueShift);
|
| +}
|
|
|
| // Convenience wrapper for XGetWindowProperty() results.
|
| template <class PropertyType>
|
| @@ -114,6 +144,8 @@ class WindowCapturerLinux : public WindowCapturer,
|
| // Returns window title for the specified X |window|.
|
| bool GetWindowTitle(::Window window, std::string* title);
|
|
|
| + std::unique_ptr<DesktopFrame> GetWindowIcon(::Window window);
|
| +
|
| Callback* callback_ = nullptr;
|
|
|
| rtc::scoped_refptr<SharedXDisplay> x_display_;
|
| @@ -121,6 +153,7 @@ class WindowCapturerLinux : public WindowCapturer,
|
| Atom wm_state_atom_;
|
| Atom window_type_atom_;
|
| Atom normal_window_type_atom_;
|
| + Atom icon_atom_;
|
| bool has_composite_extension_ = false;
|
|
|
| ::Window selected_window_ = 0;
|
| @@ -136,6 +169,7 @@ WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options)
|
| window_type_atom_ = XInternAtom(display(), "_NET_WM_WINDOW_TYPE", True);
|
| normal_window_type_atom_ = XInternAtom(
|
| display(), "_NET_WM_WINDOW_TYPE_NORMAL", True);
|
| + icon_atom_ = XInternAtom(display(), "_NET_WM_ICON", True);
|
|
|
| int event_base, error_base, major_version, minor_version;
|
| if (XCompositeQueryExtension(display(), &event_base, &error_base) &&
|
| @@ -155,8 +189,7 @@ WindowCapturerLinux::~WindowCapturerLinux() {
|
| }
|
|
|
| bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
| - WindowList result;
|
| -
|
| + windows->clear();
|
| XErrorTrap error_trap(display());
|
|
|
| int num_screens = XScreenCount(display());
|
| @@ -180,8 +213,10 @@ bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
| if (app_window && !IsDesktopElement(app_window)) {
|
| Window w;
|
| w.id = app_window;
|
| - if (GetWindowTitle(app_window, &w.title))
|
| - result.push_back(w);
|
| + if (!GetWindowTitle(app_window, &w.title))
|
| + continue;
|
| + w.icon = GetWindowIcon(app_window);
|
| + windows->push_back(std::move(w));
|
| }
|
| }
|
|
|
| @@ -189,8 +224,6 @@ bool WindowCapturerLinux::GetWindowList(WindowList* windows) {
|
| XFree(children);
|
| }
|
|
|
| - windows->swap(result);
|
| -
|
| return true;
|
| }
|
|
|
| @@ -418,6 +451,46 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
|
| return result;
|
| }
|
|
|
| +std::unique_ptr<DesktopFrame> WindowCapturerLinux::GetWindowIcon(
|
| + ::Window window) {
|
| + XWindowProperty<uint32_t> icon_property(display(), window, icon_atom_);
|
| +
|
| + long* data = (long*)icon_property.data();
|
| +
|
| + uint32_t length = icon_property.size();
|
| + if (length == 0)
|
| + return nullptr;
|
| +
|
| + long width, height;
|
| + int start = 0;
|
| + uint32_t i = 0;
|
| + while (i < length) {
|
| + if (i == 0 || data[i] * data[i + 1] > width * height) {
|
| + width = data[i];
|
| + height = data[i + 1];
|
| + start = i + 2;
|
| + }
|
| + i = i + 2 + data[i] * data[i + 1];
|
| + }
|
| +
|
| + std::unique_ptr<DesktopFrame> frame(
|
| + new BasicDesktopFrame(DesktopSize(width, height)));
|
| +
|
| + uint32_t* frame_data = (uint32_t*)frame->data();
|
| + int dest_int_stride = frame->stride() / sizeof(uint32_t);
|
| + for (int y = 0; y < height; ++y) {
|
| + for (int x = 0; x < width; ++x) {
|
| + frame_data[y * dest_int_stride + x] = PremultipliedColor(
|
| + static_cast<uint32_t>(data[start + y * width + x]));
|
| + }
|
| + }
|
| +
|
| + frame->mutable_updated_region()->SetRect(
|
| + DesktopRect::MakeSize(frame->size()));
|
| +
|
| + return frame;
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
|
|