This CL was generated by running:
git ls-files | grep ".cc" | xargs perl -i -ne 'BEGIN {undef $/}; s/("[\s\n]*<<[\s\n]*")/" "/g; print;'; git cl format
After that I manually edited modules/audio_processing/gain_controller2.cc to preserve its original
formatting.
This primary benefit of this change is a small reduction in binary size.
Bug: None
Change-Id: I689fa7ba9c717c314bb167e5d592c3c4e0871e29
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/165961
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Jonas Olsson <jonasolsson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30251}
200 lines
6.1 KiB
C++
200 lines
6.1 KiB
C++
/*
|
|
* 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 "modules/desktop_capture/linux/window_list_utils.h"
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <string.h>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "modules/desktop_capture/linux/x_error_trap.h"
|
|
#include "modules/desktop_capture/linux/x_window_property.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/constructor_magic.h"
|
|
#include "rtc_base/logging.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
class DeferXFree {
|
|
public:
|
|
explicit DeferXFree(void* data) : data_(data) {}
|
|
~DeferXFree();
|
|
|
|
private:
|
|
void* const data_;
|
|
};
|
|
|
|
DeferXFree::~DeferXFree() {
|
|
if (data_)
|
|
XFree(data_);
|
|
}
|
|
|
|
// Iterates through |window| hierarchy to find first visible window, i.e. one
|
|
// that has WM_STATE property set to NormalState.
|
|
// See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
|
|
::Window GetApplicationWindow(XAtomCache* cache, ::Window window) {
|
|
int32_t state = GetWindowState(cache, window);
|
|
if (state == NormalState) {
|
|
// Window has WM_STATE==NormalState. Return it.
|
|
return window;
|
|
} else if (state == IconicState) {
|
|
// Window is in minimized. Skip it.
|
|
return 0;
|
|
}
|
|
|
|
RTC_DCHECK_EQ(state, WithdrawnState);
|
|
// If the window is in WithdrawnState then look at all of its children.
|
|
::Window root, parent;
|
|
::Window* children;
|
|
unsigned int num_children;
|
|
if (!XQueryTree(cache->display(), window, &root, &parent, &children,
|
|
&num_children)) {
|
|
RTC_LOG(LS_ERROR) << "Failed to query for child windows although window"
|
|
"does not have a valid WM_STATE.";
|
|
return 0;
|
|
}
|
|
::Window app_window = 0;
|
|
for (unsigned int i = 0; i < num_children; ++i) {
|
|
app_window = GetApplicationWindow(cache, children[i]);
|
|
if (app_window)
|
|
break;
|
|
}
|
|
|
|
if (children)
|
|
XFree(children);
|
|
return app_window;
|
|
}
|
|
|
|
// Returns true if the |window| is a desktop element.
|
|
bool IsDesktopElement(XAtomCache* cache, ::Window window) {
|
|
RTC_DCHECK(cache);
|
|
if (window == 0)
|
|
return false;
|
|
|
|
// First look for _NET_WM_WINDOW_TYPE. The standard
|
|
// (http://standards.freedesktop.org/wm-spec/latest/ar01s05.html#id2760306)
|
|
// says this hint *should* be present on all windows, and we use the existence
|
|
// of _NET_WM_WINDOW_TYPE_NORMAL in the property to indicate a window is not
|
|
// a desktop element (that is, only "normal" windows should be shareable).
|
|
XWindowProperty<uint32_t> window_type(cache->display(), window,
|
|
cache->WindowType());
|
|
if (window_type.is_valid() && window_type.size() > 0) {
|
|
uint32_t* end = window_type.data() + window_type.size();
|
|
bool is_normal =
|
|
(end != std::find(window_type.data(), end, cache->WindowTypeNormal()));
|
|
return !is_normal;
|
|
}
|
|
|
|
// Fall back on using the hint.
|
|
XClassHint class_hint;
|
|
Status status = XGetClassHint(cache->display(), window, &class_hint);
|
|
if (status == 0) {
|
|
// No hints, assume this is a normal application window.
|
|
return false;
|
|
}
|
|
|
|
DeferXFree free_res_name(class_hint.res_name);
|
|
DeferXFree free_res_class(class_hint.res_class);
|
|
return strcmp("gnome-panel", class_hint.res_name) == 0 ||
|
|
strcmp("desktop_window", class_hint.res_name) == 0;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int32_t GetWindowState(XAtomCache* cache, ::Window window) {
|
|
// Get WM_STATE property of the window.
|
|
XWindowProperty<uint32_t> window_state(cache->display(), window,
|
|
cache->WmState());
|
|
|
|
// WM_STATE is considered to be set to WithdrawnState when it missing.
|
|
return window_state.is_valid() ? *window_state.data() : WithdrawnState;
|
|
}
|
|
|
|
bool GetWindowList(XAtomCache* cache,
|
|
rtc::FunctionView<bool(::Window)> on_window) {
|
|
RTC_DCHECK(cache);
|
|
RTC_DCHECK(on_window);
|
|
::Display* const display = cache->display();
|
|
|
|
int failed_screens = 0;
|
|
const int num_screens = XScreenCount(display);
|
|
for (int screen = 0; screen < num_screens; screen++) {
|
|
::Window root_window = XRootWindow(display, screen);
|
|
::Window parent;
|
|
::Window* children;
|
|
unsigned int num_children;
|
|
{
|
|
XErrorTrap error_trap(display);
|
|
if (XQueryTree(display, root_window, &root_window, &parent, &children,
|
|
&num_children) == 0 ||
|
|
error_trap.GetLastErrorAndDisable() != 0) {
|
|
failed_screens++;
|
|
RTC_LOG(LS_ERROR) << "Failed to query for child windows for screen "
|
|
<< screen;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
DeferXFree free_children(children);
|
|
|
|
for (unsigned int i = 0; i < num_children; i++) {
|
|
// Iterates in reverse order to return windows from front to back.
|
|
::Window app_window =
|
|
GetApplicationWindow(cache, children[num_children - 1 - i]);
|
|
if (app_window && !IsDesktopElement(cache, app_window)) {
|
|
if (!on_window(app_window)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return failed_screens < num_screens;
|
|
}
|
|
|
|
bool GetWindowRect(::Display* display,
|
|
::Window window,
|
|
DesktopRect* rect,
|
|
XWindowAttributes* attributes /* = nullptr */) {
|
|
XWindowAttributes local_attributes;
|
|
int offset_x;
|
|
int offset_y;
|
|
if (attributes == nullptr) {
|
|
attributes = &local_attributes;
|
|
}
|
|
|
|
{
|
|
XErrorTrap error_trap(display);
|
|
if (!XGetWindowAttributes(display, window, attributes) ||
|
|
error_trap.GetLastErrorAndDisable() != 0) {
|
|
return false;
|
|
}
|
|
}
|
|
*rect = DesktopRectFromXAttributes(*attributes);
|
|
|
|
{
|
|
XErrorTrap error_trap(display);
|
|
::Window child;
|
|
if (!XTranslateCoordinates(display, window, attributes->root, -rect->left(),
|
|
-rect->top(), &offset_x, &offset_y, &child) ||
|
|
error_trap.GetLastErrorAndDisable() != 0) {
|
|
return false;
|
|
}
|
|
}
|
|
rect->Translate(offset_x, offset_y);
|
|
return true;
|
|
}
|
|
|
|
} // namespace webrtc
|