| developer.brewmp.com developer.brewmp.com

Developer

Deployment Overview for Application Distribution Services

The purpose of this document is to broadly outline how a Mobile Network Operator, OEM, or other Mobile Service Provider can

  • package and authorize applications to run on Brew ® MP handsets
  • develop and deploy an application download environment
  • implement an on-device application manager

It describes the key processes, technologies, and recommendations to effectively create an end-to-end application distribution ecosystem for Brew MP devices.

Using Virtual Keypad in Legacy BREW Applications for Developers

Using Virtual Keypad in Legacy BREW applications for Developers

Base version: Brew MP 1.0 .2 and newer versions
Tested version: Brew MP 1.0.4
Phone tested: Yes
Document number: HT80-VT500-229
Date published: March 22, 2012

Legacy Brew applications that have built their own UI controls may need access to the virtual keypad to allow user input.

Objective

Brew® Mobile Platform (Brew MP™™) applications can use Widgets to access the virtual keypad. Legacy Brew applications that do not use Widgets need to use a virtual keypad. This virtual keypad application must be provided by the OEM, along with changes to the TextCtl to launch the virtual keypad. OEMs may use the JVIApp provided by Brew MP.

Requirements

To display the virtual keypad, a legacy Brew application must send pointer events to the TextCtl. The modified ITextCtl implementation uses the pointer events to determine when to launch the virtual input application.

Overview of the JVIApp

The JVIApp is used with the JVI Service and the JVI Singleton. The figure below shows the interactions between the components that are used to launch the JVIApp to allow the user to input text.

Using the Touchscreen Troubleshooting Applet

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0.3 (device), 1.0.2 (simulator)

Phone tested:

Yes

The Touch Troubleshooting applet is intended to verify the correct operation of a Brew® MP touchscreen device. It is written using Brew MP Widgets.

The applet draws points on the display in response to Brew MP pointer events:

  • green = pointer down
  • black = pointer move
  • yellow = pointer stale move
  • red = pointer up.
Events received from a touchscreen pointer other than pointer 1 (on a multi-touch device) are drawn as numbers corresponding to the pointer ID.

The applet gathers statistics when it receives touchscreen events. When a pointer up event is received, the touch observer is queried for the flick information associated with the gesture just made by the user and then the touchscreen statistics are output to the screen. The touchscreen statistics displayed are:

  • Total number of pointer down events
  • Total number of pointer move events
  • Total number of pointer stale move events
  • Total number of pointer up events
  • Last flick direction
  • Last flick speed

Three touchscreen tests are described for the user to perform in a pop-up message, which is displayed when the Tests... button is clicked. The tests to perform are:

  • Reset the statistics, then draw a circle on the screen with a pointing device.

    Note: The circle is simply a shape for the user to draw to verify that the device generates sufficient pointer events to describe the circle.

    The user should see a green point (pointer down) followed by a series of black (pointer move) or yellow (pointer stale move) points and finally a red (pointer up) point.
  • Reset the statistics, perform a vertical flick, then reset the statistics and perform a horizontal flick. The user should see a vertical or horizontal line of points.
  • If testing a multi-touch device, reset the statistics, perform a vertical pinch, then reset the statistics and perform a horizontal pinch. The user should see two vertical or horizontal lines of points, each of which corresponds to a particular pointer.

Touchscreen statistics are ouput to the screen after each gesture made by the user. These statistics should be used to verify the correct behaviour of the touchscreen device, such as its ability to correctly determine the type and position of various pointer events.

Objective

This document describes how to use the Touch Troubleshooting applet to test the functionality of a touchscreen device.

Requirements

The main functionality of the applet is contained in two files: TouchTroubleshoot.c and MainPage.c. Other files in the project support the applet functionality, such as the generic widget pop-up in WidgetPopUp.c.

At start-up, the applet

  • Creates a root container
  • Enables touch support
  • Gets the root touch observer
  • Starts last linear movement observation
  • Provides the root container with a canvas.

On receipt of the EVT_APP_START event, the main page is created. The main page consists of an XY container, two buttons and static widgets to display strings. An offscreen display is also created.

When touch events are received by the applet's event handler, they are passed to Widgets for handling, before being forwarded to the main page. This ensures the main page of the applet can respond to all pointer events, even if they are processed by Widgets, which allows, for example, the events causing a button click to be displayed on top of the button. Points are drawn on the offscreen display in response to pointer events. When a pointer up event is received, the statistics are updated and the offscreen display bitmap is blitted to the screen.

Sample code location

ZIP filename

Location

Run app

c_touchtroubleshoot

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the touchscreen Brew MP device to be tested.

Event handling

As well as handling EVT_APP_START, EVT_APP_STOP, EVT_APP_RESUME and EVT_KEY events, the applet handles touchscreen pointer events after passing them to Widgets for default handling.

Example - Touchscreen support and last linear movement observation

Touchscreen support is enabled in Widgets by creating the root container, obtaining its IWidget interface and enabling touch on it. Touch observation is required to retrieve flick information in response to user input, and it must be started before use. [TouchTroubleshoot.c]

...
// Enable widget touchscreen support
if (SUCCESS == nErr) nErr = IWidget_EnableTouch(pMe->m_pRootWidget);

// Get the root container's touch observer
if (SUCCESS == nErr) nErr = IWidget_GetTouchObserver(pMe->m_pRootWidget,
            &pMe->m_pRootTouchObs);

// Start last linear movement observation
if (SUCCESS == nErr) nErr = IObserver_StartObservation(pMe->m_pRootTouchObs,
            TOUCHOBSF_LLM);
...

Last linear movement information is obtained from the touch observer. [MainPage.c]

int i;

if (SUCCESS == IObserver_GetLLMAngle(pObs, &i)) {
   pPageData->m_stats.m_nStats[STATS_FLKDIR] = (uint32)i;
}
...

if (SUCCESS == IObserver_GetLLMSpeed(pObs, &i)) {
   pPageData->m_stats.m_nStats[STATS_FLKSPEED] = (uint32)i;
}
...

Multi-touch pointer move events are handled in the pointer event handler. [MainPage.c]

...
int nPtrID = AEE_POINTER_GET_PTRID((const char*)dwParam);

switch (evt) {
   case EVT_POINTER_MT_MOVE:
   case EVT_POINTER_MOVE:
   case EVT_POINTER_MT_STALE_MOVE:  //lint -fallthrough
   case EVT_POINTER_STALE_MOVE:
      {
         ...
         if (SUCCESS == AEE_POINTER_GET_XY(pszPointer, &x, &y)) {
            ...
         }
         else {
            DBGPRINTF("Fail: get pointer XY");
         }

         pszPointer = AEE_POINTER_GET_NEXT_POINTER(pszPointer);

         while (pszPointer) {
            if (SUCCESS == AEE_POINTER_GET_MT_XY_PTRID(pszPointer, &x, &y, &nPtrID)) {
               ...
            }
            else {
               DBGPRINTF("Fail: get MT pointer XY PTRID");
            }

            pszPointer = AEE_POINTER_GET_MT_NEXT_POINTER(pszPointer);
         }
      }
      break;

When no longer needed, the applet stops touch observation. [TouchTroubleshoot.c]

...
// Stop observation and release the root touch observer
if (pMe->m_pRootTouchObs) {
   (void)IObserver_StopObservation(pMe->m_pRootTouchObs, TOUCHOBSF_LLM);
   (void)IObserver_Release(pMe->m_pRootTouchObs);
}
...

Error handling

When writing a touchscreen applet such as this, ensure that all of the executed APIs have returned SUCCESS in order to proceed with the next step and for correct execution, unless a potential error is of no consequence (for example, this applet ignores any errors that may occur when removing a widget from the root container).

Related information

  • See the Widgets Touchscreen Technology Guide.
  • See the Widgets Technology Guide.
  • See the C/C++ API Reference.

Connecting to a WLAN

Base version:

Brew® MP 1.0.2

Tested version:

Brew MP 1.0.2

Phone tested:

Yes

Objective

This document describes how to connect to a wireless access point using wlan_IConnMgr.

Requirements

To create an application, you must:

  • install the Brew MP Multi-Platform SDK - see the Brew MP Developer's website for installation instructions.
  • have a WLAN enabled device.

To test on a device, you must install a RealView Development suite (RVCT) or ARM Development Suite (ADS) compiler.

To connect to a WLAN:

  • Create an instance of wlan_IConnMgr.
  • Scan for networks, if you know the connect information, you do not need to do a scan.
  • Call wlan_IConnMgr_Connect() to connect to the network.

To search for WLANs:

  1. Create an instance of wlan_IConnMgr.
  2. Create a signal object.
  3. Setup the signal by calling wlan_IConnMgr_OnScanEnd().
  4. Start the scan by calling wlan_IConnMgr_StartScan().
  5. When the callback is triggered, call wlan_IConnMgr_GetNetworks() to get the list of available networks returned by the scan.

Sample code location

ZIP filename

Location

Run app

c_wlanconnmgrapp_1.0.0.zip

Brew MP Library

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on a device.

Example - Creating an instance of wlan_IConnMgr

Use the IShell create instance function to create a wlan_IConnMgr object.

nResult = ISHELL_CreateInstance(pMe->piShell, wlan_AEECLSID_ConnMgr,
                               (void**)(&pMe->piConnMgr));
if( SUCCESS != nResult) 
{
   DBGPRINTF("Create instance of wlan_IConnMgr failed Return Value %d",
              nResult);
   pMe->piConnMgr = NULL;
}

Example - Starting a scan

Before starting a scan, you must create a signal and set up the signal with the wlan_IConnMgr object. Then you call wlan_IConnMgr_StartScan() to start the scan.

nErr = WCM_CreateSignal(pMe->piShell, WCM_StartScanCB, pMe,
   &pMe->piSignal, &pMe->piSignalCtl);
if (AEE_SUCCESS != nErr) 
{
   goto bail;
}

nErr = wlan_IConnMgr_OnScanEnd(pMe->piConnMgr, pMe->piSignal);
if (AEE_SUCCESS != nErr) 
{
   goto bail;
}

nErr = wlan_IConnMgr_StartScan(pMe->piConnMgr);
if (AEE_SUCCESS != nErr) 
{
   goto bail;
}

Example - Retrieving the network list

When the wlan_IConnMgr is done finding the available networks, it generates the callback signal. In the callback function, you must call wlan_IConnMgr_GetNetworks() to determine if any networks were found and the buffer size needed.

nErr = wlan_IConnMgr_GetNetworks(pMe->piConnMgr, 
                               &bScanInProgress, 
                               pMe->pNet, pMe->nNetCount, 
                               &nNetworksLenReq);

After allocating the space defined in nNetworksLenReq, call wlan_IConnMgr_GetNetworks() to get the network list.

// allocate space
pMe->pNet = REALLOC(pMe->pNet, sizeof(wlan_Network) 
                            * nNetworksLenReq);
// Get the network string
nErr = wlan_IConnMgr_GetNetworks(pMe->piConnMgr, &bScanInProgress, 
                                       pMe->pNet, pMe->nNetCount, 
                                       NULL);

Example - Connecting to an access point

To connect to a WLAN access point, you must create and set up a callback function, and then try to connect.

nErr = WCM_CreateSignal(pMe->piShell, WCM_ConnectCB, pMe,
                       &pMe->piSignal, &pMe->piSignalCtl);
if (AEE_SUCCESS != nErr) 
{
   goto bail;
}

nErr = wlan_IConnMgr_OnConnectStatusChange(pMe->piConnMgr, 
                         pMe->piSignal);
if (AEE_SUCCESS != nErr) 
{
   goto bail;
}
     
nErr = wlan_IConnMgr_Connect(pMe->piConnMgr, pNet, 
                         wlan_SCAN_AUTO, enc, pAuthInfo);
if (AEE_SUCCESS != nErr) 
{
   WCM_DisplayMsg(pMe, "Connect failed %d \n", nErr );
   goto bail;
}

Example - Retrieving network information

To get the status of the network connection, you call wlan_IConnMgr_GetConnectStatus(). This function can be used at any time.

wlan_IConnMgr_GetConnectStatus( pMe->piConnMgr,&status, &reason, 
                                &bInfoAvail, &net);

Example - Disconnecting from an access point

To disconnect from a WLAN access point, you must create and set up a callback function, and then try and disconnect.

nErr = WCM_CreateSignal(pMe->piShell, WCM_DisconnectCB, pMe,
                       &pMe->piSignal, &pMe->piSignalCtl);
if (AEE_SUCCESS != nErr) 
{
    goto bail;
}

nErr = wlan_IConnMgr_OnConnectStatusChange(pMe->piConnMgr, pMe->piSignal);
if (AEE_SUCCESS != nErr) 
{
    goto bail;
}

nErr = wlan_IConnMgr_Disconnect(pMe->piConnMgr);
if (AEE_SUCCESS != nErr) 
{
   goto bail;
}

Declaring and Using a Singleton

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0

Phone tested:

Yes

When a class is instantiated as a singleton in Brew® Mobile Platform (Brew MP), there can be only one instance of the class within a certain scope. The scope is determined by the environment (or Env) of the caller, or the entire Brew MP system, depending on the type of singleton class instantiated.

Objective

This document describes how to declare a singleton in-process class or singleton service class in the CIF and use it in a Brew MP application. For information on the usage of ISingleton, see the C/C++ API Reference.

Requirements

To use a singleton in-process class, do the following:

  • Add a Singleton declaration to your application's CIF
  • Call IEnv_CreateInstance() with the ClassID of the singleton in-process class
  • Call the appropriate functions supported by the in-process class

To use a singleton service class, do the following:

  • Add Service and Singleton declarations to your application's CIF
  • Call IEnv_CreateInstance() with the ServiceID of the singleton service
  • Call the appropriate functions supported by the service

Sample code location

The ZIP file contains two example applications: c_appio and c_appio2. The c_appio application demonstrates the use of a singleton service. c_appio2 demonstrates the use of a singleton in-process class and the use of a non-singleton in-process class.

ZIP filename

Location

Run app

singleton_samples

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile an app.

  • Run it on the Brew MP Simulator.

Using IThread

Base version: Brew MP 1.0
Tested version: Brew MP 1.0
Phone tested: Yes

You can use the Brew® Mobile Platform (Brew MP) IThread interface to write applications that use cooperative multithreading. Cooperative multithreading requires that threads give up control so that other threads can execute.

IThread exports functions to start, stop, and suspend threads, as well as functions to set up a callback to be invoked when a thread is resumed, and to set up a callback to be invoked when a thread terminates.

Objective

This document describes how to do the following:

  • Create threads
  • Set up a callback to be invoked when a thread terminates
  • Yield so that other threads can execute

Examples of the above are shown in the sections that follow.

For more information on IThread, see the C/C++API Reference.

Requirements

The application needs to include AEEThread.h.

Sample code location

The c_samplethread sample code shown in this document creates three threads:

  • Thread 1 displays a timer
  • Thread 2 displays an arc that moves around a circle
  • Thread 3 displays the degree used for the starting angle of the arc drawn by Thread 2

When the timer in thread1 reaches the maximum value, it sets the bTimerIsUp flag to notify the other threads to exit.

Note: The example code shown in this document is for thread 1 in c_samplethread. The code for threads 2 and 3 is similar.

There is second IThread example application in Resources on the Brew MP Developer Network, c_samplethread_balls, which shows a more complex use of threads.

ZIP filename

Location

Run app

c_samplethread

Brew MP Resources

  • Download and extract the ZIP file.
  • Compile the app.
  • Run it on the Brew MP Simulator.
c_samplethread_balls

Running the sample code

When you run c_samplethread on the simulator or on a device, you can use the following keys to change the application behavior:

"1" - stop thread 1 when running

"2" - stop thread 2 when running

"3" - stop thread 3 when running

"select" - relaunch all threads if thread 1 has finished

"up" - speed up the moving arc (displayed by thread 2)

"down" - slow down the moving arc

"left" - increase the size of the arc

"right" - decrease the size of the arc

Using Bitmap Interfaces

Base version: Brew MP 1.0
Tested version: Brew MP 1.0
Phone tested: Yes

Applications can use the Brew® Mobile Platform (Brew MP) IBitmap, IBitmapFX, and IBitmapScale interfaces to rotate or scale bitmap images, as well as add effects such as negative or grayscale.

The code examples shown in this document are from the c_samplebitmap application, which allows the user to select an image from a gallery, then select an effect from the Options menu, which is added to the bitmap and redisplayed.

Objective

This document shows how to use the IBitmap, IBitmapFX, and IBitmapScale interfaces to do the following:

  • Rotate a bitmap
  • Scale a bitmap
  • Add effects to a bitmap

Requirements

To use the IBitmap, IBitmapFX, and IBitmapScale interfaces, the following files needed to be included in the application:

  • AEEBitmap.h
  • AEEIBitmapFX.h
  • AEEIBitmapScale.h
  • AEEBitmapFX.bid
  • AEEBilinearScale.bid

Sample code location

ZIP filename

Location

Run app

c_samplebitmap.zip

Brew MP Resources

  • Download and extract the ZIP file.
  • Compile the app.
  • Run it on the Brew MP Simulator.

Note: To compile the sample application and run it on a device, you need the Visual Studio plugin, which can be installed from the Brew MP Launcher. You will also need the appropriate compiler for the device.

When running the application, you can save an image after adding effects. If you are running the application on a device, the newly saved image will be displayed on the screen in the gallery. The new image is not displayed in the gallery when you run the application on the simulator.

Using SMS

Base version:

Brew MP 1.0 rev 2.2

Tested version:

Brew MP 1.0 rev 1.0.6.762186

Phone tested:

Yes

Objective

This topic explains how to use the Brew® Mobile Platform (Brew MP) Short Message System (SMS) interfaces.

The example code in this topic is from the c_samplesms application, which you can download from the How To section of the Brew MP Resources. You can extract the contents of the zip file and then compile the application and run it on the Brew MP Simulator.

For information on using the Simulator to test SMS messages, see the SMS topic in the "Simulation Tools" section in the Brew MP Tools Reference.

Requirements

To use the ISMS interface, you must have:

  • A Brew MP enabled device.
  • The Brew MP 1.0 SDK rev 1.0.6.762186 or greater.
  • A MIF with privileges for AEEPRIVID_PLTapi.
  • If your application uses ISMSStorage, the MIF must have the privilege for AEECLSID_SMSMAINCLIENT.

This document assumes that you are familiar with the Brew MP C Application Primer.

Sample code location

ZIP filename

Location

Run app

c_samplesms_Brew_MP or c_samplesms_BREW_31x

Brew MP Library

  • Download and extract the ZIP file.

  • Compile the app.

  • Run it on the Simulator.

Using OpenGL in Brew Mobile Platform Applications

Base version:

Brew MP 1.0

Tested version:

Brew MP 1.0

Phone tested:

No

To provide support for OpenGL, Brew® Mobile Platform (Brew MP) includes two functions, EGL_Init() and GLES_Init(), that an application can call to do the initialization required to use OpenGL APIs in a Brew MP application. After this initialization is done, the application can call standard OpenGL functions.

Brew MP also includes EGL_Release() and GLES_Release() functions that should be called to release EGL and GL resources when the application is finished using EGL and OpenGL. No EGL calls can be made after calling EGL_Release(). No GL calls can be made after calling GLES_Release().

Note: Brew MP supports OpenGL ES 1.1 and EGL 1.3.

It is assumed that you are familiar with OpenGL programming. For more information on OpenGL ES and EGL, see http://www.opengl.org/.

Objective

This topic describes how to use OpenGL functions in a Brew MP application and shows examples of the required initialization.

Requirements

An application that uses OpenGL needs to do the following:

  • Include the following files from $(BREWMPSDK)\media\inc:
    • EGL_1x.h
    • GLES_1x.h
    • gles/egl.h
    • gles/gl.h
  • Before making any calls to OpenGL functions, call EGL_Init(), then call GLES_Init().
  • Call GLES_Release() and EGL_Release() before exiting.

In addition, when you compile an application that uses OpenGL, you need to do the following:

  • Specify $(BREWMPSDK)\media\opengles\lib\Win32_Release as an additional library directory.

    Note: If you are compiling for a device instead of the simulator, the $(BREWMPSDK)\media\opengles\lib directory also contains ADS12arm9_Release and RVCT22arm11_Release directories that contain libraries for the ADS and RVCT compilers.

  • Specify OGLExtension.lib as a required library.

Sample code location

Two versions of the sample code are available:

  • c_drawtriangle is for Brew MP 1.0.0
  • c_drawtriangle_1_0_1 is for Brew MP 1.0.1

ZIP filename

Location

Run app

c_drawtriangle

Brew MP Resources

  • Download and extract the ZIP file.
  • Compile the app.
  • Run it on the Brew MP Simulator.
c_drawtriangle_1_0_1

Example - initialization

The code examples in this section are from the c_drawTriangle sample. InitGLSurface(), which is called from c_drawTriangle_InitAppData(), calls EGL_Init() and GLES_Init() before calling EGL functions to setup the EGL display and EGL surface.

   if (EGL_Init( pMe->a.m_pIShell ) != SUCCESS)   
   {   
      return FALSE;   
   }   
   
   if (GLES_Init( pMe->a.m_pIShell ) != SUCCESS)   
   {   
      return FALSE;   
   }

Example - rendering

After c_drawTriangle_InitAppData() is called, the application sets a timer. When the timer expires, the RenderLoopTimerNotify() callback function is called, which draws the triangles and resets the timer. RenderLoopTimerNotify() calls Render(), which calls drawTriAngle() to draw the 3D geometry, then calls eglSwapBuffers() to swap the front buffer and back buffer, as shown in the following example:

void Render(c_drawTriangle* pMe, uint32 currTime) 
{ 
   drawTriAngle(pMe,currTime); 
   eglSwapBuffers(pMe->eglDisplay, pMe->eglSurface); 
} 
 
//------------------------------------------------------------------ 
void RenderLoopTimerNotify(void* pi) 
//------------------------------------------------------------------ 
{ 
   c_drawTriangle* pMe = (c_drawTriangle*)pi; 
   uint32 currTimeMs = ISHELL_GetUpTimeMS(pMe->a.m_pIShell); 
 
   Render(pMe, currTimeMs);   
   ISHELL_SetTimer(pMe->a.m_pIShell, REFRESH_IN_MS,
               (PFNNOTIFY)RenderLoopTimerNotify, pMe); 
}

Example - freeing resources

The FreeGLSurface() function, which is called from c_drawTriangle_FreeAppData() and DisplayErrorMsg(), calls a number of EGL functions to free resources, then calls GLES_Release() and EGL_Release():

   if (pMe->eglDisplay != EGL_NO_DISPLAY)   
   {   
      eglMakeCurrent( EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE,
                  EGL_NO_CONTEXT );   
      eglDestroyContext( pMe->eglDisplay, pMe->eglContext );   
      eglDestroySurface( pMe->eglDisplay, pMe->eglSurface );   
      eglTerminate( pMe->eglDisplay );   
      pMe->eglDisplay = EGL_NO_DISPLAY;   
   
      GLES_Release();   
      EGL_Release();   
   }

Related information

Creating a Custom Touch Controller that Uses Virtual Input

Base version:

Brew® MP 1.0.2

Tested version:

Brew MP 1.0.2

Phone tested:

No

Objective

This document describes how to create a custom touch controller to add virtual input support to a widget.

The sample code uses the standard DateTimeWidget and adds the touch controller logic necessary to initiate a virtual input request and retrieve user data.

Requirements

Virtual input is a flexible graphical interface that represents some sort of input device, such as a twelve key keypad or a full keyboard. However, not all widgets should use virtual input, since most do not require any user input beyond basic touch functionality. The best candidates for widgets that can support virtual input are ones that require either numerical or text input, such as TextWidget.

In this example, a custom touch controller is created for the DateTimeWidget, which will allow users to enter a date or a time using the default virtual keypad. This touch controller acts an an extension to the default DateTimeTouchController to add virtual input support to this widget.

There are two requirements for virtual input to work:

  • The application must enable touch on the root container.
  • The application must enable virtual input on the root container.
Refer to the C/C++ API Reference for more information.

Example code location

ZIP filename

Location

Run app

c_virtualinputdatetimewidget_extension

c_virtualinputdatetimewidget_app

Brew MP Resources

  • Download and extract the ZIP file.

  • Compile the extension.

  • Compile the app.

  • Run it on the Brew MP Simulator.

Initialization

This include is needed to create a touch controller that uses virtual input.

#include "AEEVirtualInputHelpers.h"

The PROPEX_VIRTUALINPUT_ENABLE property must be handled by the touch controller, which is sent to enable/disable virtual input automatically when the widget is inserted within a virtual input-enabled root container.

When disabling virtual input, all listeners must be properly cancelled, and any state enabled during initialization must be reset.

static boolean VirtualInputDateTimeTC_HandleSetPropEx(VirtualInputDateTimeTC *pMe,
            ControllerPropEx* pPropEx )   
{   
...   
      case PROPEX_VIRTUALINPUT_ENABLE:   
         if (pPropEx->nSize == (int)sizeof(boolean)) {   
            if (TRUE == *(boolean*)pPropEx->pUser) {   
               VirtualInputDateTimeTC_InitVirtualInputMgr(pMe);   
            }   
            else{   
               LISTENER_Cancel(&pMe->mlRCViewModel);   
               VirtualInputDateTimeTC_Detach(pMe);   
               RELEASEIF(pMe->picVirtualInputMgr);   
            }   
            bHandled = TRUE;   
         }   
         break;   
...   
}

The following function is used when virtual input is first initialized for the DateTimeWidget.

static __inline void VirtualInputDateTimeTC_InitVirtualInputMgr(VirtualInputDateTimeTC *pMe){   
...

A listener must be attached to the root container's view model to receive notifications in case the current Virtual Input Manager is changed.

...   
   //Attach listener to the RC's view model   
   ERR_TRY( IWIDGET_GetRootContainer(pMe->piwChild, &piwRoot) );   
   ERR_TRY( IWidget_GetViewModel(piwRoot, &pimRCViewModel) );   
      
   LISTENER_Cancel(&pMe->mlRCViewModel);   
   ERR_TRY( IModel_AddListenerEx((IModel*)pimRCViewModel, &pMe->mlRCViewModel,  
   (PFNLISTENER)VirtualInputDateTimeTC_RootViewModelListener, pMe) );   

To ensure no orphans, all references to the previous Virtual Input Manager are released and the listeners are cancelled.

   //Detach previous virtual input manager, if set   
   if (pMe->bVirtualInputMode && pMe->picVirtualInputMgr) {   
      LISTENER_Cancel(&pMe->mlVirtualInputStatus);   
      (void)IController_SetVirtualInputTargetWidget(pMe->picVirtualInputMgr, NULL);   
   }   
   RELEASEIF(pMe->picVirtualInputMgr);

Retrieve the current Virtual Input Manager from the root container for future reference.

   //Grab the virtual input manager   
   ERR_TRY(IWidget_GetVirtualInputMgr(piwRoot, &pMe->picVirtualInputMgr) );   
...   
}

Showing the Virtual Keypad

Initiate a virtual input request on pointer events, namely EVT_POINTER_UP.

static boolean VirtualInputDateTimeTC_HandleEvent(void *pCxt, AEEEvent eCode,
            uint16 wParam, uint32 dwParam){   
...   
   case EVT_POINTER_UP:   
      //If we're virtual input enabled and we're not currently already   
      //awaiting input from the virtual keypad, initiate a virtual input query   
      if (NULL != pMe->picVirtualInputMgr && !pMe->bVirtualInputMode) {   
         VirtualInputDateTimeTC_StartVirtualInputRequest(pMe);   
      }   
      bHandled = TRUE;   
      break;   
...

The following function is called to set up and display the virtual keypad.

static __inline void VirtualInputDateTimeTC_StartVirtualInputRequest(VirtualInputDateTimeTC *pMe) {   
...   
   //Set self as target   
   ERR_TRY( IController_SetVirtualInputTargetWidget(pMe->picVirtualInputMgr,
               pMe->piwChild) );   
      
   //Attach model   
   ERR_TRY( IController_GetVirtualInputStatusModel(pMe->picVirtualInputMgr,
               &pimStatusModel) );   
   ERR_TRY( IModel_AddListenerEx(pimStatusModel, &pMe->mlVirtualInputStatus,  
   (PFNLISTENER)VirtualInputDateTimeTC_VirtualInputStatusListener, (void*)pMe) );   
   //Update input mode of keypad widget to give us numbers.   
   ERR_TRY( IController_SetVirtualInputLayoutMode(pMe->picVirtualInputMgr, FALSE,
               AEE_TLANG_NUMBERS) );   
      
   //Update virtual input flag to active   
   pMe->bVirtualInputMode = TRUE;   
   ERR_TRY( IController_ShowVirtualInputFrame(pMe->picVirtualInputMgr) );   
...

Closing the Virtual Keypad

When the user presses the finish button, dismiss button, or clicks on a different widget, the status model of the Virtual Input Manager will send a notification. The touch controller must deal appropriately with each notification to ensure a proper and constant behavior.

The function must first ensure that the event is meant for this particular widget.

static void VirtualInputDateTimeTC_VirtualInputStatusListener(VirtualInputDateTimeTC *pMe,
            ModelEvent *pe)   
{   
...      
   //If we're not currently waiting for input data and we get this notification,   
   //we should detach ourselves.   
   if (!pMe->bVirtualInputMode) {   
      LISTENER_Cancel(&pMe->mlVirtualInputStatus);   
      return;   
   }   
   
   //We only care out status changes   
   if (EVT_MDL_VIRTUALINPUT_STATUS_CHANGE != pe->evCode) {   
      return;   
   }   
      
   //Disable listener if we are not the current target for the virtual input   
   nErr = IController_GetVirtualInputTargetWidget(pMe->picVirtualInputMgr, &piwTarget);   
   if (SUCCESS != nErr || pMe->piwChild != piwTarget) {   
      LISTENER_Cancel(&pMe->mlVirtualInputStatus);   
      pMe->bVirtualInputMode = FALSE;   
      RELEASEIF(piwTarget);   
      return;   
   }   
   RELEASEIF(piwTarget);

The touch controller must take different actions based on which status is received.

If VIRTUALINPUT_STATUS_ACCEPT is received, it means the user is finished entering data, and the keypad should be hidden.

   switch (ev->nStatus) {   
      case VIRTUALINPUT_STATUS_ACCEPT:   
         //On accept close the window.   
         VirtualInputDateTimeTC_Detach(pMe);   
         break;   
            

The status VIRTUALINPUT_STATUS_MOVE is sent when another widget initiates a virtual input request due to user interaction. The touch controller must respond by cancelling the listener but should not try to hide the keypad since another widget requires it.

      case VIRTUALINPUT_STATUS_MOVE:   
         //On move, only cancel the listener.   
         LISTENER_Cancel(&pMe->mlVirtualInputStatus);   
         pMe->bVirtualInputMode = FALSE;   
         break;

When a VIRTUALINPUT_STATUS_CANCEL status is received, the virtual keypad is dismissed. If a buffer is available, the touch controller ignores it's content.

      case VIRTUALINPUT_STATUS_CANCEL:   
         //On cacel, close the window   
         VirtualInputDateTimeTC_Detach(pMe);   
         break;   
...   

Dtor

Dtor is called when the base DateTimeTouchController reaches a reference count of zero. All references are released and listeners canceled.

static void VirtualInputDateTimeTC_Dtor(void *pCxt)   
{   
   VirtualInputDateTimeTC* pMe = (VirtualInputDateTimeTC*) pCxt;   
      
   //Relase all references, cancel all listeners   
   VirtualInputDateTimeTC_Detach(pMe);   
   LISTENER_Cancel(&pMe->mlRCViewModel);   
   HANDLERDESC_FREE(&pMe->hdBase);   
   RELEASEIF(pMe->picVirtualInputMgr);   
   RELEASEIF(pMe->piEnv);   
}

Related information

For more information, see

  • The Widgets Technology Guide
  • The Widgets Touchscreen Technology Guide

Pages

Subscribe to developer.brewmp.com RSS