| Index: remoting/client/x11_client.cc
|
| ===================================================================
|
| --- remoting/client/x11_client.cc (revision 52921)
|
| +++ remoting/client/x11_client.cc (working copy)
|
| @@ -2,259 +2,46 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
| //
|
| -// This file implements a X11 chromoting client.
|
| +// This file implements a simple X11 chromoting client.
|
|
|
| #include <iostream>
|
|
|
| #include "base/at_exit.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/stl_util-inl.h"
|
| -#include "base/task.h"
|
| -#include "base/waitable_event.h"
|
| +#include "remoting/client/chromoting_client.h"
|
| +#include "remoting/client/client_config.h"
|
| #include "remoting/client/client_util.h"
|
| -#include "remoting/client/host_connection.h"
|
| #include "remoting/client/jingle_host_connection.h"
|
| -#include "remoting/jingle_glue/jingle_thread.h"
|
| -
|
| -// Include Xlib at the end because it clashes with ClientMessage defined in
|
| -// the protocol buffer.
|
| -// x11_view.h also includes Xlib.h so put it behind all other headers but
|
| -// before Xlib.h
|
| #include "remoting/client/x11_view.h"
|
| -#include <X11/Xlib.h>
|
| +#include "remoting/client/x11_input_handler.h"
|
|
|
| -using remoting::JingleHostConnection;
|
| -using remoting::JingleThread;
|
| +void ClientQuit(MessageLoop* loop) {
|
| + loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
|
| +}
|
|
|
| -namespace remoting {
|
| -
|
| -class X11Client : public HostConnection::HostEventCallback {
|
| - public:
|
| - X11Client(MessageLoop* loop, base::WaitableEvent* client_done)
|
| - : message_loop_(loop),
|
| - client_done_(client_done),
|
| - display_(NULL),
|
| - window_(0),
|
| - width_(0),
|
| - height_(0) {
|
| - }
|
| -
|
| - virtual ~X11Client() {
|
| - DCHECK(!display_);
|
| - DCHECK(!window_);
|
| - }
|
| -
|
| - ////////////////////////////////////////////////////////////////////////////
|
| - // HostConnection::EventHandler implementations.
|
| - virtual void HandleMessages(HostConnection* conn,
|
| - remoting::HostMessageList* messages) {
|
| - for (size_t i = 0; i < messages->size(); ++i) {
|
| - HostMessage* msg = (*messages)[i];
|
| - if (msg->has_init_client()) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE, NewRunnableMethod(this, &X11Client::DoInitClient, msg));
|
| - } else if (msg->has_begin_update_stream()) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &X11Client::DoBeginUpdate, msg));
|
| - } else if (msg->has_update_stream_packet()) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &X11Client::DoHandleUpdate, msg));
|
| - } else if (msg->has_end_update_stream()) {
|
| - message_loop_->PostTask(
|
| - FROM_HERE, NewRunnableMethod(this, &X11Client::DoEndUpdate, msg));
|
| - } else {
|
| - NOTREACHED() << "Unknown message received";
|
| - }
|
| - }
|
| - // Assume we have processed all the messages.
|
| - messages->clear();
|
| - }
|
| -
|
| - virtual void OnConnectionOpened(HostConnection* conn) {
|
| - std::cout << "Connection established." << std::endl;
|
| - }
|
| -
|
| - virtual void OnConnectionClosed(HostConnection* conn) {
|
| - std::cout << "Connection closed." << std::endl;
|
| - client_done_->Signal();
|
| - }
|
| -
|
| - virtual void OnConnectionFailed(HostConnection* conn) {
|
| - std::cout << "Conection failed." << std::endl;
|
| - client_done_->Signal();
|
| - }
|
| -
|
| - void InitX11() {
|
| - message_loop_->PostTask(FROM_HERE,
|
| - NewRunnableMethod(this, &X11Client::DoInitX11));
|
| - }
|
| -
|
| - void DoInitX11() {
|
| - display_ = XOpenDisplay(NULL);
|
| - if (!display_) {
|
| - std::cout << "Error - cannot open display" << std::endl;
|
| - client_done_->Signal();
|
| - return;
|
| - }
|
| -
|
| - // Get properties of the screen.
|
| - int screen = DefaultScreen(display_);
|
| - int root_window = RootWindow(display_, screen);
|
| -
|
| - // Creates the window.
|
| - window_ = XCreateSimpleWindow(display_, root_window, 1, 1, 640, 480, 0,
|
| - BlackPixel(display_, screen),
|
| - BlackPixel(display_, screen));
|
| - DCHECK(window_);
|
| - XStoreName(display_, window_, "X11 Remoting");
|
| -
|
| - // Specifies what kind of messages we want to receive.
|
| - XSelectInput(display_, window_, ExposureMask | ButtonPressMask);
|
| - XMapWindow(display_, window_);
|
| - }
|
| -
|
| - void DestroyX11() {
|
| - message_loop_->PostTask(FROM_HERE,
|
| - NewRunnableMethod(this, &X11Client::DoDestroyX11));
|
| - }
|
| -
|
| - void DoDestroyX11() {
|
| - if (display_ && window_) {
|
| - // Shutdown the window system.
|
| - XDestroyWindow(display_, window_);
|
| - XCloseDisplay(display_);
|
| - display_ = NULL;
|
| - window_ = 0;
|
| - }
|
| - }
|
| -
|
| - private:
|
| - // This method is executed on the main loop.
|
| - void DoInitClient(HostMessage* msg) {
|
| - DCHECK_EQ(message_loop_, MessageLoop::current());
|
| - DCHECK(msg->has_init_client());
|
| - scoped_ptr<HostMessage> deleter(msg);
|
| -
|
| - // Saves the dimension and resize the window.
|
| - width_ = msg->init_client().width();
|
| - height_ = msg->init_client().height();
|
| - LOG(INFO) << "Init client received: " << width_ << "x" << height_;
|
| - XResizeWindow(display_, window_, width_, height_);
|
| -
|
| - // Now construct the X11View that renders the remote desktop.
|
| - view_.reset(new X11View(display_, window_, width_, height_));
|
| -
|
| - // Schedule the event handler to process the event queue of X11.
|
| - ScheduleX11EventHandler();
|
| - }
|
| -
|
| - // The following methods are executed on the same thread as libjingle.
|
| - void DoBeginUpdate(HostMessage* msg) {
|
| - DCHECK_EQ(message_loop_, MessageLoop::current());
|
| - DCHECK(msg->has_begin_update_stream());
|
| -
|
| - view_->HandleBeginUpdateStream(msg);
|
| - }
|
| -
|
| - void DoHandleUpdate(HostMessage* msg) {
|
| - DCHECK_EQ(message_loop_, MessageLoop::current());
|
| - DCHECK(msg->has_update_stream_packet());
|
| -
|
| - view_->HandleUpdateStreamPacket(msg);
|
| - }
|
| -
|
| - void DoEndUpdate(HostMessage* msg) {
|
| - DCHECK_EQ(message_loop_, MessageLoop::current());
|
| - DCHECK(msg->has_end_update_stream());
|
| -
|
| - view_->HandleEndUpdateStream(msg);
|
| - }
|
| -
|
| - void DoProcessX11Events() {
|
| - DCHECK_EQ(message_loop_, MessageLoop::current());
|
| - if (XPending(display_)) {
|
| - XEvent e;
|
| - XNextEvent(display_, &e);
|
| - if (e.type == Expose) {
|
| - // Tell the ChromotingView to paint again.
|
| - view_->Paint();
|
| - } else if (e.type == ButtonPress) {
|
| - // TODO(hclam): Implement.
|
| - NOTIMPLEMENTED();
|
| - } else {
|
| - // TODO(hclam): Implement.
|
| - NOTIMPLEMENTED();
|
| - }
|
| - }
|
| -
|
| - // Schedule the next event handler.
|
| - ScheduleX11EventHandler();
|
| - }
|
| -
|
| - void ScheduleX11EventHandler() {
|
| - // Schedule a delayed task to process X11 events in 10ms.
|
| - static const int kProcessEventsInterval = 10;
|
| - message_loop_->PostDelayedTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &X11Client::DoProcessX11Events),
|
| - kProcessEventsInterval);
|
| - }
|
| -
|
| - MessageLoop* message_loop_;
|
| - base::WaitableEvent* client_done_;
|
| -
|
| - // Members used for display.
|
| - Display* display_;
|
| - Window window_;
|
| -
|
| - // Dimension of the window. They are initialized when InitClient message is
|
| - // received.
|
| - int width_;
|
| - int height_;
|
| -
|
| - scoped_ptr<ChromotingView> view_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(X11Client);
|
| -};
|
| -
|
| -} // namespace remoting
|
| -
|
| -DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::X11Client);
|
| -
|
| int main(int argc, char** argv) {
|
| base::AtExitManager at_exit;
|
| - std::string host_jid;
|
| - std::string username;
|
| - std::string auth_token;
|
|
|
| - if (!remoting::GetLoginInfo(argc, argv, &host_jid, &username, &auth_token)) {
|
| - std::cout << "Cannot obtain login info" << std::endl;
|
| + remoting::ClientConfig config;
|
| + if (!remoting::GetLoginInfoFromArgs(argc, argv, &config)) {
|
| + std::cout << "Unable to obtain login info" << std::endl;
|
| return 1;
|
| }
|
|
|
| - JingleThread network_thread;
|
| - network_thread.Start();
|
| + MessageLoop ui_loop;
|
| + remoting::ClientContext context;
|
| + remoting::JingleHostConnection connection(&context);
|
| + remoting::X11View view;
|
| + remoting::X11InputHandler input_handler(&context, &view);
|
| + remoting::ChromotingClient client(&config, &context, &connection, &view,
|
| + &input_handler, NewRunnableFunction(&ClientQuit, &ui_loop));
|
|
|
| - base::WaitableEvent client_done(false, false);
|
| - remoting::X11Client client(network_thread.message_loop(), &client_done);
|
| - JingleHostConnection connection(&network_thread);
|
| - connection.Connect(username, auth_token, host_jid, &client);
|
| + // Run the client on a new MessageLoop until
|
| + context.Start();
|
| + client.Start();
|
| + ui_loop.Run();
|
|
|
| - client.InitX11();
|
| + client.Stop();
|
| + context.Stop();
|
|
|
| - // Wait until the main loop is done.
|
| - client_done.Wait();
|
| -
|
| - connection.Disconnect();
|
| -
|
| - client.DestroyX11();
|
| -
|
| - // Quit the current message loop.
|
| - network_thread.message_loop()->PostTask(FROM_HERE,
|
| - new MessageLoop::QuitTask());
|
| - network_thread.Stop();
|
| -
|
| return 0;
|
| }
|
|
|