An increasing number of new phones sport rotating screens, with BREW applications able to run whether the screen is in portrait or landscape orientation. Recent versions of Qualcomm BREW provide an alerting mechanism to let you know when the user has rotated the screen, as well as a way to determine the current screen orientation. By using this information and a bit of dynamic layout trickery, you can add dynamic rotation support to your application. In this article, I show you how to determine the current screen orientation and listen for events indicating screen rotation changes.
Setting the Privileges Necessary to Determine Screen Orientation
By default, not all applications are permitted to determine the screen orientation. BREW defines a specific privilege, AEEPRIVID_DISPLAYSETTINGS (0x01030810), that your application must assert before attempting to determine screen orientation. You do this in your application’s MIF, in the Dependencies section, as you see in Figure 1:
Figure 1: Setting privileges in the MIF file.
Of course, don’t forget to document this privilege in your NSTL Specification when you go to submit your application!
Determining Screen Orientation
You’ll need to determine screen orientation any time the screen rotates, as well as when your application launches. You do this by using a call to ISHELL_GetDeviceInfoEx:
int iValue = 0; int iSize = sizeof(iValue); ISHELL_GetDeviceInfoEx(p->a.m_pIShell, AEE_DEVICESTATE_SCR_ORIENTATION, &iValue, &iSize);
AEE_DEVICESTATE_SCR_ORIENTATION returns either SCREEN_ORIENTATION_LANDSCAPE or SCREEN_ORIENTATION_PORTRAIT, and is a guideline as to how the screen should be oriented. It’s up to you to tell the display at what orientation it should actually draw text and controls. This changes how BREW draws into a screen’s bitmap.
Setting Screen Orientation
To set how BREW will draw into the screen’s bitmap, you need to use IDISPLAY_SetPrefs. This interface takes a string indicating the options BREW should apply when writing to the device bitmap, including:
- r:number: Rotate the screen number degrees: typically either ‘0’ or ’90’.
- w:number: Set the screen width to number.
- h:number: Set the screen height to number.
- a:number: Show the annunciators (number=1) or hide the annunciators (number=0).
You concatenate the values into a string, and pass the string to IDISPLAY_SetPrefs. So, for example, you might write something like this:
ISHELL_GetDeviceInfoEx(p->a.m_pIShell, AEE_DEVICESTATE_SCR_ORIENTATION, &iValue, &iSize); switch(iValue) { case SCREEN_ORIENTATION_LANDSCAPE: { STRCPY(szBuffer, "r:90"); p->eCurrScrOrientation = SCREEN_ORIENTATION_LANDSCAPE; // Do any other stuff to indicate we're in landscape mode // here. break; } case SCREEN_ORIENTATION_PORTRAIT: default: { STRCPY(szBuffer, "r:0"); pThis->eCurrScrOrientation = SCREEN_ORIENTATION_PORTRAIT; // Do any other stuff to indicate we're in portrait mode // here. break; } } nError = IDISPLAY_SetPrefs(p->a.m_pIDisplay, szBuffer, STRLEN(szBuffer));
Being Notified of Screen Rotation
You need to test to determine the desired screen orientation at two different places in your application: at startup (to determine how you should lay out your user interface), and whenever the user rotates the screen. But just how do you know when that happens?
BREW sends you an event, EVT_SCR_ROTATE, whenever the user rotates the screen. When you get this event, you can determine the desired screen orientation using ISHELL_GetDeviceInfoEx, and then set the screen orientation using IDISPLAY_SetPrefs. So, if the preceding code listing was in a HandleRotate function, you would add something like the following to your top-level event handler before you pass events to other forms or application states:
Switch( evt )
{
case EVT_APP_START:
HandleRotate( p );
…
return TRUE;case EVT_APP_STOP:
…
return TRUE;case EVT_SCR_ROTATE:
HandleRotate( p );
return TRUE;
… // other events follow
}
When handling the rotation event, you should return TRUE if you intend to change orientation, FALSE otherwise.
Strategies for Dealing with Rotated Layouts
So, what about your application screen layout and logic itself? If you’re working with a legacy application, you’ve got some work ahead of you. You may well need to do some significant re-engineering, as you think best about how to lay out your application in multiple layouts. Even so, this approach can help you whether you’re working with legacy or new code:
- Store graphic assets for different screen orientations in different resource files, and select the resource file based on the current screen orientation when loading the assets.
- Lay out your screen contents in thirds. When the screen rotates, move the top or bottom third of your screen up along either the left or right side of the first two-thirds of the screen (see Figure 2).
Figure 2: Managing screen rotation by dividing your UI into thirds.
The division-by-thirds trick is approximate, and of course requires some considerable thought in laying out your application. It works best with layouts that have a bar of widgets such as buttons or annunciators along one margin; this can be rotated 90° to fit in the remaining space. Of course, games and other applications may have their own unique requirements.
Conclusion
Supporting screen rotation in Qualcomm Brew isn’t hard: It’s a matter of listening for when the screen rotates, determining the desired orientation, and then telling the screen bitmap to orient in the desired way.
Acknowledgments
I’d like to thank Rashmi Garud at Rocket Mobile for her assistance with the article and work in adding screen rotation support to our applications.
About the Author
Ray Rischpater is the chief architect at Rocket Mobile, Inc., specializing in the design and development of messaging and information access applications for today’s wireless devices. Ray Rischpater is the author of several books on software development, including eBay Application Development and Software Development for the QUALCOMM BREW Platform, both available from Apress, and is an active Amateur Radio operator. Contact Ray at kf6gpe@lothlorien.com.