// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/widget/desktop_aura/desktop_screen_x11.h"

#include <X11/extensions/Xrandr.h>
#include <X11/Xlib.h>

// It clashes with out RootWindow.
#undef RootWindow

#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/layout.h"
#include "ui/display/util/display_util.h"
#include "ui/display/util/x11/edid_parser_x11.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/display.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"

namespace {

// The delay to perform configuration after RRNotify.  See the comment
// in |Dispatch()|.
const int64 kConfigureDelayMs = 500;

// TODO(oshima): Consider using gtk-xft-dpi instead.
float GetDeviceScaleFactor(int screen_pixels, int screen_mm) {
  const int kCSSDefaultDPI = 96;
  const float kInchInMm = 25.4f;

  float screen_inches = screen_mm / kInchInMm;
  float screen_dpi = screen_pixels / screen_inches;
  float scale = screen_dpi / kCSSDefaultDPI;

  return ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(scale));
}

float GetDeviceScaleFactor() {
  gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
  return display.device_scale_factor();
}

gfx::Point PixelToDIPPoint(const gfx::Point& pixel_point) {
  return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDeviceScaleFactor()));
}

gfx::Point DIPToPixelPoint(const gfx::Point& dip_point) {
  return ToFlooredPoint(gfx::ScalePoint(dip_point, GetDeviceScaleFactor()));
}

std::vector<gfx::Display> GetFallbackDisplayList() {
  ::XDisplay* display = gfx::GetXDisplay();
  ::Screen* screen = DefaultScreenOfDisplay(display);
  int width = WidthOfScreen(screen);
  int height = HeightOfScreen(screen);
  gfx::Size physical_size(WidthMMOfScreen(screen), HeightMMOfScreen(screen));

  gfx::Rect bounds_in_pixels(0, 0, width, height);
  gfx::Display gfx_display(0, bounds_in_pixels);
  if (!gfx::Display::HasForceDeviceScaleFactor() &&
      !ui::IsDisplaySizeBlackListed(physical_size)) {
    float device_scale_factor = GetDeviceScaleFactor(
        width, physical_size.width());
    DCHECK_LE(1.0f, device_scale_factor);
    gfx_display.SetScaleAndBounds(device_scale_factor, bounds_in_pixels);
  }

  return std::vector<gfx::Display>(1, gfx_display);
}

}  // namespace

namespace views {

////////////////////////////////////////////////////////////////////////////////
// DesktopScreenX11, public:

DesktopScreenX11::DesktopScreenX11()
    : xdisplay_(gfx::GetXDisplay()),
      x_root_window_(DefaultRootWindow(xdisplay_)),
      has_xrandr_(false),
      xrandr_event_base_(0) {
  // We only support 1.3+. There were library changes before this and we should
  // use the new interface instead of the 1.2 one.
  int randr_version_major = 0;
  int randr_version_minor = 0;
  has_xrandr_ = XRRQueryVersion(
        xdisplay_, &randr_version_major, &randr_version_minor) &&
      randr_version_major == 1 &&
      randr_version_minor >= 3;

  if (has_xrandr_) {
    int error_base_ignored = 0;
    XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);

    if (ui::PlatformEventSource::GetInstance())
      ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
    XRRSelectInput(xdisplay_,
                   x_root_window_,
                   RRScreenChangeNotifyMask |
                   RROutputChangeNotifyMask |
                   RRCrtcChangeNotifyMask);

    displays_ = BuildDisplaysFromXRandRInfo();
  } else {
    displays_ = GetFallbackDisplayList();
  }
}

DesktopScreenX11::~DesktopScreenX11() {
  if (has_xrandr_ && ui::PlatformEventSource::GetInstance())
    ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
}

////////////////////////////////////////////////////////////////////////////////
// DesktopScreenX11, gfx::Screen implementation:

gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
  TRACE_EVENT0("views", "DesktopScreenX11::GetCursorScreenPoint()");

  XDisplay* display = gfx::GetXDisplay();

  ::Window root, child;
  int root_x, root_y, win_x, win_y;
  unsigned int mask;
  XQueryPointer(display,
                DefaultRootWindow(display),
                &root,
                &child,
                &root_x,
                &root_y,
                &win_x,
                &win_y,
                &mask);

  return PixelToDIPPoint(gfx::Point(root_x, root_y));
}

gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() {
  return GetWindowAtScreenPoint(GetCursorScreenPoint());
}

gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint(
    const gfx::Point& point) {
  X11TopmostWindowFinder finder;
  return finder.FindLocalProcessWindowAt(
      DIPToPixelPoint(point), std::set<aura::Window*>());
}

int DesktopScreenX11::GetNumDisplays() const {
  return displays_.size();
}

std::vector<gfx::Display> DesktopScreenX11::GetAllDisplays() const {
  return displays_;
}

gfx::Display DesktopScreenX11::GetDisplayNearestWindow(
    gfx::NativeView window) const {
  if (!window)
    return GetPrimaryDisplay();

  // Getting screen bounds here safely is hard.
  //
  // You'd think we'd be able to just call window->GetBoundsInScreen(), but we
  // can't because |window| (and the associated WindowEventDispatcher*) can be
  // partially initialized at this point; WindowEventDispatcher initializations
  // call through into GetDisplayNearestWindow(). But the X11 resources are
  // created before we create the aura::WindowEventDispatcher. So we ask what
  // the DRWHX11 believes the window bounds are instead of going through the
  // aura::Window's screen bounds.
  aura::WindowTreeHost* host = window->GetHost();
  if (host) {
    DesktopWindowTreeHostX11* rwh = DesktopWindowTreeHostX11::GetHostForXID(
        host->GetAcceleratedWidget());
    if (rwh)
      return GetDisplayMatching(rwh->GetX11RootWindowBounds());
  }

  return GetPrimaryDisplay();
}

gfx::Display DesktopScreenX11::GetDisplayNearestPoint(
    const gfx::Point& requested_point) const {
  const gfx::Point point_in_pixel = DIPToPixelPoint(requested_point);
  for (std::vector<gfx::Display>::const_iterator it = displays_.begin();
       it != displays_.end(); ++it) {
    if (it->bounds().Contains(point_in_pixel))
      return *it;
  }

  return GetPrimaryDisplay();
}

gfx::Display DesktopScreenX11::GetDisplayMatching(
    const gfx::Rect& match_rect) const {
  int max_area = 0;
  const gfx::Display* matching = NULL;
  for (std::vector<gfx::Display>::const_iterator it = displays_.begin();
       it != displays_.end(); ++it) {
    gfx::Rect intersect = gfx::IntersectRects(it->bounds(), match_rect);
    int area = intersect.width() * intersect.height();
    if (area > max_area) {
      max_area = area;
      matching = &*it;
    }
  }
  // Fallback to the primary display if there is no matching display.
  return matching ? *matching : GetPrimaryDisplay();
}

gfx::Display DesktopScreenX11::GetPrimaryDisplay() const {
  return displays_.front();
}

void DesktopScreenX11::AddObserver(gfx::DisplayObserver* observer) {
  change_notifier_.AddObserver(observer);
}

void DesktopScreenX11::RemoveObserver(gfx::DisplayObserver* observer) {
  change_notifier_.RemoveObserver(observer);
}

bool DesktopScreenX11::CanDispatchEvent(const ui::PlatformEvent& event) {
  return event->type - xrandr_event_base_ == RRScreenChangeNotify ||
         event->type - xrandr_event_base_ == RRNotify;
}

uint32_t DesktopScreenX11::DispatchEvent(const ui::PlatformEvent& event) {
  if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
    // Pass the event through to xlib.
    XRRUpdateConfiguration(event);
  } else if (event->type - xrandr_event_base_ == RRNotify) {
    // There's some sort of observer dispatch going on here, but I don't think
    // it's the screen's?
    if (configure_timer_.get() && configure_timer_->IsRunning()) {
      configure_timer_->Reset();
    } else {
      configure_timer_.reset(new base::OneShotTimer<DesktopScreenX11>());
      configure_timer_->Start(
          FROM_HERE,
          base::TimeDelta::FromMilliseconds(kConfigureDelayMs),
          this,
          &DesktopScreenX11::ConfigureTimerFired);
    }
  } else {
    NOTREACHED();
  }

  return ui::POST_DISPATCH_NONE;
}

////////////////////////////////////////////////////////////////////////////////
// DesktopScreenX11, private:

DesktopScreenX11::DesktopScreenX11(
    const std::vector<gfx::Display>& test_displays)
    : xdisplay_(gfx::GetXDisplay()),
      x_root_window_(DefaultRootWindow(xdisplay_)),
      has_xrandr_(false),
      xrandr_event_base_(0),
      displays_(test_displays) {
}

std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
  std::vector<gfx::Display> displays;
  gfx::XScopedPtr<
      XRRScreenResources,
      gfx::XObjectDeleter<XRRScreenResources, void, XRRFreeScreenResources>>
      resources(XRRGetScreenResourcesCurrent(xdisplay_, x_root_window_));
  if (!resources) {
    LOG(ERROR) << "XRandR returned no displays. Falling back to Root Window.";
    return GetFallbackDisplayList();
  }

  bool has_work_area = false;
  gfx::Rect work_area;
  std::vector<int> value;
  if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) &&
      value.size() >= 4) {
    work_area = gfx::Rect(value[0], value[1], value[2], value[3]);
    has_work_area = true;
  }

  float device_scale_factor = 1.0f;
  for (int i = 0; i < resources->noutput; ++i) {
    RROutput output_id = resources->outputs[i];
    gfx::XScopedPtr<XRROutputInfo,
                    gfx::XObjectDeleter<XRROutputInfo, void, XRRFreeOutputInfo>>
        output_info(XRRGetOutputInfo(xdisplay_, resources.get(), output_id));

    bool is_connected = (output_info->connection == RR_Connected);
    if (!is_connected)
      continue;

    if (output_info->crtc) {
      gfx::XScopedPtr<XRRCrtcInfo,
                      gfx::XObjectDeleter<XRRCrtcInfo, void, XRRFreeCrtcInfo>>
          crtc(XRRGetCrtcInfo(xdisplay_, resources.get(), output_info->crtc));

      int64 display_id = -1;
      if (!ui::GetDisplayId(output_id, static_cast<uint8>(i), &display_id)) {
        // It isn't ideal, but if we can't parse the EDID data, fallback on the
        // display number.
        display_id = i;
      }

      gfx::Rect crtc_bounds(crtc->x, crtc->y, crtc->width, crtc->height);
      gfx::Display display(display_id, crtc_bounds);

      if (!gfx::Display::HasForceDeviceScaleFactor()) {
        if (i == 0 && !ui::IsDisplaySizeBlackListed(
            gfx::Size(output_info->mm_width, output_info->mm_height))) {
          // As per display scale factor is not supported right now,
          // the primary display's scale factor is always used.
          device_scale_factor = GetDeviceScaleFactor(crtc->width,
                                                     output_info->mm_width);
          DCHECK_LE(1.0f, device_scale_factor);
        }
        display.SetScaleAndBounds(device_scale_factor, crtc_bounds);
      }

      if (has_work_area) {
        gfx::Rect intersection = crtc_bounds;
        intersection.Intersect(work_area);
        display.set_work_area(intersection);
      }

      switch (crtc->rotation) {
        case RR_Rotate_0:
          display.set_rotation(gfx::Display::ROTATE_0);
          break;
        case RR_Rotate_90:
          display.set_rotation(gfx::Display::ROTATE_90);
          break;
        case RR_Rotate_180:
          display.set_rotation(gfx::Display::ROTATE_180);
          break;
        case RR_Rotate_270:
          display.set_rotation(gfx::Display::ROTATE_270);
          break;
      }

      displays.push_back(display);
    }
  }

  if (displays.empty())
    return GetFallbackDisplayList();

  return displays;
}

void DesktopScreenX11::ConfigureTimerFired() {
  std::vector<gfx::Display> old_displays = displays_;
  displays_ = BuildDisplaysFromXRandRInfo();

  change_notifier_.NotifyDisplaysChanged(old_displays, displays_);
}

////////////////////////////////////////////////////////////////////////////////

gfx::Screen* CreateDesktopScreen() {
  return new DesktopScreenX11;
}

}  // namespace views
