Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / native_client_sdk / src / doc / devguide / coding / view-focus-input-events.rst
blob57d45c4aa9dd6bdc8cd1dd33cb60b0ca8ba57873
1 .. _view_focus_input_events:
3 ####################################
4 View Change, Focus, and Input Events
5 ####################################
7 .. contents::
8   :local:
9   :backlinks: none
10   :depth: 2
12 This section describes view change, focus, and input event handling for a
13 Native Client module. The section assumes you are familiar with the
14 material presented in the :doc:`Technical Overview <../../overview>`.
16 There are two examples used in this section to illustrate basic
17 programming techniques. The ``input_events`` example is used to
18 illustrate how your module can react to keyboard and mouse input
19 event.  The ``mouse_lock`` example is used to illustrate how your module
20 can react to view change events. You can find these examples in the
21 ``/pepper_<version>/examples/api/input_event`` and 
22 ``/pepper_<version>/examples/api/mouse_lock`` directories in the Native Client
23 SDK.  There is also the ppapi_simple library that can be used to to implement
24 most of the boiler plate.  The ``pi_generator`` example in
25 ``/pepper_<version>/examples/demo/pi_generator`` uses ppapi_simple to manage
26 view change events and 2D graphics.
29 Overview
30 ========
32 When a user interacts with the web page using a keyboard, mouse or some other
33 input device, the browser generates input events.  In a traditional web
34 application, these input events are passed to and handled in JavaScript,
35 typically through event listeners and event handlers. In a Native Client
36 application, user interaction with an instance of a module (e.g., clicking
37 inside the rectangle managed by a module) also generates input events, which
38 are passed to the module. The browser also passes view change and focus events
39 that affect a module's instance to the module. Native Client modules can
40 override certain functions in the `pp::Instance
41 </native-client/pepper_stable/cpp/classpp_1_1_instance>`_ class to handle input
42 and browser events. These functions are listed in the table below:
44 +-------------------------------------+----------------------------------------+
45 | Function                            | Use                                    |
46 +=====================================+========================================+
47 |``DidChangeView``                    |An implementation of this function might|
48 |  Called when the position, size, or |check the size of the module instance's |
49 |  clip rectangle of the module's     |rectangle has changed and reallocate the|
50 |  instance in the browser has        |graphcs context when a different size is|
51 |  changed. This event also occurs    |received.                               |
52 |  when the browser window is resized |                                        |
53 |  or the mouse wheel is scrolled.    |                                        |
54 +-------------------------------------+----------------------------------------+
55 |``DidChangeFocus``                   |An implementation of this function might|
56 |  Called when the module's instance  |start or stop an animation or a blinking|
57 |  in the browser has gone in or out  |cursor.                                 |
58 |  of focus (usually by clicking      |                                        |
59 |  inside or outside the module       |                                        |
60 |  instance). Having focus means that |                                        |
61 |  keyboard events will be sent to the|                                        |
62 |  module instance. An instance's     |                                        |
63 |  default condition is that it does  |                                        |
64 |  not have focus.                    |                                        |
65 +-------------------------------------+----------------------------------------+
66 |``HandleDocumentLoad``               |This API is only applicable when you are|
67 |  ``pp::Instance::Init()`` for a     |writing an extension to enhance the     |
68 |  full-frame module instance that was|abilities of the Chrome web browser. For|
69 |  instantiated based on the MIME     |example, a PDF viewer might implement   |
70 |  type of a DOMWindow navigation.    |this function to download and display a |
71 |  This situation only applies to     |PDF file.                               |
72 |  modules that are pre-registered to |                                        |
73 |  handle certain MIME types. If you  |                                        |
74 |  haven't specifically registered to |                                        |
75 |  handle a MIME type or aren't       |                                        |
76 |  positive this applies to you, your |                                        |
77 |  implementation of this function can|                                        |
78 |  just return false.                 |                                        |
79 +-------------------------------------+----------------------------------------+
80 |``HandleInputEvent``                 |An implementation of this function      |
81 |  Called when a user interacts with  |examines the input event type and       |
82 |  the module's instance in the       |branches accordingly.                   |
83 |  browser using an input device such |                                        |
84 |  as a mouse or keyboard. You must   |                                        |
85 |  register your module to accept     |                                        |
86 |  input events using                 |                                        |
87 |  ``RequestInputEvents()``           |                                        |
88 |  for mouse events and               |                                        |
89 |  ``RequestFilteringInputEvents()``  |                                        |
90 |  for keyboard events prior to       |                                        |
91 |  overriding this function.          |                                        |
92 +-------------------------------------+----------------------------------------+
95 These interfaces are found in the `pp::Instance class
96 </native-client/pepper_stable/cpp/classpp_1_1_instance>`_.  The sections below
97 provide examples of how to handle these events.
100 Handling browser events
101 =======================
103 DidChangeView()
104 ---------------
106 In the ``mouse_lock`` example, ``DidChangeView()`` checks the previous size
107 of instance's rectangle versus the new size.  It also compares
108 other state such as whether or not the app is running in full screen mode.
109 If none of the state has actually changed, no action is needed.
110 However, if the size of the view or other state has changed, it frees the
111 old graphics context and allocates a new one.
113 .. naclcode::
115   void MouseLockInstance::DidChangeView(const pp::View& view) {
116     // DidChangeView can get called for many reasons, so we only want to
117     // rebuild the device context if we really need to.
118     if ((size_ == view.GetRect().size()) &&
119         (was_fullscreen_ == view.IsFullscreen()) && is_context_bound_) {
120       return;
121     }
123     // ...
125     // Reallocate the graphics context.
126     size_ = view.GetRect().size();
127     device_context_ = pp::Graphics2D(this, size_, false);
128     waiting_for_flush_completion_ = false;
130     is_context_bound_ = BindGraphics(device_context_);
131     // ...
133     // Remember if we are fullscreen or not
134     was_fullscreen_ = view.IsFullscreen();
135     // ...
136   }
139 For more information about graphics contexts and how to manipulate images, see:
141 * `pp::ImageData class
142   </native-client/pepper_stable/cpp/classpp_1_1_image_data>`_
143 * `pp::Graphics2D class
144   </native-client/pepper_stable/cpp/classpp_1_1_graphics2_d>`_
147 DidChangeFocus()
148 ----------------
150 ``DidChangeFocus()`` is called when you click inside or outside of a
151 module's instance in the web page. When the instance goes out
152 of focus (click outside of the instance), you might do something
153 like stop an animation. When the instance regains focus, you can
154 restart the animation.
156 .. naclcode::
158   void DidChangeFocus(bool focus) {
159     // Do something like stopping animation or a blinking cursor in
160     // the instance.
161   }
164 Handling input events
165 =====================
167 Input events are events that occur when the user interacts with a
168 module instance using the mouse, keyboard, or other input device
169 (e.g., touch screen). This section describes how the ``input_events``
170 example handles input events.
173 Registering a module to accept input events
174 -------------------------------------------
176 Before your module can handle these events, you must register your
177 module to accept input events using ``RequestInputEvents()`` for mouse
178 events and ``RequestFilteringInputEvents()`` for keyboard events. For the
179 ``input_events`` example, this is done in the constructor of the
180 ``InputEventInstance`` class:
182 .. naclcode::
184   class InputEventInstance : public pp::Instance {
185    public:
186     explicit InputEventInstance(PP_Instance instance)
187         : pp::Instance(instance), event_thread_(NULL), callback_factory_(this) {
188       RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL |
189                          PP_INPUTEVENT_CLASS_TOUCH);
190       RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
191     }
192     // ...
193   };
196 ``RequestInputEvents()`` and ``RequestFilteringInputEvents()`` accept a
197 combination of flags that identify the class of events that the instance is
198 requesting to receive. Input event classes are defined in the
199 `PP_InputEvent_Class
200 </native-client/pepper_stable/c/group___enums.html#gafe68e3c1031daa4a6496845ff47649cd>`_
201 enumeration in `ppb_input_event.h
202 </native-client/pepper_stable/c/ppb__input__event_8h>`_.
205 Determining and branching on event types
206 ----------------------------------------
208 In a typical implementation, the ``HandleInputEvent()`` function determines the
209 type of each event using the ``GetType()`` function found in the ``InputEvent``
210 class. The ``HandleInputEvent()`` function then uses a switch statement to
211 branch on the type of input event. Input events are defined in the
212 `PP_InputEvent_Type
213 </native-client/pepper_stable/c/group___enums.html#gaca7296cfec99fcb6646b7144d1d6a0c5>`_
214 enumeration in `ppb_input_event.h
215 </native-client/pepper_stable/c/ppb__input__event_8h>`_.
217 .. naclcode::
219   virtual bool HandleInputEvent(const pp::InputEvent& event) {
220     Event* event_ptr = NULL;
221     switch (event.GetType()) {
222       case PP_INPUTEVENT_TYPE_UNDEFINED:
223         break;
224       case PP_INPUTEVENT_TYPE_MOUSEDOWN:
225       case PP_INPUTEVENT_TYPE_MOUSEUP:
226       case PP_INPUTEVENT_TYPE_MOUSEMOVE:
227       case PP_INPUTEVENT_TYPE_MOUSEENTER:
228       case PP_INPUTEVENT_TYPE_MOUSELEAVE:
229       case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
230         pp::MouseInputEvent mouse_event(event);
231         PP_InputEvent_MouseButton pp_button = mouse_event.GetButton();
232         MouseEvent::MouseButton mouse_button = MouseEvent::kNone;
233         switch (pp_button) {
234           case PP_INPUTEVENT_MOUSEBUTTON_NONE:
235             mouse_button = MouseEvent::kNone;
236             break;
237           case PP_INPUTEVENT_MOUSEBUTTON_LEFT:
238             mouse_button = MouseEvent::kLeft;
239             break;
240           case PP_INPUTEVENT_MOUSEBUTTON_MIDDLE:
241             mouse_button = MouseEvent::kMiddle;
242             break;
243           case PP_INPUTEVENT_MOUSEBUTTON_RIGHT:
244             mouse_button = MouseEvent::kRight;
245             break;
246         }
247         event_ptr =
248             new MouseEvent(ConvertEventModifier(mouse_event.GetModifiers()),
249                            mouse_button,
250                            mouse_event.GetPosition().x(),
251                            mouse_event.GetPosition().y(),
252                            mouse_event.GetClickCount(),
253                            mouse_event.GetTimeStamp(),
254                            event.GetType() == PP_INPUTEVENT_TYPE_CONTEXTMENU);
255       } break;
256       case PP_INPUTEVENT_TYPE_WHEEL: {
257         pp::WheelInputEvent wheel_event(event);
258         event_ptr =
259             new WheelEvent(ConvertEventModifier(wheel_event.GetModifiers()),
260                            wheel_event.GetDelta().x(),
261                            wheel_event.GetDelta().y(),
262                            wheel_event.GetTicks().x(),
263                            wheel_event.GetTicks().y(),
264                            wheel_event.GetScrollByPage(),
265                            wheel_event.GetTimeStamp());
266       } break;
267       case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
268       case PP_INPUTEVENT_TYPE_KEYDOWN:
269       case PP_INPUTEVENT_TYPE_KEYUP:
270       case PP_INPUTEVENT_TYPE_CHAR: {
271         pp::KeyboardInputEvent key_event(event);
272         event_ptr = new KeyEvent(ConvertEventModifier(key_event.GetModifiers()),
273                                  key_event.GetKeyCode(),
274                                  key_event.GetTimeStamp(),
275                                  key_event.GetCharacterText().DebugString());
276       } break;
277       default: {
278         // For any unhandled events, send a message to the browser
279         // so that the user is aware of these and can investigate.
280         std::stringstream oss;
281         oss << "Default (unhandled) event, type=" << event.GetType();
282         PostMessage(oss.str());
283       } break;
284     }
285     event_queue_.Push(event_ptr);
286     return true;
287   }
290 Notice that the generic ``InputEvent`` received by ``HandleInputEvent()`` is
291 converted into a specific type after the event type is
292 determined.  The event types handled in the example code are
293 ``MouseInputEvent``, ``WheelInputEvent``, and ``KeyboardInputEvent``.
294 There are also ``TouchInputEvents``.  For the latest list of event types,
295 see the `InputEvent documentation
296 </native-client/pepper_stable/c/classpp_1_1_input_event>`_.
297 For reference information related to the these event classes, see the
298 following documentation:
300 * `pp::MouseInputEvent class
301   </native-client/pepper_stable/c/classpp_1_1_mouse_input_event>`_
302 * `pp::WheelInputEvent class
303   </native-client/pepper_stable/c/classpp_1_1_wheel_input_event>`_
304 * `pp::KeyboardInputEvent class
305   </native-client/pepper_stable/c/classpp_1_1_keyboard_input_event>`_
308 Threading and blocking
309 ----------------------
311 ``HandleInputEvent()`` in this example runs on the main module thread.
312 However, the bulk of the work happens on a separate worker thread (see
313 ``ProcessEventOnWorkerThread``). ``HandleInputEvent()`` puts events in
314 the ``event_queue_`` and the worker thread takes events from the
315 ``event_queue_``. This processing happens independently of the main
316 thread, so as not to slow down the browser.