Monday, January 28, 2008

Glutton Keystroke Management

Freeglut has had an open bug for about a year now,

http://sourceforge.net/tracker/index.php?func=detail&aid=1647258&group_id=1032&atid=101032

Basically, what happens is that freeglut takes all keystrokes and ignores them after sending them to the keystroke callback.

For most keys, this is perfectly acceptable. But on Windows, it is common for keyboard junkies to press Alt+F4 rather than undertake the tedium of moving the mouse over to the "x" in the title bar and clicking. Or pressing "Alt+space" to bring up the window's system menu in order to minimize or maximize. If the keystrokes are ignored, then those capabilities disappear!

In glutton, it seemed to me that a simple fix for this bug would be to add a function, "gluttonSetWindowOption", which presents a method to write to a set of "int" options associated with each window. At first, the only option is called "gluttonWindowOptionKeyboardPassToWM". If set to 1, then glutton will send every key stroke to the window manager. On Windows, this means that Alt+F4 will work again, as will Alt+Space.

Here's what I did to make this change. In freeglut_ext.h, I added the following



/*
* Set flags to control window behaviors.
*/
FGAPI void FGAPIENTRY gluttonSetWindowOption( int Option , int );
enum
{ gluttonWindowOptionKeyboardPassToWM
/*
* If 1, key presses will be passed to the window manager.
* If 0, key presses will not be passed to the window manger (old behavior).
*/
};



In freeglut_window.c:



void FGAPIENTRY gluttonSetWindowOption( int Option , int Value )
{
FREEGLUT_EXIT_IF_NOT_INITIALISED( "glutSetWindowOption" );
FREEGLUT_EXIT_IF_NO_WINDOW( "glutSetWindowOption" );
switch( Option )
{
case gluttonWindowOptionKeyboardPassToWM:
fgStructure.CurrentWindow->AllKeysToWindowManager = Value;
break;
}
}



In freeglut_internal.h, I added this to the declaration of tagSFG_Window:



#ifdef GLUTTON
GLboolean AllKeysToWindowManager; /* Set to 1 if all keys should go to window manager */
#endif



Finally, in freeglut_main.c, in the message processing function, I added the following in strategic locations:



#ifdef GLUTTON
if ( window->AllKeysToWindowManager )
lRet = DefWindowProc( hWnd , uMsg , wParam , lParam );
#endif



This happens after any callbacks are made. There is currently no way to prevent a single keystroke from going to the window manager, and there's no reason to have such a method that I can see (right now), other than the desire to ignore Alt+F4 or Alt+Space. Such behavior would be very user-unfriendly IMHO, so I'm not implementing it at this time. But should the need arise, a simple strategy would be to add an option that could be set inside of the callback to withhold the current keystroke from the window manager. The if ( window->AllKeysToWindowManager ) statement would be changed to also check the new option, and an else clause would be added to reset the new option.

Of course, this extension doesn't address X yet. Since I'm getting ready to address X for my last extension (give the user a chance to cancel before closing a window), I'll look into implementing this one there as well. Food for 2 posts already, and I've only just started working on glutton. Nice!

No comments: