OLD | NEW |
(Empty) | |
| 1 {{+bindTo:partials.standard_nacl_article}} |
| 2 |
| 3 <section id="view-change-focus-and-input-events"> |
| 4 <span id="view-focus-input-events"></span><h1 id="view-change-focus-and-input-ev
ents"><span id="view-focus-input-events"></span>View Change, Focus, and Input Ev
ents</h1> |
| 5 <div class="contents local topic" id="contents"> |
| 6 <ul class="small-gap"> |
| 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-event
s" id="id3">Handling browser events</a></p> |
| 9 <ul class="small-gap"> |
| 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> |
| 12 </ul> |
| 13 </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-ev
ents" id="id7">Registering a module to accept input events</a></li> |
| 17 <li><a class="reference internal" href="#determining-and-branching-on-event-type
s" id="id8">Determining and branching on event types</a></li> |
| 18 <li><a class="reference internal" href="#threading-and-blocking" id="id9">Thread
ing and blocking</a></li> |
| 19 </ul> |
| 20 </li> |
| 21 </ul> |
| 22 </div> |
| 23 <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/ove
rview.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 modul
e |
| 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 <section id="overview"> |
| 38 <h2 id="overview">Overview</h2> |
| 39 <p>When a user interacts with the web page using a keyboard, mouse or |
| 40 some other input device, the browser generates input events. |
| 41 In a traditional web application, these input events are |
| 42 passed to and handled in JavaScript, typically through event listeners |
| 43 and event handlers. In a Native Client application, user interaction |
| 44 with an instance of a module (e.g., clicking inside the rectangle |
| 45 managed by a module) also generates input events, which are passed to |
| 46 the module. The browser also passes view change and focus events that |
| 47 affect a module’s instance to the module. Native Client modules can |
| 48 override certain functions in the <a class="reference external" href="https://de
velopers.google.com/native-client/peppercpp/classpp_1_1_instance">pp::Instance</
a> |
| 49 class to handle input and browser events. These functions are listed in |
| 50 the table below:</p> |
| 51 <table border="1" class="docutils"> |
| 52 <colgroup> |
| 53 </colgroup> |
| 54 <thead valign="bottom"> |
| 55 <tr class="row-odd"><th class="head">Function</th> |
| 56 <th class="head">Event</th> |
| 57 <th class="head">Use</th> |
| 58 </tr> |
| 59 </thead> |
| 60 <tbody valign="top"> |
| 61 <tr class="row-even"><td><code>DidChangeView</code></td> |
| 62 <td>Called when the position, |
| 63 size, or clip rectangle |
| 64 of the module’s instance in |
| 65 the browser has changed. |
| 66 This event also occurs |
| 67 when browser window is |
| 68 resized or mouse wheel |
| 69 is scrolled.</td> |
| 70 <td>An implementation |
| 71 of this function |
| 72 might check the size |
| 73 of the module |
| 74 instance’s rectangle |
| 75 has changed and |
| 76 reallocate the |
| 77 graphics context |
| 78 when a different |
| 79 size is received.</td> |
| 80 </tr> |
| 81 <tr class="row-odd"><td><code>DidChangeFocus</code></td> |
| 82 <td>Called when the module’s |
| 83 instance in the browser |
| 84 has gone in or out of |
| 85 focus (usually by |
| 86 clicking inside or |
| 87 outside the module |
| 88 instance). Having focus |
| 89 means that keyboard |
| 90 events will be sent to |
| 91 the module instance. |
| 92 An instance’s default |
| 93 condition is that it |
| 94 does not have focus.</td> |
| 95 <td>An implementation |
| 96 of this function |
| 97 might start or stop |
| 98 an animation or a |
| 99 blinking cursor.</td> |
| 100 </tr> |
| 101 <tr class="row-even"><td><code>HandleDocumentLoad</code></td> |
| 102 <td>Called after |
| 103 <code>pp::Instance::Init()</code> |
| 104 for a full-frame module |
| 105 instance that was |
| 106 instantiated based on |
| 107 the MIME type of a |
| 108 DOMWindow navigation. |
| 109 This situation only |
| 110 applies to modules that |
| 111 are pre-registered to |
| 112 handle certain MIME |
| 113 types. If you haven’t |
| 114 specifically registered |
| 115 to handle a MIME type or |
| 116 aren’t positive this |
| 117 applies to you, your |
| 118 implementation of this |
| 119 function can just return |
| 120 false.</td> |
| 121 <td>This API is only |
| 122 applicable when you |
| 123 are writing an |
| 124 extension to enhance |
| 125 the abilities of |
| 126 the Chrome web |
| 127 browser. For |
| 128 example, a PDF |
| 129 viewer might |
| 130 implement this |
| 131 function to download |
| 132 and display a PDF |
| 133 file.</td> |
| 134 </tr> |
| 135 <tr class="row-odd"><td><code>HandleInputEvent</code></td> |
| 136 <td>Called when a user |
| 137 interacts with the |
| 138 module’s instance in the |
| 139 browser using an input |
| 140 device such as a mouse |
| 141 or keyboard. You must |
| 142 register your module to |
| 143 accept input events |
| 144 using |
| 145 <code>RequestInputEvents()</code> |
| 146 for mouse events and |
| 147 <code>RequestFilteringInputEvents</code> |
| 148 for keyboard events |
| 149 prior to overriding this |
| 150 function.</td> |
| 151 <td>An implementation of |
| 152 this function |
| 153 examines the input |
| 154 event type and |
| 155 branches accordingly.</td> |
| 156 </tr> |
| 157 </tbody> |
| 158 </table> |
| 159 <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::Ins
tance class</a>. |
| 160 The sections below provide examples of how to handle these events.</p> |
| 161 </section><section id="handling-browser-events"> |
| 162 <h2 id="handling-browser-events">Handling browser events</h2> |
| 163 <section id="didchangeview"> |
| 164 <h3 id="didchangeview">DidChangeView()</h3> |
| 165 <p>In the <code>mouse_lock</code> example, <code>DidChangeView()</code> checks t
he previous size |
| 166 of instance’s rectangle versus the new size. It also compares |
| 167 other state such as whether or not the app is running in full screen mode. |
| 168 If none of the state has actually changed, no action is needed. |
| 169 However, if the size of the view or other state has changed, it frees the |
| 170 old graphics context and allocates a new one.</p> |
| 171 <pre class="prettyprint"> |
| 172 void MouseLockInstance::DidChangeView(const pp::View& view) { |
| 173 // DidChangeView can get called for many reasons, so we only want to |
| 174 // rebuild the device context if we really need to. |
| 175 if ((size_ == view.GetRect().size()) && |
| 176 (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) { |
| 177 return; |
| 178 } |
| 179 |
| 180 // ... |
| 181 |
| 182 // Reallocate the graphics context. |
| 183 size_ = view.GetRect().size(); |
| 184 device_context_ = pp::Graphics2D(this, size_, false); |
| 185 waiting_for_flush_completion_ = false; |
| 186 |
| 187 is_context_bound_ = BindGraphics(device_context_); |
| 188 // ... |
| 189 |
| 190 // Remember if we are fullscreen or not |
| 191 was_fullscreen_ = view.IsFullscreen(); |
| 192 // ... |
| 193 } |
| 194 </pre> |
| 195 <p>For more information about graphics contexts and how to manipulate images, se
e:</p> |
| 196 <ul class="small-gap"> |
| 197 <li><a class="reference external" href="https://developers.google.com/native-cli
ent/dev/peppercpp/classpp_1_1_image_data">pp::ImageData class</a></li> |
| 198 <li><a class="reference external" href="https://developers.google.com/native-cli
ent/dev/peppercpp/classpp_1_1_graphics2_d">pp::Graphics2D class</a></li> |
| 199 </ul> |
| 200 </section><section id="didchangefocus"> |
| 201 <h3 id="didchangefocus">DidChangeFocus()</h3> |
| 202 <p><code>DidChangeFocus()</code> is called when you click inside or outside of a |
| 203 module’s instance in the web page. When the instance goes out |
| 204 of focus (click outside of the instance), you might do something |
| 205 like stop an animation. When the instance regains focus, you can |
| 206 restart the animation.</p> |
| 207 <pre class="prettyprint"> |
| 208 void DidChangeFocus(bool focus) { |
| 209 // Do something like stopping animation or a blinking cursor in |
| 210 // the instance. |
| 211 } |
| 212 </pre> |
| 213 </section></section><section id="handling-input-events"> |
| 214 <h2 id="handling-input-events">Handling input events</h2> |
| 215 <p>Input events are events that occur when the user interacts with a |
| 216 module instance using the mouse, keyboard, or other input device |
| 217 (e.g., touch screen). This section describes how the <code>input_events</code> |
| 218 example handles input events.</p> |
| 219 <section id="registering-a-module-to-accept-input-events"> |
| 220 <h3 id="registering-a-module-to-accept-input-events">Registering a module to acc
ept input events</h3> |
| 221 <p>Before your module can handle these events, you must register your |
| 222 module to accept input events using <code>RequestInputEvents()</code> for mouse |
| 223 events and <code>RequestFilteringInputEvents()</code> for keyboard events. For t
he |
| 224 <code>input_events</code> example, this is done in the constructor of the |
| 225 <code>InputEventInstance</code> class:</p> |
| 226 <pre class="prettyprint"> |
| 227 class InputEventInstance : public pp::Instance { |
| 228 public: |
| 229 explicit InputEventInstance(PP_Instance instance) |
| 230 : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) { |
| 231 RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL | |
| 232 PP_INPUTEVENT_CLASS_TOUCH); |
| 233 RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); |
| 234 } |
| 235 // ... |
| 236 }; |
| 237 </pre> |
| 238 <p><code>RequestInputEvents()</code> and <code>RequestFilteringInputEvents()</co
de> accept a |
| 239 combination of flags that identify the class of events that the |
| 240 instance is requesting to receive. Input event classes are defined in |
| 241 the <a class="reference external" href="https://developers.google.com/native-cli
ent/dev/pepperc/group___enums.html#gafe68e3c1031daa4a6496845ff47649cd">PP_InputE
vent_Class</a> |
| 242 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> |
| 243 </section><section id="determining-and-branching-on-event-types"> |
| 244 <h3 id="determining-and-branching-on-event-types">Determining and branching on e
vent types</h3> |
| 245 <p>In a typical implementation, the <code>HandleInputEvent()</code> function |
| 246 determines the type of each event using the <code>GetType()</code> function foun
d |
| 247 in the <code>InputEvent</code> class. The <code>HandleInputEvent()</code> functi
on then uses a |
| 248 switch statement to branch on the type of input event. Input events |
| 249 are defined in the <a class="reference external" href="https://developers.google
.com/native-client/dev/pepperc/group___enums.html#gaca7296cfec99fcb6646b7144d1d6
a0c5">PP_InputEvent_Type</a> |
| 250 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> |
| 251 <pre class="prettyprint"> |
| 252 virtual bool HandleInputEvent(const pp::InputEvent& event) { |
| 253 Event* event_ptr = NULL; |
| 254 switch (event.GetType()) { |
| 255 case PP_INPUTEVENT_TYPE_UNDEFINED: |
| 256 break; |
| 257 case PP_INPUTEVENT_TYPE_MOUSEDOWN: |
| 258 case PP_INPUTEVENT_TYPE_MOUSEUP: |
| 259 case PP_INPUTEVENT_TYPE_MOUSEMOVE: |
| 260 case PP_INPUTEVENT_TYPE_MOUSEENTER: |
| 261 case PP_INPUTEVENT_TYPE_MOUSELEAVE: |
| 262 case PP_INPUTEVENT_TYPE_CONTEXTMENU: { |
| 263 pp::MouseInputEvent mouse_event(event); |
| 264 PP_InputEvent_MouseButton pp_button = mouse_event.GetButton(); |
| 265 MouseEvent::MouseButton mouse_button = MouseEvent::kNone; |
| 266 switch (pp_button) { |
| 267 case PP_INPUTEVENT_MOUSEBUTTON_NONE: |
| 268 mouse_button = MouseEvent::kNone; |
| 269 break; |
| 270 case PP_INPUTEVENT_MOUSEBUTTON_LEFT: |
| 271 mouse_button = MouseEvent::kLeft; |
| 272 break; |
| 273 case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE: |
| 274 mouse_button = MouseEvent::kMiddle; |
| 275 break; |
| 276 case PP_INPUTEVENT_MOUSEBUTTON_RIGHT: |
| 277 mouse_button = MouseEvent::kRight; |
| 278 break; |
| 279 } |
| 280 event_ptr = |
| 281 new MouseEvent(ConvertEventModifier(mouse_event.GetModifiers()), |
| 282 mouse_button, |
| 283 mouse_event.GetPosition().x(), |
| 284 mouse_event.GetPosition().y(), |
| 285 mouse_event.GetClickCount(), |
| 286 mouse_event.GetTimeStamp(), |
| 287 event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU); |
| 288 } break; |
| 289 case PP_INPUTEVENT_TYPE_WHEEL: { |
| 290 pp::WheelInputEvent wheel_event(event); |
| 291 event_ptr = |
| 292 new WheelEvent(ConvertEventModifier(wheel_event.GetModifiers()), |
| 293 wheel_event.GetDelta().x(), |
| 294 wheel_event.GetDelta().y(), |
| 295 wheel_event.GetTicks().x(), |
| 296 wheel_event.GetTicks().y(), |
| 297 wheel_event.GetScrollByPage(), |
| 298 wheel_event.GetTimeStamp()); |
| 299 } break; |
| 300 case PP_INPUTEVENT_TYPE_RAWKEYDOWN: |
| 301 case PP_INPUTEVENT_TYPE_KEYDOWN: |
| 302 case PP_INPUTEVENT_TYPE_KEYUP: |
| 303 case PP_INPUTEVENT_TYPE_CHAR: { |
| 304 pp::KeyboardInputEvent key_event(event); |
| 305 event_ptr = new KeyEvent(ConvertEventModifier(key_event.GetModifiers()), |
| 306 key_event.GetKeyCode(), |
| 307 key_event.GetTimeStamp(), |
| 308 key_event.GetCharacterText().DebugString()); |
| 309 } break; |
| 310 default: { |
| 311 // For any unhandled events, send a message to the browser |
| 312 // so that the user is aware of these and can investigate. |
| 313 std::stringstream oss; |
| 314 oss << "Default (unhandled) event, type=" << event.G
etType(); |
| 315 PostMessage(oss.str()); |
| 316 } break; |
| 317 } |
| 318 event_queue_.Push(event_ptr); |
| 319 return true; |
| 320 } |
| 321 </pre> |
| 322 <p>Notice that the generic <code>InputEvent</code> received by <code>HandleInput
Event()</code> is |
| 323 converted into a specific type after the event type is |
| 324 determined. The event types handled in the example code are |
| 325 <code>MouseInputEvent</code>, <code>WheelInputEvent</code>, and <code>KeyboardIn
putEvent</code>. |
| 326 There are also <code>TouchInputEvents</code>. For the latest list of event type
s, |
| 327 see the <a class="reference external" href="https://developers.google.com/native
-client/dev/peppercpp/classpp_1_1_input_event">InputEvent documentation</a>. |
| 328 For reference information related to the these event classes, see the |
| 329 following documentation:</p> |
| 330 <ul class="small-gap"> |
| 331 <li><a class="reference external" href="https://developers.google.com/native-cli
ent/dev/peppercpp/classpp_1_1_mouse_input_event">pp::MouseInputEvent class</a></
li> |
| 332 <li><a class="reference external" href="https://developers.google.com/native-cli
ent/dev/peppercpp/classpp_1_1_wheel_input_event">pp::WheelInputEvent class</a></
li> |
| 333 <li><a class="reference external" href="https://developers.google.com/native-cli
ent/dev/peppercpp/classpp_1_1_keyboard_input_event">pp::KeyboardInputEvent class
</a></li> |
| 334 </ul> |
| 335 </section><section id="threading-and-blocking"> |
| 336 <h3 id="threading-and-blocking">Threading and blocking</h3> |
| 337 <p><code>HandleInputEvent()</code> in this example runs on the main module threa
d. |
| 338 However, the bulk of the work happens on a separate worker thread (see |
| 339 <code>ProcessEventOnWorkerThread</code>). <code>HandleInputEvent()</code> puts e
vents in |
| 340 the <code>event_queue_</code> and the worker thread takes events from the |
| 341 <code>event_queue_</code>. This processing happens independently of the main |
| 342 thread, so as not to slow down the browser.</p> |
| 343 </section></section></section> |
| 344 |
| 345 {{/partials.standard_nacl_article}} |
OLD | NEW |