View Change, Focus, and Input Events

This section describes view change, focus, and input event handling for a
Native Client module. The section assumes you are familiar with the
material presented in the Technical Overview.

There are two examples used in this section to illustrate basic
programming techniques. The input_events example is used to
illustrate how your module can react to keyboard and mouse input
event. The mouse_lock example is used to illustrate how your module
can react to view change events. You can find these examples in the
/pepper_<version>/examples/api/input_event and
/pepper_<version>/examples/api/mouse_lock 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 pi_generator example in
/pepper_<version>/examples/demo/pi_generator uses ppapi_simple to manage
view change events and 2D graphics.

Overview

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 pp::Instance class to handle input
and browser events. These functions are listed in the table below:

Function

Use

DidChangeView

Called when the position, size, or
clip rectangle of the module’s
instance in the browser has
changed. This event also occurs
when the browser window is resized
or the mouse wheel is scrolled.

An implementation of this function might
check the size of the module instance’s
rectangle has changed and reallocate the
graphcs context when a different size is
received.

DidChangeFocus

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.

An implementation of this function might
start or stop an animation or a blinking
cursor.

HandleDocumentLoad

pp::Instance::Init() 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.

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.

HandleInputEvent

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
RequestInputEvents()
for mouse events and
RequestFilteringInputEvents()
for keyboard events prior to
overriding this function.

An implementation of this function
examines the input event type and
branches accordingly.

These interfaces are found in the pp::Instance class. The sections below
provide examples of how to handle these events.

Handling browser events

DidChangeView()

In the mouse_lock example, DidChangeView() 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.

DidChangeFocus()

DidChangeFocus() 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.

void DidChangeFocus(bool focus) {
// Do something like stopping animation or a blinking cursor in
// the instance.
}

Handling input events

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 input_events
example handles input events.

Registering a module to accept input events

Before your module can handle these events, you must register your
module to accept input events using RequestInputEvents() for mouse
events and RequestFilteringInputEvents() for keyboard events. For the
input_events example, this is done in the constructor of the
InputEventInstance class:

RequestInputEvents() and RequestFilteringInputEvents() 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
PP_InputEvent_Class
enumeration in ppb_input_event.h.

Determining and branching on event types

In a typical implementation, the HandleInputEvent() function determines the
type of each event using the GetType() function found in the InputEvent
class. The HandleInputEvent() function then uses a switch statement to
branch on the type of input event. Input events are defined in the
PP_InputEvent_Type
enumeration in ppb_input_event.h.

Notice that the generic InputEvent received by HandleInputEvent() is
converted into a specific type after the event type is
determined. The event types handled in the example code are
MouseInputEvent, WheelInputEvent, and KeyboardInputEvent.
There are also TouchInputEvents. For the latest list of event types,
see the InputEvent documentation.
For reference information related to the these event classes, see the
following documentation:

Threading and blocking

HandleInputEvent() in this example runs on the main module thread.
However, the bulk of the work happens on a separate worker thread (see
ProcessEventOnWorkerThread). HandleInputEvent() puts events in
the event_queue_ and the worker thread takes events from the
event_queue_. This processing happens independently of the main
thread, so as not to slow down the browser.