Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 // Implementation of a client that produces output in the form of RGBA | 5 // Implementation of a client that produces output in the form of RGBA |
| 6 // buffers when receiving pointer/touch events. RGB contains the lower | 6 // buffers when receiving pointer/touch events. RGB contains the lower |
| 7 // 24 bits of the event timestamp and A is 0xff. | 7 // 24 bits of the event timestamp and A is 0xff. |
| 8 | 8 |
| 9 #include <wayland-client-core.h> | 9 #include <wayland-client-core.h> |
| 10 #include <wayland-client-protocol.h> | 10 #include <wayland-client-protocol.h> |
| 11 | 11 |
| 12 #include <iostream> | |
| 12 #include <vector> | 13 #include <vector> |
| 13 | 14 |
| 15 #include "base/command_line.h" | |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/macros.h" | 17 #include "base/macros.h" |
| 16 #include "base/memory/shared_memory.h" | 18 #include "base/memory/shared_memory.h" |
| 19 #include "base/strings/string_number_conversions.h" | |
| 20 #include "base/time/time.h" | |
| 17 #include "third_party/skia/include/core/SkCanvas.h" | 21 #include "third_party/skia/include/core/SkCanvas.h" |
| 18 #include "third_party/skia/include/core/SkRefCnt.h" | 22 #include "third_party/skia/include/core/SkRefCnt.h" |
| 19 #include "third_party/skia/include/core/SkSurface.h" | 23 #include "third_party/skia/include/core/SkSurface.h" |
| 20 | 24 |
| 21 // Convenient macro that is used to define default deleters for wayland object | 25 // Convenient macro that is used to define default deleters for wayland object |
| 22 // types allowing them to be used with std::unique_ptr. | 26 // types allowing them to be used with std::unique_ptr. |
| 23 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ | 27 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ |
| 24 namespace std { \ | 28 namespace std { \ |
| 25 template <> \ | 29 template <> \ |
| 26 struct default_delete<TypeName> { \ | 30 struct default_delete<TypeName> { \ |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 40 DEFAULT_DELETER(wl_seat, wl_seat_destroy) | 44 DEFAULT_DELETER(wl_seat, wl_seat_destroy) |
| 41 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) | 45 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) |
| 42 DEFAULT_DELETER(wl_touch, wl_touch_destroy) | 46 DEFAULT_DELETER(wl_touch, wl_touch_destroy) |
| 43 DEFAULT_DELETER(wl_callback, wl_callback_destroy) | 47 DEFAULT_DELETER(wl_callback, wl_callback_destroy) |
| 44 | 48 |
| 45 namespace exo { | 49 namespace exo { |
| 46 namespace wayland { | 50 namespace wayland { |
| 47 namespace clients { | 51 namespace clients { |
| 48 namespace { | 52 namespace { |
| 49 | 53 |
| 50 // Window size. | |
| 51 const size_t kWidth = 256; | |
| 52 const size_t kHeight = 256; | |
| 53 | |
| 54 // Buffer format. | 54 // Buffer format. |
| 55 const int32_t kFormat = WL_SHM_FORMAT_ARGB8888; | 55 const int32_t kFormat = WL_SHM_FORMAT_ARGB8888; |
| 56 const SkColorType kColorType = kBGRA_8888_SkColorType; | 56 const SkColorType kColorType = kBGRA_8888_SkColorType; |
| 57 const size_t kBytesPerPixel = 4; | 57 const size_t kBytesPerPixel = 4; |
| 58 | 58 |
| 59 // Number of buffers. | 59 // Number of buffers. |
| 60 const size_t kBuffers = 2; | 60 const size_t kBuffers = 2; |
| 61 | 61 |
| 62 // Rotation speed (degrees/second). | 62 // Rotation speed (degrees/second). |
| 63 const double kRotationSpeed = 360.0; | 63 const double kRotationSpeed = 360.0; |
| 64 | 64 |
| 65 // Helper constants. | 65 // Benchmark interval in seconds. |
| 66 const size_t kStride = kWidth * kBytesPerPixel; | 66 const int kBenchmarkInterval = 5; |
| 67 const size_t kBufferSize = kHeight * kStride; | |
| 68 const size_t kMemorySize = kBufferSize * kBuffers; | |
| 69 | 67 |
| 70 struct Globals { | 68 struct Globals { |
| 71 std::unique_ptr<wl_compositor> compositor; | 69 std::unique_ptr<wl_compositor> compositor; |
| 72 std::unique_ptr<wl_shm> shm; | 70 std::unique_ptr<wl_shm> shm; |
| 73 std::unique_ptr<wl_shell> shell; | 71 std::unique_ptr<wl_shell> shell; |
| 74 std::unique_ptr<wl_seat> seat; | 72 std::unique_ptr<wl_seat> seat; |
| 75 }; | 73 }; |
| 76 | 74 |
| 77 void RegistryHandler(void* data, | 75 void RegistryHandler(void* data, |
| 78 wl_registry* registry, | 76 wl_registry* registry, |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 | 201 |
| 204 static uint32_t initial_time = time; | 202 static uint32_t initial_time = time; |
| 205 frame->time = time - initial_time; | 203 frame->time = time - initial_time; |
| 206 frame->callback_pending = false; | 204 frame->callback_pending = false; |
| 207 } | 205 } |
| 208 | 206 |
| 209 } // namespace | 207 } // namespace |
| 210 | 208 |
| 211 class MotionEvents { | 209 class MotionEvents { |
| 212 public: | 210 public: |
| 213 MotionEvents() {} | 211 MotionEvents(size_t width, |
| 212 size_t height, | |
| 213 int scale, | |
| 214 size_t rects, | |
|
Daniele Castagna
2016/11/05 21:49:20
nit: maybe rect_num?
reveman
2016/11/05 22:38:20
Done. "num_rects" now
| |
| 215 bool fullscreen) | |
| 216 : width_(width), | |
| 217 height_(height), | |
| 218 scale_(scale), | |
| 219 rects_(rects), | |
| 220 fullscreen_(fullscreen) {} | |
| 214 | 221 |
| 215 // Initialize and run client main loop. | 222 // Initialize and run client main loop. |
| 216 int Run(); | 223 int Run(); |
| 217 | 224 |
| 218 private: | 225 private: |
| 226 size_t stride() const { return width_ * kBytesPerPixel; } | |
| 227 size_t buffer_size() const { return stride() * height_; } | |
| 228 | |
| 229 const size_t width_; | |
| 230 const size_t height_; | |
| 231 const int scale_; | |
| 232 const size_t rects_; | |
|
Daniele Castagna
2016/11/05 21:49:19
rect_num_?
reveman
2016/11/05 22:38:19
Done.
| |
| 233 const bool fullscreen_; | |
| 234 | |
| 219 DISALLOW_COPY_AND_ASSIGN(MotionEvents); | 235 DISALLOW_COPY_AND_ASSIGN(MotionEvents); |
| 220 }; | 236 }; |
| 221 | 237 |
| 222 int MotionEvents::Run() { | 238 int MotionEvents::Run() { |
| 223 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); | 239 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); |
| 224 if (!display) { | 240 if (!display) { |
| 225 LOG(ERROR) << "wl_display_connect failed"; | 241 LOG(ERROR) << "wl_display_connect failed"; |
| 226 return 1; | 242 return 1; |
| 227 } | 243 } |
| 228 | 244 |
| 229 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; | 245 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; |
| 230 | 246 |
| 231 Globals globals; | 247 Globals globals; |
| 232 wl_registry* registry = wl_display_get_registry(display.get()); | 248 wl_registry* registry = wl_display_get_registry(display.get()); |
| 233 wl_registry_add_listener(registry, ®istry_listener, &globals); | 249 wl_registry_add_listener(registry, ®istry_listener, &globals); |
| 234 | 250 |
| 235 wl_display_dispatch(display.get()); | |
| 236 wl_display_roundtrip(display.get()); | 251 wl_display_roundtrip(display.get()); |
| 237 | 252 |
| 238 if (!globals.compositor) { | 253 if (!globals.compositor) { |
| 239 LOG(ERROR) << "Can't find compositor interface"; | 254 LOG(ERROR) << "Can't find compositor interface"; |
| 240 return 1; | 255 return 1; |
| 241 } | 256 } |
| 242 if (!globals.shm) { | 257 if (!globals.shm) { |
| 243 LOG(ERROR) << "Can't find shm interface"; | 258 LOG(ERROR) << "Can't find shm interface"; |
| 244 return 1; | 259 return 1; |
| 245 } | 260 } |
| 246 if (!globals.shell) { | 261 if (!globals.shell) { |
| 247 LOG(ERROR) << "Can't find shell interface"; | 262 LOG(ERROR) << "Can't find shell interface"; |
| 248 return 1; | 263 return 1; |
| 249 } | 264 } |
| 250 if (!globals.seat) { | 265 if (!globals.seat) { |
| 251 LOG(ERROR) << "Can't find seat interface"; | 266 LOG(ERROR) << "Can't find seat interface"; |
| 252 return 1; | 267 return 1; |
| 253 } | 268 } |
| 254 | 269 |
| 255 wl_buffer_listener buffer_listener = {BufferRelease}; | 270 wl_buffer_listener buffer_listener = {BufferRelease}; |
| 256 | 271 |
| 257 Buffer buffers[kBuffers]; | 272 Buffer buffers[kBuffers]; |
| 258 base::SharedMemory shared_memory; | 273 base::SharedMemory shared_memory; |
| 259 shared_memory.CreateAndMapAnonymous(kMemorySize); | 274 shared_memory.CreateAndMapAnonymous(buffer_size() * kBuffers); |
| 260 std::unique_ptr<wl_shm_pool> shm_pool( | 275 std::unique_ptr<wl_shm_pool> shm_pool( |
| 261 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, | 276 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, |
| 262 shared_memory.requested_size())); | 277 shared_memory.requested_size())); |
| 263 for (size_t i = 0; i < kBuffers; ++i) { | 278 for (size_t i = 0; i < kBuffers; ++i) { |
| 264 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( | 279 buffers[i].buffer.reset(static_cast<wl_buffer*>( |
| 265 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); | 280 wl_shm_pool_create_buffer(shm_pool.get(), i * buffer_size(), width_, |
| 281 height_, stride(), kFormat))); | |
| 266 if (!buffers[i].buffer) { | 282 if (!buffers[i].buffer) { |
| 267 LOG(ERROR) << "Can't create buffer"; | 283 LOG(ERROR) << "Can't create buffer"; |
| 268 return 1; | 284 return 1; |
| 269 } | 285 } |
| 270 buffers[i].sk_surface = SkSurface::MakeRasterDirect( | 286 buffers[i].sk_surface = SkSurface::MakeRasterDirect( |
| 271 SkImageInfo::Make(kWidth, kHeight, kColorType, kUnpremul_SkAlphaType), | 287 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType), |
| 272 static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i, | 288 static_cast<uint8_t*>(shared_memory.memory()) + buffer_size() * i, |
| 273 kStride); | 289 stride()); |
| 274 if (!buffers[i].sk_surface) { | 290 if (!buffers[i].sk_surface) { |
| 275 LOG(ERROR) << "Can't create SkSurface"; | 291 LOG(ERROR) << "Can't create SkSurface"; |
| 276 return 1; | 292 return 1; |
| 277 } | 293 } |
| 278 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, | 294 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, |
| 279 &buffers[i]); | 295 &buffers[i]); |
| 280 } | 296 } |
| 281 | 297 |
| 282 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( | 298 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( |
| 283 wl_compositor_create_surface(globals.compositor.get()))); | 299 wl_compositor_create_surface(globals.compositor.get()))); |
| 284 if (!surface) { | 300 if (!surface) { |
| 285 LOG(ERROR) << "Can't create surface"; | 301 LOG(ERROR) << "Can't create surface"; |
| 286 return 1; | 302 return 1; |
| 287 } | 303 } |
| 288 | 304 |
| 289 std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>( | 305 std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>( |
| 290 wl_compositor_create_region(globals.compositor.get()))); | 306 wl_compositor_create_region(globals.compositor.get()))); |
| 291 if (!opaque_region) { | 307 if (!opaque_region) { |
| 292 LOG(ERROR) << "Can't create region"; | 308 LOG(ERROR) << "Can't create region"; |
| 293 return 1; | 309 return 1; |
| 294 } | 310 } |
| 295 | 311 |
| 296 wl_region_add(opaque_region.get(), 0, 0, kWidth, kHeight); | 312 wl_region_add(opaque_region.get(), 0, 0, width_, height_); |
| 297 wl_surface_set_opaque_region(surface.get(), opaque_region.get()); | 313 wl_surface_set_opaque_region(surface.get(), opaque_region.get()); |
| 298 | 314 |
| 299 std::unique_ptr<wl_shell_surface> shell_surface( | 315 std::unique_ptr<wl_shell_surface> shell_surface( |
| 300 static_cast<wl_shell_surface*>( | 316 static_cast<wl_shell_surface*>( |
| 301 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); | 317 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); |
| 302 if (!shell_surface) { | 318 if (!shell_surface) { |
| 303 LOG(ERROR) << "Can't get shell surface"; | 319 LOG(ERROR) << "Can't get shell surface"; |
| 304 return 1; | 320 return 1; |
| 305 } | 321 } |
| 306 | 322 |
| 307 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); | 323 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); |
| 308 wl_shell_surface_set_toplevel(shell_surface.get()); | 324 if (fullscreen_) { |
| 325 wl_shell_surface_set_fullscreen(shell_surface.get(), | |
| 326 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, | |
| 327 0, nullptr); | |
| 328 } else { | |
| 329 wl_shell_surface_set_toplevel(shell_surface.get()); | |
| 330 } | |
| 309 | 331 |
| 310 EventTimeStack event_times; | 332 EventTimeStack event_times; |
| 311 | 333 |
| 312 std::unique_ptr<wl_pointer> pointer( | 334 std::unique_ptr<wl_pointer> pointer( |
| 313 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); | 335 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); |
| 314 if (!pointer) { | 336 if (!pointer) { |
| 315 LOG(ERROR) << "Can't get pointer"; | 337 LOG(ERROR) << "Can't get pointer"; |
| 316 return 1; | 338 return 1; |
| 317 } | 339 } |
| 318 | 340 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 330 } | 352 } |
| 331 | 353 |
| 332 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, | 354 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, |
| 333 TouchFrame, TouchCancel}; | 355 TouchFrame, TouchCancel}; |
| 334 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); | 356 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); |
| 335 | 357 |
| 336 Frame frame; | 358 Frame frame; |
| 337 std::unique_ptr<wl_callback> frame_callback; | 359 std::unique_ptr<wl_callback> frame_callback; |
| 338 wl_callback_listener frame_listener = {FrameCallback}; | 360 wl_callback_listener frame_listener = {FrameCallback}; |
| 339 | 361 |
| 362 uint32_t frames = 0; | |
| 363 base::TimeTicks benchmark_time = base::TimeTicks::Now(); | |
| 364 base::TimeDelta benchmark_interval = | |
| 365 base::TimeDelta::FromSeconds(kBenchmarkInterval); | |
| 366 | |
| 340 do { | 367 do { |
| 341 if (frame.callback_pending) | 368 if (frame.callback_pending) |
| 342 continue; | 369 continue; |
| 343 | 370 |
| 344 Buffer* buffer = | 371 Buffer* buffer = |
| 345 std::find_if(std::begin(buffers), std::end(buffers), | 372 std::find_if(std::begin(buffers), std::end(buffers), |
| 346 [](const Buffer& buffer) { return !buffer.busy; }); | 373 [](const Buffer& buffer) { return !buffer.busy; }); |
| 347 if (buffer == std::end(buffers)) | 374 if (buffer == std::end(buffers)) |
| 348 continue; | 375 continue; |
| 349 | 376 |
| 377 base::TimeTicks current_time = base::TimeTicks::Now(); | |
| 378 if ((current_time - benchmark_time) > benchmark_interval) { | |
| 379 std::cout << frames << " frames in " << benchmark_interval.InSeconds() | |
|
Daniele Castagna
2016/11/05 21:49:19
Couldn't we just print this info to the canvas its
reveman
2016/11/05 22:38:20
Yes, lets add a --fps-counter flag for that in a f
| |
| 380 << " seconds: " | |
| 381 << static_cast<double>(frames) / benchmark_interval.InSeconds() | |
| 382 << " fps" << std::endl; | |
| 383 benchmark_time = current_time; | |
| 384 frames = 0; | |
| 385 } | |
| 386 | |
| 350 SkCanvas* canvas = buffer->sk_surface->getCanvas(); | 387 SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| 351 canvas->save(); | 388 canvas->save(); |
| 352 | 389 |
| 353 // Clear background to black. | 390 if (event_times.empty()) { |
| 354 canvas->clear(SK_ColorBLACK); | 391 canvas->clear(SK_ColorBLACK); |
| 355 | 392 } else { |
| 356 // Split buffer into one horizontal rectangle for each event received since | 393 // Split buffer into one horizontal rectangle for each event received |
| 357 // last frame. Latest event at the top. | 394 // since last frame. Latest event at the top. |
| 358 if (!event_times.empty()) { | 395 int y = 0; |
| 359 double y = 0; | 396 int h = (height_ + (event_times.size() / 2)) / event_times.size(); |
|
Daniele Castagna
2016/11/05 21:49:19
Is the + event_time.size/2 to make sure it'll cove
reveman
2016/11/05 22:38:20
Yes, added a comment to make that clear in latest
| |
| 360 double height = static_cast<double>(kHeight) / event_times.size(); | |
| 361 while (!event_times.empty()) { | 397 while (!event_times.empty()) { |
| 362 SkRect rect = SkRect::MakeXYWH(0, y, kWidth, height); | 398 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); |
| 363 SkPaint paint; | 399 SkPaint paint; |
| 364 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, | 400 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, |
| 365 (event_times.back() & 0x00ff00) >> 8, | 401 (event_times.back() & 0x00ff00) >> 8, |
| 366 (event_times.back() & 0xff0000) >> 16)); | 402 (event_times.back() & 0xff0000) >> 16)); |
| 367 canvas->drawRect(rect, paint); | 403 canvas->drawIRect(rect, paint); |
| 368 event_times.pop_back(); | 404 event_times.pop_back(); |
| 369 y += height; | 405 y += h; |
| 370 } | 406 } |
| 371 } | 407 } |
| 372 | 408 |
| 373 // Draw a blue rotating rectangle on top. | 409 // Draw rotating rects. |
| 374 canvas->translate(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)); | 410 SkScalar half_width = SkScalarHalf(width_); |
| 375 canvas->rotate(SkDoubleToScalar((frame.time / 1000.0f) * kRotationSpeed)); | 411 SkScalar half_height = SkScalarHalf(height_); |
| 376 SkRect rect = SkRect::MakeXYWH(-(kWidth / 4.0f), -(kHeight / 4.0f), | 412 SkIRect rect = |
| 377 kWidth / 2.0f, kHeight / 2.0f); | 413 SkIRect::MakeXYWH(-SkScalarHalf(half_width), -SkScalarHalf(half_height), |
| 414 half_width, half_height); | |
| 415 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000); | |
| 378 SkPaint paint; | 416 SkPaint paint; |
| 379 paint.setColor(SK_ColorBLUE); | 417 canvas->translate(half_width, half_height); |
| 380 canvas->drawRect(rect, paint); | 418 for (size_t i = 0; i < rects_; ++i) { |
| 381 | 419 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, |
| 420 SK_ColorRED, SK_ColorYELLOW, | |
| 421 SK_ColorCYAN, SK_ColorMAGENTA}; | |
| 422 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); | |
| 423 canvas->rotate(rotation / rects_); | |
| 424 canvas->drawIRect(rect, paint); | |
| 425 } | |
| 382 canvas->restore(); | 426 canvas->restore(); |
| 383 | 427 |
| 428 wl_surface_set_buffer_scale(surface.get(), scale_); | |
| 384 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); | 429 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); |
| 385 buffer->busy = true; | 430 buffer->busy = true; |
| 386 | 431 |
| 387 frame_callback.reset(wl_surface_frame(surface.get())); | 432 frame_callback.reset(wl_surface_frame(surface.get())); |
| 388 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); | 433 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); |
| 389 frame.callback_pending = true; | 434 frame.callback_pending = true; |
| 390 | 435 |
| 436 ++frames; | |
| 437 | |
| 391 wl_surface_commit(surface.get()); | 438 wl_surface_commit(surface.get()); |
| 392 wl_display_flush(display.get()); | |
| 393 } while (wl_display_dispatch(display.get()) != -1); | 439 } while (wl_display_dispatch(display.get()) != -1); |
| 394 | 440 |
| 395 return 0; | 441 return 0; |
| 396 } | 442 } |
| 397 | 443 |
| 398 } // namespace clients | 444 } // namespace clients |
| 399 } // namespace wayland | 445 } // namespace wayland |
| 400 } // namespace exo | 446 } // namespace exo |
| 401 | 447 |
| 402 int main() { | 448 namespace switches { |
| 403 return exo::wayland::clients::MotionEvents().Run(); | 449 |
| 450 // Specifies the client buffer size. | |
| 451 const char kSize[] = "size"; | |
| 452 | |
| 453 // Specifies the client scale factor. | |
|
Daniele Castagna
2016/11/05 21:49:20
You might want to expand a little on that. If I we
reveman
2016/11/05 22:38:20
Done.
| |
| 454 const char kScale[] = "scale"; | |
| 455 | |
| 456 // Specifies the number of rotating rects to draw. | |
| 457 const char kRects[] = "rects"; | |
| 458 | |
| 459 // Specifies if client should be fullscreen. | |
| 460 const char kFullscreen[] = "fullscreen"; | |
| 461 | |
| 462 } // namespace switches | |
| 463 | |
| 464 int main(int argc, char* argv[]) { | |
| 465 base::CommandLine command_line(argc, argv); | |
| 466 | |
| 467 int width = 256; | |
| 468 int height = 256; | |
| 469 if (command_line.HasSwitch(switches::kSize)) { | |
| 470 std::string size_str = command_line.GetSwitchValueASCII(switches::kSize); | |
| 471 if (sscanf(size_str.c_str(), "%dx%d", &width, &height) != 2) { | |
| 472 LOG(ERROR) << "Invalid value for " << switches::kSize; | |
| 473 return 1; | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 int scale = 1; | |
| 478 if (command_line.HasSwitch(switches::kScale) && | |
| 479 !base::StringToInt(command_line.GetSwitchValueASCII(switches::kScale), | |
| 480 &scale)) { | |
| 481 LOG(ERROR) << "Invalid value for " << switches::kScale; | |
| 482 return 1; | |
| 483 } | |
| 484 | |
| 485 size_t rects = 1; | |
| 486 if (command_line.HasSwitch(switches::kRects) && | |
| 487 !base::StringToSizeT(command_line.GetSwitchValueASCII(switches::kRects), | |
| 488 &rects)) { | |
| 489 LOG(ERROR) << "Invalid value for " << switches::kRects; | |
| 490 return 1; | |
| 491 } | |
| 492 | |
| 493 bool fullscreen = command_line.HasSwitch(switches::kFullscreen); | |
| 494 | |
| 495 exo::wayland::clients::MotionEvents client(width, height, scale, rects, | |
| 496 fullscreen); | |
| 497 return client.Run(); | |
| 404 } | 498 } |
| OLD | NEW |