Index: native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/view-focus-input-events.html |
diff --git a/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/view-focus-input-events.html b/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/view-focus-input-events.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9c231791c9970e139719f01385b2e42e2c4d2435 |
--- /dev/null |
+++ b/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/view-focus-input-events.html |
@@ -0,0 +1,345 @@ |
+{{+bindTo:partials.standard_nacl_article}} |
+ |
+<section id="view-change-focus-and-input-events"> |
+<span id="view-focus-input-events"></span><h1 id="view-change-focus-and-input-events"><span id="view-focus-input-events"></span>View Change, Focus, and Input Events</h1> |
+<div class="contents local topic" id="contents"> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#overview" id="id2">Overview</a></li> |
+<li><p class="first"><a class="reference internal" href="#handling-browser-events" id="id3">Handling browser events</a></p> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#didchangeview" id="id4">DidChangeView()</a></li> |
+<li><a class="reference internal" href="#didchangefocus" id="id5">DidChangeFocus()</a></li> |
+</ul> |
+</li> |
+<li><p class="first"><a class="reference internal" href="#handling-input-events" id="id6">Handling input events</a></p> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#registering-a-module-to-accept-input-events" id="id7">Registering a module to accept input events</a></li> |
+<li><a class="reference internal" href="#determining-and-branching-on-event-types" id="id8">Determining and branching on event types</a></li> |
+<li><a class="reference internal" href="#threading-and-blocking" id="id9">Threading and blocking</a></li> |
+</ul> |
+</li> |
+</ul> |
+</div> |
+<p>This chapter describes view change, focus, and input event handling for a |
+Native Client module. The chapter assumes you are familiar with the |
+material presented in the <a class="reference internal" href="/native-client/overview.html"><em>Technical Overview</em></a>.</p> |
+<p>There are two examples used in this chapter to illustrate basic |
+programming techniques. The <code>input_events</code> example is used to |
+illustrate how your module can react to keyboard and mouse input |
+event. The <code>mouse_lock</code> example is used to illustrate how your module |
+can react to view change events. You can find these examples in the |
+<code>/examples/api/input_events</code> and <code>/examples/api/mouse_lock</code> |
+directories in the Native Client SDK. There is also the |
+ppapi_simple library that can be used to to implement most of the |
+boiler plate. The <code>pi_generator</code> example in |
+<code>/examples/demo/pi_generator</code> uses ppapi_simple to manage view |
+change events and 2D graphics.</p> |
+<section id="overview"> |
+<h2 id="overview">Overview</h2> |
+<p>When a user interacts with the web page using a keyboard, mouse or |
+some other input device, the browser generates input events. |
+In a traditional web application, these input events are |
+passed to and handled in JavaScript, typically through event listeners |
+and event handlers. In a Native Client application, user interaction |
+with an instance of a module (e.g., clicking inside the rectangle |
+managed by a module) also generates input events, which are passed to |
+the module. The browser also passes view change and focus events that |
+affect a module’s instance to the module. Native Client modules can |
+override certain functions in the <a class="reference external" href="https://developers.google.com/native-client/peppercpp/classpp_1_1_instance">pp::Instance</a> |
+class to handle input and browser events. These functions are listed in |
+the table below:</p> |
+<table border="1" class="docutils"> |
+<colgroup> |
+</colgroup> |
+<thead valign="bottom"> |
+<tr class="row-odd"><th class="head">Function</th> |
+<th class="head">Event</th> |
+<th class="head">Use</th> |
+</tr> |
+</thead> |
+<tbody valign="top"> |
+<tr class="row-even"><td><code>DidChangeView</code></td> |
+<td>Called when the position, |
+size, or clip rectangle |
+of the module’s instance in |
+the browser has changed. |
+This event also occurs |
+when browser window is |
+resized or mouse wheel |
+is scrolled.</td> |
+<td>An implementation |
+of this function |
+might check the size |
+of the module |
+instance’s rectangle |
+has changed and |
+reallocate the |
+graphics context |
+when a different |
+size is received.</td> |
+</tr> |
+<tr class="row-odd"><td><code>DidChangeFocus</code></td> |
+<td>Called when the module’s |
+instance in the browser |
+has gone in or out of |
+focus (usually by |
+clicking inside or |
+outside the module |
+instance). Having focus |
+means that keyboard |
+events will be sent to |
+the module instance. |
+An instance’s default |
+condition is that it |
+does not have focus.</td> |
+<td>An implementation |
+of this function |
+might start or stop |
+an animation or a |
+blinking cursor.</td> |
+</tr> |
+<tr class="row-even"><td><code>HandleDocumentLoad</code></td> |
+<td>Called after |
+<code>pp::Instance::Init()</code> |
+for a full-frame module |
+instance that was |
+instantiated based on |
+the MIME type of a |
+DOMWindow navigation. |
+This situation only |
+applies to modules that |
+are pre-registered to |
+handle certain MIME |
+types. If you haven’t |
+specifically registered |
+to handle a MIME type or |
+aren’t positive this |
+applies to you, your |
+implementation of this |
+function can just return |
+false.</td> |
+<td>This API is only |
+applicable when you |
+are writing an |
+extension to enhance |
+the abilities of |
+the Chrome web |
+browser. For |
+example, a PDF |
+viewer might |
+implement this |
+function to download |
+and display a PDF |
+file.</td> |
+</tr> |
+<tr class="row-odd"><td><code>HandleInputEvent</code></td> |
+<td>Called when a user |
+interacts with the |
+module’s instance in the |
+browser using an input |
+device such as a mouse |
+or keyboard. You must |
+register your module to |
+accept input events |
+using |
+<code>RequestInputEvents()</code> |
+for mouse events and |
+<code>RequestFilteringInputEvents</code> |
+for keyboard events |
+prior to overriding this |
+function.</td> |
+<td>An implementation of |
+this function |
+examines the input |
+event type and |
+branches accordingly.</td> |
+</tr> |
+</tbody> |
+</table> |
+<p>These interfaces are found in the <a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_instance">pp::Instance class</a>. |
+The sections below provide examples of how to handle these events.</p> |
+</section><section id="handling-browser-events"> |
+<h2 id="handling-browser-events">Handling browser events</h2> |
+<section id="didchangeview"> |
+<h3 id="didchangeview">DidChangeView()</h3> |
+<p>In the <code>mouse_lock</code> example, <code>DidChangeView()</code> checks the previous size |
+of instance’s rectangle versus the new size. It also compares |
+other state such as whether or not the app is running in full screen mode. |
+If none of the state has actually changed, no action is needed. |
+However, if the size of the view or other state has changed, it frees the |
+old graphics context and allocates a new one.</p> |
+<pre class="prettyprint"> |
+void MouseLockInstance::DidChangeView(const pp::View& view) { |
+ // DidChangeView can get called for many reasons, so we only want to |
+ // rebuild the device context if we really need to. |
+ if ((size_ == view.GetRect().size()) && |
+ (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) { |
+ return; |
+ } |
+ |
+ // ... |
+ |
+ // Reallocate the graphics context. |
+ size_ = view.GetRect().size(); |
+ device_context_ = pp::Graphics2D(this, size_, false); |
+ waiting_for_flush_completion_ = false; |
+ |
+ is_context_bound_ = BindGraphics(device_context_); |
+ // ... |
+ |
+ // Remember if we are fullscreen or not |
+ was_fullscreen_ = view.IsFullscreen(); |
+ // ... |
+} |
+</pre> |
+<p>For more information about graphics contexts and how to manipulate images, see:</p> |
+<ul class="small-gap"> |
+<li><a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_image_data">pp::ImageData class</a></li> |
+<li><a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_graphics2_d">pp::Graphics2D class</a></li> |
+</ul> |
+</section><section id="didchangefocus"> |
+<h3 id="didchangefocus">DidChangeFocus()</h3> |
+<p><code>DidChangeFocus()</code> is called when you click inside or outside of a |
+module’s instance in the web page. When the instance goes out |
+of focus (click outside of the instance), you might do something |
+like stop an animation. When the instance regains focus, you can |
+restart the animation.</p> |
+<pre class="prettyprint"> |
+void DidChangeFocus(bool focus) { |
+ // Do something like stopping animation or a blinking cursor in |
+ // the instance. |
+} |
+</pre> |
+</section></section><section id="handling-input-events"> |
+<h2 id="handling-input-events">Handling input events</h2> |
+<p>Input events are events that occur when the user interacts with a |
+module instance using the mouse, keyboard, or other input device |
+(e.g., touch screen). This section describes how the <code>input_events</code> |
+example handles input events.</p> |
+<section id="registering-a-module-to-accept-input-events"> |
+<h3 id="registering-a-module-to-accept-input-events">Registering a module to accept input events</h3> |
+<p>Before your module can handle these events, you must register your |
+module to accept input events using <code>RequestInputEvents()</code> for mouse |
+events and <code>RequestFilteringInputEvents()</code> for keyboard events. For the |
+<code>input_events</code> example, this is done in the constructor of the |
+<code>InputEventInstance</code> class:</p> |
+<pre class="prettyprint"> |
+class InputEventInstance : public pp::Instance { |
+ public: |
+ explicit InputEventInstance(PP_Instance instance) |
+ : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) { |
+ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL | |
+ PP_INPUTEVENT_CLASS_TOUCH); |
+ RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); |
+ } |
+ // ... |
+}; |
+</pre> |
+<p><code>RequestInputEvents()</code> and <code>RequestFilteringInputEvents()</code> accept a |
+combination of flags that identify the class of events that the |
+instance is requesting to receive. Input event classes are defined in |
+the <a class="reference external" href="https://developers.google.com/native-client/dev/pepperc/group___enums.html#gafe68e3c1031daa4a6496845ff47649cd">PP_InputEvent_Class</a> |
+enumeration in <a class="reference external" href="https://developers.google.com/native-client/dev/pepperc/ppb__input__event_8h">ppb_input_event.h</a>.</p> |
+</section><section id="determining-and-branching-on-event-types"> |
+<h3 id="determining-and-branching-on-event-types">Determining and branching on event types</h3> |
+<p>In a typical implementation, the <code>HandleInputEvent()</code> function |
+determines the type of each event using the <code>GetType()</code> function found |
+in the <code>InputEvent</code> class. The <code>HandleInputEvent()</code> function then uses a |
+switch statement to branch on the type of input event. Input events |
+are defined in the <a class="reference external" href="https://developers.google.com/native-client/dev/pepperc/group___enums.html#gaca7296cfec99fcb6646b7144d1d6a0c5">PP_InputEvent_Type</a> |
+enumeration in <a class="reference external" href="https://developers.google.com/native-client/dev/pepperc/ppb__input__event_8h">ppb_input_event.h</a>.</p> |
+<pre class="prettyprint"> |
+virtual bool HandleInputEvent(const pp::InputEvent& event) { |
+ Event* event_ptr = NULL; |
+ switch (event.GetType()) { |
+ case PP_INPUTEVENT_TYPE_UNDEFINED: |
+ break; |
+ case PP_INPUTEVENT_TYPE_MOUSEDOWN: |
+ case PP_INPUTEVENT_TYPE_MOUSEUP: |
+ case PP_INPUTEVENT_TYPE_MOUSEMOVE: |
+ case PP_INPUTEVENT_TYPE_MOUSEENTER: |
+ 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; |
+ 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; |
+ 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; |
+ default: { |
+ // For any unhandled events, send a message to the browser |
+ // so that the user is aware of these and can investigate. |
+ std::stringstream oss; |
+ oss << "Default (unhandled) event, type=" << event.GetType(); |
+ PostMessage(oss.str()); |
+ } break; |
+ } |
+ event_queue_.Push(event_ptr); |
+ return true; |
+} |
+</pre> |
+<p>Notice that the generic <code>InputEvent</code> received by <code>HandleInputEvent()</code> is |
+converted into a specific type after the event type is |
+determined. The event types handled in the example code are |
+<code>MouseInputEvent</code>, <code>WheelInputEvent</code>, and <code>KeyboardInputEvent</code>. |
+There are also <code>TouchInputEvents</code>. For the latest list of event types, |
+see the <a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_input_event">InputEvent documentation</a>. |
+For reference information related to the these event classes, see the |
+following documentation:</p> |
+<ul class="small-gap"> |
+<li><a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_mouse_input_event">pp::MouseInputEvent class</a></li> |
+<li><a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_wheel_input_event">pp::WheelInputEvent class</a></li> |
+<li><a class="reference external" href="https://developers.google.com/native-client/dev/peppercpp/classpp_1_1_keyboard_input_event">pp::KeyboardInputEvent class</a></li> |
+</ul> |
+</section><section id="threading-and-blocking"> |
+<h3 id="threading-and-blocking">Threading and blocking</h3> |
+<p><code>HandleInputEvent()</code> in this example runs on the main module thread. |
+However, the bulk of the work happens on a separate worker thread (see |
+<code>ProcessEventOnWorkerThread</code>). <code>HandleInputEvent()</code> puts events in |
+the <code>event_queue_</code> and the worker thread takes events from the |
+<code>event_queue_</code>. This processing happens independently of the main |
+thread, so as not to slow down the browser.</p> |
+</section></section></section> |
+ |
+{{/partials.standard_nacl_article}} |