Purpose
Screensaver application monitors the system for user inactivity
and displays graphical objects in case of prolonged inactivity. Screensaver
immediately stops displaying these objects when user activity resumes. In
addition, the display is partially shut down during inactivity.
The graphical object displayed by the Screensaver application can be one
of the following:
Screensaver plug-ins are used by Screensaver and Themes applications.
Screen Saver API allows third party developers to create screensaver plug-ins.
These plug-ins only need to implement code for displaying the custom graphical
object. All other functionalities (user activity monitoring, management of
screensaver settings, preview functionality, etc.) are already available in
Screensaver and Themes applications.
Screensaver plug-ins are implemented as ECom plug-ins and can be installed
from SIS packages.
This document describes how to use Screen Saver API to create custom screensaver
plug-ins.
Constraints
This API is valid for all platforms running on Symbian OS v9.1 or later.
Classification and release information
Screen Saver API is an SDK API and was first published in S60 3rd Edition.
API description
Screensaver plug-in architecture is based on two main classes. The Screensaver
application (and all underlying services) is represented by the abstract interface
MScreensaverPluginHost
.
Screensaver plug-in objects are ECom-plug-ins, implementing the
MScreensaverPlugin
interface.
The plug-in only need to provide code for drawing the custom graphical object.
MScreensaverPluginHost
provides
the default screensaver behavior and data.
There is a two-way communication between the Screensaver plug-in module
and the host. The host knows when to activate Screensaver and update the screen.
It calls the
Draw()
function of the plug-in module with graphics
context as a parameter. The plug-in module can adjust certain attributes through
its host interface such as timeout value of the refresh timer.
Plug-in host (MScreensaverPluginHost)
The plug-in host is represented by interface
MScreensaverPluginHost
.
Plug-ins receive a pointer to the host during initialization. The host has
the following responsibilities:
-
creating, initializing, owning and deleting the plug-in
-
providing data for Screensaver indicators (new messages, missed calls,
etc.)
-
providing display information
-
activating partial display mode (power saving)
-
redrawing the plug-in object on a regular basis
-
sending Screensaver events to the currently active plug-in
Related APIs
Plug-in (MScreensaverPlugin)
Screensaver plug-ins implement the
MScreensaverPlugin
interface.
Plug-ins are installed as ECom plug-ins, implementing the
KCScreensaverPluginInterfaceDefinitionUid
(0x101F87F8)
interface. For convenience reasons, the class
CScreensaverPluginInterfaceDefinition
is
provided.
CScreensaverPluginInterfaceDefinition
derives from
MScreenSaverPlugin
and
implements ECom plug-in instantiation. Concrete plug-in implementations should
derive from
CScreensaverPluginInterfaceDefinition
.
Plug-ins implement specific functions in the method
PluginFunction()
.
The host invokes a given function if the plug-in capabilities indicate the
support for that particular function. Plug-ins advertise their capabilities
by implementing
Capabilities()
. The same capabilities also
need to be defined in the ECom registration file as well.
Related APIs
-
CScreensaverPluginInterfaceDefinition
-
Capabilities()
-
MScreenSaverPlugin
-
MScreensaverPlugin
-
PluginFunction()
Preview mode
Screensavers may be run in preview mode. Preview displays the screensaver
shortly, for 10 seconds or until the first user activity. The Themes application
calls the plug-in function
EScpCapsPreviewNotification
before
activating preview. The plug-in must have the
EScpCapsPreviewNotification
capability
to receive this notification.
Related APIs
-
EScpCapsPreviewNotification
Partial display mode
For power saving purposes, partial display mode may be available. Availability
of this mode depends on the display hardware.
It is possible that the display hardware supports only a limited number
of colors when the partial mode is activated. The host provides a method for
the plug-in modules to query a color model supported by the display hardware.
The maximum amount of lines active in partial display mode is display specific.
There is no function to query the supported value. See
Limitations of the API
for limitations.
Plug-ins should always use partial display mode. See Section
Power saving considerations
.
Use cases
-
Implementing custom plug-in
-
Overriding standard indicators
-
Getting indicator data
-
Setting refresh timer
-
Disabling refresh
-
Querying display info
-
Configuring the plug-in
-
Suspending drawing
-
Entering partial display mode
-
Exiting partial display mode
API class structure
Figure 2 shows the main classes of Screen Saver API. Minor data structures
are omitted for clarity.
The main classes are
MScreenSaverPluginHost
and
MScreenSaverPlugin
,
representing the host application and the screensaver plug-in, respectively.
The class
CScreenSaverPluginInterfaceDefinition
is the
convenience class, to be used as a base to the actual screen saver plug-in.
It uses
REcomSession
to load the plug-in.
CExampleScreenSaverPlugin
is included for clarity. It
is not part of Screen Saver API.
Related APIs
-
CExampleScreenSaverPlugin
-
CScreenSaverPluginInterfaceDefinition
-
MScreenSaverPlugin
-
MScreenSaverPluginHost
-
REcomSession
Related APIs
-
Draw()
-
MScreensaverPlugin
-
MScreensaverPluginHost
Using Screen Saver API
Using Screen Saver API means implementing a plug-in, which uses services
of the host.
Implementing custom plug-in
Plug-ins derive from
CScreensaverPluginInterfaceDefinition
.
class CExampleScreenSaverPlugin:
public CScreensaverPluginInterfaceDefinition
{
public:
static CExampleScreenSaverPlugin* NewL();
virtual ~CExampleScreenSaverPlugin();
public: // from CScreensaverPluginInterfaceDefinition
virtual TInt InitializeL( MScreensaverPluginHost *aHost );
virtual TInt Draw( CWindowGc& aGc );
virtual const TDesC16& Name() const;
virtual TInt Capabilities();
virtual TInt PluginFunction(
TScPluginCaps aFunction,
TAny* aParam );
virtual TInt HandleScreensaverEventL(
TScreensaverEvent aEvent,
TAny* aData );
private: // data
MScreensaverPluginHost* iHost; // Host, not owned.
TRect iRect; // Rect of display area.
};
MMP file fragment.
TARGET ExampleScreenSaverPlugin.dll
TARGETTYPE PLUGIN
UID 0x10009D8D 0xE000ABCD
CAPABILITY NetworkServices LocalServices Location ReadUserData WriteUserData
ReadDeviceData WriteDeviceData SwEvent UserEnvironment PowerMgmt
START RESOURCE ..\data\10207447.rss
TARGET ExampleScreenSaverPlugin.rsc
END
SOURCE ExampleScreenSaverPlugin.cpp
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\ecom
LIBRARY ecom.lib
LIBRARY euser.lib
ECom registration resource file fragment.
The
opaque_data
contains the plug-in capabilities in string
format. Same capability values must be returned in numeric format by
MScreensaverPlugin::Capabilities()
.
MScreensaverPlugin::Name()
or
display_name
provide
the string displayed to the user in Screensaver settings view in the Themes
application.
display_name
is not used unless
MScreensaverPlugin::Name()
returns
an empty string. This way the plug-in registration file need not contain localizable
information.
Note that in S60 3rd Edition,
display_name
was used instead
of
MScreensaverPlugin::Name()
.
#include <RegistryInfo.rh>
#include "ScreensaverPluginIntDef.hrh"
RESOURCE REGISTRY_INFO theInfo
{
dll_uid = 0xE000ABCD;
interfaces =
{
INTERFACE_INFO
{
interface_uid = KCScreensaverPluginInterfaceDefinitionUid;
implementations =
{
IMPLEMENTATION_INFO
{
implementation_uid = 0xE0001234;
version_no = 1;
display_name = "Example plugin";
default_data = "";
opaque_data = "07";
}
};
}
};
}
The ECom plug-in must export its implementation proxy table:
#include <e32Std.h>
#include <ImplementationProxy.h>
const TImplementationProxy ImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY( 0xE0001234, CExampleScreenSaverPlugin::NewL )
};
EXPORT_C const TImplementationProxy*
ImplementationGroupProxy( TInt& aTableCount )
{
aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
return ImplementationTable;
}
Instance creation through ECom should be light. It is possible that plug-ins
are created but never initialized and drawn. For example, if the plug-in supports
the configure function, the Themes application creates an instance and calls
plug-in function
EScpCapsConfigure
, without initializing
the plug-in.
The Screensaver application will call
InitializeL()
to
prepare the plug-in for drawing. Initialization for drawing-related resources
should be implemented in
InitializeL()
instead of
ConstructL()
.
void CExampleScreenSaverPlugin::ConstructL()
{
}
TInt CExampleScreenSaverPlugin::InitializeL
( MScreensaverPluginHost *aHost )
{
iScreenSaverHost = aHost;
// Prepare for drawing: load resources, etc.
// ...
return KErrNone;
}
Capabilities must match the supported plug-in functions. Capabilities are
read by, and the plug-in functions are called from the Themes application.
TInt CExampleScreenSaverPlugin::Capabilities()
{
return EScpCapsConfigure |
EScpCapsSelectionNotification |
EScpCapsPreviewNotification;
}
TInt CExampleScreenSaverPlugin::PluginFunction(
TScPluginCaps aFunction,
TAny* /*aParam*/)
{
switch ( aFunction )
{
case EScpCapsConfigure:
{
// Called from Themes.
// Options->Settings selected.
// Launch dialog to configure plug-in settings.
// InitializeL() may not have been called.
// ...
break;
}
case EScpCapsSelectionNotification:
{
// Called from Themes.
// Options->Apply selected.
// ...
break;
}
case EScpCapsPreviewNotification:
{
// Called from Themes.
// Options->Preview selected.
// Prepare for preview.
// ...
break;
}
}
return KErrNone;
}
The plug-in responds to screensaver events, sent by the host.
TInt CExampleScreenSaverPlugin::HandleScreensaverEventL(
TScreensaverEvent aEvent,
TAny* /*aData*/ )
{
switch ( aEvent )
{
case EScreensaverEventNothing:
{
// This event should never be delivered.
break;
}
case EScreensaverEventStarting:
{
// This event is delivered when screensaver is about to start.
break;
}
case EScreensaverEventStopping:
{
// This event is delivered when screensaver is stopped.
// In case plug-in has internal timers while screensaver
// is displayed, here you can stop those.
break;
}
case EScreensaverEventDisplayChanged:
{
// This event needs to be handled when display resolution
// or orientation is changed.
// You can refresh information about display using
// MScreensaverPluginHost::DisplayInfo method.
break;
}
case EScreensaverEventTimeout:
{
// This event is delivered when plug-in requested
// timeout expires.
// See MScreensaverPluginHost::RequestTimeout.
break;
}
case EScreensaverEventPreview:
{
// This event is delivered by screensaver application
// when plug-in started to be used in preview mode.
// Note that themes application
// informs of preview activation through PluginFunction.
break;
}
default:
{
// Ignore any new events.
}
break;
}
return KErrNone;
}
Plug-ins implement the drawing code in the
Draw()
method.
Based on the refresh timer, the host calls
Draw()
periodically.
Draw()
receives
the window context to be used for drawing as parameter
Related APIs
-
CScreensaverPluginInterfaceDefinition
-
ConstructL()
-
Draw()
-
EScpCapsConfigure
-
InitializeL()
-
MScreensaverPlugin::Capabilities()
-
MScreensaverPlugin::Name()
-
display_name
-
opaque_data
Overriding standard indicators
By default, Screensaver draws the indicators and the plug-in only draws
the custom graphical object. It is possible to turn standard indicators off.
iHost->OverrideStandardIndicators();
Typical uses of this feature include:
-
the plug-in draws custom indicators
-
the plug-in displays animation, and does not want the animation be obscured
by the standard indicators.
Getting indicator data
The following code snippet gets the number of missed calls from the host.
This is typically used if the plug-in draws custom indicators.
TInt missedCalls = 0;
TIndicatorPayload payload;
TInt err = iHost->GetIndicatorPayload
( EScreensaverIndicatorIndexNewMissedCalls, payload );
if ( KErrNone == err )
{
missedCalls = payload.iInteger;
}
Setting refresh timer
Plug-ins can adjust the refresh timer. See
Power saving considerations
.
iHost->SetRefreshTimerValue( 10000000 ); // 10 seconds
Disabling refresh
If refresh timer is disabled, the host does not call the
Draw()
method
of the plug-in.
iHost->UseRefreshTimer( EFalse );
Related APIs
Querying display info
The following example demonstrates screensaver event handling. In response
to the
EScreensaverEventDisplayChanged
event, a display info
is queried from the host.
Note that
TScreensaverDisplayInfo::iSize
must be set by
the caller.
In this example, the plug-in copies the display
TRect
to
a member variable.
TInt CExampleScreenSaverPlugin::HandleScreensaverEventL(
TScreensaverEvent aEvent,
TAny* /*aData*/ )
{
if ( EScreensaverEventDisplayChanged == aEvent )
{
// Display Changed is called when there is a change in the size
// of the window and when the parent control is set for the
// first time.
TScreensaverDisplayInfo displayInfo;
displayInfo.iSize = sizeof( TScreensaverDisplayInfo );
User::LeaveIfError( iHost->DisplayInfo( &displayInfo ) );
iRect = displayInfo->iRect; // Save display rect.
}
//...
return KErrNone;
}
Related APIs
-
EScreensaverEventDisplayChanged
-
TRect
-
TScreensaverDisplayInfo::iSize
Configuring the plug-in
Configurable plug-ins must advertise capability
EScpCapsConfigure
.
Plug-in function
EScpCapsConfigure
can be used to display
the configuration UI to the user.
Note that plug-in function
EScpCapsConfigure
may be called
without
InitializeL()
being called first.
Management and persistence of the plug-in specific settings are beyond
the scope of this document. One possible implementation is using Central Repository.
Related APIs
-
EScpCapsConfigure
-
InitializeL()
Suspending drawing
Plug-ins can suspend drawing for a requested period of time, or indefinitely.
During this standard screensaver view is drawn.
iHost->Suspend( -1 ); // Value in microsecods.
// Negative value: suspend indefinitely.
Entering partial display mode
The following code snippet demonstrates using the partial display mode.
TInt CExampleScreenSaverPlugin::Draw( CWindowGc& aGc )
{
TRect rect = TRect( 0, 0, 240, 40 );
aGc.Clear( rect );
aGc.SetPenColor( KRgbBlack );
aGc.SetBrushStyle( CGraphicsContext::ESolidBrush );
aGc.SetPenStyle( CGraphicsContext::ESolidPen );
aGc.UseFont( iEikonEnv->TitleFont() );
aGc.DrawText( _L("hello world"), TPoint( 0, 30 ) );
TScreensaverPartialMode partialMode;
partialMode.iBpp = 0;
partialMode.iType = EPartialModeTypeMostPowerSaving;
// Call SetActiveDisplayArea last - it may cause flush.
(void)iHost->SetActiveDisplayArea( rect, partialMode );
return KErrNone;
}
Exiting partial display mode
The following code snippet cancels the effect of the
SetActiveDisplayArea()
method.
The whole display area is activated.
iHost->ExitPartialMode ();
Related APIs
Error handling
Screen Saver API uses standard Symbian platform error reporting mechanism and
standard error codes.
In certain error situations plug-ins may detect unrecoverable errors. The
plug-in may choose to disable itself and revert back to the default screensaver,
by calling
MScreensaverPluginHost::RevertToDefaultSaver()
.
This causes the plug-in to be unloaded. An example for such a situation could
be if the plug-in’s graphical object is digitally protected, and the client
Rights Object to render the graphical object has expired.
It should be noted, however, that the plug-in host also has a fallback
mechanism. If the plug-in fails to load, the host activates a default screensaver.
Related APIs
-
MScreensaverPluginHost::RevertToDefaultSaver()
Memory overhead
Memory consumption of screensaver depends on the actual plug-in implementation.
Power saving considerations
Reducing power consumption is one of the primary considerations in Screensaver.
When writing plug-ins, prefer low power consumption over fancy graphics. Screensaver
runs when nobody is watching.
-
Partial display mode should always be used. Full screen mode should only
be used temporarily, as it reduces standby time significantly.
-
Using own timers in plug-in code is not recommended. The refresh timer
(provided by the plug-in host) should be sufficient for most uses.
-
Refresh rate should be kept low.
-
Unnecessary computations should be avoided.
-
Overriding screen backlight handling should be avoided.
Limitations of the API
There is no function to query the maximum number of lines supported by
the display hardware in partial display mode. As a rule of thumb, support
for 50 lines could be assumed.