Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(690)

Side by Side Diff: remoting/client/x11_client.cc

Issue 2861047: Refactor the client code. Move all x11-related code into X11View and create... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file implements a X11 chromoting client. 5 // This file implements a simple X11 chromoting client.
6 6
7 #include <iostream> 7 #include <iostream>
8 8
9 #include "base/at_exit.h" 9 #include "base/at_exit.h"
10 #include "base/message_loop.h" 10 #include "remoting/client/chromoting_client.h"
11 #include "base/stl_util-inl.h" 11 #include "remoting/client/client_config.h"
12 #include "base/task.h"
13 #include "base/waitable_event.h"
14 #include "remoting/client/client_util.h" 12 #include "remoting/client/client_util.h"
15 #include "remoting/client/host_connection.h"
16 #include "remoting/client/jingle_host_connection.h" 13 #include "remoting/client/jingle_host_connection.h"
17 #include "remoting/jingle_glue/jingle_thread.h" 14 #include "remoting/client/x11_view.h"
15 #include "remoting/client/x11_input_handler.h"
18 16
19 // Include Xlib at the end because it clashes with ClientMessage defined in 17 void ClientQuit(MessageLoop* loop) {
20 // the protocol buffer. 18 loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
21 // x11_view.h also includes Xlib.h so put it behind all other headers but 19 }
22 // before Xlib.h
23 #include "remoting/client/x11_view.h"
24 #include <X11/Xlib.h>
25
26 using remoting::JingleHostConnection;
27 using remoting::JingleThread;
28
29 namespace remoting {
30
31 class X11Client : public HostConnection::HostEventCallback {
32 public:
33 X11Client(MessageLoop* loop, base::WaitableEvent* client_done)
34 : message_loop_(loop),
35 client_done_(client_done),
36 display_(NULL),
37 window_(0),
38 width_(0),
39 height_(0) {
40 }
41
42 virtual ~X11Client() {
43 DCHECK(!display_);
44 DCHECK(!window_);
45 }
46
47 ////////////////////////////////////////////////////////////////////////////
48 // HostConnection::EventHandler implementations.
49 virtual void HandleMessages(HostConnection* conn,
50 remoting::HostMessageList* messages) {
51 for (size_t i = 0; i < messages->size(); ++i) {
52 HostMessage* msg = (*messages)[i];
53 if (msg->has_init_client()) {
54 message_loop_->PostTask(
55 FROM_HERE, NewRunnableMethod(this, &X11Client::DoInitClient, msg));
56 } else if (msg->has_begin_update_stream()) {
57 message_loop_->PostTask(
58 FROM_HERE,
59 NewRunnableMethod(this, &X11Client::DoBeginUpdate, msg));
60 } else if (msg->has_update_stream_packet()) {
61 message_loop_->PostTask(
62 FROM_HERE,
63 NewRunnableMethod(this, &X11Client::DoHandleUpdate, msg));
64 } else if (msg->has_end_update_stream()) {
65 message_loop_->PostTask(
66 FROM_HERE, NewRunnableMethod(this, &X11Client::DoEndUpdate, msg));
67 } else {
68 NOTREACHED() << "Unknown message received";
69 }
70 }
71 // Assume we have processed all the messages.
72 messages->clear();
73 }
74
75 virtual void OnConnectionOpened(HostConnection* conn) {
76 std::cout << "Connection established." << std::endl;
77 }
78
79 virtual void OnConnectionClosed(HostConnection* conn) {
80 std::cout << "Connection closed." << std::endl;
81 client_done_->Signal();
82 }
83
84 virtual void OnConnectionFailed(HostConnection* conn) {
85 std::cout << "Conection failed." << std::endl;
86 client_done_->Signal();
87 }
88
89 void InitX11() {
90 message_loop_->PostTask(FROM_HERE,
91 NewRunnableMethod(this, &X11Client::DoInitX11));
92 }
93
94 void DoInitX11() {
95 display_ = XOpenDisplay(NULL);
96 if (!display_) {
97 std::cout << "Error - cannot open display" << std::endl;
98 client_done_->Signal();
99 return;
100 }
101
102 // Get properties of the screen.
103 int screen = DefaultScreen(display_);
104 int root_window = RootWindow(display_, screen);
105
106 // Creates the window.
107 window_ = XCreateSimpleWindow(display_, root_window, 1, 1, 640, 480, 0,
108 BlackPixel(display_, screen),
109 BlackPixel(display_, screen));
110 DCHECK(window_);
111 XStoreName(display_, window_, "X11 Remoting");
112
113 // Specifies what kind of messages we want to receive.
114 XSelectInput(display_, window_, ExposureMask | ButtonPressMask);
115 XMapWindow(display_, window_);
116 }
117
118 void DestroyX11() {
119 message_loop_->PostTask(FROM_HERE,
120 NewRunnableMethod(this, &X11Client::DoDestroyX11));
121 }
122
123 void DoDestroyX11() {
124 if (display_ && window_) {
125 // Shutdown the window system.
126 XDestroyWindow(display_, window_);
127 XCloseDisplay(display_);
128 display_ = NULL;
129 window_ = 0;
130 }
131 }
132
133 private:
134 // This method is executed on the main loop.
135 void DoInitClient(HostMessage* msg) {
136 DCHECK_EQ(message_loop_, MessageLoop::current());
137 DCHECK(msg->has_init_client());
138 scoped_ptr<HostMessage> deleter(msg);
139
140 // Saves the dimension and resize the window.
141 width_ = msg->init_client().width();
142 height_ = msg->init_client().height();
143 LOG(INFO) << "Init client received: " << width_ << "x" << height_;
144 XResizeWindow(display_, window_, width_, height_);
145
146 // Now construct the X11View that renders the remote desktop.
147 view_.reset(new X11View(display_, window_, width_, height_));
148
149 // Schedule the event handler to process the event queue of X11.
150 ScheduleX11EventHandler();
151 }
152
153 // The following methods are executed on the same thread as libjingle.
154 void DoBeginUpdate(HostMessage* msg) {
155 DCHECK_EQ(message_loop_, MessageLoop::current());
156 DCHECK(msg->has_begin_update_stream());
157
158 view_->HandleBeginUpdateStream(msg);
159 }
160
161 void DoHandleUpdate(HostMessage* msg) {
162 DCHECK_EQ(message_loop_, MessageLoop::current());
163 DCHECK(msg->has_update_stream_packet());
164
165 view_->HandleUpdateStreamPacket(msg);
166 }
167
168 void DoEndUpdate(HostMessage* msg) {
169 DCHECK_EQ(message_loop_, MessageLoop::current());
170 DCHECK(msg->has_end_update_stream());
171
172 view_->HandleEndUpdateStream(msg);
173 }
174
175 void DoProcessX11Events() {
176 DCHECK_EQ(message_loop_, MessageLoop::current());
177 if (XPending(display_)) {
178 XEvent e;
179 XNextEvent(display_, &e);
180 if (e.type == Expose) {
181 // Tell the ChromotingView to paint again.
182 view_->Paint();
183 } else if (e.type == ButtonPress) {
184 // TODO(hclam): Implement.
185 NOTIMPLEMENTED();
186 } else {
187 // TODO(hclam): Implement.
188 NOTIMPLEMENTED();
189 }
190 }
191
192 // Schedule the next event handler.
193 ScheduleX11EventHandler();
194 }
195
196 void ScheduleX11EventHandler() {
197 // Schedule a delayed task to process X11 events in 10ms.
198 static const int kProcessEventsInterval = 10;
199 message_loop_->PostDelayedTask(
200 FROM_HERE,
201 NewRunnableMethod(this, &X11Client::DoProcessX11Events),
202 kProcessEventsInterval);
203 }
204
205 MessageLoop* message_loop_;
206 base::WaitableEvent* client_done_;
207
208 // Members used for display.
209 Display* display_;
210 Window window_;
211
212 // Dimension of the window. They are initialized when InitClient message is
213 // received.
214 int width_;
215 int height_;
216
217 scoped_ptr<ChromotingView> view_;
218
219 DISALLOW_COPY_AND_ASSIGN(X11Client);
220 };
221
222 } // namespace remoting
223
224 DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::X11Client);
225 20
226 int main(int argc, char** argv) { 21 int main(int argc, char** argv) {
227 base::AtExitManager at_exit; 22 base::AtExitManager at_exit;
228 std::string host_jid;
229 std::string username;
230 std::string auth_token;
231 23
232 if (!remoting::GetLoginInfo(argc, argv, &host_jid, &username, &auth_token)) { 24 remoting::ClientConfig config;
233 std::cout << "Cannot obtain login info" << std::endl; 25 if (!remoting::GetLoginInfoFromArgs(argc, argv, &config)) {
26 std::cout << "Unable to obtain login info" << std::endl;
234 return 1; 27 return 1;
235 } 28 }
236 29
237 JingleThread network_thread; 30 MessageLoop ui_loop;
238 network_thread.Start(); 31 remoting::ClientContext context;
32 remoting::JingleHostConnection connection(&context);
33 remoting::X11View view;
34 remoting::X11InputHandler input_handler(&context, &view);
35 remoting::ChromotingClient client(&config, &context, &connection, &view,
36 &input_handler, NewRunnableFunction(&ClientQuit, &ui_loop));
239 37
240 base::WaitableEvent client_done(false, false); 38 // Run the client on a new MessageLoop until
241 remoting::X11Client client(network_thread.message_loop(), &client_done); 39 context.Start();
242 JingleHostConnection connection(&network_thread); 40 client.Start();
243 connection.Connect(username, auth_token, host_jid, &client); 41 ui_loop.Run();
244 42
245 client.InitX11(); 43 client.Stop();
246 44 context.Stop();
247 // Wait until the main loop is done.
248 client_done.Wait();
249
250 connection.Disconnect();
251
252 client.DestroyX11();
253
254 // Quit the current message loop.
255 network_thread.message_loop()->PostTask(FROM_HERE,
256 new MessageLoop::QuitTask());
257 network_thread.Stop();
258 45
259 return 0; 46 return 0;
260 } 47 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698