// 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 LocalInputMonitorLinux : public base::NonThreadSafe,
                               public LocalInputMonitor {
 public:
  LocalInputMonitorLinux(
      scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
      scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
      base::WeakPtr<ClientSessionControl> client_session_control);
  virtual ~LocalInputMonitorLinux();

 private:
  // The actual implementation resides in LocalInputMonitorLinux::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>;
    virtual ~Core();

    void StartOnInputThread();
    void StopOnInputThread();

    // base::MessagePumpLibevent::Watcher interface.
    virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
    virtual 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(LocalInputMonitorLinux);
};

LocalInputMonitorLinux::LocalInputMonitorLinux(
    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();
}

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

LocalInputMonitorLinux::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_(NULL),
      x_record_display_(NULL),
      x_record_context_(0) {
  DCHECK(caller_task_runner_->BelongsToCurrentThread());
  DCHECK(client_session_control_.get());

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

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

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

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

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

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

void LocalInputMonitorLinux::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(NULL);
  x_record_display_ = XOpenDisplay(NULL);
  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 LocalInputMonitorLinux::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] = NULL;
  }
  if (x_record_range_[1]) {
    XFree(x_record_range_[1]);
    x_record_range_[1] = NULL;
  }
  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_ = NULL;
  }
  if (display_) {
    XCloseDisplay(display_);
    display_ = NULL;
  }
}

void LocalInputMonitorLinux::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 LocalInputMonitorLinux::Core::OnFileCanWriteWithoutBlocking(int fd) {
  NOTREACHED();
}

void LocalInputMonitorLinux::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_));
    }
  }
}

// static
void LocalInputMonitorLinux::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 scoped_ptr<LocalInputMonitor>(
      new LocalInputMonitorLinux(caller_task_runner,
                                 input_task_runner,
                                 client_session_control));
}

}  // namespace remoting
