1 {{+bindTo:partials.standard_nacl_api}}
3 <section id="view-change-focus-and-input-events">
4 <h1 id="view-change-focus-and-input-events">View Change, Focus, and Input Events</h1>
5 <div class="contents local" id="contents" style="display: none">
7 <li><a class="reference internal" href="#overview" id="id2">Overview</a></li>
8 <li><p class="first"><a class="reference internal" href="#handling-browser-events" id="id3">Handling browser events</a></p>
10 <li><a class="reference internal" href="#didchangeview" id="id4">DidChangeView()</a></li>
11 <li><a class="reference internal" href="#didchangefocus" id="id5">DidChangeFocus()</a></li>
14 <li><p class="first"><a class="reference internal" href="#handling-input-events" id="id6">Handling input events</a></p>
15 <ul class="small-gap">
16 <li><a class="reference internal" href="#registering-a-module-to-accept-input-events" id="id7">Registering a module to accept input events</a></li>
17 <li><a class="reference internal" href="#determining-and-branching-on-event-types" id="id8">Determining and branching on event types</a></li>
18 <li><a class="reference internal" href="#threading-and-blocking" id="id9">Threading and blocking</a></li>
23 </div><p>This chapter describes view change, focus, and input event handling for a
24 Native Client module. The chapter assumes you are familiar with the
25 material presented in the <a class="reference internal" href="/native-client/overview.html"><em>Technical Overview</em></a>.</p>
26 <p>There are two examples used in this chapter to illustrate basic
27 programming techniques. The <code>input_events</code> example is used to
28 illustrate how your module can react to keyboard and mouse input
29 event. The <code>mouse_lock</code> example is used to illustrate how your module
30 can react to view change events. You can find these examples in the
31 <code>/examples/api/input_events</code> and <code>/examples/api/mouse_lock</code>
32 directories in the Native Client SDK. There is also the
33 ppapi_simple library that can be used to to implement most of the
34 boiler plate. The <code>pi_generator</code> example in
35 <code>/examples/demo/pi_generator</code> uses ppapi_simple to manage view
36 change events and 2D graphics.</p>
37 <h2 id="overview">Overview</h2>
38 <p>When a user interacts with the web page using a keyboard, mouse or some other
39 input device, the browser generates input events. In a traditional web
40 application, these input events are passed to and handled in JavaScript,
41 typically through event listeners and event handlers. In a Native Client
42 application, user interaction with an instance of a module (e.g., clicking
43 inside the rectangle managed by a module) also generates input events, which
44 are passed to the module. The browser also passes view change and focus events
45 that affect a module’s instance to the module. Native Client modules can
46 override certain functions in the <a class="reference external" href="/native-client/pepper_stable/cpp/classpp_1_1_instance">pp::Instance</a> class to handle input
47 and browser events. These functions are listed in the table below:</p>
48 <table border="1" class="docutils">
51 <thead valign="bottom">
52 <tr class="row-odd"><th class="head">Function</th>
53 <th class="head">Event</th>
54 <th class="head">Use</th>
58 <tr class="row-even"><td><code>DidChangeView</code></td>
59 <td>Called when the position,
60 size, or clip rectangle
61 of the module’s instance in
62 the browser has changed.
63 This event also occurs
64 when browser window is
65 resized or mouse wheel
71 instance’s rectangle
76 size is received.</td>
78 <tr class="row-odd"><td><code>DidChangeFocus</code></td>
79 <td>Called when the module’s
80 instance in the browser
85 instance). Having focus
87 events will be sent to
89 An instance’s default
91 does not have focus.</td>
98 <tr class="row-even"><td><code>HandleDocumentLoad</code></td>
100 <code>pp::Instance::Init()</code>
101 for a full-frame module
103 instantiated based on
105 DOMWindow navigation.
107 applies to modules that
108 are pre-registered to
110 types. If you haven’t
111 specifically registered
112 to handle a MIME type or
113 aren’t positive this
115 implementation of this
116 function can just return
132 <tr class="row-odd"><td><code>HandleInputEvent</code></td>
133 <td>Called when a user
135 module’s instance in the
136 browser using an input
137 device such as a mouse
138 or keyboard. You must
139 register your module to
142 <code>RequestInputEvents()</code>
144 <code>RequestFilteringInputEvents</code>
146 prior to overriding this
148 <td>An implementation of
152 branches accordingly.</td>
156 <p>These interfaces are found in the <a class="reference external" href="/native-client/pepper_stable/cpp/classpp_1_1_instance">pp::Instance class</a>. The sections below
157 provide examples of how to handle these events.</p>
158 <h2 id="handling-browser-events">Handling browser events</h2>
159 <h3 id="didchangeview">DidChangeView()</h3>
160 <p>In the <code>mouse_lock</code> example, <code>DidChangeView()</code> checks the previous size
161 of instance’s rectangle versus the new size. It also compares
162 other state such as whether or not the app is running in full screen mode.
163 If none of the state has actually changed, no action is needed.
164 However, if the size of the view or other state has changed, it frees the
165 old graphics context and allocates a new one.</p>
166 <pre class="prettyprint">
167 void MouseLockInstance::DidChangeView(const pp::View& view) {
168 // DidChangeView can get called for many reasons, so we only want to
169 // rebuild the device context if we really need to.
170 if ((size_ == view.GetRect().size()) &&
171 (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) {
177 // Reallocate the graphics context.
178 size_ = view.GetRect().size();
179 device_context_ = pp::Graphics2D(this, size_, false);
180 waiting_for_flush_completion_ = false;
182 is_context_bound_ = BindGraphics(device_context_);
185 // Remember if we are fullscreen or not
186 was_fullscreen_ = view.IsFullscreen();
190 <p>For more information about graphics contexts and how to manipulate images, see:</p>
191 <ul class="small-gap">
192 <li><a class="reference external" href="/native-client/pepper_stable/cpp/classpp_1_1_image_data">pp::ImageData class</a></li>
193 <li><a class="reference external" href="/native-client/pepper_stable/cpp/classpp_1_1_graphics2_d">pp::Graphics2D class</a></li>
195 <h3 id="didchangefocus">DidChangeFocus()</h3>
196 <p><code>DidChangeFocus()</code> is called when you click inside or outside of a
197 module’s instance in the web page. When the instance goes out
198 of focus (click outside of the instance), you might do something
199 like stop an animation. When the instance regains focus, you can
200 restart the animation.</p>
201 <pre class="prettyprint">
202 void DidChangeFocus(bool focus) {
203 // Do something like stopping animation or a blinking cursor in
207 <h2 id="handling-input-events">Handling input events</h2>
208 <p>Input events are events that occur when the user interacts with a
209 module instance using the mouse, keyboard, or other input device
210 (e.g., touch screen). This section describes how the <code>input_events</code>
211 example handles input events.</p>
212 <h3 id="registering-a-module-to-accept-input-events">Registering a module to accept input events</h3>
213 <p>Before your module can handle these events, you must register your
214 module to accept input events using <code>RequestInputEvents()</code> for mouse
215 events and <code>RequestFilteringInputEvents()</code> for keyboard events. For the
216 <code>input_events</code> example, this is done in the constructor of the
217 <code>InputEventInstance</code> class:</p>
218 <pre class="prettyprint">
219 class InputEventInstance : public pp::Instance {
221 explicit InputEventInstance(PP_Instance instance)
222 : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) {
223 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL |
224 PP_INPUTEVENT_CLASS_TOUCH);
225 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
230 <p><code>RequestInputEvents()</code> and <code>RequestFilteringInputEvents()</code> accept a
231 combination of flags that identify the class of events that the instance is
232 requesting to receive. Input event classes are defined in the
233 <a class="reference external" href="/native-client/pepper_stable/c/group___enums.html#gafe68e3c1031daa4a6496845ff47649cd">PP_InputEvent_Class</a>
234 enumeration in <a class="reference external" href="/native-client/pepper_stable/c/ppb__input__event_8h">ppb_input_event.h</a>.</p>
235 <h3 id="determining-and-branching-on-event-types">Determining and branching on event types</h3>
236 <p>In a typical implementation, the <code>HandleInputEvent()</code> function determines the
237 type of each event using the <code>GetType()</code> function found in the <code>InputEvent</code>
238 class. The <code>HandleInputEvent()</code> function then uses a switch statement to
239 branch on the type of input event. Input events are defined in the
240 <a class="reference external" href="/native-client/pepper_stable/c/group___enums.html#gaca7296cfec99fcb6646b7144d1d6a0c5">PP_InputEvent_Type</a>
241 enumeration in <a class="reference external" href="/native-client/pepper_stable/c/ppb__input__event_8h">ppb_input_event.h</a>.</p>
242 <pre class="prettyprint">
243 virtual bool HandleInputEvent(const pp::InputEvent& event) {
244 Event* event_ptr = NULL;
245 switch (event.GetType()) {
246 case PP_INPUTEVENT_TYPE_UNDEFINED:
248 case PP_INPUTEVENT_TYPE_MOUSEDOWN:
249 case PP_INPUTEVENT_TYPE_MOUSEUP:
250 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
251 case PP_INPUTEVENT_TYPE_MOUSEENTER:
252 case PP_INPUTEVENT_TYPE_MOUSELEAVE:
253 case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
254 pp::MouseInputEvent mouse_event(event);
255 PP_InputEvent_MouseButton pp_button = mouse_event.GetButton();
256 MouseEvent::MouseButton mouse_button = MouseEvent::kNone;
258 case PP_INPUTEVENT_MOUSEBUTTON_NONE:
259 mouse_button = MouseEvent::kNone;
261 case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
262 mouse_button = MouseEvent::kLeft;
264 case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
265 mouse_button = MouseEvent::kMiddle;
267 case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
268 mouse_button = MouseEvent::kRight;
272 new MouseEvent(ConvertEventModifier(mouse_event.GetModifiers()),
274 mouse_event.GetPosition().x(),
275 mouse_event.GetPosition().y(),
276 mouse_event.GetClickCount(),
277 mouse_event.GetTimeStamp(),
278 event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU);
280 case PP_INPUTEVENT_TYPE_WHEEL: {
281 pp::WheelInputEvent wheel_event(event);
283 new WheelEvent(ConvertEventModifier(wheel_event.GetModifiers()),
284 wheel_event.GetDelta().x(),
285 wheel_event.GetDelta().y(),
286 wheel_event.GetTicks().x(),
287 wheel_event.GetTicks().y(),
288 wheel_event.GetScrollByPage(),
289 wheel_event.GetTimeStamp());
291 case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
292 case PP_INPUTEVENT_TYPE_KEYDOWN:
293 case PP_INPUTEVENT_TYPE_KEYUP:
294 case PP_INPUTEVENT_TYPE_CHAR: {
295 pp::KeyboardInputEvent key_event(event);
296 event_ptr = new KeyEvent(ConvertEventModifier(key_event.GetModifiers()),
297 key_event.GetKeyCode(),
298 key_event.GetTimeStamp(),
299 key_event.GetCharacterText().DebugString());
302 // For any unhandled events, send a message to the browser
303 // so that the user is aware of these and can investigate.
304 std::stringstream oss;
305 oss << "Default (unhandled) event, type=" << event.GetType();
306 PostMessage(oss.str());
309 event_queue_.Push(event_ptr);
313 <p>Notice that the generic <code>InputEvent</code> received by <code>HandleInputEvent()</code> is
314 converted into a specific type after the event type is
315 determined. The event types handled in the example code are
316 <code>MouseInputEvent</code>, <code>WheelInputEvent</code>, and <code>KeyboardInputEvent</code>.
317 There are also <code>TouchInputEvents</code>. For the latest list of event types,
318 see the <a class="reference external" href="/native-client/pepper_stable/c/classpp_1_1_input_event">InputEvent documentation</a>.
319 For reference information related to the these event classes, see the
320 following documentation:</p>
321 <ul class="small-gap">
322 <li><a class="reference external" href="/native-client/pepper_stable/c/classpp_1_1_mouse_input_event">pp::MouseInputEvent class</a></li>
323 <li><a class="reference external" href="/native-client/pepper_stable/c/classpp_1_1_wheel_input_event">pp::WheelInputEvent class</a></li>
324 <li><a class="reference external" href="/native-client/pepper_stable/c/classpp_1_1_keyboard_input_event">pp::KeyboardInputEvent class</a></li>
326 <h3 id="threading-and-blocking">Threading and blocking</h3>
327 <p><code>HandleInputEvent()</code> in this example runs on the main module thread.
328 However, the bulk of the work happens on a separate worker thread (see
329 <code>ProcessEventOnWorkerThread</code>). <code>HandleInputEvent()</code> puts events in
330 the <code>event_queue_</code> and the worker thread takes events from the
331 <code>event_queue_</code>. This processing happens independently of the main
332 thread, so as not to slow down the browser.</p>
335 {{/partials.standard_nacl_api}}