Replace WindowUnderPoint free function with WindowFinder interface

WindowUnderPoint have different signatures on different platforms, which should
be abstract as an interface.
So this change adds a WindowFinder interface to replace WindowUnderPoint free
function. Meanwhile, this change also includes the implementation of
WindowFinderX11 for X11.

Bug: webrtc:7950
Change-Id: I897a50d4033e713b339b6b6f48b5dbbe601e8db0
Reviewed-on: https://chromium-review.googlesource.com/611745
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Commit-Queue: Zijie He <zijiehe@chromium.org>
Cr-Commit-Position: refs/heads/master@{#19375}
This commit is contained in:
Zijie He 2017-08-15 15:45:00 -07:00 committed by Commit Bot
parent 0ed6de4cad
commit 70fbbad5ac
16 changed files with 277 additions and 106 deletions

View file

@ -251,10 +251,11 @@ rtc_static_library("desktop_capture") {
"win/window_capture_utils.h",
"window_capturer_mac.mm",
"window_capturer_win.cc",
"window_under_point.h",
"window_under_point_linux.cc",
"window_under_point_mac.mm",
"window_under_point_win.cc",
"window_finder.h",
"window_finder_mac.h",
"window_finder_mac.mm",
"window_finder_win.cc",
"window_finder_win.h",
]
if (use_x11) {
@ -262,6 +263,8 @@ rtc_static_library("desktop_capture") {
"mouse_cursor_monitor_x11.cc",
"screen_capturer_x11.cc",
"window_capturer_x11.cc",
"window_finder_x11.cc",
"window_finder_x11.h",
"x11/shared_x_display.cc",
"x11/shared_x_display.h",
"x11/window_list_utils.cc",

View file

@ -219,14 +219,17 @@ void WindowCapturerLinux::CaptureFrame() {
bool WindowCapturerLinux::HandleXEvent(const XEvent& event) {
if (event.type == ConfigureNotify) {
XConfigureEvent xce = event.xconfigure;
if (!DesktopSize(xce.width, xce.height).equals(
x_server_pixel_buffer_.window_size())) {
if (!x_server_pixel_buffer_.Init(display(), selected_window_)) {
LOG(LS_ERROR) << "Failed to initialize pixel buffer after resizing.";
if (xce.window == selected_window_) {
if (!DesktopRectFromXAttributes(xce).equals(
x_server_pixel_buffer_.window_rect())) {
if (!x_server_pixel_buffer_.Init(display(), selected_window_)) {
LOG(LS_ERROR) << "Failed to initialize pixel buffer after resizing.";
}
}
return true;
}
}
// Always returns false, so other observers can still receive the events.
return false;
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_H_
#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
namespace webrtc {
// An interface to return the id of the visible window under a certain point.
class WindowFinder {
public:
WindowFinder() = default;
virtual ~WindowFinder() = default;
// Returns the id of the visible window under |point|. This function returns
// kNullWindowId if no window is under |point| and the platform does not have
// "root window" concept, i.e. the visible area under |point| is the desktop.
virtual WindowId GetWindowUnderPoint(DesktopVector point) = 0;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_H_

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_MAC_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_MAC_H_
#include "webrtc/modules/desktop_capture/window_finder.h"
namespace webrtc {
// The implementation of WindowFinder for Windows.
class WindowFinderMac final : public WindowFinder {
public:
WindowFinderMac();
~WindowFinderMac() override;
// WindowFinder implementation.
WindowId GetWindowUnderPoint(DesktopVector point) override;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_MAC_H_

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/window_finder_mac.h"
#include <CoreFoundation/CoreFoundation.h>
#include "webrtc/modules/desktop_capture/mac/window_list_utils.h"
namespace webrtc {
WindowFinderMac::WindowFinderMac() = default;
WindowFinderMac::~WindowFinderMac() = default;
WindowId WindowFinderMac::GetWindowUnderPoint(DesktopVector point) {
WindowId id = kNullWindowId;
GetWindowList([&id, point](CFDictionaryRef window) {
DesktopRect bounds = GetWindowBounds(window);
if (bounds.Contains(point)) {
id = GetWindowId(window);
return false;
}
return true;
},
true);
return id;
}
} // namespace webrtc

View file

@ -8,13 +8,16 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/window_under_point.h"
#include "webrtc/modules/desktop_capture/window_finder_win.h"
#include <windows.h>
namespace webrtc {
WindowId GetWindowUnderPoint(DesktopVector point) {
WindowFinderWin::WindowFinderWin() = default;
WindowFinderWin::~WindowFinderWin() = default;
WindowId WindowFinderWin::GetWindowUnderPoint(DesktopVector point) {
HWND window = WindowFromPoint(POINT { point.x(), point.y() });
if (!window) {
return kNullWindowId;

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_WIN_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_WIN_H_
#include "webrtc/modules/desktop_capture/window_finder.h"
namespace webrtc {
// The implementation of WindowFinder for Windows.
class WindowFinderWin final : public WindowFinder {
public:
WindowFinderWin();
~WindowFinderWin() override;
// WindowFinder implementation.
WindowId GetWindowUnderPoint(DesktopVector point) override;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_WIN_H_

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/window_finder_x11.h"
#include "webrtc/modules/desktop_capture/x11/window_list_utils.h"
#include "webrtc/rtc_base/checks.h"
namespace webrtc {
WindowFinderX11::WindowFinderX11(XAtomCache* cache)
: cache_(cache) {
RTC_DCHECK(cache_);
}
WindowFinderX11::~WindowFinderX11() = default;
WindowId WindowFinderX11::GetWindowUnderPoint(DesktopVector point) {
WindowId id = kNullWindowId;
GetWindowList(cache_,
[&id, this, point](::Window window) {
DesktopRect rect;
if (GetWindowRect(this->cache_->display(), window, &rect) &&
rect.Contains(point)) {
id = window;
return false;
}
return true;
});
return id;
}
} // namespace webrtc

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_X11_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_X11_H_
#include "webrtc/modules/desktop_capture/window_finder.h"
namespace webrtc {
class XAtomCache;
// The implementation of WindowFinder for Windows.
class WindowFinderX11 final : public WindowFinder {
public:
explicit WindowFinderX11(XAtomCache* cache);
~WindowFinderX11() override;
// WindowFinder implementation.
WindowId GetWindowUnderPoint(DesktopVector point) override;
private:
XAtomCache* const cache_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_X11_H_

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_UNDER_POINT_H_
#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_UNDER_POINT_H_
#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
namespace webrtc {
// Returns the id of the visible window under |point|. This function returns
// kNullWindowId if no window is under |point| and the platform does not have
// "root window" concept, i.e. the visible area under |point| is the desktop.
WindowId GetWindowUnderPoint(DesktopVector point);
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_UNDER_POINT_H_

View file

@ -1,20 +0,0 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/desktop_capture/window_under_point.h"
namespace webrtc {
WindowId GetWindowUnderPoint(DesktopVector point) {
// TODO(zijiehe): Implementation required.
return kNullWindowId;
}
} // namespace webrtc

View file

@ -1,34 +0,0 @@
/*
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <CoreFoundation/CoreFoundation.h>
#include "webrtc/modules/desktop_capture/mac/window_list_utils.h"
#include "webrtc/modules/desktop_capture/window_under_point.h"
namespace webrtc {
WindowId GetWindowUnderPoint(DesktopVector point) {
WindowId id;
if (!GetWindowList([&id, point](CFDictionaryRef window) {
DesktopRect bounds = GetWindowBounds(window);
if (bounds.Contains(point)) {
id = GetWindowId(window);
return false;
}
return true;
},
true)) {
return kNullWindowId;
}
return id;
}
} // namespace webrtc

View file

@ -216,4 +216,25 @@ bool GetWindowList(XAtomCache* cache,
return failed_screens < num_screens;
}
bool GetWindowRect(::Display* display,
::Window window,
DesktopRect* rect,
XWindowAttributes* attributes /* = nullptr */) {
XWindowAttributes local_attributes;
if (attributes == nullptr) {
attributes = &local_attributes;
}
{
XErrorTrap error_trap(display);
if (!XGetWindowAttributes(display, window, attributes) ||
error_trap.GetLastErrorAndDisable() != 0) {
return false;
}
}
*rect = DesktopRectFromXAttributes(*attributes);
return true;
}
} // namespace webrtc

View file

@ -13,6 +13,7 @@
#include <X11/Xlib.h>
#include "webrtc/modules/desktop_capture/desktop_geometry.h"
#include "webrtc/modules/desktop_capture/x11/x_atom_cache.h"
#include "webrtc/rtc_base/function_view.h"
@ -32,6 +33,23 @@ bool GetWindowList(XAtomCache* cache,
// WithdrawnState if the |window| is missing.
int32_t GetWindowState(XAtomCache* cache, ::Window window);
// Returns the rectangle of the |window| in the coordinates of |display|. This
// function returns false if native APIs failed. If |attributes| is provided, it
// will be filled with the attributes of |window|.
bool GetWindowRect(::Display* display,
::Window window,
DesktopRect* rect,
XWindowAttributes* attributes = nullptr);
// Creates a DesktopRect from |attributes|.
template <typename T>
DesktopRect DesktopRectFromXAttributes(const T& attributes) {
return DesktopRect::MakeXYWH(attributes.x,
attributes.y,
attributes.width,
attributes.height);
}
} // namespace webrtc
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_X11_WINDOW_LIST_UTILS_H_

View file

@ -10,12 +10,13 @@
#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
#include <assert.h>
#include <string.h>
#include <sys/shm.h>
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/x11/window_list_utils.h"
#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/logging.h"
namespace webrtc {
@ -175,15 +176,10 @@ bool XServerPixelBuffer::Init(Display* display, Window window) {
display_ = display;
XWindowAttributes attributes;
{
XErrorTrap error_trap(display_);
if (!XGetWindowAttributes(display_, window, &attributes) ||
error_trap.GetLastErrorAndDisable() != 0) {
return false;
}
if (!GetWindowRect(display_, window, &window_rect_, &attributes)) {
return false;
}
window_size_ = DesktopSize(attributes.width, attributes.height);
window_ = window;
InitShm(attributes);
@ -208,7 +204,7 @@ void XServerPixelBuffer::InitShm(const XWindowAttributes& attributes) {
shm_segment_info_->readOnly = False;
x_shm_image_ = XShmCreateImage(display_, default_visual, default_depth,
ZPixmap, 0, shm_segment_info_,
window_size_.width(), window_size_.height());
window_rect_.width(), window_rect_.height());
if (x_shm_image_) {
shm_segment_info_->shmid =
shmget(IPC_PRIVATE, x_shm_image_->bytes_per_line * x_shm_image_->height,
@ -261,8 +257,8 @@ bool XServerPixelBuffer::InitPixmaps(int depth) {
shm_pixmap_ = XShmCreatePixmap(display_, window_,
shm_segment_info_->shmaddr,
shm_segment_info_,
window_size_.width(),
window_size_.height(), depth);
window_rect_.width(),
window_rect_.height(), depth);
XSync(display_, False);
if (error_trap.GetLastErrorAndDisable() != 0) {
// |shm_pixmap_| is not not valid because the request was not processed
@ -316,8 +312,8 @@ void XServerPixelBuffer::Synchronize() {
bool XServerPixelBuffer::CaptureRect(const DesktopRect& rect,
DesktopFrame* frame) {
assert(rect.right() <= window_size_.width());
assert(rect.bottom() <= window_size_.height());
RTC_DCHECK_LE(rect.right(), window_rect_.width());
RTC_DCHECK_LE(rect.bottom(), window_rect_.height());
XImage* image;
uint8_t* data;

View file

@ -39,7 +39,10 @@ class XServerPixelBuffer {
bool is_initialized() { return window_ != 0; }
// Returns the size of the window the buffer was initialized for.
const DesktopSize& window_size() { return window_size_; }
DesktopSize window_size() { return window_rect_.size(); }
// Returns the rectangle of the window the buffer was initialized for.
const DesktopRect& window_rect() { return window_rect_; }
// Returns true if the window can be found.
bool IsWindowValid() const;
@ -65,7 +68,7 @@ class XServerPixelBuffer {
Display* display_ = nullptr;
Window window_ = 0;
DesktopSize window_size_;
DesktopRect window_rect_;
XImage* x_image_ = nullptr;
XShmSegmentInfo* shm_segment_info_ = nullptr;
XImage* x_shm_image_ = nullptr;