| Index: webrtc/modules/desktop_capture/screen_drawer_linux.cc
|
| diff --git a/webrtc/modules/desktop_capture/screen_drawer_linux.cc b/webrtc/modules/desktop_capture/screen_drawer_linux.cc
|
| index 2aff80b6c7ce1259f48f32ef94b12121f0256ac5..08d8195b42dd66601351d02d138e081137e8220d 100644
|
| --- a/webrtc/modules/desktop_capture/screen_drawer_linux.cc
|
| +++ b/webrtc/modules/desktop_capture/screen_drawer_linux.cc
|
| @@ -13,6 +13,7 @@
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/modules/desktop_capture/screen_drawer.h"
|
| #include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
|
| +#include "webrtc/system_wrappers/include/sleep.h"
|
|
|
| namespace webrtc {
|
|
|
| @@ -26,12 +27,12 @@ class ScreenDrawerLinux : public ScreenDrawer {
|
|
|
| // ScreenDrawer interface.
|
| DesktopRect DrawableRegion() override;
|
| - void DrawRectangle(DesktopRect rect, uint32_t rgba) override;
|
| + void DrawRectangle(DesktopRect rect, RgbaColor color) override;
|
| void Clear() override;
|
| + void WaitForPendingDraws() override;
|
|
|
| private:
|
| rtc::scoped_refptr<SharedXDisplay> display_;
|
| - Screen* screen_;
|
| int screen_num_;
|
| DesktopRect rect_;
|
| Window window_;
|
| @@ -42,15 +43,18 @@ class ScreenDrawerLinux : public ScreenDrawer {
|
| ScreenDrawerLinux::ScreenDrawerLinux() {
|
| display_ = SharedXDisplay::CreateDefault();
|
| RTC_CHECK(display_.get());
|
| - screen_ = DefaultScreenOfDisplay(display_->display());
|
| - RTC_CHECK(screen_);
|
| screen_num_ = DefaultScreen(display_->display());
|
| - rect_ = DesktopRect::MakeWH(screen_->width, screen_->height);
|
| - window_ = XCreateSimpleWindow(display_->display(),
|
| - RootWindow(display_->display(), screen_num_), 0,
|
| - 0, rect_.width(), rect_.height(), 0,
|
| - BlackPixel(display_->display(), screen_num_),
|
| - BlackPixel(display_->display(), screen_num_));
|
| + XWindowAttributes root_attributes;
|
| + if (!XGetWindowAttributes(display_->display(),
|
| + RootWindow(display_->display(), screen_num_),
|
| + &root_attributes)) {
|
| + RTC_DCHECK(false) << "Failed to get root window size.";
|
| + }
|
| + window_ = XCreateSimpleWindow(
|
| + display_->display(), RootWindow(display_->display(), screen_num_), 0, 0,
|
| + root_attributes.width, root_attributes.height, 0,
|
| + BlackPixel(display_->display(), screen_num_),
|
| + BlackPixel(display_->display(), screen_num_));
|
| XSelectInput(display_->display(), window_, StructureNotifyMask);
|
| XMapWindow(display_->display(), window_);
|
| while (true) {
|
| @@ -61,8 +65,23 @@ ScreenDrawerLinux::ScreenDrawerLinux() {
|
| }
|
| }
|
| XFlush(display_->display());
|
| + Window child;
|
| + int x, y;
|
| + if (!XTranslateCoordinates(display_->display(), window_,
|
| + RootWindow(display_->display(), screen_num_), 0, 0,
|
| + &x, &y, &child)) {
|
| + RTC_DCHECK(false) << "Failed to get window position.";
|
| + }
|
| + // Some window manager does not allow a window to cover two or more monitors.
|
| + // So if the window is on the first monitor of a two-monitor system, the
|
| + // second half won't be able to show up without changing configurations of WM,
|
| + // and its DrawableRegion() is not accurate.
|
| + rect_ = DesktopRect::MakeLTRB(x, y, root_attributes.width,
|
| + root_attributes.height);
|
| context_ = DefaultGC(display_->display(), screen_num_);
|
| colormap_ = DefaultColormap(display_->display(), screen_num_);
|
| + // Wait for window animations.
|
| + SleepMs(200);
|
| }
|
|
|
| ScreenDrawerLinux::~ScreenDrawerLinux() {
|
| @@ -74,33 +93,42 @@ DesktopRect ScreenDrawerLinux::DrawableRegion() {
|
| return rect_;
|
| }
|
|
|
| -void ScreenDrawerLinux::DrawRectangle(DesktopRect rect, uint32_t rgba) {
|
| - int r = (rgba & 0xff00) >> 8;
|
| - int g = (rgba & 0xff0000) >> 16;
|
| - int b = (rgba & 0xff000000) >> 24;
|
| +void ScreenDrawerLinux::DrawRectangle(DesktopRect rect, RgbaColor color) {
|
| + rect.Translate(-rect_.left(), -rect_.top());
|
| + XColor xcolor;
|
| // X11 does not support Alpha.
|
| - XColor color;
|
| - // X11 uses 16 bits for each primary color.
|
| - color.red = r * 256;
|
| - color.green = g * 256;
|
| - color.blue = b * 256;
|
| - color.flags = DoRed | DoGreen | DoBlue;
|
| - XAllocColor(display_->display(), colormap_, &color);
|
| - XSetForeground(display_->display(), context_, color.pixel);
|
| + // X11 uses 16 bits for each primary color, so we need to slightly normalize
|
| + // a 8 bits channel to 16 bits channel, by setting the low 8 bits as its high
|
| + // 8 bits to avoid a mismatch of color returned by capturer.
|
| + xcolor.red = (color.red << 8) + color.red;
|
| + xcolor.green = (color.green << 8) + color.green;
|
| + xcolor.blue = (color.blue << 8) + color.blue;
|
| + xcolor.flags = DoRed | DoGreen | DoBlue;
|
| + XAllocColor(display_->display(), colormap_, &xcolor);
|
| + XSetForeground(display_->display(), context_, xcolor.pixel);
|
| XFillRectangle(display_->display(), window_, context_, rect.left(),
|
| rect.top(), rect.width(), rect.height());
|
| XFlush(display_->display());
|
| }
|
|
|
| void ScreenDrawerLinux::Clear() {
|
| - DrawRectangle(DrawableRegion(), 0);
|
| + DrawRectangle(rect_, RgbaColor(0, 0, 0));
|
| +}
|
| +
|
| +// TODO(zijiehe): Find the right signal from X11 to indicate the finish of all
|
| +// pending paintings.
|
| +void ScreenDrawerLinux::WaitForPendingDraws() {
|
| + SleepMs(50);
|
| }
|
|
|
| } // namespace
|
|
|
| // static
|
| std::unique_ptr<ScreenDrawer> ScreenDrawer::Create() {
|
| - return std::unique_ptr<ScreenDrawer>(new ScreenDrawerLinux());
|
| + if (SharedXDisplay::CreateDefault().get()) {
|
| + return std::unique_ptr<ScreenDrawer>(new ScreenDrawerLinux());
|
| + }
|
| + return nullptr;
|
| }
|
|
|
| } // namespace webrtc
|
|
|