// 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/aura/window_tree_host_x11.h"

#include <strings.h>
#include <X11/cursorfont.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xrandr.h>
#include <X11/Xatom.h>
#include <X11/Xcursor/Xcursor.h>
#include <X11/Xlib.h>

#include <algorithm>
#include <limits>
#include <string>

#include "base/command_line.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/view_prop.h"
#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_window_event_manager.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/display/screen.h"
#include "ui/events/devices/x11/device_data_manager_x11.h"
#include "ui/events/devices/x11/device_list_cache_x11.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
#include "ui/events/event.h"
#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/platform/platform_event_observer.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/x11/x11_event_source.h"

using std::max;
using std::min;

namespace aura {

namespace {

const char* kAtomsToCache[] = {
  "WM_DELETE_WINDOW",
  "_NET_WM_PING",
  "_NET_WM_PID",
  NULL
};

constexpr uint32_t kInputEventMask =
    ButtonPressMask | ButtonReleaseMask | FocusChangeMask | KeyPressMask |
    KeyReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask;

constexpr uint32_t kEventMask = kInputEventMask | ExposureMask |
                                VisibilityChangeMask | StructureNotifyMask |
                                PropertyChangeMask;

::Window FindEventTarget(const base::NativeEvent& xev) {
  ::Window target = xev->xany.window;
  if (xev->type == GenericEvent)
    target = static_cast<XIDeviceEvent*>(xev->xcookie.data)->event;
  return target;
}

void SelectXInput2EventsForRootWindow(XDisplay* display, ::Window root_window) {
  CHECK(ui::IsXInput2Available());
  unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {};
  memset(mask, 0, sizeof(mask));

  XISetMask(mask, XI_HierarchyChanged);

  XIEventMask evmask;
  evmask.deviceid = XIAllDevices;
  evmask.mask_len = sizeof(mask);
  evmask.mask = mask;
  XISelectEvents(display, root_window, &evmask, 1);

#if defined(OS_CHROMEOS)
  if (base::SysInfo::IsRunningOnChromeOS()) {
    // It is necessary to listen for touch events on the root window for proper
    // touch event calibration on Chrome OS, but this is not currently necessary
    // on the desktop. This seems to fail in some cases (e.g. when logging
    // in incognito). So select for non-touch events first, and then select for
    // touch-events (but keep the other events in the mask, i.e. do not memset
    // |mask| back to 0).
    // TODO(sad): Figure out why this happens. http://crbug.com/153976
    XISetMask(mask, XI_TouchBegin);
    XISetMask(mask, XI_TouchUpdate);
    XISetMask(mask, XI_TouchEnd);
    XISelectEvents(display, root_window, &evmask, 1);
  }
#endif
}

bool default_override_redirect = false;

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// WindowTreeHostX11

WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds)
    : xdisplay_(gfx::GetXDisplay()),
      xwindow_(0),
      x_root_window_(DefaultRootWindow(xdisplay_)),
      current_cursor_(ui::kCursorNull),
      window_mapped_(false),
      bounds_(bounds),
      atom_cache_(xdisplay_, kAtomsToCache) {
  XSetWindowAttributes swa;
  memset(&swa, 0, sizeof(swa));
  swa.background_pixmap = None;
  swa.bit_gravity = NorthWestGravity;
  swa.override_redirect = default_override_redirect;
  xwindow_ = XCreateWindow(
      xdisplay_, x_root_window_,
      bounds.x(), bounds.y(), bounds.width(), bounds.height(),
      0,               // border width
      CopyFromParent,  // depth
      InputOutput,
      CopyFromParent,  // visual
      CWBackPixmap | CWBitGravity | CWOverrideRedirect,
      &swa);
  if (ui::PlatformEventSource::GetInstance())
    ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);

  xwindow_events_.reset(new ui::XScopedEventSelector(xwindow_, kEventMask));
  XFlush(xdisplay_);

  if (ui::IsXInput2Available()) {
    ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
    SelectXInput2EventsForRootWindow(xdisplay_, x_root_window_);
  }

  // TODO(erg): We currently only request window deletion events. We also
  // should listen for activation events and anything else that GTK+ listens
  // for, and do something useful.
  ::Atom protocols[2];
  protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
  protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
  XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);

  // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
  // the desktop environment.
  XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);

  // Likewise, the X server needs to know this window's pid so it knows which
  // program to kill if the window hangs.
  // XChangeProperty() expects "pid" to be long.
  static_assert(sizeof(long) >= sizeof(pid_t),
                "pid_t should not be larger than long");
  long pid = getpid();
  XChangeProperty(xdisplay_,
                  xwindow_,
                  atom_cache_.GetAtom("_NET_WM_PID"),
                  XA_CARDINAL,
                  32,
                  PropModeReplace,
                  reinterpret_cast<unsigned char*>(&pid), 1);

  // Allow subclasses to create and cache additional atoms.
  atom_cache_.allow_uncached_atoms();

  XRRSelectInput(xdisplay_, x_root_window_,
                 RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
  CreateCompositor();
  OnAcceleratedWidgetAvailable();
}

WindowTreeHostX11::~WindowTreeHostX11() {
  if (ui::PlatformEventSource::GetInstance())
    ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);

  DestroyCompositor();
  DestroyDispatcher();
  XDestroyWindow(xdisplay_, xwindow_);
}

bool WindowTreeHostX11::CanDispatchEvent(const ui::PlatformEvent& event) {
  ::Window target = FindEventTarget(event);
  return target == xwindow_ || target == x_root_window_;
}

uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) {
  XEvent* xev = event;
  if (FindEventTarget(xev) == x_root_window_) {
    if (xev->type == GenericEvent)
      DispatchXI2Event(xev);
    return ui::POST_DISPATCH_NONE;
  }

  if (xev->type == MotionNotify) {
    // Discard all but the most recent motion event that targets the same
    // window with unchanged state.
    XEvent last_event;
    while (XPending(xev->xany.display)) {
      XEvent next_event;
      XPeekEvent(xev->xany.display, &next_event);
      if (next_event.type == MotionNotify &&
          next_event.xmotion.window == xev->xmotion.window &&
          next_event.xmotion.subwindow == xev->xmotion.subwindow &&
          next_event.xmotion.state == xev->xmotion.state) {
        XNextEvent(xev->xany.display, &last_event);
        xev = &last_event;
      } else {
        break;
      }
    }
  }

  if ((xev->type == EnterNotify || xev->type == LeaveNotify) &&
      xev->xcrossing.detail == NotifyInferior) {
    // Ignore EventNotify and LeaveNotify  events from children of |xwindow_|.
    // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
    // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
    // necessary. crbug.com/385716
    return ui::POST_DISPATCH_STOP_PROPAGATION;
  }

  if (xev->type == EnterNotify ||
      xev->type == LeaveNotify ||
      xev->type == KeyPress ||
      xev->type == KeyRelease ||
      xev->type == ButtonPress ||
      xev->type == ButtonRelease ||
      xev->type == MotionNotify) {
    switch (ui::EventTypeFromNative(xev)) {
      case ui::ET_KEY_PRESSED:
      case ui::ET_KEY_RELEASED: {
        ui::KeyEvent keydown_event(xev);
        SendEventToProcessor(&keydown_event);
        break;
      }
      case ui::ET_MOUSE_MOVED:
      case ui::ET_MOUSE_DRAGGED:
      case ui::ET_MOUSE_ENTERED:
      case ui::ET_MOUSE_EXITED:
      case ui::ET_MOUSE_PRESSED:
      case ui::ET_MOUSE_RELEASED: {
        ui::MouseEvent mouse_event(xev);
        if (xev->type == EnterNotify) {
          aura::Window* root_window = window();
          client::CursorClient* cursor_client =
              client::GetCursorClient(root_window);
          if (cursor_client) {
            const display::Display display =
                display::Screen::GetScreen()->GetDisplayNearestWindow(
                    root_window);
            cursor_client->SetDisplay(display);
          }
          // EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is
          // not a real mouse move event.
          mouse_event.set_flags(mouse_event.flags() | ui::EF_IS_SYNTHESIZED);
        }

        TranslateAndDispatchLocatedEvent(&mouse_event);
        break;
      }
      case ui::ET_MOUSEWHEEL: {
        ui::MouseWheelEvent mouseev(xev);
        TranslateAndDispatchLocatedEvent(&mouseev);
        break;
      }
      case ui::ET_UNKNOWN:
        // No event is created for X11-release events for mouse-wheel buttons.
        break;
      default:
         NOTREACHED();
    }
    return ui::POST_DISPATCH_STOP_PROPAGATION;
  }

  switch (xev->type) {
    case Expose: {
      gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
                            xev->xexpose.width, xev->xexpose.height);
      compositor()->ScheduleRedrawRect(damage_rect);
      break;
    }
    case FocusOut:
      if (xev->xfocus.mode != NotifyGrab)
        OnHostLostWindowCapture();
      break;
    case ConfigureNotify: {
      DCHECK_EQ(xwindow_, xev->xconfigure.event);
      DCHECK_EQ(xwindow_, xev->xconfigure.window);
      // It's possible that the X window may be resized by some other means
      // than from within aura (e.g. the X window manager can change the
      // size). Make sure the root window size is maintained properly.
      gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
          xev->xconfigure.width, xev->xconfigure.height);
      bool size_changed = bounds_.size() != bounds.size();
      bool origin_changed = bounds_.origin() != bounds.origin();
      bounds_ = bounds;
      OnConfigureNotify();
      if (size_changed)
        OnHostResized(bounds.size());
      if (origin_changed)
        OnHostMoved(bounds_.origin());
      break;
    }
    case GenericEvent:
      DispatchXI2Event(xev);
      break;
    case ClientMessage: {
      Atom message_type = static_cast<Atom>(xev->xclient.data.l[0]);
      if (message_type == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
        // We have received a close message from the window manager.
        OnHostCloseRequested();
      } else if (message_type == atom_cache_.GetAtom("_NET_WM_PING")) {
        XEvent reply_event = *xev;
        reply_event.xclient.window = x_root_window_;

        XSendEvent(xdisplay_,
                   reply_event.xclient.window,
                   False,
                   SubstructureRedirectMask | SubstructureNotifyMask,
                   &reply_event);
        XFlush(xdisplay_);
      }
      break;
    }
    case MappingNotify: {
      switch (xev->xmapping.request) {
        case MappingModifier:
        case MappingKeyboard:
          XRefreshKeyboardMapping(&xev->xmapping);
          break;
        case MappingPointer:
          ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap();
          break;
        default:
          NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
          break;
      }
      break;
    }
  }
  return ui::POST_DISPATCH_STOP_PROPAGATION;
}

ui::EventSource* WindowTreeHostX11::GetEventSource() {
  return this;
}

gfx::AcceleratedWidget WindowTreeHostX11::GetAcceleratedWidget() {
  return xwindow_;
}

void WindowTreeHostX11::ShowImpl() {
  if (!window_mapped_) {
    // Before we map the window, set size hints. Otherwise, some window managers
    // will ignore toplevel XMoveWindow commands.
    XSizeHints size_hints;
    size_hints.flags = PPosition | PWinGravity;
    size_hints.x = bounds_.x();
    size_hints.y = bounds_.y();
    // Set StaticGravity so that the window position is not affected by the
    // frame width when running with window manager.
    size_hints.win_gravity = StaticGravity;
    XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);

    XMapWindow(xdisplay_, xwindow_);

    // We now block until our window is mapped. Some X11 APIs will crash and
    // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
    // asynchronous.
    if (ui::X11EventSource::GetInstance())
      ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
    window_mapped_ = true;
  }
}

void WindowTreeHostX11::HideImpl() {
  if (window_mapped_) {
    XWithdrawWindow(xdisplay_, xwindow_, 0);
    window_mapped_ = false;
  }
}

gfx::Rect WindowTreeHostX11::GetBounds() const {
  return bounds_;
}

void WindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
  // Even if the host window's size doesn't change, aura's root window
  // size, which is in DIP, changes when the scale changes.
  float current_scale = compositor()->device_scale_factor();
  float new_scale = display::Screen::GetScreen()
                        ->GetDisplayNearestWindow(window())
                        .device_scale_factor();
  bool origin_changed = bounds_.origin() != bounds.origin();
  bool size_changed = bounds_.size() != bounds.size();
  XWindowChanges changes = {0};
  unsigned value_mask = 0;

  if (size_changed) {
    changes.width = bounds.width();
    changes.height = bounds.height();
    value_mask = CWHeight | CWWidth;
  }

  if (origin_changed) {
    changes.x = bounds.x();
    changes.y = bounds.y();
    value_mask |= CWX | CWY;
  }
  if (value_mask)
    XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);

  // Assume that the resize will go through as requested, which should be the
  // case if we're running without a window manager.  If there's a window
  // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
  // (possibly synthetic) ConfigureNotify about the actual size and correct
  // |bounds_| later.
  bounds_ = bounds;
  if (origin_changed)
    OnHostMoved(bounds.origin());
  if (size_changed || current_scale != new_scale) {
    OnHostResized(bounds.size());
  } else {
    window()->SchedulePaintInRect(window()->bounds());
  }
}

gfx::Point WindowTreeHostX11::GetLocationOnNativeScreen() const {
  return bounds_.origin();
}

void WindowTreeHostX11::SetCapture() {
  // Do not grab X11 input. Grabbing X11 input is asynchronous and this method
  // is expected to be synchronous. Grabbing X11 input is unnecessary on
  // ChromeOS because ChromeOS manages all of the X windows. When running
  // ChromeOS on the desktop for the sake of debugging:
  // - Implicit pointer grab as a result of pressing a mouse button
  // - Releasing capture as a result of losing activation (FocusOut)
  // is sufficient.
}

void WindowTreeHostX11::ReleaseCapture() {
}

void WindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
  if (cursor == current_cursor_)
    return;
  current_cursor_ = cursor;
  SetCursorInternal(cursor);
}

void WindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) {
  XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
               bounds_.x() + location.x(),
               bounds_.y() + location.y());
}

void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
}

void WindowTreeHostX11::DisableInput() {
  xwindow_events_.reset(
      new ui::XScopedEventSelector(xwindow_, kEventMask & ~kInputEventMask));
  unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0};
  XIEventMask evmask;
  evmask.deviceid = XIAllDevices;
  evmask.mask_len = sizeof(mask);
  evmask.mask = mask;
  XISelectEvents(gfx::GetXDisplay(), xwindow_, &evmask, 1);
}

void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) {
  ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
  XEvent* xev = event;
  if (!factory->ShouldProcessXI2Event(xev))
    return;

  TRACE_EVENT1("input", "WindowTreeHostX11::DispatchXI2Event",
               "event_latency_us",
               (ui::EventTimeForNow() - ui::EventTimeFromNative(event)).
                 InMicroseconds());

  int num_coalesced = 0;
  XEvent last_event;
  if (xev->xgeneric.evtype == XI_Motion) {
    // If this is a motion event, we want to coalesce all pending motion
    // events that are at the top of the queue. Note, we don't coalesce
    // touch update events here.
    num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
    if (num_coalesced > 0)
      xev = &last_event;
  }
  ui::EventType type = ui::EventTypeFromNative(xev);

  switch (type) {
    case ui::ET_TOUCH_MOVED:
    case ui::ET_TOUCH_PRESSED:
    case ui::ET_TOUCH_CANCELLED:
    case ui::ET_TOUCH_RELEASED: {
      ui::TouchEvent touchev(xev);
      TranslateAndDispatchLocatedEvent(&touchev);
      break;
    }
    case ui::ET_MOUSE_MOVED:
    case ui::ET_MOUSE_DRAGGED:
    case ui::ET_MOUSE_PRESSED:
    case ui::ET_MOUSE_RELEASED:
    case ui::ET_MOUSE_ENTERED:
    case ui::ET_MOUSE_EXITED: {
      ui::MouseEvent mouseev(xev);
      TranslateAndDispatchLocatedEvent(&mouseev);
      break;
    }
    case ui::ET_MOUSEWHEEL: {
      ui::MouseWheelEvent mouseev(xev);
      TranslateAndDispatchLocatedEvent(&mouseev);
      break;
    }
    case ui::ET_SCROLL_FLING_START:
    case ui::ET_SCROLL_FLING_CANCEL:
    case ui::ET_SCROLL: {
      ui::ScrollEvent scrollev(xev);
      SendEventToProcessor(&scrollev);
      break;
    }
    case ui::ET_KEY_PRESSED:
    case ui::ET_KEY_RELEASED: {
      ui::KeyEvent key_event(xev);
      SendEventToProcessor(&key_event);
      break;
    }
    case ui::ET_UMA_DATA:
      break;
    case ui::ET_UNKNOWN:
      break;
    default:
      NOTREACHED();
  }

  // If we coalesced an event we need to free its cookie.
  if (num_coalesced > 0)
    XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
}

void WindowTreeHostX11::SetCursorInternal(gfx::NativeCursor cursor) {
  XDefineCursor(xdisplay_, xwindow_, cursor.platform());
}

void WindowTreeHostX11::OnConfigureNotify() {}

void WindowTreeHostX11::TranslateAndDispatchLocatedEvent(
    ui::LocatedEvent* event) {
  SendEventToProcessor(event);
}

// static
WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
  return new WindowTreeHostX11(bounds);
}

namespace test {

void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
  default_override_redirect = override_redirect;
}

}  // namespace test
}  // namespace aura
