October 23, 2016
Hot Topics:

Using Palm Device Hardware Buttons in Your Application

  • June 18, 2003
  • By Alex Gusev
  • Send Email »
  • More Articles »

Method II: Handling user input

Up to now all looks fine and optimistical, but... PalmOS has no keyUpEvent, so you can't know when button is released. If you are going to program some game application, such a knowledge seems to be a must. PalmOS API, being rich API,  has Key Manager, which allows managing hardware button's input and behavior, i.e. which buttons are enabled or disabled and so forth. Let's examine which opportunities we do have.

In KeyMgr.h you may found following three functions:

UInt32 KeySetMask(UInt32 keyMask);
UInt32 KeyCurrentState(void);
Err    KeyRates(Boolean set, UInt16 *initDelayP, UInt16 *periodP, UInt16 *doubleTapDelayP, Boolean *queueAheadP);

They allows you to enable/disable desired buttons, check current buttons state and set up reaction rates. Thus the idea is to poll user input periodically. Again, the point to do it is in EventLoop function before any other event processing. In addition, in this case application should swallow unnecessary hardware keyDown events, if you don't want to allow using other butons than allowed ones.

First, you should call KeySetMask if you want to declare which buttons will remain active. This function takes single 4-byte sized parameter as bit mask of keys. All them are defined in KeyMgr.h (default is keyBitsAll, of course) :

 * Definition of bit field returned from KeyCurrentState
#define	keyBitPower		0x0001		// Power key
#define	keyBitPageUp		0x0002		// Page-up
#define	keyBitPageDown		0x0004		// Page-down
#define	keyBitHard1		0x0008		// App #1
#define	keyBitHard2		0x0010		// App #2
#define	keyBitHard3		0x0020		// App #3
#define	keyBitHard4		0x0040		// App #4
#define	keyBitCradle		0x0080		// Button on cradle
#define	keyBitAntenna		0x0100		// Antenna "key"
#define	keyBitContrast		0x0200		// Contrast key

#define	keyBitsAll		0xFFFFFFFF	// all keys

Each bit in mask presents one button, so you may combine them in any desired combinations. Just be aware of getting entangled with HotSync key and power button, because they are important for device's usability, don't they :) ?

Application masks those keys it is going to use, because we are planning to poll them instead of handling keyDown events. Second, call KeyRates to set up repetition timeouts and so forth. Its parameters are enough self-documented by their mnemonics. And finally, during polling, KeyCurrentState returns you current state of hardware buttons similar to KeySetMask. What's left for you is to check this state and respond as needed.

Following sample illustrates all the flow (extracted from Reptoids sample of Palm SDK):

// This function should be called somewhere to mask keys
static void GameMaskKeys ()
	Word initDelay;
	Word period;
	Boolean queueAhead;
	// Set the keys we poll to not generate events.  This saves cpu cycles.
	// Also set the key repeat rate low to avoid constantly checking them.
	initDelay = slowestKeyDelayRate;
	period = slowestKeyPeriodRate;
	queueAhead = false;
	KeyRates(true, &initDelay, &period, &period, &queueAhead);
DWord ConsoleGetInput()
      DWord hardKeyState = KeyCurrentState() & keysAllowedMask;
      // Handle it as needed
      return hardKeyState;
void EventLoop (void)
	Word error;
	EventType event;
	DWord dwKeyState = 0;

		// Wait until the next game period.
		EvtGetEvent (&event, TimeUntillNextPeriod());
		// if it's time to poll , do it
		if ( TimeUntillNextPeriod() == 0 )
		   dwKeyState = ConsoleGetInput();
		   if (event.eType == nilEvent)
		// Intercept the hard keys to prevent them from switching apps
		if (event.eType == keyDownEvent)
			// Swallow events notifying us of key presses.  We poll instead.
			if (event.data.keyDown.chr >= hard1Chr &&
			    event.data.keyDown.chr <= hard4Chr &&
			    !(event.data.keyDown.modifiers & poweredOnKeyMask))
                // Here standard sequence is presented
                if (! SysHandleEvent (&event))
			if (! MenuHandleEvent (0, &event, &error))
				if (! ApplicationHandleEvent (&event))
					FrmDispatchEvent (&event);
         while (event.eType != appStopEvent);

EvtGetEvent is commanded to wait for events during fixed period. After timeout is over, it returns event occured or nilEvent if there were no events at all. In such case we just continue the event loop. Besides this, hardware keys are intercepted as we have discussed above. Another important thing is to properly set key rate values to avoid CPU overloading.


As we have seen, there are at least two methods of managing hardware keys behavior. When comparing them, you should take into account the required functionality for your application. The first method is simplier, but it doesn't give you all the data. From the other side, second method is more complex and powerfull, but it doesn't allow you to catch all virtual keyDown events (just see Chars.h for possible vchrXXXX values). Thus, as usually in real programmer's world, the responsibility of choosing proper balanced solution is totally on you :)

About the Author

Alex Gusev started to play with mainframes in the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.

Page 2 of 2

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel