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

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

#include <algorithm>

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

// 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)) {
    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
