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 |