// 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 "remoting/host/local_input_monitor.h"

#include <sys/select.h>
#include <unistd.h>
#define XK_MISCELLANY
#include <X11/keysymdef.h>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_pump_libevent.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/non_thread_safe.h"
#include "remoting/host/client_session_control.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"

// These includes need to be later than dictated by the style guide due to
// Xlib header pollution, specifically the min, max, and Status macros.
#include <X11/XKBlib.h>
#include <X11/Xlibint.h>
#include <X11/extensions/record.h>

namespace remoting {

namespace {

class LocalInputMonitorX11 : public base::NonThreadSafe,
                               public LocalInputMonitor {
 public:
  LocalInputMonitorX11(
      scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
      scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
      base::WeakPtr<ClientSessionControl> client_session_control);
  ~LocalInputMonitorX11() override;

 private:
  // The actual implementation resides in LocalInputMonitorX11::Core class.
  class Core
      : public base::RefCountedThreadSafe<Core>,
        public base::MessagePumpLibevent::Watcher {
   public:
    Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
         scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
         base::WeakPtr<ClientSessionControl> client_session_control);

    void Start();
    void Stop();

   private:
    friend class base::RefCountedThreadSafe<Core>;
    ~Core() override;

    void StartOnInputThread();
    void StopOnInputThread();

    // base::MessagePumpLibevent::Watcher interface.
    void OnFileCanReadWithoutBlocking(int fd) override;
    void OnFileCanWriteWithoutBlocking(int fd) override;

    // Processes key and mouse events.
    void ProcessXEvent(xEvent* event);

    static void ProcessReply(XPointer self, XRecordInterceptData* data);

    // Task runner on which public methods of this class must be called.
    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;

    // Task runner on which X Window events are received.
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;

    // Points to the object receiving mouse event notifications and session
    // disconnect requests.
    base::WeakPtr<ClientSessionControl> client_session_control_;

    // Used to receive base::MessagePumpLibevent::Watcher events.
    base::MessagePumpLibevent::FileDescriptorWatcher controller_;

    // True when Alt is pressed.
    bool alt_pressed_;

    // True when Ctrl is pressed.
    bool ctrl_pressed_;

    Display* display_;
    Display* x_record_display_;
    XRecordRange* x_record_range_[2];
    XRecordContext x_record_context_;

    DISALLOW_COPY_AND_ASSIGN(Core);
  };

  scoped_refptr<Core> core_;

  DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorX11);
};

LocalInputMonitorX11::LocalInputMonitorX11(
    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
    base::WeakPtr<ClientSessionControl> client_session_control)
    : core_(new Core(caller_task_runner,
                     input_task_runner,
                     client_session_control)) {
  core_->Start();
}

LocalInputMonitorX11::~LocalInputMonitorX11() {
  core_->Stop();
}

LocalInputMonitorX11::Core::Core(
    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
    base::WeakPtr<ClientSessionControl> client_session_control)
    : caller_task_runner_(caller_task_runner),
      input_task_runner_(input_task_runner),
      client_session_control_(client_session_control),
      alt_pressed_(false),
      ctrl_pressed_(false),
      display_(nullptr),
      x_record_display_(nullptr),
      x_record_context_(0) {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());
  DCHECK(client_session_control_.get());

  x_record_range_[0] = nullptr;
  x_record_range_[1] = nullptr;
}

void LocalInputMonitorX11::Core::Start() {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  input_task_runner_->PostTask(FROM_HERE,
                               base::Bind(&Core::StartOnInputThread, this));
}

void LocalInputMonitorX11::Core::Stop() {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());

  input_task_runner_->PostTask(FROM_HERE,
                               base::Bind(&Core::StopOnInputThread, this));
}

LocalInputMonitorX11::Core::~Core() {
  DCHECK(!display_);
  DCHECK(!x_record_display_);
  DCHECK(!x_record_range_[0]);
  DCHECK(!x_record_range_[1]);
  DCHECK(!x_record_context_);
}

void LocalInputMonitorX11::Core::StartOnInputThread() {
  DCHECK(input_task_runner_->BelongsToCurrentThread());
  DCHECK(!display_);
  DCHECK(!x_record_display_);
  DCHECK(!x_record_range_[0]);
  DCHECK(!x_record_range_[1]);
  DCHECK(!x_record_context_);

  // TODO(jamiewalch): We should pass the display in. At that point, since
  // XRecord needs a private connection to the X Server for its data channel
  // and both channels are used from a separate thread, we'll need to duplicate
  // them with something like the following:
  //   XOpenDisplay(DisplayString(display));
  display_ = XOpenDisplay(nullptr);
  x_record_display_ = XOpenDisplay(nullptr);
  if (!display_ || !x_record_display_) {
    LOG(ERROR) << "Couldn't open X display";
    return;
  }

  int xr_opcode, xr_event, xr_error;
  if (!XQueryExtension(display_, "RECORD", &xr_opcode, &xr_event, &xr_error)) {
    LOG(ERROR) << "X Record extension not available.";
    return;
  }

  x_record_range_[0] = XRecordAllocRange();
  x_record_range_[1] = XRecordAllocRange();
  if (!x_record_range_[0] || !x_record_range_[1]) {
    LOG(ERROR) << "XRecordAllocRange failed.";
    return;
  }
  x_record_range_[0]->device_events.first = MotionNotify;
  x_record_range_[0]->device_events.last = MotionNotify;
  x_record_range_[1]->device_events.first = KeyPress;
  x_record_range_[1]->device_events.last = KeyRelease;
  XRecordClientSpec client_spec = XRecordAllClients;

  x_record_context_ = XRecordCreateContext(
      x_record_display_, 0, &client_spec, 1, x_record_range_,
      arraysize(x_record_range_));
  if (!x_record_context_) {
    LOG(ERROR) << "XRecordCreateContext failed.";
    return;
  }

  if (!XRecordEnableContextAsync(x_record_display_, x_record_context_,
                                 &Core::ProcessReply,
                                 reinterpret_cast<XPointer>(this))) {
    LOG(ERROR) << "XRecordEnableContextAsync failed.";
    return;
  }

  // Register OnFileCanReadWithoutBlocking() to be called every time there is
  // something to read from |x_record_display_|.
  base::MessageLoopForIO* message_loop = base::MessageLoopForIO::current();
  int result =
      message_loop->WatchFileDescriptor(ConnectionNumber(x_record_display_),
                                        true,
                                        base::MessageLoopForIO::WATCH_READ,
                                        &controller_,
                                        this);
  if (!result) {
    LOG(ERROR) << "Failed to create X record task.";
    return;
  }

  // Fetch pending events if any.
  while (XPending(x_record_display_)) {
    XEvent ev;
    XNextEvent(x_record_display_, &ev);
  }
}

void LocalInputMonitorX11::Core::StopOnInputThread() {
  DCHECK(input_task_runner_->BelongsToCurrentThread());

  // Context must be disabled via the control channel because we can't send
  // any X protocol traffic over the data channel while it's recording.
  if (x_record_context_) {
    XRecordDisableContext(display_, x_record_context_);
    XFlush(display_);
  }

  controller_.StopWatchingFileDescriptor();

  if (x_record_range_[0]) {
    XFree(x_record_range_[0]);
    x_record_range_[0] = nullptr;
  }
  if (x_record_range_[1]) {
    XFree(x_record_range_[1]);
    x_record_range_[1] = nullptr;
  }
  if (x_record_context_) {
    XRecordFreeContext(x_record_display_, x_record_context_);
    x_record_context_ = 0;
  }
  if (x_record_display_) {
    XCloseDisplay(x_record_display_);
    x_record_display_ = nullptr;
  }
  if (display_) {
    XCloseDisplay(display_);
    display_ = nullptr;
  }
}

void LocalInputMonitorX11::Core::OnFileCanReadWithoutBlocking(int fd) {
  DCHECK(input_task_runner_->BelongsToCurrentThread());

  // Fetch pending events if any.
  while (XPending(x_record_display_)) {
    XEvent ev;
    XNextEvent(x_record_display_, &ev);
  }
}

void LocalInputMonitorX11::Core::OnFileCanWriteWithoutBlocking(int fd) {
  NOTREACHED();
}

void LocalInputMonitorX11::Core::ProcessXEvent(xEvent* event) {
  DCHECK(input_task_runner_->BelongsToCurrentThread());

  if (event->u.u.type == MotionNotify) {
    webrtc::DesktopVector position(event->u.keyButtonPointer.rootX,
                                   event->u.keyButtonPointer.rootY);
    caller_task_runner_->PostTask(
        FROM_HERE, base::Bind(&ClientSessionControl::OnLocalMouseMoved,
                              client_session_control_,
                              position));
  } else {
    int key_code = event->u.u.detail;
    bool down = event->u.u.type == KeyPress;
    KeySym key_sym = XkbKeycodeToKeysym(display_, key_code, 0, 0);
    if (key_sym == XK_Control_L || key_sym == XK_Control_R) {
      ctrl_pressed_ = down;
    } else if (key_sym == XK_Alt_L || key_sym == XK_Alt_R) {
      alt_pressed_ = down;
    } else if (key_sym == XK_Escape && down && alt_pressed_ && ctrl_pressed_) {
      caller_task_runner_->PostTask(
          FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession,
                                client_session_control_, protocol::OK));
    }
  }
}

// static
void LocalInputMonitorX11::Core::ProcessReply(XPointer self,
                                                XRecordInterceptData* data) {
  if (data->category == XRecordFromServer) {
    xEvent* event = reinterpret_cast<xEvent*>(data->data);
    reinterpret_cast<Core*>(self)->ProcessXEvent(event);
  }
  XRecordFreeData(data);
}

}  // namespace

scoped_ptr<LocalInputMonitor> LocalInputMonitor::Create(
    scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
    base::WeakPtr<ClientSessionControl> client_session_control) {
  return make_scoped_ptr(new LocalInputMonitorX11(
      caller_task_runner, input_task_runner, client_session_control));
}

}  // namespace remoting
