| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <errno.h> | |
| 6 #include <fcntl.h> | |
| 7 #include <pthread.h> | |
| 8 #include <stdio.h> | |
| 9 #include <stdlib.h> | |
| 10 #include <sys/ioctl.h> | |
| 11 #include <sys/types.h> | |
| 12 #include <sys/stat.h> | |
| 13 #include <termios.h> | |
| 14 | |
| 15 #include <algorithm> | |
| 16 #include <cstdlib> | |
| 17 #include <cstring> | |
| 18 #include <sstream> | |
| 19 #include <string> | |
| 20 #include <vector> | |
| 21 | |
| 22 #include "nacl_io/ioctl.h" | |
| 23 #include "nacl_io/kernel_wrap.h" | |
| 24 #include "nacl_io/log.h" | |
| 25 #include "nacl_io/nacl_io.h" | |
| 26 | |
| 27 #include "ppapi/c/ppb_var.h" | |
| 28 | |
| 29 #include "ppapi/cpp/input_event.h" | |
| 30 #include "ppapi/cpp/message_loop.h" | |
| 31 #include "ppapi/cpp/module.h" | |
| 32 #include "ppapi/cpp/rect.h" | |
| 33 #include "ppapi/cpp/size.h" | |
| 34 #include "ppapi/cpp/touch_point.h" | |
| 35 #include "ppapi/cpp/var.h" | |
| 36 #include "ppapi/cpp/var_array.h" | |
| 37 #include "ppapi/cpp/var_dictionary.h" | |
| 38 | |
| 39 #include "ppapi_simple/ps_event.h" | |
| 40 #include "ppapi_simple/ps_instance.h" | |
| 41 #include "ppapi_simple/ps_interface.h" | |
| 42 #include "ppapi_simple/ps_main.h" | |
| 43 | |
| 44 #if defined(WIN32) | |
| 45 #define open _open | |
| 46 #define dup2 _dup2 | |
| 47 #endif | |
| 48 | |
| 49 static PSInstance* s_InstanceObject = NULL; | |
| 50 | |
| 51 PSInstance* PSInstance::GetInstance() { | |
| 52 return s_InstanceObject; | |
| 53 } | |
| 54 | |
| 55 struct StartInfo { | |
| 56 PSInstance* inst_; | |
| 57 uint32_t argc_; | |
| 58 char** argv_; | |
| 59 }; | |
| 60 | |
| 61 | |
| 62 // The starting point for 'main'. We create this thread to hide the real | |
| 63 // main pepper thread which must never be blocked. | |
| 64 void* PSInstance::MainThreadThunk(void *info) { | |
| 65 s_InstanceObject->Trace("Got MainThreadThunk.\n"); | |
| 66 StartInfo* si = static_cast<StartInfo*>(info); | |
| 67 PSInstance* instance = si->inst_; | |
| 68 instance->main_loop_ = new pp::MessageLoop(si->inst_); | |
| 69 instance->main_loop_->AttachToCurrentThread(); | |
| 70 | |
| 71 int ret = instance->MainThread(si->argc_, si->argv_); | |
| 72 | |
| 73 // Clean up StartInfo. | |
| 74 for (uint32_t i = 0; i < si->argc_; i++) { | |
| 75 delete[] si->argv_[i]; | |
| 76 } | |
| 77 delete[] si->argv_; | |
| 78 delete si; | |
| 79 | |
| 80 // Exit the entire process once the 'main' thread returns. | |
| 81 // The error code will be available to javascript via | |
| 82 // the exitcode parameter of the crash event. | |
| 83 #ifdef __native_client__ | |
| 84 exit(ret); | |
| 85 #else | |
| 86 instance->ExitHandshake(ret); | |
| 87 #endif | |
| 88 return NULL; | |
| 89 } | |
| 90 | |
| 91 void PSInstance::ExitHandshake(int status) { | |
| 92 if (exit_message_ == NULL) | |
| 93 return; | |
| 94 | |
| 95 RegisterMessageHandler(exit_message_, MessageHandlerExitStatic, this); | |
| 96 | |
| 97 // Send the exit message to JavaScript. Then wait | |
| 98 // for the reply/confirmation. | |
| 99 std::stringstream ss; | |
| 100 ss << exit_message_ << ":" << status; | |
| 101 | |
| 102 pthread_mutex_lock(&exit_lock_); | |
| 103 PostMessage(ss.str()); | |
| 104 pthread_cond_wait(&exit_cond_, &exit_lock_); | |
| 105 pthread_mutex_unlock(&exit_lock_); | |
| 106 } | |
| 107 | |
| 108 // The default implementation supports running a 'C' main. | |
| 109 int PSInstance::MainThread(int argc, char* argv[]) { | |
| 110 if (!main_cb_) { | |
| 111 Error("No main defined.\n"); | |
| 112 return 0; | |
| 113 } | |
| 114 | |
| 115 Trace("Starting MAIN.\n"); | |
| 116 int ret = main_cb_(argc, argv); | |
| 117 Log("Main thread returned with %d.\n", ret); | |
| 118 | |
| 119 return ret; | |
| 120 } | |
| 121 | |
| 122 PSInstance::PSInstance(PP_Instance instance) | |
| 123 : pp::Instance(instance), | |
| 124 pp::MouseLock(this), | |
| 125 pp::Graphics3DClient(this), | |
| 126 main_loop_(NULL), | |
| 127 events_enabled_(PSE_NONE), | |
| 128 verbosity_(PSV_WARN), | |
| 129 tty_fd_(-1), | |
| 130 tty_prefix_(NULL), | |
| 131 exit_message_(NULL) { | |
| 132 | |
| 133 pthread_mutex_init(&exit_lock_, NULL); | |
| 134 pthread_cond_init(&exit_cond_, NULL); | |
| 135 | |
| 136 // Set the single Instance object | |
| 137 s_InstanceObject = this; | |
| 138 | |
| 139 #ifdef NACL_SDK_DEBUG | |
| 140 SetVerbosity(PSV_LOG); | |
| 141 #endif | |
| 142 | |
| 143 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | | |
| 144 PP_INPUTEVENT_CLASS_KEYBOARD | | |
| 145 PP_INPUTEVENT_CLASS_WHEEL | | |
| 146 PP_INPUTEVENT_CLASS_TOUCH); | |
| 147 } | |
| 148 | |
| 149 PSInstance::~PSInstance() { | |
| 150 s_InstanceObject = NULL; | |
| 151 } | |
| 152 | |
| 153 void PSInstance::SetMain(PSMainFunc_t main) { | |
| 154 main_cb_ = main; | |
| 155 } | |
| 156 | |
| 157 bool PSInstance::Init(uint32_t arg, | |
| 158 const char* argn[], | |
| 159 const char* argv[]) { | |
| 160 StartInfo* si = new StartInfo; | |
| 161 | |
| 162 si->inst_ = this; | |
| 163 si->argc_ = 0; | |
| 164 si->argv_ = new char *[arg+1]; | |
| 165 si->argv_[0] = NULL; | |
| 166 | |
| 167 // Process embed attributes into the environment. | |
| 168 // Converted the attribute names to uppercase as environment variables are | |
| 169 // case sensitive but are almost universally uppercase in practice. | |
| 170 for (uint32_t i = 0; i < arg; i++) { | |
| 171 std::string key = argn[i]; | |
| 172 std::transform(key.begin(), key.end(), key.begin(), toupper); | |
| 173 setenv(key.c_str(), argv[i], 1); | |
| 174 } | |
| 175 | |
| 176 // Set a default value for SRC. | |
| 177 setenv("SRC", "NMF?", 0); | |
| 178 // Use the src tag name if ARG0 is not explicitly specified. | |
| 179 setenv("ARG0", getenv("SRC"), 0); | |
| 180 | |
| 181 // Walk ARG0..ARGn populating argv until an argument is missing. | |
| 182 for (;;) { | |
| 183 std::ostringstream arg_stream; | |
| 184 arg_stream << "ARG" << si->argc_; | |
| 185 std::string arg_name = arg_stream.str(); | |
| 186 const char* next_arg = getenv(arg_name.c_str()); | |
| 187 if (NULL == next_arg) | |
| 188 break; | |
| 189 | |
| 190 char* value = new char[strlen(next_arg) + 1]; | |
| 191 strcpy(value, next_arg); | |
| 192 si->argv_[si->argc_++] = value; | |
| 193 } | |
| 194 | |
| 195 PSInterfaceInit(); | |
| 196 bool props_processed = ProcessProperties(); | |
| 197 | |
| 198 // Log arg values only once ProcessProperties has been | |
| 199 // called so that the ps_verbosity attribute will be in | |
| 200 // effect. | |
| 201 for (uint32_t i = 0; i < arg; i++) { | |
| 202 if (argv[i]) { | |
| 203 Trace("attribs[%d] '%s=%s'\n", i, argn[i], argv[i]); | |
| 204 } else { | |
| 205 Trace("attribs[%d] '%s'\n", i, argn[i]); | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 for (uint32_t i = 0; i < si->argc_; i++) { | |
| 210 Trace("argv[%d] '%s'\n", i, si->argv_[i]); | |
| 211 } | |
| 212 | |
| 213 if (!props_processed) { | |
| 214 Warn("Skipping create thread.\n"); | |
| 215 return false; | |
| 216 } | |
| 217 | |
| 218 pthread_t main_thread; | |
| 219 int ret = pthread_create(&main_thread, NULL, MainThreadThunk, si); | |
| 220 Trace("Created thread: %d.\n", ret); | |
| 221 return ret == 0; | |
| 222 } | |
| 223 | |
| 224 // Processes the properties set at compile time via the | |
| 225 // initialization macro, or via dynamically set embed attributes | |
| 226 // through instance DidCreate. | |
| 227 bool PSInstance::ProcessProperties() { | |
| 228 // Reset verbosity if passed in | |
| 229 const char* verbosity = getenv("PS_VERBOSITY"); | |
| 230 if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity))); | |
| 231 | |
| 232 // Enable NaCl IO to map STDIN, STDOUT, and STDERR | |
| 233 nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface); | |
| 234 | |
| 235 tty_prefix_ = getenv("PS_TTY_PREFIX"); | |
| 236 if (tty_prefix_) { | |
| 237 tty_fd_ = open("/dev/tty", O_WRONLY); | |
| 238 if (tty_fd_ >= 0) { | |
| 239 RegisterMessageHandler(tty_prefix_, MessageHandlerInputStatic, this); | |
| 240 const char* tty_resize = getenv("PS_TTY_RESIZE"); | |
| 241 if (tty_resize) | |
| 242 RegisterMessageHandler(tty_resize, MessageHandlerResizeStatic, this); | |
| 243 | |
| 244 char* tty_rows = getenv("PS_TTY_ROWS"); | |
| 245 char* tty_cols = getenv("PS_TTY_COLS"); | |
| 246 if (tty_rows && tty_cols) { | |
| 247 char* end = tty_rows; | |
| 248 int rows = strtol(tty_rows, &end, 10); | |
| 249 if (*end != '\0' || rows < 0) { | |
| 250 Error("Invalid value for PS_TTY_ROWS: %s\n", tty_rows); | |
| 251 } else { | |
| 252 end = tty_cols; | |
| 253 int cols = strtol(tty_cols, &end, 10); | |
| 254 if (*end != '\0' || cols < 0) | |
| 255 Error("Invalid value for PS_TTY_COLS: %s\n", tty_cols); | |
| 256 else | |
| 257 HandleResize(cols, rows); | |
| 258 } | |
| 259 } | |
| 260 else if (tty_rows || tty_cols) { | |
| 261 Error("PS_TTY_ROWS and PS_TTY_COLS must be set together\n"); | |
| 262 } | |
| 263 | |
| 264 tioc_nacl_output handler; | |
| 265 handler.handler = TtyOutputHandlerStatic; | |
| 266 handler.user_data = this; | |
| 267 ioctl(tty_fd_, TIOCNACLOUTPUT, &handler); | |
| 268 } else { | |
| 269 Error("Failed to open /dev/tty.\n"); | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 // Set default values | |
| 274 setenv("PS_STDIN", "/dev/stdin", 0); | |
| 275 setenv("PS_STDOUT", "/dev/stdout", 0); | |
| 276 setenv("PS_STDERR", "/dev/console3", 0); | |
| 277 | |
| 278 int fd0 = open(getenv("PS_STDIN"), O_RDONLY); | |
| 279 dup2(fd0, 0); | |
| 280 | |
| 281 int fd1 = open(getenv("PS_STDOUT"), O_WRONLY); | |
| 282 dup2(fd1, 1); | |
| 283 | |
| 284 int fd2 = open(getenv("PS_STDERR"), O_WRONLY); | |
| 285 dup2(fd2, 2); | |
| 286 | |
| 287 RegisterMessageHandler("jspipe1", MessageHandlerInputStatic, this); | |
| 288 RegisterMessageHandler("jspipe2", MessageHandlerInputStatic, this); | |
| 289 RegisterMessageHandler("jspipe3", MessageHandlerInputStatic, this); | |
| 290 | |
| 291 exit_message_ = getenv("PS_EXIT_MESSAGE"); | |
| 292 | |
| 293 // If PS_EXIT_MESSAGE is set in the environment then we perform a handshake | |
| 294 // with JavaScript when program exits. | |
| 295 if (exit_message_ != NULL) | |
| 296 nacl_io_set_exit_callback(HandleExitStatic, this); | |
| 297 | |
| 298 // Set line buffering on stdout and stderr | |
| 299 #if !defined(WIN32) | |
| 300 setvbuf(stderr, NULL, _IOLBF, 0); | |
| 301 setvbuf(stdout, NULL, _IOLBF, 0); | |
| 302 #endif | |
| 303 return true; | |
| 304 } | |
| 305 | |
| 306 void PSInstance::SetVerbosity(Verbosity verbosity) { | |
| 307 verbosity_ = verbosity; | |
| 308 } | |
| 309 | |
| 310 void PSInstance::VALog(Verbosity verbosity, const char *fmt, va_list args) { | |
| 311 if (verbosity <= verbosity_) { | |
| 312 fprintf(stderr, "ps: "); | |
| 313 vfprintf(stderr, fmt, args); | |
| 314 } | |
| 315 } | |
| 316 | |
| 317 void PSInstance::Trace(const char *fmt, ...) { | |
| 318 va_list ap; | |
| 319 va_start(ap, fmt); | |
| 320 VALog(PSV_TRACE, fmt, ap); | |
| 321 va_end(ap); | |
| 322 } | |
| 323 | |
| 324 void PSInstance::Log(const char *fmt, ...) { | |
| 325 va_list ap; | |
| 326 va_start(ap, fmt); | |
| 327 VALog(PSV_LOG, fmt, ap); | |
| 328 va_end(ap); | |
| 329 } | |
| 330 | |
| 331 void PSInstance::Warn(const char *fmt, ...) { | |
| 332 va_list ap; | |
| 333 va_start(ap, fmt); | |
| 334 VALog(PSV_WARN, fmt, ap); | |
| 335 va_end(ap); | |
| 336 } | |
| 337 | |
| 338 void PSInstance::Error(const char *fmt, ...) { | |
| 339 va_list ap; | |
| 340 va_start(ap, fmt); | |
| 341 VALog(PSV_ERROR, fmt, ap); | |
| 342 va_end(ap); | |
| 343 } | |
| 344 | |
| 345 void PSInstance::SetEnabledEvents(uint32_t mask) { | |
| 346 events_enabled_ = mask; | |
| 347 if (mask == 0) { | |
| 348 static bool warn_once = true; | |
| 349 if (warn_once) { | |
| 350 Warn("PSInstance::SetEnabledEvents(mask) where mask == 0 will block\n"); | |
| 351 Warn("all events. This can come from PSEventSetFilter(PSE_NONE);\n"); | |
| 352 warn_once = false; | |
| 353 } | |
| 354 } | |
| 355 } | |
| 356 | |
| 357 void PSInstance::PostEvent(PSEventType type) { | |
| 358 assert(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST == type || | |
| 359 PSE_MOUSELOCK_MOUSELOCKLOST == type); | |
| 360 | |
| 361 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); | |
| 362 memset(env, 0, sizeof(*env)); | |
| 363 env->type = type; | |
| 364 event_queue_.Enqueue(env); | |
| 365 } | |
| 366 | |
| 367 void PSInstance::PostEvent(PSEventType type, PP_Bool bool_value) { | |
| 368 assert(PSE_INSTANCE_DIDCHANGEFOCUS == type); | |
| 369 | |
| 370 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); | |
| 371 memset(env, 0, sizeof(*env)); | |
| 372 env->type = type; | |
| 373 env->as_bool = bool_value; | |
| 374 event_queue_.Enqueue(env); | |
| 375 } | |
| 376 | |
| 377 void PSInstance::PostEvent(PSEventType type, PP_Resource resource) { | |
| 378 assert(PSE_INSTANCE_HANDLEINPUT == type || | |
| 379 PSE_INSTANCE_DIDCHANGEVIEW == type); | |
| 380 | |
| 381 if (resource) { | |
| 382 PSInterfaceCore()->AddRefResource(resource); | |
| 383 } | |
| 384 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); | |
| 385 memset(env, 0, sizeof(*env)); | |
| 386 env->type = type; | |
| 387 env->as_resource = resource; | |
| 388 event_queue_.Enqueue(env); | |
| 389 } | |
| 390 | |
| 391 ssize_t PSInstance::TtyOutputHandler(const char* buf, size_t count) { | |
| 392 // We prepend the prefix_ to the data in buf, then package it up | |
| 393 // and post it as a message to javascript. | |
| 394 const char* data = static_cast<const char*>(buf); | |
| 395 std::string message = tty_prefix_; | |
| 396 message.append(data, count); | |
| 397 PostMessage(pp::Var(message)); | |
| 398 return count; | |
| 399 } | |
| 400 | |
| 401 void PSInstance::MessageHandlerExit(const pp::Var& message) { | |
| 402 assert(message.is_string()); | |
| 403 pthread_mutex_lock(&exit_lock_); | |
| 404 pthread_cond_signal(&exit_cond_); | |
| 405 pthread_mutex_unlock(&exit_lock_); | |
| 406 } | |
| 407 | |
| 408 void PSInstance::MessageHandlerInput(const pp::Var& key, | |
| 409 const pp::Var& message) { | |
| 410 std::string key_string = key.AsString(); | |
| 411 | |
| 412 const char* filename = NULL; | |
| 413 if (key_string == tty_prefix_) { | |
| 414 filename = "/dev/tty"; | |
| 415 } else if (key_string == "jspipe1") { | |
| 416 filename = "/dev/jspipe1"; | |
| 417 } else if (key_string == "jspipe2") { | |
| 418 filename = "/dev/jspipe2"; | |
| 419 } else if (key_string == "jspipe3") { | |
| 420 filename = "/dev/jspipe3"; | |
| 421 } else { | |
| 422 Error("unexpected input key: %s", key_string.c_str()); | |
| 423 return; | |
| 424 } | |
| 425 | |
| 426 int fd = open(filename, O_RDONLY); | |
| 427 if (fd < 0) { | |
| 428 Error("error opening file: %s (%s)", filename, strerror(errno)); | |
| 429 return; | |
| 430 } | |
| 431 | |
| 432 int ret = ioctl(fd, NACL_IOC_HANDLEMESSAGE, &message.pp_var()); | |
| 433 if (ret != 0) { | |
| 434 Error("ioctl on %s failed: %d.\n", filename, ret); | |
| 435 close(fd); | |
| 436 return; | |
| 437 } | |
| 438 | |
| 439 close(fd); | |
| 440 } | |
| 441 | |
| 442 void PSInstance::HandleExitStatic(int status, void* user_data) { | |
| 443 PSInstance* instance = static_cast<PSInstance*>(user_data); | |
| 444 instance->ExitHandshake(status); | |
| 445 } | |
| 446 | |
| 447 void PSInstance::HandleResize(int width, int height) { | |
| 448 struct winsize size; | |
| 449 memset(&size, 0, sizeof(size)); | |
| 450 size.ws_col = width; | |
| 451 size.ws_row = height; | |
| 452 ioctl(tty_fd_, TIOCSWINSZ, &size); | |
| 453 } | |
| 454 | |
| 455 void PSInstance::MessageHandlerResize(const pp::Var& message) { | |
| 456 assert(message.is_array()); | |
| 457 pp::VarArray array(message); | |
| 458 assert(array.GetLength() == 2); | |
| 459 | |
| 460 int width = array.Get(0).AsInt(); | |
| 461 int height = array.Get(1).AsInt(); | |
| 462 HandleResize(width, height); | |
| 463 } | |
| 464 | |
| 465 ssize_t PSInstance::TtyOutputHandlerStatic(const char* buf, | |
| 466 size_t count, | |
| 467 void* user_data) { | |
| 468 PSInstance* instance = static_cast<PSInstance*>(user_data); | |
| 469 return instance->TtyOutputHandler(buf, count); | |
| 470 } | |
| 471 | |
| 472 void PSInstance::MessageHandlerExitStatic(const pp::Var& key, | |
| 473 const pp::Var& value, | |
| 474 void* user_data) { | |
| 475 PSInstance* instance = static_cast<PSInstance*>(user_data); | |
| 476 instance->MessageHandlerExit(value); | |
| 477 } | |
| 478 | |
| 479 void PSInstance::MessageHandlerInputStatic(const pp::Var& key, | |
| 480 const pp::Var& value, | |
| 481 void* user_data) { | |
| 482 PSInstance* instance = static_cast<PSInstance*>(user_data); | |
| 483 instance->MessageHandlerInput(key, value); | |
| 484 } | |
| 485 | |
| 486 void PSInstance::MessageHandlerResizeStatic(const pp::Var& key, | |
| 487 const pp::Var& value, | |
| 488 void* user_data) { | |
| 489 PSInstance* instance = static_cast<PSInstance*>(user_data); | |
| 490 instance->MessageHandlerResize(value); | |
| 491 } | |
| 492 | |
| 493 void PSInstance::RegisterMessageHandler(std::string message_name, | |
| 494 MessageHandler_t handler, | |
| 495 void* user_data) { | |
| 496 Trace("registering msg handler: %s\n", message_name.c_str()); | |
| 497 if (handler == NULL) { | |
| 498 message_handlers_.erase(message_name); | |
| 499 return; | |
| 500 } | |
| 501 | |
| 502 MessageHandler message_handler = { handler, user_data }; | |
| 503 message_handlers_[message_name] = message_handler; | |
| 504 } | |
| 505 | |
| 506 void PSInstance::PostEvent(PSEventType type, const PP_Var& var) { | |
| 507 assert(PSE_INSTANCE_HANDLEMESSAGE == type); | |
| 508 | |
| 509 pp::Var event(var); | |
| 510 | |
| 511 // If the message is a dictionary then see if it matches one | |
| 512 // of the specific handlers, then call that handler rather than | |
| 513 // queuing an event. | |
| 514 if (event.is_dictionary()) { | |
| 515 pp::VarDictionary dictionary(var); | |
| 516 pp::VarArray keys = dictionary.GetKeys(); | |
| 517 if (keys.GetLength() == 1) { | |
| 518 pp::Var key = keys.Get(0); | |
| 519 Trace("calling handler for: %s\n", key.AsString().c_str()); | |
| 520 MessageHandlerMap::iterator iter = message_handlers_.find(key.AsString()); | |
| 521 if (iter != message_handlers_.end()) { | |
| 522 MessageHandler_t handler = iter->second.handler; | |
| 523 void* user_data = iter->second.user_data; | |
| 524 handler(key, dictionary.Get(key), user_data); | |
| 525 return; | |
| 526 } | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 PSInterfaceVar()->AddRef(var); | |
| 531 PSEvent *env = (PSEvent *) malloc(sizeof(PSEvent)); | |
| 532 memset(env, 0, sizeof(*env)); | |
| 533 env->type = type; | |
| 534 env->as_var = var; | |
| 535 event_queue_.Enqueue(env); | |
| 536 } | |
| 537 | |
| 538 PSEvent* PSInstance::TryAcquireEvent() { | |
| 539 PSEvent* event; | |
| 540 while(true) { | |
| 541 event = event_queue_.Dequeue(false); | |
| 542 if (NULL == event) | |
| 543 break; | |
| 544 if (events_enabled_ & event->type) | |
| 545 break; | |
| 546 // Release filtered events & continue to acquire. | |
| 547 ReleaseEvent(event); | |
| 548 } | |
| 549 return event; | |
| 550 } | |
| 551 | |
| 552 PSEvent* PSInstance::WaitAcquireEvent() { | |
| 553 PSEvent* event; | |
| 554 while(true) { | |
| 555 event = event_queue_.Dequeue(true); | |
| 556 if (events_enabled_ & event->type) | |
| 557 break; | |
| 558 // Release filtered events & continue to acquire. | |
| 559 ReleaseEvent(event); | |
| 560 } | |
| 561 return event; | |
| 562 } | |
| 563 | |
| 564 void PSInstance::ReleaseEvent(PSEvent* event) { | |
| 565 if (event) { | |
| 566 switch(event->type) { | |
| 567 case PSE_INSTANCE_HANDLEMESSAGE: | |
| 568 PSInterfaceVar()->Release(event->as_var); | |
| 569 break; | |
| 570 case PSE_INSTANCE_HANDLEINPUT: | |
| 571 case PSE_INSTANCE_DIDCHANGEVIEW: | |
| 572 if (event->as_resource) { | |
| 573 PSInterfaceCore()->ReleaseResource(event->as_resource); | |
| 574 } | |
| 575 break; | |
| 576 default: | |
| 577 break; | |
| 578 } | |
| 579 free(event); | |
| 580 } | |
| 581 } | |
| 582 | |
| 583 void PSInstance::HandleMessage(const pp::Var& message) { | |
| 584 Trace("Got Message\n"); | |
| 585 PostEvent(PSE_INSTANCE_HANDLEMESSAGE, message.pp_var()); | |
| 586 } | |
| 587 | |
| 588 bool PSInstance::HandleInputEvent(const pp::InputEvent& event) { | |
| 589 PostEvent(PSE_INSTANCE_HANDLEINPUT, event.pp_resource()); | |
| 590 return true; | |
| 591 } | |
| 592 | |
| 593 void PSInstance::DidChangeView(const pp::View& view) { | |
| 594 pp::Size new_size = view.GetRect().size(); | |
| 595 Log("Got View change: %d,%d\n", new_size.width(), new_size.height()); | |
| 596 PostEvent(PSE_INSTANCE_DIDCHANGEVIEW, view.pp_resource()); | |
| 597 } | |
| 598 | |
| 599 void PSInstance::DidChangeFocus(bool focus) { | |
| 600 Log("Got Focus change: %s\n", focus ? "FOCUS ON" : "FOCUS OFF"); | |
| 601 PostEvent(PSE_INSTANCE_DIDCHANGEFOCUS, focus ? PP_TRUE : PP_FALSE); | |
| 602 } | |
| 603 | |
| 604 void PSInstance::Graphics3DContextLost() { | |
| 605 Log("Graphics3DContextLost\n"); | |
| 606 PostEvent(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST); | |
| 607 } | |
| 608 | |
| 609 void PSInstance::MouseLockLost() { | |
| 610 Log("MouseLockLost\n"); | |
| 611 PostEvent(PSE_MOUSELOCK_MOUSELOCKLOST); | |
| 612 } | |
| OLD | NEW |