This File
=========

This document describes how to use to speed up QML application startup
in Harmattan/MeeGo using the applauncherd daemon and the qdeclarative booster.

For a more general description of the launcher concept and technical
details, see the README file in the meegotouch-applauncherd source
tree.

1. COMPILING YOUR APPLICATION TO BE LAUNCHABLE

Binaries intended to be run with applauncherd should be compiled with -fPIC option
to produce position independent code. In order to produce a position independent
executable, -pie option and -rdynamic options can be used in linking. This allows
the result to be executed both traditionally and with the launcher.

To improve linking and loading times of shared object libraries it is
encouraged to hide any unnecessary symbols from the resulting binary by using
-fvisibility=hidden and -fvisibility-inlines-hidden flags as well.


1.1 Build configuration

These instructions describe how to build your application so that it
can be launched using applauncherd. Only Debian packaging is considered,
you have to creatively apply the instructions if you are doing RPM packaging.

If you are too impatient to read instructions, take a look at the
examples in the source tree instead.

  Using QMake
  -----------

  If you are using QMake, making your application boostable is just a
  matter of adding a suitable configuration option.

  For Qt Declarative (QML) applications, the configuration option is
  provided by the applauncherd-dev package. If you are building a
  Debian package, you have to add a build dependency to
  applauncherd-dev. The configuration option is:

    CONFIG += qdeclarative-boostable

  If you want to use pkg-config directly for some reason (like getting
  error messages), you can add explicit pkg-config calls in the appropriate
  flags:

    QMAKE_CXXFLAGS += `pkg-config --cflags qdeclarative-boostable`
    QMAKE_LFLAGS += `pkg-config --libs qdeclarative-boostable`

  You can also manually set the options in your .pro file like this:

    QMAKE_CXXFLAGS += -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
    QMAKE_LFLAGS += -pie -rdynamic

  Note that you have to update the flags manually if there are any changes in
  the required flags.

  Using CMake
  ---------------------------

  You can utilize pkg-config in CMake by including FindPkgConfig in CMakeLists.txt:

  include(FindPkgConfig) 

  To get Debian packages built correctly, make the package
  build-depend on applauncherd-dev. To obtain the compiler and linker
  flags, add the following lines in CMakeLists.txt:

  pkg_check_modules(QDECLARATIVE_BOOSTABLE REQUIRED qdeclarative-boostable)
  add_definitions(${QDECLARATIVE_BOOSTABLE_CFLAGS})
  link_libraries(${QDECLARATIVE_BOOSTABLE_LDFLAGS})
  
  If you do not want to use pkg-config for some reason, you can manually add the
  compiler and linker flags like this:

  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden 
      -fvisibility-inlines-hidden")
  set(CMAKE_EXE_LINKER_FLAGS "-pie -rdynamic")
  
  Again, this requires you to update the flags if something changes.

  Automatic settings with pkg-config (any build system)
  -----------------------------------------------------

  To get Debian packages built correctly, make the package
  build-depend on applauncherd-dev. The correct flags can be
  automatically obtained with:

    pkg-config --cflags qdeclarative-boostable
    pkg-config --libs qdeclarative-boostable

1.3 Changes to the code

With -fvisibility=hidden you must make sure that the symbol for main() is
exported, because otherwise the launcher is not able to find the entry point
for your application. This can be done like this:

  #include <QtCore/QtGlobal>
  
  Q_DECL_EXPORT int main(int argc, char **argv)
  {
  ...
  }

The application cannot directly instantiate QApplication and
QDeclarativeView. Instead of writing e.g.

      QApplication app;
      QDeclarativeView view;

you need to pick up instances of QApplication and QDeclarativeView from a cache:

     QApplication *app = MDeclarativeCache::qApplication(argc, argv);
     QDeclarativeView *window = MDeclarativeCache::qDeclarativeView();

The ownership of the instances is currently transferred from the cache to the
application code, but this is subject to change if there is a need to align
the API with Symbian.

If you plan to use QCoreApplication::applicationDirPath() or
QCoreApplication::applicationFilePath(), please see KNOWN ISSUES below.

2. LAUNCHING YOUR APPLICATION USING INVOKER

The application to be launched must be "invoked" using the invoker binary.  The
invoker then sends the application data, essentially arguments and environment
variables, to the launcher daemon via a socket connection. The launched
application will see its real binary name in its argv[0].

2.1 Launch from the command-line

Use --type=d for Qt Declarative applications:

  /usr/bin/invoker --type=d <application_name>

2.2 D-Bus launch

If you are using D-Bus to launch your application, it can be done
straightly in the .service-file and without any wrapper scripts slowing
things down:

  [D-BUS Service]
  Name=com.nokia.<application_name>
  Exec=/usr/bin/invoker --type=d /usr/bin/<application_name>

By default, invoker waits for the application to terminate and exits with
the same exit code. Unix signals are also forwarded.
  
Note 1: If --no-wait and --delay is used, it is important to add enough delay to
invoker so that it won't exit before the launched application gets its
(possible) D-Bus service registered. Otherwise D-Bus daemon may think that the
application just died. 

Note 2: There is a slight difference in the application start-up time if you use a
wrapper script instead of the actual binary in Exec-field of .desktop and .service files. 
Therefore, it is recommended that you always use the actual invoker call with the 
binary name as presented above. 

Note 3: When .desktop file contains the X-Maemo-Service field, the application
is started by default through D-Bus. This might cause some delay for
application start-up time. Therefore it is recommended to use the single
instance launch functionality (see below) instead of a X-Maemo-Service if
possible

See invoker --help for all possible command-line parameters.

2.3 Single instance launch

Usually user wants the application to be run as a single instance. This means,
that if the launched application is already running, the existing application
window is activated and no new application processes are started.

This can be achieved by adding --single-instance to the invoker command:

  [D-BUS Service]
  Name=com.nokia.<application_name>
  Exec=/usr/bin/invoker --single-instance --type=d /usr/bin/<application_name>
 
As a result, a lock file /var/run/single-instance-locks/<application_name>/instance.lock 
is created.  If applauncherd cannot acquire the lock, it tries to find the
corresponding window and activates it.

This functionality is implemented in a position-independent executable called
single-instance. Applauncherd uses the executable as a library, but it can be
used as an ordinary program to start anything as a single instance:

  /usr/bin/single-instance <application_name>

Note, that in this case the launcher is not used.

Consider using --single-instance instead of the single instance functionality
provided by D-Bus, because it very likely is much faster.

2.4 Splash screen

Applauncherd supports showing a splash screen if there is mcompositor
(the MeeGo window manager) running.

The splash screen is not shown by default. If an application wants it
to be shown, it must pass --splash, and optionally --splash-landscape
arguments to the invoker.

For instance,

/usr/bin/invoker --splash=/usr/share/application_name/splash.jpg \
		 --splash-landscape=/usr/share/application_name/splash-l.jpg \
		 --type=d \
		 /usr/bin/application_name

shows the splash screen with splash.jpg as its content when the device
is in the portrait orientation. Otherwise splash-l.jpg is shown. If
only --splash is given, that image is shown in both orientations.

Invoker passes the splash request to the booster. The booster sends
the splash request to the window manager by setting a window property
to window manager's window.

If the filenames do not include absolute paths, the window manager
looks for the files from a default location.

3. PACKAGE DEPENDENCIES

Applications using the launcher must depend on the applauncherd Debian package.


4. CURRENT KNOWN ISSUES

4.1 Forking

Using QApplication or QDeclarativeView fetched from the cache in a child
process does not work, because they would share the X11 connection with the
parent.

4.2 Non-working QCoreApplication methods

The following methods of QCoreApplication are known not to work with
qdeclarative booster:

    QCoreApplication::applicationDirPath()
    QCoreApplication::applicationFilePath()

The reason for this that the methods get the path from the /proc file system,
so they return the path to the booster rather than the path to the launched
application. This is unlikely to be fixed for Qt 4.7.

The MDeclarativeCache class provides the replacements
MDeclarativeCache::applicationDirPath() and
MDeclarativeCache::applicationFilePath(), which are identical to the
QCoreApplication counterparts, except that in the boosted case they use argv[0]
of the boosted application.

5. COMMAND-LINE PARAMETERS

All parameters are listed by:

invoker --help
applauncherd --help
