/*
 *  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/x11/window_list_utils.h"

#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>

#include <algorithm>

#include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/constructormagic.h"
#include "webrtc/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_);
}

// Convenience wrapper for XGetWindowProperty() results.
template <class PropertyType>
class XWindowProperty {
 public:
  XWindowProperty(Display* display, Window window, Atom property) {
    const int kBitsPerByte = 8;
    Atom actual_type;
    int actual_format;
    unsigned long bytes_after;  // NOLINT: type required by XGetWindowProperty
    int status = XGetWindowProperty(display, window, property, 0L, ~0L, False,
                                    AnyPropertyType, &actual_type,
                                    &actual_format, &size_,
                                    &bytes_after, &data_);
    if (status != Success) {
      data_ = nullptr;
      return;
    }
    if (sizeof(PropertyType) * kBitsPerByte != actual_format) {
      size_ = 0;
      return;
    }

    is_valid_ = true;
  }

  ~XWindowProperty() {
    if (data_)
      XFree(data_);
  }

  // True if we got properly value successfully.
  bool is_valid() const { return is_valid_; }

  // Size and value of the property.
  size_t size() const { return size_; }
  const PropertyType* data() const {
    return reinterpret_cast<PropertyType*>(data_);
  }
  PropertyType* data() {
    return reinterpret_cast<PropertyType*>(data_);
  }

 private:
  bool is_valid_ = false;
  unsigned long size_ = 0;  // NOLINT: type required by XGetWindowProperty
  unsigned char* data_ = nullptr;

  RTC_DISALLOW_COPY_AND_ASSIGN(XWindowProperty);
};

// 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)) {
    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++;
        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;
    }
  }
  {
    XErrorTrap error_trap(display);
    ::Window child;
    if (!XTranslateCoordinates(display,
                               window,
                               attributes->root,
                               0,
                               0,
                               &offset_x,
                               &offset_y,
                               &child) ||
        error_trap.GetLastErrorAndDisable() != 0) {
      return false;
    }
  }

  *rect = DesktopRectFromXAttributes(*attributes);
  rect->Translate(offset_x, offset_y);
  return true;
}

}  // namespace webrtc
