diff options
author | binji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-22 00:21:53 +0000 |
---|---|---|
committer | binji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-22 00:21:53 +0000 |
commit | 5089c49fa38605755a50aa459bbc8d5da797002d (patch) | |
tree | 66b744b475ca6b66194eeca8259cb9a863f060b5 /native_client_sdk | |
parent | a60a34dbaf547de7a323f6d487a6bca182f0a40c (diff) | |
download | chromium_src-5089c49fa38605755a50aa459bbc8d5da797002d.zip chromium_src-5089c49fa38605755a50aa459bbc8d5da797002d.tar.gz chromium_src-5089c49fa38605755a50aa459bbc8d5da797002d.tar.bz2 |
[NaCl SDK] Make input_event example single-threaded again.
This significantly simplifies the example.
Also, it isn't necessary to do anything complex to pass InputEvents to worker
threads anymore; the functions can be called off main-thread.
BUG=243083
R=sbc@chromium.org, noelallen@chromium.org
Review URL: https://codereview.chromium.org/30683002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@229968 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
7 files changed, 145 insertions, 748 deletions
diff --git a/native_client_sdk/src/examples/api/input_event/custom_events.cc b/native_client_sdk/src/examples/api/input_event/custom_events.cc deleted file mode 100644 index e0558a5..0000000 --- a/native_client_sdk/src/examples/api/input_event/custom_events.cc +++ /dev/null @@ -1,151 +0,0 @@ -// 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 <sstream> - -#include "custom_events.h" - -// Convert a given modifier to a descriptive string. Note that the actual -// declared type of modifier in each of the event classes is uint32_t, but it is -// expected to be interpreted as a bitfield of 'or'ed PP_InputEvent_Modifier -// values. -std::string ModifierToString(uint32_t modifier) { - std::string s; - if (modifier & kShiftKeyModifier) { - s += "shift "; - } - if (modifier & kControlKeyModifier) { - s += "ctrl "; - } - if (modifier & kAltKeyModifier) { - s += "alt "; - } - if (modifier & kMetaKeyModifer) { - s += "meta "; - } - if (modifier & kKeyPadModifier) { - s += "keypad "; - } - if (modifier & kAutoRepeatModifier) { - s += "autorepeat "; - } - if (modifier & kLeftButtonModifier) { - s += "left-button-down "; - } - if (modifier & kMiddleButtonModifier) { - s += "middle-button-down "; - } - if (modifier & kRightButtonModifier) { - s += "right-button-down "; - } - if (modifier & kCapsLockModifier) { - s += "caps-lock "; - } - if (modifier & kNumLockModifier) { - s += "num-lock "; - } - return s; -} - -std::string KeyEvent::ToString() const { - std::ostringstream stream; - stream << "Key event:" - << " modifier:" << string_event_modifiers() - << " key_code:" << key_code_ << " time:" << timestamp_ - << " text:" << text_ << "\n"; - return stream.str(); -} - -std::string MouseEvent::ToString() const { - std::ostringstream stream; - stream << "Mouse event:" - << " modifier:" << string_event_modifiers() - << " button:" << MouseButtonToString(mouse_button_) - << " x:" << x_position_ << " y:" << y_position_ - << " click_count:" << click_count_ << " time:" << timestamp_ - << " is_context_menu: " << is_context_menu_ << "\n"; - return stream.str(); -} - -std::string WheelEvent::ToString() const { - std::ostringstream stream; - stream << "Wheel event:" - << " modifier:" << string_event_modifiers() << " deltax:" << delta_x_ - << " deltay:" << delta_y_ << " wheel_ticks_x:" << ticks_x_ - << " wheel_ticks_y:" << ticks_y_ - << " scroll_by_page: " << scroll_by_page_ << " time:" << timestamp_ - << "\n"; - return stream.str(); -} - -std::string MouseEvent::MouseButtonToString(MouseButton button) const { - switch (button) { - case kNone: - return "None"; - case kLeft: - return "Left"; - case kMiddle: - return "Middle"; - case kRight: - return "Right"; - default: - std::ostringstream stream; - stream << "Unrecognized (" << static_cast<int32_t>(button) << ")"; - return stream.str(); - } -} - -std::string TouchEvent::KindToString(Kind kind) const { - switch (kind) { - case kNone: - return "None"; - case kStart: - return "Start"; - case kMove: - return "Move"; - case kEnd: - return "End"; - case kCancel: - return "Cancel"; - default: - std::ostringstream stream; - stream << "Unrecognized (" << static_cast<int32_t>(kind) << ")"; - return stream.str(); - } -} - -void TouchEvent::AddTouch(uint32_t id, - float x, - float y, - float radii_x, - float radii_y, - float angle, - float pressure) { - Touch touch; - touch.id = id; - touch.x = x; - touch.y = y; - touch.radii_x = radii_x; - touch.radii_y = radii_y; - touch.angle = angle; - touch.pressure = pressure; - touches.push_back(touch); -} - -std::string TouchEvent::ToString() const { - std::ostringstream stream; - stream << "Touch event:" << KindToString(kind_) - << " modifier:" << string_event_modifiers(); - for (size_t i = 0; i < touches.size(); ++i) { - const Touch& touch = touches[i]; - stream << " x[" << touch.id << "]:" << touch.x << " y[" << touch.id - << "]:" << touch.y << " radii_x[" << touch.id - << "]:" << touch.radii_x << " radii_y[" << touch.id - << "]:" << touch.radii_y << " angle[" << touch.id - << "]:" << touch.angle << " pressure[" << touch.id - << "]:" << touch.pressure; - } - stream << " time:" << timestamp_ << "\n"; - return stream.str(); -} diff --git a/native_client_sdk/src/examples/api/input_event/custom_events.h b/native_client_sdk/src/examples/api/input_event/custom_events.h deleted file mode 100644 index fde32d5..0000000 --- a/native_client_sdk/src/examples/api/input_event/custom_events.h +++ /dev/null @@ -1,191 +0,0 @@ -// 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. - -#ifndef CUSTOM_EVENTS_H -#define CUSTOM_EVENTS_H - -#include <stdint.h> -#include <string> -#include <vector> - -// These functions and classes are used to define a non-Pepper set of -// events. This is typical of what many developers might do, since it -// would be common to convert a Pepper event into some other more -// application-specific type of event (SDL, Qt, etc.). - -// Constants used for Event::event_modifers_ (which is an int) -// are given below. Use powers of 2 so we can use bitwise AND/OR operators. -const uint32_t kShiftKeyModifier = 1 << 0; -const uint32_t kControlKeyModifier = 1 << 1; -const uint32_t kAltKeyModifier = 1 << 2; -const uint32_t kMetaKeyModifer = 1 << 3; -const uint32_t kKeyPadModifier = 1 << 4; -const uint32_t kAutoRepeatModifier = 1 << 5; -const uint32_t kLeftButtonModifier = 1 << 6; -const uint32_t kMiddleButtonModifier = 1 << 7; -const uint32_t kRightButtonModifier = 1 << 8; -const uint32_t kCapsLockModifier = 1 << 9; -const uint32_t kNumLockModifier = 1 << 10; - -std::string ModifierToString(uint32_t modifier); - -// Abstract base class for an Event -- ToString() is not defined. -// With polymorphism, we can have a collection of Event* and call -// ToString() on each one to be able to display the details of each -// event. -class Event { - public: - // Constructor for the base class. - // |modifiers| is an int that uses bit fields to set specific - // changes, such as the Alt key, specific button, etc. See - // ModifierToString() and constants defined in custom_events.cc. - explicit Event(uint32_t modifiers) : event_modifiers_(modifiers) {} - uint32_t event_modifiers() const { return event_modifiers_; } - std::string string_event_modifiers() const { - return ModifierToString(event_modifiers_); - } - // Convert the WheelEvent to a string - virtual std::string ToString() const = 0; - virtual ~Event() {} - - private: - uint32_t event_modifiers_; -}; - -// Class for a keyboard event. -class KeyEvent : public Event { - public: - // KeyEvent Constructor. |modifiers| is passed to Event base class. - // |keycode| is the ASCII value, |time| is a timestamp, - // |text| is the value as a string. - KeyEvent(uint32_t modifiers, uint32_t keycode, double time, std::string text) - : Event(modifiers), key_code_(keycode), timestamp_(time), text_(text) {} - // Convert the WheelEvent to a string - virtual std::string ToString() const; - - private: - uint32_t key_code_; - double timestamp_; - std::string text_; -}; - -class MouseEvent : public Event { - public: - // Specify a mouse button, with kNone available for initialization. - enum MouseButton { - kNone, - kLeft, - kMiddle, - kRight - }; - - // MouseEvent Constructor. |modifiers| is passed to Event base class. - // |button| specifies which button - // |xpos| and |ypos| give the location, - // |clicks| is how many times this same |xpos|,|ypos| - // has been clicked in a row. |time| is a timestamp, - MouseEvent(uint32_t modifiers, - MouseButton button, - uint32_t xpos, - uint32_t ypos, - uint32_t clicks, - double time, - bool is_context_menu) - : Event(modifiers), - mouse_button_(button), - x_position_(xpos), - y_position_(ypos), - click_count_(clicks), - timestamp_(time), - is_context_menu_(is_context_menu) {} - // Convert the WheelEvent to a string - virtual std::string ToString() const; - - private: - MouseButton mouse_button_; - uint32_t x_position_; - uint32_t y_position_; - uint32_t click_count_; - double timestamp_; - bool is_context_menu_; - - std::string MouseButtonToString(MouseButton button) const; -}; - -class WheelEvent : public Event { - public: - // WheelEvent Constructor. |modifiers| is passed to Event base class. - // |xticks| and |yticks| specify number of mouse wheel ticks. - // |scroll_by_page| indicates if we have scrolled past the current - // page. |time| is a timestamp, - WheelEvent(int modifiers, - uint32_t dx, - uint32_t dy, - uint32_t xticks, - uint32_t yticks, - bool scroll_by_page, - float time) - : Event(modifiers), - delta_x_(dx), - delta_y_(dy), - ticks_x_(xticks), - ticks_y_(yticks), - scroll_by_page_(scroll_by_page), - timestamp_(time) {} - // Convert the WheelEvent to a string - virtual std::string ToString() const; - - private: - uint32_t delta_x_; - uint32_t delta_y_; - uint32_t ticks_x_; - uint32_t ticks_y_; - bool scroll_by_page_; - double timestamp_; -}; - -class TouchEvent : public Event { - public: - // The kind of touch event that occurred. - enum Kind { - kNone, - kStart, - kMove, - kEnd, - kCancel - }; - - // TouchEvent constructor. - TouchEvent(int modifiers, Kind kind, float time) - : Event(modifiers), kind_(kind), timestamp_(time) {} - // Add a changed touch to this touch event. - void AddTouch(uint32_t id, - float x, - float y, - float radii_x, - float radii_y, - float angle, - float pressure); - // Convert the TouchEvent to a string - virtual std::string ToString() const; - - private: - std::string KindToString(Kind kind) const; - - struct Touch { - uint32_t id; - float x; - float y; - float radii_x; - float radii_y; - float angle; - float pressure; - }; - - Kind kind_; - std::vector<Touch> touches; - double timestamp_; -}; - -#endif // CUSTOM_EVENTS_H diff --git a/native_client_sdk/src/examples/api/input_event/example.dsc b/native_client_sdk/src/examples/api/input_event/example.dsc index 5744367..725a83c 100644 --- a/native_client_sdk/src/examples/api/input_event/example.dsc +++ b/native_client_sdk/src/examples/api/input_event/example.dsc @@ -5,10 +5,7 @@ 'NAME' : 'input_event', 'TYPE' : 'main', 'SOURCES' : [ - 'custom_events.cc', - 'custom_events.h', 'input_event.cc', - 'shared_queue.h', ], 'LIBS': ['ppapi_cpp', 'ppapi', 'pthread'] } diff --git a/native_client_sdk/src/examples/api/input_event/example.js b/native_client_sdk/src/examples/api/input_event/example.js index 003e843..6375382 100644 --- a/native_client_sdk/src/examples/api/input_event/example.js +++ b/native_client_sdk/src/examples/api/input_event/example.js @@ -8,19 +8,6 @@ function moduleDidLoad() { } // Called by the common.js module. -function attachListeners() { - document.getElementById('killButton').addEventListener('click', cancelQueue); -} - -// Called by the common.js module. function handleMessage(message) { common.logMessage(message.data); } - -function cancelQueue() { - if (common.naclModule == null) { - console.log('Module is not loaded.'); - return; - } - common.naclModule.postMessage('CANCEL'); -} diff --git a/native_client_sdk/src/examples/api/input_event/index.html b/native_client_sdk/src/examples/api/input_event/index.html index 0739c7a..da8f178 100644 --- a/native_client_sdk/src/examples/api/input_event/index.html +++ b/native_client_sdk/src/examples/api/input_event/index.html @@ -11,28 +11,19 @@ found in the LICENSE file. <title>{{title}}</title> <script type="text/javascript" src="common.js"></script> <script type="text/javascript" src="example.js"></script> + <style> + #listener { float: left; padding-right: 8px; } + </style> </head> <body {{attrs}}> <h1>{{title}}</h1> <h2>Status: <code id="statusField">NO-STATUS</code></h2> - <p>The Input Events example shows how to handle input events in a - multi-threaded application. The main thread converts input events to - non-pepper events and puts them on a queue. The worker thread pulls them - off of the queue, converts them to a string, and then uses - CallOnMainThread so that PostMessage can send the result of the worker - thread to the browser.</p> - <p>If you press the 'Kill worker thread and queue' button, then the main - thread (which puts events on the queue) will call CancelQueue, indicating - that the main thread will no longer put events on the queue. When the worker - sees that the shared queue has been cancelled, the worker thread will - terminate.</p> - - <button id="killButton">Kill worker thread and queue</button> - - <!-- The NaCl plugin will be embedded inside the element with id "listener". - See common.js.--> <div id="listener"></div> - <h2>Events:</h2> + <p>This example shows how to handle input events.</p> + <p>Click or touch the box to the left to see the events being sent to the + NaCl module. When it has focus, the module will also accept keyboard + events.</p> + <h2 style="clear: left">Events:</h2> <pre id="log" style="font-weight: bold"></pre> </body> </html> diff --git a/native_client_sdk/src/examples/api/input_event/input_event.cc b/native_client_sdk/src/examples/api/input_event/input_event.cc index 1f57fcc..fee260b 100644 --- a/native_client_sdk/src/examples/api/input_event/input_event.cc +++ b/native_client_sdk/src/examples/api/input_event/input_event.cc @@ -3,8 +3,7 @@ // found in the LICENSE file. // C headers -#include <cassert> -#include <cstdio> +#include <stdio.h> // C++ headers #include <sstream> @@ -19,77 +18,100 @@ #include "ppapi/cpp/var.h" #include "ppapi/utility/completion_callback_factory.h" -#include "custom_events.h" -#include "shared_queue.h" - #ifdef PostMessage #undef PostMessage #endif -const char* const kDidChangeView = "DidChangeView\n"; -const char* const kHandleInputEvent = "DidHandleInputEvent\n"; -const char* const kDidChangeFocus = "DidChangeFocus\n"; -const char* const kHaveFocus = "HaveFocus\n"; -const char* const kDontHaveFocus = "DontHaveFocus\n"; -const char* const kCancelMessage = "CANCEL"; +namespace { + +const char* const kDidChangeFocus = "DidChangeFocus"; +const char* const kHaveFocus = "HaveFocus"; +const char* const kDontHaveFocus = "DontHaveFocus"; -// Convert a pepper inputevent modifier value into a -// custom event modifier. -unsigned int ConvertEventModifier(uint32_t pp_modifier) { - unsigned int custom_modifier = 0; - if (pp_modifier & PP_INPUTEVENT_MODIFIER_SHIFTKEY) { - custom_modifier |= kShiftKeyModifier; +std::string ModifierToString(uint32_t modifier) { + std::string s; + if (modifier & PP_INPUTEVENT_MODIFIER_SHIFTKEY) { + s += "shift "; + } + if (modifier & PP_INPUTEVENT_MODIFIER_CONTROLKEY) { + s += "ctrl "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_CONTROLKEY) { - custom_modifier |= kControlKeyModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_ALTKEY) { + s += "alt "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_ALTKEY) { - custom_modifier |= kAltKeyModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_METAKEY) { + s += "meta "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_METAKEY) { - custom_modifier |= kMetaKeyModifer; + if (modifier & PP_INPUTEVENT_MODIFIER_ISKEYPAD) { + s += "keypad "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_ISKEYPAD) { - custom_modifier |= kKeyPadModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) { + s += "autorepeat "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_ISAUTOREPEAT) { - custom_modifier |= kAutoRepeatModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { + s += "left-button-down "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) { - custom_modifier |= kLeftButtonModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) { + s += "middle-button-down "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN) { - custom_modifier |= kMiddleButtonModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) { + s += "right-button-down "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN) { - custom_modifier |= kRightButtonModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) { + s += "caps-lock "; } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY) { - custom_modifier |= kCapsLockModifier; + if (modifier & PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) { + s += "num-lock "; + } + return s; +} + +std::string MouseButtonToString(PP_InputEvent_MouseButton button) { + switch (button) { + case PP_INPUTEVENT_MOUSEBUTTON_NONE: + return "None"; + case PP_INPUTEVENT_MOUSEBUTTON_LEFT: + return "Left"; + case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE: + return "Middle"; + case PP_INPUTEVENT_MOUSEBUTTON_RIGHT: + return "Right"; + default: + std::ostringstream stream; + stream << "Unrecognized (" << static_cast<int32_t>(button) << ")"; + return stream.str(); } - if (pp_modifier & PP_INPUTEVENT_MODIFIER_NUMLOCKKEY) { - custom_modifier |= kNumLockModifier; +} + +std::string TouchKindToString(PP_InputEvent_Type kind) { + switch (kind) { + case PP_INPUTEVENT_TYPE_TOUCHSTART: + return "Start"; + case PP_INPUTEVENT_TYPE_TOUCHMOVE: + return "Move"; + case PP_INPUTEVENT_TYPE_TOUCHEND: + return "End"; + case PP_INPUTEVENT_TYPE_TOUCHCANCEL: + return "Cancel"; + default: + std::ostringstream stream; + stream << "Unrecognized (" << static_cast<int32_t>(kind) << ")"; + return stream.str(); } - return custom_modifier; } +} // namespace + class InputEventInstance : public pp::Instance { public: explicit InputEventInstance(PP_Instance instance) - : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) { + : pp::Instance(instance) { RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_TOUCH); RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); } - // Not guaranteed to be called in Pepper, but a good idea to cancel the - // queue and signal to workers to die if it is called. - virtual ~InputEventInstance() { CancelQueueAndWaitForWorker(); } - - // Create the 'worker thread'. bool Init(uint32_t argc, const char* argn[], const char* argv[]) { - event_thread_ = new pthread_t; - pthread_create(event_thread_, NULL, ProcessEventOnWorkerThread, this); return true; } @@ -100,50 +122,36 @@ class InputEventInstance : public pp::Instance { /// (the NaCl instance is back in focus). The default is /// that the instance is out of focus. void DidChangeFocus(bool focus) { - PostMessage(pp::Var(kDidChangeFocus)); - if (focus == true) { - PostMessage(pp::Var(kHaveFocus)); - } else { - PostMessage(pp::Var(kDontHaveFocus)); - } + std::ostringstream stream; + stream << "DidChangeFocus:" << " focus:" << focus; + PostMessage(stream.str()); } /// Scrolling the mouse wheel causes a DidChangeView event. void DidChangeView(const pp::View& view) { - PostMessage(pp::Var(kDidChangeView)); - } - - virtual void HandleMessage(const pp::Var& var_message) { - std::string message = var_message.AsString(); - if (kCancelMessage == message) { - std::string reply = - "Received cancel : only Focus events will be " - "displayed. Worker thread for mouse/wheel/keyboard will exit."; - PostMessage(pp::Var(reply)); - printf("Calling cancel queue\n"); - CancelQueueAndWaitForWorker(); - } + std::ostringstream stream; + stream << "DidChangeView:" + << " x:" << view.GetRect().x() + << " y:" << view.GetRect().y() + << " width:" << view.GetRect().width() + << " height:" << view.GetRect().height() + << "\n" + << " IsFullscreen:" << view.IsFullscreen() + << " IsVisible:" << view.IsVisible() + << " IsPageVisible:" << view.IsPageVisible() + << " GetDeviceScale:" << view.GetDeviceScale() + << " GetCSSScale:" << view.GetCSSScale(); + PostMessage(stream.str()); } - // HandleInputEvent operates on the main Pepper thread. Here we - // illustrate copying the Pepper input event to our own custom event type. - // Since we need to use Pepper API calls to convert it, we must do the - // conversion on the main thread. Once we have converted it to our own - // event type, we push that into a thread-safe queue and quickly return. - // The worker thread can process the custom event and do whatever - // (possibly slow) things it wants to do without making the browser - // become unresponsive. - // We dynamically allocate a sub-class of our custom event (Event) - // so that the queue can contain an Event*. virtual bool HandleInputEvent(const pp::InputEvent& event) { - Event* event_ptr = NULL; switch (event.GetType()) { case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START: case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE: case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END: case PP_INPUTEVENT_TYPE_IME_TEXT: - // these cases are not handled...fall through below... case PP_INPUTEVENT_TYPE_UNDEFINED: + // these cases are not handled. break; case PP_INPUTEVENT_TYPE_MOUSEDOWN: case PP_INPUTEVENT_TYPE_MOUSEUP: @@ -152,88 +160,76 @@ class InputEventInstance : public pp::Instance { case PP_INPUTEVENT_TYPE_MOUSELEAVE: case PP_INPUTEVENT_TYPE_CONTEXTMENU: { pp::MouseInputEvent mouse_event(event); - PP_InputEvent_MouseButton pp_button = mouse_event.GetButton(); - MouseEvent::MouseButton mouse_button = MouseEvent::kNone; - switch (pp_button) { - case PP_INPUTEVENT_MOUSEBUTTON_NONE: - mouse_button = MouseEvent::kNone; - break; - case PP_INPUTEVENT_MOUSEBUTTON_LEFT: - mouse_button = MouseEvent::kLeft; - break; - case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE: - mouse_button = MouseEvent::kMiddle; - break; - case PP_INPUTEVENT_MOUSEBUTTON_RIGHT: - mouse_button = MouseEvent::kRight; - break; - } - event_ptr = - new MouseEvent(ConvertEventModifier(mouse_event.GetModifiers()), - mouse_button, - mouse_event.GetPosition().x(), - mouse_event.GetPosition().y(), - mouse_event.GetClickCount(), - mouse_event.GetTimeStamp(), - event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU); - } break; + std::ostringstream stream; + stream << "Mouse event:" + << " modifier:" << ModifierToString(mouse_event.GetModifiers()) + << " button:" << MouseButtonToString(mouse_event.GetButton()) + << " x:" << mouse_event.GetPosition().x() + << " y:" << mouse_event.GetPosition().y() + << " click_count:" << mouse_event.GetClickCount() + << " time:" << mouse_event.GetTimeStamp() + << " is_context_menu: " + << (event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU); + PostMessage(stream.str()); + break; + } + case PP_INPUTEVENT_TYPE_WHEEL: { pp::WheelInputEvent wheel_event(event); - event_ptr = - new WheelEvent(ConvertEventModifier(wheel_event.GetModifiers()), - wheel_event.GetDelta().x(), - wheel_event.GetDelta().y(), - wheel_event.GetTicks().x(), - wheel_event.GetTicks().y(), - wheel_event.GetScrollByPage(), - wheel_event.GetTimeStamp()); - } break; + std::ostringstream stream; + stream << "Wheel event:" + << " modifier:" << ModifierToString(wheel_event.GetModifiers()) + << " deltax:" << wheel_event.GetDelta().x() + << " deltay:" << wheel_event.GetDelta().y() + << " wheel_ticks_x:" << wheel_event.GetTicks().x() + << " wheel_ticks_y:" << wheel_event.GetTicks().y() + << " scroll_by_page: " << wheel_event.GetScrollByPage() + << " time:" << wheel_event.GetTimeStamp(); + PostMessage(stream.str()); + break; + } + case PP_INPUTEVENT_TYPE_RAWKEYDOWN: case PP_INPUTEVENT_TYPE_KEYDOWN: case PP_INPUTEVENT_TYPE_KEYUP: case PP_INPUTEVENT_TYPE_CHAR: { pp::KeyboardInputEvent key_event(event); - event_ptr = new KeyEvent(ConvertEventModifier(key_event.GetModifiers()), - key_event.GetKeyCode(), - key_event.GetTimeStamp(), - key_event.GetCharacterText().DebugString()); - } break; + std::ostringstream stream; + stream << "Key event:" + << " modifier:" << ModifierToString(key_event.GetModifiers()) + << " key_code:" << key_event.GetKeyCode() + << " time:" << key_event.GetTimeStamp() + << " text:" << key_event.GetCharacterText().DebugString(); + PostMessage(stream.str()); + break; + } + case PP_INPUTEVENT_TYPE_TOUCHSTART: case PP_INPUTEVENT_TYPE_TOUCHMOVE: case PP_INPUTEVENT_TYPE_TOUCHEND: case PP_INPUTEVENT_TYPE_TOUCHCANCEL: { pp::TouchInputEvent touch_event(event); - - TouchEvent::Kind touch_kind = TouchEvent::kNone; - if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHSTART) - touch_kind = TouchEvent::kStart; - else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHMOVE) - touch_kind = TouchEvent::kMove; - else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHEND) - touch_kind = TouchEvent::kEnd; - else if (event.GetType() == PP_INPUTEVENT_TYPE_TOUCHCANCEL) - touch_kind = TouchEvent::kCancel; - - TouchEvent* touch_event_ptr = - new TouchEvent(ConvertEventModifier(touch_event.GetModifiers()), - touch_kind, - touch_event.GetTimeStamp()); - event_ptr = touch_event_ptr; + std::ostringstream stream; + stream << "Touch event:" << TouchKindToString(event.GetType()) + << " modifier:" << ModifierToString(touch_event.GetModifiers()); uint32_t touch_count = touch_event.GetTouchCount(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES); for (uint32_t i = 0; i < touch_count; ++i) { pp::TouchPoint point = touch_event.GetTouchByIndex(PP_TOUCHLIST_TYPE_CHANGEDTOUCHES, i); - touch_event_ptr->AddTouch(point.id(), - point.position().x(), - point.position().y(), - point.radii().x(), - point.radii().y(), - point.rotation_angle(), - point.pressure()); + stream << " x[" << point.id() << "]:" << point.position().x() + << " y[" << point.id() << "]:" << point.position().y() + << " radii_x[" << point.id() << "]:" << point.radii().x() + << " radii_y[" << point.id() << "]:" << point.radii().y() + << " angle[" << point.id() << "]:" << point.rotation_angle() + << " pressure[" << point.id() << "]:" << point.pressure(); } - } break; + stream << " time:" << touch_event.GetTimeStamp(); + PostMessage(stream.str()); + break; + } + default: { // For any unhandled events, send a message to the browser // so that the user is aware of these and can investigate. @@ -242,86 +238,9 @@ class InputEventInstance : public pp::Instance { PostMessage(oss.str()); } break; } - event_queue_.Push(event_ptr); - return true; - } - // Return an event from the thread-safe queue, waiting for a new event - // to occur if the queue is empty. Set |was_queue_cancelled| to indicate - // whether the queue was cancelled. If it was cancelled, then the - // Event* will be NULL. - const Event* GetEventFromQueue(bool* was_queue_cancelled) { - Event* event = NULL; - QueueGetResult result = event_queue_.GetItem(&event, kWait); - if (result == kQueueWasCancelled) { - *was_queue_cancelled = true; - return NULL; - } - *was_queue_cancelled = false; - return event; - } - - // This method is called from the worker thread using CallOnMainThread. - // It is not static, and allows PostMessage to be called. - void* PostStringToBrowser(int32_t result, std::string data_to_send) { - PostMessage(pp::Var(data_to_send)); - return 0; - } - - // |ProcessEventOnWorkerThread| is a static method that is run - // by a thread. It pulls events from the queue, converts - // them to a string, and calls CallOnMainThread so that - // PostStringToBrowser will be called, which will call PostMessage - // to send the converted event back to the browser. - static void* ProcessEventOnWorkerThread(void* param) { - InputEventInstance* event_instance = - static_cast<InputEventInstance*>(param); - while (1) { - // Grab a generic Event* so that down below we can call - // event->ToString(), which will use the correct virtual method - // to convert the event to a string. This 'conversion' is - // the 'work' being done on the worker thread. In an application - // the work might involve changing application state based on - // the event that was processed. - bool queue_cancelled; - const Event* event = event_instance->GetEventFromQueue(&queue_cancelled); - if (queue_cancelled) { - printf("Queue was cancelled, worker thread exiting\n"); - pthread_exit(NULL); - } - std::string event_string = event->ToString(); - delete event; - // Need to invoke callback on main thread. - pp::Module::Get()->core()->CallOnMainThread( - 0, - event_instance->callback_factory().NewCallback( - &InputEventInstance::PostStringToBrowser, event_string)); - } // end of while loop. - return 0; - } - - // Return the callback factory. - // Allows the static method (ProcessEventOnWorkerThread) to use - // the |event_instance| pointer to get the factory. - pp::CompletionCallbackFactory<InputEventInstance>& callback_factory() { - return callback_factory_; - } - - private: - // Cancels the queue (which will cause the thread to exit). - // Wait for the thread. Set |event_thread_| to NULL so we only - // execute the body once. - void CancelQueueAndWaitForWorker() { - if (event_thread_) { - event_queue_.CancelQueue(); - pthread_join(*event_thread_, NULL); - delete event_thread_; - event_thread_ = NULL; - } + return true; } - pthread_t* event_thread_; - LockingQueue<Event*> event_queue_; - pp::CompletionCallbackFactory<InputEventInstance> callback_factory_; }; class InputEventModule : public pp::Module { diff --git a/native_client_sdk/src/examples/api/input_event/shared_queue.h b/native_client_sdk/src/examples/api/input_event/shared_queue.h deleted file mode 100644 index 22a75bc..0000000 --- a/native_client_sdk/src/examples/api/input_event/shared_queue.h +++ /dev/null @@ -1,155 +0,0 @@ -// 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. - -#ifndef SHARED_QUEUE_H -#define SHARED_QUEUE_H - -#include <pthread.h> -#include <cassert> -#include <deque> - -// This file provides a queue that uses a mutex and condition variable so that -// one thread can put pointers into the queue and another thread can pull items -// out of the queue. - -// Specifies whether we want to wait for the queue. -enum QueueWaitingFlag { - kWait = 0, - kDontWait -}; - -// Indicates if we got an item, did not wait, or if the queue was cancelled. -enum QueueGetResult { - kReturnedItem = 0, - kDidNotWait = 1, - kQueueWasCancelled -}; - -// A simple scoped mutex lock. -// For most cases, pp::AutoLock in "ppapi/utility/threading/lock.h" can be -// used; LockingQueue needs to use the pthread_mutex_t directly in -// pthread_cond_wait so we reimplement a scoped lock here. -class ScopedLock { - public: - explicit ScopedLock(pthread_mutex_t* mutex) : mutex_(mutex) { - const int kPthreadMutexSuccess = 0; - if (pthread_mutex_lock(mutex_) != kPthreadMutexSuccess) { - mutex_ = NULL; - } - } - ~ScopedLock() { - if (mutex_ != NULL) { - pthread_mutex_unlock(mutex_); - } - } - - private: - pthread_mutex_t* mutex_; // Weak reference, passed in to constructor. - - // Disable copy and assign. - ScopedLock& operator=(const ScopedLock&); - ScopedLock(const ScopedLock&); -}; - - -#ifdef __GNUC__ -#define UNUSED __attribute__ ((unused)) -#else -#define UNUSED -#endif - -// LockingQueue contains a collection of <T>, such as a collection of -// objects or pointers. The Push() method is used to add items to the -// queue in a thread-safe manner. The GetItem() is used to retrieve -// items from the queue in a thread-safe manner. -template <class T> class LockingQueue { - public: - LockingQueue() : quit_(false) { - int result UNUSED; - result = pthread_mutex_init(&queue_mutex_, NULL); - assert(result == 0); - result = pthread_cond_init(&queue_condition_var_, NULL); - assert(result == 0); - } - ~LockingQueue() { pthread_mutex_destroy(&queue_mutex_); } - - // The producer (who instantiates the queue) calls this to tell the - // consumer that the queue is no longer being used. - void CancelQueue() { - ScopedLock scoped_mutex(&queue_mutex_); - quit_ = true; - // Signal the condition var so that if a thread is waiting in - // GetItem the thread will wake up and see that the queue has - // been cancelled. - pthread_cond_signal(&queue_condition_var_); - } - - // The consumer calls this to see if the queue has been cancelled by - // the producer. If so, the thread should not call GetItem and may - // need to terminate -- i.e. in a case where the producer created - // the consumer thread. - bool IsCancelled() { - ScopedLock scoped_mutex(&queue_mutex_); - return quit_; - } - - // Grabs the mutex and pushes a new item to the end of the queue if the - // queue is not full. Signals the condition variable so that a thread - // that is waiting will wake up and grab the item. - void Push(const T& item) { - ScopedLock scoped_mutex(&queue_mutex_); - the_queue_.push_back(item); - pthread_cond_signal(&queue_condition_var_); - } - - // Tries to pop the front element from the queue; returns an enum: - // kReturnedItem if an item is returned in |item_ptr|, - // kDidNotWait if |wait| was kDontWait and the queue was empty, - // kQueueWasCancelled if the producer called CancelQueue(). - // If |wait| is kWait, GetItem will wait to return until the queue - // contains an item (unless the queue is cancelled). - QueueGetResult GetItem(T* item_ptr, QueueWaitingFlag wait) { - ScopedLock scoped_mutex(&queue_mutex_); - // Use a while loop to get an item. If the user does not want to wait, - // we will exit from the loop anyway, unlocking the mutex. - // If the user does want to wait, we will wait for pthread_cond_wait, - // and the while loop will check is_empty_no_locking() one more - // time so that a spurious wake-up of pthread_cond_wait is handled. - // If |quit_| has been set, break out of the loop. - while (!quit_ && is_empty_no_locking()) { - // If user doesn't want to wait, return... - if (kDontWait == wait) { - return kDidNotWait; - } - // Wait for signal to occur. - pthread_cond_wait(&queue_condition_var_, &queue_mutex_); - } - // Check to see if quit_ woke us up - if (quit_) { - return kQueueWasCancelled; - } - - // At this point, the queue was either not empty or, if it was empty, - // we called pthread_cond_wait (which released the mutex, waited for the - // signal to occur, and then atomically reacquired the mutex). - // Thus, if we are here, the queue cannot be empty because we either - // had the mutex and verified it was not empty, or we waited for the - // producer to put an item in and signal a single thread (us). - T& item = the_queue_.front(); - *item_ptr = item; - the_queue_.pop_front(); - return kReturnedItem; - } - - private: - std::deque<T> the_queue_; - bool quit_; - pthread_mutex_t queue_mutex_; - pthread_cond_t queue_condition_var_; - - // This is used by methods that already have the lock. - bool is_empty_no_locking() const { return the_queue_.empty(); } -}; - -#endif // SHARED_QUEUE_H |