#include <sys/stat.h>
#elif TARGET_HOST_WIN32
#elif TARGET_HOST_WINCE
- // including gx.h does only work in c++ (thanks MS...),
- // so we define this on our own...
-struct GXKeyList {
- short vkUp; // key for up
- POINT ptUp; // x,y position of key/button. Not on screen but in screen coordinates.
- short vkDown;
- POINT ptDown;
- short vkLeft;
- POINT ptLeft;
- short vkRight;
- POINT ptRight;
- short vkA;
- POINT ptA;
- short vkB;
- POINT ptB;
- short vkC;
- POINT ptC;
- short vkStart;
- POINT ptStart;
-};
-/*__declspec(dllimport) struct GXKeyList GXGetDefaultKeys(int iOptions);
-__declspec(dllimport) int GXOpenInput();
-#include "my_gx.h"*/
-
-extern void wince_GetDefaultKeys(void* nData, int iOptions);
-extern void wince_OpenInput();
-
-/*void wince_GetDefaultKeys(void* nData, int iOptions)
-{
- *(struct GXKeyList*)nData = GXGetDefaultKeys(iOptions);
-}
-void wince_OpenInput()
-{
- GXOpenInput();
-}*/
+
+typedef struct GXDisplayProperties GXDisplayProperties;
+typedef struct GXKeyList GXKeyList;
+#include <gx.h>
+
+typedef struct GXKeyList (*GXGETDEFAULTKEYS)(int);
+typedef int (*GXOPENINPUT)();
+
+GXGETDEFAULTKEYS GXGetDefaultKeys_ = NULL;
+GXOPENINPUT GXOpenInput_ = NULL;
+
+struct GXKeyList gxKeyList;
#endif
* callback is hooked, the viewport size is updated to
* match the new window size.
*/
-static void fghReshapeWindowByHandle ( SFG_WindowHandleType handle,
- int width, int height )
+static void fghReshapeWindow ( SFG_Window *window, int width, int height )
{
SFG_Window *current_window = fgStructure.Window;
- SFG_Window* window = fgWindowByHandle( handle );
freeglut_return_if_fail( window != NULL );
#if !TARGET_HOST_WINCE
{
- RECT rect;
+ RECT winRect;
+ int x, y, w, h;
/*
* For windowed mode, get the current position of the
* decorations into account.
*/
- GetWindowRect( window->Window.Handle, &rect );
- rect.right = rect.left + width;
- rect.bottom = rect.top + height;
+ /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
+ GetWindowRect( window->Window.Handle, &winRect );
+ x = winRect.left;
+ y = winRect.top;
+ w = width;
+ h = height;
if ( window->Parent == NULL )
{
if ( ! window->IsMenu && !window->State.IsGameMode )
{
- rect.right += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
- rect.bottom += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
- GetSystemMetrics( SM_CYCAPTION );
+ w += GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
+ h += GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
+ GetSystemMetrics( SM_CYCAPTION );
}
}
else
{
- GetWindowRect( window->Parent->Window.Handle, &rect );
- AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
- WS_CLIPCHILDREN, FALSE );
+ RECT parentRect;
+ GetWindowRect( window->Parent->Window.Handle, &parentRect );
+ x -= parentRect.left + GetSystemMetrics( SM_CXSIZEFRAME ) * 2;
+ y -= parentRect.top + GetSystemMetrics( SM_CYSIZEFRAME ) * 2 +
+ GetSystemMetrics( SM_CYCAPTION );
}
/*
SetWindowPos( window->Window.Handle,
HWND_TOP,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
+ x, y, w, h,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
SWP_NOZORDER
);
* Calls a window's redraw method. This is used when
* a redraw is forced by the incoming window messages.
*/
-static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle )
+static void fghRedrawWindow ( SFG_Window *window )
{
- SFG_Window* window = fgWindowByHandle( handle );
+ SFG_Window *current_window = fgStructure.Window;
+
freeglut_return_if_fail( window );
freeglut_return_if_fail( FETCH_WCB ( *window, Display ) );
freeglut_return_if_fail( window->State.Visible );
+ fgSetWindow( window );
+
if( window->State.NeedToResize )
{
- SFG_Window *current_window = fgStructure.Window;
-
- fgSetWindow( window );
-
- fghReshapeWindowByHandle(
- window->Window.Handle,
+ fghReshapeWindow(
+ window,
window->State.Width,
window->State.Height
);
window->State.NeedToResize = GL_FALSE;
- fgSetWindow( current_window );
}
INVOKE_WCB( *window, Display, ( ) );
+
+ fgSetWindow( current_window );
}
/*
static void fghcbDisplayWindow( SFG_Window *window,
SFG_Enumerator *enumerator )
{
- if( window->State.NeedToResize )
- {
- SFG_Window *current_window = fgStructure.Window;
-
- fgSetWindow( window );
-
- fghReshapeWindowByHandle(
- window->Window.Handle,
- window->State.Width,
- window->State.Height
- );
-
- window->State.NeedToResize = GL_FALSE;
- fgSetWindow ( current_window );
- }
-
if( window->State.Redisplay &&
window->State.Visible )
{
window->State.Redisplay = GL_FALSE;
#if TARGET_HOST_UNIX_X11
- {
- SFG_Window *current_window = fgStructure.Window;
-
- INVOKE_WCB( *window, Display, ( ) );
- fgSetWindow( current_window );
- }
+ fghRedrawWindow ( window ) ;
#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
RedrawWindow(
window->Window.Handle, NULL, NULL,
* and all other "joystick timer" code can be yanked.
*
*/
-static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
+static void fghCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
{
if( FETCH_WCB( *w, Joystick ) )
{
e->found = GL_TRUE;
e->data = w;
}
- fgEnumSubWindows( w, fgCheckJoystickCallback, e );
+ fgEnumSubWindows( w, fghCheckJoystickCallback, e );
}
-static int fgHaveJoystick( void )
+static int fghHaveJoystick( void )
{
SFG_Enumerator enumerator;
enumerator.found = GL_FALSE;
enumerator.data = NULL;
- fgEnumWindows( fgCheckJoystickCallback, &enumerator );
+ fgEnumWindows( fghCheckJoystickCallback, &enumerator );
return !!enumerator.data;
}
-static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e)
+static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e)
{
if( w->State.Redisplay )
{
e->found = GL_TRUE;
e->data = w;
}
- fgEnumSubWindows( w, fgHavePendingRedisplaysCallback, e );
+ fgEnumSubWindows( w, fghHavePendingRedisplaysCallback, e );
}
-static int fgHavePendingRedisplays (void)
+static int fghHavePendingRedisplays (void)
{
SFG_Enumerator enumerator;
enumerator.found = GL_FALSE;
enumerator.data = NULL;
- fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator );
+ fgEnumWindows( fghHavePendingRedisplaysCallback, &enumerator );
return !!enumerator.data;
}
/*
* Returns the number of GLUT ticks (milliseconds) till the next timer event.
*/
-static long fgNextTimer( void )
+static long fghNextTimer( void )
{
long ret = INT_MAX;
SFG_Timer *timer = fgState.Timers.First;
* Does the magic required to relinquish the CPU until something interesting
* happens.
*/
-static void fgSleepForEvents( void )
+static void fghSleepForEvents( void )
{
long msec;
- if( fgState.IdleCallback || fgHavePendingRedisplays( ) )
+ if( fgState.IdleCallback || fghHavePendingRedisplays( ) )
return;
- msec = fgNextTimer( );
- if( fgHaveJoystick( ) ) /* XXX Use GLUT timers for joysticks... */
- msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */
+ msec = fghNextTimer( );
+ if( fghHaveJoystick( ) ) /* XXX Use GLUT timers for joysticks... */
+ msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */
#if TARGET_HOST_UNIX_X11
/*
* it is possible to have our socket drained but still have
* unprocessed events. (Or, this may just be normal with
* X, anyway?) We do non-trivial processing of X events
- * after tham in event-reading loop, in any case, so we
+ * after the event-reading loop, in any case, so we
* need to allow that we may have an empty socket but non-
* empty event queue.
*/
wait.tv_usec = (msec % 1000) * 1000;
err = select( socket+1, &fdset, NULL, NULL, &wait );
- if( -1 == err )
- fgWarning ( "freeglut select() error: %d\n", errno );
+ if( ( -1 == err ) && ( errno != EINTR ) )
+ fgWarning ( "freeglut select() error: %d", errno );
}
#elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLEVENTS );
/*
* Returns GLUT modifier mask for an XEvent.
*/
-int fgGetXModifiers( XEvent *event )
+static int fghGetXModifiers( XEvent *event )
{
int ret = 0;
SFG_Window* window;
XEvent event;
- /*
- * This code was repeated constantly, so here it goes into a definition:
- */
+ /* This code was repeated constantly, so here it goes into a definition: */
#define GETWINDOW(a) \
window = fgWindowByHandle( event.a.window ); \
if( window == NULL ) \
switch( event.type )
{
case ClientMessage:
- /*
- * Destroy the window when the WM_DELETE_WINDOW message arrives
- */
+ /* Destroy the window when the WM_DELETE_WINDOW message arrives */
if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.DeleteWindow )
{
GETWINDOW( xclient );
fgDeinitialize( );
exit( 0 );
}
+ else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
- fgState.ExecState = GLUT_EXEC_STATE_STOP;
return;
}
break;
break;
default:
- fgWarning( "Uknown X visibility state: %d",
+ fgWarning( "Unknown X visibility state: %d",
event.xvisibility.state );
break;
}
break;
}
- /*
- * No active menu, let's check whether we need to activate one.
- */
+ /* No active menu, let's check whether we need to activate one. */
if( ( 0 <= button ) &&
( FREEGLUT_MAX_MENUS > button ) &&
( window->Menu[ button ] ) &&
pressed )
{
- /*
- * XXX Posting a requisite Redisplay seems bogus.
- */
+ /* XXX Posting a requisite Redisplay seems bogus. */
window->State.Redisplay = GL_TRUE;
fgSetWindow( window );
fgActivateMenu( window, button );
! FETCH_WCB( *window, MouseWheel ) )
break;
- fgState.Modifiers = fgGetXModifiers( &event );
+ fgState.Modifiers = fghGetXModifiers( &event );
/*
* Finally execute the mouse or mouse wheel callback
);
}
- /*
- * Trash the modifiers state
- */
+ /* Trash the modifiers state */
fgState.Modifiers = 0xffffffff;
}
break;
char keys[32];
XQueryKeymap( fgDisplay.Display, keys ); /* Look at X11 keystate to detect repeat mode */
- if ( keys[event.xkey.keycode>>3] & (1<<(event.xkey.keycode%8)) )
- window->State.KeyRepeating = GL_TRUE;
- else
- window->State.KeyRepeating = GL_FALSE;
+ if ( event.xkey.keycode<256 ) /* XQueryKeymap is limited to 256 keycodes */
+ {
+ if ( keys[event.xkey.keycode>>3] & (1<<(event.xkey.keycode%8)) )
+ window->State.KeyRepeating = GL_TRUE;
+ else
+ window->State.KeyRepeating = GL_FALSE;
+ }
}
}
else
if( keyboard_cb )
{
fgSetWindow( window );
- fgState.Modifiers = fgGetXModifiers( &event );
+ fgState.Modifiers = fghGetXModifiers( &event );
keyboard_cb( asciiCode[ 0 ],
event.xkey.x, event.xkey.y
);
if( special_cb && (special != -1) )
{
fgSetWindow( window );
- fgState.Modifiers = fgGetXModifiers( &event );
+ fgState.Modifiers = fghGetXModifiers( &event );
special_cb( special, event.xkey.x, event.xkey.y );
fgState.Modifiers = 0xffffffff;
}
fgDeinitialize( );
exit( 0 );
}
- fgState.ExecState = GLUT_EXEC_STATE_STOP;
+ else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+
return;
}
if( fgState.IdleCallback )
fgState.IdleCallback( );
- fgSleepForEvents( );
+ fghSleepForEvents( );
}
}
/*
* Determine a GLUT modifer mask based on MS-WINDOWS system info.
*/
-int fgGetWin32Modifiers (void)
+static int fghGetWin32Modifiers (void)
{
return
( ( ( GetKeyState( VK_LSHIFT ) < 0 ) ||
switch( uMsg )
{
case WM_CREATE:
- /*
- * The window structure is passed as the creation structure paramter...
- */
+ /* The window structure is passed as the creation structure paramter... */
window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
assert( window != NULL );
ReleaseDC( window->Window.Handle, window->Window.Device );
#if TARGET_HOST_WINCE
- // Take over button handling
- wince_OpenInput();
+ /* Take over button handling */
+ {
+ HINSTANCE dxDllLib=LoadLibrary(_T("gx.dll"));
+ if (dxDllLib)
+ {
+ GXGetDefaultKeys_=(GXGETDEFAULTKEYS)GetProcAddress(dxDllLib, _T("?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z"));
+ GXOpenInput_=(GXOPENINPUT)GetProcAddress(dxDllLib, _T("?GXOpenInput@@YAHXZ"));
+ }
+
+ if(GXOpenInput_)
+ (*GXOpenInput_)();
+ if(GXGetDefaultKeys_)
+ gxKeyList = (*GXGetDefaultKeys_)(GX_LANDSCAPEKEYS);
+ }
+
#endif /* TARGET_HOST_WINCE */
break;
break;
#if 0
case WM_SETFOCUS:
- printf("WM_SETFOCUS: %p\n", window );
+/* printf("WM_SETFOCUS: %p\n", window ); */
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
break;
if (LOWORD(wParam) != WA_INACTIVE)
{
/* glutSetCursor( fgStructure.Window->State.Cursor ); */
- printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window,
- window->State.Cursor );
+/* printf("WM_ACTIVATE: glutSetCursor( %p, %d)\n", window,
+ window->State.Cursor ); */
glutSetCursor( window->State.Cursor );
}
/* Turn on the visibility in case it was turned off somehow */
window->State.Visible = GL_TRUE;
BeginPaint( hWnd, &ps );
- fghRedrawWindowByHandle( hWnd );
+ fghRedrawWindow( window );
EndPaint( hWnd, &ps );
break;
window->State.MouseX = LOWORD( lParam );
window->State.MouseY = HIWORD( lParam );
#endif /* TARGET_HOST_WINCE */
+ /* Restrict to [-32768, 32767] to match X11 behaviour */
+ /* See comment in "freeglut_developer" mailing list 10/4/04 */
+ if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
+ if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
if ( window->ActiveMenu )
{
break;
}
- fgState.Modifiers = fgGetWin32Modifiers( );
+ fgState.Modifiers = fghGetWin32Modifiers( );
if( ( wParam & MK_LBUTTON ) ||
( wParam & MK_MBUTTON ) ||
window->State.MouseY = HIWORD( lParam );
#endif /* TARGET_HOST_WINCE */
+ /* Restrict to [-32768, 32767] to match X11 behaviour */
+ /* See comment in "freeglut_developer" mailing list 10/4/04 */
+ if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
+ if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
+
switch( uMsg )
{
case WM_LBUTTONDOWN:
break;
}
+ /* Set capture so that the window captures all the mouse messages */
+ /*
+ * XXX - Multiple button support: Under X11, the mouse is not released
+ * XXX - from the window until all buttons have been released, even if the
+ * XXX - user presses a button in another window. This will take more
+ * XXX - code changes than I am up to at the moment (10/5/04). The present
+ * XXX - is a 90 percent solution.
+ */
+ if ( pressed == GL_TRUE )
+ SetCapture ( window->Window.Handle ) ;
+ else
+ ReleaseCapture () ;
+
if( ! FETCH_WCB( *window, Mouse ) )
break;
fgSetWindow( window );
- fgState.Modifiers = fgGetWin32Modifiers( );
+ fgState.Modifiers = fghGetWin32Modifiers( );
INVOKE_WCB(
*window, Mouse,
break;
fgSetWindow( window );
- fgState.Modifiers = fgGetWin32Modifiers( );
+ fgState.Modifiers = fghGetWin32Modifiers( );
while( ticks-- )
if( FETCH_WCB( *window, MouseWheel ) )
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
{
-#if TARGET_HOST_WINCE
- struct GXKeyList gxKeyList;
-#endif /* TARGET_HOST_WINCE */
int keypress = -1;
POINT mouse_pos ;
* Remember the current modifiers state. This is done here in order
* to make sure the VK_DELETE keyboard callback is executed properly.
*/
- fgState.Modifiers = fgGetWin32Modifiers( );
+ fgState.Modifiers = fghGetWin32Modifiers( );
GetCursorPos( &mouse_pos );
ScreenToClient( window->Window.Handle, &mouse_pos );
}
#if TARGET_HOST_WINCE
- if(!(lParam & 0x40000000)) // Prevent auto-repeat
+ if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
{
- wince_GetDefaultKeys(&gxKeyList, 0x03);
-
if(wParam==(unsigned)gxKeyList.vkRight)
keypress = GLUT_KEY_RIGHT;
else if(wParam==(unsigned)gxKeyList.vkLeft)
* Remember the current modifiers state. This is done here in order
* to make sure the VK_DELETE keyboard callback is executed properly.
*/
- fgState.Modifiers = fgGetWin32Modifiers( );
+ fgState.Modifiers = fghGetWin32Modifiers( );
GetCursorPos( &mouse_pos );
ScreenToClient( window->Window.Handle, &mouse_pos );
if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
break;
- fgState.Modifiers = fgGetWin32Modifiers( );
+ fgState.Modifiers = fghGetWin32Modifiers( );
INVOKE_WCB( *window, Keyboard,
( (char)wParam,
window->State.MouseX, window->State.MouseY )
{
/*
* We have received a system command message. Try to act on it.
- * The commands are passed in through the "lParam" parameter:
- * Clicking on a corner to resize the window gives a "F004" message
- * but this is not defined in my header file.
+ * The commands are passed in through the "wParam" parameter:
+ * The least significant digit seems to be which edge of the window
+ * is being used for a resize event:
+ * 4 3 5
+ * 1 2
+ * 7 6 8
+ * Congratulations and thanks to Richard Rauch for figuring this out..
*/
- switch ( lParam )
+ switch ( wParam & 0xfff0 )
{
case SC_SIZE :
break ;
case SC_HOTKEY :
break ;
+
+ default:
+#if _DEBUG
+ fgWarning( "Unknown wParam type 0x%x", wParam );
+#endif
+ break;
}
}
#endif /* !TARGET_HOST_WINCE */