X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;ds=inline;f=doc%2FApplicationGuide.md;h=d66f20b4f4f112f3eb47dc51c531d0f2ddf5df3c;hb=c83642c69ede418f4c4d89daa0dae4b8698e0765;hp=25d87be52f11ec007457166bfbbaf1ba39fb3f7b;hpb=074d058a7a483a66af7f8c0b928b321ad483f47c;p=apps%2Fagl-service-windowmanager.git
diff --git a/doc/ApplicationGuide.md b/doc/ApplicationGuide.md
index 25d87be..d66f20b 100644
--- a/doc/ApplicationGuide.md
+++ b/doc/ApplicationGuide.md
@@ -1,10 +1,42 @@
**Window Manager Application Guide**
====
-
Revision: 0.2Beta
+Revision: 0.2Final
TOYOTA MOTOR CORPORATION
-30th/Sep/2017
+23rd/Oct/2017
* * *
+
+
+Table of content
+============
+- [Introduction](#Introduction)
+ - [Intended audience](#Intended\ audience)
+ - [Scope of this Document](#Scope\ of\ this\ Document)
+ - [Known Issues](#Known\ Issues)
+ - [External libraries](#External\ libraries)
+ - [Client Library](#Client\ Library)
+- [Concepts](#Concepts)
+ - [Layers](#Layers)
+ - [Surfaces](#Surfaces)
+- [Configuration](#Configuration)
+ - [Configuration Items](#Configuration\ Items)
+- [Building and Running](#Building\ and\ Running)
+ - [Dependencies](#Dependencies)
+ - [Build Configuration](#Build\ Configuration)
+- [Implementation Notes](#Implementation\ Notes)
+ - [Binding code generation](#Binding\ code\ generation)
+ - [Structure](#Structure)
+- [Sequence](#Sequence)
+- [Binding API](#Binding\ API)
+ - [LibWindowmanager](#LibWindowmanager)
+ - [Methods](#Methods)
+ - [Errors](#Errors)
+ - [Usage](#Usage)
+ - [Events](#Events)
+- [Sample](#Sample)
+
+
+
Introduction
============
@@ -12,12 +44,16 @@ Introduction
This WindowManager implements simple layout switching of applications on
multiple layers and with different layer layouts.
+
+
Intended audience
-----------------
This documentation is intended for developers and system integrators who
need to know, how the window manager works and how it is to be used.
+
+
Scope of this Document
----------------------
@@ -37,6 +73,8 @@ It does not include
It is highly recommended to have a good understanding of these documents
and projects before using the window manager.
+
+
Known Issues
------------
@@ -46,20 +84,23 @@ Currently there is a one known issues:
libwindowmanager library. This is a limitation of how Qt creates surface
IDs for the ivi-application interface.
+
+
External libraries
------------------
This project includes a copy of version 2.1.1 the excellent [C++11 JSON
library by Niels Lohmann](https://github.com/nlohmann/json).
+
+
Client Library
--------------
A client library implementation that internally uses the *libafbwsc*, is
-provided in the subdirectory `libwindowmanager/` with its own documentation
-directory.
+provided in the `libwindowmanager`.
-The client library is built together with the window manager itself.
+
Concepts
========
@@ -67,6 +108,8 @@ Concepts
The window manager implements a couple of concepts in order to allow
efficient implementation.
+
+
Layers
------
@@ -85,122 +128,29 @@ currently used layer.
It is possible to deactivate these surfaces on lower layers explicitly
using the `DeactivateSurface` API call.
+
+
Surfaces
--------
Surfaces are *placed* on layers according to their name. The surface
-will then be resized to dimensions, according to the layerâs layout
+will then be resized to dimensions, according to the layer's layout
configuration.
-Binding API
-===========
-
-The binding API consists of a couple of AFB *verbs* - that is; function
-calls to the Window Manager.
-
-Verbs (Functions)
------------------
-
-Each function returns a reply containing at least a failed or successful
-result of the call, additionally, when calls return something, it is
-noted. The notation used has the following meaning:
-
- FunctionName(argument_name: argument_type)[: function_return_type]
-
-Where the return type may be omitted if it is void.
-
-- `RequestSurface(drawing_name: string): int` Request a surface ID for
- the given name. This name and ID association will live until the
- surface is destroyed (or e.g. the application exits). Each surface
- that is managed by the window manager needs to call this function
- first!
-
-- `ActivateSurface(drawing_name: string)` This function requests the
- activation of a surface. It usually is not called by the
- application, but rather by the application framework or
- the HomeScreen.
-
-- `DeactivateSurface(drawing_name: string)` Request deactivation of
- a surface. This function is not usually called by applications
- themselves, but rather by the application framework or
- the HomeScreen.
-
-- `EndDraw(drawing_name: string)` Signals the window manager, that the
- surface is finished drawing. This is useful for consistent
- flicker-free layout switches, see the Architecture document
- for details.
-
-There are a couple of non-essential (mostly for debugging and
-development) API calls:
-
-- `list_drawing_names(): json` List known surface *name* to
- *ID* associations.
-
-- `ping()` Ping the window manager. Does also dispatch pending events
- if any.
-
-- `debug_status(): json` Returns a json representation of the current
- layers and surfaces known to the window manager. This represents the
- wayland-ivi-extension objectâs properties.
-
-- `debug_surfaces(): json` Returns a json representation of all
- surfaces known to the window manager. This represents the
- wayland-ivi-extension properties of the surfaces.
-
-- `debug_layers(): json` Returns the current layer configuration, as
- configured through *layers.json*.
-
-- `debug_terminate()` Terminates the afb-daemon running the window
- manager binding, if the environment variable
- `WINMAN_DEBUG_TERMINATE` is set.
-
-Events
-------
-
-The window manager broadcasts certain events (to all applications) that
-signal information on the state of the surface regarding the current
-layout.
-
-- `Active(drawing_name: string)` Signal that the surface with the name
- `drawing_name` is now active.
-
-- `Inactive(drawing_name: string)` Signal that the surface with the
- name `drawing_name` is now inactive. This usually means, the layout
- got changed, and the surface is now considered inactive
- (or sleeping).
-
-- `Visible(drawing_name: string)` Signal applications, that the
- surface with name `drawing_name` is now visible.
-
-- `Invisible(drawing_name: string)` Signal applications that the
- surface with name `drawing_name` is now invisible.
-
-- `SyncDraw(drawing_name: string)` Signal applications, that the
- surface with name `drawing_name` needs to redraw its content - this
- usually is sent when the surface geometry changed.
-
-- `FlushDraw(drawing_name: string)` Signal to applications, that the
- surface with name `drawing_name` can now be swapped to its newly
- drawn content as the window manager is ready to activate a new
- layout (i.e. a new surface geometry).
-
-Binding API Usage
------------------
-For a detailed description on how the binding API is supposed to be
-used, refer to the Architecture document.
+
Configuration
=============
The window manager is configured with the *layers.json* configuration
-file, by default it is searched in `/etc/layers.json` but through the
-use of the environment variable `LAYERS_JSON` the WM can be instructed
-to use different file. Note, that the WM will not run unless this
-configuration is found and valid.
+file, by default it is searched in `${AFM_APP_INSTALL_DIR}/etc/layers.json`.
+Note, that the WM will not run unless this configuration is found and valid.
A sample configuration is provided with the window manager
-implementation, this sample is installed to /etc/layers.json.
+implementation, this sample is installed to ${AFM_APP_INSTALL_DIR}/etc/layers.json.
+
+
Configuration Items
-------------------
@@ -231,30 +181,43 @@ This configuration item is a list of surface-name to layer mappings.
#### surface to layer mapping
"mappings": [
- {
- "role": "^HomeScreen$",
- "name": "HomeScreen",
- "layer_id": 1000,
- "area": { "type": "full" },
- },
- {
- "role": "MediaPlayer|Radio|Phone",
- "name": "apps",
- "layer_id": 1001,
- "area": { "type": "rect",
- "rect": { "x": 0,
- "y": 100,
- "width": -1,
- "height": -201 } },
- "split_layouts": []
- }
+ {
+ "role": "^HomeScreen$",
+ "name": "HomeScreen",
+ "layer_id": 1000,
+ "area": { "type": "full" },
+ "comment": "Single layer map for the HomeScreen"
+ },
+ {
+ "role": "MediaPlayer|Radio|Phone|Navigation|HVAC|Settings|Dashboard|POI|Mixer",
+ "name": "apps",
+ "layer_id": 1001,
+ "area": { "type": "rect", "rect": { "x": 0, "y": 218, "width": -1, "height": -433 } },
+ "comment": "Range of IDs that will always be placed on layer 1001, negative rect values are interpreted as output_size.dimension - $value",
+
+ "split_layouts": [
+ {
+ "name": "Navigation",
+ "main_match": "Navigation",
+ "sub_match": "HVAC|MediaPlayer",
+ "priority": 1000
+ }
+ ]
+ },
+ {
+ "role": "^OnScreen.*",
+ "name": "popups",
+ "layer_id": 9999,
+ "area": { "type": "rect", "rect": { "x": 0, "y": 760, "width": -1, "height": 400 } },
+ "comment": "Range of IDs that will always be placed on the popup layer, that gets a very high 'dummy' id of 9999"
+ }
]
Each mapping defines the following items to map corresponding surfaces
to a layer.
- `role` defines a regular expression that application drawing names
- are matched against. If applications match tis regular expression,
+ are matched against. If applications match this regular expression,
the surface will be visible on this layer.
- `name` is just a name definition for this layer, it has no
@@ -317,9 +280,9 @@ activated).
"split_layouts": [
{
- "name": "Media Player",
- "main_match": "^App MPlayer Main$",
- "sub_match": "^App MPlayer Sub",
+ "name": "Navigation",
+ "main_match": "Navigation",
+ "sub_match": "HVAC|MediaPlayer",
}
]
@@ -335,15 +298,19 @@ A split layout object has the following attributes:
surface of this layout.
In the above example only the surface with drawing name
-`App MPlayer Main` will be used as the *main* surface, but all surfaces
-that begin with `App MPlayer Sub` can be used as a *sub* surface for
+`Navigation` will be used as the *main* surface, and the surfaces
+with drawing name `HVAC` or `MediaPlayer` can be used as a *sub* surface for
this layout.
-The names must still match the layerâs role match!
+The names must still match the layer's role match!
+
+
Building and Running
====================
+
+
Dependencies
------------
@@ -359,43 +326,47 @@ Build dependencies are as follows:
- cmake >= 3.6.1
+
+
+Supported environment
+-------------------
+
+| Item | Description |
+|:------------|:----------------------------------|
+| AGL version | Electric Eel |
+| Hardware | Renesas R-Car Starter Kit Pro(M3) |
+
+
+
+
Build Configuration
-------------------
**Download recipe**
If repo is already done, please start with git clone
+
```
$ mkdir WORK
$ cd WORK
-$ repo init -b dab -m dab_4.0.0_xml -u https://gerrit.automotivelinux.org/gerrit/AGL/AGL-repo
+$ repo init -u https://gerrit.automotivelinux.org/gerrit/AGL/AGL-repo
$ repo sync
-$ git clone https://gerrit.automotivelinux.org/gerrit/staging/meta-hmi-framework
```
Then you can get the following recipe.
-* `meta-hmi-framework/windowmanager`
+* `meta-agl-devel/meta-hmi-framework/recipes-graphics/agl-service-windowmanager-2017`
+
+* `meta-agl-devel/meta-hmi-framework/recipes-graphics/libwindowmanager`
**Bitbake**
+
```
$ source meta-agl/scripts/aglsetup.sh -m m3ulcb agl-demo agl-devel agl-appfw-smack agl-hmi-framework
-$ bitbake agl-service-windowmanager-2017
+$ bitbake agl-demo-platform
```
-
-A couple of build options to configure the build are available:
-
-- `ENABLE_DEBUG_OUTPUT:BOOL` Compiles including very verbose debug
- output from the window manager, use --verbose three times on an
- afb-daemon instance to see the debug messages.
-
-- `ENABLE_SCOPE_TRACING:BOOL` Enables a simple scope tracing mechanism
- used for a rather small portion of the window manager code. However,
- it is used quite extensively in the libwindowmanager implementation.
-
-By default these options will be disabled.
-
+
Implementation Notes
====================
@@ -404,6 +375,8 @@ The window manager is implemented as a app-framework-binder binding.
That means, the build produces one shared object that exports a binding
interface.
+
+
Binding code generation
-----------------------
@@ -441,6 +414,8 @@ exception is thrown and not handled inside the afb\_binding\_call, that
internal state of the window manager might be broken at this time (hence
the talkative error log).
+
+
Structure
---------
@@ -494,4 +469,323 @@ The implementation is loosely split across the following source files:
libwayland-client wrapper. It is instanced in `main.cpp` and handles
all our wayland needs.
+
+
+Sequence
+===============
+
+To understand the sequence between application and window manager, refer to the [spec documentation](https://wiki.automotivelinux.org/windowmanager).
+
+
+
+
+Binding API
+===============
+
+Each function returns a reply containing at least a failed or successful
+result of the call, additionally, when calls return something, it is
+noted.
+
+
+
+LibWindowmanager
+------
+
+This is the public interface of the class `LibWindowmanager`.
+
+ class LibWindowmanager
+ {
+ public:
+ LibWindowmanager();
+ ~LibWindowmanager();
+
+ enum EventType {
+ Event_Active = 0,
+ Event_Inactive,
+
+ Event_Visible,
+ Event_Invisible,
+
+ Event_SyncDraw,
+ Event_FlushDraw,
+ };
+
+ int init(int port, char const *token);
+
+ // WM API
+ int requestSurface(json_object *object);
+ int activateSurface(json_object *object);
+ int deactivateSurface(json_object *object);
+ int endDraw(json_object *object);
+ int getDisplayInfo(json_object *object);
+ int getAreaInfo(json_object *in_obj, json_object *out_obj);
+
+ int getAreaInfo(const char *label, json_object *out_obj);
+
+ void set_event_handler(enum EventType et, handler_fun f);
+
+ };
+
+
+
+Methods
+-------
+
+### init(int port, char const *token)
+
+Initialize the Binding communication.
+
+The `token` parameter is a string consisting of only alphanumeric characters.
+If these conditions are not met, the LibWindowmanager instance will not initialize,
+i.e. this call will return `-EINVAL`.
+
+The `port` parameter is the port the afb daemon is listening on, an
+invalid port will lead to a failure of the call and return `-EINVAL`.
+
+### requestSurface(json_object *object)
+
+**args: `{ 'kKeyDrawingName': 'application name' }`**
+This method requests a surface with the label given from the *Window Manager*.
+It will return `surface id` a client application can use, and
+`-errno` on failure. Additionally, on the standard error, messages are
+logged to help debgging the issue.
+
+### activateSurface(json_object *object)
+
+**args: `{ 'kKeyDrawingName': 'application name', 'kKeyDrawingArea': 'layout' }`**
+This method is mainly intended for *manager* applications that control
+other applications (think an application manager or the *HomeScreen*).
+It instructs the window manager to activate the surface with the given
+*label*.
+
+This method only is effective after the actual window or surface was
+created by the application.
+
+### deactivateSurface(json_object *object)
+
+**args: `{ 'kKeyDrawingName': 'application name' }`**
+This method is mainly intended for *manager* applications that control
+other applications. It instructs the window manager to deactivate the
+surface associated with the given label. Note, that deactivating a
+surface also means to implicitly activate another (the last active or if
+not available *main surface* or *HomeScreen*.)
+
+This method only is effective after the actual window or surface was
+created by the application.
+
+### endDraw(json_object *object)
+
+**args: `{ 'kKeyDrawingName': 'application name' }`**
+This function is called from a client application when it is done
+drawing its surface content.
+
+It is not crucial to make this call at every time a drawing is finished
+- it is mainly intended to allow the window manager to synchronize
+drawing in case of layout switch. The exact semantics are explained in
+the next [Events](#_events) Section.
+
+### getDisplayInfo(json_object *object)
+
+**args: `{ }`**
+This function gets the display information as follows:
+ - width[pixel]
+ - height[pixel]
+ - width[mm]
+ - height[mm]
+
+It outputs the display information for json_object in the argument as follows:
+ `{"width_pixel": int value of width[pixel], "height_pixel": int value of height[pixel],
+ "width_mm": int value of width[mm], "height_mm": int value of height[mm]}`
+
+It should be called after calling init().
+It should not be called in the event handler because it occurs hang-up.
+
+#### NOTE
+It uses wl_output::geometry() for getting physical width[mm] and height[mm] of the display,
+but the value is different with measured value.
+
+ - value from wl_output::geometry(): width:320 height:520
+ - measured value : width:193 height:343
+
+### getAreaInfo(json_object *in_obj, json_object *out_obj)
+
+**args1: `{ 'kKeyDrawingName': 'application name' }`**
+**args2: `{ }`**
+This function gets the information of area drawn by the application as follows:
+ - x-coordinate
+ - y-coordinate
+ - width
+ - height
+
+It outputs the area information for json_object in the 2nd argument as follows:
+ `{"x": int value of x-coordinate, "y": int value of y-coordinate,
+ "width": int value of width, "height": int value of height}`
+
+It should be called after calling activateSurface().
+It should not be called in the event handler because it occurs hang-up.
+
+#### NOTE
+The same information can given by SyncDraw event.
+
+### getAreaInfo(const char *label, json_object *out_obj)
+
+**args1: String of application name**
+**args2: `{ }`**
+This function is same with `getAreaInfo(json_object *in_obj, json_object *out_obj)`,
+but only has difference of 1st argument.
+
+### set\_event\_handler(enum EventType et, handler_fun f)
+
+This method needs to be used to register event handlers for the WM
+events described in the EventType enum. Only one hendler for each
+EventType is possible, i.e. if it is called multiple times with the same
+EventType the previous handler will be replaced.
+
+The `func` handler functions will receive the label of the surface this
+event is targeted at.
+
+See Section [Events](#_events) for mor detailed information about event
+delivery to client applications.
+
+
+
+Errors
+------
+
+Methods returning an `int` signal successful operation when returning
+`0`. In case of an error, an error value is returned as a negative errno
+value. E.g. `-EINVAL` to signal that some input value was invalid.
+
+Additionally, logging of error messages is done on the standard error
+file descriptor to help debugging the issue.
+
+
+
+Usage
+-----
+
+### Initialization of LibWindowmanager
+
+Before usage of the LibWindowmanager, the method `init()` must be
+called once, it will return `-errno` in case of en error and log
+diagnostic messages to stderr.
+
+### Request a surface
+
+When creating a surface with *Qt* - it is necessary to request a surface
+from the WM, internally this will communicate with the window manager
+binding. Only after `requestSurface()` was successful, a surface should
+be created.
+
+This is also true for *QML* applications, where only after the
+`requestSurface()` should the load of the resource be done. The method
+returns `surface id` a client application can use
+after the surface was requested successfully.
+
+#### Workings of requestSurface()
+
+`LibWindowmanager::requestSurface()` calls the AFB binding verb
+`requestsurface` of the `windowmanager` API. This API call will return a
+numeric ID to be used when creating the surface. This ID is never
+explicitly returned to the client application, instead, it is set in the
+application environment in order for *Qt* to then use it when creating
+the surface.
+
+With the current *Qt* implementation this means, that only one surface
+will be available to client applications, as subsequent windows will
+increment this numeric ID internally - which then will lead to IDs that
+cannot be known by the window manager as there is no direct
+communication from *Qt* to the WM.
+
+
+
+Events
+------
+
+Events are a way for the *Window Manager* to propagate information to
+client applications. It was vital for the project to implement a number
+of events, that mirror functionality that is already present in the
+wayland protocol.
+
+All events have the surface label as argument - a way to enable future
+multi-surface applications.
+
+As already stated above, this is currently not possible with the way
+*Qt* implements its surface ID setting.
+
+### Active and Inactive Events
+
+These events signal an application that it was activated or deactivated
+respectively. Usually this means it was switched visible - which means
+the surface will now be on the screen and therefor continue to render.
+
+- `Active(json_object *object)`
+ args: { 'kKeyDrawingName': 'application name' }
+ Signal that the surface with the name
+ `kKeyDrawingName` is now active.
+
+- `Inactive(json_object *object)`
+ args: { 'kKeyDrawingName': 'application name' }
+ Signal that the surface with the
+ name `kKeyDrawingName` is now inactive. This usually means, the layout
+ got changed, and the surface is now considered inactive
+ (or sleeping).
+
+### Visible and Invisible
+
+These events signal an application that it was switched to be visible or
+invisible respectively. These events also are handled implicitly through
+the wayland protocol by means of `wl_surface::enter` and
+`wl_surface::leave` events to the client.
+
+- `Visible(json_object *object)`
+ args: { 'kKeyDrawingName': 'application name' }
+ Signal applications, that the
+ surface with name `kKeyDrawingName` is now visible.
+
+- `Invisible(json_object *object)`
+ args: { 'kKeyDrawingName': 'application name' }
+ Signal applications that the
+ surface with name `kKeyDrawingName` is now invisible.
+
+### SyncDraw and FlushDraw
+
+These events instruct applications that they should redraw their surface
+contents - again, this is handled implicitly by the wayland protocol.
+
+`SyncDraw` is sent to the application when it has to redraw its surface.
+
+`FlushDraw` is sent to the application when it should swap its buffers,
+that is *signal* the compositor that its surface contains new content.
+
+- `SyncDraw(json_object *object)`
+ args: { 'kKeyDrawingName': 'application name', 'kKeyDrawingArea': 'layout',
+ 'kKeyDrawingRect': { "x": int value of x-coordinate, "y": int value of y-coordinate,
+ "width": int value of width, "height": int value of height } }
+ Signal applications, that the
+ surface with name `kKeyDrawingArea` needs to redraw its content
+ in the layout with name `kKeyDrawingArea` - this
+ usually is sent when the surface geometry changed.
+ And the area position and size are included with name `kKeyDrawingRect`.
+
+- `FlushDraw(json_object *object)`
+ args: { 'kKeyDrawingName': 'application name' }
+ Signal applications, that the
+ surface with name `kKeyDrawingArea` can now be swapped to its newly
+ drawn content as the window manager is ready to activate a new
+ layout (i.e. a new surface geometry).
+
+
+
+Sample
+============
+
+In order to enable application to use the `WM` surface registration
+function the above described steps need to be implemented.
+
+As a minimal example the usage and initialization can look like the
+following.
+
+Repo: `apps/agl-service-homescreen-2017`
+Path: `sample/template/main.c`