)
SET(FREEGLUT_SRCS
${FREEGLUT_HEADERS}
- src/Common/freeglut_callbacks.c
- src/Common/freeglut_cursor.c
- src/Common/freeglut_display.c
- src/Common/freeglut_ext.c
- src/Common/freeglut_font_data.c
- src/Common/freeglut_gamemode.c
- src/Common/freeglut_init.c
- src/Common/freeglut_internal.h
- src/Common/freeglut_input_devices.c
- src/Common/freeglut_joystick.c
- src/Common/freeglut_main.c
- src/Common/freeglut_misc.c
- src/Common/freeglut_overlay.c
- src/Common/freeglut_spaceball.c
- src/Common/freeglut_state.c
- src/Common/freeglut_stroke_mono_roman.c
- src/Common/freeglut_stroke_roman.c
- src/Common/freeglut_structure.c
- src/Common/freeglut_videoresize.c
- src/Common/freeglut_window.c
+ src/fg_callbacks.c
+ src/fg_cursor.c
+ src/fg_display.c
+ src/fg_ext.c
+ src/fg_font_data.c
+ src/fg_gamemode.c
+ src/fg_init.c
+ src/fg_internal.h
+ src/fg_input_devices.c
+ src/fg_joystick.c
+ src/fg_main.c
+ src/fg_misc.c
+ src/fg_overlay.c
+ src/fg_spaceball.c
+ src/fg_state.c
+ src/fg_stroke_mono_roman.c
+ src/fg_stroke_roman.c
+ src/fg_structure.c
+ src/fg_videoresize.c
+ src/fg_window.c
)
# Android port requires adding a version of these compatible with
# OpenGL ES (TODO):
IF(NOT ANDROID)
LIST(APPEND FREEGLUT_SRCS
- src/Common/freeglut_font.c
- src/Common/freeglut_geometry.c
- src/Common/freeglut_menu.c
- src/Common/freeglut_teapot.c
+ src/fg_font.c
+ src/fg_geometry.c
+ src/fg_menu.c
+ src/fg_teapot.c
)
ENDIF()
-IF(WIN32)
+IF(WIN32) # TODO: is this true for 64 bit as well? Chaneg to WINDOWS?
LIST(APPEND FREEGLUT_SRCS
- src/Common/xparsegeometry_repl.c
- src/Common/xparsegeometry_repl.h
- src/mswin/freeglut_cursor_mswin.c
- src/mswin/freeglut_display_mswin.c
- src/mswin/freeglut_ext_mswin.c
- src/mswin/freeglut_gamemode_mswin.c
- src/mswin/freeglut_init_mswin.c
- src/mswin/freeglut_internal_mswin.h
- src/mswin/freeglut_input_devices_mswin.c
- src/mswin/freeglut_joystick_mswin.c
- src/mswin/freeglut_main_mswin.c
- src/mswin/freeglut_menu_mswin.c
- src/mswin/freeglut_spaceball_mswin.c
- src/mswin/freeglut_state_mswin.c
- src/mswin/freeglut_structure_mswin.c
- src/mswin/freeglut_window_mswin.c
+ src/util/xparsegeometry_repl.c # TODO: instead of this, detect if function is available and include if not
+ src/util/xparsegeometry_repl.h
+ src/mswin/fg_cursor_mswin.c
+ src/mswin/fg_display_mswin.c
+ src/mswin/fg_ext_mswin.c
+ src/mswin/fg_gamemode_mswin.c
+ src/mswin/fg_init_mswin.c
+ src/mswin/fg_internal_mswin.h
+ src/mswin/fg_input_devices_mswin.c
+ src/mswin/fg_joystick_mswin.c
+ src/mswin/fg_main_mswin.c
+ src/mswin/fg_menu_mswin.c
+ src/mswin/fg_spaceball_mswin.c
+ src/mswin/fg_state_mswin.c
+ src/mswin/fg_structure_mswin.c
+ src/mswin/fg_window_mswin.c
)
ELSEIF(ANDROID)
LIST(APPEND FREEGLUT_SRCS
- src/Common/xparsegeometry_repl.c
- src/Common/xparsegeometry_repl.h
- src/egl/freeglut_internal_egl.h
- src/egl/freeglut_display_egl.c
- src/egl/freeglut_init_egl.c
- src/egl/freeglut_structure_egl.c
- src/egl/freeglut_window_egl.c
+ src/util/xparsegeometry_repl.c
+ src/util/xparsegeometry_repl.h
+ src/egl/fg_internal_egl.h
+ src/egl/fg_display_egl.c
+ src/egl/fg_init_egl.c
+ src/egl/fg_structure_egl.c
+ src/egl/fg_window_egl.c
src/android/native_app_glue/android_native_app_glue.c
src/android/native_app_glue/android_native_app_glue.h
- src/android/freeglut_runtime_android.c
- src/android/freeglut_gamemode_android.c
- src/android/freeglut_input_devices_android.c
- src/android/freeglut_joystick_android.c
- src/android/freeglut_main_android.c
- src/android/freeglut_spaceball_android.c
- src/android/freeglut_state_android.c
- src/android/freeglut_window_android.c
+ src/android/fg_runtime_android.c
+ src/android/fg_gamemode_android.c
+ src/android/fg_input_devices_android.c
+ src/android/fg_joystick_android.c
+ src/android/fg_main_android.c
+ src/android/fg_spaceball_android.c
+ src/android/fg_state_android.c
+ src/android/fg_window_android.c
src/android/opengles_stubs.c
- src/android/freeglut_internal_android.h
+ src/android/fg_internal_android.h
)
ELSE()
LIST(APPEND FREEGLUT_SRCS
- src/x11/freeglut_cursor_x11.c
- src/x11/freeglut_display_x11.c
- src/x11/freeglut_ext_x11.c
- src/x11/freeglut_gamemode_x11.c
- src/x11/freeglut_glutfont_definitions_x11.c
- src/x11/freeglut_init_x11.c
- src/x11/freeglut_internal_x11.h
- src/x11/freeglut_input_devices_x11.c
- src/x11/freeglut_joystick_x11.c
- src/x11/freeglut_main_x11.c
- src/x11/freeglut_menu_x11.c
- src/x11/freeglut_spaceball_x11.c
- src/x11/freeglut_state_x11.c
- src/x11/freeglut_structure_x11.c
- src/x11/freeglut_window_x11.c
- src/x11/freeglut_xinput_x11.c
+ src/x11/fg_cursor_x11.c
+ src/x11/fg_display_x11.c
+ src/x11/fg_ext_x11.c
+ src/x11/fg_gamemode_x11.c
+ src/x11/fg_glutfont_definitions_x11.c
+ src/x11/fg_init_x11.c
+ src/x11/fg_internal_x11.h
+ src/x11/fg_input_devices_x11.c
+ src/x11/fg_joystick_x11.c
+ src/x11/fg_main_x11.c
+ src/x11/fg_menu_x11.c
+ src/x11/fg_spaceball_x11.c
+ src/x11/fg_state_x11.c
+ src/x11/fg_structure_x11.c
+ src/x11/fg_window_x11.c
+ src/x11/fg_xinput_x11.c
)
--- /dev/null
+/*
+ * freeglut_cursor_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Thu Jan 19, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+
+void fgPlatformSetCursor ( SFG_Window *window, int cursorID )
+{
+ /*
+ * Joe Krahn is re-writing the following code.
+ */
+ /* Set the cursor AND change it for this window class. */
+#if !defined(__MINGW64__) && _MSC_VER <= 1200
+# define MAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( LoadCursor( NULL, b ) ); \
+ SetClassLong( window->Window.Handle, \
+ GCL_HCURSOR, \
+ ( LONG )LoadCursor( NULL, b ) ); \
+ break;
+ /* Nuke the cursor AND change it for this window class. */
+# define ZAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( NULL ); \
+ SetClassLong( window->Window.Handle, \
+ GCL_HCURSOR, ( LONG )NULL ); \
+ break;
+#else
+# define MAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( LoadCursor( NULL, b ) ); \
+ SetClassLongPtr( window->Window.Handle, \
+ GCLP_HCURSOR, \
+ ( LONG )( LONG_PTR )LoadCursor( NULL, b ) ); \
+ break;
+ /* Nuke the cursor AND change it for this window class. */
+# define ZAP_CURSOR(a,b) \
+ case a: \
+ SetCursor( NULL ); \
+ SetClassLongPtr( window->Window.Handle, \
+ GCLP_HCURSOR, ( LONG )( LONG_PTR )NULL ); \
+ break;
+#endif
+
+ switch( cursorID )
+ {
+ MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
+ MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
+ MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP );
+ MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
+ MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
+ MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
+ MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_IBEAM );
+ MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
+ MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_SIZENS );
+ MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT, IDC_SIZEWE );
+ MAP_CURSOR( GLUT_CURSOR_TOP_SIDE, IDC_ARROW ); /* XXX ToDo */
+ MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE, IDC_ARROW ); /* XXX ToDo */
+ MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE, IDC_ARROW ); /* XXX ToDo */
+ MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE, IDC_ARROW ); /* XXX ToDo */
+ MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER, IDC_SIZENWSE );
+ MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER, IDC_SIZENESW );
+ MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE );
+ MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER, IDC_SIZENESW );
+ MAP_CURSOR( GLUT_CURSOR_INHERIT, IDC_ARROW ); /* XXX ToDo */
+ ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
+ MAP_CURSOR( GLUT_CURSOR_FULL_CROSSHAIR, IDC_CROSS ); /* XXX ToDo */
+
+ default:
+ fgError( "Unknown cursor type: %d", cursorID );
+ break;
+ }
+}
+
+
+void fgPlatformWarpPointer ( int x, int y )
+{
+ POINT coords;
+ coords.x = x;
+ coords.y = y;
+
+ /* ClientToScreen() translates {coords} for us. */
+ ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
+ SetCursorPos( coords.x, coords.y );
+}
+
+
--- /dev/null
+/*
+ * freeglut_display_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sat Jan 28, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+
+
+void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow )
+{
+ SwapBuffers( CurrentWindow->Window.pContext.Device );
+}
--- /dev/null
+/*
+ * freeglut_ext_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Thu Jan 19, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+GLUTproc fgPlatformGetGLUTProcAddress( const char* procName )
+{
+#if !defined(_WIN32_WCE)
+ /* optimization: quick initial check */
+ if( strncmp( procName, "glut", 4 ) != 0 )
+ return NULL;
+
+#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x;
+ CHECK_NAME(glutJoystickFunc);
+ CHECK_NAME(glutForceJoystickFunc);
+ CHECK_NAME(glutGameModeString);
+ CHECK_NAME(glutEnterGameMode);
+ CHECK_NAME(glutLeaveGameMode);
+ CHECK_NAME(glutGameModeGet);
+#undef CHECK_NAME
+#endif /* !defined(_WIN32_WCE) */
+
+ return NULL;
+}
+
+
+
+SFG_Proc fgPlatformGetProcAddress( const char *procName )
+{
+ return (SFG_Proc)wglGetProcAddress( ( LPCSTR )procName );
+}
--- /dev/null
+/*
+ * freeglut_gamemode_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Thu Jan 19, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+/*
+ * Remembers the current visual settings, so that
+ * we can change them and restore later...
+ */
+void fgPlatformRememberState( void )
+{
+ /* Grab the current desktop settings... */
+
+ /* hack to get around my stupid cross-gcc headers */
+ #define FREEGLUT_ENUM_CURRENT_SETTINGS -1
+
+ EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS,
+ &fgDisplay.pDisplay.DisplayMode );
+
+ /* Make sure we will be restoring all settings needed */
+ fgDisplay.pDisplay.DisplayMode.dmFields |=
+ DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
+
+}
+
+/*
+ * Restores the previously remembered visual settings
+ */
+void fgPlatformRestoreState( void )
+{
+ /* Restore the previously remembered desktop display settings */
+ ChangeDisplaySettingsEx( fgDisplay.pDisplay.DisplayName,&fgDisplay.pDisplay.DisplayMode, 0,0,0 );
+}
+
+
+
+
+/*
+ * Changes the current display mode to match user's settings
+ */
+GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )
+{
+ GLboolean success = GL_FALSE;
+ DEVMODE devMode;
+ char *fggmstr = NULL;
+ char displayMode[300];
+
+ success = GL_FALSE;
+
+ EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, -1, &devMode );
+ devMode.dmFields = 0;
+
+ if (fgState.GameModeSize.X!=-1)
+ {
+ devMode.dmPelsWidth = fgState.GameModeSize.X;
+ devMode.dmFields |= DM_PELSWIDTH;
+ }
+ if (fgState.GameModeSize.Y!=-1)
+ {
+ devMode.dmPelsHeight = fgState.GameModeSize.Y;
+ devMode.dmFields |= DM_PELSHEIGHT;
+ }
+ if (fgState.GameModeDepth!=-1)
+ {
+ devMode.dmBitsPerPel = fgState.GameModeDepth;
+ devMode.dmFields |= DM_BITSPERPEL;
+ }
+ if (fgState.GameModeRefresh!=-1)
+ {
+ devMode.dmDisplayFrequency = fgState.GameModeRefresh;
+ devMode.dmFields |= DM_DISPLAYFREQUENCY;
+ }
+
+ switch ( ChangeDisplaySettingsEx(fgDisplay.pDisplay.DisplayName, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
+ {
+ case DISP_CHANGE_SUCCESSFUL:
+ success = GL_TRUE;
+
+ if (!haveToTest)
+ {
+ /* update vars in case if windows switched to proper mode */
+ EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
+ fgState.GameModeSize.X = devMode.dmPelsWidth;
+ fgState.GameModeSize.Y = devMode.dmPelsHeight;
+ fgState.GameModeDepth = devMode.dmBitsPerPel;
+ fgState.GameModeRefresh = devMode.dmDisplayFrequency;
+ }
+ break;
+ case DISP_CHANGE_RESTART:
+ fggmstr = "The computer must be restarted for the graphics mode to work.";
+ break;
+ case DISP_CHANGE_BADFLAGS:
+ fggmstr = "An invalid set of flags was passed in.";
+ break;
+ case DISP_CHANGE_BADPARAM:
+ fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
+ break;
+ case DISP_CHANGE_FAILED:
+ fggmstr = "The display driver failed the specified graphics mode.";
+ break;
+ case DISP_CHANGE_BADMODE:
+ fggmstr = "The graphics mode is not supported.";
+ break;
+ default:
+ fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible,MSDN does not mention any other error */
+ break;
+ }
+
+ if ( !success )
+ {
+ /* I'd rather get info whats going on in my program than wonder about */
+ /* magic happenings behind my back, its lib for devels at last ;) */
+
+ /* append display mode to error to make things more informative */
+ sprintf(displayMode,"%s Problem with requested mode: %ix%i:%i@%i", fggmstr, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmDisplayFrequency);
+ fgWarning(displayMode);
+ }
+
+ return success;
+}
+
+void fgPlatformEnterGameMode( void )
+{
+}
+
+void fgPlatformLeaveGameMode( void )
+{
+}
--- /dev/null
+/*
+ * freeglut_init_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Thu Jan 19, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+
+extern LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam );
+
+
+/*
+ * A call to this function should initialize all the display stuff...
+ */
+void fgPlatformInitialize( const char* displayName )
+{
+ WNDCLASS wc;
+ ATOM atom;
+
+ /* What we need to do is to initialize the fgDisplay global structure here. */
+ fgDisplay.pDisplay.Instance = GetModuleHandle( NULL );
+ fgDisplay.pDisplay.DisplayName= displayName ? strdup(displayName) : 0 ;
+ atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc );
+
+ if( atom == 0 )
+ {
+ ZeroMemory( &wc, sizeof(WNDCLASS) );
+
+ /*
+ * Each of the windows should have its own device context, and we
+ * want redraw events during Vertical and Horizontal Resizes by
+ * the user.
+ *
+ * XXX Old code had "| CS_DBCLCKS" commented out. Plans for the
+ * XXX future? Dead-end idea?
+ */
+ wc.lpfnWndProc = fgPlatformWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = fgDisplay.pDisplay.Instance;
+ wc.hIcon = LoadIcon( fgDisplay.pDisplay.Instance, _T("GLUT_ICON") );
+
+#if defined(_WIN32_WCE)
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+#else
+ wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ if (!wc.hIcon)
+ wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
+#endif
+
+ wc.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = _T("FREEGLUT");
+
+ /* Register the window class */
+ atom = RegisterClass( &wc );
+ FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Not Registered", "fgPlatformInitialize" );
+ }
+
+ /* The screen dimensions can be obtained via GetSystemMetrics() calls */
+ fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
+ fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
+
+ {
+ HWND desktop = GetDesktopWindow( );
+ HDC context = GetDC( desktop );
+
+ fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
+ fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
+
+ ReleaseDC( desktop, context );
+ }
+ /* If we have a DisplayName try to use it for metrics */
+ if( fgDisplay.pDisplay.DisplayName )
+ {
+ HDC context = CreateDC(fgDisplay.pDisplay.DisplayName,0,0,0);
+ if( context )
+ {
+ fgDisplay.ScreenWidth = GetDeviceCaps( context, HORZRES );
+ fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES );
+ fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
+ fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
+ DeleteDC(context);
+ }
+ else
+ fgWarning("fgPlatformInitialize: "
+ "CreateDC failed, Screen size info may be incorrect\n"
+ "This is quite likely caused by a bad '-display' parameter");
+
+ }
+ /* Set the timer granularity to 1 ms */
+ timeBeginPeriod ( 1 );
+
+
+ fgState.Initialised = GL_TRUE;
+
+ /* Avoid registering atexit callback on Win32 as it can result in an
+ * access violation due to calling into a module which has been
+ * unloaded.
+ * Any cleanup isn't needed on Windows anyway, the OS takes care of it.
+ * see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
+ */
+/* atexit(fgDeinitialize); */
+
+ /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */
+ fgInitialiseInputDevices();
+}
+
+
+
+/* Platform-Specific Deinitialization Functions: */
+extern void fghCloseInputDevices ( void );
+
+void fgPlatformDeinitialiseInputDevices ( void )
+{
+#if !defined(_WIN32_WCE)
+ fghCloseInputDevices ();
+#endif /* !defined(_WIN32_WCE) */
+ fgState.JoysticksInitialised = GL_FALSE;
+ fgState.InputDevsInitialised = GL_FALSE;
+}
+
+void fgPlatformCloseDisplay ( void )
+{
+ if( fgDisplay.pDisplay.DisplayName )
+ {
+ free( fgDisplay.pDisplay.DisplayName );
+ fgDisplay.pDisplay.DisplayName = NULL;
+ }
+
+ /* Reset the timer granularity */
+ timeEndPeriod ( 1 );
+}
+
+void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext )
+{
+ /* Do nothing -- this is required for X11 */
+}
+
+/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */
+
+void (__cdecl *__glutExitFunc)( int return_value ) = NULL;
+
+void FGAPIENTRY __glutInitWithExit( int *pargc, char **argv, void (__cdecl *exit_function)(int) )
+{
+ __glutExitFunc = exit_function;
+ glutInit(pargc, argv);
+}
+
--- /dev/null
+/*
+ * freeglut_input_devices_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sat Jan 21, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+#include <sys/types.h>
+#include <winbase.h>
+
+typedef struct {
+ HANDLE fh;
+ COMMTIMEOUTS timeouts_save;
+ DCB dcb_save;
+} SERIALPORT;
+
+/* Serial Port Prototypes */
+SERIALPORT *serial_open ( const char *device );
+void serial_close ( SERIALPORT *port );
+int serial_getchar ( SERIALPORT *port );
+int serial_putchar ( SERIALPORT *port, unsigned char ch );
+void serial_flush ( SERIALPORT *port );
+
+
+void fgPlatformRegisterDialDevice ( const char *dial_device )
+{
+ if (!dial_device){
+ static char devname[256];
+ DWORD size=sizeof(devname);
+ DWORD type = REG_SZ;
+ HKEY key;
+ if (RegOpenKeyA(HKEY_LOCAL_MACHINE,"SOFTWARE\\FreeGLUT",&key)==ERROR_SUCCESS) {
+ if (RegQueryValueExA(key,"DialboxSerialPort",NULL,&type,(LPBYTE)devname,&size)==ERROR_SUCCESS){
+ dial_device=devname;
+ }
+ RegCloseKey(key);
+ }
+ }
+}
+
+
+/* Serial Port Functions */
+SERIALPORT *serial_open(const char *device){
+ HANDLE fh;
+ DCB dcb={sizeof(DCB)};
+ COMMTIMEOUTS timeouts;
+ SERIALPORT *port;
+
+ fh = CreateFile(device,GENERIC_READ|GENERIC_WRITE,0,NULL,
+ OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
+ if (!fh) return NULL;
+
+ port = malloc(sizeof(SERIALPORT));
+ ZeroMemory(port, sizeof(SERIALPORT));
+ port->fh = fh;
+
+ /* save current port settings */
+ GetCommState(fh,&port->dcb_save);
+ GetCommTimeouts(fh,&port->timeouts_save);
+
+ dcb.DCBlength=sizeof(DCB);
+ BuildCommDCB("96,n,8,1",&dcb);
+ SetCommState(fh,&dcb);
+
+ ZeroMemory(&timeouts,sizeof(timeouts));
+ timeouts.ReadTotalTimeoutConstant=1;
+ timeouts.WriteTotalTimeoutConstant=1;
+ SetCommTimeouts(fh,&timeouts);
+
+ serial_flush(port);
+
+ return port;
+}
+
+void serial_close(SERIALPORT *port){
+ if (port){
+ /* restore old port settings */
+ SetCommState(port->fh,&port->dcb_save);
+ SetCommTimeouts(port->fh,&port->timeouts_save);
+ CloseHandle(port->fh);
+ free(port);
+ }
+}
+
+int serial_getchar(SERIALPORT *port){
+ DWORD n;
+ unsigned char ch;
+ if (!port) return EOF;
+ if (!ReadFile(port->fh,&ch,1,&n,NULL)) return EOF;
+ if (n==1) return ch;
+ return EOF;
+}
+
+int serial_putchar(SERIALPORT *port, unsigned char ch){
+ DWORD n;
+ if (!port) return 0;
+ return WriteFile(port->fh,&ch,1,&n,NULL);
+}
+
+void serial_flush ( SERIALPORT *port )
+{
+ FlushFileBuffers(port->fh);
+}
+
--- /dev/null
+/*
+ * freeglut_internal_mswin.h
+ *
+ * The freeglut library private include file.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Thu Jan 19, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef FREEGLUT_INTERNAL_MSWIN_H
+#define FREEGLUT_INTERNAL_MSWIN_H
+
+
+/* All Win32 headers depend on the huge windows.h recursive include.
+ * Note: Lower-case header names are used, for best cross-platform
+ * compatibility.
+ */
+#if !defined(_WIN32_WCE)
+# include <windows.h>
+# include <windowsx.h>
+# include <mmsystem.h>
+/* CYGWIN does not have tchar.h, but has TEXT(x), defined in winnt.h. */
+# ifndef __CYGWIN__
+# include <tchar.h>
+# else
+# define _TEXT(x) TEXT(x)
+# define _T(x) TEXT(x)
+# endif
+
+#endif
+
+
+#ifndef HAVE_VFPRINTF
+#define HAVE_VFPRINTF 1
+#endif
+
+/* MinGW may lack a prototype for ChangeDisplaySettingsEx() (depending on the version?) */
+#if !defined(ChangeDisplaySettingsEx)
+LONG WINAPI ChangeDisplaySettingsExA(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID);
+LONG WINAPI ChangeDisplaySettingsExW(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID);
+# ifdef UNICODE
+# define ChangeDisplaySettingsEx ChangeDisplaySettingsExW
+# else
+# define ChangeDisplaySettingsEx ChangeDisplaySettingsExA
+# endif
+#endif
+
+
+/* Structure Definitions */
+
+typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
+struct tagSFG_PlatformDisplay
+{
+ HINSTANCE Instance; /* The application's instance */
+ DEVMODE DisplayMode; /* Desktop's display settings */
+ char *DisplayName; /* Display name for multi display support*/
+};
+
+/*
+ * Make "freeglut" window handle and context types so that we don't need so
+ * much conditionally-compiled code later in the library.
+ */
+typedef HWND SFG_WindowHandleType;
+typedef HGLRC SFG_WindowContextType;
+typedef struct tagSFG_PlatformContext SFG_PlatformContext;
+struct tagSFG_PlatformContext
+{
+ HDC Device; /* The window's device context */
+};
+
+
+/* Window's state description. This structure should be kept portable. */
+typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
+struct tagSFG_PlatformWindowState
+{
+ RECT OldRect; /* window rect - stored before the window is made fullscreen */
+ DWORD OldStyle; /* window style - stored before the window is made fullscreen */
+};
+
+
+
+/* Joystick-Specific Definitions */
+#if !defined(_WIN32_WCE)
+# define _JS_MAX_AXES 8
+typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
+struct tagSFG_PlatformJoystick
+{
+ JOYCAPS jsCaps;
+ JOYINFOEX js;
+ UINT js_id;
+};
+#endif
+
+
+/* Menu font and color definitions */
+#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13
+
+#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
+#define FREEGLUT_MENU_PEN_BACK_COLORS {0.85f, 0.85f, 0.85f, 1.0f}
+#define FREEGLUT_MENU_PEN_HFORE_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
+#define FREEGLUT_MENU_PEN_HBACK_COLORS {0.15f, 0.15f, 0.45f, 1.0f}
+
+
+/* Function to be called on exit */
+extern void (__cdecl *__glutExitFunc)( int return_value );
+
+
+#endif /* FREEGLUT_INTERNAL_MSWIN_H */
--- /dev/null
+/*
+ * freeglut_joystick_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sat Jan 28, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+#if !defined(_WIN32_WCE)
+# include <windows.h>
+# include <mmsystem.h>
+# include <regstr.h>
+
+
+
+
+void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
+{
+ MMRESULT status;
+
+ status = joyGetPosEx( joy->pJoystick.js_id, &joy->pJoystick.js );
+
+ if ( status != JOYERR_NOERROR )
+ {
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ if ( buttons )
+ *buttons = joy->pJoystick.js.dwButtons;
+
+ if ( axes )
+ {
+ /*
+ * WARNING - Fall through case clauses!!
+ */
+ switch ( joy->num_axes )
+ {
+ case 8:
+ /* Generate two POV axes from the POV hat angle.
+ * Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in
+ * hundredths of a degree, or 0xFFFF when idle.
+ */
+ if ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) == 0xFFFF )
+ {
+ axes [ 6 ] = 0.0;
+ axes [ 7 ] = 0.0;
+ }
+ else
+ {
+ /* This is the contentious bit: how to convert angle to X/Y.
+ * wk: I know of no define for PI that we could use here:
+ * SG_PI would pull in sg, M_PI is undefined for MSVC
+ * But the accuracy of the value of PI is very unimportant at
+ * this point.
+ */
+ float s = (float) sin ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) );
+ float c = (float) cos ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) );
+
+ /* Convert to coordinates on a square so that North-East
+ * is (1,1) not (.7,.7), etc.
+ * s and c cannot both be zero so we won't divide by zero.
+ */
+ if ( fabs ( s ) < fabs ( c ) )
+ {
+ axes [ 6 ] = ( c < 0.0 ) ? -s/c : s/c ;
+ axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f;
+ }
+ else
+ {
+ axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f;
+ axes [ 7 ] = ( s < 0.0 ) ? -c/s : c/s ;
+ }
+ }
+
+ case 6: axes[5] = (float) joy->pJoystick.js.dwVpos;
+ case 5: axes[4] = (float) joy->pJoystick.js.dwUpos;
+ case 4: axes[3] = (float) joy->pJoystick.js.dwRpos;
+ case 3: axes[2] = (float) joy->pJoystick.js.dwZpos;
+ case 2: axes[1] = (float) joy->pJoystick.js.dwYpos;
+ case 1: axes[0] = (float) joy->pJoystick.js.dwXpos;
+ }
+ }
+}
+
+
+
+/* Inspired by
+ http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
+ */
+# if FREEGLUT_LIB_PRAGMAS
+# pragma comment (lib, "advapi32.lib")
+# endif
+
+static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz )
+{
+ char buffer [ 256 ];
+
+ char OEMKey [ 256 ];
+
+ HKEY hKey;
+ DWORD dwcb;
+ LONG lr;
+
+ if ( joy->error )
+ return 0;
+
+ /* Open .. MediaResources\CurrentJoystickSettings */
+ _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s",
+ REGSTR_PATH_JOYCONFIG, joy->pJoystick.jsCaps.szRegKey,
+ REGSTR_KEY_JOYCURR );
+
+ lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ /* Get OEM Key name */
+ dwcb = sizeof(OEMKey);
+
+ /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */
+ _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->pJoystick.js_id + 1, REGSTR_VAL_JOYOEMNAME );
+
+ lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);
+ RegCloseKey ( hKey );
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ /* Open OEM Key from ...MediaProperties */
+ _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
+
+ lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ /* Get OEM Name */
+ dwcb = buf_sz;
+
+ lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf,
+ &dwcb );
+ RegCloseKey ( hKey );
+
+ if ( lr != ERROR_SUCCESS ) return 0;
+
+ return 1;
+}
+
+
+void fgPlatformJoystickOpen( SFG_Joystick* joy )
+{
+ int i = 0;
+
+ joy->pJoystick.js.dwFlags = JOY_RETURNALL;
+ joy->pJoystick.js.dwSize = sizeof( joy->pJoystick.js );
+
+ memset( &joy->pJoystick.jsCaps, 0, sizeof( joy->pJoystick.jsCaps ) );
+
+ joy->error =
+ ( joyGetDevCaps( joy->pJoystick.js_id, &joy->pJoystick.jsCaps, sizeof( joy->pJoystick.jsCaps ) ) !=
+ JOYERR_NOERROR );
+
+ if( joy->pJoystick.jsCaps.wNumAxes == 0 )
+ {
+ joy->num_axes = 0;
+ joy->error = GL_TRUE;
+ }
+ else
+ {
+ /* Device name from jsCaps is often "Microsoft PC-joystick driver",
+ * at least for USB. Try to get the real name from the registry.
+ */
+ if ( ! fghJoystickGetOEMProductName( joy, joy->name,
+ sizeof( joy->name ) ) )
+ {
+ fgWarning( "JS: Failed to read joystick name from registry" );
+ strncpy( joy->name, joy->pJoystick.jsCaps.szPname, sizeof( joy->name ) );
+ }
+
+ /* Windows joystick drivers may provide any combination of
+ * X,Y,Z,R,U,V,POV - not necessarily the first n of these.
+ */
+ if( joy->pJoystick.jsCaps.wCaps & JOYCAPS_HASPOV )
+ {
+ joy->num_axes = _JS_MAX_AXES;
+ joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0; /* POV Y */
+ joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0; /* POV X */
+ }
+ else
+ joy->num_axes = 6;
+
+ joy->min[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmin;
+ joy->max[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmax;
+ joy->min[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmin;
+ joy->max[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmax;
+ joy->min[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmin;
+ joy->max[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmax;
+ joy->min[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmin;
+ joy->max[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmax;
+ joy->min[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmin;
+ joy->max[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmax;
+ joy->min[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmin;
+ joy->max[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmax;
+ }
+
+ /* Guess all the rest judging on the axes extremals */
+ for( i = 0; i < joy->num_axes; i++ )
+ {
+ joy->center [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f;
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate [ i ] = 1.0f;
+ }
+}
+
+
+
+void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )
+{
+ switch( ident )
+ {
+ case 0:
+ fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID1;
+ fgJoystick[ ident ]->error = GL_FALSE;
+ break;
+ case 1:
+ fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID2;
+ fgJoystick[ ident ]->error = GL_FALSE;
+ break;
+ default:
+ fgJoystick[ ident ]->num_axes = 0;
+ fgJoystick[ ident ]->error = GL_TRUE;
+ return;
+ }
+}
+
+
+
+void fgPlatformJoystickClose ( int ident )
+{
+ /* Do nothing special */
+}
+#endif
+
--- /dev/null
+/*
+ * freeglut_main_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sat Jan 21, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+extern void fghRedrawWindow ( SFG_Window *window );
+
+extern void fgNewWGLCreateContext( SFG_Window* window );
+extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
+ unsigned char layer_type );
+
+#ifdef WM_TOUCH
+typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
+typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT);
+static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF;
+static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF;
+#endif
+
+#ifdef _WIN32_WCE
+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 /* _WIN32_WCE */
+
+/*
+ * Helper functions for getting client area from the window rect
+ * and the window rect from the client area given the style of the window
+ * (or a valid window pointer from which the style can be queried).
+ */
+extern void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
+extern RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside );
+
+
+void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
+{
+ RECT windowRect;
+
+ /*
+ * For windowed mode, get the current position of the
+ * window and resize taking the size of the frame
+ * decorations into account.
+ */
+
+ /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
+ GetWindowRect( window->Window.Handle, &windowRect );
+
+ /* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */
+ windowRect.right = windowRect.left+width;
+ windowRect.bottom = windowRect.top+height;
+
+ if (window->Parent == NULL)
+ /* get the window rect from this to feed to SetWindowPos, correct for window decorations */
+ fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE);
+ else
+ {
+ /* correct rect for position client area of parent window
+ * (SetWindowPos input for child windows is in coordinates
+ * relative to the parent's client area).
+ * Child windows don't have decoration, so no need to correct
+ * for them.
+ */
+ RECT parentRect;
+ parentRect = fghGetClientArea( window->Parent, FALSE );
+ windowRect.left -= parentRect.left;
+ windowRect.right -= parentRect.left;
+ windowRect.top -= parentRect.top;
+ windowRect.bottom -= parentRect.top;
+ }
+
+ /* Do the actual resizing */
+ SetWindowPos( window->Window.Handle,
+ HWND_TOP,
+ windowRect.left, windowRect.top,
+ windowRect.right - windowRect.left,
+ windowRect.bottom- windowRect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
+ SWP_NOZORDER
+ );
+}
+
+
+void fgPlatformDisplayWindow ( SFG_Window *window )
+{
+ RedrawWindow(
+ window->Window.Handle, NULL, NULL,
+ RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
+ );
+}
+
+
+fg_time_t fgPlatformSystemTime ( void )
+{
+#if defined(_WIN32_WCE)
+ return GetTickCount();
+#else
+ /* TODO: do this with QueryPerformanceCounter as timeGetTime has
+ * insufficient resolution (only about 5 ms on system under low load).
+ * See:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629(v=vs.85).aspx
+ * Or maybe QueryPerformanceCounter is not a good idea either, see
+ * http://old.nabble.com/Re%3A-glutTimerFunc-does-not-detect-if-system-time-moved-backward-p33479674.html
+ * for some other ideas (at bottom)...
+ */
+ return timeGetTime();
+#endif
+}
+
+
+void fgPlatformSleepForEvents( fg_time_t msec )
+{
+ MsgWaitForMultipleObjects( 0, NULL, FALSE, (DWORD) msec, QS_ALLINPUT );
+}
+
+
+void fgPlatformProcessSingleEvent ( void )
+{
+ MSG stMsg;
+
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
+
+ while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
+ {
+ if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
+ {
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ {
+ fgDeinitialize( );
+ exit( 0 );
+ }
+ else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+
+ return;
+ }
+
+ TranslateMessage( &stMsg );
+ DispatchMessage( &stMsg );
+ }
+}
+
+
+
+void fgPlatformMainLoopPreliminaryWork ( void )
+{
+ SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
+
+ /*
+ * Processing before the main loop: If there is a window which is open and
+ * which has a visibility callback, call it. I know this is an ugly hack,
+ * but I'm not sure what else to do about it. Ideally we should leave
+ * something uninitialized in the create window code and initialize it in
+ * the main loop, and have that initialization create a "WM_ACTIVATE"
+ * message. Then we would put the visibility callback code in the
+ * "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
+ */
+ while( window )
+ {
+ if ( FETCH_WCB( *window, Visibility ) )
+ {
+ SFG_Window *current_window = fgStructure.CurrentWindow ;
+
+ INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
+ fgSetWindow( current_window );
+ }
+
+ window = (SFG_Window *)window->Node.Next ;
+ }
+}
+
+
+/*
+ * Determine a GLUT modifer mask based on MS-WINDOWS system info.
+ */
+static int fgPlatformGetModifiers (void)
+{
+ return
+ ( ( ( GetKeyState( VK_LSHIFT ) < 0 ) ||
+ ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
+ ( ( ( GetKeyState( VK_LCONTROL ) < 0 ) ||
+ ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
+ ( ( ( GetKeyState( VK_LMENU ) < 0 ) ||
+ ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
+}
+
+/*
+ * The window procedure for handling Win32 events
+ */
+LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ static unsigned char lControl = 0, rControl = 0, lShift = 0,
+ rShift = 0, lAlt = 0, rAlt = 0;
+
+ SFG_Window* window;
+ PAINTSTRUCT ps;
+ LRESULT lRet = 1;
+
+ FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
+
+ window = fgWindowByHandle( hWnd );
+
+ if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+
+ /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
+ uMsg, wParam, lParam ); */
+
+ if ( window )
+ {
+ /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
+ if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) )
+ {
+ INVOKE_WCB ( *window, Special,
+ ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
+ );
+
+ lControl = 1;
+ }
+
+ if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) )
+ {
+ INVOKE_WCB ( *window, Special,
+ ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
+ );
+
+ rControl = 1;
+ }
+
+ if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) )
+ {
+ INVOKE_WCB ( *window, Special,
+ ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
+ );
+
+ lShift = 1;
+ }
+
+ if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) )
+ {
+ INVOKE_WCB ( *window, Special,
+ ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
+ );
+
+ rShift = 1;
+ }
+
+ if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) )
+ {
+ INVOKE_WCB ( *window, Special,
+ ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
+ );
+
+ lAlt = 1;
+ }
+
+ if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) )
+ {
+ INVOKE_WCB ( *window, Special,
+ ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
+ );
+
+ rAlt = 1;
+ }
+
+ /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */
+ if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) )
+ {
+ INVOKE_WCB ( *window, SpecialUp,
+ ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
+ );
+
+ lControl = 0;
+ }
+
+ if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) )
+ {
+ INVOKE_WCB ( *window, SpecialUp,
+ ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
+ );
+
+ rControl = 0;
+ }
+
+ if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) )
+ {
+ INVOKE_WCB ( *window, SpecialUp,
+ ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
+ );
+
+ lShift = 0;
+ }
+
+ if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) )
+ {
+ INVOKE_WCB ( *window, SpecialUp,
+ ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
+ );
+
+ rShift = 0;
+ }
+
+ if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) )
+ {
+ INVOKE_WCB ( *window, SpecialUp,
+ ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
+ );
+
+ lAlt = 0;
+ }
+
+ if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) )
+ {
+ INVOKE_WCB ( *window, SpecialUp,
+ ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
+ );
+
+ rAlt = 0;
+ }
+ }
+
+ switch( uMsg )
+ {
+ case WM_CREATE:
+ /* The window structure is passed as the creation structure parameter... */
+ window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
+ FREEGLUT_INTERNAL_ERROR_EXIT ( ( window != NULL ), "Cannot create window",
+ "fgPlatformWindowProc" );
+
+ window->Window.Handle = hWnd;
+ window->Window.pContext.Device = GetDC( hWnd );
+ if( window->IsMenu )
+ {
+ unsigned int current_DisplayMode = fgState.DisplayMode;
+ fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
+#if !defined(_WIN32_WCE)
+ fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
+#endif
+ fgState.DisplayMode = current_DisplayMode;
+
+ if( fgStructure.MenuContext )
+ wglMakeCurrent( window->Window.pContext.Device,
+ fgStructure.MenuContext->MContext
+ );
+ else
+ {
+ fgStructure.MenuContext =
+ (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
+ fgStructure.MenuContext->MContext =
+ wglCreateContext( window->Window.pContext.Device );
+ }
+
+ /* window->Window.Context = wglGetCurrentContext (); */
+ window->Window.Context = wglCreateContext( window->Window.pContext.Device );
+ }
+ else
+ {
+#if !defined(_WIN32_WCE)
+ fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
+#endif
+
+ if( ! fgState.UseCurrentContext )
+ window->Window.Context =
+ wglCreateContext( window->Window.pContext.Device );
+ else
+ {
+ window->Window.Context = wglGetCurrentContext( );
+ if( ! window->Window.Context )
+ window->Window.Context =
+ wglCreateContext( window->Window.pContext.Device );
+ }
+
+#if !defined(_WIN32_WCE)
+ fgNewWGLCreateContext( window );
+#endif
+ }
+
+ window->State.NeedToResize = GL_TRUE;
+ /* if we used CW_USEDEFAULT (thats a negative value) for the size
+ * of the window, query the window now for the size at which it
+ * was created.
+ */
+ if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) )
+ {
+ SFG_Window *current_window = fgStructure.CurrentWindow;
+
+ fgSetWindow( window );
+ window->State.Width = glutGet( GLUT_WINDOW_WIDTH );
+ window->State.Height = glutGet( GLUT_WINDOW_HEIGHT );
+ fgSetWindow( current_window );
+ }
+
+ ReleaseDC( window->Window.Handle, window->Window.pContext.Device );
+
+#if defined(_WIN32_WCE)
+ /* 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 /* defined(_WIN32_WCE) */
+ break;
+
+ case WM_SIZE:
+ /*
+ * If the window is visible, then it is the user manually resizing it.
+ * If it is not, then it is the system sending us a dummy resize with
+ * zero dimensions on a "glutIconifyWindow" call.
+ */
+ if( window->State.Visible )
+ {
+ window->State.NeedToResize = GL_TRUE;
+#if defined(_WIN32_WCE)
+ window->State.Width = HIWORD(lParam);
+ window->State.Height = LOWORD(lParam);
+#else
+ window->State.Width = LOWORD(lParam);
+ window->State.Height = HIWORD(lParam);
+#endif /* defined(_WIN32_WCE) */
+ }
+
+ break;
+
+ case WM_SETFOCUS:
+/* printf("WM_SETFOCUS: %p\n", window ); */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
+
+ UpdateWindow ( hWnd );
+ break;
+
+ case WM_KILLFOCUS:
+/* printf("WM_KILLFOCUS: %p\n", window ); */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
+
+ if( window->IsMenu &&
+ window->ActiveMenu && window->ActiveMenu->IsActive )
+ fgUpdateMenuHighlight( window->ActiveMenu );
+
+ break;
+
+#if 0
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_INACTIVE)
+ {
+/* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
+ window->State.Cursor ); */
+ fgSetCursor( window, window->State.Cursor );
+ }
+
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+#endif
+
+ case WM_SETCURSOR:
+/* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */
+ if( LOWORD( lParam ) == HTCLIENT )
+ fgSetCursor ( window, window->State.Cursor ) ;
+ else
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+ case WM_SHOWWINDOW:
+ window->State.Visible = GL_TRUE;
+ window->State.Redisplay = GL_TRUE;
+ break;
+
+ case WM_PAINT:
+ /* Turn on the visibility in case it was turned off somehow */
+ window->State.Visible = GL_TRUE;
+ BeginPaint( hWnd, &ps );
+ fghRedrawWindow( window );
+ EndPaint( hWnd, &ps );
+ break;
+
+ case WM_CLOSE:
+ fgDestroyWindow ( window );
+ if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
+ PostQuitMessage(0);
+ break;
+
+ case WM_DESTROY:
+ /*
+ * The window already got destroyed, so don't bother with it.
+ */
+ return 0;
+
+ case WM_MOUSEMOVE:
+ {
+#if defined(_WIN32_WCE)
+ window->State.MouseX = 320-HIWORD( lParam );
+ window->State.MouseY = LOWORD( lParam );
+#else
+ window->State.MouseX = LOWORD( lParam );
+ window->State.MouseY = HIWORD( lParam );
+#endif /* defined(_WIN32_WCE) */
+ /* 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 )
+ {
+ fgUpdateMenuHighlight( window->ActiveMenu );
+ break;
+ }
+ SetFocus(window->Window.Handle);
+
+ fgState.Modifiers = fgPlatformGetModifiers( );
+
+ if( ( wParam & MK_LBUTTON ) ||
+ ( wParam & MK_MBUTTON ) ||
+ ( wParam & MK_RBUTTON ) )
+ INVOKE_WCB( *window, Motion, ( window->State.MouseX,
+ window->State.MouseY ) );
+ else
+ INVOKE_WCB( *window, Passive, ( window->State.MouseX,
+ window->State.MouseY ) );
+
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ {
+ GLboolean pressed = GL_TRUE;
+ int button;
+
+#if defined(_WIN32_WCE)
+ window->State.MouseX = 320-HIWORD( lParam );
+ window->State.MouseY = LOWORD( lParam );
+#else
+ window->State.MouseX = LOWORD( lParam );
+ window->State.MouseY = HIWORD( lParam );
+#endif /* defined(_WIN32_WCE) */
+
+ /* 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:
+ pressed = GL_TRUE;
+ button = GLUT_LEFT_BUTTON;
+ break;
+ case WM_MBUTTONDOWN:
+ pressed = GL_TRUE;
+ button = GLUT_MIDDLE_BUTTON;
+ break;
+ case WM_RBUTTONDOWN:
+ pressed = GL_TRUE;
+ button = GLUT_RIGHT_BUTTON;
+ break;
+ case WM_LBUTTONUP:
+ pressed = GL_FALSE;
+ button = GLUT_LEFT_BUTTON;
+ break;
+ case WM_MBUTTONUP:
+ pressed = GL_FALSE;
+ button = GLUT_MIDDLE_BUTTON;
+ break;
+ case WM_RBUTTONUP:
+ pressed = GL_FALSE;
+ button = GLUT_RIGHT_BUTTON;
+ break;
+ default:
+ pressed = GL_FALSE;
+ button = -1;
+ break;
+ }
+
+#if !defined(_WIN32_WCE)
+ if( GetSystemMetrics( SM_SWAPBUTTON ) )
+ {
+ if( button == GLUT_LEFT_BUTTON )
+ button = GLUT_RIGHT_BUTTON;
+ else
+ if( button == GLUT_RIGHT_BUTTON )
+ button = GLUT_LEFT_BUTTON;
+ }
+#endif /* !defined(_WIN32_WCE) */
+
+ if( button == -1 )
+ return DefWindowProc( hWnd, uMsg, lParam, wParam );
+
+ /*
+ * Do not execute the application's mouse callback if a menu
+ * is hooked to this button. In that case an appropriate
+ * private call should be generated.
+ */
+ if( fgCheckActiveMenu( window, button, pressed,
+ window->State.MouseX, window->State.MouseY ) )
+ 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 = fgPlatformGetModifiers( );
+
+ INVOKE_WCB(
+ *window, Mouse,
+ ( button,
+ pressed ? GLUT_DOWN : GLUT_UP,
+ window->State.MouseX,
+ window->State.MouseY
+ )
+ );
+
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case 0x020a:
+ /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */
+ {
+ int wheel_number = LOWORD( wParam );
+ short ticks = ( short )HIWORD( wParam );
+ fgState.MouseWheelTicks += ticks;
+
+ /*
+ * XXX Should use WHEEL_DELTA instead of 120
+ */
+ if ( abs ( fgState.MouseWheelTicks ) > 120 )
+ {
+ int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
+
+ if( ! FETCH_WCB( *window, MouseWheel ) &&
+ ! FETCH_WCB( *window, Mouse ) )
+ break;
+
+ fgSetWindow( window );
+ fgState.Modifiers = fgPlatformGetModifiers( );
+
+ /*
+ * XXX Should use WHEEL_DELTA instead of 120
+ */
+ while( abs ( fgState.MouseWheelTicks ) > 120 )
+ {
+ if( FETCH_WCB( *window, MouseWheel ) )
+ INVOKE_WCB( *window, MouseWheel,
+ ( wheel_number,
+ direction,
+ window->State.MouseX,
+ window->State.MouseY
+ )
+ );
+ else /* No mouse wheel, call the mouse button callback twice */
+ {
+ /*
+ * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
+ * " " one +1 to 5, -1 to 6, ...
+ *
+ * XXX The below assumes that you have no more than 3 mouse
+ * XXX buttons. Sorry.
+ */
+ int button = wheel_number * 2 + 3;
+ if( direction < 0 )
+ ++button;
+ INVOKE_WCB( *window, Mouse,
+ ( button, GLUT_DOWN,
+ window->State.MouseX, window->State.MouseY )
+ );
+ INVOKE_WCB( *window, Mouse,
+ ( button, GLUT_UP,
+ window->State.MouseX, window->State.MouseY )
+ );
+ }
+
+ /*
+ * XXX Should use WHEEL_DELTA instead of 120
+ */
+ fgState.MouseWheelTicks -= 120 * direction;
+ }
+
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ }
+ break ;
+
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ {
+ int keypress = -1;
+ POINT mouse_pos ;
+
+ if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
+ break;
+
+ /*
+ * Remember the current modifiers state. This is done here in order
+ * to make sure the VK_DELETE keyboard callback is executed properly.
+ */
+ fgState.Modifiers = fgPlatformGetModifiers( );
+
+ GetCursorPos( &mouse_pos );
+ ScreenToClient( window->Window.Handle, &mouse_pos );
+
+ window->State.MouseX = mouse_pos.x;
+ window->State.MouseY = mouse_pos.y;
+
+ /* Convert the Win32 keystroke codes to GLUTtish way */
+# define KEY(a,b) case a: keypress = b; break;
+
+ switch( wParam )
+ {
+ KEY( VK_F1, GLUT_KEY_F1 );
+ KEY( VK_F2, GLUT_KEY_F2 );
+ KEY( VK_F3, GLUT_KEY_F3 );
+ KEY( VK_F4, GLUT_KEY_F4 );
+ KEY( VK_F5, GLUT_KEY_F5 );
+ KEY( VK_F6, GLUT_KEY_F6 );
+ KEY( VK_F7, GLUT_KEY_F7 );
+ KEY( VK_F8, GLUT_KEY_F8 );
+ KEY( VK_F9, GLUT_KEY_F9 );
+ KEY( VK_F10, GLUT_KEY_F10 );
+ KEY( VK_F11, GLUT_KEY_F11 );
+ KEY( VK_F12, GLUT_KEY_F12 );
+ KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
+ KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
+ KEY( VK_HOME, GLUT_KEY_HOME );
+ KEY( VK_END, GLUT_KEY_END );
+ KEY( VK_LEFT, GLUT_KEY_LEFT );
+ KEY( VK_UP, GLUT_KEY_UP );
+ KEY( VK_RIGHT, GLUT_KEY_RIGHT );
+ KEY( VK_DOWN, GLUT_KEY_DOWN );
+ KEY( VK_INSERT, GLUT_KEY_INSERT );
+ KEY( VK_LCONTROL, GLUT_KEY_CTRL_L );
+ KEY( VK_RCONTROL, GLUT_KEY_CTRL_R );
+ KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L );
+ KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R );
+ KEY( VK_LMENU, GLUT_KEY_ALT_L );
+ KEY( VK_RMENU, GLUT_KEY_ALT_R );
+
+ case VK_DELETE:
+ /* The delete key should be treated as an ASCII keypress: */
+ INVOKE_WCB( *window, Keyboard,
+ ( 127, window->State.MouseX, window->State.MouseY )
+ );
+ }
+
+#if defined(_WIN32_WCE)
+ if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
+ {
+ if(wParam==(unsigned)gxKeyList.vkRight)
+ keypress = GLUT_KEY_RIGHT;
+ else if(wParam==(unsigned)gxKeyList.vkLeft)
+ keypress = GLUT_KEY_LEFT;
+ else if(wParam==(unsigned)gxKeyList.vkUp)
+ keypress = GLUT_KEY_UP;
+ else if(wParam==(unsigned)gxKeyList.vkDown)
+ keypress = GLUT_KEY_DOWN;
+ else if(wParam==(unsigned)gxKeyList.vkA)
+ keypress = GLUT_KEY_F1;
+ else if(wParam==(unsigned)gxKeyList.vkB)
+ keypress = GLUT_KEY_F2;
+ else if(wParam==(unsigned)gxKeyList.vkC)
+ keypress = GLUT_KEY_F3;
+ else if(wParam==(unsigned)gxKeyList.vkStart)
+ keypress = GLUT_KEY_F4;
+ }
+#endif
+
+ if( keypress != -1 )
+ INVOKE_WCB( *window, Special,
+ ( keypress,
+ window->State.MouseX, window->State.MouseY )
+ );
+
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ {
+ 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 = fgPlatformGetModifiers( );
+
+ GetCursorPos( &mouse_pos );
+ ScreenToClient( window->Window.Handle, &mouse_pos );
+
+ window->State.MouseX = mouse_pos.x;
+ window->State.MouseY = mouse_pos.y;
+
+ /*
+ * Convert the Win32 keystroke codes to GLUTtish way.
+ * "KEY(a,b)" was defined under "WM_KEYDOWN"
+ */
+
+ switch( wParam )
+ {
+ KEY( VK_F1, GLUT_KEY_F1 );
+ KEY( VK_F2, GLUT_KEY_F2 );
+ KEY( VK_F3, GLUT_KEY_F3 );
+ KEY( VK_F4, GLUT_KEY_F4 );
+ KEY( VK_F5, GLUT_KEY_F5 );
+ KEY( VK_F6, GLUT_KEY_F6 );
+ KEY( VK_F7, GLUT_KEY_F7 );
+ KEY( VK_F8, GLUT_KEY_F8 );
+ KEY( VK_F9, GLUT_KEY_F9 );
+ KEY( VK_F10, GLUT_KEY_F10 );
+ KEY( VK_F11, GLUT_KEY_F11 );
+ KEY( VK_F12, GLUT_KEY_F12 );
+ KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
+ KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
+ KEY( VK_HOME, GLUT_KEY_HOME );
+ KEY( VK_END, GLUT_KEY_END );
+ KEY( VK_LEFT, GLUT_KEY_LEFT );
+ KEY( VK_UP, GLUT_KEY_UP );
+ KEY( VK_RIGHT, GLUT_KEY_RIGHT );
+ KEY( VK_DOWN, GLUT_KEY_DOWN );
+ KEY( VK_INSERT, GLUT_KEY_INSERT );
+ KEY( VK_LCONTROL, GLUT_KEY_CTRL_L );
+ KEY( VK_RCONTROL, GLUT_KEY_CTRL_R );
+ KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L );
+ KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R );
+ KEY( VK_LMENU, GLUT_KEY_ALT_L );
+ KEY( VK_RMENU, GLUT_KEY_ALT_R );
+
+ case VK_DELETE:
+ /* The delete key should be treated as an ASCII keypress: */
+ INVOKE_WCB( *window, KeyboardUp,
+ ( 127, window->State.MouseX, window->State.MouseY )
+ );
+ break;
+
+ default:
+ {
+#if !defined(_WIN32_WCE)
+ BYTE state[ 256 ];
+ WORD code[ 2 ];
+
+ GetKeyboardState( state );
+
+ if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
+ wParam=code[ 0 ];
+
+ INVOKE_WCB( *window, KeyboardUp,
+ ( (char)wParam,
+ window->State.MouseX, window->State.MouseY )
+ );
+#endif /* !defined(_WIN32_WCE) */
+ }
+ }
+
+ if( keypress != -1 )
+ INVOKE_WCB( *window, SpecialUp,
+ ( keypress,
+ window->State.MouseX, window->State.MouseY )
+ );
+
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ case WM_CHAR:
+ {
+ if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
+ break;
+
+ fgState.Modifiers = fgPlatformGetModifiers( );
+ INVOKE_WCB( *window, Keyboard,
+ ( (char)wParam,
+ window->State.MouseX, window->State.MouseY )
+ );
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case WM_CAPTURECHANGED:
+ /* User has finished resizing the window, force a redraw */
+ INVOKE_WCB( *window, Display, ( ) );
+
+ /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
+ break;
+
+ /* Other messages that I have seen and which are not handled already */
+ case WM_SETTEXT: /* 0x000c */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ /* Pass it on to "DefWindowProc" to set the window text */
+ break;
+
+ case WM_GETTEXT: /* 0x000d */
+ /* Ideally we would copy the title of the window into "lParam" */
+ /* strncpy ( (char *)lParam, "Window Title", wParam );
+ lRet = ( wParam > 12 ) ? 12 : wParam; */
+ /* the number of characters copied */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+ case WM_GETTEXTLENGTH: /* 0x000e */
+ /* Ideally we would get the length of the title of the window */
+ lRet = 12;
+ /* the number of characters in "Window Title\0" (see above) */
+ break;
+
+ case WM_ERASEBKGND: /* 0x0014 */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+#if !defined(_WIN32_WCE)
+ case WM_SYNCPAINT: /* 0x0088 */
+ /* Another window has moved, need to update this one */
+ window->State.Redisplay = GL_TRUE;
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ /* Help screen says this message must be passed to "DefWindowProc" */
+ break;
+
+ case WM_NCPAINT: /* 0x0085 */
+ /* Need to update the border of this window */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ /* Pass it on to "DefWindowProc" to repaint a standard border */
+ break;
+
+ case WM_SYSCOMMAND : /* 0x0112 */
+ {
+ /*
+ * We have received a system command message. Try to act on it.
+ * 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 ( wParam & 0xfff0 )
+ {
+ case SC_SIZE :
+ break ;
+
+ case SC_MOVE :
+ break ;
+
+ case SC_MINIMIZE :
+ /* User has clicked on the "-" to minimize the window */
+ /* Turn off the visibility */
+ window->State.Visible = GL_FALSE ;
+
+ break ;
+
+ case SC_MAXIMIZE :
+ break ;
+
+ case SC_NEXTWINDOW :
+ break ;
+
+ case SC_PREVWINDOW :
+ break ;
+
+ case SC_CLOSE :
+ /* Followed very closely by a WM_CLOSE message */
+ break ;
+
+ case SC_VSCROLL :
+ break ;
+
+ case SC_HSCROLL :
+ break ;
+
+ case SC_MOUSEMENU :
+ break ;
+
+ case SC_KEYMENU :
+ break ;
+
+ case SC_ARRANGE :
+ break ;
+
+ case SC_RESTORE :
+ break ;
+
+ case SC_TASKLIST :
+ break ;
+
+ case SC_SCREENSAVE :
+ break ;
+
+ case SC_HOTKEY :
+ break ;
+
+#if(WINVER >= 0x0400)
+ case SC_DEFAULT :
+ break ;
+
+ case SC_MONITORPOWER :
+ break ;
+
+ case SC_CONTEXTHELP :
+ break ;
+#endif /* WINVER >= 0x0400 */
+
+ default:
+#if _DEBUG
+ fgWarning( "Unknown wParam type 0x%x", wParam );
+#endif
+ break;
+ }
+ }
+#endif /* !defined(_WIN32_WCE) */
+
+ /* We need to pass the message on to the operating system as well */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+
+#ifdef WM_TOUCH
+ /* handle multi-touch messages */
+ case WM_TOUCH:
+ {
+ unsigned int numInputs = (unsigned int)wParam;
+ unsigned int i = 0;
+ TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs);
+
+ if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) {
+ fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo");
+ fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle");
+ }
+
+ if (!fghGetTouchInputInfo) {
+ free( (void*)ti );
+ break;
+ }
+
+ if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) {
+ /* Handle each contact point */
+ for (i = 0; i < numInputs; ++i ) {
+
+ POINT tp;
+ tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
+ tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
+ ScreenToClient( hWnd, &tp );
+
+ ti[i].dwID = ti[i].dwID * 2;
+
+ if (ti[i].dwFlags & TOUCHEVENTF_DOWN) {
+ INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) );
+ INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) );
+ } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
+ INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) );
+ } else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
+ INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) );
+ INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) );
+ }
+ }
+ }
+ fghCloseTouchInputHandle((HTOUCHINPUT)lParam);
+ free( (void*)ti );
+ lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/
+ break;
+ }
+#endif
+ default:
+ /* Handle unhandled messages */
+ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+ break;
+ }
+
+ return lRet;
+}
--- /dev/null
+/*
+ * freeglut_menu_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sun Jan 22, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y )
+{
+ *x = glutGet ( GLUT_SCREEN_WIDTH );
+ *y = glutGet ( GLUT_SCREEN_HEIGHT );
+}
+
+
+
+/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */
+
+int FGAPIENTRY __glutCreateMenuWithExit( void(* callback)( int ), void (__cdecl *exit_function)(int) )
+{
+ __glutExitFunc = exit_function;
+ return glutCreateMenu( callback );
+}
+
--- /dev/null
+/*
+ * freeglut_spaceball_mswin.c
+ *
+ * Spaceball support for Windows
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by Evan Felix <karcaw at gmail.com>
+ * Creation date: Sat Feb 4, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * This code is a very complicated way of doing nothing.
+ * But is needed for mswindows platform builds.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+void fgPlatformInitializeSpaceball(void)
+{
+ return;
+}
+
+void fgPlatformSpaceballClose(void)
+{
+ return;
+}
+
+int fgPlatformHasSpaceball(void)
+{
+ return 0;
+}
+
+int fgPlatformSpaceballNumButtons(void)
+{
+ return 0;
+}
+
+void fgPlatformSpaceballSetWindow(SFG_Window *window)
+{
+ return;
+}
--- /dev/null
+/*
+ * freeglut_state_mswin.c
+ *
+ * The Windows-specific state query methods.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sun Jan 22, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
+ unsigned char layer_type );
+
+/*
+ * Helper functions for getting client area from the window rect
+ * and the window rect from the client area given the style of the window
+ * (or a valid window pointer from which the style can be queried).
+ */
+extern RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside );
+extern void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
+
+
+/* The following include file is available from SGI but is not standard:
+ * #include <GL/wglext.h>
+ * So we copy the necessary parts out of it to support the multisampling query
+ */
+#define WGL_SAMPLES_ARB 0x2042
+
+#if defined(_WIN32_WCE)
+# include <Aygshell.h>
+# ifdef FREEGLUT_LIB_PRAGMAS
+# pragma comment( lib, "Aygshell.lib" )
+# endif
+#endif /* defined(_WIN32_WCE) */
+
+
+
+int fgPlatformGlutGet ( GLenum eWhat )
+{
+ int returnValue ;
+ GLboolean boolValue ;
+
+ int nsamples = 0;
+
+ switch( eWhat )
+ {
+ case GLUT_WINDOW_NUM_SAMPLES:
+ glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
+ return nsamples;
+
+ /* Handle the OpenGL inquiries */
+ case GLUT_WINDOW_RGBA:
+#if defined(_WIN32_WCE)
+ boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
+#else
+ glGetBooleanv ( GL_RGBA_MODE, &boolValue );
+ returnValue = boolValue ? 1 : 0;
+#endif
+ return returnValue;
+ case GLUT_WINDOW_DOUBLEBUFFER:
+#if defined(_WIN32_WCE)
+ boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
+#else
+ glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
+ returnValue = boolValue ? 1 : 0;
+#endif
+ return returnValue;
+ case GLUT_WINDOW_STEREO:
+#if defined(_WIN32_WCE)
+ boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
+#else
+ glGetBooleanv ( GL_STEREO, &boolValue );
+ returnValue = boolValue ? 1 : 0;
+#endif
+ return returnValue;
+
+ case GLUT_WINDOW_RED_SIZE:
+ glGetIntegerv ( GL_RED_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_GREEN_SIZE:
+ glGetIntegerv ( GL_GREEN_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_BLUE_SIZE:
+ glGetIntegerv ( GL_BLUE_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ALPHA_SIZE:
+ glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_RED_SIZE:
+#if defined(_WIN32_WCE)
+ returnValue = 0; /* WinCE doesn't support this feature */
+#else
+ glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
+#endif
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_GREEN_SIZE:
+#if defined(_WIN32_WCE)
+ returnValue = 0; /* WinCE doesn't support this feature */
+#else
+ glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
+#endif
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_BLUE_SIZE:
+#if defined(_WIN32_WCE)
+ returnValue = 0; /* WinCE doesn't support this feature */
+#else
+ glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
+#endif
+ return returnValue;
+ case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
+#if defined(_WIN32_WCE)
+ returnValue = 0; /* WinCE doesn't support this feature */
+#else
+ glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
+#endif
+ return returnValue;
+ case GLUT_WINDOW_DEPTH_SIZE:
+ glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
+ return returnValue;
+
+ case GLUT_WINDOW_BUFFER_SIZE:
+ returnValue = 1 ; /* ????? */
+ return returnValue;
+ case GLUT_WINDOW_STENCIL_SIZE:
+ returnValue = 0 ; /* ????? */
+ return returnValue;
+
+ case GLUT_WINDOW_X:
+ case GLUT_WINDOW_Y:
+ case GLUT_WINDOW_WIDTH:
+ case GLUT_WINDOW_HEIGHT:
+ {
+ /*
+ * There is considerable confusion about the "right thing to
+ * do" concerning window size and position. GLUT itself is
+ * not consistent between Windows and UNIX/X11; since
+ * platform independence is a virtue for "freeglut", we
+ * decided to break with GLUT's behaviour.
+ *
+ * Under UNIX/X11, it is apparently not possible to get the
+ * window border sizes in order to subtract them off the
+ * window's initial position until some time after the window
+ * has been created. Therefore we decided on the following
+ * behaviour, both under Windows and under UNIX/X11:
+ * - When you create a window with position (x,y) and size
+ * (w,h), the upper left hand corner of the outside of the
+ * window is at (x,y) and the size of the drawable area is
+ * (w,h).
+ * - When you query the size and position of the window--as
+ * is happening here for Windows--"freeglut" will return
+ * the size of the drawable area--the (w,h) that you
+ * specified when you created the window--and the coordinates
+ * of the upper left hand corner of the drawable
+ * area--which is NOT the (x,y) you specified.
+ */
+
+ RECT winRect;
+
+ freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
+
+#if defined(_WIN32_WCE)
+ GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
+#else
+ winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
+#endif /* defined(_WIN32_WCE) */
+
+ switch( eWhat )
+ {
+ case GLUT_WINDOW_X: return winRect.left ;
+ case GLUT_WINDOW_Y: return winRect.top ;
+ case GLUT_WINDOW_WIDTH: return winRect.right - winRect.left;
+ case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
+ }
+ }
+ break;
+
+ case GLUT_WINDOW_BORDER_WIDTH :
+ case GLUT_WINDOW_HEADER_HEIGHT :
+#if defined(_WIN32_WCE)
+ return 0;
+#else
+ {
+ DWORD windowStyle;
+
+ if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
+ windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
+ else
+ /* If no window, return sizes for a default window with title bar and border */
+ windowStyle = WS_OVERLAPPEDWINDOW;
+
+ switch( eWhat )
+ {
+ case GLUT_WINDOW_BORDER_WIDTH:
+ {
+ int xBorderWidth, yBorderWidth;
+ fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
+ return xBorderWidth;
+ }
+ case GLUT_WINDOW_HEADER_HEIGHT:
+ /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
+ return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
+ }
+ }
+#endif /* defined(_WIN32_WCE) */
+
+ case GLUT_DISPLAY_MODE_POSSIBLE:
+#if defined(_WIN32_WCE)
+ return 0;
+#else
+ return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
+ PFD_MAIN_PLANE );
+#endif /* defined(_WIN32_WCE) */
+
+
+ case GLUT_WINDOW_FORMAT_ID:
+#if !defined(_WIN32_WCE)
+ if( fgStructure.CurrentWindow != NULL )
+ return GetPixelFormat( fgStructure.CurrentWindow->Window.pContext.Device );
+#endif /* defined(_WIN32_WCE) */
+ return 0;
+
+ default:
+ fgWarning( "glutGet(): missing enum handle %d", eWhat );
+ break;
+ }
+
+ return -1;
+}
+
+
+int fgPlatformGlutDeviceGet ( GLenum eWhat )
+{
+ switch( eWhat )
+ {
+ case GLUT_HAS_KEYBOARD:
+ /*
+ * Win32 is assumed a keyboard, and this cannot be queried,
+ * except for WindowsCE.
+ */
+#if defined(_WIN32_CE)
+ return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
+# if FREEGLUT_LIB_PRAGMAS
+# pragma comment (lib,"Kbdui.lib")
+# endif
+
+#else
+ return 1;
+#endif
+
+ case GLUT_HAS_MOUSE:
+ /*
+ * MS Windows can be booted without a mouse.
+ */
+ return GetSystemMetrics( SM_MOUSEPRESENT );
+
+ case GLUT_NUM_MOUSE_BUTTONS:
+# if defined(_WIN32_WCE)
+ return 1;
+# else
+ return GetSystemMetrics( SM_CMOUSEBUTTONS );
+# endif
+
+ default:
+ fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
+ break;
+ }
+
+ /* And now -- the failure. */
+ return -1;
+}
+
+/*
+ * This is for querying the number of supported auxiliary or multisample
+ * buffers for a (the current?) display mode.
+ * see http://old.nabble.com/-GLX--glutGetModeValues-to13514723.html#a13514723
+ * Not currently implemented, but we should be able to query the relevant
+ * info using
+ * http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
+ * (if supported on the executing machine!)
+ */
+int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
+{
+ *size = 0;
+ return NULL;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * freeglut_structure_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sun Jan 22, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+void fgPlatformCreateWindow ( SFG_Window *window )
+{
+}
--- /dev/null
+/*
+ * freeglut_window_mswin.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sun Jan 22, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+
+/* The following include file is available from SGI but is not standard:
+ * #include <GL/wglext.h>
+ * So we copy the necessary parts out of it.
+ * XXX: should local definitions for extensions be put in a separate include file?
+ */
+typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+
+typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
+
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+
+#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+
+#ifndef WGL_ARB_create_context
+#define WGL_ARB_create_context 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
+
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#define ERROR_INVALID_PROFILE_ARB 0x2096
+#endif
+/* End of copying the necessary parts out of it. */
+
+#ifdef WM_TOUCH
+typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG);
+static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF;
+#endif
+
+/*
+ * Helper functions for getting client area from the window rect
+ * and the window rect from the client area given the style of the window
+ * (or a valid window pointer from which the style can be queried).
+ */
+extern void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
+
+
+/*
+ * Setup the pixel format for a Win32 window
+ */
+
+#if defined(_WIN32_WCE)
+static wchar_t* fghWstrFromStr(const char* str)
+{
+ int i,len=strlen(str);
+ wchar_t* wstr = (wchar_t*)malloc(2*len+2);
+ for(i=0; i<len; i++)
+ wstr[i] = str[i];
+ wstr[len] = 0;
+ return wstr;
+}
+#endif /* defined(_WIN32_WCE) */
+
+
+static void fghFillContextAttributes( int *attributes ) {
+ int where = 0, contextFlags, contextProfile;
+
+ if ( !fghIsLegacyContextVersionRequested() ) {
+ ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
+ ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
+ }
+
+ contextFlags =
+ fghMapBit( fgState.ContextFlags, GLUT_DEBUG, WGL_CONTEXT_DEBUG_BIT_ARB ) |
+ fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
+ if ( contextFlags != 0 ) {
+ ATTRIB_VAL( WGL_CONTEXT_FLAGS_ARB, contextFlags );
+ }
+
+ contextProfile =
+ fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, WGL_CONTEXT_CORE_PROFILE_BIT_ARB ) |
+ fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
+ if ( contextProfile != 0 ) {
+ ATTRIB_VAL( WGL_CONTEXT_PROFILE_MASK_ARB, contextProfile );
+ }
+
+ ATTRIB( 0 );
+}
+
+static int fghIsExtensionSupported( HDC hdc, const char *extension ) {
+ const char *pWglExtString;
+ PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB =
+ (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
+ if ( wglGetEntensionsStringARB == NULL )
+ {
+ return FALSE;
+ }
+ pWglExtString = wglGetEntensionsStringARB( hdc );
+ return ( pWglExtString != NULL ) && ( strstr(pWglExtString, extension) != NULL );
+}
+
+void fgNewWGLCreateContext( SFG_Window* window )
+{
+ HGLRC context;
+ int attributes[9];
+ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
+
+ /* If nothing fancy has been required, leave the context as it is */
+ if ( fghIsLegacyContextRequested() )
+ {
+ return;
+ }
+
+ wglMakeCurrent( window->Window.pContext.Device, window->Window.Context );
+
+ if ( !fghIsExtensionSupported( window->Window.pContext.Device, "WGL_ARB_create_context" ) )
+ {
+ return;
+ }
+
+ /* new context creation */
+ fghFillContextAttributes( attributes );
+
+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" );
+ if ( wglCreateContextAttribsARB == NULL )
+ {
+ fgError( "wglCreateContextAttribsARB not found" );
+ }
+
+ context = wglCreateContextAttribsARB( window->Window.pContext.Device, 0, attributes );
+ if ( context == NULL )
+ {
+ fghContextCreationError();
+ }
+
+ wglMakeCurrent( NULL, NULL );
+ wglDeleteContext( window->Window.Context );
+ window->Window.Context = context;
+}
+
+#if !defined(_WIN32_WCE)
+
+static void fghFillPFD( PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char layer_type )
+{
+ int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ if ( fgState.DisplayMode & GLUT_DOUBLE ) {
+ flags |= PFD_DOUBLEBUFFER;
+ }
+ if ( fgState.DisplayMode & GLUT_STEREO ) {
+ flags |= PFD_STEREO;
+ }
+
+#if defined(_MSC_VER)
+#pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
+#endif
+
+ /* Specify which pixel format do we opt for... */
+ ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ ppfd->nVersion = 1;
+ ppfd->dwFlags = flags;
+
+ if( fgState.DisplayMode & GLUT_INDEX ) {
+ ppfd->iPixelType = PFD_TYPE_COLORINDEX;
+ ppfd->cRedBits = 0;
+ ppfd->cGreenBits = 0;
+ ppfd->cBlueBits = 0;
+ ppfd->cAlphaBits = 0;
+ } else {
+ ppfd->iPixelType = PFD_TYPE_RGBA;
+ ppfd->cRedBits = 8;
+ ppfd->cGreenBits = 8;
+ ppfd->cBlueBits = 8;
+ ppfd->cAlphaBits = ( fgState.DisplayMode & GLUT_ALPHA ) ? 8 : 0;
+ }
+
+ ppfd->cColorBits = 24;
+ ppfd->cRedShift = 0;
+ ppfd->cGreenShift = 0;
+ ppfd->cBlueShift = 0;
+ ppfd->cAlphaShift = 0;
+ ppfd->cAccumBits = ( fgState.DisplayMode & GLUT_ACCUM ) ? 1 : 0;
+ ppfd->cAccumRedBits = 0;
+ ppfd->cAccumGreenBits = 0;
+ ppfd->cAccumBlueBits = 0;
+ ppfd->cAccumAlphaBits = 0;
+
+ /* Hmmm, or 32/0 instead of 24/8? */
+ ppfd->cDepthBits = 24;
+ ppfd->cStencilBits = 8;
+
+ ppfd->cAuxBuffers = fghNumberOfAuxBuffersRequested();
+ ppfd->iLayerType = layer_type;
+ ppfd->bReserved = 0;
+ ppfd->dwLayerMask = 0;
+ ppfd->dwVisibleMask = 0;
+ ppfd->dwDamageMask = 0;
+
+ ppfd->cColorBits = (BYTE) GetDeviceCaps( hdc, BITSPIXEL );
+}
+
+static void fghFillPixelFormatAttributes( int *attributes, const PIXELFORMATDESCRIPTOR *ppfd )
+{
+ int where = 0;
+
+ ATTRIB_VAL( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
+ ATTRIB_VAL( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
+ ATTRIB_VAL( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
+
+ ATTRIB_VAL( WGL_COLOR_BITS_ARB, ppfd->cColorBits );
+ ATTRIB_VAL( WGL_ALPHA_BITS_ARB, ppfd->cAlphaBits );
+ ATTRIB_VAL( WGL_DEPTH_BITS_ARB, ppfd->cDepthBits );
+ ATTRIB_VAL( WGL_STENCIL_BITS_ARB, ppfd->cStencilBits );
+
+ ATTRIB_VAL( WGL_DOUBLE_BUFFER_ARB, ( fgState.DisplayMode & GLUT_DOUBLE ) != 0 );
+
+ if ( fgState.DisplayMode & GLUT_SRGB ) {
+ ATTRIB_VAL( WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE );
+ }
+
+ ATTRIB_VAL( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
+ ATTRIB_VAL( WGL_SAMPLES_ARB, fgState.SampleNumber );
+ ATTRIB( 0 );
+}
+#endif
+
+GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
+ unsigned char layer_type )
+{
+#if defined(_WIN32_WCE)
+ return GL_TRUE;
+#else
+ PIXELFORMATDESCRIPTOR pfd;
+ PIXELFORMATDESCRIPTOR* ppfd = &pfd;
+ int pixelformat;
+ HDC current_hDC;
+ GLboolean success;
+
+ if (checkOnly)
+ current_hDC = CreateDC(TEXT("DISPLAY"), NULL ,NULL ,NULL);
+ else
+ current_hDC = window->Window.pContext.Device;
+
+ fghFillPFD( ppfd, current_hDC, layer_type );
+ pixelformat = ChoosePixelFormat( current_hDC, ppfd );
+
+ /* windows hack for multismapling/sRGB */
+ if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) ||
+ ( fgState.DisplayMode & GLUT_SRGB ) )
+ {
+ HGLRC rc, rc_before=wglGetCurrentContext();
+ HWND hWnd;
+ HDC hDC, hDC_before=wglGetCurrentDC();
+ WNDCLASS wndCls;
+
+ /* create a dummy window */
+ ZeroMemory(&wndCls, sizeof(wndCls));
+ wndCls.lpfnWndProc = DefWindowProc;
+ wndCls.hInstance = fgDisplay.pDisplay.Instance;
+ wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ wndCls.lpszClassName = _T("FREEGLUT_dummy");
+ RegisterClass( &wndCls );
+
+ hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.pDisplay.Instance, 0 );
+ hDC=GetDC(hWnd);
+ SetPixelFormat( hDC, pixelformat, ppfd );
+
+ rc = wglCreateContext( hDC );
+ wglMakeCurrent(hDC, rc);
+
+ if ( fghIsExtensionSupported( hDC, "WGL_ARB_multisample" ) )
+ {
+ PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc =
+ (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
+ if ( wglChoosePixelFormatARBProc )
+ {
+ int attributes[100];
+ int iPixelFormat;
+ BOOL bValid;
+ float fAttributes[] = { 0, 0 };
+ UINT numFormats;
+ fghFillPixelFormatAttributes( attributes, ppfd );
+ bValid = wglChoosePixelFormatARBProc(hDC, attributes, fAttributes, 1, &iPixelFormat, &numFormats);
+
+ if ( bValid && numFormats > 0 )
+ {
+ pixelformat = iPixelFormat;
+ }
+ }
+ }
+
+ wglMakeCurrent( hDC_before, rc_before);
+ wglDeleteContext(rc);
+ ReleaseDC(hWnd, hDC);
+ DestroyWindow(hWnd);
+ UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.pDisplay.Instance);
+ }
+
+ success = ( pixelformat != 0 ) && ( checkOnly || SetPixelFormat( current_hDC, pixelformat, ppfd ) );
+
+ if (checkOnly)
+ DeleteDC(current_hDC);
+
+ return success;
+#endif /* defined(_WIN32_WCE) */
+}
+
+
+
+void fgPlatformSetWindow ( SFG_Window *window )
+{
+ if ( window != fgStructure.CurrentWindow )
+ {
+ if( fgStructure.CurrentWindow )
+ ReleaseDC( fgStructure.CurrentWindow->Window.Handle,
+ fgStructure.CurrentWindow->Window.pContext.Device );
+
+ if ( window )
+ {
+ window->Window.pContext.Device = GetDC( window->Window.Handle );
+ wglMakeCurrent(
+ window->Window.pContext.Device,
+ window->Window.Context
+ );
+ }
+ }
+}
+
+
+
+/* Computes position of corners of window Rect (outer position including
+ * decorations) based on the provided client rect and based on the style
+ * of the window in question.
+ * If posIsOutside is set to true, the input client Rect is taken to follow
+ * freeGLUT's window specification convention in which the top-left corner
+ * is at the outside of the window, while the size
+ * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
+ * area.
+ */
+void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside )
+{
+ int xBorderWidth = 0, yBorderWidth = 0;
+
+ /* If window has title bar, correct rect for it */
+ if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
+ if (posIsOutside)
+ clientRect->bottom += GetSystemMetrics( SM_CYCAPTION );
+ else
+ clientRect->top -= GetSystemMetrics( SM_CYCAPTION );
+
+ /* get width of window's borders (frame), correct rect for it.
+ * Note, borders can be of zero width if style does not specify borders
+ */
+ fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
+ if (posIsOutside)
+ {
+ clientRect->right += xBorderWidth * 2;
+ clientRect->bottom += yBorderWidth * 2;
+ }
+ else
+ {
+ clientRect->left -= xBorderWidth;
+ clientRect->right += xBorderWidth;
+ clientRect->top -= yBorderWidth;
+ clientRect->bottom += yBorderWidth;
+ }
+}
+
+/* Computes position of corners of window Rect (outer position including
+ * decorations) based on the provided client rect and based on the style
+ * of the window in question. If the window pointer or the window handle
+ * is NULL, a fully decorated window (caption and border) is assumed.
+ * Furthermore, if posIsOutside is set to true, the input client Rect is
+ * taken to follow freeGLUT's window specification convention in which the
+ * top-left corner is at the outside of the window, while the size
+ * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
+ * area.
+*/
+void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside )
+{
+ DWORD windowStyle = 0;
+
+ if (window && window->Window.Handle)
+ windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
+ else
+ windowStyle = WS_OVERLAPPEDWINDOW;
+
+ fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, posIsOutside);
+}
+
+/* Computes position of corners of client area (drawable area) of a window
+ * based on the provided window Rect (outer position including decorations)
+ * and based on the style of the window in question. If the window pointer
+ * or the window handle is NULL, a fully decorated window (caption and
+ * border) is assumed.
+ * Furthermore, if wantPosOutside is set to true, the output client Rect
+ * will follow freeGLUT's window specification convention in which the
+ * top-left corner is at the outside of the window, the size
+ * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
+ * area.
+ */
+void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside )
+{
+ DWORD windowStyle = 0;
+ int xBorderWidth = 0, yBorderWidth = 0;
+
+ if (window && window->Window.Handle)
+ windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
+ else
+ windowStyle = WS_OVERLAPPEDWINDOW;
+
+ /* If window has title bar, correct rect for it */
+ if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
+ if (wantPosOutside)
+ windowRect->bottom -= GetSystemMetrics( SM_CYCAPTION );
+ else
+ windowRect->top += GetSystemMetrics( SM_CYCAPTION );
+
+ /* get width of window's borders (frame), correct rect for it.
+ * Note, borders can be of zero width if style does not specify borders
+ */
+ fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
+ if (wantPosOutside)
+ {
+ windowRect->right -= xBorderWidth * 2;
+ windowRect->bottom -= yBorderWidth * 2;
+ }
+ else
+ {
+ windowRect->left += xBorderWidth;
+ windowRect->right -= xBorderWidth;
+ windowRect->top += yBorderWidth;
+ windowRect->bottom -= yBorderWidth;
+ }
+}
+
+/* Gets the rect describing the client area (drawable area) of the
+ * specified window.
+ * Returns an empty rect if window pointer or window handle is NULL.
+ * If wantPosOutside is set to true, the output client Rect
+ * will follow freeGLUT's window specification convention in which the
+ * top-left corner is at the outside of the window, while the size
+ * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
+ * area.
+ */
+RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
+{
+ RECT windowRect = {0,0,0,0};
+
+ freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
+
+ /*
+ * call GetWindowRect()
+ * (this returns the pixel coordinates of the outside of the window)
+ */
+ GetWindowRect( window->Window.Handle, &windowRect );
+
+ /* Then correct the results */
+ fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside);
+
+ return windowRect;
+}
+
+/* Returns the width of the window borders based on the window's style.
+ */
+void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth)
+{
+ if (windowStyle & WS_THICKFRAME)
+ {
+ *xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
+ *yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME);
+ }
+ else if (windowStyle & WS_DLGFRAME)
+ {
+ *xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
+ *yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
+ }
+ else
+ {
+ *xBorderWidth = 0;
+ *yBorderWidth = 0;
+ }
+}
+
+#if(WINVER >= 0x500)
+typedef struct
+{
+ int *x;
+ int *y;
+ const char *name;
+} m_proc_t;
+
+static BOOL CALLBACK m_proc(HMONITOR mon,
+ HDC hdc,
+ LPRECT rect,
+ LPARAM data)
+{
+ m_proc_t *dp=(m_proc_t *)data;
+ MONITORINFOEX info;
+ BOOL res;
+ info.cbSize=sizeof(info);
+ res=GetMonitorInfo(mon,(LPMONITORINFO)&info);
+ if( res )
+ {
+ if( strcmp(dp->name,info.szDevice)==0 )
+ {
+ *(dp->x)=info.rcMonitor.left;
+ *(dp->y)=info.rcMonitor.top;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * this function returns the origin of the screen identified by
+ * fgDisplay.pDisplay.DisplayName, and 0 otherwise.
+ * This is used in fgOpenWindow to open the gamemode window on the screen
+ * identified by the -display command line argument. The function should
+ * not be called otherwise.
+ */
+
+static void get_display_origin(int *xp,int *yp)
+{
+ *xp = 0;
+ *yp = 0;
+
+ if( fgDisplay.pDisplay.DisplayName )
+ {
+ m_proc_t st;
+ st.x=xp;
+ st.y=yp;
+ st.name=fgDisplay.pDisplay.DisplayName;
+ EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st);
+ }
+}
+#else
+#pragma message( "-display parameter only works if compiled with WINVER >= 0x0500")
+
+static void get_display_origin(int *xp,int *yp)
+{
+ *xp = 0;
+ *yp = 0;
+
+ if( fgDisplay.pDisplay.DisplayName )
+ {
+ fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500");
+ }
+}
+#endif
+
+
+
+/*
+ * Opens a window. Requires a SFG_Window object created and attached
+ * to the freeglut structure. OpenGL context is created here.
+ */
+void fgPlatformOpenWindow( SFG_Window* window, const char* title,
+ GLboolean positionUse, int x, int y,
+ GLboolean sizeUse, int w, int h,
+ GLboolean gameMode, GLboolean isSubWindow )
+{
+
+ WNDCLASS wc;
+ DWORD flags = 0;
+ DWORD exFlags = 0;
+ ATOM atom;
+
+ /* Grab the window class we have registered on glutInit(): */
+ atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc );
+ FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
+ "fgOpenWindow" );
+
+ /* Determine window style flags*/
+ if( gameMode )
+ {
+ FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
+ "Game mode being invoked on a subwindow",
+ "fgOpenWindow" );
+
+ /*
+ * Set the window creation flags appropriately to make the window
+ * entirely visible:
+ */
+ flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+ }
+ else
+ {
+ flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+ /*
+ * There's a small difference between creating the top, child and
+ * menu windows
+ */
+ if ( window->IsMenu )
+ {
+ flags |= WS_POPUP;
+ exFlags |= WS_EX_TOOLWINDOW;
+ }
+#if defined(_WIN32_WCE)
+ /* no decorations for windows CE */
+#else
+ /* if this is not a subwindow (child), set its style based on the requested display mode */
+ else if( window->Parent == NULL )
+ if ( fgState.DisplayMode & GLUT_BORDERLESS )
+ {
+ /* no window decorations needed */
+ }
+ else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
+ /* only window decoration is a border, no title bar or buttons */
+ flags |= WS_DLGFRAME;
+ else
+ /* window decoration are a border, title bar and buttons.
+ * NB: we later query whether the window has a title bar or
+ * not by testing for the maximize button, as the test for
+ * WS_CAPTION can be true without the window having a title
+ * bar. This style WS_OVERLAPPEDWINDOW gives you a maximize
+ * button. */
+ flags |= WS_OVERLAPPEDWINDOW;
+#endif
+ else
+ /* subwindows always have no decoration, but are marked as a child window to the OS */
+ flags |= WS_CHILD;
+ }
+
+ /* determine window size and position */
+ if( gameMode )
+ {
+ /* if in gamemode, query the origin of specified by the -display
+ * command line parameter (if any) and offset the upper-left corner
+ * of the window so we create the window on that screen.
+ * The -display argument doesn't do anything if not trying to enter
+ * gamemode.
+ */
+ int xoff=0, yoff=0;
+ get_display_origin(&xoff,&yoff);
+ x += xoff;
+ y += yoff;
+ }
+ if( !positionUse )
+ {
+ x = CW_USEDEFAULT;
+ y = CW_USEDEFAULT;
+ }
+ if( !sizeUse )
+ {
+ if( ! window->IsMenu )
+ {
+ w = CW_USEDEFAULT;
+ h = CW_USEDEFAULT;
+ }
+ else /* fail safe - Windows can make a window of size (0, 0) */
+ w = h = 300; /* default window size */
+ }
+ /* store requested client area width and height */
+ window->State.Width = w;
+ window->State.Height = h;
+
+#if !defined(_WIN32_WCE) /* no decorations for windows CE */
+ if( sizeUse )
+ {
+ RECT windowRect;
+ /*
+ * Update the window dimensions, taking the window decorations
+ * into account. FreeGLUT is to create the window with the
+ * topleft outside corner at (x,y) and with client area
+ * dimensions (w,h).
+ * note: don't need to do this when w=h=CW_USEDEFAULT, so in the
+ * if( sizeUse ) here is convenient.
+ */
+ windowRect.left = x;
+ windowRect.top = y;
+ windowRect.right = x+w;
+ windowRect.bottom = y+h;
+
+ fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
+
+ w = windowRect.right - windowRect.left;
+ h = windowRect.bottom- windowRect.top;
+ }
+#endif /* !defined(_WIN32_WCE) */
+
+#if defined(_WIN32_WCE)
+ {
+ wchar_t* wstr = fghWstrFromStr(title);
+
+ window->Window.Handle = CreateWindow(
+ _T("FREEGLUT"),
+ wstr,
+ WS_VISIBLE | WS_POPUP,
+ 0,0, 240,320,
+ NULL,
+ NULL,
+ fgDisplay.pDisplay.Instance,
+ (LPVOID) window
+ );
+
+ free(wstr);
+
+ SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON);
+ SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON);
+ SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR);
+ MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE);
+ ShowWindow(window->Window.Handle, SW_SHOW);
+ UpdateWindow(window->Window.Handle);
+ }
+#else
+ window->Window.Handle = CreateWindowEx(
+ exFlags,
+ _T("FREEGLUT"),
+ title,
+ flags,
+ x, y, w, h,
+ (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
+ (HMENU) NULL,
+ fgDisplay.pDisplay.Instance,
+ (LPVOID) window
+ );
+#endif /* defined(_WIN32_WCE) */
+
+ if( !( window->Window.Handle ) )
+ fgError( "Failed to create a window (%s)!", title );
+
+#if !defined(_WIN32_WCE)
+ /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */
+ SetWindowLong(window->Window.Handle, GWL_STYLE, flags);
+ SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+#endif /* defined(_WIN32_WCE) */
+
+ /* Make a menu window always on top - fix Feature Request 947118 */
+ if( window->IsMenu || gameMode )
+ SetWindowPos(
+ window->Window.Handle,
+ HWND_TOPMOST,
+ 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE
+ );
+
+ /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */
+ #ifdef WM_TOUCH
+ if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF)
+ fghRegisterTouchWindow = (pRegisterTouchWindow)GetProcAddress(GetModuleHandle("user32"),"RegisterTouchWindow");
+ if (fghRegisterTouchWindow)
+ fghRegisterTouchWindow( window->Window.Handle, TWF_FINETOUCH | TWF_WANTPALM );
+ #endif
+
+#if defined(_WIN32_WCE)
+ ShowWindow( window->Window.Handle, SW_SHOW );
+#else
+ ShowWindow( window->Window.Handle,
+ fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
+#endif /* defined(_WIN32_WCE) */
+
+ UpdateWindow( window->Window.Handle );
+ ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */
+
+}
+
+
+/*
+ * Closes a window, destroying the frame and OpenGL context
+ */
+void fgPlatformCloseWindow( SFG_Window* window )
+{
+ /* Make sure we don't close a window with current context active */
+ if( fgStructure.CurrentWindow == window )
+ wglMakeCurrent( NULL, NULL );
+
+ /*
+ * Step through the list of windows. If the rendering context
+ * is not being used by another window, then we delete it.
+ */
+ {
+ int used = FALSE ;
+ SFG_Window *iter ;
+
+ for( iter = (SFG_Window *)fgStructure.Windows.First;
+ iter;
+ iter = (SFG_Window *)iter->Node.Next )
+ {
+ if( ( iter->Window.Context == window->Window.Context ) &&
+ ( iter != window ) )
+ used = TRUE;
+ }
+
+ if( ! used )
+ wglDeleteContext( window->Window.Context );
+ }
+
+ DestroyWindow( window->Window.Handle );
+}
+
+
+
+/*
+ * This function makes the current window visible
+ */
+void fgPlatformGlutShowWindow( void )
+{
+ ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW );
+}
+
+/*
+ * This function hides the current window
+ */
+void fgPlatformGlutHideWindow( void )
+{
+ ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE );
+}
+
+/*
+ * Iconify the current window (top-level windows only)
+ */
+void fgPlatformGlutIconifyWindow( void )
+{
+ ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE );
+}
+
+/*
+ * Set the current window's title
+ */
+void fgPlatformGlutSetWindowTitle( const char* title )
+{
+#ifdef _WIN32_WCE
+ {
+ wchar_t* wstr = fghWstrFromStr(title);
+ SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
+ free(wstr);
+ }
+#else
+ SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
+#endif
+}
+
+/*
+ * Set the current window's iconified title
+ */
+void fgPlatformGlutSetIconTitle( const char* title )
+{
+#ifdef _WIN32_WCE
+ {
+ wchar_t* wstr = fghWstrFromStr(title);
+ SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
+ free(wstr);
+ }
+#else
+ SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
+#endif
+}
+
+/*
+ * Change the current window's position
+ */
+void fgPlatformGlutPositionWindow( int x, int y )
+{
+ RECT winRect;
+
+ /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
+ GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
+ MoveWindow(
+ fgStructure.CurrentWindow->Window.Handle,
+ x,
+ y,
+ winRect.right - winRect.left,
+ winRect.bottom - winRect.top,
+ TRUE
+ );
+}
+
+/*
+ * Lowers the current window (by Z order change)
+ */
+void fgPlatformGlutPushWindow( void )
+{
+ SetWindowPos(
+ fgStructure.CurrentWindow->Window.Handle,
+ HWND_BOTTOM,
+ 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE
+ );
+}
+
+/*
+ * Raises the current window (by Z order change)
+ */
+void fgPlatformGlutPopWindow( void )
+{
+ SetWindowPos(
+ fgStructure.CurrentWindow->Window.Handle,
+ HWND_TOP,
+ 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE
+ );
+}
+
+/*
+ * Resize the current window so that it fits the whole screen
+ */
+void fgPlatformGlutFullScreen( SFG_Window *win )
+{
+#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
+
+ if (glutGet(GLUT_FULL_SCREEN))
+ {
+ /* Leave full screen state before entering fullscreen again (resizing?) */
+ glutLeaveFullScreen();
+ }
+
+ {
+#if(WINVER >= 0x0500) /* Windows 2000 or later */
+ DWORD s;
+ RECT rect;
+ HMONITOR hMonitor;
+ MONITORINFO mi;
+
+ /* For fullscreen mode, first remove all window decoration
+ * and set style to popup so it will overlap the taskbar
+ * then force to maximize on the screen on which it has the most
+ * overlap.
+ */
+
+
+ /* store current window rect */
+ GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect );
+
+ /* store current window style */
+ win->State.pWState.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE);
+
+ /* remove decorations from style and add popup style*/
+ s &= ~WS_OVERLAPPEDWINDOW;
+ s |= WS_POPUP;
+ SetWindowLong(win->Window.Handle, GWL_STYLE, s);
+ SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+
+ /* For fullscreen mode, find the monitor that is covered the most
+ * by the window and get its rect as the resize target.
+ */
+ hMonitor= MonitorFromRect(&win->State.pWState.OldRect, MONITOR_DEFAULTTONEAREST);
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(hMonitor, &mi);
+ rect = mi.rcMonitor;
+#else /* if (WINVER >= 0x0500) */
+ RECT rect;
+
+ /* For fullscreen mode, force the top-left corner to 0,0
+ * and adjust the window rectangle so that the client area
+ * covers the whole screen.
+ */
+
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = fgDisplay.ScreenWidth;
+ rect.bottom = fgDisplay.ScreenHeight;
+
+ AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
+ WS_CLIPCHILDREN, FALSE );
+#endif /* (WINVER >= 0x0500) */
+
+ /*
+ * then resize window
+ * SWP_NOACTIVATE Do not activate the window
+ * SWP_NOOWNERZORDER Do not change position in z-order
+ * SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message
+ * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
+ */
+ SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
+ HWND_TOP,
+ rect.left,
+ rect.top,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
+ SWP_NOZORDER
+ );
+
+ win->State.IsFullscreen = GL_TRUE;
+ }
+#endif
+}
+
+/*
+ * If we are fullscreen, resize the current window back to its original size
+ */
+void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
+{
+#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
+ if (!glutGet(GLUT_FULL_SCREEN))
+ {
+ /* nothing to do */
+ return;
+ }
+
+ /* restore style of window before making it fullscreen */
+ SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.pWState.OldStyle);
+ SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+
+ /* Then resize */
+ SetWindowPos(win->Window.Handle,
+ HWND_TOP,
+ win->State.pWState.OldRect.left,
+ win->State.pWState.OldRect.top,
+ win->State.pWState.OldRect.right - win->State.pWState.OldRect.left,
+ win->State.pWState.OldRect.bottom - win->State.pWState.OldRect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
+ SWP_NOZORDER
+ );
+
+ win->State.IsFullscreen = GL_FALSE;
+#endif
+}
+
+/*
+ * Toggle the window's full screen state.
+ */
+void fgPlatformGlutFullScreenToggle( SFG_Window *win )
+{
+ if (!win->State.IsFullscreen)
+ glutFullScreen();
+ else
+ glutLeaveFullScreen();
+}
+
+
+/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */
+
+int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exit_function)(int) )
+{
+ __glutExitFunc = exit_function;
+ return glutCreateWindow( title );
+}
+
+++ /dev/null
-/*
- * freeglut_cursor_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Thu Jan 19, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-
-void fgPlatformSetCursor ( SFG_Window *window, int cursorID )
-{
- /*
- * Joe Krahn is re-writing the following code.
- */
- /* Set the cursor AND change it for this window class. */
-#if !defined(__MINGW64__) && _MSC_VER <= 1200
-# define MAP_CURSOR(a,b) \
- case a: \
- SetCursor( LoadCursor( NULL, b ) ); \
- SetClassLong( window->Window.Handle, \
- GCL_HCURSOR, \
- ( LONG )LoadCursor( NULL, b ) ); \
- break;
- /* Nuke the cursor AND change it for this window class. */
-# define ZAP_CURSOR(a,b) \
- case a: \
- SetCursor( NULL ); \
- SetClassLong( window->Window.Handle, \
- GCL_HCURSOR, ( LONG )NULL ); \
- break;
-#else
-# define MAP_CURSOR(a,b) \
- case a: \
- SetCursor( LoadCursor( NULL, b ) ); \
- SetClassLongPtr( window->Window.Handle, \
- GCLP_HCURSOR, \
- ( LONG )( LONG_PTR )LoadCursor( NULL, b ) ); \
- break;
- /* Nuke the cursor AND change it for this window class. */
-# define ZAP_CURSOR(a,b) \
- case a: \
- SetCursor( NULL ); \
- SetClassLongPtr( window->Window.Handle, \
- GCLP_HCURSOR, ( LONG )( LONG_PTR )NULL ); \
- break;
-#endif
-
- switch( cursorID )
- {
- MAP_CURSOR( GLUT_CURSOR_RIGHT_ARROW, IDC_ARROW );
- MAP_CURSOR( GLUT_CURSOR_LEFT_ARROW, IDC_ARROW );
- MAP_CURSOR( GLUT_CURSOR_INFO, IDC_HELP );
- MAP_CURSOR( GLUT_CURSOR_DESTROY, IDC_CROSS );
- MAP_CURSOR( GLUT_CURSOR_HELP, IDC_HELP );
- MAP_CURSOR( GLUT_CURSOR_CYCLE, IDC_SIZEALL );
- MAP_CURSOR( GLUT_CURSOR_SPRAY, IDC_CROSS );
- MAP_CURSOR( GLUT_CURSOR_WAIT, IDC_WAIT );
- MAP_CURSOR( GLUT_CURSOR_TEXT, IDC_IBEAM );
- MAP_CURSOR( GLUT_CURSOR_CROSSHAIR, IDC_CROSS );
- MAP_CURSOR( GLUT_CURSOR_UP_DOWN, IDC_SIZENS );
- MAP_CURSOR( GLUT_CURSOR_LEFT_RIGHT, IDC_SIZEWE );
- MAP_CURSOR( GLUT_CURSOR_TOP_SIDE, IDC_ARROW ); /* XXX ToDo */
- MAP_CURSOR( GLUT_CURSOR_BOTTOM_SIDE, IDC_ARROW ); /* XXX ToDo */
- MAP_CURSOR( GLUT_CURSOR_LEFT_SIDE, IDC_ARROW ); /* XXX ToDo */
- MAP_CURSOR( GLUT_CURSOR_RIGHT_SIDE, IDC_ARROW ); /* XXX ToDo */
- MAP_CURSOR( GLUT_CURSOR_TOP_LEFT_CORNER, IDC_SIZENWSE );
- MAP_CURSOR( GLUT_CURSOR_TOP_RIGHT_CORNER, IDC_SIZENESW );
- MAP_CURSOR( GLUT_CURSOR_BOTTOM_RIGHT_CORNER, IDC_SIZENWSE );
- MAP_CURSOR( GLUT_CURSOR_BOTTOM_LEFT_CORNER, IDC_SIZENESW );
- MAP_CURSOR( GLUT_CURSOR_INHERIT, IDC_ARROW ); /* XXX ToDo */
- ZAP_CURSOR( GLUT_CURSOR_NONE, NULL );
- MAP_CURSOR( GLUT_CURSOR_FULL_CROSSHAIR, IDC_CROSS ); /* XXX ToDo */
-
- default:
- fgError( "Unknown cursor type: %d", cursorID );
- break;
- }
-}
-
-
-void fgPlatformWarpPointer ( int x, int y )
-{
- POINT coords;
- coords.x = x;
- coords.y = y;
-
- /* ClientToScreen() translates {coords} for us. */
- ClientToScreen( fgStructure.CurrentWindow->Window.Handle, &coords );
- SetCursorPos( coords.x, coords.y );
-}
-
-
+++ /dev/null
-/*
- * freeglut_display_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sat Jan 28, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-
-
-void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow )
-{
- SwapBuffers( CurrentWindow->Window.pContext.Device );
-}
+++ /dev/null
-/*
- * freeglut_ext_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Thu Jan 19, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-GLUTproc fgPlatformGetGLUTProcAddress( const char* procName )
-{
-#if !defined(_WIN32_WCE)
- /* optimization: quick initial check */
- if( strncmp( procName, "glut", 4 ) != 0 )
- return NULL;
-
-#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x;
- CHECK_NAME(glutJoystickFunc);
- CHECK_NAME(glutForceJoystickFunc);
- CHECK_NAME(glutGameModeString);
- CHECK_NAME(glutEnterGameMode);
- CHECK_NAME(glutLeaveGameMode);
- CHECK_NAME(glutGameModeGet);
-#undef CHECK_NAME
-#endif /* !defined(_WIN32_WCE) */
-
- return NULL;
-}
-
-
-
-SFG_Proc fgPlatformGetProcAddress( const char *procName )
-{
- return (SFG_Proc)wglGetProcAddress( ( LPCSTR )procName );
-}
+++ /dev/null
-/*
- * freeglut_gamemode_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Thu Jan 19, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-/*
- * Remembers the current visual settings, so that
- * we can change them and restore later...
- */
-void fgPlatformRememberState( void )
-{
- /* Grab the current desktop settings... */
-
- /* hack to get around my stupid cross-gcc headers */
- #define FREEGLUT_ENUM_CURRENT_SETTINGS -1
-
- EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS,
- &fgDisplay.pDisplay.DisplayMode );
-
- /* Make sure we will be restoring all settings needed */
- fgDisplay.pDisplay.DisplayMode.dmFields |=
- DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
-
-}
-
-/*
- * Restores the previously remembered visual settings
- */
-void fgPlatformRestoreState( void )
-{
- /* Restore the previously remembered desktop display settings */
- ChangeDisplaySettingsEx( fgDisplay.pDisplay.DisplayName,&fgDisplay.pDisplay.DisplayMode, 0,0,0 );
-}
-
-
-
-
-/*
- * Changes the current display mode to match user's settings
- */
-GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )
-{
- GLboolean success = GL_FALSE;
- DEVMODE devMode;
- char *fggmstr = NULL;
- char displayMode[300];
-
- success = GL_FALSE;
-
- EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, -1, &devMode );
- devMode.dmFields = 0;
-
- if (fgState.GameModeSize.X!=-1)
- {
- devMode.dmPelsWidth = fgState.GameModeSize.X;
- devMode.dmFields |= DM_PELSWIDTH;
- }
- if (fgState.GameModeSize.Y!=-1)
- {
- devMode.dmPelsHeight = fgState.GameModeSize.Y;
- devMode.dmFields |= DM_PELSHEIGHT;
- }
- if (fgState.GameModeDepth!=-1)
- {
- devMode.dmBitsPerPel = fgState.GameModeDepth;
- devMode.dmFields |= DM_BITSPERPEL;
- }
- if (fgState.GameModeRefresh!=-1)
- {
- devMode.dmDisplayFrequency = fgState.GameModeRefresh;
- devMode.dmFields |= DM_DISPLAYFREQUENCY;
- }
-
- switch ( ChangeDisplaySettingsEx(fgDisplay.pDisplay.DisplayName, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) )
- {
- case DISP_CHANGE_SUCCESSFUL:
- success = GL_TRUE;
-
- if (!haveToTest)
- {
- /* update vars in case if windows switched to proper mode */
- EnumDisplaySettings( fgDisplay.pDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode );
- fgState.GameModeSize.X = devMode.dmPelsWidth;
- fgState.GameModeSize.Y = devMode.dmPelsHeight;
- fgState.GameModeDepth = devMode.dmBitsPerPel;
- fgState.GameModeRefresh = devMode.dmDisplayFrequency;
- }
- break;
- case DISP_CHANGE_RESTART:
- fggmstr = "The computer must be restarted for the graphics mode to work.";
- break;
- case DISP_CHANGE_BADFLAGS:
- fggmstr = "An invalid set of flags was passed in.";
- break;
- case DISP_CHANGE_BADPARAM:
- fggmstr = "An invalid parameter was passed in. This can include an invalid flag or combination of flags.";
- break;
- case DISP_CHANGE_FAILED:
- fggmstr = "The display driver failed the specified graphics mode.";
- break;
- case DISP_CHANGE_BADMODE:
- fggmstr = "The graphics mode is not supported.";
- break;
- default:
- fggmstr = "Unknown error in graphics mode???"; /* dunno if it is possible,MSDN does not mention any other error */
- break;
- }
-
- if ( !success )
- {
- /* I'd rather get info whats going on in my program than wonder about */
- /* magic happenings behind my back, its lib for devels at last ;) */
-
- /* append display mode to error to make things more informative */
- sprintf(displayMode,"%s Problem with requested mode: %ix%i:%i@%i", fggmstr, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel, devMode.dmDisplayFrequency);
- fgWarning(displayMode);
- }
-
- return success;
-}
-
-void fgPlatformEnterGameMode( void )
-{
-}
-
-void fgPlatformLeaveGameMode( void )
-{
-}
+++ /dev/null
-/*
- * freeglut_init_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Thu Jan 19, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define FREEGLUT_BUILDING_LIB
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-
-extern LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam );
-
-
-/*
- * A call to this function should initialize all the display stuff...
- */
-void fgPlatformInitialize( const char* displayName )
-{
- WNDCLASS wc;
- ATOM atom;
-
- /* What we need to do is to initialize the fgDisplay global structure here. */
- fgDisplay.pDisplay.Instance = GetModuleHandle( NULL );
- fgDisplay.pDisplay.DisplayName= displayName ? strdup(displayName) : 0 ;
- atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc );
-
- if( atom == 0 )
- {
- ZeroMemory( &wc, sizeof(WNDCLASS) );
-
- /*
- * Each of the windows should have its own device context, and we
- * want redraw events during Vertical and Horizontal Resizes by
- * the user.
- *
- * XXX Old code had "| CS_DBCLCKS" commented out. Plans for the
- * XXX future? Dead-end idea?
- */
- wc.lpfnWndProc = fgPlatformWindowProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = fgDisplay.pDisplay.Instance;
- wc.hIcon = LoadIcon( fgDisplay.pDisplay.Instance, _T("GLUT_ICON") );
-
-#if defined(_WIN32_WCE)
- wc.style = CS_HREDRAW | CS_VREDRAW;
-#else
- wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- if (!wc.hIcon)
- wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
-#endif
-
- wc.hCursor = LoadCursor( NULL, IDC_ARROW );
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = _T("FREEGLUT");
-
- /* Register the window class */
- atom = RegisterClass( &wc );
- FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Not Registered", "fgPlatformInitialize" );
- }
-
- /* The screen dimensions can be obtained via GetSystemMetrics() calls */
- fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
- fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
-
- {
- HWND desktop = GetDesktopWindow( );
- HDC context = GetDC( desktop );
-
- fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
- fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
-
- ReleaseDC( desktop, context );
- }
- /* If we have a DisplayName try to use it for metrics */
- if( fgDisplay.pDisplay.DisplayName )
- {
- HDC context = CreateDC(fgDisplay.pDisplay.DisplayName,0,0,0);
- if( context )
- {
- fgDisplay.ScreenWidth = GetDeviceCaps( context, HORZRES );
- fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES );
- fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
- fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
- DeleteDC(context);
- }
- else
- fgWarning("fgPlatformInitialize: "
- "CreateDC failed, Screen size info may be incorrect\n"
- "This is quite likely caused by a bad '-display' parameter");
-
- }
- /* Set the timer granularity to 1 ms */
- timeBeginPeriod ( 1 );
-
-
- fgState.Initialised = GL_TRUE;
-
- /* Avoid registering atexit callback on Win32 as it can result in an
- * access violation due to calling into a module which has been
- * unloaded.
- * Any cleanup isn't needed on Windows anyway, the OS takes care of it.
- * see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
- */
-/* atexit(fgDeinitialize); */
-
- /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */
- fgInitialiseInputDevices();
-}
-
-
-
-/* Platform-Specific Deinitialization Functions: */
-extern void fghCloseInputDevices ( void );
-
-void fgPlatformDeinitialiseInputDevices ( void )
-{
-#if !defined(_WIN32_WCE)
- fghCloseInputDevices ();
-#endif /* !defined(_WIN32_WCE) */
- fgState.JoysticksInitialised = GL_FALSE;
- fgState.InputDevsInitialised = GL_FALSE;
-}
-
-void fgPlatformCloseDisplay ( void )
-{
- if( fgDisplay.pDisplay.DisplayName )
- {
- free( fgDisplay.pDisplay.DisplayName );
- fgDisplay.pDisplay.DisplayName = NULL;
- }
-
- /* Reset the timer granularity */
- timeEndPeriod ( 1 );
-}
-
-void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext )
-{
- /* Do nothing -- this is required for X11 */
-}
-
-/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */
-
-void (__cdecl *__glutExitFunc)( int return_value ) = NULL;
-
-void FGAPIENTRY __glutInitWithExit( int *pargc, char **argv, void (__cdecl *exit_function)(int) )
-{
- __glutExitFunc = exit_function;
- glutInit(pargc, argv);
-}
-
+++ /dev/null
-/*
- * freeglut_input_devices_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sat Jan 21, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-#include <sys/types.h>
-#include <winbase.h>
-
-typedef struct {
- HANDLE fh;
- COMMTIMEOUTS timeouts_save;
- DCB dcb_save;
-} SERIALPORT;
-
-/* Serial Port Prototypes */
-SERIALPORT *serial_open ( const char *device );
-void serial_close ( SERIALPORT *port );
-int serial_getchar ( SERIALPORT *port );
-int serial_putchar ( SERIALPORT *port, unsigned char ch );
-void serial_flush ( SERIALPORT *port );
-
-
-void fgPlatformRegisterDialDevice ( const char *dial_device )
-{
- if (!dial_device){
- static char devname[256];
- DWORD size=sizeof(devname);
- DWORD type = REG_SZ;
- HKEY key;
- if (RegOpenKeyA(HKEY_LOCAL_MACHINE,"SOFTWARE\\FreeGLUT",&key)==ERROR_SUCCESS) {
- if (RegQueryValueExA(key,"DialboxSerialPort",NULL,&type,(LPBYTE)devname,&size)==ERROR_SUCCESS){
- dial_device=devname;
- }
- RegCloseKey(key);
- }
- }
-}
-
-
-/* Serial Port Functions */
-SERIALPORT *serial_open(const char *device){
- HANDLE fh;
- DCB dcb={sizeof(DCB)};
- COMMTIMEOUTS timeouts;
- SERIALPORT *port;
-
- fh = CreateFile(device,GENERIC_READ|GENERIC_WRITE,0,NULL,
- OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- if (!fh) return NULL;
-
- port = malloc(sizeof(SERIALPORT));
- ZeroMemory(port, sizeof(SERIALPORT));
- port->fh = fh;
-
- /* save current port settings */
- GetCommState(fh,&port->dcb_save);
- GetCommTimeouts(fh,&port->timeouts_save);
-
- dcb.DCBlength=sizeof(DCB);
- BuildCommDCB("96,n,8,1",&dcb);
- SetCommState(fh,&dcb);
-
- ZeroMemory(&timeouts,sizeof(timeouts));
- timeouts.ReadTotalTimeoutConstant=1;
- timeouts.WriteTotalTimeoutConstant=1;
- SetCommTimeouts(fh,&timeouts);
-
- serial_flush(port);
-
- return port;
-}
-
-void serial_close(SERIALPORT *port){
- if (port){
- /* restore old port settings */
- SetCommState(port->fh,&port->dcb_save);
- SetCommTimeouts(port->fh,&port->timeouts_save);
- CloseHandle(port->fh);
- free(port);
- }
-}
-
-int serial_getchar(SERIALPORT *port){
- DWORD n;
- unsigned char ch;
- if (!port) return EOF;
- if (!ReadFile(port->fh,&ch,1,&n,NULL)) return EOF;
- if (n==1) return ch;
- return EOF;
-}
-
-int serial_putchar(SERIALPORT *port, unsigned char ch){
- DWORD n;
- if (!port) return 0;
- return WriteFile(port->fh,&ch,1,&n,NULL);
-}
-
-void serial_flush ( SERIALPORT *port )
-{
- FlushFileBuffers(port->fh);
-}
-
+++ /dev/null
-/*
- * freeglut_internal_mswin.h
- *
- * The freeglut library private include file.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Thu Jan 19, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef FREEGLUT_INTERNAL_MSWIN_H
-#define FREEGLUT_INTERNAL_MSWIN_H
-
-
-/* All Win32 headers depend on the huge windows.h recursive include.
- * Note: Lower-case header names are used, for best cross-platform
- * compatibility.
- */
-#if !defined(_WIN32_WCE)
-# include <windows.h>
-# include <windowsx.h>
-# include <mmsystem.h>
-/* CYGWIN does not have tchar.h, but has TEXT(x), defined in winnt.h. */
-# ifndef __CYGWIN__
-# include <tchar.h>
-# else
-# define _TEXT(x) TEXT(x)
-# define _T(x) TEXT(x)
-# endif
-
-#endif
-
-
-#ifndef HAVE_VFPRINTF
-#define HAVE_VFPRINTF 1
-#endif
-
-/* MinGW may lack a prototype for ChangeDisplaySettingsEx() (depending on the version?) */
-#if !defined(ChangeDisplaySettingsEx)
-LONG WINAPI ChangeDisplaySettingsExA(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID);
-LONG WINAPI ChangeDisplaySettingsExW(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID);
-# ifdef UNICODE
-# define ChangeDisplaySettingsEx ChangeDisplaySettingsExW
-# else
-# define ChangeDisplaySettingsEx ChangeDisplaySettingsExA
-# endif
-#endif
-
-
-/* Structure Definitions */
-
-typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
-struct tagSFG_PlatformDisplay
-{
- HINSTANCE Instance; /* The application's instance */
- DEVMODE DisplayMode; /* Desktop's display settings */
- char *DisplayName; /* Display name for multi display support*/
-};
-
-/*
- * Make "freeglut" window handle and context types so that we don't need so
- * much conditionally-compiled code later in the library.
- */
-typedef HWND SFG_WindowHandleType;
-typedef HGLRC SFG_WindowContextType;
-typedef struct tagSFG_PlatformContext SFG_PlatformContext;
-struct tagSFG_PlatformContext
-{
- HDC Device; /* The window's device context */
-};
-
-
-/* Window's state description. This structure should be kept portable. */
-typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
-struct tagSFG_PlatformWindowState
-{
- RECT OldRect; /* window rect - stored before the window is made fullscreen */
- DWORD OldStyle; /* window style - stored before the window is made fullscreen */
-};
-
-
-
-/* Joystick-Specific Definitions */
-#if !defined(_WIN32_WCE)
-# define _JS_MAX_AXES 8
-typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
-struct tagSFG_PlatformJoystick
-{
- JOYCAPS jsCaps;
- JOYINFOEX js;
- UINT js_id;
-};
-#endif
-
-
-/* Menu font and color definitions */
-#define FREEGLUT_MENU_FONT GLUT_BITMAP_8_BY_13
-
-#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
-#define FREEGLUT_MENU_PEN_BACK_COLORS {0.85f, 0.85f, 0.85f, 1.0f}
-#define FREEGLUT_MENU_PEN_HFORE_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
-#define FREEGLUT_MENU_PEN_HBACK_COLORS {0.15f, 0.15f, 0.45f, 1.0f}
-
-
-/* Function to be called on exit */
-extern void (__cdecl *__glutExitFunc)( int return_value );
-
-
-#endif /* FREEGLUT_INTERNAL_MSWIN_H */
+++ /dev/null
-/*
- * freeglut_joystick_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sat Jan 28, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-#if !defined(_WIN32_WCE)
-# include <windows.h>
-# include <mmsystem.h>
-# include <regstr.h>
-
-
-
-
-void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
-{
- MMRESULT status;
-
- status = joyGetPosEx( joy->pJoystick.js_id, &joy->pJoystick.js );
-
- if ( status != JOYERR_NOERROR )
- {
- joy->error = GL_TRUE;
- return;
- }
-
- if ( buttons )
- *buttons = joy->pJoystick.js.dwButtons;
-
- if ( axes )
- {
- /*
- * WARNING - Fall through case clauses!!
- */
- switch ( joy->num_axes )
- {
- case 8:
- /* Generate two POV axes from the POV hat angle.
- * Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in
- * hundredths of a degree, or 0xFFFF when idle.
- */
- if ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) == 0xFFFF )
- {
- axes [ 6 ] = 0.0;
- axes [ 7 ] = 0.0;
- }
- else
- {
- /* This is the contentious bit: how to convert angle to X/Y.
- * wk: I know of no define for PI that we could use here:
- * SG_PI would pull in sg, M_PI is undefined for MSVC
- * But the accuracy of the value of PI is very unimportant at
- * this point.
- */
- float s = (float) sin ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) );
- float c = (float) cos ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) );
-
- /* Convert to coordinates on a square so that North-East
- * is (1,1) not (.7,.7), etc.
- * s and c cannot both be zero so we won't divide by zero.
- */
- if ( fabs ( s ) < fabs ( c ) )
- {
- axes [ 6 ] = ( c < 0.0 ) ? -s/c : s/c ;
- axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f;
- }
- else
- {
- axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f;
- axes [ 7 ] = ( s < 0.0 ) ? -c/s : c/s ;
- }
- }
-
- case 6: axes[5] = (float) joy->pJoystick.js.dwVpos;
- case 5: axes[4] = (float) joy->pJoystick.js.dwUpos;
- case 4: axes[3] = (float) joy->pJoystick.js.dwRpos;
- case 3: axes[2] = (float) joy->pJoystick.js.dwZpos;
- case 2: axes[1] = (float) joy->pJoystick.js.dwYpos;
- case 1: axes[0] = (float) joy->pJoystick.js.dwXpos;
- }
- }
-}
-
-
-
-/* Inspired by
- http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp
- */
-# if FREEGLUT_LIB_PRAGMAS
-# pragma comment (lib, "advapi32.lib")
-# endif
-
-static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz )
-{
- char buffer [ 256 ];
-
- char OEMKey [ 256 ];
-
- HKEY hKey;
- DWORD dwcb;
- LONG lr;
-
- if ( joy->error )
- return 0;
-
- /* Open .. MediaResources\CurrentJoystickSettings */
- _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s",
- REGSTR_PATH_JOYCONFIG, joy->pJoystick.jsCaps.szRegKey,
- REGSTR_KEY_JOYCURR );
-
- lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
-
- if ( lr != ERROR_SUCCESS ) return 0;
-
- /* Get OEM Key name */
- dwcb = sizeof(OEMKey);
-
- /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */
- _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->pJoystick.js_id + 1, REGSTR_VAL_JOYOEMNAME );
-
- lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);
- RegCloseKey ( hKey );
-
- if ( lr != ERROR_SUCCESS ) return 0;
-
- /* Open OEM Key from ...MediaProperties */
- _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );
-
- lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );
-
- if ( lr != ERROR_SUCCESS ) return 0;
-
- /* Get OEM Name */
- dwcb = buf_sz;
-
- lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf,
- &dwcb );
- RegCloseKey ( hKey );
-
- if ( lr != ERROR_SUCCESS ) return 0;
-
- return 1;
-}
-
-
-void fgPlatformJoystickOpen( SFG_Joystick* joy )
-{
- int i = 0;
-
- joy->pJoystick.js.dwFlags = JOY_RETURNALL;
- joy->pJoystick.js.dwSize = sizeof( joy->pJoystick.js );
-
- memset( &joy->pJoystick.jsCaps, 0, sizeof( joy->pJoystick.jsCaps ) );
-
- joy->error =
- ( joyGetDevCaps( joy->pJoystick.js_id, &joy->pJoystick.jsCaps, sizeof( joy->pJoystick.jsCaps ) ) !=
- JOYERR_NOERROR );
-
- if( joy->pJoystick.jsCaps.wNumAxes == 0 )
- {
- joy->num_axes = 0;
- joy->error = GL_TRUE;
- }
- else
- {
- /* Device name from jsCaps is often "Microsoft PC-joystick driver",
- * at least for USB. Try to get the real name from the registry.
- */
- if ( ! fghJoystickGetOEMProductName( joy, joy->name,
- sizeof( joy->name ) ) )
- {
- fgWarning( "JS: Failed to read joystick name from registry" );
- strncpy( joy->name, joy->pJoystick.jsCaps.szPname, sizeof( joy->name ) );
- }
-
- /* Windows joystick drivers may provide any combination of
- * X,Y,Z,R,U,V,POV - not necessarily the first n of these.
- */
- if( joy->pJoystick.jsCaps.wCaps & JOYCAPS_HASPOV )
- {
- joy->num_axes = _JS_MAX_AXES;
- joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0; /* POV Y */
- joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0; /* POV X */
- }
- else
- joy->num_axes = 6;
-
- joy->min[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmin;
- joy->max[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmax;
- joy->min[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmin;
- joy->max[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmax;
- joy->min[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmin;
- joy->max[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmax;
- joy->min[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmin;
- joy->max[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmax;
- joy->min[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmin;
- joy->max[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmax;
- joy->min[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmin;
- joy->max[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmax;
- }
-
- /* Guess all the rest judging on the axes extremals */
- for( i = 0; i < joy->num_axes; i++ )
- {
- joy->center [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f;
- joy->dead_band[ i ] = 0.0f;
- joy->saturate [ i ] = 1.0f;
- }
-}
-
-
-
-void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )
-{
- switch( ident )
- {
- case 0:
- fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID1;
- fgJoystick[ ident ]->error = GL_FALSE;
- break;
- case 1:
- fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID2;
- fgJoystick[ ident ]->error = GL_FALSE;
- break;
- default:
- fgJoystick[ ident ]->num_axes = 0;
- fgJoystick[ ident ]->error = GL_TRUE;
- return;
- }
-}
-
-
-
-void fgPlatformJoystickClose ( int ident )
-{
- /* Do nothing special */
-}
-#endif
-
+++ /dev/null
-/*
- * freeglut_main_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sat Jan 21, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-extern void fghRedrawWindow ( SFG_Window *window );
-
-extern void fgNewWGLCreateContext( SFG_Window* window );
-extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
- unsigned char layer_type );
-
-#ifdef WM_TOUCH
-typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
-typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT);
-static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF;
-static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF;
-#endif
-
-#ifdef _WIN32_WCE
-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 /* _WIN32_WCE */
-
-/*
- * Helper functions for getting client area from the window rect
- * and the window rect from the client area given the style of the window
- * (or a valid window pointer from which the style can be queried).
- */
-extern void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
-extern RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside );
-
-
-void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
-{
- RECT windowRect;
-
- /*
- * For windowed mode, get the current position of the
- * window and resize taking the size of the frame
- * decorations into account.
- */
-
- /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
- GetWindowRect( window->Window.Handle, &windowRect );
-
- /* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */
- windowRect.right = windowRect.left+width;
- windowRect.bottom = windowRect.top+height;
-
- if (window->Parent == NULL)
- /* get the window rect from this to feed to SetWindowPos, correct for window decorations */
- fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE);
- else
- {
- /* correct rect for position client area of parent window
- * (SetWindowPos input for child windows is in coordinates
- * relative to the parent's client area).
- * Child windows don't have decoration, so no need to correct
- * for them.
- */
- RECT parentRect;
- parentRect = fghGetClientArea( window->Parent, FALSE );
- windowRect.left -= parentRect.left;
- windowRect.right -= parentRect.left;
- windowRect.top -= parentRect.top;
- windowRect.bottom -= parentRect.top;
- }
-
- /* Do the actual resizing */
- SetWindowPos( window->Window.Handle,
- HWND_TOP,
- windowRect.left, windowRect.top,
- windowRect.right - windowRect.left,
- windowRect.bottom- windowRect.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
- SWP_NOZORDER
- );
-}
-
-
-void fgPlatformDisplayWindow ( SFG_Window *window )
-{
- RedrawWindow(
- window->Window.Handle, NULL, NULL,
- RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
- );
-}
-
-
-fg_time_t fgPlatformSystemTime ( void )
-{
-#if defined(_WIN32_WCE)
- return GetTickCount();
-#else
- /* TODO: do this with QueryPerformanceCounter as timeGetTime has
- * insufficient resolution (only about 5 ms on system under low load).
- * See:
- * http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629(v=vs.85).aspx
- * Or maybe QueryPerformanceCounter is not a good idea either, see
- * http://old.nabble.com/Re%3A-glutTimerFunc-does-not-detect-if-system-time-moved-backward-p33479674.html
- * for some other ideas (at bottom)...
- */
- return timeGetTime();
-#endif
-}
-
-
-void fgPlatformSleepForEvents( fg_time_t msec )
-{
- MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLINPUT );
-}
-
-
-void fgPlatformProcessSingleEvent ( void )
-{
- MSG stMsg;
-
- FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
-
- while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
- {
- if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
- {
- if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
- {
- fgDeinitialize( );
- exit( 0 );
- }
- else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
- fgState.ExecState = GLUT_EXEC_STATE_STOP;
-
- return;
- }
-
- TranslateMessage( &stMsg );
- DispatchMessage( &stMsg );
- }
-}
-
-
-
-void fgPlatformMainLoopPreliminaryWork ( void )
-{
- SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
-
- /*
- * Processing before the main loop: If there is a window which is open and
- * which has a visibility callback, call it. I know this is an ugly hack,
- * but I'm not sure what else to do about it. Ideally we should leave
- * something uninitialized in the create window code and initialize it in
- * the main loop, and have that initialization create a "WM_ACTIVATE"
- * message. Then we would put the visibility callback code in the
- * "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
- */
- while( window )
- {
- if ( FETCH_WCB( *window, Visibility ) )
- {
- SFG_Window *current_window = fgStructure.CurrentWindow ;
-
- INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
- fgSetWindow( current_window );
- }
-
- window = (SFG_Window *)window->Node.Next ;
- }
-}
-
-
-/*
- * Determine a GLUT modifer mask based on MS-WINDOWS system info.
- */
-static int fgPlatformGetModifiers (void)
-{
- return
- ( ( ( GetKeyState( VK_LSHIFT ) < 0 ) ||
- ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
- ( ( ( GetKeyState( VK_LCONTROL ) < 0 ) ||
- ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
- ( ( ( GetKeyState( VK_LMENU ) < 0 ) ||
- ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
-}
-
-/*
- * The window procedure for handling Win32 events
- */
-LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam )
-{
- static unsigned char lControl = 0, rControl = 0, lShift = 0,
- rShift = 0, lAlt = 0, rAlt = 0;
-
- SFG_Window* window;
- PAINTSTRUCT ps;
- LRESULT lRet = 1;
-
- FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
-
- window = fgWindowByHandle( hWnd );
-
- if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
-
- /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
- uMsg, wParam, lParam ); */
-
- if ( window )
- {
- /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
- if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) )
- {
- INVOKE_WCB ( *window, Special,
- ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
- );
-
- lControl = 1;
- }
-
- if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) )
- {
- INVOKE_WCB ( *window, Special,
- ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
- );
-
- rControl = 1;
- }
-
- if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) )
- {
- INVOKE_WCB ( *window, Special,
- ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
- );
-
- lShift = 1;
- }
-
- if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) )
- {
- INVOKE_WCB ( *window, Special,
- ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
- );
-
- rShift = 1;
- }
-
- if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) )
- {
- INVOKE_WCB ( *window, Special,
- ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
- );
-
- lAlt = 1;
- }
-
- if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) )
- {
- INVOKE_WCB ( *window, Special,
- ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
- );
-
- rAlt = 1;
- }
-
- /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */
- if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) )
- {
- INVOKE_WCB ( *window, SpecialUp,
- ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
- );
-
- lControl = 0;
- }
-
- if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) )
- {
- INVOKE_WCB ( *window, SpecialUp,
- ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
- );
-
- rControl = 0;
- }
-
- if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) )
- {
- INVOKE_WCB ( *window, SpecialUp,
- ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
- );
-
- lShift = 0;
- }
-
- if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) )
- {
- INVOKE_WCB ( *window, SpecialUp,
- ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
- );
-
- rShift = 0;
- }
-
- if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) )
- {
- INVOKE_WCB ( *window, SpecialUp,
- ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
- );
-
- lAlt = 0;
- }
-
- if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) )
- {
- INVOKE_WCB ( *window, SpecialUp,
- ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
- );
-
- rAlt = 0;
- }
- }
-
- switch( uMsg )
- {
- case WM_CREATE:
- /* The window structure is passed as the creation structure parameter... */
- window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
- FREEGLUT_INTERNAL_ERROR_EXIT ( ( window != NULL ), "Cannot create window",
- "fgPlatformWindowProc" );
-
- window->Window.Handle = hWnd;
- window->Window.pContext.Device = GetDC( hWnd );
- if( window->IsMenu )
- {
- unsigned int current_DisplayMode = fgState.DisplayMode;
- fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
-#if !defined(_WIN32_WCE)
- fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
-#endif
- fgState.DisplayMode = current_DisplayMode;
-
- if( fgStructure.MenuContext )
- wglMakeCurrent( window->Window.pContext.Device,
- fgStructure.MenuContext->MContext
- );
- else
- {
- fgStructure.MenuContext =
- (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
- fgStructure.MenuContext->MContext =
- wglCreateContext( window->Window.pContext.Device );
- }
-
- /* window->Window.Context = wglGetCurrentContext (); */
- window->Window.Context = wglCreateContext( window->Window.pContext.Device );
- }
- else
- {
-#if !defined(_WIN32_WCE)
- fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
-#endif
-
- if( ! fgState.UseCurrentContext )
- window->Window.Context =
- wglCreateContext( window->Window.pContext.Device );
- else
- {
- window->Window.Context = wglGetCurrentContext( );
- if( ! window->Window.Context )
- window->Window.Context =
- wglCreateContext( window->Window.pContext.Device );
- }
-
-#if !defined(_WIN32_WCE)
- fgNewWGLCreateContext( window );
-#endif
- }
-
- window->State.NeedToResize = GL_TRUE;
- /* if we used CW_USEDEFAULT (thats a negative value) for the size
- * of the window, query the window now for the size at which it
- * was created.
- */
- if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) )
- {
- SFG_Window *current_window = fgStructure.CurrentWindow;
-
- fgSetWindow( window );
- window->State.Width = glutGet( GLUT_WINDOW_WIDTH );
- window->State.Height = glutGet( GLUT_WINDOW_HEIGHT );
- fgSetWindow( current_window );
- }
-
- ReleaseDC( window->Window.Handle, window->Window.pContext.Device );
-
-#if defined(_WIN32_WCE)
- /* 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 /* defined(_WIN32_WCE) */
- break;
-
- case WM_SIZE:
- /*
- * If the window is visible, then it is the user manually resizing it.
- * If it is not, then it is the system sending us a dummy resize with
- * zero dimensions on a "glutIconifyWindow" call.
- */
- if( window->State.Visible )
- {
- window->State.NeedToResize = GL_TRUE;
-#if defined(_WIN32_WCE)
- window->State.Width = HIWORD(lParam);
- window->State.Height = LOWORD(lParam);
-#else
- window->State.Width = LOWORD(lParam);
- window->State.Height = HIWORD(lParam);
-#endif /* defined(_WIN32_WCE) */
- }
-
- break;
-
- case WM_SETFOCUS:
-/* printf("WM_SETFOCUS: %p\n", window ); */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
-
- UpdateWindow ( hWnd );
- break;
-
- case WM_KILLFOCUS:
-/* printf("WM_KILLFOCUS: %p\n", window ); */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
-
- if( window->IsMenu &&
- window->ActiveMenu && window->ActiveMenu->IsActive )
- fgUpdateMenuHighlight( window->ActiveMenu );
-
- break;
-
-#if 0
- case WM_ACTIVATE:
- if (LOWORD(wParam) != WA_INACTIVE)
- {
-/* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
- window->State.Cursor ); */
- fgSetCursor( window, window->State.Cursor );
- }
-
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-#endif
-
- case WM_SETCURSOR:
-/* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */
- if( LOWORD( lParam ) == HTCLIENT )
- fgSetCursor ( window, window->State.Cursor ) ;
- else
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-
- case WM_SHOWWINDOW:
- window->State.Visible = GL_TRUE;
- window->State.Redisplay = GL_TRUE;
- break;
-
- case WM_PAINT:
- /* Turn on the visibility in case it was turned off somehow */
- window->State.Visible = GL_TRUE;
- BeginPaint( hWnd, &ps );
- fghRedrawWindow( window );
- EndPaint( hWnd, &ps );
- break;
-
- case WM_CLOSE:
- fgDestroyWindow ( window );
- if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
- PostQuitMessage(0);
- break;
-
- case WM_DESTROY:
- /*
- * The window already got destroyed, so don't bother with it.
- */
- return 0;
-
- case WM_MOUSEMOVE:
- {
-#if defined(_WIN32_WCE)
- window->State.MouseX = 320-HIWORD( lParam );
- window->State.MouseY = LOWORD( lParam );
-#else
- window->State.MouseX = LOWORD( lParam );
- window->State.MouseY = HIWORD( lParam );
-#endif /* defined(_WIN32_WCE) */
- /* 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 )
- {
- fgUpdateMenuHighlight( window->ActiveMenu );
- break;
- }
- SetFocus(window->Window.Handle);
-
- fgState.Modifiers = fgPlatformGetModifiers( );
-
- if( ( wParam & MK_LBUTTON ) ||
- ( wParam & MK_MBUTTON ) ||
- ( wParam & MK_RBUTTON ) )
- INVOKE_WCB( *window, Motion, ( window->State.MouseX,
- window->State.MouseY ) );
- else
- INVOKE_WCB( *window, Passive, ( window->State.MouseX,
- window->State.MouseY ) );
-
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- {
- GLboolean pressed = GL_TRUE;
- int button;
-
-#if defined(_WIN32_WCE)
- window->State.MouseX = 320-HIWORD( lParam );
- window->State.MouseY = LOWORD( lParam );
-#else
- window->State.MouseX = LOWORD( lParam );
- window->State.MouseY = HIWORD( lParam );
-#endif /* defined(_WIN32_WCE) */
-
- /* 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:
- pressed = GL_TRUE;
- button = GLUT_LEFT_BUTTON;
- break;
- case WM_MBUTTONDOWN:
- pressed = GL_TRUE;
- button = GLUT_MIDDLE_BUTTON;
- break;
- case WM_RBUTTONDOWN:
- pressed = GL_TRUE;
- button = GLUT_RIGHT_BUTTON;
- break;
- case WM_LBUTTONUP:
- pressed = GL_FALSE;
- button = GLUT_LEFT_BUTTON;
- break;
- case WM_MBUTTONUP:
- pressed = GL_FALSE;
- button = GLUT_MIDDLE_BUTTON;
- break;
- case WM_RBUTTONUP:
- pressed = GL_FALSE;
- button = GLUT_RIGHT_BUTTON;
- break;
- default:
- pressed = GL_FALSE;
- button = -1;
- break;
- }
-
-#if !defined(_WIN32_WCE)
- if( GetSystemMetrics( SM_SWAPBUTTON ) )
- {
- if( button == GLUT_LEFT_BUTTON )
- button = GLUT_RIGHT_BUTTON;
- else
- if( button == GLUT_RIGHT_BUTTON )
- button = GLUT_LEFT_BUTTON;
- }
-#endif /* !defined(_WIN32_WCE) */
-
- if( button == -1 )
- return DefWindowProc( hWnd, uMsg, lParam, wParam );
-
- /*
- * Do not execute the application's mouse callback if a menu
- * is hooked to this button. In that case an appropriate
- * private call should be generated.
- */
- if( fgCheckActiveMenu( window, button, pressed,
- window->State.MouseX, window->State.MouseY ) )
- 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 = fgPlatformGetModifiers( );
-
- INVOKE_WCB(
- *window, Mouse,
- ( button,
- pressed ? GLUT_DOWN : GLUT_UP,
- window->State.MouseX,
- window->State.MouseY
- )
- );
-
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case 0x020a:
- /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */
- {
- int wheel_number = LOWORD( wParam );
- short ticks = ( short )HIWORD( wParam );
- fgState.MouseWheelTicks += ticks;
-
- /*
- * XXX Should use WHEEL_DELTA instead of 120
- */
- if ( abs ( fgState.MouseWheelTicks ) > 120 )
- {
- int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
-
- if( ! FETCH_WCB( *window, MouseWheel ) &&
- ! FETCH_WCB( *window, Mouse ) )
- break;
-
- fgSetWindow( window );
- fgState.Modifiers = fgPlatformGetModifiers( );
-
- /*
- * XXX Should use WHEEL_DELTA instead of 120
- */
- while( abs ( fgState.MouseWheelTicks ) > 120 )
- {
- if( FETCH_WCB( *window, MouseWheel ) )
- INVOKE_WCB( *window, MouseWheel,
- ( wheel_number,
- direction,
- window->State.MouseX,
- window->State.MouseY
- )
- );
- else /* No mouse wheel, call the mouse button callback twice */
- {
- /*
- * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
- * " " one +1 to 5, -1 to 6, ...
- *
- * XXX The below assumes that you have no more than 3 mouse
- * XXX buttons. Sorry.
- */
- int button = wheel_number * 2 + 3;
- if( direction < 0 )
- ++button;
- INVOKE_WCB( *window, Mouse,
- ( button, GLUT_DOWN,
- window->State.MouseX, window->State.MouseY )
- );
- INVOKE_WCB( *window, Mouse,
- ( button, GLUT_UP,
- window->State.MouseX, window->State.MouseY )
- );
- }
-
- /*
- * XXX Should use WHEEL_DELTA instead of 120
- */
- fgState.MouseWheelTicks -= 120 * direction;
- }
-
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- }
- break ;
-
- case WM_SYSKEYDOWN:
- case WM_KEYDOWN:
- {
- int keypress = -1;
- POINT mouse_pos ;
-
- if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
- break;
-
- /*
- * Remember the current modifiers state. This is done here in order
- * to make sure the VK_DELETE keyboard callback is executed properly.
- */
- fgState.Modifiers = fgPlatformGetModifiers( );
-
- GetCursorPos( &mouse_pos );
- ScreenToClient( window->Window.Handle, &mouse_pos );
-
- window->State.MouseX = mouse_pos.x;
- window->State.MouseY = mouse_pos.y;
-
- /* Convert the Win32 keystroke codes to GLUTtish way */
-# define KEY(a,b) case a: keypress = b; break;
-
- switch( wParam )
- {
- KEY( VK_F1, GLUT_KEY_F1 );
- KEY( VK_F2, GLUT_KEY_F2 );
- KEY( VK_F3, GLUT_KEY_F3 );
- KEY( VK_F4, GLUT_KEY_F4 );
- KEY( VK_F5, GLUT_KEY_F5 );
- KEY( VK_F6, GLUT_KEY_F6 );
- KEY( VK_F7, GLUT_KEY_F7 );
- KEY( VK_F8, GLUT_KEY_F8 );
- KEY( VK_F9, GLUT_KEY_F9 );
- KEY( VK_F10, GLUT_KEY_F10 );
- KEY( VK_F11, GLUT_KEY_F11 );
- KEY( VK_F12, GLUT_KEY_F12 );
- KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
- KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
- KEY( VK_HOME, GLUT_KEY_HOME );
- KEY( VK_END, GLUT_KEY_END );
- KEY( VK_LEFT, GLUT_KEY_LEFT );
- KEY( VK_UP, GLUT_KEY_UP );
- KEY( VK_RIGHT, GLUT_KEY_RIGHT );
- KEY( VK_DOWN, GLUT_KEY_DOWN );
- KEY( VK_INSERT, GLUT_KEY_INSERT );
- KEY( VK_LCONTROL, GLUT_KEY_CTRL_L );
- KEY( VK_RCONTROL, GLUT_KEY_CTRL_R );
- KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L );
- KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R );
- KEY( VK_LMENU, GLUT_KEY_ALT_L );
- KEY( VK_RMENU, GLUT_KEY_ALT_R );
-
- case VK_DELETE:
- /* The delete key should be treated as an ASCII keypress: */
- INVOKE_WCB( *window, Keyboard,
- ( 127, window->State.MouseX, window->State.MouseY )
- );
- }
-
-#if defined(_WIN32_WCE)
- if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
- {
- if(wParam==(unsigned)gxKeyList.vkRight)
- keypress = GLUT_KEY_RIGHT;
- else if(wParam==(unsigned)gxKeyList.vkLeft)
- keypress = GLUT_KEY_LEFT;
- else if(wParam==(unsigned)gxKeyList.vkUp)
- keypress = GLUT_KEY_UP;
- else if(wParam==(unsigned)gxKeyList.vkDown)
- keypress = GLUT_KEY_DOWN;
- else if(wParam==(unsigned)gxKeyList.vkA)
- keypress = GLUT_KEY_F1;
- else if(wParam==(unsigned)gxKeyList.vkB)
- keypress = GLUT_KEY_F2;
- else if(wParam==(unsigned)gxKeyList.vkC)
- keypress = GLUT_KEY_F3;
- else if(wParam==(unsigned)gxKeyList.vkStart)
- keypress = GLUT_KEY_F4;
- }
-#endif
-
- if( keypress != -1 )
- INVOKE_WCB( *window, Special,
- ( keypress,
- window->State.MouseX, window->State.MouseY )
- );
-
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case WM_SYSKEYUP:
- case WM_KEYUP:
- {
- 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 = fgPlatformGetModifiers( );
-
- GetCursorPos( &mouse_pos );
- ScreenToClient( window->Window.Handle, &mouse_pos );
-
- window->State.MouseX = mouse_pos.x;
- window->State.MouseY = mouse_pos.y;
-
- /*
- * Convert the Win32 keystroke codes to GLUTtish way.
- * "KEY(a,b)" was defined under "WM_KEYDOWN"
- */
-
- switch( wParam )
- {
- KEY( VK_F1, GLUT_KEY_F1 );
- KEY( VK_F2, GLUT_KEY_F2 );
- KEY( VK_F3, GLUT_KEY_F3 );
- KEY( VK_F4, GLUT_KEY_F4 );
- KEY( VK_F5, GLUT_KEY_F5 );
- KEY( VK_F6, GLUT_KEY_F6 );
- KEY( VK_F7, GLUT_KEY_F7 );
- KEY( VK_F8, GLUT_KEY_F8 );
- KEY( VK_F9, GLUT_KEY_F9 );
- KEY( VK_F10, GLUT_KEY_F10 );
- KEY( VK_F11, GLUT_KEY_F11 );
- KEY( VK_F12, GLUT_KEY_F12 );
- KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
- KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
- KEY( VK_HOME, GLUT_KEY_HOME );
- KEY( VK_END, GLUT_KEY_END );
- KEY( VK_LEFT, GLUT_KEY_LEFT );
- KEY( VK_UP, GLUT_KEY_UP );
- KEY( VK_RIGHT, GLUT_KEY_RIGHT );
- KEY( VK_DOWN, GLUT_KEY_DOWN );
- KEY( VK_INSERT, GLUT_KEY_INSERT );
- KEY( VK_LCONTROL, GLUT_KEY_CTRL_L );
- KEY( VK_RCONTROL, GLUT_KEY_CTRL_R );
- KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L );
- KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R );
- KEY( VK_LMENU, GLUT_KEY_ALT_L );
- KEY( VK_RMENU, GLUT_KEY_ALT_R );
-
- case VK_DELETE:
- /* The delete key should be treated as an ASCII keypress: */
- INVOKE_WCB( *window, KeyboardUp,
- ( 127, window->State.MouseX, window->State.MouseY )
- );
- break;
-
- default:
- {
-#if !defined(_WIN32_WCE)
- BYTE state[ 256 ];
- WORD code[ 2 ];
-
- GetKeyboardState( state );
-
- if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
- wParam=code[ 0 ];
-
- INVOKE_WCB( *window, KeyboardUp,
- ( (char)wParam,
- window->State.MouseX, window->State.MouseY )
- );
-#endif /* !defined(_WIN32_WCE) */
- }
- }
-
- if( keypress != -1 )
- INVOKE_WCB( *window, SpecialUp,
- ( keypress,
- window->State.MouseX, window->State.MouseY )
- );
-
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case WM_SYSCHAR:
- case WM_CHAR:
- {
- if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
- break;
-
- fgState.Modifiers = fgPlatformGetModifiers( );
- INVOKE_WCB( *window, Keyboard,
- ( (char)wParam,
- window->State.MouseX, window->State.MouseY )
- );
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case WM_CAPTURECHANGED:
- /* User has finished resizing the window, force a redraw */
- INVOKE_WCB( *window, Display, ( ) );
-
- /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
- break;
-
- /* Other messages that I have seen and which are not handled already */
- case WM_SETTEXT: /* 0x000c */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- /* Pass it on to "DefWindowProc" to set the window text */
- break;
-
- case WM_GETTEXT: /* 0x000d */
- /* Ideally we would copy the title of the window into "lParam" */
- /* strncpy ( (char *)lParam, "Window Title", wParam );
- lRet = ( wParam > 12 ) ? 12 : wParam; */
- /* the number of characters copied */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-
- case WM_GETTEXTLENGTH: /* 0x000e */
- /* Ideally we would get the length of the title of the window */
- lRet = 12;
- /* the number of characters in "Window Title\0" (see above) */
- break;
-
- case WM_ERASEBKGND: /* 0x0014 */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-
-#if !defined(_WIN32_WCE)
- case WM_SYNCPAINT: /* 0x0088 */
- /* Another window has moved, need to update this one */
- window->State.Redisplay = GL_TRUE;
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- /* Help screen says this message must be passed to "DefWindowProc" */
- break;
-
- case WM_NCPAINT: /* 0x0085 */
- /* Need to update the border of this window */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- /* Pass it on to "DefWindowProc" to repaint a standard border */
- break;
-
- case WM_SYSCOMMAND : /* 0x0112 */
- {
- /*
- * We have received a system command message. Try to act on it.
- * 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 ( wParam & 0xfff0 )
- {
- case SC_SIZE :
- break ;
-
- case SC_MOVE :
- break ;
-
- case SC_MINIMIZE :
- /* User has clicked on the "-" to minimize the window */
- /* Turn off the visibility */
- window->State.Visible = GL_FALSE ;
-
- break ;
-
- case SC_MAXIMIZE :
- break ;
-
- case SC_NEXTWINDOW :
- break ;
-
- case SC_PREVWINDOW :
- break ;
-
- case SC_CLOSE :
- /* Followed very closely by a WM_CLOSE message */
- break ;
-
- case SC_VSCROLL :
- break ;
-
- case SC_HSCROLL :
- break ;
-
- case SC_MOUSEMENU :
- break ;
-
- case SC_KEYMENU :
- break ;
-
- case SC_ARRANGE :
- break ;
-
- case SC_RESTORE :
- break ;
-
- case SC_TASKLIST :
- break ;
-
- case SC_SCREENSAVE :
- break ;
-
- case SC_HOTKEY :
- break ;
-
-#if(WINVER >= 0x0400)
- case SC_DEFAULT :
- break ;
-
- case SC_MONITORPOWER :
- break ;
-
- case SC_CONTEXTHELP :
- break ;
-#endif /* WINVER >= 0x0400 */
-
- default:
-#if _DEBUG
- fgWarning( "Unknown wParam type 0x%x", wParam );
-#endif
- break;
- }
- }
-#endif /* !defined(_WIN32_WCE) */
-
- /* We need to pass the message on to the operating system as well */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
-
-#ifdef WM_TOUCH
- /* handle multi-touch messages */
- case WM_TOUCH:
- {
- unsigned int numInputs = (unsigned int)wParam;
- unsigned int i = 0;
- TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs);
-
- if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) {
- fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo");
- fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle");
- }
-
- if (!fghGetTouchInputInfo) {
- free( (void*)ti );
- break;
- }
-
- if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) {
- /* Handle each contact point */
- for (i = 0; i < numInputs; ++i ) {
-
- POINT tp;
- tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
- tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
- ScreenToClient( hWnd, &tp );
-
- ti[i].dwID = ti[i].dwID * 2;
-
- if (ti[i].dwFlags & TOUCHEVENTF_DOWN) {
- INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) );
- INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) );
- } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
- INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) );
- } else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
- INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) );
- INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) );
- }
- }
- }
- fghCloseTouchInputHandle((HTOUCHINPUT)lParam);
- free( (void*)ti );
- lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/
- break;
- }
-#endif
- default:
- /* Handle unhandled messages */
- lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- break;
- }
-
- return lRet;
-}
+++ /dev/null
-/*
- * freeglut_menu_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sun Jan 22, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define FREEGLUT_BUILDING_LIB
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y )
-{
- *x = glutGet ( GLUT_SCREEN_WIDTH );
- *y = glutGet ( GLUT_SCREEN_HEIGHT );
-}
-
-
-
-/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */
-
-int FGAPIENTRY __glutCreateMenuWithExit( void(* callback)( int ), void (__cdecl *exit_function)(int) )
-{
- __glutExitFunc = exit_function;
- return glutCreateMenu( callback );
-}
-
+++ /dev/null
-/*
- * freeglut_spaceball_mswin.c
- *
- * Spaceball support for Windows
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by Evan Felix <karcaw at gmail.com>
- * Creation date: Sat Feb 4, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-/*
- * This code is a very complicated way of doing nothing.
- * But is needed for mswindows platform builds.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-void fgPlatformInitializeSpaceball(void)
-{
- return;
-}
-
-void fgPlatformSpaceballClose(void)
-{
- return;
-}
-
-int fgPlatformHasSpaceball(void)
-{
- return 0;
-}
-
-int fgPlatformSpaceballNumButtons(void)
-{
- return 0;
-}
-
-void fgPlatformSpaceballSetWindow(SFG_Window *window)
-{
- return;
-}
+++ /dev/null
-/*
- * freeglut_state_mswin.c
- *
- * The Windows-specific state query methods.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sun Jan 22, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
- unsigned char layer_type );
-
-/*
- * Helper functions for getting client area from the window rect
- * and the window rect from the client area given the style of the window
- * (or a valid window pointer from which the style can be queried).
- */
-extern RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside );
-extern void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
-
-
-/* The following include file is available from SGI but is not standard:
- * #include <GL/wglext.h>
- * So we copy the necessary parts out of it to support the multisampling query
- */
-#define WGL_SAMPLES_ARB 0x2042
-
-#if defined(_WIN32_WCE)
-# include <Aygshell.h>
-# ifdef FREEGLUT_LIB_PRAGMAS
-# pragma comment( lib, "Aygshell.lib" )
-# endif
-#endif /* defined(_WIN32_WCE) */
-
-
-
-int fgPlatformGlutGet ( GLenum eWhat )
-{
- int returnValue ;
- GLboolean boolValue ;
-
- int nsamples = 0;
-
- switch( eWhat )
- {
- case GLUT_WINDOW_NUM_SAMPLES:
- glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
- return nsamples;
-
- /* Handle the OpenGL inquiries */
- case GLUT_WINDOW_RGBA:
-#if defined(_WIN32_WCE)
- boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
-#else
- glGetBooleanv ( GL_RGBA_MODE, &boolValue );
- returnValue = boolValue ? 1 : 0;
-#endif
- return returnValue;
- case GLUT_WINDOW_DOUBLEBUFFER:
-#if defined(_WIN32_WCE)
- boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
-#else
- glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
- returnValue = boolValue ? 1 : 0;
-#endif
- return returnValue;
- case GLUT_WINDOW_STEREO:
-#if defined(_WIN32_WCE)
- boolValue = (GLboolean)0; /* WinCE doesn't support this feature */
-#else
- glGetBooleanv ( GL_STEREO, &boolValue );
- returnValue = boolValue ? 1 : 0;
-#endif
- return returnValue;
-
- case GLUT_WINDOW_RED_SIZE:
- glGetIntegerv ( GL_RED_BITS, &returnValue );
- return returnValue;
- case GLUT_WINDOW_GREEN_SIZE:
- glGetIntegerv ( GL_GREEN_BITS, &returnValue );
- return returnValue;
- case GLUT_WINDOW_BLUE_SIZE:
- glGetIntegerv ( GL_BLUE_BITS, &returnValue );
- return returnValue;
- case GLUT_WINDOW_ALPHA_SIZE:
- glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
- return returnValue;
- case GLUT_WINDOW_ACCUM_RED_SIZE:
-#if defined(_WIN32_WCE)
- returnValue = 0; /* WinCE doesn't support this feature */
-#else
- glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
-#endif
- return returnValue;
- case GLUT_WINDOW_ACCUM_GREEN_SIZE:
-#if defined(_WIN32_WCE)
- returnValue = 0; /* WinCE doesn't support this feature */
-#else
- glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
-#endif
- return returnValue;
- case GLUT_WINDOW_ACCUM_BLUE_SIZE:
-#if defined(_WIN32_WCE)
- returnValue = 0; /* WinCE doesn't support this feature */
-#else
- glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
-#endif
- return returnValue;
- case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
-#if defined(_WIN32_WCE)
- returnValue = 0; /* WinCE doesn't support this feature */
-#else
- glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
-#endif
- return returnValue;
- case GLUT_WINDOW_DEPTH_SIZE:
- glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
- return returnValue;
-
- case GLUT_WINDOW_BUFFER_SIZE:
- returnValue = 1 ; /* ????? */
- return returnValue;
- case GLUT_WINDOW_STENCIL_SIZE:
- returnValue = 0 ; /* ????? */
- return returnValue;
-
- case GLUT_WINDOW_X:
- case GLUT_WINDOW_Y:
- case GLUT_WINDOW_WIDTH:
- case GLUT_WINDOW_HEIGHT:
- {
- /*
- * There is considerable confusion about the "right thing to
- * do" concerning window size and position. GLUT itself is
- * not consistent between Windows and UNIX/X11; since
- * platform independence is a virtue for "freeglut", we
- * decided to break with GLUT's behaviour.
- *
- * Under UNIX/X11, it is apparently not possible to get the
- * window border sizes in order to subtract them off the
- * window's initial position until some time after the window
- * has been created. Therefore we decided on the following
- * behaviour, both under Windows and under UNIX/X11:
- * - When you create a window with position (x,y) and size
- * (w,h), the upper left hand corner of the outside of the
- * window is at (x,y) and the size of the drawable area is
- * (w,h).
- * - When you query the size and position of the window--as
- * is happening here for Windows--"freeglut" will return
- * the size of the drawable area--the (w,h) that you
- * specified when you created the window--and the coordinates
- * of the upper left hand corner of the drawable
- * area--which is NOT the (x,y) you specified.
- */
-
- RECT winRect;
-
- freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
-
-#if defined(_WIN32_WCE)
- GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
-#else
- winRect = fghGetClientArea(fgStructure.CurrentWindow, FALSE);
-#endif /* defined(_WIN32_WCE) */
-
- switch( eWhat )
- {
- case GLUT_WINDOW_X: return winRect.left ;
- case GLUT_WINDOW_Y: return winRect.top ;
- case GLUT_WINDOW_WIDTH: return winRect.right - winRect.left;
- case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
- }
- }
- break;
-
- case GLUT_WINDOW_BORDER_WIDTH :
- case GLUT_WINDOW_HEADER_HEIGHT :
-#if defined(_WIN32_WCE)
- return 0;
-#else
- {
- DWORD windowStyle;
-
- if (fgStructure.CurrentWindow && fgStructure.CurrentWindow->Window.Handle)
- windowStyle = GetWindowLong(fgStructure.CurrentWindow->Window.Handle, GWL_STYLE);
- else
- /* If no window, return sizes for a default window with title bar and border */
- windowStyle = WS_OVERLAPPEDWINDOW;
-
- switch( eWhat )
- {
- case GLUT_WINDOW_BORDER_WIDTH:
- {
- int xBorderWidth, yBorderWidth;
- fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
- return xBorderWidth;
- }
- case GLUT_WINDOW_HEADER_HEIGHT:
- /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
- return (windowStyle & WS_MAXIMIZEBOX)? GetSystemMetrics( SM_CYCAPTION ) : 0;
- }
- }
-#endif /* defined(_WIN32_WCE) */
-
- case GLUT_DISPLAY_MODE_POSSIBLE:
-#if defined(_WIN32_WCE)
- return 0;
-#else
- return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
- PFD_MAIN_PLANE );
-#endif /* defined(_WIN32_WCE) */
-
-
- case GLUT_WINDOW_FORMAT_ID:
-#if !defined(_WIN32_WCE)
- if( fgStructure.CurrentWindow != NULL )
- return GetPixelFormat( fgStructure.CurrentWindow->Window.pContext.Device );
-#endif /* defined(_WIN32_WCE) */
- return 0;
-
- default:
- fgWarning( "glutGet(): missing enum handle %d", eWhat );
- break;
- }
-
- return -1;
-}
-
-
-int fgPlatformGlutDeviceGet ( GLenum eWhat )
-{
- switch( eWhat )
- {
- case GLUT_HAS_KEYBOARD:
- /*
- * Win32 is assumed a keyboard, and this cannot be queried,
- * except for WindowsCE.
- */
-#if defined(_WIN32_CE)
- return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
-# if FREEGLUT_LIB_PRAGMAS
-# pragma comment (lib,"Kbdui.lib")
-# endif
-
-#else
- return 1;
-#endif
-
- case GLUT_HAS_MOUSE:
- /*
- * MS Windows can be booted without a mouse.
- */
- return GetSystemMetrics( SM_MOUSEPRESENT );
-
- case GLUT_NUM_MOUSE_BUTTONS:
-# if defined(_WIN32_WCE)
- return 1;
-# else
- return GetSystemMetrics( SM_CMOUSEBUTTONS );
-# endif
-
- default:
- fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
- break;
- }
-
- /* And now -- the failure. */
- return -1;
-}
-
-/*
- * This is for querying the number of supported auxiliary or multisample
- * buffers for a (the current?) display mode.
- * see http://old.nabble.com/-GLX--glutGetModeValues-to13514723.html#a13514723
- * Not currently implemented, but we should be able to query the relevant
- * info using
- * http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt
- * (if supported on the executing machine!)
- */
-int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
-{
- *size = 0;
- return NULL;
-}
\ No newline at end of file
+++ /dev/null
-/*
- * freeglut_structure_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sun Jan 22, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-void fgPlatformCreateWindow ( SFG_Window *window )
-{
-}
+++ /dev/null
-/*
- * freeglut_window_mswin.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sun Jan 22, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define FREEGLUT_BUILDING_LIB
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-
-/* The following include file is available from SGI but is not standard:
- * #include <GL/wglext.h>
- * So we copy the necessary parts out of it.
- * XXX: should local definitions for extensions be put in a separate include file?
- */
-typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
-
-typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
-
-#define WGL_DRAW_TO_WINDOW_ARB 0x2001
-#define WGL_ACCELERATION_ARB 0x2003
-#define WGL_SUPPORT_OPENGL_ARB 0x2010
-#define WGL_DOUBLE_BUFFER_ARB 0x2011
-#define WGL_COLOR_BITS_ARB 0x2014
-#define WGL_ALPHA_BITS_ARB 0x201B
-#define WGL_DEPTH_BITS_ARB 0x2022
-#define WGL_STENCIL_BITS_ARB 0x2023
-#define WGL_FULL_ACCELERATION_ARB 0x2027
-
-#define WGL_SAMPLE_BUFFERS_ARB 0x2041
-#define WGL_SAMPLES_ARB 0x2042
-
-#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
-
-#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
-
-#ifndef WGL_ARB_create_context
-#define WGL_ARB_create_context 1
-#ifdef WGL_WGLEXT_PROTOTYPES
-extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *);
-#endif /* WGL_WGLEXT_PROTOTYPES */
-typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
-
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-
-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
-#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
-
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-
-#define ERROR_INVALID_VERSION_ARB 0x2095
-#define ERROR_INVALID_PROFILE_ARB 0x2096
-#endif
-/* End of copying the necessary parts out of it. */
-
-#ifdef WM_TOUCH
-typedef BOOL (WINAPI *pRegisterTouchWindow)(HWND,ULONG);
-static pRegisterTouchWindow fghRegisterTouchWindow = (pRegisterTouchWindow)0xDEADBEEF;
-#endif
-
-/*
- * Helper functions for getting client area from the window rect
- * and the window rect from the client area given the style of the window
- * (or a valid window pointer from which the style can be queried).
- */
-extern void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth);
-
-
-/*
- * Setup the pixel format for a Win32 window
- */
-
-#if defined(_WIN32_WCE)
-static wchar_t* fghWstrFromStr(const char* str)
-{
- int i,len=strlen(str);
- wchar_t* wstr = (wchar_t*)malloc(2*len+2);
- for(i=0; i<len; i++)
- wstr[i] = str[i];
- wstr[len] = 0;
- return wstr;
-}
-#endif /* defined(_WIN32_WCE) */
-
-
-static void fghFillContextAttributes( int *attributes ) {
- int where = 0, contextFlags, contextProfile;
-
- if ( !fghIsLegacyContextVersionRequested() ) {
- ATTRIB_VAL( WGL_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
- ATTRIB_VAL( WGL_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
- }
-
- contextFlags =
- fghMapBit( fgState.ContextFlags, GLUT_DEBUG, WGL_CONTEXT_DEBUG_BIT_ARB ) |
- fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
- if ( contextFlags != 0 ) {
- ATTRIB_VAL( WGL_CONTEXT_FLAGS_ARB, contextFlags );
- }
-
- contextProfile =
- fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, WGL_CONTEXT_CORE_PROFILE_BIT_ARB ) |
- fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
- if ( contextProfile != 0 ) {
- ATTRIB_VAL( WGL_CONTEXT_PROFILE_MASK_ARB, contextProfile );
- }
-
- ATTRIB( 0 );
-}
-
-static int fghIsExtensionSupported( HDC hdc, const char *extension ) {
- const char *pWglExtString;
- PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB =
- (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
- if ( wglGetEntensionsStringARB == NULL )
- {
- return FALSE;
- }
- pWglExtString = wglGetEntensionsStringARB( hdc );
- return ( pWglExtString != NULL ) && ( strstr(pWglExtString, extension) != NULL );
-}
-
-void fgNewWGLCreateContext( SFG_Window* window )
-{
- HGLRC context;
- int attributes[9];
- PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
-
- /* If nothing fancy has been required, leave the context as it is */
- if ( fghIsLegacyContextRequested() )
- {
- return;
- }
-
- wglMakeCurrent( window->Window.pContext.Device, window->Window.Context );
-
- if ( !fghIsExtensionSupported( window->Window.pContext.Device, "WGL_ARB_create_context" ) )
- {
- return;
- }
-
- /* new context creation */
- fghFillContextAttributes( attributes );
-
- wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" );
- if ( wglCreateContextAttribsARB == NULL )
- {
- fgError( "wglCreateContextAttribsARB not found" );
- }
-
- context = wglCreateContextAttribsARB( window->Window.pContext.Device, 0, attributes );
- if ( context == NULL )
- {
- fghContextCreationError();
- }
-
- wglMakeCurrent( NULL, NULL );
- wglDeleteContext( window->Window.Context );
- window->Window.Context = context;
-}
-
-#if !defined(_WIN32_WCE)
-
-static void fghFillPFD( PIXELFORMATDESCRIPTOR *ppfd, HDC hdc, unsigned char layer_type )
-{
- int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
- if ( fgState.DisplayMode & GLUT_DOUBLE ) {
- flags |= PFD_DOUBLEBUFFER;
- }
- if ( fgState.DisplayMode & GLUT_STEREO ) {
- flags |= PFD_STEREO;
- }
-
-#if defined(_MSC_VER)
-#pragma message( "fgSetupPixelFormat(): there is still some work to do here!" )
-#endif
-
- /* Specify which pixel format do we opt for... */
- ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
- ppfd->nVersion = 1;
- ppfd->dwFlags = flags;
-
- if( fgState.DisplayMode & GLUT_INDEX ) {
- ppfd->iPixelType = PFD_TYPE_COLORINDEX;
- ppfd->cRedBits = 0;
- ppfd->cGreenBits = 0;
- ppfd->cBlueBits = 0;
- ppfd->cAlphaBits = 0;
- } else {
- ppfd->iPixelType = PFD_TYPE_RGBA;
- ppfd->cRedBits = 8;
- ppfd->cGreenBits = 8;
- ppfd->cBlueBits = 8;
- ppfd->cAlphaBits = ( fgState.DisplayMode & GLUT_ALPHA ) ? 8 : 0;
- }
-
- ppfd->cColorBits = 24;
- ppfd->cRedShift = 0;
- ppfd->cGreenShift = 0;
- ppfd->cBlueShift = 0;
- ppfd->cAlphaShift = 0;
- ppfd->cAccumBits = ( fgState.DisplayMode & GLUT_ACCUM ) ? 1 : 0;
- ppfd->cAccumRedBits = 0;
- ppfd->cAccumGreenBits = 0;
- ppfd->cAccumBlueBits = 0;
- ppfd->cAccumAlphaBits = 0;
-
- /* Hmmm, or 32/0 instead of 24/8? */
- ppfd->cDepthBits = 24;
- ppfd->cStencilBits = 8;
-
- ppfd->cAuxBuffers = fghNumberOfAuxBuffersRequested();
- ppfd->iLayerType = layer_type;
- ppfd->bReserved = 0;
- ppfd->dwLayerMask = 0;
- ppfd->dwVisibleMask = 0;
- ppfd->dwDamageMask = 0;
-
- ppfd->cColorBits = (BYTE) GetDeviceCaps( hdc, BITSPIXEL );
-}
-
-static void fghFillPixelFormatAttributes( int *attributes, const PIXELFORMATDESCRIPTOR *ppfd )
-{
- int where = 0;
-
- ATTRIB_VAL( WGL_DRAW_TO_WINDOW_ARB, GL_TRUE );
- ATTRIB_VAL( WGL_SUPPORT_OPENGL_ARB, GL_TRUE );
- ATTRIB_VAL( WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB );
-
- ATTRIB_VAL( WGL_COLOR_BITS_ARB, ppfd->cColorBits );
- ATTRIB_VAL( WGL_ALPHA_BITS_ARB, ppfd->cAlphaBits );
- ATTRIB_VAL( WGL_DEPTH_BITS_ARB, ppfd->cDepthBits );
- ATTRIB_VAL( WGL_STENCIL_BITS_ARB, ppfd->cStencilBits );
-
- ATTRIB_VAL( WGL_DOUBLE_BUFFER_ARB, ( fgState.DisplayMode & GLUT_DOUBLE ) != 0 );
-
- if ( fgState.DisplayMode & GLUT_SRGB ) {
- ATTRIB_VAL( WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, TRUE );
- }
-
- ATTRIB_VAL( WGL_SAMPLE_BUFFERS_ARB, GL_TRUE );
- ATTRIB_VAL( WGL_SAMPLES_ARB, fgState.SampleNumber );
- ATTRIB( 0 );
-}
-#endif
-
-GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
- unsigned char layer_type )
-{
-#if defined(_WIN32_WCE)
- return GL_TRUE;
-#else
- PIXELFORMATDESCRIPTOR pfd;
- PIXELFORMATDESCRIPTOR* ppfd = &pfd;
- int pixelformat;
- HDC current_hDC;
- GLboolean success;
-
- if (checkOnly)
- current_hDC = CreateDC(TEXT("DISPLAY"), NULL ,NULL ,NULL);
- else
- current_hDC = window->Window.pContext.Device;
-
- fghFillPFD( ppfd, current_hDC, layer_type );
- pixelformat = ChoosePixelFormat( current_hDC, ppfd );
-
- /* windows hack for multismapling/sRGB */
- if ( ( fgState.DisplayMode & GLUT_MULTISAMPLE ) ||
- ( fgState.DisplayMode & GLUT_SRGB ) )
- {
- HGLRC rc, rc_before=wglGetCurrentContext();
- HWND hWnd;
- HDC hDC, hDC_before=wglGetCurrentDC();
- WNDCLASS wndCls;
-
- /* create a dummy window */
- ZeroMemory(&wndCls, sizeof(wndCls));
- wndCls.lpfnWndProc = DefWindowProc;
- wndCls.hInstance = fgDisplay.pDisplay.Instance;
- wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- wndCls.lpszClassName = _T("FREEGLUT_dummy");
- RegisterClass( &wndCls );
-
- hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.pDisplay.Instance, 0 );
- hDC=GetDC(hWnd);
- SetPixelFormat( hDC, pixelformat, ppfd );
-
- rc = wglCreateContext( hDC );
- wglMakeCurrent(hDC, rc);
-
- if ( fghIsExtensionSupported( hDC, "WGL_ARB_multisample" ) )
- {
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARBProc =
- (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
- if ( wglChoosePixelFormatARBProc )
- {
- int attributes[100];
- int iPixelFormat;
- BOOL bValid;
- float fAttributes[] = { 0, 0 };
- UINT numFormats;
- fghFillPixelFormatAttributes( attributes, ppfd );
- bValid = wglChoosePixelFormatARBProc(hDC, attributes, fAttributes, 1, &iPixelFormat, &numFormats);
-
- if ( bValid && numFormats > 0 )
- {
- pixelformat = iPixelFormat;
- }
- }
- }
-
- wglMakeCurrent( hDC_before, rc_before);
- wglDeleteContext(rc);
- ReleaseDC(hWnd, hDC);
- DestroyWindow(hWnd);
- UnregisterClass(_T("FREEGLUT_dummy"), fgDisplay.pDisplay.Instance);
- }
-
- success = ( pixelformat != 0 ) && ( checkOnly || SetPixelFormat( current_hDC, pixelformat, ppfd ) );
-
- if (checkOnly)
- DeleteDC(current_hDC);
-
- return success;
-#endif /* defined(_WIN32_WCE) */
-}
-
-
-
-void fgPlatformSetWindow ( SFG_Window *window )
-{
- if ( window != fgStructure.CurrentWindow )
- {
- if( fgStructure.CurrentWindow )
- ReleaseDC( fgStructure.CurrentWindow->Window.Handle,
- fgStructure.CurrentWindow->Window.pContext.Device );
-
- if ( window )
- {
- window->Window.pContext.Device = GetDC( window->Window.Handle );
- wglMakeCurrent(
- window->Window.pContext.Device,
- window->Window.Context
- );
- }
- }
-}
-
-
-
-/* Computes position of corners of window Rect (outer position including
- * decorations) based on the provided client rect and based on the style
- * of the window in question.
- * If posIsOutside is set to true, the input client Rect is taken to follow
- * freeGLUT's window specification convention in which the top-left corner
- * is at the outside of the window, while the size
- * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
- * area.
- */
-void fghComputeWindowRectFromClientArea_UseStyle( const DWORD windowStyle, RECT *clientRect, BOOL posIsOutside )
-{
- int xBorderWidth = 0, yBorderWidth = 0;
-
- /* If window has title bar, correct rect for it */
- if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
- if (posIsOutside)
- clientRect->bottom += GetSystemMetrics( SM_CYCAPTION );
- else
- clientRect->top -= GetSystemMetrics( SM_CYCAPTION );
-
- /* get width of window's borders (frame), correct rect for it.
- * Note, borders can be of zero width if style does not specify borders
- */
- fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
- if (posIsOutside)
- {
- clientRect->right += xBorderWidth * 2;
- clientRect->bottom += yBorderWidth * 2;
- }
- else
- {
- clientRect->left -= xBorderWidth;
- clientRect->right += xBorderWidth;
- clientRect->top -= yBorderWidth;
- clientRect->bottom += yBorderWidth;
- }
-}
-
-/* Computes position of corners of window Rect (outer position including
- * decorations) based on the provided client rect and based on the style
- * of the window in question. If the window pointer or the window handle
- * is NULL, a fully decorated window (caption and border) is assumed.
- * Furthermore, if posIsOutside is set to true, the input client Rect is
- * taken to follow freeGLUT's window specification convention in which the
- * top-left corner is at the outside of the window, while the size
- * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
- * area.
-*/
-void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside )
-{
- DWORD windowStyle = 0;
-
- if (window && window->Window.Handle)
- windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
- else
- windowStyle = WS_OVERLAPPEDWINDOW;
-
- fghComputeWindowRectFromClientArea_UseStyle(windowStyle, clientRect, posIsOutside);
-}
-
-/* Computes position of corners of client area (drawable area) of a window
- * based on the provided window Rect (outer position including decorations)
- * and based on the style of the window in question. If the window pointer
- * or the window handle is NULL, a fully decorated window (caption and
- * border) is assumed.
- * Furthermore, if wantPosOutside is set to true, the output client Rect
- * will follow freeGLUT's window specification convention in which the
- * top-left corner is at the outside of the window, the size
- * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
- * area.
- */
-void fghComputeClientAreaFromWindowRect( const SFG_Window *window, RECT *windowRect, BOOL wantPosOutside )
-{
- DWORD windowStyle = 0;
- int xBorderWidth = 0, yBorderWidth = 0;
-
- if (window && window->Window.Handle)
- windowStyle = GetWindowLong(window->Window.Handle, GWL_STYLE);
- else
- windowStyle = WS_OVERLAPPEDWINDOW;
-
- /* If window has title bar, correct rect for it */
- if (windowStyle & WS_MAXIMIZEBOX) /* Need to query for WS_MAXIMIZEBOX to see if we have a title bar, the WS_CAPTION query is also true for a WS_DLGFRAME only... */
- if (wantPosOutside)
- windowRect->bottom -= GetSystemMetrics( SM_CYCAPTION );
- else
- windowRect->top += GetSystemMetrics( SM_CYCAPTION );
-
- /* get width of window's borders (frame), correct rect for it.
- * Note, borders can be of zero width if style does not specify borders
- */
- fghGetBorderWidth(windowStyle, &xBorderWidth, &yBorderWidth);
- if (wantPosOutside)
- {
- windowRect->right -= xBorderWidth * 2;
- windowRect->bottom -= yBorderWidth * 2;
- }
- else
- {
- windowRect->left += xBorderWidth;
- windowRect->right -= xBorderWidth;
- windowRect->top += yBorderWidth;
- windowRect->bottom -= yBorderWidth;
- }
-}
-
-/* Gets the rect describing the client area (drawable area) of the
- * specified window.
- * Returns an empty rect if window pointer or window handle is NULL.
- * If wantPosOutside is set to true, the output client Rect
- * will follow freeGLUT's window specification convention in which the
- * top-left corner is at the outside of the window, while the size
- * (rect.right-rect.left,rect.bottom-rect.top) is the size of the drawable
- * area.
- */
-RECT fghGetClientArea( const SFG_Window *window, BOOL wantPosOutside )
-{
- RECT windowRect = {0,0,0,0};
-
- freeglut_return_val_if_fail((window && window->Window.Handle),windowRect);
-
- /*
- * call GetWindowRect()
- * (this returns the pixel coordinates of the outside of the window)
- */
- GetWindowRect( window->Window.Handle, &windowRect );
-
- /* Then correct the results */
- fghComputeClientAreaFromWindowRect(window, &windowRect, wantPosOutside);
-
- return windowRect;
-}
-
-/* Returns the width of the window borders based on the window's style.
- */
-void fghGetBorderWidth(const DWORD windowStyle, int* xBorderWidth, int* yBorderWidth)
-{
- if (windowStyle & WS_THICKFRAME)
- {
- *xBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
- *yBorderWidth = GetSystemMetrics(SM_CYSIZEFRAME);
- }
- else if (windowStyle & WS_DLGFRAME)
- {
- *xBorderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
- *yBorderWidth = GetSystemMetrics(SM_CYFIXEDFRAME);
- }
- else
- {
- *xBorderWidth = 0;
- *yBorderWidth = 0;
- }
-}
-
-#if(WINVER >= 0x500)
-typedef struct
-{
- int *x;
- int *y;
- const char *name;
-} m_proc_t;
-
-static BOOL CALLBACK m_proc(HMONITOR mon,
- HDC hdc,
- LPRECT rect,
- LPARAM data)
-{
- m_proc_t *dp=(m_proc_t *)data;
- MONITORINFOEX info;
- BOOL res;
- info.cbSize=sizeof(info);
- res=GetMonitorInfo(mon,(LPMONITORINFO)&info);
- if( res )
- {
- if( strcmp(dp->name,info.szDevice)==0 )
- {
- *(dp->x)=info.rcMonitor.left;
- *(dp->y)=info.rcMonitor.top;
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/*
- * this function returns the origin of the screen identified by
- * fgDisplay.pDisplay.DisplayName, and 0 otherwise.
- * This is used in fgOpenWindow to open the gamemode window on the screen
- * identified by the -display command line argument. The function should
- * not be called otherwise.
- */
-
-static void get_display_origin(int *xp,int *yp)
-{
- *xp = 0;
- *yp = 0;
-
- if( fgDisplay.pDisplay.DisplayName )
- {
- m_proc_t st;
- st.x=xp;
- st.y=yp;
- st.name=fgDisplay.pDisplay.DisplayName;
- EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st);
- }
-}
-#else
-#pragma message( "-display parameter only works if compiled with WINVER >= 0x0500")
-
-static void get_display_origin(int *xp,int *yp)
-{
- *xp = 0;
- *yp = 0;
-
- if( fgDisplay.pDisplay.DisplayName )
- {
- fgWarning( "for working -display support FreeGLUT must be compiled with WINVER >= 0x0500");
- }
-}
-#endif
-
-
-
-/*
- * Opens a window. Requires a SFG_Window object created and attached
- * to the freeglut structure. OpenGL context is created here.
- */
-void fgPlatformOpenWindow( SFG_Window* window, const char* title,
- GLboolean positionUse, int x, int y,
- GLboolean sizeUse, int w, int h,
- GLboolean gameMode, GLboolean isSubWindow )
-{
-
- WNDCLASS wc;
- DWORD flags = 0;
- DWORD exFlags = 0;
- ATOM atom;
-
- /* Grab the window class we have registered on glutInit(): */
- atom = GetClassInfo( fgDisplay.pDisplay.Instance, _T("FREEGLUT"), &wc );
- FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Info Not Found",
- "fgOpenWindow" );
-
- /* Determine window style flags*/
- if( gameMode )
- {
- FREEGLUT_INTERNAL_ERROR_EXIT ( window->Parent == NULL,
- "Game mode being invoked on a subwindow",
- "fgOpenWindow" );
-
- /*
- * Set the window creation flags appropriately to make the window
- * entirely visible:
- */
- flags = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
- }
- else
- {
- flags = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
-
- /*
- * There's a small difference between creating the top, child and
- * menu windows
- */
- if ( window->IsMenu )
- {
- flags |= WS_POPUP;
- exFlags |= WS_EX_TOOLWINDOW;
- }
-#if defined(_WIN32_WCE)
- /* no decorations for windows CE */
-#else
- /* if this is not a subwindow (child), set its style based on the requested display mode */
- else if( window->Parent == NULL )
- if ( fgState.DisplayMode & GLUT_BORDERLESS )
- {
- /* no window decorations needed */
- }
- else if ( fgState.DisplayMode & GLUT_CAPTIONLESS )
- /* only window decoration is a border, no title bar or buttons */
- flags |= WS_DLGFRAME;
- else
- /* window decoration are a border, title bar and buttons.
- * NB: we later query whether the window has a title bar or
- * not by testing for the maximize button, as the test for
- * WS_CAPTION can be true without the window having a title
- * bar. This style WS_OVERLAPPEDWINDOW gives you a maximize
- * button. */
- flags |= WS_OVERLAPPEDWINDOW;
-#endif
- else
- /* subwindows always have no decoration, but are marked as a child window to the OS */
- flags |= WS_CHILD;
- }
-
- /* determine window size and position */
- if( gameMode )
- {
- /* if in gamemode, query the origin of specified by the -display
- * command line parameter (if any) and offset the upper-left corner
- * of the window so we create the window on that screen.
- * The -display argument doesn't do anything if not trying to enter
- * gamemode.
- */
- int xoff=0, yoff=0;
- get_display_origin(&xoff,&yoff);
- x += xoff;
- y += yoff;
- }
- if( !positionUse )
- {
- x = CW_USEDEFAULT;
- y = CW_USEDEFAULT;
- }
- if( !sizeUse )
- {
- if( ! window->IsMenu )
- {
- w = CW_USEDEFAULT;
- h = CW_USEDEFAULT;
- }
- else /* fail safe - Windows can make a window of size (0, 0) */
- w = h = 300; /* default window size */
- }
- /* store requested client area width and height */
- window->State.Width = w;
- window->State.Height = h;
-
-#if !defined(_WIN32_WCE) /* no decorations for windows CE */
- if( sizeUse )
- {
- RECT windowRect;
- /*
- * Update the window dimensions, taking the window decorations
- * into account. FreeGLUT is to create the window with the
- * topleft outside corner at (x,y) and with client area
- * dimensions (w,h).
- * note: don't need to do this when w=h=CW_USEDEFAULT, so in the
- * if( sizeUse ) here is convenient.
- */
- windowRect.left = x;
- windowRect.top = y;
- windowRect.right = x+w;
- windowRect.bottom = y+h;
-
- fghComputeWindowRectFromClientArea_UseStyle(flags,&windowRect,TRUE);
-
- w = windowRect.right - windowRect.left;
- h = windowRect.bottom- windowRect.top;
- }
-#endif /* !defined(_WIN32_WCE) */
-
-#if defined(_WIN32_WCE)
- {
- wchar_t* wstr = fghWstrFromStr(title);
-
- window->Window.Handle = CreateWindow(
- _T("FREEGLUT"),
- wstr,
- WS_VISIBLE | WS_POPUP,
- 0,0, 240,320,
- NULL,
- NULL,
- fgDisplay.pDisplay.Instance,
- (LPVOID) window
- );
-
- free(wstr);
-
- SHFullScreen(window->Window.Handle, SHFS_HIDESTARTICON);
- SHFullScreen(window->Window.Handle, SHFS_HIDESIPBUTTON);
- SHFullScreen(window->Window.Handle, SHFS_HIDETASKBAR);
- MoveWindow(window->Window.Handle, 0, 0, 240, 320, TRUE);
- ShowWindow(window->Window.Handle, SW_SHOW);
- UpdateWindow(window->Window.Handle);
- }
-#else
- window->Window.Handle = CreateWindowEx(
- exFlags,
- _T("FREEGLUT"),
- title,
- flags,
- x, y, w, h,
- (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle,
- (HMENU) NULL,
- fgDisplay.pDisplay.Instance,
- (LPVOID) window
- );
-#endif /* defined(_WIN32_WCE) */
-
- if( !( window->Window.Handle ) )
- fgError( "Failed to create a window (%s)!", title );
-
-#if !defined(_WIN32_WCE)
- /* Need to set requested style again, apparently Windows doesn't listen when requesting windows without title bar or borders */
- SetWindowLong(window->Window.Handle, GWL_STYLE, flags);
- SetWindowPos(window->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-#endif /* defined(_WIN32_WCE) */
-
- /* Make a menu window always on top - fix Feature Request 947118 */
- if( window->IsMenu || gameMode )
- SetWindowPos(
- window->Window.Handle,
- HWND_TOPMOST,
- 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE
- );
-
- /* Enable multitouch: additional flag TWF_FINETOUCH, TWF_WANTPALM */
- #ifdef WM_TOUCH
- if (fghRegisterTouchWindow == (pRegisterTouchWindow)0xDEADBEEF)
- fghRegisterTouchWindow = (pRegisterTouchWindow)GetProcAddress(GetModuleHandle("user32"),"RegisterTouchWindow");
- if (fghRegisterTouchWindow)
- fghRegisterTouchWindow( window->Window.Handle, TWF_FINETOUCH | TWF_WANTPALM );
- #endif
-
-#if defined(_WIN32_WCE)
- ShowWindow( window->Window.Handle, SW_SHOW );
-#else
- ShowWindow( window->Window.Handle,
- fgState.ForceIconic ? SW_SHOWMINIMIZED : SW_SHOW );
-#endif /* defined(_WIN32_WCE) */
-
- UpdateWindow( window->Window.Handle );
- ShowCursor( TRUE ); /* XXX Old comments say "hide cursor"! */
-
-}
-
-
-/*
- * Closes a window, destroying the frame and OpenGL context
- */
-void fgPlatformCloseWindow( SFG_Window* window )
-{
- /* Make sure we don't close a window with current context active */
- if( fgStructure.CurrentWindow == window )
- wglMakeCurrent( NULL, NULL );
-
- /*
- * Step through the list of windows. If the rendering context
- * is not being used by another window, then we delete it.
- */
- {
- int used = FALSE ;
- SFG_Window *iter ;
-
- for( iter = (SFG_Window *)fgStructure.Windows.First;
- iter;
- iter = (SFG_Window *)iter->Node.Next )
- {
- if( ( iter->Window.Context == window->Window.Context ) &&
- ( iter != window ) )
- used = TRUE;
- }
-
- if( ! used )
- wglDeleteContext( window->Window.Context );
- }
-
- DestroyWindow( window->Window.Handle );
-}
-
-
-
-/*
- * This function makes the current window visible
- */
-void fgPlatformGlutShowWindow( void )
-{
- ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_SHOW );
-}
-
-/*
- * This function hides the current window
- */
-void fgPlatformGlutHideWindow( void )
-{
- ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_HIDE );
-}
-
-/*
- * Iconify the current window (top-level windows only)
- */
-void fgPlatformGlutIconifyWindow( void )
-{
- ShowWindow( fgStructure.CurrentWindow->Window.Handle, SW_MINIMIZE );
-}
-
-/*
- * Set the current window's title
- */
-void fgPlatformGlutSetWindowTitle( const char* title )
-{
-#ifdef _WIN32_WCE
- {
- wchar_t* wstr = fghWstrFromStr(title);
- SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
- free(wstr);
- }
-#else
- SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
-#endif
-}
-
-/*
- * Set the current window's iconified title
- */
-void fgPlatformGlutSetIconTitle( const char* title )
-{
-#ifdef _WIN32_WCE
- {
- wchar_t* wstr = fghWstrFromStr(title);
- SetWindowText( fgStructure.CurrentWindow->Window.Handle, wstr );
- free(wstr);
- }
-#else
- SetWindowText( fgStructure.CurrentWindow->Window.Handle, title );
-#endif
-}
-
-/*
- * Change the current window's position
- */
-void fgPlatformGlutPositionWindow( int x, int y )
-{
- RECT winRect;
-
- /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
- GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
- MoveWindow(
- fgStructure.CurrentWindow->Window.Handle,
- x,
- y,
- winRect.right - winRect.left,
- winRect.bottom - winRect.top,
- TRUE
- );
-}
-
-/*
- * Lowers the current window (by Z order change)
- */
-void fgPlatformGlutPushWindow( void )
-{
- SetWindowPos(
- fgStructure.CurrentWindow->Window.Handle,
- HWND_BOTTOM,
- 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE
- );
-}
-
-/*
- * Raises the current window (by Z order change)
- */
-void fgPlatformGlutPopWindow( void )
-{
- SetWindowPos(
- fgStructure.CurrentWindow->Window.Handle,
- HWND_TOP,
- 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE
- );
-}
-
-/*
- * Resize the current window so that it fits the whole screen
- */
-void fgPlatformGlutFullScreen( SFG_Window *win )
-{
-#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
-
- if (glutGet(GLUT_FULL_SCREEN))
- {
- /* Leave full screen state before entering fullscreen again (resizing?) */
- glutLeaveFullScreen();
- }
-
- {
-#if(WINVER >= 0x0500) /* Windows 2000 or later */
- DWORD s;
- RECT rect;
- HMONITOR hMonitor;
- MONITORINFO mi;
-
- /* For fullscreen mode, first remove all window decoration
- * and set style to popup so it will overlap the taskbar
- * then force to maximize on the screen on which it has the most
- * overlap.
- */
-
-
- /* store current window rect */
- GetWindowRect( win->Window.Handle, &win->State.pWState.OldRect );
-
- /* store current window style */
- win->State.pWState.OldStyle = s = GetWindowLong(win->Window.Handle, GWL_STYLE);
-
- /* remove decorations from style and add popup style*/
- s &= ~WS_OVERLAPPEDWINDOW;
- s |= WS_POPUP;
- SetWindowLong(win->Window.Handle, GWL_STYLE, s);
- SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-
- /* For fullscreen mode, find the monitor that is covered the most
- * by the window and get its rect as the resize target.
- */
- hMonitor= MonitorFromRect(&win->State.pWState.OldRect, MONITOR_DEFAULTTONEAREST);
- mi.cbSize = sizeof(mi);
- GetMonitorInfo(hMonitor, &mi);
- rect = mi.rcMonitor;
-#else /* if (WINVER >= 0x0500) */
- RECT rect;
-
- /* For fullscreen mode, force the top-left corner to 0,0
- * and adjust the window rectangle so that the client area
- * covers the whole screen.
- */
-
- rect.left = 0;
- rect.top = 0;
- rect.right = fgDisplay.ScreenWidth;
- rect.bottom = fgDisplay.ScreenHeight;
-
- AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS |
- WS_CLIPCHILDREN, FALSE );
-#endif /* (WINVER >= 0x0500) */
-
- /*
- * then resize window
- * SWP_NOACTIVATE Do not activate the window
- * SWP_NOOWNERZORDER Do not change position in z-order
- * SWP_NOSENDCHANGING Suppress WM_WINDOWPOSCHANGING message
- * SWP_NOZORDER Retains the current Z order (ignore 2nd param)
- */
- SetWindowPos( fgStructure.CurrentWindow->Window.Handle,
- HWND_TOP,
- rect.left,
- rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
- SWP_NOZORDER
- );
-
- win->State.IsFullscreen = GL_TRUE;
- }
-#endif
-}
-
-/*
- * If we are fullscreen, resize the current window back to its original size
- */
-void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
-{
-#if !defined(_WIN32_WCE) /* FIXME: what about WinCE */
- if (!glutGet(GLUT_FULL_SCREEN))
- {
- /* nothing to do */
- return;
- }
-
- /* restore style of window before making it fullscreen */
- SetWindowLong(win->Window.Handle, GWL_STYLE, win->State.pWState.OldStyle);
- SetWindowPos(win->Window.Handle, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-
- /* Then resize */
- SetWindowPos(win->Window.Handle,
- HWND_TOP,
- win->State.pWState.OldRect.left,
- win->State.pWState.OldRect.top,
- win->State.pWState.OldRect.right - win->State.pWState.OldRect.left,
- win->State.pWState.OldRect.bottom - win->State.pWState.OldRect.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
- SWP_NOZORDER
- );
-
- win->State.IsFullscreen = GL_FALSE;
-#endif
-}
-
-/*
- * Toggle the window's full screen state.
- */
-void fgPlatformGlutFullScreenToggle( SFG_Window *win )
-{
- if (!win->State.IsFullscreen)
- glutFullScreen();
- else
- glutLeaveFullScreen();
-}
-
-
-/* -- PLATFORM-SPECIFIC INTERFACE FUNCTION -------------------------------------------------- */
-
-int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exit_function)(int) )
-{
- __glutExitFunc = exit_function;
- return glutCreateWindow( title );
-}
-
--- /dev/null
+/*
+ * freeglut_cursor_x11.c
+ *
+ * The Windows-specific mouse cursor related stuff.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sun Feb 5, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+/* This code is for Posix/X11, Solaris, and OSX */
+#include <X11/cursorfont.h>
+
+/*
+ * A factory method for an empty cursor
+ */
+static Cursor getEmptyCursor( void )
+{
+ static Cursor cursorNone = None;
+ if( cursorNone == None ) {
+ char cursorNoneBits[ 32 ];
+ XColor dontCare;
+ Pixmap cursorNonePixmap;
+ memset( cursorNoneBits, 0, sizeof( cursorNoneBits ) );
+ memset( &dontCare, 0, sizeof( dontCare ) );
+ cursorNonePixmap = XCreateBitmapFromData ( fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.RootWindow,
+ cursorNoneBits, 16, 16 );
+ if( cursorNonePixmap != None ) {
+ cursorNone = XCreatePixmapCursor( fgDisplay.pDisplay.Display,
+ cursorNonePixmap, cursorNonePixmap,
+ &dontCare, &dontCare, 0, 0 );
+ XFreePixmap( fgDisplay.pDisplay.Display, cursorNonePixmap );
+ }
+ }
+ return cursorNone;
+}
+
+typedef struct tag_cursorCacheEntry cursorCacheEntry;
+struct tag_cursorCacheEntry {
+ unsigned int cursorShape; /* an XC_foo value */
+ Cursor cachedCursor; /* None if the corresponding cursor has
+ not been created yet */
+};
+
+/*
+ * Note: The arrangement of the table below depends on the fact that
+ * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive.
+ */
+static cursorCacheEntry cursorCache[] = {
+ { XC_arrow, None }, /* GLUT_CURSOR_RIGHT_ARROW */
+ { XC_top_left_arrow, None }, /* GLUT_CURSOR_LEFT_ARROW */
+ { XC_hand1, None }, /* GLUT_CURSOR_INFO */
+ { XC_pirate, None }, /* GLUT_CURSOR_DESTROY */
+ { XC_question_arrow, None }, /* GLUT_CURSOR_HELP */
+ { XC_exchange, None }, /* GLUT_CURSOR_CYCLE */
+ { XC_spraycan, None }, /* GLUT_CURSOR_SPRAY */
+ { XC_watch, None }, /* GLUT_CURSOR_WAIT */
+ { XC_xterm, None }, /* GLUT_CURSOR_TEXT */
+ { XC_crosshair, None }, /* GLUT_CURSOR_CROSSHAIR */
+ { XC_sb_v_double_arrow, None }, /* GLUT_CURSOR_UP_DOWN */
+ { XC_sb_h_double_arrow, None }, /* GLUT_CURSOR_LEFT_RIGHT */
+ { XC_top_side, None }, /* GLUT_CURSOR_TOP_SIDE */
+ { XC_bottom_side, None }, /* GLUT_CURSOR_BOTTOM_SIDE */
+ { XC_left_side, None }, /* GLUT_CURSOR_LEFT_SIDE */
+ { XC_right_side, None }, /* GLUT_CURSOR_RIGHT_SIDE */
+ { XC_top_left_corner, None }, /* GLUT_CURSOR_TOP_LEFT_CORNER */
+ { XC_top_right_corner, None }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */
+ { XC_bottom_right_corner, None }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */
+ { XC_bottom_left_corner, None } /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */
+};
+
+void fgPlatformSetCursor ( SFG_Window *window, int cursorID )
+{
+ Cursor cursor;
+ /*
+ * XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows
+ * for this, but if there is a system that easily supports a full-
+ * window (or full-screen) crosshair, we might consider it.
+ */
+ int cursorIDToUse =
+ ( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID;
+
+ if( ( cursorIDToUse >= 0 ) &&
+ ( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) {
+ cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ];
+ if( entry->cachedCursor == None ) {
+ entry->cachedCursor =
+ XCreateFontCursor( fgDisplay.pDisplay.Display, entry->cursorShape );
+ }
+ cursor = entry->cachedCursor;
+ } else {
+ switch( cursorIDToUse )
+ {
+ case GLUT_CURSOR_NONE:
+ cursor = getEmptyCursor( );
+ break;
+
+ case GLUT_CURSOR_INHERIT:
+ cursor = None;
+ break;
+
+ default:
+ fgError( "Unknown cursor type: %d", cursorIDToUse );
+ return;
+ }
+ }
+
+ if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) {
+ XUndefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle );
+ } else if ( cursor != None ) {
+ XDefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle, cursor );
+ } else if ( cursorIDToUse != GLUT_CURSOR_NONE ) {
+ fgError( "Failed to create cursor" );
+ }
+}
+
+
+void fgPlatformWarpPointer ( int x, int y )
+{
+ XWarpPointer(
+ fgDisplay.pDisplay.Display,
+ None,
+ fgStructure.CurrentWindow->Window.Handle,
+ 0, 0, 0, 0,
+ x, y
+ );
+ /* Make the warp visible immediately. */
+ XFlush( fgDisplay.pDisplay.Display );
+}
+
--- /dev/null
+/*
+ * freeglut_display_x11.c
+ *
+ * Display message posting, context buffer swapping.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow )
+{
+ glXSwapBuffers( pDisplayPtr->Display, CurrentWindow->Window.Handle );
+}
+
--- /dev/null
+/*
+ * freeglut_ext.c
+ *
+ * Functions related to OpenGL extensions.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+GLUTproc fgPlatformGetGLUTProcAddress( const char* procName )
+{
+ /* optimization: quick initial check */
+ if( strncmp( procName, "glut", 4 ) != 0 )
+ return NULL;
+
+#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x;
+ CHECK_NAME(glutJoystickFunc);
+ CHECK_NAME(glutForceJoystickFunc);
+ CHECK_NAME(glutGameModeString);
+ CHECK_NAME(glutEnterGameMode);
+ CHECK_NAME(glutLeaveGameMode);
+ CHECK_NAME(glutGameModeGet);
+#undef CHECK_NAME
+
+ return NULL;
+}
+
+
+SFG_Proc fgPlatformGetProcAddress( const char *procName )
+{
+#if defined( GLX_ARB_get_proc_address )
+ return (SFG_Proc)glXGetProcAddressARB( ( const GLubyte * )procName );
+#else
+ return NULL;
+#endif
+}
+
--- /dev/null
+/*
+ * freeglut_gamemode_x11.c
+ *
+ * The game mode handling code.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
+{
+#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ int event_base, error_base, ver_major, ver_minor, use_rate;
+ XRRScreenConfiguration *xrr_config = 0;
+ Status result = -1;
+
+ /* must check at runtime for the availability of the extension */
+ if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {
+ return -1;
+ }
+
+ XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor);
+
+ /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and
+ * the user actually cares about it (rate > 0)
+ */
+ use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) ||
+ ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) );
+
+ /* this loop is only so that the whole thing will be repeated if someone
+ * else changes video mode between our query of the current information and
+ * the attempt to change it.
+ */
+ do {
+ XRRScreenSize *ssizes;
+ short *rates;
+ Rotation rot;
+ int i, ssizes_count, rates_count, curr, res_idx = -1;
+ Time timestamp, cfg_timestamp;
+
+ if(xrr_config) {
+ XRRFreeScreenConfigInfo(xrr_config);
+ }
+
+ if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {
+ fgWarning("XRRGetScreenInfo failed");
+ break;
+ }
+ ssizes = XRRConfigSizes(xrr_config, &ssizes_count);
+ curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
+ timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);
+
+ /* if either of xsz or ysz are unspecified, use the current values */
+ if(xsz <= 0)
+ xsz = fgState.GameModeSize.X = ssizes[curr].width;
+ if(ysz <= 0)
+ ysz = fgState.GameModeSize.Y = ssizes[curr].height;
+
+
+ if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {
+ /* no need to switch, we're already in the requested resolution */
+ res_idx = curr;
+ } else {
+ for(i=0; i<ssizes_count; i++) {
+ if(ssizes[i].width == xsz && ssizes[i].height == ysz) {
+ res_idx = i;
+ break; /* found it */
+ }
+ }
+ }
+ if(res_idx == -1)
+ break; /* no matching resolution */
+
+#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
+ if(use_rate) {
+ rate = fgState.GameModeRefresh;
+
+ /* for the selected resolution, let's find out if there is
+ * a matching refresh rate available.
+ */
+ rates = XRRConfigRates(xrr_config, res_idx, &rates_count);
+
+ for(i=0; i<rates_count; i++) {
+ if(rates[i] == rate) {
+ break;
+ }
+ }
+ if(i == rates_count) {
+ break; /* no matching rate */
+ }
+ }
+#endif
+
+ if(just_checking) {
+ result = 0;
+ break;
+ }
+
+#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
+ if(use_rate)
+ result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config,
+ fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp);
+ else
+#endif
+ result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config,
+ fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp);
+
+ } while(result == RRSetConfigInvalidTime);
+
+ if(xrr_config) {
+ XRRFreeScreenConfigInfo(xrr_config);
+ }
+
+ if(result == 0) {
+ return 0;
+ }
+
+#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */
+ return -1;
+}
+
+/*
+ * Remembers the current visual settings, so that
+ * we can change them and restore later...
+ */
+void fgPlatformRememberState( void )
+{
+ int event_base, error_base;
+
+ /*
+ * Remember the current pointer location before going fullscreen
+ * for restoring it later:
+ */
+ Window junk_window;
+ unsigned int junk_mask;
+
+ XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow,
+ &junk_window, &junk_window,
+ &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY,
+ &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask);
+
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ if(XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {
+ XRRScreenConfiguration *xrr_config;
+ XRRScreenSize *ssizes;
+ Rotation rot;
+ int ssize_count, curr;
+
+ if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {
+ ssizes = XRRConfigSizes(xrr_config, &ssize_count);
+ curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
+
+ fgDisplay.pDisplay.prev_xsz = ssizes[curr].width;
+ fgDisplay.pDisplay.prev_ysz = ssizes[curr].height;
+ fgDisplay.pDisplay.prev_refresh = -1;
+
+# if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
+ if(fgState.GameModeRefresh != -1) {
+ fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);
+ }
+# endif
+
+ fgDisplay.pDisplay.prev_size_valid = 1;
+
+ XRRFreeScreenConfigInfo(xrr_config);
+ }
+ }
+# endif
+
+ /*
+ * This highly depends on the XFree86 extensions,
+ * not approved as X Consortium standards
+ */
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+ if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {
+ return;
+ }
+
+ /*
+ * Remember the current ViewPort location of the screen to be able to
+ * restore the ViewPort on LeaveGameMode():
+ */
+ if( !XF86VidModeGetViewPort(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ &fgDisplay.pDisplay.DisplayViewPortX,
+ &fgDisplay.pDisplay.DisplayViewPortY ) )
+ fgWarning( "XF86VidModeGetViewPort failed" );
+
+
+ /* Query the current display settings: */
+ fgDisplay.pDisplay.DisplayModeValid =
+ XF86VidModeGetModeLine(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ &fgDisplay.pDisplay.DisplayModeClock,
+ &fgDisplay.pDisplay.DisplayMode
+ );
+
+ if( !fgDisplay.pDisplay.DisplayModeValid )
+ fgWarning( "XF86VidModeGetModeLine failed" );
+# endif
+
+}
+
+/*
+ * Restores the previously remembered visual settings
+ */
+void fgPlatformRestoreState( void )
+{
+ /* Restore the remembered pointer position: */
+ XWarpPointer(
+ fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0,
+ fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY
+ );
+
+
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ if(fgDisplay.pDisplay.prev_size_valid) {
+ if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) {
+ fgDisplay.pDisplay.prev_size_valid = 0;
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+ fgDisplay.pDisplay.DisplayModeValid = 0;
+# endif
+ return;
+ }
+ }
+# endif
+
+
+
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+ /*
+ * This highly depends on the XFree86 extensions,
+ * not approved as X Consortium standards
+ */
+
+ if( fgDisplay.pDisplay.DisplayModeValid )
+ {
+ XF86VidModeModeInfo** displayModes;
+ int i, displayModesCount;
+
+ if( !XF86VidModeGetAllModeLines(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ &displayModesCount,
+ &displayModes ) )
+ {
+ fgWarning( "XF86VidModeGetAllModeLines failed" );
+ return;
+ }
+
+
+ /*
+ * Check every of the modes looking for one that matches our demands.
+ * If we find one, switch to it and restore the remembered viewport.
+ */
+ for( i = 0; i < displayModesCount; i++ )
+ {
+ if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay &&
+ displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay &&
+ displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock )
+ {
+ if( !XF86VidModeSwitchToMode(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ displayModes[ i ] ) )
+ {
+ fgWarning( "XF86VidModeSwitchToMode failed" );
+ break;
+ }
+
+ if( !XF86VidModeSetViewPort(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ fgDisplay.pDisplay.DisplayViewPortX,
+ fgDisplay.pDisplay.DisplayViewPortY ) )
+ fgWarning( "XF86VidModeSetViewPort failed" );
+
+
+ /*
+ * For the case this would be the last X11 call the application
+ * calls exit() we've to flush the X11 output queue to have the
+ * commands sent to the X server before the application exits.
+ */
+ XFlush( fgDisplay.pDisplay.Display );
+
+ fgDisplay.pDisplay.DisplayModeValid = 0;
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ fgDisplay.pDisplay.prev_size_valid = 0;
+# endif
+
+ break;
+ }
+ }
+ XFree( displayModes );
+ }
+
+# endif
+
+}
+
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+
+/*
+ * Checks a single display mode settings against user's preferences.
+ */
+static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
+{
+ /* The desired values should be stored in fgState structure... */
+ return ( width == fgState.GameModeSize.X ) &&
+ ( height == fgState.GameModeSize.Y ) &&
+ ( depth == fgState.GameModeDepth ) &&
+ ( refresh == fgState.GameModeRefresh );
+}
+
+/*
+ * Checks all display modes settings against user's preferences.
+ * Returns the mode number found or -1 if none could be found.
+ */
+static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes )
+{
+ int i;
+ for( i = 0; i < displayModesCount; i++ )
+ {
+ /* Compute the displays refresh rate, dotclock comes in kHz. */
+ int refresh = ( displayModes[ i ]->dotclock * 1000 ) /
+ ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );
+
+ if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,
+ displayModes[ i ]->vdisplay,
+ fgState.GameModeDepth,
+ ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {
+ if (!exactMatch)
+ {
+ /* Update the chosen refresh rate, otherwise a
+ * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not
+ * return the right values
+ */
+ fgState.GameModeRefresh = refresh;
+ }
+
+ return i;
+ }
+ }
+ return -1;
+}
+
+#endif
+
+/*
+ * Changes the current display mode to match user's settings
+ */
+GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )
+{
+ GLboolean success = GL_FALSE;
+ /* first try to use XRandR, then fallback to XF86VidMode */
+# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y,
+ fgState.GameModeRefresh, haveToTest) != -1) {
+ return GL_TRUE;
+ }
+# endif
+
+
+ /*
+ * This highly depends on the XFree86 extensions,
+ * not approved as X Consortium standards
+ */
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+
+ /*
+ * This is also used by applications which check modes by calling
+ * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
+ */
+ if( haveToTest || fgDisplay.pDisplay.DisplayModeValid )
+ {
+ XF86VidModeModeInfo** displayModes;
+ int i, displayModesCount;
+
+ /* If we don't have a valid modeline in the display structure, which
+ * can happen if this is called from glutGameModeGet instead of
+ * glutEnterGameMode, then we need to query the current mode, to make
+ * unspecified settings to default to their current values.
+ */
+ if(!fgDisplay.pDisplay.DisplayModeValid) {
+ if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen,
+ &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) {
+ return success;
+ }
+ }
+
+ if (fgState.GameModeSize.X == -1)
+ {
+ fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay;
+ }
+ if (fgState.GameModeSize.Y == -1)
+ {
+ fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay;
+ }
+ if (fgState.GameModeDepth == -1)
+ {
+ /* can't get color depth from this, nor can we change it, do nothing
+ * TODO: get with XGetVisualInfo()? but then how to set?
+ */
+ }
+ if (fgState.GameModeRefresh == -1)
+ {
+ /* Compute the displays refresh rate, dotclock comes in kHz. */
+ int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) /
+ ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal );
+
+ fgState.GameModeRefresh = refresh;
+ }
+
+ /* query all possible display modes */
+ if( !XF86VidModeGetAllModeLines(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ &displayModesCount,
+ &displayModes ) )
+ {
+ fgWarning( "XF86VidModeGetAllModeLines failed" );
+ return success;
+ }
+
+
+ /*
+ * Check every of the modes looking for one that matches our demands,
+ * ignoring the refresh rate if no exact match could be found.
+ */
+ i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes );
+ if( i < 0 ) {
+ i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes );
+ }
+ success = ( i < 0 ) ? GL_FALSE : GL_TRUE;
+
+ if( !haveToTest && success ) {
+ if( !XF86VidModeSwitchToMode(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ displayModes[ i ] ) )
+ fgWarning( "XF86VidModeSwitchToMode failed" );
+ }
+
+ XFree( displayModes );
+ }
+
+# endif
+
+ return success;
+}
+
+
+void fgPlatformEnterGameMode( void )
+{
+
+ /*
+ * Sync needed to avoid a real race, the Xserver must have really created
+ * the window before we can grab the pointer into it:
+ */
+ XSync( fgDisplay.pDisplay.Display, False );
+ /*
+ * Grab the pointer to confine it into the window after the calls to
+ * XWrapPointer() which ensure that the pointer really enters the window.
+ *
+ * We also need to wait here until XGrabPointer() returns GrabSuccess,
+ * otherwise the new window is not viewable yet and if the next function
+ * (XSetInputFocus) is called with a not yet viewable window, it will exit
+ * the application which we have to aviod, so wait until it's viewable:
+ */
+ while( GrabSuccess != XGrabPointer(
+ fgDisplay.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle,
+ TRUE,
+ ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
+ | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync,
+ fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )
+ usleep( 100 );
+ /*
+ * Change input focus to the new window. This will exit the application
+ * if the new window is not viewable yet, see the XGrabPointer loop above.
+ */
+ XSetInputFocus(
+ fgDisplay.pDisplay.Display,
+ fgStructure.GameModeWindow->Window.Handle,
+ RevertToNone,
+ CurrentTime
+ );
+
+ /* Move the Pointer to the middle of the fullscreen window */
+ XWarpPointer(
+ fgDisplay.pDisplay.Display,
+ None,
+ fgDisplay.pDisplay.RootWindow,
+ 0, 0, 0, 0,
+ fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
+ );
+
+# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+
+ if( fgDisplay.pDisplay.DisplayModeValid )
+ {
+ int x, y;
+ Window child;
+
+ /* Change to viewport to the window topleft edge: */
+ if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) )
+ fgWarning( "XF86VidModeSetViewPort failed" );
+
+ /*
+ * Final window repositioning: It could be avoided using an undecorated
+ * window using override_redirect, but this * would possily require
+ * more changes and investigation.
+ */
+
+ /* Get the current postion of the drawable area on screen */
+ XTranslateCoordinates(
+ fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ fgDisplay.pDisplay.RootWindow,
+ 0, 0, &x, &y,
+ &child
+ );
+
+ /* Move the decorataions out of the topleft corner of the display */
+ XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
+ -x, -y);
+ }
+
+#endif
+
+ /* Grab the keyboard, too */
+ XGrabKeyboard(
+ fgDisplay.pDisplay.Display,
+ fgStructure.GameModeWindow->Window.Handle,
+ FALSE,
+ GrabModeAsync, GrabModeAsync,
+ CurrentTime
+ );
+
+}
+
+void fgPlatformLeaveGameMode( void )
+{
+ XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime );
+ XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime );
+}
+
--- /dev/null
+/*
+ * freeglut_glutfont_definitions_x11.c
+ *
+ * Bitmap and stroke fonts displaying.
+ *
+ * Copyright (c) 2003 Stephen J. Baker (whether he wants it or not).
+ * All Rights Reserved.
+ * Written by John F. Fay <fayjf@sourceforge.net>, who releases the
+ * copyright over to the "freeglut" project lead.
+ * Creation date: Mon July 21 2003
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This file is necessary for the *nix version of "freeglut" because the
+ * original GLUT defined its font variables in rather an unusual way.
+ * Publicly, in "glut.h", they were defined as "void *". Privately,
+ * in one of the source code files, they were defined as pointers to a
+ * structure. Most compilers and linkers are satisfied with the "void *"
+ * and don't go any farther, but some of them balked. In particular,
+ * when compiling with "freeglut" and then trying to run using the GLUT
+ * ".so" library, some of them would give an error. So we are having to
+ * create this file to define the variables as pointers to an unusual
+ * structure to match GLUT.
+ */
+
+/*
+ * freeglut_internal.h uses some GL types, but including the GL header portably
+ * is a bit tricky, so we include freeglut_std.h here, which contains the
+ * necessary machinery. But this poses another problem, caused by the ugly
+ * original defintion of the font constants in "classic" GLUT: They are defined
+ * as void* externally, so we move them temporarily out of the way by AN EXTREME
+ * CPP HACK.
+ */
+
+#define glutStrokeRoman glutStrokeRomanIGNOREME
+#define glutStrokeMonoRoman glutStrokeMonoRomanIGNOREME
+#define glutBitmap9By15 glutBitmap9By15IGNOREME
+#define glutBitmap8By13 glutBitmap8By13IGNOREME
+#define glutBitmapTimesRoman10 glutBitmapTimesRoman10IGNOREME
+#define glutBitmapTimesRoman24 glutBitmapTimesRoman24IGNOREME
+#define glutBitmapHelvetica10 glutBitmapHelvetica10IGNOREME
+#define glutBitmapHelvetica12 glutBitmapHelvetica12IGNOREME
+#define glutBitmapHelvetica18 glutBitmapHelvetica18IGNOREME
+
+#include <GL/freeglut_std.h>
+
+#undef glutStrokeRoman
+#undef glutStrokeMonoRoman
+#undef glutBitmap9By15
+#undef glutBitmap8By13
+#undef glutBitmapTimesRoman10
+#undef glutBitmapTimesRoman24
+#undef glutBitmapHelvetica10
+#undef glutBitmapHelvetica12
+#undef glutBitmapHelvetica18
+
+#include "../fg_internal.h"
+
+struct freeglutStrokeFont
+{
+ const char *name ;
+ int num_chars ;
+ void *ch ;
+ float top ;
+ float bottom ;
+};
+
+struct freeglutBitmapFont
+{
+ const char *name ;
+ const int num_chars ;
+ const int first ;
+ const void *ch ;
+};
+
+
+struct freeglutStrokeFont glutStrokeRoman ;
+struct freeglutStrokeFont glutStrokeMonoRoman ;
+
+struct freeglutBitmapFont glutBitmap9By15 ;
+struct freeglutBitmapFont glutBitmap8By13 ;
+struct freeglutBitmapFont glutBitmapTimesRoman10 ;
+struct freeglutBitmapFont glutBitmapTimesRoman24 ;
+struct freeglutBitmapFont glutBitmapHelvetica10 ;
+struct freeglutBitmapFont glutBitmapHelvetica12 ;
+struct freeglutBitmapFont glutBitmapHelvetica18 ;
+
--- /dev/null
+/*
+ * freeglut_init_x11.c
+ *
+ * Various freeglut initialization functions.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <limits.h> /* LONG_MAX */
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+/* Return the atom associated with "name". */
+static Atom fghGetAtom(const char * name)
+{
+ return XInternAtom(fgDisplay.pDisplay.Display, name, False);
+}
+
+/*
+ * Check if "property" is set on "window". The property's values are returned
+ * through "data". If the property is set and is of type "type", return the
+ * number of elements in "data". Return zero otherwise. In both cases, use
+ * "Xfree()" to free "data".
+ */
+static int fghGetWindowProperty(Window window,
+ Atom property,
+ Atom type,
+ unsigned char ** data)
+{
+ /*
+ * Caller always has to use "Xfree()" to free "data", since
+ * "XGetWindowProperty() always allocates one extra byte in prop_return
+ * [i.e. "data"] (even if the property is zero length) [..]".
+ */
+
+ int status; /* Returned by "XGetWindowProperty". */
+
+ Atom type_returned;
+ int temp_format; /* Not used. */
+ unsigned long number_of_elements;
+ unsigned long temp_bytes_after; /* Not used. */
+
+
+ status = XGetWindowProperty(fgDisplay.pDisplay.Display,
+ window,
+ property,
+ 0,
+ LONG_MAX,
+ False,
+ type,
+ &type_returned,
+ &temp_format,
+ &number_of_elements,
+ &temp_bytes_after,
+ data);
+
+ FREEGLUT_INTERNAL_ERROR_EXIT(status == Success,
+ "XGetWindowProperty failled",
+ "fghGetWindowProperty");
+
+ if (type_returned != type)
+ {
+ number_of_elements = 0;
+ }
+
+ return number_of_elements;
+}
+
+/* Check if the window manager is NET WM compliant. */
+static int fghNetWMSupported(void)
+{
+ Atom wm_check;
+ Window ** window_ptr_1;
+
+ int number_of_windows;
+ int net_wm_supported;
+
+
+ net_wm_supported = 0;
+
+ wm_check = fghGetAtom("_NET_SUPPORTING_WM_CHECK");
+ window_ptr_1 = malloc(sizeof(Window *));
+
+ /*
+ * Check that the window manager has set this property on the root window.
+ * The property must be the ID of a child window.
+ */
+ number_of_windows = fghGetWindowProperty(fgDisplay.pDisplay.RootWindow,
+ wm_check,
+ XA_WINDOW,
+ (unsigned char **) window_ptr_1);
+ if (number_of_windows == 1)
+ {
+ Window ** window_ptr_2;
+
+ window_ptr_2 = malloc(sizeof(Window *));
+
+ /* Check that the window has the same property set to the same value. */
+ number_of_windows = fghGetWindowProperty(**window_ptr_1,
+ wm_check,
+ XA_WINDOW,
+ (unsigned char **) window_ptr_2);
+ if ((number_of_windows == 1) && (**window_ptr_1 == **window_ptr_2))
+ {
+ /* NET WM compliant */
+ net_wm_supported = 1;
+ }
+
+ XFree(*window_ptr_2);
+ free(window_ptr_2);
+ }
+
+ XFree(*window_ptr_1);
+ free(window_ptr_1);
+
+ return net_wm_supported;
+}
+
+/* Check if "hint" is present in "property" for "window". */
+int fgHintPresent(Window window, Atom property, Atom hint)
+{
+ Atom *atoms;
+ int number_of_atoms;
+ int supported;
+ int i;
+
+ supported = 0;
+
+ number_of_atoms = fghGetWindowProperty(window,
+ property,
+ XA_ATOM,
+ (unsigned char **) &atoms);
+ for (i = 0; i < number_of_atoms; i++)
+ {
+ if (atoms[i] == hint)
+ {
+ supported = 1;
+ break;
+ }
+ }
+
+ XFree(atoms);
+ return supported;
+}
+
+/*
+ * A call to this function should initialize all the display stuff...
+ */
+void fgPlatformInitialize( const char* displayName )
+{
+ fgDisplay.pDisplay.Display = XOpenDisplay( displayName );
+
+ if( fgDisplay.pDisplay.Display == NULL )
+ fgError( "failed to open display '%s'", XDisplayName( displayName ) );
+
+ if( !glXQueryExtension( fgDisplay.pDisplay.Display, NULL, NULL ) )
+ fgError( "OpenGL GLX extension not supported by display '%s'",
+ XDisplayName( displayName ) );
+
+ fgDisplay.pDisplay.Screen = DefaultScreen( fgDisplay.pDisplay.Display );
+ fgDisplay.pDisplay.RootWindow = RootWindow(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen
+ );
+
+ fgDisplay.ScreenWidth = DisplayWidth(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen
+ );
+ fgDisplay.ScreenHeight = DisplayHeight(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen
+ );
+
+ fgDisplay.ScreenWidthMM = DisplayWidthMM(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen
+ );
+ fgDisplay.ScreenHeightMM = DisplayHeightMM(
+ fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen
+ );
+
+ fgDisplay.pDisplay.Connection = ConnectionNumber( fgDisplay.pDisplay.Display );
+
+ /* Create the window deletion atom */
+ fgDisplay.pDisplay.DeleteWindow = fghGetAtom("WM_DELETE_WINDOW");
+
+ /* Create the state and full screen atoms */
+ fgDisplay.pDisplay.State = None;
+ fgDisplay.pDisplay.StateFullScreen = None;
+
+ if (fghNetWMSupported())
+ {
+ const Atom supported = fghGetAtom("_NET_SUPPORTED");
+ const Atom state = fghGetAtom("_NET_WM_STATE");
+
+ /* Check if the state hint is supported. */
+ if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, state))
+ {
+ const Atom full_screen = fghGetAtom("_NET_WM_STATE_FULLSCREEN");
+
+ fgDisplay.pDisplay.State = state;
+
+ /* Check if the window manager supports full screen. */
+ /** Check "_NET_WM_ALLOWED_ACTIONS" on our window instead? **/
+ if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, full_screen))
+ {
+ fgDisplay.pDisplay.StateFullScreen = full_screen;
+ }
+ }
+ }
+
+
+ fgState.Initialised = GL_TRUE;
+
+ atexit(fgDeinitialize);
+
+ /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */
+ fgInitialiseInputDevices();
+}
+
+void fgPlatformDeinitialiseInputDevices ( void )
+{
+ fghCloseInputDevices ();
+
+ fgState.JoysticksInitialised = GL_FALSE;
+ fgState.InputDevsInitialised = GL_FALSE;
+}
+
+
+void fgPlatformCloseDisplay ( void )
+{
+ /*
+ * Make sure all X-client data we have created will be destroyed on
+ * display closing
+ */
+ XSetCloseDownMode( fgDisplay.pDisplay.Display, DestroyAll );
+
+ /*
+ * Close the display connection, destroying all windows we have
+ * created so far
+ */
+ XCloseDisplay( fgDisplay.pDisplay.Display );
+}
+
+
+void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext )
+{
+ /* Note that the MVisualInfo is not owned by the MenuContext! */
+ glXDestroyContext( pDisplay.Display, MContext );
+}
--- /dev/null
+/*
+ * freeglut_input_devices_x11.c
+ *
+ * Handles miscellaneous input devices via direct serial-port access.
+ * Proper X11 XInput device support is not yet supported.
+ * Also lacks Mac support.
+ *
+ * Written by Joe Krahn <krahn@niehs.nih.gov> 2005
+ *
+ * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved.
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <fcntl.h>
+
+struct _serialport {
+ int fd;
+ struct termios termio, termio_save;
+};
+
+typedef struct _serialport SERIALPORT;
+
+void serial_flush ( SERIALPORT *port );
+
+/* local variables */
+static SERIALPORT *dialbox_port=NULL;
+
+/*****************************************************************/
+
+/*
+ * Try initializing the input device(s)
+ */
+void fgPlatformRegisterDialDevice ( const char *dial_device )
+{
+}
+
+SERIALPORT *serial_open ( const char *device )
+{
+ int fd;
+ struct termios termio;
+ SERIALPORT *port;
+
+ fd = open(device, O_RDWR | O_NONBLOCK );
+ if (fd <0) {
+ perror(device);
+ return NULL;
+ }
+
+ port = malloc(sizeof(SERIALPORT));
+ memset(port, 0, sizeof(SERIALPORT));
+ port->fd = fd;
+
+ /* save current port settings */
+ tcgetattr(fd,&port->termio_save);
+
+ memset(&termio, 0, sizeof(termio));
+ termio.c_cflag = CS8 | CREAD | HUPCL ;
+ termio.c_iflag = IGNPAR | IGNBRK ;
+ termio.c_cc[VTIME] = 0; /* inter-character timer */
+ termio.c_cc[VMIN] = 1; /* block read until 1 chars received, when blocking I/O */
+
+ cfsetispeed(&termio, B9600);
+ cfsetospeed(&termio, B9600);
+ tcsetattr(fd,TCSANOW,&termio);
+
+ serial_flush(port);
+ return port;
+}
+
+void serial_close(SERIALPORT *port)
+{
+ if (port)
+ {
+ /* restore old port settings */
+ tcsetattr(port->fd,TCSANOW,&port->termio_save);
+ close(port->fd);
+ free(port);
+ }
+}
+
+int serial_getchar(SERIALPORT *port)
+{
+ unsigned char ch;
+ if (!port) return EOF;
+ if (read(port->fd,&ch,1)) return ch;
+ return EOF;
+}
+
+int serial_putchar(SERIALPORT *port, unsigned char ch)
+{
+ if (!port) return 0;
+ return write(port->fd,&ch,1);
+}
+
+void serial_flush ( SERIALPORT *port )
+{
+ tcflush ( port->fd, TCIOFLUSH );
+}
--- /dev/null
+/*
+ * freeglut_internal_x11.h
+ *
+ * The freeglut library private include file.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by Diederick C. Niehorster, <dcnieho@gmail.com>
+ * Creation date: Fri Jan 20, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef FREEGLUT_INTERNAL_X11_H
+#define FREEGLUT_INTERNAL_X11_H
+
+
+/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XInput.h>
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+# include <X11/extensions/xf86vmode.h>
+#endif
+#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+# include <X11/extensions/Xrandr.h>
+#endif
+/* If GLX is too old, we will fail during runtime when multisampling
+ is requested, but at least freeglut compiles. */
+#ifndef GLX_SAMPLE_BUFFERS
+# define GLX_SAMPLE_BUFFERS 0x80A8
+#endif
+#ifndef GLX_SAMPLES
+# define GLX_SAMPLES 0x80A9
+#endif
+
+
+
+/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
+/* The structure used by display initialization in freeglut_init.c */
+typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
+struct tagSFG_PlatformDisplay
+{
+ Display* Display; /* The display we are being run in. */
+ int Screen; /* The screen we are about to use. */
+ Window RootWindow; /* The screen's root window. */
+ int Connection; /* The display's connection number */
+ Atom DeleteWindow; /* The window deletion atom */
+ Atom State; /* The state atom */
+ Atom StateFullScreen; /* The full screen atom */
+
+#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
+ int prev_xsz, prev_ysz;
+ int prev_refresh;
+ int prev_size_valid;
+#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */
+
+#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
+ /*
+ * XF86VidMode may be compilable even if it fails at runtime. Therefore,
+ * the validity of the VidMode has to be tracked
+ */
+ int DisplayModeValid; /* Flag that indicates runtime status*/
+ XF86VidModeModeLine DisplayMode; /* Current screen's display settings */
+ int DisplayModeClock; /* The display mode's refresh rate */
+ int DisplayViewPortX; /* saved X location of the viewport */
+ int DisplayViewPortY; /* saved Y location of the viewport */
+#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */
+
+ int DisplayPointerX; /* saved X location of the pointer */
+ int DisplayPointerY; /* saved Y location of the pointer */
+};
+
+
+/*
+ * Make "freeglut" window handle and context types so that we don't need so
+ * much conditionally-compiled code later in the library.
+ */
+typedef Window SFG_WindowHandleType ;
+typedef GLXContext SFG_WindowContextType ;
+typedef struct tagSFG_PlatformContext SFG_PlatformContext;
+struct tagSFG_PlatformContext
+{
+ GLXFBConfig* FBConfig; /* The window's FBConfig */
+};
+
+
+/* Window's state description. This structure should be kept portable. */
+typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
+struct tagSFG_PlatformWindowState
+{
+ int OldWidth; /* Window width from before a resize */
+ int OldHeight; /* " height " " " " */
+};
+
+
+/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */
+/*
+ * Initial defines from "js.h" starting around line 33 with the existing "freeglut_joystick.c"
+ * interspersed
+ */
+# ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+# endif
+# ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+# endif
+# ifdef HAVE_ERRNO_H
+# include <errno.h>
+# include <string.h>
+# endif
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+/* XXX The below hack is done until freeglut's autoconf is updated. */
+# define HAVE_USB_JS 1
+
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+# include <sys/joystick.h>
+# else
+/*
+ * XXX NetBSD/amd64 systems may find that they have to steal the
+ * XXX /usr/include/machine/joystick.h from a NetBSD/i386 system.
+ * XXX I cannot comment whether that works for the interface, but
+ * XXX it lets you compile...(^& I do not think that we can do away
+ * XXX with this header.
+ */
+# include <machine/joystick.h> /* For analog joysticks */
+# endif
+# define JS_DATA_TYPE joystick
+# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
+# endif
+
+# if defined(__linux__)
+# include <linux/joystick.h>
+
+/* check the joystick driver version */
+# if defined(JS_VERSION) && JS_VERSION >= 0x010000
+# define JS_NEW
+# endif
+# else /* Not BSD or Linux */
+# ifndef JS_RETURN
+
+ /*
+ * We'll put these values in and that should
+ * allow the code to at least compile when there is
+ * no support. The JS open routine should error out
+ * and shut off all the code downstream anyway and if
+ * the application doesn't use a joystick we'll be fine.
+ */
+
+ struct JS_DATA_TYPE
+ {
+ int buttons;
+ int x;
+ int y;
+ };
+
+# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
+# endif
+# endif
+
+/* XXX It might be better to poll the operating system for the numbers of buttons and
+ * XXX axes and then dynamically allocate the arrays.
+ */
+# define _JS_MAX_AXES 16
+typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
+struct tagSFG_PlatformJoystick
+{
+# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+ struct os_specific_s *os;
+# endif
+
+# ifdef JS_NEW
+ struct js_event js;
+ int tmp_buttons;
+ float tmp_axes [ _JS_MAX_AXES ];
+# else
+ struct JS_DATA_TYPE js;
+# endif
+
+ char fname [ 128 ];
+ int fd;
+};
+
+
+/* Menu font and color definitions */
+#define FREEGLUT_MENU_FONT GLUT_BITMAP_HELVETICA_18
+
+#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
+#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f}
+#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
+#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
+
+
+
+
+/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */
+/* spaceball device functions, defined in freeglut_spaceball.c */
+int fgIsSpaceballXEvent( const XEvent *ev );
+void fgSpaceballHandleXEvent( const XEvent *ev );
+
+/*
+ * Check if "hint" is present in "property" for "window". See freeglut_init.c
+ */
+int fgHintPresent(Window window, Atom property, Atom hint);
+
+/* Handler for X extension Events */
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+ void fgHandleExtensionEvents( XEvent * ev );
+ void fgRegisterDevices( Display* dpy, Window* win );
+#endif
+
+
+#endif /* FREEGLUT_INTERNAL_X11_H */
--- /dev/null
+/*
+ * freeglut_joystick_x11.c
+ *
+ * Joystick handling code
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Steve Baker, <sjbaker1@airmail.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * FreeBSD port by Stephen Montgomery-Smith <stephen@math.missouri.edu>
+ *
+ * Redone by John Fay 2/4/04 with another look from the PLIB "js" library.
+ * Many thanks for Steve Baker for permission to pull from that library.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+
+/*this should be defined in a header file */
+#define MAX_NUM_JOYSTICKS 2
+extern SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
+
+void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
+{
+ int status;
+
+ int i;
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
+ int len;
+
+ if ( joy->pJoystick.os->is_analog )
+ {
+ int status = read ( joy->pJoystick.os->fd, &joy->pJoystick.os->ajs, sizeof(joy->pJoystick.os->ajs) );
+ if ( status != sizeof(joy->pJoystick.os->ajs) ) {
+ perror ( joy->pJoystick.os->fname );
+ joy->error = GL_TRUE;
+ return;
+ }
+ if ( buttons != NULL )
+ *buttons = ( joy->pJoystick.os->ajs.b1 ? 1 : 0 ) | ( joy->pJoystick.os->ajs.b2 ? 2 : 0 );
+
+ if ( axes != NULL )
+ {
+ axes[0] = (float) joy->pJoystick.os->ajs.x;
+ axes[1] = (float) joy->pJoystick.os->ajs.y;
+ }
+
+ return;
+ }
+
+# ifdef HAVE_USB_JS
+ while ( ( len = read ( joy->pJoystick.os->fd, joy->pJoystick.os->hid_data_buf, joy->pJoystick.os->hid_dlen ) ) == joy->pJoystick.os->hid_dlen )
+ {
+ struct hid_item *h;
+
+ for ( h = joy->pJoystick.os->hids; h; h = h->next )
+ {
+ int d = hid_get_data ( joy->pJoystick.os->hid_data_buf, h );
+
+ int page = HID_PAGE ( h->usage );
+ int usage = HID_USAGE ( h->usage );
+
+ if ( page == HUP_GENERIC_DESKTOP )
+ {
+ int i;
+ for ( i = 0; i < joy->num_axes; i++ )
+ if (joy->pJoystick.os->axes_usage[i] == usage)
+ {
+ if (usage == HUG_HAT_SWITCH)
+ {
+ if (d < 0 || d > 8)
+ d = 0; /* safety */
+ joy->pJoystick.os->cache_axes[i] = (float)hatmap_x[d];
+ joy->pJoystick.os->cache_axes[i + 1] = (float)hatmap_y[d];
+ }
+ else
+ {
+ joy->pJoystick.os->cache_axes[i] = (float)d;
+ }
+ break;
+ }
+ }
+ else if (page == HUP_BUTTON)
+ {
+ if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
+ {
+ if (d)
+ joy->pJoystick.os->cache_buttons |= (1 << ( usage - 1 ));
+ else
+ joy->pJoystick.os->cache_buttons &= ~(1 << ( usage - 1 ));
+ }
+ }
+ }
+ }
+# ifdef HAVE_ERRNO_H
+ if ( len < 0 && errno != EAGAIN )
+# else
+ if ( len < 0 )
+# endif
+ {
+ perror( joy->pJoystick.os->fname );
+ joy->error = 1;
+ }
+ if ( buttons != NULL ) *buttons = joy->pJoystick.os->cache_buttons;
+ if ( axes != NULL )
+ memcpy ( axes, joy->pJoystick.os->cache_axes, sizeof(float) * joy->num_axes );
+# endif
+#endif
+
+#ifdef JS_NEW
+
+ while ( 1 )
+ {
+ status = read ( joy->pJoystick.fd, &joy->pJoystick.js, sizeof(struct js_event) );
+
+ if ( status != sizeof( struct js_event ) )
+ {
+# ifdef HAVE_ERRNO_H
+ if ( errno == EAGAIN )
+ {
+ /* Use the old values */
+ if ( buttons )
+ *buttons = joy->pJoystick.tmp_buttons;
+ if ( axes )
+ memcpy( axes, joy->pJoystick.tmp_axes,
+ sizeof( float ) * joy->num_axes );
+ return;
+ }
+# endif
+
+ fgWarning ( "%s", joy->pJoystick.fname );
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ switch ( joy->pJoystick.js.type & ~JS_EVENT_INIT )
+ {
+ case JS_EVENT_BUTTON:
+ if( joy->pJoystick.js.value == 0 ) /* clear the flag */
+ joy->pJoystick.tmp_buttons &= ~( 1 << joy->pJoystick.js.number );
+ else
+ joy->pJoystick.tmp_buttons |= ( 1 << joy->pJoystick.js.number );
+ break;
+
+ case JS_EVENT_AXIS:
+ if ( joy->pJoystick.js.number < joy->num_axes )
+ {
+ joy->pJoystick.tmp_axes[ joy->pJoystick.js.number ] = ( float )joy->pJoystick.js.value;
+
+ if( axes )
+ memcpy( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes );
+ }
+ break;
+
+ default:
+ fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" );
+
+ /* use the old values */
+
+ if ( buttons != NULL ) *buttons = joy->pJoystick.tmp_buttons;
+ if ( axes != NULL )
+ memcpy ( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes );
+
+ return;
+ }
+
+ if( buttons )
+ *buttons = joy->pJoystick.tmp_buttons;
+ }
+#else
+
+ status = read( joy->pJoystick.fd, &joy->pJoystick.js, JS_RETURN );
+
+ if ( status != JS_RETURN )
+ {
+ fgWarning( "%s", joy->pJoystick.fname );
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ if ( buttons )
+# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
+ *buttons = ( joy->pJoystick.js.b1 ? 1 : 0 ) | ( joy->pJoystick.js.b2 ? 2 : 0 ); /* XXX Should not be here -- BSD is handled earlier */
+# else
+ *buttons = joy->pJoystick.js.buttons;
+# endif
+
+ if ( axes )
+ {
+ axes[ 0 ] = (float) joy->pJoystick.js.x;
+ axes[ 1 ] = (float) joy->pJoystick.js.y;
+ }
+#endif
+}
+
+
+void fgPlatformJoystickOpen( SFG_Joystick* joy )
+{
+#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
+ int i = 0;
+ char *cp;
+#endif
+#ifdef JS_NEW
+ unsigned char u;
+ int i=0;
+#else
+# if defined( __linux__ ) || TARGET_HOST_SOLARIS
+ int i = 0;
+ int counter = 0;
+# endif
+#endif
+
+#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ joy->pJoystick.os->cache_axes[ i ] = 0.0f;
+
+ joy->pJoystick.os->cache_buttons = 0;
+
+ joy->pJoystick.os->fd = open( joy->pJoystick.os->fname, O_RDONLY | O_NONBLOCK);
+
+#ifdef HAVE_ERRNO_H
+ if( joy->pJoystick.os->fd < 0 && errno == EACCES )
+ fgWarning ( "%s exists but is not readable by you", joy->pJoystick.os->fname );
+#endif
+
+ joy->error =( joy->pJoystick.os->fd < 0 );
+
+ if( joy->error )
+ return;
+
+ joy->num_axes = 0;
+ joy->num_buttons = 0;
+ if( joy->pJoystick.os->is_analog )
+ {
+ FILE *joyfile;
+ char joyfname[ 1024 ];
+ int noargs, in_no_axes;
+
+ float axes [ _JS_MAX_AXES ];
+ int buttons[ _JS_MAX_AXES ];
+
+ joy->num_axes = 2;
+ joy->num_buttons = 32;
+
+ fghJoystickRawRead( joy, buttons, axes );
+ joy->error = axes[ 0 ] < -1000000000.0f;
+ if( joy->error )
+ return;
+
+ snprintf( joyfname, sizeof(joyfname), "%s/.joy%drc", getenv( "HOME" ), joy->id );
+
+ joyfile = fopen( joyfname, "r" );
+ joy->error =( joyfile == NULL );
+ if( joy->error )
+ return;
+
+ noargs = fscanf( joyfile, "%d%f%f%f%f%f%f", &in_no_axes,
+ &joy->min[ 0 ], &joy->center[ 0 ], &joy->max[ 0 ],
+ &joy->min[ 1 ], &joy->center[ 1 ], &joy->max[ 1 ] );
+ joy->error = noargs != 7 || in_no_axes != _JS_MAX_AXES;
+ fclose( joyfile );
+ if( joy->error )
+ return;
+
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ {
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate [ i ] = 1.0f;
+ }
+
+ return; /* End of analog code */
+ }
+
+# ifdef HAVE_USB_JS
+ if( ! fghJoystickInitializeHID( joy->pJoystick.os, &joy->num_axes,
+ &joy->num_buttons ) )
+ {
+ close( joy->pJoystick.os->fd );
+ joy->error = GL_TRUE;
+ return;
+ }
+
+ cp = strrchr( joy->pJoystick.os->fname, '/' );
+ if( cp )
+ {
+ if( fghJoystickFindUSBdev( &cp[1], joy->name, sizeof( joy->name ) ) ==
+ 0 )
+ strcpy( joy->name, &cp[1] );
+ }
+
+ if( joy->num_axes > _JS_MAX_AXES )
+ joy->num_axes = _JS_MAX_AXES;
+
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ {
+ /* We really should get this from the HID, but that data seems
+ * to be quite unreliable for analog-to-USB converters. Punt for
+ * now.
+ */
+ if( joy->pJoystick.os->axes_usage[ i ] == HUG_HAT_SWITCH )
+ {
+ joy->max [ i ] = 1.0f;
+ joy->center[ i ] = 0.0f;
+ joy->min [ i ] = -1.0f;
+ }
+ else
+ {
+ joy->max [ i ] = 255.0f;
+ joy->center[ i ] = 127.0f;
+ joy->min [ i ] = 0.0f;
+ }
+
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate[ i ] = 1.0f;
+ }
+# endif
+#endif
+
+#if defined( __linux__ ) || TARGET_HOST_SOLARIS
+ /* Default for older Linux systems. */
+ joy->num_axes = 2;
+ joy->num_buttons = 32;
+
+# ifdef JS_NEW
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ joy->pJoystick.tmp_axes[ i ] = 0.0f;
+
+ joy->pJoystick.tmp_buttons = 0;
+# endif
+
+ joy->pJoystick.fd = open( joy->pJoystick.fname, O_RDONLY );
+
+ joy->error =( joy->pJoystick.fd < 0 );
+
+ if( joy->error )
+ return;
+
+ /* Set the correct number of axes for the linux driver */
+# ifdef JS_NEW
+ /* Melchior Franz's fixes for big-endian Linuxes since writing
+ * to the upper byte of an uninitialized word doesn't work.
+ * 9 April 2003
+ */
+ ioctl( joy->pJoystick.fd, JSIOCGAXES, &u );
+ joy->num_axes = u;
+ ioctl( joy->pJoystick.fd, JSIOCGBUTTONS, &u );
+ joy->num_buttons = u;
+ ioctl( joy->pJoystick.fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name );
+ fcntl( joy->pJoystick.fd, F_SETFL, O_NONBLOCK );
+# endif
+
+ /*
+ * The Linux driver seems to return 512 for all axes
+ * when no stick is present - but there is a chance
+ * that could happen by accident - so it's gotta happen
+ * on both axes for at least 100 attempts.
+ *
+ * PWO: shouldn't be that done somehow wiser on the kernel level?
+ */
+# ifndef JS_NEW
+ counter = 0;
+
+ do
+ {
+ fghJoystickRawRead( joy, NULL, joy->center );
+ counter++;
+ } while( !joy->error &&
+ counter < 100 &&
+ joy->center[ 0 ] == 512.0f &&
+ joy->center[ 1 ] == 512.0f );
+
+ if ( counter >= 100 )
+ joy->error = GL_TRUE;
+# endif
+
+ for( i = 0; i < _JS_MAX_AXES; i++ )
+ {
+# ifdef JS_NEW
+ joy->max [ i ] = 32767.0f;
+ joy->center[ i ] = 0.0f;
+ joy->min [ i ] = -32767.0f;
+# else
+ joy->max[ i ] = joy->center[ i ] * 2.0f;
+ joy->min[ i ] = 0.0f;
+# endif
+ joy->dead_band[ i ] = 0.0f;
+ joy->saturate [ i ] = 1.0f;
+ }
+#endif
+}
+
+
+void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )
+{
+#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
+ fgJoystick[ ident ]->id = ident;
+ fgJoystick[ ident ]->error = GL_FALSE;
+
+ fgJoystick[ ident ]->pJoystick.os = calloc( 1, sizeof( struct os_specific_s ) );
+ memset( fgJoystick[ ident ]->pJoystick.os, 0, sizeof( struct os_specific_s ) );
+ if( ident < USB_IDENT_OFFSET )
+ fgJoystick[ ident ]->pJoystick.os->is_analog = 1;
+ if( fgJoystick[ ident ]->pJoystick.os->is_analog )
+ snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", AJSDEV, ident );
+ else
+ snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", UHIDDEV,
+ ident - USB_IDENT_OFFSET );
+#elif defined( __linux__ )
+ fgJoystick[ ident ]->id = ident;
+ fgJoystick[ ident ]->error = GL_FALSE;
+
+ snprintf( fgJoystick[ident]->pJoystick.fname, sizeof(fgJoystick[ident]->pJoystick.fname), "/dev/input/js%d", ident );
+
+ if( access( fgJoystick[ ident ]->pJoystick.fname, F_OK ) != 0 )
+ snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident );
+#endif
+}
+
+
+void fgPlatformJoystickClose ( int ident )
+{
+#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
+ if( fgJoystick[ident]->pJoystick.os )
+ {
+ if( ! fgJoystick[ ident ]->error )
+ close( fgJoystick[ ident ]->pJoystick.os->fd );
+#ifdef HAVE_USB_JS
+ if( fgJoystick[ ident ]->pJoystick.os->hids )
+ free (fgJoystick[ ident ]->pJoystick.os->hids);
+ if( fgJoystick[ ident ]->pJoystick.os->hid_data_buf )
+ free( fgJoystick[ ident ]->pJoystick.os->hid_data_buf );
+#endif
+ free( fgJoystick[ident]->pJoystick.os );
+ }
+#endif
+
+ if( ! fgJoystick[ident]->error )
+ close( fgJoystick[ ident ]->pJoystick.fd );
+}
+
--- /dev/null
+/*
+ * freeglut_main_x11.c
+ *
+ * The X11-specific windows message processing methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+#ifdef HAVE_ERRNO_H
+# include <errno.h>
+#endif
+#include <stdarg.h>
+#ifdef HAVE_VFPRINTF
+# define VFPRINTF(s,f,a) vfprintf((s),(f),(a))
+#elif defined(HAVE__DOPRNT)
+# define VFPRINTF(s,f,a) _doprnt((f),(a),(s))
+#else
+# define VFPRINTF(s,f,a)
+#endif
+
+/*
+ * Try to get the maximum value allowed for ints, falling back to the minimum
+ * guaranteed by ISO C99 if there is no suitable header.
+ */
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef INT_MAX
+# define INT_MAX 32767
+#endif
+
+#ifndef MIN
+# define MIN(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * There are some issues concerning window redrawing under X11, and maybe
+ * some events are not handled. The Win32 version lacks some more features,
+ * but seems acceptable for not demanding purposes.
+ *
+ * Need to investigate why the X11 version breaks out with an error when
+ * closing a window (using the window manager, not glutDestroyWindow)...
+ */
+
+
+/*
+ * Handle a window configuration change. When no reshape
+ * callback is hooked, the viewport size is updated to
+ * match the new window size.
+ */
+void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
+{
+ XResizeWindow( fgDisplay.pDisplay.Display, window->Window.Handle,
+ width, height );
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+
+/*
+ * A static helper function to execute display callback for a window
+ */
+void fgPlatformDisplayWindow ( SFG_Window *window )
+{
+ fghRedrawWindow ( window ) ;
+}
+
+
+fg_time_t fgPlatformSystemTime ( void )
+{
+#ifdef CLOCK_MONOTONIC
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return now.tv_nsec/1000000 + now.tv_sec*1000;
+#elif defined(HAVE_GETTIMEOFDAY)
+ struct timeval now;
+ gettimeofday( &now, NULL );
+ return now.tv_usec/1000 + now.tv_sec*1000;
+#endif
+}
+
+/*
+ * Does the magic required to relinquish the CPU until something interesting
+ * happens.
+ */
+
+void fgPlatformSleepForEvents( fg_time_t msec )
+{
+ /*
+ * Possibly due to aggressive use of XFlush() and friends,
+ * 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 the event-reading loop, in any case, so we
+ * need to allow that we may have an empty socket but non-
+ * empty event queue.
+ */
+ if( ! XPending( fgDisplay.pDisplay.Display ) )
+ {
+ fd_set fdset;
+ int err;
+ int socket;
+ struct timeval wait;
+
+ socket = ConnectionNumber( fgDisplay.pDisplay.Display );
+ FD_ZERO( &fdset );
+ FD_SET( socket, &fdset );
+ wait.tv_sec = msec / 1000;
+ wait.tv_usec = (msec % 1000) * 1000;
+ err = select( socket+1, &fdset, NULL, NULL, &wait );
+
+#ifdef HAVE_ERRNO_H
+ if( ( -1 == err ) && ( errno != EINTR ) )
+ fgWarning ( "freeglut select() error: %d", errno );
+#endif
+ }
+}
+
+
+/*
+ * Returns GLUT modifier mask for the state field of an X11 event.
+ */
+int fgPlatformGetModifiers( int state )
+{
+ int ret = 0;
+
+ if( state & ( ShiftMask | LockMask ) )
+ ret |= GLUT_ACTIVE_SHIFT;
+ if( state & ControlMask )
+ ret |= GLUT_ACTIVE_CTRL;
+ if( state & Mod1Mask )
+ ret |= GLUT_ACTIVE_ALT;
+
+ return ret;
+}
+
+static const char* fghTypeToString( int type )
+{
+ switch( type ) {
+ case KeyPress: return "KeyPress";
+ case KeyRelease: return "KeyRelease";
+ case ButtonPress: return "ButtonPress";
+ case ButtonRelease: return "ButtonRelease";
+ case MotionNotify: return "MotionNotify";
+ case EnterNotify: return "EnterNotify";
+ case LeaveNotify: return "LeaveNotify";
+ case FocusIn: return "FocusIn";
+ case FocusOut: return "FocusOut";
+ case KeymapNotify: return "KeymapNotify";
+ case Expose: return "Expose";
+ case GraphicsExpose: return "GraphicsExpose";
+ case NoExpose: return "NoExpose";
+ case VisibilityNotify: return "VisibilityNotify";
+ case CreateNotify: return "CreateNotify";
+ case DestroyNotify: return "DestroyNotify";
+ case UnmapNotify: return "UnmapNotify";
+ case MapNotify: return "MapNotify";
+ case MapRequest: return "MapRequest";
+ case ReparentNotify: return "ReparentNotify";
+ case ConfigureNotify: return "ConfigureNotify";
+ case ConfigureRequest: return "ConfigureRequest";
+ case GravityNotify: return "GravityNotify";
+ case ResizeRequest: return "ResizeRequest";
+ case CirculateNotify: return "CirculateNotify";
+ case CirculateRequest: return "CirculateRequest";
+ case PropertyNotify: return "PropertyNotify";
+ case SelectionClear: return "SelectionClear";
+ case SelectionRequest: return "SelectionRequest";
+ case SelectionNotify: return "SelectionNotify";
+ case ColormapNotify: return "ColormapNotify";
+ case ClientMessage: return "ClientMessage";
+ case MappingNotify: return "MappingNotify";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghBoolToString( Bool b )
+{
+ return b == False ? "False" : "True";
+}
+
+static const char* fghNotifyHintToString( char is_hint )
+{
+ switch( is_hint ) {
+ case NotifyNormal: return "NotifyNormal";
+ case NotifyHint: return "NotifyHint";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghNotifyModeToString( int mode )
+{
+ switch( mode ) {
+ case NotifyNormal: return "NotifyNormal";
+ case NotifyGrab: return "NotifyGrab";
+ case NotifyUngrab: return "NotifyUngrab";
+ case NotifyWhileGrabbed: return "NotifyWhileGrabbed";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghNotifyDetailToString( int detail )
+{
+ switch( detail ) {
+ case NotifyAncestor: return "NotifyAncestor";
+ case NotifyVirtual: return "NotifyVirtual";
+ case NotifyInferior: return "NotifyInferior";
+ case NotifyNonlinear: return "NotifyNonlinear";
+ case NotifyNonlinearVirtual: return "NotifyNonlinearVirtual";
+ case NotifyPointer: return "NotifyPointer";
+ case NotifyPointerRoot: return "NotifyPointerRoot";
+ case NotifyDetailNone: return "NotifyDetailNone";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghVisibilityToString( int state ) {
+ switch( state ) {
+ case VisibilityUnobscured: return "VisibilityUnobscured";
+ case VisibilityPartiallyObscured: return "VisibilityPartiallyObscured";
+ case VisibilityFullyObscured: return "VisibilityFullyObscured";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghConfigureDetailToString( int detail )
+{
+ switch( detail ) {
+ case Above: return "Above";
+ case Below: return "Below";
+ case TopIf: return "TopIf";
+ case BottomIf: return "BottomIf";
+ case Opposite: return "Opposite";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghPlaceToString( int place )
+{
+ switch( place ) {
+ case PlaceOnTop: return "PlaceOnTop";
+ case PlaceOnBottom: return "PlaceOnBottom";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghMappingRequestToString( int request )
+{
+ switch( request ) {
+ case MappingModifier: return "MappingModifier";
+ case MappingKeyboard: return "MappingKeyboard";
+ case MappingPointer: return "MappingPointer";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghPropertyStateToString( int state )
+{
+ switch( state ) {
+ case PropertyNewValue: return "PropertyNewValue";
+ case PropertyDelete: return "PropertyDelete";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char* fghColormapStateToString( int state )
+{
+ switch( state ) {
+ case ColormapUninstalled: return "ColormapUninstalled";
+ case ColormapInstalled: return "ColormapInstalled";
+ default: return "UNKNOWN";
+ }
+}
+
+static void fghPrintEvent( XEvent *event )
+{
+ switch( event->type ) {
+
+ case KeyPress:
+ case KeyRelease: {
+ XKeyEvent *e = &event->xkey;
+ fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
+ "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, "
+ "keycode=%u, same_screen=%s", fghTypeToString( e->type ),
+ e->window, e->root, e->subwindow, (unsigned long)e->time,
+ e->x, e->y, e->x_root, e->y_root, e->state, e->keycode,
+ fghBoolToString( e->same_screen ) );
+ break;
+ }
+
+ case ButtonPress:
+ case ButtonRelease: {
+ XButtonEvent *e = &event->xbutton;
+ fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
+ "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, "
+ "button=%u, same_screen=%d", fghTypeToString( e->type ),
+ e->window, e->root, e->subwindow, (unsigned long)e->time,
+ e->x, e->y, e->x_root, e->y_root, e->state, e->button,
+ fghBoolToString( e->same_screen ) );
+ break;
+ }
+
+ case MotionNotify: {
+ XMotionEvent *e = &event->xmotion;
+ fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
+ "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, "
+ "is_hint=%s, same_screen=%d", fghTypeToString( e->type ),
+ e->window, e->root, e->subwindow, (unsigned long)e->time,
+ e->x, e->y, e->x_root, e->y_root, e->state,
+ fghNotifyHintToString( e->is_hint ),
+ fghBoolToString( e->same_screen ) );
+ break;
+ }
+
+ case EnterNotify:
+ case LeaveNotify: {
+ XCrossingEvent *e = &event->xcrossing;
+ fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
+ "(x,y)=(%d,%d), mode=%s, detail=%s, same_screen=%d, "
+ "focus=%d, state=0x%x", fghTypeToString( e->type ),
+ e->window, e->root, e->subwindow, (unsigned long)e->time,
+ e->x, e->y, fghNotifyModeToString( e->mode ),
+ fghNotifyDetailToString( e->detail ), (int)e->same_screen,
+ (int)e->focus, e->state );
+ break;
+ }
+
+ case FocusIn:
+ case FocusOut: {
+ XFocusChangeEvent *e = &event->xfocus;
+ fgWarning( "%s: window=0x%x, mode=%s, detail=%s",
+ fghTypeToString( e->type ), e->window,
+ fghNotifyModeToString( e->mode ),
+ fghNotifyDetailToString( e->detail ) );
+ break;
+ }
+
+ case KeymapNotify: {
+ XKeymapEvent *e = &event->xkeymap;
+ char buf[32 * 2 + 1];
+ int i;
+ for ( i = 0; i < 32; i++ ) {
+ snprintf( &buf[ i * 2 ], sizeof( buf ) - i * 2,
+ "%02x", e->key_vector[ i ] );
+ }
+ buf[ i ] = '\0';
+ fgWarning( "%s: window=0x%x, %s", fghTypeToString( e->type ), e->window,
+ buf );
+ break;
+ }
+
+ case Expose: {
+ XExposeEvent *e = &event->xexpose;
+ fgWarning( "%s: window=0x%x, (x,y)=(%d,%d), (width,height)=(%d,%d), "
+ "count=%d", fghTypeToString( e->type ), e->window, e->x,
+ e->y, e->width, e->height, e->count );
+ break;
+ }
+
+ case GraphicsExpose: {
+ XGraphicsExposeEvent *e = &event->xgraphicsexpose;
+ fgWarning( "%s: drawable=0x%x, (x,y)=(%d,%d), (width,height)=(%d,%d), "
+ "count=%d, (major_code,minor_code)=(%d,%d)",
+ fghTypeToString( e->type ), e->drawable, e->x, e->y,
+ e->width, e->height, e->count, e->major_code,
+ e->minor_code );
+ break;
+ }
+
+ case NoExpose: {
+ XNoExposeEvent *e = &event->xnoexpose;
+ fgWarning( "%s: drawable=0x%x, (major_code,minor_code)=(%d,%d)",
+ fghTypeToString( e->type ), e->drawable, e->major_code,
+ e->minor_code );
+ break;
+ }
+
+ case VisibilityNotify: {
+ XVisibilityEvent *e = &event->xvisibility;
+ fgWarning( "%s: window=0x%x, state=%s", fghTypeToString( e->type ),
+ e->window, fghVisibilityToString( e->state) );
+ break;
+ }
+
+ case CreateNotify: {
+ XCreateWindowEvent *e = &event->xcreatewindow;
+ fgWarning( "%s: (x,y)=(%d,%d), (width,height)=(%d,%d), border_width=%d, "
+ "window=0x%x, override_redirect=%s",
+ fghTypeToString( e->type ), e->x, e->y, e->width, e->height,
+ e->border_width, e->window,
+ fghBoolToString( e->override_redirect ) );
+ break;
+ }
+
+ case DestroyNotify: {
+ XDestroyWindowEvent *e = &event->xdestroywindow;
+ fgWarning( "%s: event=0x%x, window=0x%x",
+ fghTypeToString( e->type ), e->event, e->window );
+ break;
+ }
+
+ case UnmapNotify: {
+ XUnmapEvent *e = &event->xunmap;
+ fgWarning( "%s: event=0x%x, window=0x%x, from_configure=%s",
+ fghTypeToString( e->type ), e->event, e->window,
+ fghBoolToString( e->from_configure ) );
+ break;
+ }
+
+ case MapNotify: {
+ XMapEvent *e = &event->xmap;
+ fgWarning( "%s: event=0x%x, window=0x%x, override_redirect=%s",
+ fghTypeToString( e->type ), e->event, e->window,
+ fghBoolToString( e->override_redirect ) );
+ break;
+ }
+
+ case MapRequest: {
+ XMapRequestEvent *e = &event->xmaprequest;
+ fgWarning( "%s: parent=0x%x, window=0x%x",
+ fghTypeToString( event->type ), e->parent, e->window );
+ break;
+ }
+
+ case ReparentNotify: {
+ XReparentEvent *e = &event->xreparent;
+ fgWarning( "%s: event=0x%x, window=0x%x, parent=0x%x, (x,y)=(%d,%d), "
+ "override_redirect=%s", fghTypeToString( e->type ),
+ e->event, e->window, e->parent, e->x, e->y,
+ fghBoolToString( e->override_redirect ) );
+ break;
+ }
+
+ case ConfigureNotify: {
+ XConfigureEvent *e = &event->xconfigure;
+ fgWarning( "%s: event=0x%x, window=0x%x, (x,y)=(%d,%d), "
+ "(width,height)=(%d,%d), border_width=%d, above=0x%x, "
+ "override_redirect=%s", fghTypeToString( e->type ), e->event,
+ e->window, e->x, e->y, e->width, e->height, e->border_width,
+ e->above, fghBoolToString( e->override_redirect ) );
+ break;
+ }
+
+ case ConfigureRequest: {
+ XConfigureRequestEvent *e = &event->xconfigurerequest;
+ fgWarning( "%s: parent=0x%x, window=0x%x, (x,y)=(%d,%d), "
+ "(width,height)=(%d,%d), border_width=%d, above=0x%x, "
+ "detail=%s, value_mask=%lx", fghTypeToString( e->type ),
+ e->parent, e->window, e->x, e->y, e->width, e->height,
+ e->border_width, e->above,
+ fghConfigureDetailToString( e->detail ), e->value_mask );
+ break;
+ }
+
+ case GravityNotify: {
+ XGravityEvent *e = &event->xgravity;
+ fgWarning( "%s: event=0x%x, window=0x%x, (x,y)=(%d,%d)",
+ fghTypeToString( e->type ), e->event, e->window, e->x, e->y );
+ break;
+ }
+
+ case ResizeRequest: {
+ XResizeRequestEvent *e = &event->xresizerequest;
+ fgWarning( "%s: window=0x%x, (width,height)=(%d,%d)",
+ fghTypeToString( e->type ), e->window, e->width, e->height );
+ break;
+ }
+
+ case CirculateNotify: {
+ XCirculateEvent *e = &event->xcirculate;
+ fgWarning( "%s: event=0x%x, window=0x%x, place=%s",
+ fghTypeToString( e->type ), e->event, e->window,
+ fghPlaceToString( e->place ) );
+ break;
+ }
+
+ case CirculateRequest: {
+ XCirculateRequestEvent *e = &event->xcirculaterequest;
+ fgWarning( "%s: parent=0x%x, window=0x%x, place=%s",
+ fghTypeToString( e->type ), e->parent, e->window,
+ fghPlaceToString( e->place ) );
+ break;
+ }
+
+ case PropertyNotify: {
+ XPropertyEvent *e = &event->xproperty;
+ fgWarning( "%s: window=0x%x, atom=%lu, time=%lu, state=%s",
+ fghTypeToString( e->type ), e->window,
+ (unsigned long)e->atom, (unsigned long)e->time,
+ fghPropertyStateToString( e->state ) );
+ break;
+ }
+
+ case SelectionClear: {
+ XSelectionClearEvent *e = &event->xselectionclear;
+ fgWarning( "%s: window=0x%x, selection=%lu, time=%lu",
+ fghTypeToString( e->type ), e->window,
+ (unsigned long)e->selection, (unsigned long)e->time );
+ break;
+ }
+
+ case SelectionRequest: {
+ XSelectionRequestEvent *e = &event->xselectionrequest;
+ fgWarning( "%s: owner=0x%x, requestor=0x%x, selection=0x%x, "
+ "target=0x%x, property=%lu, time=%lu",
+ fghTypeToString( e->type ), e->owner, e->requestor,
+ (unsigned long)e->selection, (unsigned long)e->target,
+ (unsigned long)e->property, (unsigned long)e->time );
+ break;
+ }
+
+ case SelectionNotify: {
+ XSelectionEvent *e = &event->xselection;
+ fgWarning( "%s: requestor=0x%x, selection=0x%x, target=0x%x, "
+ "property=%lu, time=%lu", fghTypeToString( e->type ),
+ e->requestor, (unsigned long)e->selection,
+ (unsigned long)e->target, (unsigned long)e->property,
+ (unsigned long)e->time );
+ break;
+ }
+
+ case ColormapNotify: {
+ XColormapEvent *e = &event->xcolormap;
+ fgWarning( "%s: window=0x%x, colormap=%lu, new=%s, state=%s",
+ fghTypeToString( e->type ), e->window,
+ (unsigned long)e->colormap, fghBoolToString( e->new ),
+ fghColormapStateToString( e->state ) );
+ break;
+ }
+
+ case ClientMessage: {
+ XClientMessageEvent *e = &event->xclient;
+ char buf[ 61 ];
+ char* p = buf;
+ char* end = buf + sizeof( buf );
+ int i;
+ switch( e->format ) {
+ case 8:
+ for ( i = 0; i < 20; i++, p += 3 ) {
+ snprintf( p, end - p, " %02x", e->data.b[ i ] );
+ }
+ break;
+ case 16:
+ for ( i = 0; i < 10; i++, p += 5 ) {
+ snprintf( p, end - p, " %04x", e->data.s[ i ] );
+ }
+ break;
+ case 32:
+ for ( i = 0; i < 5; i++, p += 9 ) {
+ snprintf( p, end - p, " %08lx", e->data.l[ i ] );
+ }
+ break;
+ }
+ *p = '\0';
+ fgWarning( "%s: window=0x%x, message_type=%lu, format=%d, data=(%s )",
+ fghTypeToString( e->type ), e->window,
+ (unsigned long)e->message_type, e->format, buf );
+ break;
+ }
+
+ case MappingNotify: {
+ XMappingEvent *e = &event->xmapping;
+ fgWarning( "%s: window=0x%x, request=%s, first_keycode=%d, count=%d",
+ fghTypeToString( e->type ), e->window,
+ fghMappingRequestToString( e->request ), e->first_keycode,
+ e->count );
+ break;
+ }
+
+ default: {
+ fgWarning( "%s", fghTypeToString( event->type ) );
+ break;
+ }
+ }
+}
+
+
+void fgPlatformProcessSingleEvent ( void )
+{
+ SFG_Window* window;
+ XEvent event;
+
+ /* This code was repeated constantly, so here it goes into a definition: */
+#define GETWINDOW(a) \
+ window = fgWindowByHandle( event.a.window ); \
+ if( window == NULL ) \
+ break;
+
+#define GETMOUSE(a) \
+ window->State.MouseX = event.a.x; \
+ window->State.MouseY = event.a.y;
+
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
+
+ while( XPending( fgDisplay.pDisplay.Display ) )
+ {
+ XNextEvent( fgDisplay.pDisplay.Display, &event );
+#if _DEBUG
+ fghPrintEvent( &event );
+#endif
+
+ switch( event.type )
+ {
+ case ClientMessage:
+ if(fgIsSpaceballXEvent(&event)) {
+ fgSpaceballHandleXEvent(&event);
+ break;
+ }
+ /* Destroy the window when the WM_DELETE_WINDOW message arrives */
+ if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.pDisplay.DeleteWindow )
+ {
+ GETWINDOW( xclient );
+
+ fgDestroyWindow ( window );
+
+ if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
+ {
+ fgDeinitialize( );
+ exit( 0 );
+ }
+ else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
+ fgState.ExecState = GLUT_EXEC_STATE_STOP;
+
+ return;
+ }
+ break;
+
+ /*
+ * CreateNotify causes a configure-event so that sub-windows are
+ * handled compatibly with GLUT. Otherwise, your sub-windows
+ * (in freeglut only) will not get an initial reshape event,
+ * which can break things.
+ *
+ * GLUT presumably does this because it generally tries to treat
+ * sub-windows the same as windows.
+ */
+ case CreateNotify:
+ case ConfigureNotify:
+ {
+ int width, height;
+ if( event.type == CreateNotify ) {
+ GETWINDOW( xcreatewindow );
+ width = event.xcreatewindow.width;
+ height = event.xcreatewindow.height;
+ } else {
+ GETWINDOW( xconfigure );
+ width = event.xconfigure.width;
+ height = event.xconfigure.height;
+ }
+
+ if( ( width != window->State.pWState.OldWidth ) ||
+ ( height != window->State.pWState.OldHeight ) )
+ {
+ SFG_Window *current_window = fgStructure.CurrentWindow;
+
+ window->State.pWState.OldWidth = width;
+ window->State.pWState.OldHeight = height;
+ if( FETCH_WCB( *window, Reshape ) )
+ INVOKE_WCB( *window, Reshape, ( width, height ) );
+ else
+ {
+ fgSetWindow( window );
+ glViewport( 0, 0, width, height );
+ }
+ glutPostRedisplay( );
+ if( window->IsMenu )
+ fgSetWindow( current_window );
+ }
+ }
+ break;
+
+ case DestroyNotify:
+ /*
+ * This is sent to confirm the XDestroyWindow call.
+ *
+ * XXX WHY is this commented out? Should we re-enable it?
+ */
+ /* fgAddToWindowDestroyList ( window ); */
+ break;
+
+ case Expose:
+ /*
+ * We are too dumb to process partial exposes...
+ *
+ * XXX Well, we could do it. However, it seems to only
+ * XXX be potentially useful for single-buffered (since
+ * XXX double-buffered does not respect viewport when we
+ * XXX do a buffer-swap).
+ *
+ */
+ if( event.xexpose.count == 0 )
+ {
+ GETWINDOW( xexpose );
+ window->State.Redisplay = GL_TRUE;
+ }
+ break;
+
+ case MapNotify:
+ break;
+
+ case UnmapNotify:
+ /* We get this when iconifying a window. */
+ GETWINDOW( xunmap );
+ INVOKE_WCB( *window, WindowStatus, ( GLUT_HIDDEN ) );
+ window->State.Visible = GL_FALSE;
+ break;
+
+ case MappingNotify:
+ /*
+ * Have the client's keyboard knowledge updated (xlib.ps,
+ * page 206, says that's a good thing to do)
+ */
+ XRefreshKeyboardMapping( (XMappingEvent *) &event );
+ break;
+
+ case VisibilityNotify:
+ {
+ /*
+ * Sending this event, the X server can notify us that the window
+ * has just acquired one of the three possible visibility states:
+ * VisibilityUnobscured, VisibilityPartiallyObscured or
+ * VisibilityFullyObscured. Note that we DO NOT receive a
+ * VisibilityNotify event when iconifying a window, we only get an
+ * UnmapNotify then.
+ */
+ GETWINDOW( xvisibility );
+ switch( event.xvisibility.state )
+ {
+ case VisibilityUnobscured:
+ INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) );
+ window->State.Visible = GL_TRUE;
+ break;
+
+ case VisibilityPartiallyObscured:
+ INVOKE_WCB( *window, WindowStatus,
+ ( GLUT_PARTIALLY_RETAINED ) );
+ window->State.Visible = GL_TRUE;
+ break;
+
+ case VisibilityFullyObscured:
+ INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) );
+ window->State.Visible = GL_FALSE;
+ break;
+
+ default:
+ fgWarning( "Unknown X visibility state: %d",
+ event.xvisibility.state );
+ break;
+ }
+ }
+ break;
+
+ case EnterNotify:
+ case LeaveNotify:
+ GETWINDOW( xcrossing );
+ GETMOUSE( xcrossing );
+ if( ( event.type == LeaveNotify ) && window->IsMenu &&
+ window->ActiveMenu && window->ActiveMenu->IsActive )
+ fgUpdateMenuHighlight( window->ActiveMenu );
+
+ INVOKE_WCB( *window, Entry, ( ( EnterNotify == event.type ) ?
+ GLUT_ENTERED :
+ GLUT_LEFT ) );
+ break;
+
+ case MotionNotify:
+ {
+ GETWINDOW( xmotion );
+ GETMOUSE( xmotion );
+
+ if( window->ActiveMenu )
+ {
+ if( window == window->ActiveMenu->ParentWindow )
+ {
+ window->ActiveMenu->Window->State.MouseX =
+ event.xmotion.x_root - window->ActiveMenu->X;
+ window->ActiveMenu->Window->State.MouseY =
+ event.xmotion.y_root - window->ActiveMenu->Y;
+ }
+
+ fgUpdateMenuHighlight( window->ActiveMenu );
+
+ break;
+ }
+
+ /*
+ * XXX For more than 5 buttons, just check {event.xmotion.state},
+ * XXX rather than a host of bit-masks? Or maybe we need to
+ * XXX track ButtonPress/ButtonRelease events in our own
+ * XXX bit-mask?
+ */
+ fgState.Modifiers = fgPlatformGetModifiers( event.xmotion.state );
+ if ( event.xmotion.state & ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) ) {
+ INVOKE_WCB( *window, Motion, ( event.xmotion.x,
+ event.xmotion.y ) );
+ } else {
+ INVOKE_WCB( *window, Passive, ( event.xmotion.x,
+ event.xmotion.y ) );
+ }
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case ButtonRelease:
+ case ButtonPress:
+ {
+ GLboolean pressed = GL_TRUE;
+ int button;
+
+ if( event.type == ButtonRelease )
+ pressed = GL_FALSE ;
+
+ /*
+ * A mouse button has been pressed or released. Traditionally,
+ * break if the window was found within the freeglut structures.
+ */
+ GETWINDOW( xbutton );
+ GETMOUSE( xbutton );
+
+ /*
+ * An X button (at least in XFree86) is numbered from 1.
+ * A GLUT button is numbered from 0.
+ * Old GLUT passed through buttons other than just the first
+ * three, though it only gave symbolic names and official
+ * support to the first three.
+ */
+ button = event.xbutton.button - 1;
+
+ /*
+ * Do not execute the application's mouse callback if a menu
+ * is hooked to this button. In that case an appropriate
+ * private call should be generated.
+ */
+ if( fgCheckActiveMenu( window, button, pressed,
+ event.xbutton.x_root, event.xbutton.y_root ) )
+ break;
+
+ /*
+ * Check if there is a mouse or mouse wheel callback hooked to the
+ * window
+ */
+ if( ! FETCH_WCB( *window, Mouse ) &&
+ ! FETCH_WCB( *window, MouseWheel ) )
+ break;
+
+ fgState.Modifiers = fgPlatformGetModifiers( event.xbutton.state );
+
+ /* Finally execute the mouse or mouse wheel callback */
+ if( ( button < glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS ) ) || ( ! FETCH_WCB( *window, MouseWheel ) ) )
+ INVOKE_WCB( *window, Mouse, ( button,
+ pressed ? GLUT_DOWN : GLUT_UP,
+ event.xbutton.x,
+ event.xbutton.y )
+ );
+ else
+ {
+ /*
+ * Map 4 and 5 to wheel zero; EVEN to +1, ODD to -1
+ * " 6 and 7 " " one; ...
+ *
+ * XXX This *should* be behind some variables/macros,
+ * XXX since the order and numbering isn't certain
+ * XXX See XFree86 configuration docs (even back in the
+ * XXX 3.x days, and especially with 4.x).
+ *
+ * XXX Note that {button} has already been decremented
+ * XXX in mapping from X button numbering to GLUT.
+ *
+ * XXX Should add support for partial wheel turns as Windows does -- 5/27/11
+ */
+ int wheel_number = (button - glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS )) / 2;
+ int direction = -1;
+ if( button % 2 )
+ direction = 1;
+
+ if( pressed )
+ INVOKE_WCB( *window, MouseWheel, ( wheel_number,
+ direction,
+ event.xbutton.x,
+ event.xbutton.y )
+ );
+ }
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ break;
+
+ case KeyRelease:
+ case KeyPress:
+ {
+ FGCBKeyboard keyboard_cb;
+ FGCBSpecial special_cb;
+
+ GETWINDOW( xkey );
+ GETMOUSE( xkey );
+
+ /* Detect auto repeated keys, if configured globally or per-window */
+
+ if ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE )
+ {
+ if (event.type==KeyRelease)
+ {
+ /*
+ * Look at X11 keystate to detect repeat mode.
+ * While X11 says the key is actually held down, we'll ignore KeyRelease/KeyPress pairs.
+ */
+
+ char keys[32];
+ XQueryKeymap( fgDisplay.pDisplay.Display, keys ); /* Look at X11 keystate to detect repeat mode */
+
+ 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
+ window->State.KeyRepeating = GL_FALSE;
+
+ /* Cease processing this event if it is auto repeated */
+
+ if (window->State.KeyRepeating)
+ {
+ if (event.type == KeyPress) window->State.KeyRepeating = GL_FALSE;
+ break;
+ }
+
+ if( event.type == KeyPress )
+ {
+ keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard ));
+ special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special ));
+ }
+ else
+ {
+ keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp ));
+ special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp ));
+ }
+
+ /* Is there a keyboard/special callback hooked for this window? */
+ if( keyboard_cb || special_cb )
+ {
+ XComposeStatus composeStatus;
+ char asciiCode[ 32 ];
+ KeySym keySym;
+ int len;
+
+ /* Check for the ASCII/KeySym codes associated with the event: */
+ len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
+ &keySym, &composeStatus
+ );
+
+ /* GLUT API tells us to have two separate callbacks... */
+ if( len > 0 )
+ {
+ /* ...one for the ASCII translateable keypresses... */
+ if( keyboard_cb )
+ {
+ fgSetWindow( window );
+ fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
+ keyboard_cb( asciiCode[ 0 ],
+ event.xkey.x, event.xkey.y
+ );
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ }
+ else
+ {
+ int special = -1;
+
+ /*
+ * ...and one for all the others, which need to be
+ * translated to GLUT_KEY_Xs...
+ */
+ switch( keySym )
+ {
+ case XK_F1: special = GLUT_KEY_F1; break;
+ case XK_F2: special = GLUT_KEY_F2; break;
+ case XK_F3: special = GLUT_KEY_F3; break;
+ case XK_F4: special = GLUT_KEY_F4; break;
+ case XK_F5: special = GLUT_KEY_F5; break;
+ case XK_F6: special = GLUT_KEY_F6; break;
+ case XK_F7: special = GLUT_KEY_F7; break;
+ case XK_F8: special = GLUT_KEY_F8; break;
+ case XK_F9: special = GLUT_KEY_F9; break;
+ case XK_F10: special = GLUT_KEY_F10; break;
+ case XK_F11: special = GLUT_KEY_F11; break;
+ case XK_F12: special = GLUT_KEY_F12; break;
+
+ case XK_KP_Left:
+ case XK_Left: special = GLUT_KEY_LEFT; break;
+ case XK_KP_Right:
+ case XK_Right: special = GLUT_KEY_RIGHT; break;
+ case XK_KP_Up:
+ case XK_Up: special = GLUT_KEY_UP; break;
+ case XK_KP_Down:
+ case XK_Down: special = GLUT_KEY_DOWN; break;
+
+ case XK_KP_Prior:
+ case XK_Prior: special = GLUT_KEY_PAGE_UP; break;
+ case XK_KP_Next:
+ case XK_Next: special = GLUT_KEY_PAGE_DOWN; break;
+ case XK_KP_Home:
+ case XK_Home: special = GLUT_KEY_HOME; break;
+ case XK_KP_End:
+ case XK_End: special = GLUT_KEY_END; break;
+ case XK_KP_Insert:
+ case XK_Insert: special = GLUT_KEY_INSERT; break;
+
+ case XK_Num_Lock : special = GLUT_KEY_NUM_LOCK; break;
+ case XK_KP_Begin : special = GLUT_KEY_BEGIN; break;
+ case XK_KP_Delete: special = GLUT_KEY_DELETE; break;
+
+ case XK_Shift_L: special = GLUT_KEY_SHIFT_L; break;
+ case XK_Shift_R: special = GLUT_KEY_SHIFT_R; break;
+ case XK_Control_L: special = GLUT_KEY_CTRL_L; break;
+ case XK_Control_R: special = GLUT_KEY_CTRL_R; break;
+ case XK_Alt_L: special = GLUT_KEY_ALT_L; break;
+ case XK_Alt_R: special = GLUT_KEY_ALT_R; break;
+ }
+
+ /*
+ * Execute the callback (if one has been specified),
+ * given that the special code seems to be valid...
+ */
+ if( special_cb && (special != -1) )
+ {
+ fgSetWindow( window );
+ fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
+ special_cb( special, event.xkey.x, event.xkey.y );
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ }
+ }
+ }
+ break;
+
+ case ReparentNotify:
+ break; /* XXX Should disable this event */
+
+ /* Not handled */
+ case GravityNotify:
+ break;
+
+ default:
+ /* enter handling of Extension Events here */
+ #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+ fgHandleExtensionEvents( &event );
+ #endif
+ break;
+ }
+ }
+}
+
+
+void fgPlatformMainLoopPreliminaryWork ( void )
+{
+}
+
--- /dev/null
+/*
+ * freeglut_menu_x11.c
+ *
+ * Pull-down menu creation and handling.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Wed Feb 1, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+/*
+ * * Private function to get the virtual maximum screen extent
+ * */
+GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y )
+{
+ int wx, wy;
+ Window w;
+
+ XTranslateCoordinates(
+ fgDisplay.pDisplay.Display,
+ window->Window.Handle,
+ fgDisplay.pDisplay.RootWindow,
+ 0, 0, &wx, &wy, &w);
+
+ *x = fgState.GameModeSize.X + wx;
+ *y = fgState.GameModeSize.Y + wy;
+}
+
--- /dev/null
+/* Spaceball support for Linux.
+ * Written by John Tsiombikas <nuclear@member.fsf.org>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * This code supports 3Dconnexion's 6-dof space-whatever devices.
+ * It can communicate with either the proprietary 3Dconnexion daemon (3dxsrv)
+ * free spacenavd (http://spacenav.sourceforge.net), through the "standard"
+ * magellan X-based protocol.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+#include <X11/Xlib.h>
+
+extern int sball_initialized;
+
+enum {
+ SPNAV_EVENT_ANY, /* used by spnav_remove_events() */
+ SPNAV_EVENT_MOTION,
+ SPNAV_EVENT_BUTTON /* includes both press and release */
+};
+
+struct spnav_event_motion {
+ int type;
+ int x, y, z;
+ int rx, ry, rz;
+ unsigned int period;
+ int *data;
+};
+
+struct spnav_event_button {
+ int type;
+ int press;
+ int bnum;
+};
+
+typedef union spnav_event {
+ int type;
+ struct spnav_event_motion motion;
+ struct spnav_event_button button;
+} spnav_event;
+
+
+static int spnav_x11_open(Display *dpy, Window win);
+static int spnav_x11_window(Window win);
+static int spnav_x11_event(const XEvent *xev, spnav_event *event);
+static int spnav_close(void);
+static int spnav_fd(void);
+static int spnav_remove_events(int type);
+
+static SFG_Window *spnav_win;
+
+void fgPlatformInitializeSpaceball(void)
+{
+ Window w;
+
+ sball_initialized = 1;
+ if(!fgStructure.CurrentWindow)
+ {
+ sball_initialized = -1;
+ return;
+ }
+
+ w = fgStructure.CurrentWindow->Window.Handle;
+ if(spnav_x11_open(fgDisplay.pDisplay.Display, w) == -1)
+ {
+ sball_initialized = -1;
+ return;
+ }
+}
+
+void fgPlatformSpaceballClose(void)
+{
+ spnav_close();
+}
+
+int fgPlatformHasSpaceball(void)
+{
+ /* XXX this function should somehow query the driver if there's a device
+ * plugged in, as opposed to just checking if there's a driver to talk to.
+ */
+ return spnav_fd() == -1 ? 0 : 1;
+}
+
+int fgPlatformSpaceballNumButtons(void) {
+ return 2;
+}
+
+void fgPlatformSpaceballSetWindow(SFG_Window *window)
+{
+ if(spnav_win != window) {
+ spnav_x11_window(window->Window.Handle);
+ spnav_win = window;
+ }
+}
+
+int fgIsSpaceballXEvent(const XEvent *xev)
+{
+ spnav_event sev;
+
+ if(spnav_win != fgStructure.CurrentWindow) {
+ /* this will also initialize spaceball if needed (first call) */
+ fgSpaceballSetWindow(fgStructure.CurrentWindow);
+ }
+
+ if(sball_initialized != 1) {
+ return 0;
+ }
+
+ return spnav_x11_event(xev, &sev);
+}
+
+void fgSpaceballHandleXEvent(const XEvent *xev)
+{
+ spnav_event sev;
+
+ if(sball_initialized == 0) {
+ fgInitialiseSpaceball();
+ if(sball_initialized != 1) {
+ return;
+ }
+ }
+
+ if(spnav_x11_event(xev, &sev)) {
+ switch(sev.type) {
+ case SPNAV_EVENT_MOTION:
+ if(sev.motion.x | sev.motion.y | sev.motion.z) {
+ INVOKE_WCB(*spnav_win, SpaceMotion, (sev.motion.x, sev.motion.y, sev.motion.z));
+ }
+ if(sev.motion.rx | sev.motion.ry | sev.motion.rz) {
+ INVOKE_WCB(*spnav_win, SpaceRotation, (sev.motion.rx, sev.motion.ry, sev.motion.rz));
+ }
+ spnav_remove_events(SPNAV_EVENT_MOTION);
+ break;
+
+ case SPNAV_EVENT_BUTTON:
+ INVOKE_WCB(*spnav_win, SpaceButton, (sev.button.bnum, sev.button.press ? GLUT_DOWN : GLUT_UP));
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*
+The following code is part of libspnav, part of the spacenav project (spacenav.sf.net)
+Copyright (C) 2007-2009 John Tsiombikas <nuclear@member.fsf.org>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGE.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+static Window get_daemon_window(Display *dpy);
+static int catch_badwin(Display *dpy, XErrorEvent *err);
+
+static Display *dpy;
+static Window app_win;
+static Atom motion_event, button_press_event, button_release_event, command_event;
+
+enum {
+ CMD_APP_WINDOW = 27695,
+ CMD_APP_SENS
+};
+
+#define IS_OPEN dpy
+
+struct event_node {
+ spnav_event event;
+ struct event_node *next;
+};
+
+static int spnav_x11_open(Display *display, Window win)
+{
+ if(IS_OPEN) {
+ return -1;
+ }
+
+ dpy = display;
+
+ motion_event = XInternAtom(dpy, "MotionEvent", True);
+ button_press_event = XInternAtom(dpy, "ButtonPressEvent", True);
+ button_release_event = XInternAtom(dpy, "ButtonReleaseEvent", True);
+ command_event = XInternAtom(dpy, "CommandEvent", True);
+
+ if(!motion_event || !button_press_event || !button_release_event || !command_event) {
+ dpy = 0;
+ return -1; /* daemon not started */
+ }
+
+ if(spnav_x11_window(win) == -1) {
+ dpy = 0;
+ return -1; /* daemon not started */
+ }
+
+ app_win = win;
+ return 0;
+}
+
+static int spnav_close(void)
+{
+ if(dpy) {
+ spnav_x11_window(DefaultRootWindow(dpy));
+ app_win = 0;
+ dpy = 0;
+ return 0;
+ }
+ return -1;
+}
+
+static int spnav_x11_window(Window win)
+{
+ int (*prev_xerr_handler)(Display*, XErrorEvent*);
+ XEvent xev;
+ Window daemon_win;
+
+ if(!IS_OPEN) {
+ return -1;
+ }
+
+ if(!(daemon_win = get_daemon_window(dpy))) {
+ return -1;
+ }
+
+ prev_xerr_handler = XSetErrorHandler(catch_badwin);
+
+ xev.type = ClientMessage;
+ xev.xclient.send_event = False;
+ xev.xclient.display = dpy;
+ xev.xclient.window = win;
+ xev.xclient.message_type = command_event;
+ xev.xclient.format = 16;
+ xev.xclient.data.s[0] = ((unsigned int)win & 0xffff0000) >> 16;
+ xev.xclient.data.s[1] = (unsigned int)win & 0xffff;
+ xev.xclient.data.s[2] = CMD_APP_WINDOW;
+
+ XSendEvent(dpy, daemon_win, False, 0, &xev);
+ XSync(dpy, False);
+
+ XSetErrorHandler(prev_xerr_handler);
+ return 0;
+}
+
+static int spnav_fd(void)
+{
+ if(dpy) {
+ return ConnectionNumber(dpy);
+ }
+ return -1;
+}
+
+/*static int spnav_wait_event(spnav_event *event)
+{
+ if(dpy) {
+ for(;;) {
+ XEvent xev;
+ XNextEvent(dpy, &xev);
+
+ if(spnav_x11_event(&xev, event) > 0) {
+ return event->type;
+ }
+ }
+ }
+ return 0;
+}
+
+static int spnav_poll_event(spnav_event *event)
+{
+ if(dpy) {
+ if(XPending(dpy)) {
+ XEvent xev;
+ XNextEvent(dpy, &xev);
+
+ return spnav_x11_event(&xev, event);
+ }
+ }
+ return 0;
+}*/
+
+static Bool match_events(Display *dpy, XEvent *xev, char *arg)
+{
+ int evtype = *(int*)arg;
+
+ if(xev->type != ClientMessage) {
+ return False;
+ }
+
+ if(xev->xclient.message_type == motion_event) {
+ return !evtype || evtype == SPNAV_EVENT_MOTION ? True : False;
+ }
+ if(xev->xclient.message_type == button_press_event ||
+ xev->xclient.message_type == button_release_event) {
+ return !evtype || evtype == SPNAV_EVENT_BUTTON ? True : False;
+ }
+ return False;
+}
+
+static int spnav_remove_events(int type)
+{
+ int rm_count = 0;
+
+ if(dpy) {
+ XEvent xev;
+
+ while(XCheckIfEvent(dpy, &xev, match_events, (char*)&type)) {
+ rm_count++;
+ }
+ return rm_count;
+ }
+ return 0;
+}
+
+static int spnav_x11_event(const XEvent *xev, spnav_event *event)
+{
+ int i;
+ int xmsg_type;
+
+ if(xev->type != ClientMessage) {
+ return 0;
+ }
+
+ xmsg_type = xev->xclient.message_type;
+
+ if(xmsg_type != motion_event && xmsg_type != button_press_event &&
+ xmsg_type != button_release_event) {
+ return 0;
+ }
+
+ if(xmsg_type == motion_event) {
+ event->type = SPNAV_EVENT_MOTION;
+ event->motion.data = &event->motion.x;
+
+ for(i=0; i<6; i++) {
+ event->motion.data[i] = xev->xclient.data.s[i + 2];
+ }
+ event->motion.period = xev->xclient.data.s[8];
+ } else {
+ event->type = SPNAV_EVENT_BUTTON;
+ event->button.press = xmsg_type == button_press_event ? 1 : 0;
+ event->button.bnum = xev->xclient.data.s[2];
+ }
+ return event->type;
+}
+
+
+static Window get_daemon_window(Display *dpy)
+{
+ Window win, root_win;
+ XTextProperty wname;
+ Atom type;
+ int fmt;
+ unsigned long nitems, bytes_after;
+ unsigned char *prop;
+
+ root_win = DefaultRootWindow(dpy);
+
+ XGetWindowProperty(dpy, root_win, command_event, 0, 1, False, AnyPropertyType, &type, &fmt, &nitems, &bytes_after, &prop);
+ if(!prop) {
+ return 0;
+ }
+
+ win = *(Window*)prop;
+ XFree(prop);
+
+ if(!XGetWMName(dpy, win, &wname) || strcmp("Magellan Window", (char*)wname.value) != 0) {
+ return 0;
+ }
+
+ return win;
+}
+
+static int catch_badwin(Display *dpy, XErrorEvent *err)
+{
+ char buf[256];
+
+ if(err->error_code == BadWindow) {
+ /* do nothing? */
+ } else {
+ XGetErrorText(dpy, err->error_code, buf, sizeof buf);
+ fprintf(stderr, "Caught unexpected X error: %s\n", buf);
+ }
+ return 0;
+}
+
--- /dev/null
+/*
+ * freeglut_state_x11.c
+ *
+ * X11-specific freeglut state query methods.
+ *
+ * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
+ * Written by John F. Fay, <fayjf@sourceforge.net>
+ * Creation date: Sat Feb 4 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * fgPlatformChooseFBConfig() -- OK, but what about glutInitDisplayString()?
+ */
+
+/* A helper function to check if a display mode is possible to use */
+GLXFBConfig* fgPlatformChooseFBConfig( int* numcfgs );
+
+/*
+ * Queries the GL context about some attributes
+ */
+int fgPlatformGetConfig( int attribute )
+{
+ int returnValue = 0;
+ int result; /* Not checked */
+
+ if( fgStructure.CurrentWindow )
+ result = glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
+ *(fgStructure.CurrentWindow->Window.pContext.FBConfig),
+ attribute,
+ &returnValue );
+
+ return returnValue;
+}
+
+int fgPlatformGlutGet ( GLenum eWhat )
+{
+ int nsamples = 0;
+
+ switch( eWhat )
+ {
+ /*
+ * The window/context specific queries are handled mostly by
+ * fgPlatformGetConfig().
+ */
+ case GLUT_WINDOW_NUM_SAMPLES:
+#ifdef GLX_VERSION_1_3
+ glGetIntegerv(GL_SAMPLES, &nsamples);
+#endif
+ return nsamples;
+
+ /*
+ * The rest of GLX queries under X are general enough to use a macro to
+ * check them
+ */
+# define GLX_QUERY(a,b) case a: return fgPlatformGetConfig( b );
+
+ GLX_QUERY( GLUT_WINDOW_RGBA, GLX_RGBA );
+ GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER, GLX_DOUBLEBUFFER );
+ GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE, GLX_BUFFER_SIZE );
+ GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE, GLX_STENCIL_SIZE );
+ GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE, GLX_DEPTH_SIZE );
+ GLX_QUERY( GLUT_WINDOW_RED_SIZE, GLX_RED_SIZE );
+ GLX_QUERY( GLUT_WINDOW_GREEN_SIZE, GLX_GREEN_SIZE );
+ GLX_QUERY( GLUT_WINDOW_BLUE_SIZE, GLX_BLUE_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE, GLX_ALPHA_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE, GLX_ACCUM_RED_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE, GLX_ACCUM_GREEN_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE, GLX_ACCUM_BLUE_SIZE );
+ GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE, GLX_ACCUM_ALPHA_SIZE );
+ GLX_QUERY( GLUT_WINDOW_STEREO, GLX_STEREO );
+
+# undef GLX_QUERY
+
+ /* Colormap size is handled in a bit different way than all the rest */
+ case GLUT_WINDOW_COLORMAP_SIZE:
+ if( (fgPlatformGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
+ {
+ /*
+ * We've got a RGBA visual, so there is no colormap at all.
+ * The other possibility is that we have no current window set.
+ */
+ return 0;
+ }
+ else
+ {
+ const GLXFBConfig * fbconfig =
+ fgStructure.CurrentWindow->Window.pContext.FBConfig;
+
+ XVisualInfo * visualInfo =
+ glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display, *fbconfig );
+
+ const int result = visualInfo->visual->map_entries;
+
+ XFree(visualInfo);
+
+ return result;
+ }
+
+ /*
+ * Those calls are somewhat similiar, as they use XGetWindowAttributes()
+ * function
+ */
+ case GLUT_WINDOW_X:
+ case GLUT_WINDOW_Y:
+ case GLUT_WINDOW_BORDER_WIDTH:
+ case GLUT_WINDOW_HEADER_HEIGHT:
+ {
+ int x, y;
+ Window w;
+
+ if( fgStructure.CurrentWindow == NULL )
+ return 0;
+
+ XTranslateCoordinates(
+ fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ fgDisplay.pDisplay.RootWindow,
+ 0, 0, &x, &y, &w);
+
+ switch ( eWhat )
+ {
+ case GLUT_WINDOW_X: return x;
+ case GLUT_WINDOW_Y: return y;
+ }
+
+ if ( w == 0 )
+ return 0;
+ XTranslateCoordinates(
+ fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ w, 0, 0, &x, &y, &w);
+
+ switch ( eWhat )
+ {
+ case GLUT_WINDOW_BORDER_WIDTH: return x;
+ case GLUT_WINDOW_HEADER_HEIGHT: return y;
+ }
+ }
+
+ case GLUT_WINDOW_WIDTH:
+ case GLUT_WINDOW_HEIGHT:
+ {
+ XWindowAttributes winAttributes;
+
+ if( fgStructure.CurrentWindow == NULL )
+ return 0;
+ XGetWindowAttributes(
+ fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ &winAttributes
+ );
+ switch ( eWhat )
+ {
+ case GLUT_WINDOW_WIDTH: return winAttributes.width ;
+ case GLUT_WINDOW_HEIGHT: return winAttributes.height ;
+ }
+ }
+
+ /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
+ case GLUT_DISPLAY_MODE_POSSIBLE:
+ {
+ /* We should not have to call fgPlatformChooseFBConfig again here. */
+ GLXFBConfig * fbconfig;
+ int isPossible;
+
+ fbconfig = fgPlatformChooseFBConfig(NULL);
+
+ if (fbconfig == NULL)
+ {
+ isPossible = 0;
+ }
+ else
+ {
+ isPossible = 1;
+ XFree(fbconfig);
+ }
+
+ return isPossible;
+ }
+
+ /* This is system-dependant */
+ case GLUT_WINDOW_FORMAT_ID:
+ if( fgStructure.CurrentWindow == NULL )
+ return 0;
+
+ return fgPlatformGetConfig( GLX_VISUAL_ID );
+
+ default:
+ fgWarning( "glutGet(): missing enum handle %d", eWhat );
+ break;
+ }
+
+ return -1;
+}
+
+
+int fgPlatformGlutDeviceGet ( GLenum eWhat )
+{
+ switch( eWhat )
+ {
+ case GLUT_HAS_KEYBOARD:
+ /*
+ * X11 has a core keyboard by definition, although it can
+ * be present as a virtual/dummy keyboard. For now, there
+ * is no reliable way to tell if a real keyboard is present.
+ */
+ return 1;
+
+ /* X11 has a mouse by definition */
+ case GLUT_HAS_MOUSE:
+ return 1 ;
+
+ case GLUT_NUM_MOUSE_BUTTONS:
+ /* We should be able to pass NULL when the last argument is zero,
+ * but at least one X server has a bug where this causes a segfault.
+ *
+ * In XFree86/Xorg servers, a mouse wheel is seen as two buttons
+ * rather than an Axis; "freeglut_main.c" expects this when
+ * checking for a wheel event.
+ */
+ {
+ unsigned char map;
+ int nbuttons = XGetPointerMapping(fgDisplay.pDisplay.Display, &map,0);
+ return nbuttons;
+ }
+
+ default:
+ fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
+ break;
+ }
+
+ /* And now -- the failure. */
+ return -1;
+}
+
+
+int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
+{
+ int *array;
+
+ int attributes[9];
+ GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
+ int fbconfigArraySize; /* Number of FBConfigs in the array */
+ int attribute_name = 0;
+
+ array = NULL;
+ *size = 0;
+
+ switch (eWhat)
+ {
+ case GLUT_AUX:
+ case GLUT_MULTISAMPLE:
+
+ attributes[0] = GLX_BUFFER_SIZE;
+ attributes[1] = GLX_DONT_CARE;
+
+ switch (eWhat)
+ {
+ case GLUT_AUX:
+ /*
+ FBConfigs are now sorted by increasing number of auxiliary
+ buffers. We want at least one buffer.
+ */
+ attributes[2] = GLX_AUX_BUFFERS;
+ attributes[3] = 1;
+ attributes[4] = None;
+
+ attribute_name = GLX_AUX_BUFFERS;
+
+ break;
+
+
+ case GLUT_MULTISAMPLE:
+ attributes[2] = GLX_AUX_BUFFERS;
+ attributes[3] = GLX_DONT_CARE;
+ attributes[4] = GLX_SAMPLE_BUFFERS;
+ attributes[5] = 1;
+ /*
+ FBConfigs are now sorted by increasing number of samples per
+ pixel. We want at least one sample.
+ */
+ attributes[6] = GLX_SAMPLES;
+ attributes[7] = 1;
+ attributes[8] = None;
+
+ attribute_name = GLX_SAMPLES;
+
+ break;
+ }
+
+ fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ attributes,
+ &fbconfigArraySize);
+
+ if (fbconfigArray != NULL)
+ {
+ int * temp_array;
+ int result; /* Returned by glXGetFBConfigAttrib. Not checked. */
+ int previous_value;
+ int i;
+
+ temp_array = malloc(sizeof(int) * fbconfigArraySize);
+ previous_value = 0;
+
+ for (i = 0; i < fbconfigArraySize; i++)
+ {
+ int value;
+
+ result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display,
+ fbconfigArray[i],
+ attribute_name,
+ &value);
+ if (value > previous_value)
+ {
+ temp_array[*size] = value;
+ previous_value = value;
+ (*size)++;
+ }
+ }
+
+ array = malloc(sizeof(int) * (*size));
+ for (i = 0; i < *size; i++)
+ {
+ array[i] = temp_array[i];
+ }
+
+ free(temp_array);
+ XFree(fbconfigArray);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ return array;
+}
+
+
--- /dev/null
+/*
+ * freeglut_structure.c
+ *
+ * Windows and menus need tree structure
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "../fg_internal.h"
+
+extern SFG_Structure fgStructure;
+
+void fgPlatformCreateWindow ( SFG_Window *window )
+{
+ window->Window.pContext.FBConfig = NULL;
+
+ window->State.pWState.OldHeight = window->State.pWState.OldWidth = -1;
+}
+
--- /dev/null
+/*
+ * freeglut_window_x11.c
+ *
+ * Window management methods for X11
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Copied for Platform code by Evan Felix <karcaw at gmail.com>
+ * Creation date: Thur Feb 2 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <GL/freeglut.h>
+#include <limits.h> /* LONG_MAX */
+#include <unistd.h> /* usleep */
+#include "../fg_internal.h"
+
+/* pushing attribute/value pairs into an array */
+#define ATTRIB(a) attributes[where++]=(a)
+#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
+
+
+#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+#endif
+
+#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#endif
+
+#ifndef GLX_CONTEXT_MINOR_VERSION_ARB
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#endif
+
+#ifndef GLX_CONTEXT_FLAGS_ARB
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#endif
+
+#ifndef GLX_CONTEXT_PROFILE_MASK_ARB
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#endif
+
+#ifndef GLX_CONTEXT_DEBUG_BIT_ARB
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
+#endif
+
+#ifndef GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#endif
+
+#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#endif
+
+#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#endif
+
+#ifndef GLX_RGBA_FLOAT_TYPE
+#define GLX_RGBA_FLOAT_TYPE 0x20B9
+#endif
+
+#ifndef GLX_RGBA_FLOAT_BIT
+#define GLX_RGBA_FLOAT_BIT 0x00000004
+#endif
+
+
+/*
+ * Chooses a visual basing on the current display mode settings
+ */
+
+GLXFBConfig* fgPlatformChooseFBConfig( int *numcfgs )
+{
+ GLboolean wantIndexedMode = GL_FALSE;
+ int attributes[ 100 ];
+ int where = 0, numAuxBuffers;
+
+ /* First we have to process the display mode settings... */
+ if( fgState.DisplayMode & GLUT_INDEX ) {
+ ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
+ /* Buffer size is selected later. */
+
+ ATTRIB_VAL( GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT );
+ wantIndexedMode = GL_TRUE;
+ } else {
+ ATTRIB_VAL( GLX_RED_SIZE, 1 );
+ ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
+ ATTRIB_VAL( GLX_BLUE_SIZE, 1 );
+ if( fgState.DisplayMode & GLUT_ALPHA ) {
+ ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
+ }
+ }
+
+ if( fgState.DisplayMode & GLUT_DOUBLE ) {
+ ATTRIB_VAL( GLX_DOUBLEBUFFER, True );
+ }
+
+ if( fgState.DisplayMode & GLUT_STEREO ) {
+ ATTRIB_VAL( GLX_STEREO, True );
+ }
+
+ if( fgState.DisplayMode & GLUT_DEPTH ) {
+ ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
+ }
+
+ if( fgState.DisplayMode & GLUT_STENCIL ) {
+ ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
+ }
+
+ if( fgState.DisplayMode & GLUT_ACCUM ) {
+ ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 );
+ ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
+ ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 );
+ if( fgState.DisplayMode & GLUT_ALPHA ) {
+ ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
+ }
+ }
+
+ numAuxBuffers = fghNumberOfAuxBuffersRequested();
+ if ( numAuxBuffers > 0 ) {
+ ATTRIB_VAL( GLX_AUX_BUFFERS, numAuxBuffers );
+ }
+
+ if( fgState.DisplayMode & GLUT_SRGB ) {
+ ATTRIB_VAL( GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True );
+ }
+
+ if (fgState.DisplayMode & GLUT_MULTISAMPLE) {
+ ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1);
+ ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber);
+ }
+
+ /* Push a terminator at the end of the list */
+ ATTRIB( None );
+
+ {
+ GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
+ GLXFBConfig * fbconfig; /* The FBConfig we want */
+ int fbconfigArraySize; /* Number of FBConfigs in the array */
+
+
+ /* Get all FBConfigs that match "attributes". */
+ fbconfigArray = glXChooseFBConfig( fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ attributes,
+ &fbconfigArraySize );
+
+ if (fbconfigArray != NULL)
+ {
+ int result; /* Returned by glXGetFBConfigAttrib, not checked. */
+
+
+ if( wantIndexedMode )
+ {
+ /*
+ * In index mode, we want the largest buffer size, i.e. visual
+ * depth. Here, FBConfigs are sorted by increasing buffer size
+ * first, so FBConfigs with the largest size come last.
+ */
+
+ int bufferSizeMin, bufferSizeMax;
+
+ /* Get bufferSizeMin. */
+ result =
+ glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
+ fbconfigArray[0],
+ GLX_BUFFER_SIZE,
+ &bufferSizeMin );
+ /* Get bufferSizeMax. */
+ result =
+ glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
+ fbconfigArray[fbconfigArraySize - 1],
+ GLX_BUFFER_SIZE,
+ &bufferSizeMax );
+
+ if (bufferSizeMax > bufferSizeMin)
+ {
+ /*
+ * Free and reallocate fbconfigArray, keeping only FBConfigs
+ * with the largest buffer size.
+ */
+ XFree(fbconfigArray);
+
+ /* Add buffer size token at the end of the list. */
+ where--;
+ ATTRIB_VAL( GLX_BUFFER_SIZE, bufferSizeMax );
+ ATTRIB( None );
+
+ fbconfigArray = glXChooseFBConfig( fgDisplay.pDisplay.Display,
+ fgDisplay.pDisplay.Screen,
+ attributes,
+ &fbconfigArraySize );
+ }
+ }
+
+ /*
+ * We now have an array of FBConfigs, the first one being the "best"
+ * one. So we should return only this FBConfig:
+ *
+ * int fbconfigXID;
+ *
+ * - pick the XID of the FBConfig we want
+ * result = glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
+ * fbconfigArray[0],
+ * GLX_FBCONFIG_ID,
+ * &fbconfigXID );
+ *
+ * - free the array
+ * XFree(fbconfigArray);
+ *
+ * - reset "attributes" with the XID
+ * where = 0;
+ * ATTRIB_VAL( GLX_FBCONFIG_ID, fbconfigXID );
+ * ATTRIB( None );
+ *
+ * - get our FBConfig only
+ * fbconfig = glXChooseFBConfig( fgDisplay.pDisplay.Display,
+ * fgDisplay.pDisplay.Screen,
+ * attributes,
+ * &fbconfigArraySize );
+ *
+ * However, for some configurations (for instance multisampling with
+ * Mesa 6.5.2 and ATI drivers), this does not work:
+ * glXChooseFBConfig returns NULL, whereas fbconfigXID is a valid
+ * XID. Further investigation is needed.
+ *
+ * So, for now, we return the whole array of FBConfigs. This should
+ * not produce any side effects elsewhere.
+ */
+ fbconfig = fbconfigArray;
+ }
+ else
+ {
+ fbconfig = NULL;
+ }
+
+ if (numcfgs)
+ *numcfgs = fbconfigArraySize;
+
+ return fbconfig;
+ }
+}
+
+
+static void fghFillContextAttributes( int *attributes ) {
+ int where = 0, contextFlags, contextProfile;
+
+ if ( !fghIsLegacyContextVersionRequested() ) {
+ ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
+ ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
+ }
+
+ contextFlags =
+ fghMapBit( fgState.ContextFlags, GLUT_DEBUG, GLX_CONTEXT_DEBUG_BIT_ARB ) |
+ fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
+ if ( contextFlags != 0 ) {
+ ATTRIB_VAL( GLX_CONTEXT_FLAGS_ARB, contextFlags );
+ }
+
+ contextProfile =
+ fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB ) |
+ fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
+ if ( contextProfile != 0 ) {
+ ATTRIB_VAL( GLX_CONTEXT_PROFILE_MASK_ARB, contextProfile );
+ }
+
+ ATTRIB( 0 );
+}
+
+typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config,
+ GLXContext share_list, Bool direct,
+ const int *attrib_list);
+
+static GLXContext fghCreateNewContext( SFG_Window* window )
+{
+ /* for color model calculation */
+ int menu = ( window->IsMenu && !fgStructure.MenuContext );
+ int index_mode = ( fgState.DisplayMode & GLUT_INDEX );
+
+ /* "classic" context creation */
+ Display *dpy = fgDisplay.pDisplay.Display;
+ GLXFBConfig config = *(window->Window.pContext.FBConfig);
+ int render_type = ( !menu && index_mode ) ? GLX_COLOR_INDEX_TYPE : GLX_RGBA_TYPE;
+ GLXContext share_list = NULL;
+ Bool direct = ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT );
+ GLXContext context;
+
+ /* new context creation */
+ int attributes[9];
+ CreateContextAttribsProc createContextAttribs = (CreateContextAttribsProc) fgPlatformGetProcAddress( "glXCreateContextAttribsARB" );
+
+ /* glXCreateContextAttribsARB not found, yet the user has requested the new context creation */
+ if ( !createContextAttribs && !fghIsLegacyContextRequested() ) {
+ fgWarning( "OpenGL >2.1 context requested but glXCreateContextAttribsARB is not available! Falling back to legacy context creation" );
+ fgState.MajorVersion = 2;
+ fgState.MinorVersion = 1;
+ }
+
+ /* If nothing fancy has been required, simply use the old context creation GLX API entry */
+ if ( fghIsLegacyContextRequested() || !createContextAttribs )
+ {
+ context = glXCreateNewContext( dpy, config, render_type, share_list, direct );
+ if ( context == NULL ) {
+ fghContextCreationError();
+ }
+ return context;
+ }
+
+ /* color index mode is not available anymore with OpenGL 3.0 */
+ if ( render_type == GLX_COLOR_INDEX_TYPE ) {
+ fgWarning( "color index mode is deprecated, using RGBA mode" );
+ }
+
+ fghFillContextAttributes( attributes );
+
+ context = createContextAttribs( dpy, config, share_list, direct, attributes );
+ if ( context == NULL ) {
+ fghContextCreationError();
+ }
+ return context;
+}
+
+
+#define _NET_WM_STATE_TOGGLE 2
+static int fghResizeFullscrToggle(void)
+{
+ XWindowAttributes attributes;
+
+ if(glutGet(GLUT_FULL_SCREEN)) {
+ /* restore original window size */
+ SFG_Window *win = fgStructure.CurrentWindow;
+ fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
+ fgStructure.CurrentWindow->State.Width = win->State.pWState.OldWidth;
+ fgStructure.CurrentWindow->State.Height = win->State.pWState.OldHeight;
+
+ } else {
+ /* resize the window to cover the entire screen */
+ XGetWindowAttributes(fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ &attributes);
+
+ /*
+ * The "x" and "y" members of "attributes" are the window's coordinates
+ * relative to its parent, i.e. to the decoration window.
+ */
+ XMoveResizeWindow(fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ -attributes.x,
+ -attributes.y,
+ fgDisplay.ScreenWidth,
+ fgDisplay.ScreenHeight);
+ }
+ return 0;
+}
+
+static int fghEwmhFullscrToggle(void)
+{
+ XEvent xev;
+ long evmask = SubstructureRedirectMask | SubstructureNotifyMask;
+
+ if(!fgDisplay.pDisplay.State || !fgDisplay.pDisplay.StateFullScreen) {
+ return -1;
+ }
+
+ xev.type = ClientMessage;
+ xev.xclient.window = fgStructure.CurrentWindow->Window.Handle;
+ xev.xclient.message_type = fgDisplay.pDisplay.State;
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
+ xev.xclient.data.l[1] = fgDisplay.pDisplay.StateFullScreen;
+ xev.xclient.data.l[2] = 0; /* no second property to toggle */
+ xev.xclient.data.l[3] = 1; /* source indication: application */
+ xev.xclient.data.l[4] = 0; /* unused */
+
+ if(!XSendEvent(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, 0, evmask, &xev)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int fghToggleFullscreen(void)
+{
+ /* first try the EWMH (_NET_WM_STATE) method ... */
+ if(fghEwmhFullscrToggle() != -1) {
+ return 0;
+ }
+
+ /* fall back to resizing the window */
+ if(fghResizeFullscrToggle() != -1) {
+ return 0;
+ }
+ return -1;
+}
+
+void fgPlatformSetWindow ( SFG_Window *window )
+{
+ if ( window )
+ {
+ glXMakeContextCurrent(
+ fgDisplay.pDisplay.Display,
+ window->Window.Handle,
+ window->Window.Handle,
+ window->Window.Context
+ );
+ }
+}
+
+static Bool fghWindowIsVisible( Display *display, XEvent *event, XPointer arg)
+{
+ Window window = (Window)arg;
+ return (event->type == MapNotify) && (event->xmap.window == window);
+}
+
+/*
+ * Opens a window. Requires a SFG_Window object created and attached
+ * to the freeglut structure. OpenGL context is created here.
+ */
+void fgPlatformOpenWindow( SFG_Window* window, const char* title,
+ GLboolean positionUse, int x, int y,
+ GLboolean sizeUse, int w, int h,
+ GLboolean gameMode, GLboolean isSubWindow )
+{
+ XVisualInfo * visualInfo = NULL;
+ XSetWindowAttributes winAttr;
+ XTextProperty textProperty;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ XEvent eventReturnBuffer; /* return buffer required for a call */
+ unsigned long mask;
+ int num_FBConfigs, i;
+ unsigned int current_DisplayMode = fgState.DisplayMode ;
+
+ /* Save the display mode if we are creating a menu window */
+ if( window->IsMenu && ( ! fgStructure.MenuContext ) )
+ fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ;
+
+ window->Window.pContext.FBConfig = fgPlatformChooseFBConfig( &num_FBConfigs );
+
+ if( window->IsMenu && ( ! fgStructure.MenuContext ) )
+ fgState.DisplayMode = current_DisplayMode ;
+
+ if( ! window->Window.pContext.FBConfig )
+ {
+ /*
+ * The "fgPlatformChooseFBConfig" returned a null meaning that the visual
+ * context is not available.
+ * Try a couple of variations to see if they will work.
+ */
+ if( !( fgState.DisplayMode & GLUT_DOUBLE ) )
+ {
+ fgState.DisplayMode |= GLUT_DOUBLE ;
+ window->Window.pContext.FBConfig = fgPlatformChooseFBConfig( &num_FBConfigs );
+ fgState.DisplayMode &= ~GLUT_DOUBLE;
+ }
+
+ if( fgState.DisplayMode & GLUT_MULTISAMPLE )
+ {
+ fgState.DisplayMode &= ~GLUT_MULTISAMPLE ;
+ window->Window.pContext.FBConfig = fgPlatformChooseFBConfig( &num_FBConfigs );
+ fgState.DisplayMode |= GLUT_MULTISAMPLE;
+ }
+ }
+
+ FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.pContext.FBConfig != NULL,
+ "FBConfig with necessary capabilities not found", "fgOpenWindow" );
+
+ /* Get the X visual. */
+ for (i = 0; i < num_FBConfigs; i++) {
+ visualInfo = glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display,
+ window->Window.pContext.FBConfig[i] );
+ if (visualInfo)
+ break;
+ }
+
+ FREEGLUT_INTERNAL_ERROR_EXIT( visualInfo != NULL,
+ "visualInfo could not be retrieved from FBConfig", "fgOpenWindow" );
+
+ /*
+ * XXX HINT: the masks should be updated when adding/removing callbacks.
+ * XXX This might speed up message processing. Is that true?
+ * XXX
+ * XXX A: Not appreciably, but it WILL make it easier to debug.
+ * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT
+ * XXX turns off events that it doesn't need and is a whole lot
+ * XXX more pleasant to trace. (Think mouse-motion! Tons of
+ * XXX ``bonus'' GUI events stream in.)
+ */
+ winAttr.event_mask =
+ StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
+ ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
+ VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask | ButtonMotionMask;
+ winAttr.background_pixmap = None;
+ winAttr.background_pixel = 0;
+ winAttr.border_pixel = 0;
+
+ winAttr.colormap = XCreateColormap(
+ fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow,
+ visualInfo->visual, AllocNone
+ );
+
+ mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
+
+ if( window->IsMenu || ( gameMode == GL_TRUE ) )
+ {
+ winAttr.override_redirect = True;
+ mask |= CWOverrideRedirect;
+ }
+
+ if( ! positionUse )
+ x = y = -1; /* default window position */
+ if( ! sizeUse )
+ w = h = 300; /* default window size */
+
+ window->Window.Handle = XCreateWindow(
+ fgDisplay.pDisplay.Display,
+ window->Parent == NULL ? fgDisplay.pDisplay.RootWindow :
+ window->Parent->Window.Handle,
+ x, y, w, h, 0,
+ visualInfo->depth, InputOutput,
+ visualInfo->visual, mask,
+ &winAttr
+ );
+
+ /*
+ * The GLX context creation, possibly trying the direct context rendering
+ * or else use the current context if the user has so specified
+ */
+
+ if( window->IsMenu )
+ {
+ /*
+ * If there isn't already an OpenGL rendering context for menu
+ * windows, make one
+ */
+ if( !fgStructure.MenuContext )
+ {
+ fgStructure.MenuContext =
+ (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
+ fgStructure.MenuContext->MContext = fghCreateNewContext( window );
+ }
+
+ /* window->Window.Context = fgStructure.MenuContext->MContext; */
+ window->Window.Context = fghCreateNewContext( window );
+ }
+ else if( fgState.UseCurrentContext )
+ {
+ window->Window.Context = glXGetCurrentContext( );
+
+ if( ! window->Window.Context )
+ window->Window.Context = fghCreateNewContext( window );
+ }
+ else
+ window->Window.Context = fghCreateNewContext( window );
+
+#if !defined( __FreeBSD__ ) && !defined( __NetBSD__ )
+ if( !glXIsDirect( fgDisplay.pDisplay.Display, window->Window.Context ) )
+ {
+ if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
+ fgError( "Unable to force direct context rendering for window '%s'",
+ title );
+ }
+#endif
+
+ /*
+ * XXX Assume the new window is visible by default
+ * XXX Is this a safe assumption?
+ */
+ window->State.Visible = GL_TRUE;
+
+ sizeHints.flags = 0;
+ if ( positionUse )
+ sizeHints.flags |= USPosition;
+ if ( sizeUse )
+ sizeHints.flags |= USSize;
+
+ /*
+ * Fill in the size hints values now (the x, y, width and height
+ * settings are obsolete, are there any more WMs that support them?)
+ * Unless the X servers actually stop supporting these, we should
+ * continue to fill them in. It is *not* our place to tell the user
+ * that they should replace a window manager that they like, and which
+ * works, just because *we* think that it's not "modern" enough.
+ */
+ sizeHints.x = x;
+ sizeHints.y = y;
+ sizeHints.width = w;
+ sizeHints.height = h;
+
+ wmHints.flags = StateHint;
+ wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
+ /* Prepare the window and iconified window names... */
+ XStringListToTextProperty( (char **) &title, 1, &textProperty );
+
+ XSetWMProperties(
+ fgDisplay.pDisplay.Display,
+ window->Window.Handle,
+ &textProperty,
+ &textProperty,
+ 0,
+ 0,
+ &sizeHints,
+ &wmHints,
+ NULL
+ );
+ XFree( textProperty.value );
+
+ XSetWMProtocols( fgDisplay.pDisplay.Display, window->Window.Handle,
+ &fgDisplay.pDisplay.DeleteWindow, 1 );
+
+ glXMakeContextCurrent(
+ fgDisplay.pDisplay.Display,
+ window->Window.Handle,
+ window->Window.Handle,
+ window->Window.Context
+ );
+
+ /* register extension events _before_ window is mapped */
+ #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+ fgRegisterDevices( fgDisplay.pDisplay.Display, &(window->Window.Handle) );
+ #endif
+
+ XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
+
+ XFree(visualInfo);
+
+ if( !isSubWindow)
+ XPeekIfEvent( fgDisplay.pDisplay.Display, &eventReturnBuffer, &fghWindowIsVisible, (XPointer)(window->Window.Handle) );
+}
+
+
+/*
+ * Closes a window, destroying the frame and OpenGL context
+ */
+void fgPlatformCloseWindow( SFG_Window* window )
+{
+ if( window->Window.Context )
+ glXDestroyContext( fgDisplay.pDisplay.Display, window->Window.Context );
+ XFree( window->Window.pContext.FBConfig );
+
+ if( window->Window.Handle ) {
+ XDestroyWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
+ }
+ /* XFlush( fgDisplay.pDisplay.Display ); */ /* XXX Shouldn't need this */
+}
+
+
+/*
+ * This function makes the current window visible
+ */
+void fgPlatformGlutShowWindow( void )
+{
+ XMapWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+/*
+ * This function hides the current window
+ */
+void fgPlatformGlutHideWindow( void )
+{
+ if( fgStructure.CurrentWindow->Parent == NULL )
+ XWithdrawWindow( fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ fgDisplay.pDisplay.Screen );
+ else
+ XUnmapWindow( fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle );
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+/*
+ * Iconify the current window (top-level windows only)
+ */
+void fgPlatformGlutIconifyWindow( void )
+{
+ XIconifyWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
+ fgDisplay.pDisplay.Screen );
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+/*
+ * Set the current window's title
+ */
+void fgPlatformGlutSetWindowTitle( const char* title )
+{
+ XTextProperty text;
+
+ text.value = (unsigned char *) title;
+ text.encoding = XA_STRING;
+ text.format = 8;
+ text.nitems = strlen( title );
+
+ XSetWMName(
+ fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ &text
+ );
+
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+/*
+ * Set the current window's iconified title
+ */
+void fgPlatformGlutSetIconTitle( const char* title )
+{
+ XTextProperty text;
+
+ text.value = (unsigned char *) title;
+ text.encoding = XA_STRING;
+ text.format = 8;
+ text.nitems = strlen( title );
+
+ XSetWMIconName(
+ fgDisplay.pDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ &text
+ );
+
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+/*
+ * Change the current window's position
+ */
+void fgPlatformGlutPositionWindow( int x, int y )
+{
+ XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
+ x, y );
+ XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
+}
+
+/*
+ * Lowers the current window (by Z order change)
+ */
+void fgPlatformGlutPushWindow( void )
+{
+ XLowerWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
+}
+
+/*
+ * Raises the current window (by Z order change)
+ */
+void fgPlatformGlutPopWindow( void )
+{
+ XRaiseWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
+}
+
+/*
+ * Resize the current window so that it fits the whole screen
+ */
+void fgPlatformGlutFullScreen( SFG_Window *win )
+{
+ if(!glutGet(GLUT_FULL_SCREEN)) {
+ if(fghToggleFullscreen() != -1) {
+ win->State.IsFullscreen = GL_TRUE;
+ }
+ }
+}
+
+/*
+ * If we are fullscreen, resize the current window back to its original size
+ */
+void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
+{
+ if(glutGet(GLUT_FULL_SCREEN)) {
+ if(fghToggleFullscreen() != -1) {
+ win->State.IsFullscreen = GL_FALSE;
+ }
+ }
+}
+
+/*
+ * Toggle the window's full screen state.
+ */
+void fgPlatformGlutFullScreenToggle( SFG_Window *win )
+{
+ if(fghToggleFullscreen() != -1) {
+ win->State.IsFullscreen = !win->State.IsFullscreen;
+ }
+}
+
--- /dev/null
+/* Written for XI1 by Nikolas Doerfler <doerflen@in.tum.de> (c) 2008 *
+ * Rewritten for XI2 by Florian Echtler <echtler@in.tum.de> (c) 2009 */
+
+#include <GL/freeglut.h>
+
+#include "../fg_internal.h"
+
+#if HAVE_X11_EXTENSIONS_XINPUT2_H
+
+#include <errno.h>
+#include <stdarg.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
+
+/* import function from freeglut_main.c */
+extern int fgPlatformGetModifiers( int state );
+
+/* extension opcode for XInput */
+int xi_opcode = -1;
+
+/**
+ * \brief Sets window up for XI2 events.
+ */
+void fgRegisterDevices( Display* dpy, Window* win ) {
+
+ XIEventMask mask;
+ unsigned char flags[2] = { 0, 0 };
+ int event, error;
+
+ /*Display* dpy = fgDisplay.pDisplay.Display;
+ Window* win = glutGetXWindow();*/
+
+ /* get XInput extension opcode */
+ if (!XQueryExtension( dpy, "XInputExtension", &xi_opcode, &event, &error )) { xi_opcode = -1; }
+
+ /* Select for motion events */
+ mask.deviceid = XIAllMasterDevices;
+ mask.mask_len = 2;
+ mask.mask = flags;
+
+ XISetMask(mask.mask, XI_Enter);
+ XISetMask(mask.mask, XI_Motion);
+ XISetMask(mask.mask, XI_ButtonPress);
+ XISetMask(mask.mask, XI_ButtonRelease);
+ XISetMask(mask.mask, XI_Leave);
+ /*XISetMask(mask.mask, XI_KeyPress);
+ XISetMask(mask.mask, XI_KeyRelease);
+ XISetMask(mask.mask, XI_DeviceChanged);
+ XISetMask(mask.mask, XI_RawEvent);
+ XISetMask(mask.mask, XI_FocusIn);
+ XISetMask(mask.mask, XI_FocusOut);
+ XISetMask(mask.mask, XI_HierarchyChanged);*/
+
+ XISelectEvents( dpy, *win, &mask, 1 );
+}
+
+
+void fgPrintXILeaveEvent(XILeaveEvent* event)
+{
+ char* mode = "";
+ char* detail = "";
+ int i;
+
+ printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
+ event->root, event->event, event->child);
+ switch(event->mode)
+ {
+ case NotifyNormal: mode = "NotifyNormal"; break;
+ case NotifyGrab: mode = "NotifyGrab"; break;
+ case NotifyUngrab: mode = "NotifyUngrab"; break;
+ case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
+ }
+ switch (event->detail)
+ {
+ case NotifyAncestor: detail = "NotifyAncestor"; break;
+ case NotifyVirtual: detail = "NotifyVirtual"; break;
+ case NotifyInferior: detail = "NotifyInferior"; break;
+ case NotifyNonlinear: detail = "NotifyNonlinear"; break;
+ case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+ case NotifyPointer: detail = "NotifyPointer"; break;
+ case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+ case NotifyDetailNone: detail = "NotifyDetailNone"; break;
+ }
+ printf(" mode: %s (detail %s)\n", mode, detail);
+ printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
+ event->same_screen ? "[same screen]" : "");
+ printf(" buttons:");
+ for (i = 0; i < event->buttons.mask_len * 8; i++)
+ if (XIMaskIsSet(event->buttons.mask, i))
+ printf(" %d", i);
+ printf("\n");
+
+ printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
+ event->mods.locked, event->mods.latched,
+ event->mods.base);
+ printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
+ event->group.locked, event->group.latched,
+ event->group.base);
+
+ printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
+ printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
+
+}
+
+
+void fgPrintXIDeviceEvent(XIDeviceEvent* event)
+{
+ double *val;
+ int i;
+
+ printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
+ printf(" detail: %d\n", event->detail);
+ printf(" buttons:");
+ for (i = 0; i < event->buttons.mask_len * 8; i++)
+ if (XIMaskIsSet(event->buttons.mask, i))
+ printf(" %d", i);
+ printf("\n");
+
+ printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
+ event->mods.locked, event->mods.latched,
+ event->mods.base);
+ printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
+ event->group.locked, event->group.latched,
+ event->group.base);
+ printf(" valuators:");
+
+ val = event->valuators.values;
+ for (i = 0; i < event->valuators.mask_len * 8; i++)
+ if (XIMaskIsSet(event->valuators.mask, i))
+ printf(" %d: %.2f", i, *val++);
+ printf("\n");
+
+ printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
+ event->root, event->event, event->child);
+ printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
+ printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
+
+}
+
+
+/**
+ * \brief This function is called when an Extension Event is received
+ * and calls the corresponding callback functions for these events.
+ */
+void fgHandleExtensionEvents( XEvent* base_ev ) {
+
+ int i, button = 0;
+ XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
+
+ if ( XGetEventData( fgDisplay.pDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
+
+ XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
+ /*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
+
+ SFG_Window* window = fgWindowByHandle( event->event );
+ if (!window) return;
+
+ switch (cookie->evtype) {
+
+ case XI_Enter:
+ case XI_Leave:
+ fgState.Modifiers = fgPlatformGetModifiers( ((XIEnterEvent*)event)->mods.base );
+ INVOKE_WCB( *window, MultiEntry, (
+ event->deviceid,
+ (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
+ ));
+ #if _DEBUG
+ fgPrintXILeaveEvent((XILeaveEvent*)event);
+ #endif
+ break;
+
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
+ INVOKE_WCB( *window, MultiButton, (
+ event->deviceid,
+ event->event_x,
+ event->event_y,
+ (event->detail)-1,
+ (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
+ ));
+ INVOKE_WCB( *window, Mouse, (
+ (event->detail)-1,
+ (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP),
+ event->event_x,
+ event->event_y
+ ));
+ break;
+
+ case XI_Motion:
+ fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
+ for (i = 0; i < event->buttons.mask_len; i++) if (event->buttons.mask[i]) button = 1;
+ if (button) {
+ INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
+ INVOKE_WCB( *window, Motion, ( event->event_x, event->event_y ) );
+ } else {
+ INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
+ INVOKE_WCB( *window, Passive, ( event->event_x, event->event_y ) );
+ }
+ #if _DEBUG
+ fgPrintXIDeviceEvent(event);
+ #endif
+ break;
+
+ default:
+ #if _DEBUG
+ fgWarning( "Unknown XI2 device event:" );
+ fgPrintXIDeviceEvent( event );
+ #endif
+ break;
+ }
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ XFreeEventData( fgDisplay.pDisplay.Display, cookie );
+}
+
+#endif\r
+\r
+++ /dev/null
-/*
- * freeglut_cursor_x11.c
- *
- * The Windows-specific mouse cursor related stuff.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sun Feb 5, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-/* This code is for Posix/X11, Solaris, and OSX */
-#include <X11/cursorfont.h>
-
-/*
- * A factory method for an empty cursor
- */
-static Cursor getEmptyCursor( void )
-{
- static Cursor cursorNone = None;
- if( cursorNone == None ) {
- char cursorNoneBits[ 32 ];
- XColor dontCare;
- Pixmap cursorNonePixmap;
- memset( cursorNoneBits, 0, sizeof( cursorNoneBits ) );
- memset( &dontCare, 0, sizeof( dontCare ) );
- cursorNonePixmap = XCreateBitmapFromData ( fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.RootWindow,
- cursorNoneBits, 16, 16 );
- if( cursorNonePixmap != None ) {
- cursorNone = XCreatePixmapCursor( fgDisplay.pDisplay.Display,
- cursorNonePixmap, cursorNonePixmap,
- &dontCare, &dontCare, 0, 0 );
- XFreePixmap( fgDisplay.pDisplay.Display, cursorNonePixmap );
- }
- }
- return cursorNone;
-}
-
-typedef struct tag_cursorCacheEntry cursorCacheEntry;
-struct tag_cursorCacheEntry {
- unsigned int cursorShape; /* an XC_foo value */
- Cursor cachedCursor; /* None if the corresponding cursor has
- not been created yet */
-};
-
-/*
- * Note: The arrangement of the table below depends on the fact that
- * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive.
- */
-static cursorCacheEntry cursorCache[] = {
- { XC_arrow, None }, /* GLUT_CURSOR_RIGHT_ARROW */
- { XC_top_left_arrow, None }, /* GLUT_CURSOR_LEFT_ARROW */
- { XC_hand1, None }, /* GLUT_CURSOR_INFO */
- { XC_pirate, None }, /* GLUT_CURSOR_DESTROY */
- { XC_question_arrow, None }, /* GLUT_CURSOR_HELP */
- { XC_exchange, None }, /* GLUT_CURSOR_CYCLE */
- { XC_spraycan, None }, /* GLUT_CURSOR_SPRAY */
- { XC_watch, None }, /* GLUT_CURSOR_WAIT */
- { XC_xterm, None }, /* GLUT_CURSOR_TEXT */
- { XC_crosshair, None }, /* GLUT_CURSOR_CROSSHAIR */
- { XC_sb_v_double_arrow, None }, /* GLUT_CURSOR_UP_DOWN */
- { XC_sb_h_double_arrow, None }, /* GLUT_CURSOR_LEFT_RIGHT */
- { XC_top_side, None }, /* GLUT_CURSOR_TOP_SIDE */
- { XC_bottom_side, None }, /* GLUT_CURSOR_BOTTOM_SIDE */
- { XC_left_side, None }, /* GLUT_CURSOR_LEFT_SIDE */
- { XC_right_side, None }, /* GLUT_CURSOR_RIGHT_SIDE */
- { XC_top_left_corner, None }, /* GLUT_CURSOR_TOP_LEFT_CORNER */
- { XC_top_right_corner, None }, /* GLUT_CURSOR_TOP_RIGHT_CORNER */
- { XC_bottom_right_corner, None }, /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */
- { XC_bottom_left_corner, None } /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */
-};
-
-void fgPlatformSetCursor ( SFG_Window *window, int cursorID )
-{
- Cursor cursor;
- /*
- * XXX FULL_CROSSHAIR demotes to plain CROSSHAIR. Old GLUT allows
- * for this, but if there is a system that easily supports a full-
- * window (or full-screen) crosshair, we might consider it.
- */
- int cursorIDToUse =
- ( cursorID == GLUT_CURSOR_FULL_CROSSHAIR ) ? GLUT_CURSOR_CROSSHAIR : cursorID;
-
- if( ( cursorIDToUse >= 0 ) &&
- ( cursorIDToUse < sizeof( cursorCache ) / sizeof( cursorCache[0] ) ) ) {
- cursorCacheEntry *entry = &cursorCache[ cursorIDToUse ];
- if( entry->cachedCursor == None ) {
- entry->cachedCursor =
- XCreateFontCursor( fgDisplay.pDisplay.Display, entry->cursorShape );
- }
- cursor = entry->cachedCursor;
- } else {
- switch( cursorIDToUse )
- {
- case GLUT_CURSOR_NONE:
- cursor = getEmptyCursor( );
- break;
-
- case GLUT_CURSOR_INHERIT:
- cursor = None;
- break;
-
- default:
- fgError( "Unknown cursor type: %d", cursorIDToUse );
- return;
- }
- }
-
- if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) {
- XUndefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle );
- } else if ( cursor != None ) {
- XDefineCursor( fgDisplay.pDisplay.Display, window->Window.Handle, cursor );
- } else if ( cursorIDToUse != GLUT_CURSOR_NONE ) {
- fgError( "Failed to create cursor" );
- }
-}
-
-
-void fgPlatformWarpPointer ( int x, int y )
-{
- XWarpPointer(
- fgDisplay.pDisplay.Display,
- None,
- fgStructure.CurrentWindow->Window.Handle,
- 0, 0, 0, 0,
- x, y
- );
- /* Make the warp visible immediately. */
- XFlush( fgDisplay.pDisplay.Display );
-}
-
+++ /dev/null
-/*
- * freeglut_display_x11.c
- *
- * Display message posting, context buffer swapping.
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow )
-{
- glXSwapBuffers( pDisplayPtr->Display, CurrentWindow->Window.Handle );
-}
-
+++ /dev/null
-/*
- * freeglut_ext.c
- *
- * Functions related to OpenGL extensions.
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define GLX_GLXEXT_PROTOTYPES
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-GLUTproc fgPlatformGetGLUTProcAddress( const char* procName )
-{
- /* optimization: quick initial check */
- if( strncmp( procName, "glut", 4 ) != 0 )
- return NULL;
-
-#define CHECK_NAME(x) if( strcmp( procName, #x ) == 0) return (GLUTproc)x;
- CHECK_NAME(glutJoystickFunc);
- CHECK_NAME(glutForceJoystickFunc);
- CHECK_NAME(glutGameModeString);
- CHECK_NAME(glutEnterGameMode);
- CHECK_NAME(glutLeaveGameMode);
- CHECK_NAME(glutGameModeGet);
-#undef CHECK_NAME
-
- return NULL;
-}
-
-
-SFG_Proc fgPlatformGetProcAddress( const char *procName )
-{
-#if defined( GLX_ARB_get_proc_address )
- return (SFG_Proc)glXGetProcAddressARB( ( const GLubyte * )procName );
-#else
- return NULL;
-#endif
-}
-
+++ /dev/null
-/*
- * freeglut_gamemode_x11.c
- *
- * The game mode handling code.
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-static int xrandr_resize(int xsz, int ysz, int rate, int just_checking)
-{
-#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
- int event_base, error_base, ver_major, ver_minor, use_rate;
- XRRScreenConfiguration *xrr_config = 0;
- Status result = -1;
-
- /* must check at runtime for the availability of the extension */
- if(!XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {
- return -1;
- }
-
- XRRQueryVersion(fgDisplay.pDisplay.Display, &ver_major, &ver_minor);
-
- /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and
- * the user actually cares about it (rate > 0)
- */
- use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) ||
- ( ( ver_major == 1 ) && ( ver_minor >= 1 ) ) );
-
- /* this loop is only so that the whole thing will be repeated if someone
- * else changes video mode between our query of the current information and
- * the attempt to change it.
- */
- do {
- XRRScreenSize *ssizes;
- short *rates;
- Rotation rot;
- int i, ssizes_count, rates_count, curr, res_idx = -1;
- Time timestamp, cfg_timestamp;
-
- if(xrr_config) {
- XRRFreeScreenConfigInfo(xrr_config);
- }
-
- if(!(xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {
- fgWarning("XRRGetScreenInfo failed");
- break;
- }
- ssizes = XRRConfigSizes(xrr_config, &ssizes_count);
- curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
- timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp);
-
- /* if either of xsz or ysz are unspecified, use the current values */
- if(xsz <= 0)
- xsz = fgState.GameModeSize.X = ssizes[curr].width;
- if(ysz <= 0)
- ysz = fgState.GameModeSize.Y = ssizes[curr].height;
-
-
- if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) {
- /* no need to switch, we're already in the requested resolution */
- res_idx = curr;
- } else {
- for(i=0; i<ssizes_count; i++) {
- if(ssizes[i].width == xsz && ssizes[i].height == ysz) {
- res_idx = i;
- break; /* found it */
- }
- }
- }
- if(res_idx == -1)
- break; /* no matching resolution */
-
-#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
- if(use_rate) {
- rate = fgState.GameModeRefresh;
-
- /* for the selected resolution, let's find out if there is
- * a matching refresh rate available.
- */
- rates = XRRConfigRates(xrr_config, res_idx, &rates_count);
-
- for(i=0; i<rates_count; i++) {
- if(rates[i] == rate) {
- break;
- }
- }
- if(i == rates_count) {
- break; /* no matching rate */
- }
- }
-#endif
-
- if(just_checking) {
- result = 0;
- break;
- }
-
-#if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
- if(use_rate)
- result = XRRSetScreenConfigAndRate(fgDisplay.pDisplay.Display, xrr_config,
- fgDisplay.pDisplay.RootWindow, res_idx, rot, rate, timestamp);
- else
-#endif
- result = XRRSetScreenConfig(fgDisplay.pDisplay.Display, xrr_config,
- fgDisplay.pDisplay.RootWindow, res_idx, rot, timestamp);
-
- } while(result == RRSetConfigInvalidTime);
-
- if(xrr_config) {
- XRRFreeScreenConfigInfo(xrr_config);
- }
-
- if(result == 0) {
- return 0;
- }
-
-#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */
- return -1;
-}
-
-/*
- * Remembers the current visual settings, so that
- * we can change them and restore later...
- */
-void fgPlatformRememberState( void )
-{
- int event_base, error_base;
-
- /*
- * Remember the current pointer location before going fullscreen
- * for restoring it later:
- */
- Window junk_window;
- unsigned int junk_mask;
-
- XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow,
- &junk_window, &junk_window,
- &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY,
- &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask);
-
-# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
- if(XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {
- XRRScreenConfiguration *xrr_config;
- XRRScreenSize *ssizes;
- Rotation rot;
- int ssize_count, curr;
-
- if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) {
- ssizes = XRRConfigSizes(xrr_config, &ssize_count);
- curr = XRRConfigCurrentConfiguration(xrr_config, &rot);
-
- fgDisplay.pDisplay.prev_xsz = ssizes[curr].width;
- fgDisplay.pDisplay.prev_ysz = ssizes[curr].height;
- fgDisplay.pDisplay.prev_refresh = -1;
-
-# if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) )
- if(fgState.GameModeRefresh != -1) {
- fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config);
- }
-# endif
-
- fgDisplay.pDisplay.prev_size_valid = 1;
-
- XRRFreeScreenConfigInfo(xrr_config);
- }
- }
-# endif
-
- /*
- * This highly depends on the XFree86 extensions,
- * not approved as X Consortium standards
- */
-# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
- if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) {
- return;
- }
-
- /*
- * Remember the current ViewPort location of the screen to be able to
- * restore the ViewPort on LeaveGameMode():
- */
- if( !XF86VidModeGetViewPort(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- &fgDisplay.pDisplay.DisplayViewPortX,
- &fgDisplay.pDisplay.DisplayViewPortY ) )
- fgWarning( "XF86VidModeGetViewPort failed" );
-
-
- /* Query the current display settings: */
- fgDisplay.pDisplay.DisplayModeValid =
- XF86VidModeGetModeLine(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- &fgDisplay.pDisplay.DisplayModeClock,
- &fgDisplay.pDisplay.DisplayMode
- );
-
- if( !fgDisplay.pDisplay.DisplayModeValid )
- fgWarning( "XF86VidModeGetModeLine failed" );
-# endif
-
-}
-
-/*
- * Restores the previously remembered visual settings
- */
-void fgPlatformRestoreState( void )
-{
- /* Restore the remembered pointer position: */
- XWarpPointer(
- fgDisplay.pDisplay.Display, None, fgDisplay.pDisplay.RootWindow, 0, 0, 0, 0,
- fgDisplay.pDisplay.DisplayPointerX, fgDisplay.pDisplay.DisplayPointerY
- );
-
-
-# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
- if(fgDisplay.pDisplay.prev_size_valid) {
- if(xrandr_resize(fgDisplay.pDisplay.prev_xsz, fgDisplay.pDisplay.prev_ysz, fgDisplay.pDisplay.prev_refresh, 0) != -1) {
- fgDisplay.pDisplay.prev_size_valid = 0;
-# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
- fgDisplay.pDisplay.DisplayModeValid = 0;
-# endif
- return;
- }
- }
-# endif
-
-
-
-# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
- /*
- * This highly depends on the XFree86 extensions,
- * not approved as X Consortium standards
- */
-
- if( fgDisplay.pDisplay.DisplayModeValid )
- {
- XF86VidModeModeInfo** displayModes;
- int i, displayModesCount;
-
- if( !XF86VidModeGetAllModeLines(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- &displayModesCount,
- &displayModes ) )
- {
- fgWarning( "XF86VidModeGetAllModeLines failed" );
- return;
- }
-
-
- /*
- * Check every of the modes looking for one that matches our demands.
- * If we find one, switch to it and restore the remembered viewport.
- */
- for( i = 0; i < displayModesCount; i++ )
- {
- if(displayModes[ i ]->hdisplay == fgDisplay.pDisplay.DisplayMode.hdisplay &&
- displayModes[ i ]->vdisplay == fgDisplay.pDisplay.DisplayMode.vdisplay &&
- displayModes[ i ]->dotclock == fgDisplay.pDisplay.DisplayModeClock )
- {
- if( !XF86VidModeSwitchToMode(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- displayModes[ i ] ) )
- {
- fgWarning( "XF86VidModeSwitchToMode failed" );
- break;
- }
-
- if( !XF86VidModeSetViewPort(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- fgDisplay.pDisplay.DisplayViewPortX,
- fgDisplay.pDisplay.DisplayViewPortY ) )
- fgWarning( "XF86VidModeSetViewPort failed" );
-
-
- /*
- * For the case this would be the last X11 call the application
- * calls exit() we've to flush the X11 output queue to have the
- * commands sent to the X server before the application exits.
- */
- XFlush( fgDisplay.pDisplay.Display );
-
- fgDisplay.pDisplay.DisplayModeValid = 0;
-# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
- fgDisplay.pDisplay.prev_size_valid = 0;
-# endif
-
- break;
- }
- }
- XFree( displayModes );
- }
-
-# endif
-
-}
-
-#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
-
-/*
- * Checks a single display mode settings against user's preferences.
- */
-static GLboolean fghCheckDisplayMode( int width, int height, int depth, int refresh )
-{
- /* The desired values should be stored in fgState structure... */
- return ( width == fgState.GameModeSize.X ) &&
- ( height == fgState.GameModeSize.Y ) &&
- ( depth == fgState.GameModeDepth ) &&
- ( refresh == fgState.GameModeRefresh );
-}
-
-/*
- * Checks all display modes settings against user's preferences.
- * Returns the mode number found or -1 if none could be found.
- */
-static int fghCheckDisplayModes( GLboolean exactMatch, int displayModesCount, XF86VidModeModeInfo** displayModes )
-{
- int i;
- for( i = 0; i < displayModesCount; i++ )
- {
- /* Compute the displays refresh rate, dotclock comes in kHz. */
- int refresh = ( displayModes[ i ]->dotclock * 1000 ) /
- ( displayModes[ i ]->htotal * displayModes[ i ]->vtotal );
-
- if( fghCheckDisplayMode( displayModes[ i ]->hdisplay,
- displayModes[ i ]->vdisplay,
- fgState.GameModeDepth,
- ( exactMatch ? refresh : fgState.GameModeRefresh ) ) ) {
- if (!exactMatch)
- {
- /* Update the chosen refresh rate, otherwise a
- * glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE) would not
- * return the right values
- */
- fgState.GameModeRefresh = refresh;
- }
-
- return i;
- }
- }
- return -1;
-}
-
-#endif
-
-/*
- * Changes the current display mode to match user's settings
- */
-GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest )
-{
- GLboolean success = GL_FALSE;
- /* first try to use XRandR, then fallback to XF86VidMode */
-# ifdef HAVE_X11_EXTENSIONS_XRANDR_H
- if(xrandr_resize(fgState.GameModeSize.X, fgState.GameModeSize.Y,
- fgState.GameModeRefresh, haveToTest) != -1) {
- return GL_TRUE;
- }
-# endif
-
-
- /*
- * This highly depends on the XFree86 extensions,
- * not approved as X Consortium standards
- */
-# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
-
- /*
- * This is also used by applications which check modes by calling
- * glutGameModeGet(GLUT_GAME_MODE_POSSIBLE), so allow the check:
- */
- if( haveToTest || fgDisplay.pDisplay.DisplayModeValid )
- {
- XF86VidModeModeInfo** displayModes;
- int i, displayModesCount;
-
- /* If we don't have a valid modeline in the display structure, which
- * can happen if this is called from glutGameModeGet instead of
- * glutEnterGameMode, then we need to query the current mode, to make
- * unspecified settings to default to their current values.
- */
- if(!fgDisplay.pDisplay.DisplayModeValid) {
- if(!XF86VidModeGetModeLine(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen,
- &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode)) {
- return success;
- }
- }
-
- if (fgState.GameModeSize.X == -1)
- {
- fgState.GameModeSize.X = fgDisplay.pDisplay.DisplayMode.hdisplay;
- }
- if (fgState.GameModeSize.Y == -1)
- {
- fgState.GameModeSize.Y = fgDisplay.pDisplay.DisplayMode.vdisplay;
- }
- if (fgState.GameModeDepth == -1)
- {
- /* can't get color depth from this, nor can we change it, do nothing
- * TODO: get with XGetVisualInfo()? but then how to set?
- */
- }
- if (fgState.GameModeRefresh == -1)
- {
- /* Compute the displays refresh rate, dotclock comes in kHz. */
- int refresh = ( fgDisplay.pDisplay.DisplayModeClock * 1000 ) /
- ( fgDisplay.pDisplay.DisplayMode.htotal * fgDisplay.pDisplay.DisplayMode.vtotal );
-
- fgState.GameModeRefresh = refresh;
- }
-
- /* query all possible display modes */
- if( !XF86VidModeGetAllModeLines(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- &displayModesCount,
- &displayModes ) )
- {
- fgWarning( "XF86VidModeGetAllModeLines failed" );
- return success;
- }
-
-
- /*
- * Check every of the modes looking for one that matches our demands,
- * ignoring the refresh rate if no exact match could be found.
- */
- i = fghCheckDisplayModes( GL_TRUE, displayModesCount, displayModes );
- if( i < 0 ) {
- i = fghCheckDisplayModes( GL_FALSE, displayModesCount, displayModes );
- }
- success = ( i < 0 ) ? GL_FALSE : GL_TRUE;
-
- if( !haveToTest && success ) {
- if( !XF86VidModeSwitchToMode(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- displayModes[ i ] ) )
- fgWarning( "XF86VidModeSwitchToMode failed" );
- }
-
- XFree( displayModes );
- }
-
-# endif
-
- return success;
-}
-
-
-void fgPlatformEnterGameMode( void )
-{
-
- /*
- * Sync needed to avoid a real race, the Xserver must have really created
- * the window before we can grab the pointer into it:
- */
- XSync( fgDisplay.pDisplay.Display, False );
- /*
- * Grab the pointer to confine it into the window after the calls to
- * XWrapPointer() which ensure that the pointer really enters the window.
- *
- * We also need to wait here until XGrabPointer() returns GrabSuccess,
- * otherwise the new window is not viewable yet and if the next function
- * (XSetInputFocus) is called with a not yet viewable window, it will exit
- * the application which we have to aviod, so wait until it's viewable:
- */
- while( GrabSuccess != XGrabPointer(
- fgDisplay.pDisplay.Display, fgStructure.GameModeWindow->Window.Handle,
- TRUE,
- ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
- | PointerMotionMask,
- GrabModeAsync, GrabModeAsync,
- fgStructure.GameModeWindow->Window.Handle, None, CurrentTime) )
- usleep( 100 );
- /*
- * Change input focus to the new window. This will exit the application
- * if the new window is not viewable yet, see the XGrabPointer loop above.
- */
- XSetInputFocus(
- fgDisplay.pDisplay.Display,
- fgStructure.GameModeWindow->Window.Handle,
- RevertToNone,
- CurrentTime
- );
-
- /* Move the Pointer to the middle of the fullscreen window */
- XWarpPointer(
- fgDisplay.pDisplay.Display,
- None,
- fgDisplay.pDisplay.RootWindow,
- 0, 0, 0, 0,
- fgState.GameModeSize.X/2, fgState.GameModeSize.Y/2
- );
-
-# ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
-
- if( fgDisplay.pDisplay.DisplayModeValid )
- {
- int x, y;
- Window child;
-
- /* Change to viewport to the window topleft edge: */
- if( !XF86VidModeSetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, 0, 0 ) )
- fgWarning( "XF86VidModeSetViewPort failed" );
-
- /*
- * Final window repositioning: It could be avoided using an undecorated
- * window using override_redirect, but this * would possily require
- * more changes and investigation.
- */
-
- /* Get the current postion of the drawable area on screen */
- XTranslateCoordinates(
- fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- fgDisplay.pDisplay.RootWindow,
- 0, 0, &x, &y,
- &child
- );
-
- /* Move the decorataions out of the topleft corner of the display */
- XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
- -x, -y);
- }
-
-#endif
-
- /* Grab the keyboard, too */
- XGrabKeyboard(
- fgDisplay.pDisplay.Display,
- fgStructure.GameModeWindow->Window.Handle,
- FALSE,
- GrabModeAsync, GrabModeAsync,
- CurrentTime
- );
-
-}
-
-void fgPlatformLeaveGameMode( void )
-{
- XUngrabPointer( fgDisplay.pDisplay.Display, CurrentTime );
- XUngrabKeyboard( fgDisplay.pDisplay.Display, CurrentTime );
-}
-
+++ /dev/null
-/*
- * freeglut_glutfont_definitions_x11.c
- *
- * Bitmap and stroke fonts displaying.
- *
- * Copyright (c) 2003 Stephen J. Baker (whether he wants it or not).
- * All Rights Reserved.
- * Written by John F. Fay <fayjf@sourceforge.net>, who releases the
- * copyright over to the "freeglut" project lead.
- * Creation date: Mon July 21 2003
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * This file is necessary for the *nix version of "freeglut" because the
- * original GLUT defined its font variables in rather an unusual way.
- * Publicly, in "glut.h", they were defined as "void *". Privately,
- * in one of the source code files, they were defined as pointers to a
- * structure. Most compilers and linkers are satisfied with the "void *"
- * and don't go any farther, but some of them balked. In particular,
- * when compiling with "freeglut" and then trying to run using the GLUT
- * ".so" library, some of them would give an error. So we are having to
- * create this file to define the variables as pointers to an unusual
- * structure to match GLUT.
- */
-
-/*
- * freeglut_internal.h uses some GL types, but including the GL header portably
- * is a bit tricky, so we include freeglut_std.h here, which contains the
- * necessary machinery. But this poses another problem, caused by the ugly
- * original defintion of the font constants in "classic" GLUT: They are defined
- * as void* externally, so we move them temporarily out of the way by AN EXTREME
- * CPP HACK.
- */
-
-#define glutStrokeRoman glutStrokeRomanIGNOREME
-#define glutStrokeMonoRoman glutStrokeMonoRomanIGNOREME
-#define glutBitmap9By15 glutBitmap9By15IGNOREME
-#define glutBitmap8By13 glutBitmap8By13IGNOREME
-#define glutBitmapTimesRoman10 glutBitmapTimesRoman10IGNOREME
-#define glutBitmapTimesRoman24 glutBitmapTimesRoman24IGNOREME
-#define glutBitmapHelvetica10 glutBitmapHelvetica10IGNOREME
-#define glutBitmapHelvetica12 glutBitmapHelvetica12IGNOREME
-#define glutBitmapHelvetica18 glutBitmapHelvetica18IGNOREME
-
-#include <GL/freeglut_std.h>
-
-#undef glutStrokeRoman
-#undef glutStrokeMonoRoman
-#undef glutBitmap9By15
-#undef glutBitmap8By13
-#undef glutBitmapTimesRoman10
-#undef glutBitmapTimesRoman24
-#undef glutBitmapHelvetica10
-#undef glutBitmapHelvetica12
-#undef glutBitmapHelvetica18
-
-#include "../fg_internal.h"
-
-struct freeglutStrokeFont
-{
- const char *name ;
- int num_chars ;
- void *ch ;
- float top ;
- float bottom ;
-};
-
-struct freeglutBitmapFont
-{
- const char *name ;
- const int num_chars ;
- const int first ;
- const void *ch ;
-};
-
-
-struct freeglutStrokeFont glutStrokeRoman ;
-struct freeglutStrokeFont glutStrokeMonoRoman ;
-
-struct freeglutBitmapFont glutBitmap9By15 ;
-struct freeglutBitmapFont glutBitmap8By13 ;
-struct freeglutBitmapFont glutBitmapTimesRoman10 ;
-struct freeglutBitmapFont glutBitmapTimesRoman24 ;
-struct freeglutBitmapFont glutBitmapHelvetica10 ;
-struct freeglutBitmapFont glutBitmapHelvetica12 ;
-struct freeglutBitmapFont glutBitmapHelvetica18 ;
-
+++ /dev/null
-/*
- * freeglut_init_x11.c
- *
- * Various freeglut initialization functions.
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define FREEGLUT_BUILDING_LIB
-#include <limits.h> /* LONG_MAX */
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-/* Return the atom associated with "name". */
-static Atom fghGetAtom(const char * name)
-{
- return XInternAtom(fgDisplay.pDisplay.Display, name, False);
-}
-
-/*
- * Check if "property" is set on "window". The property's values are returned
- * through "data". If the property is set and is of type "type", return the
- * number of elements in "data". Return zero otherwise. In both cases, use
- * "Xfree()" to free "data".
- */
-static int fghGetWindowProperty(Window window,
- Atom property,
- Atom type,
- unsigned char ** data)
-{
- /*
- * Caller always has to use "Xfree()" to free "data", since
- * "XGetWindowProperty() always allocates one extra byte in prop_return
- * [i.e. "data"] (even if the property is zero length) [..]".
- */
-
- int status; /* Returned by "XGetWindowProperty". */
-
- Atom type_returned;
- int temp_format; /* Not used. */
- unsigned long number_of_elements;
- unsigned long temp_bytes_after; /* Not used. */
-
-
- status = XGetWindowProperty(fgDisplay.pDisplay.Display,
- window,
- property,
- 0,
- LONG_MAX,
- False,
- type,
- &type_returned,
- &temp_format,
- &number_of_elements,
- &temp_bytes_after,
- data);
-
- FREEGLUT_INTERNAL_ERROR_EXIT(status == Success,
- "XGetWindowProperty failled",
- "fghGetWindowProperty");
-
- if (type_returned != type)
- {
- number_of_elements = 0;
- }
-
- return number_of_elements;
-}
-
-/* Check if the window manager is NET WM compliant. */
-static int fghNetWMSupported(void)
-{
- Atom wm_check;
- Window ** window_ptr_1;
-
- int number_of_windows;
- int net_wm_supported;
-
-
- net_wm_supported = 0;
-
- wm_check = fghGetAtom("_NET_SUPPORTING_WM_CHECK");
- window_ptr_1 = malloc(sizeof(Window *));
-
- /*
- * Check that the window manager has set this property on the root window.
- * The property must be the ID of a child window.
- */
- number_of_windows = fghGetWindowProperty(fgDisplay.pDisplay.RootWindow,
- wm_check,
- XA_WINDOW,
- (unsigned char **) window_ptr_1);
- if (number_of_windows == 1)
- {
- Window ** window_ptr_2;
-
- window_ptr_2 = malloc(sizeof(Window *));
-
- /* Check that the window has the same property set to the same value. */
- number_of_windows = fghGetWindowProperty(**window_ptr_1,
- wm_check,
- XA_WINDOW,
- (unsigned char **) window_ptr_2);
- if ((number_of_windows == 1) && (**window_ptr_1 == **window_ptr_2))
- {
- /* NET WM compliant */
- net_wm_supported = 1;
- }
-
- XFree(*window_ptr_2);
- free(window_ptr_2);
- }
-
- XFree(*window_ptr_1);
- free(window_ptr_1);
-
- return net_wm_supported;
-}
-
-/* Check if "hint" is present in "property" for "window". */
-int fgHintPresent(Window window, Atom property, Atom hint)
-{
- Atom *atoms;
- int number_of_atoms;
- int supported;
- int i;
-
- supported = 0;
-
- number_of_atoms = fghGetWindowProperty(window,
- property,
- XA_ATOM,
- (unsigned char **) &atoms);
- for (i = 0; i < number_of_atoms; i++)
- {
- if (atoms[i] == hint)
- {
- supported = 1;
- break;
- }
- }
-
- XFree(atoms);
- return supported;
-}
-
-/*
- * A call to this function should initialize all the display stuff...
- */
-void fgPlatformInitialize( const char* displayName )
-{
- fgDisplay.pDisplay.Display = XOpenDisplay( displayName );
-
- if( fgDisplay.pDisplay.Display == NULL )
- fgError( "failed to open display '%s'", XDisplayName( displayName ) );
-
- if( !glXQueryExtension( fgDisplay.pDisplay.Display, NULL, NULL ) )
- fgError( "OpenGL GLX extension not supported by display '%s'",
- XDisplayName( displayName ) );
-
- fgDisplay.pDisplay.Screen = DefaultScreen( fgDisplay.pDisplay.Display );
- fgDisplay.pDisplay.RootWindow = RootWindow(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen
- );
-
- fgDisplay.ScreenWidth = DisplayWidth(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen
- );
- fgDisplay.ScreenHeight = DisplayHeight(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen
- );
-
- fgDisplay.ScreenWidthMM = DisplayWidthMM(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen
- );
- fgDisplay.ScreenHeightMM = DisplayHeightMM(
- fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen
- );
-
- fgDisplay.pDisplay.Connection = ConnectionNumber( fgDisplay.pDisplay.Display );
-
- /* Create the window deletion atom */
- fgDisplay.pDisplay.DeleteWindow = fghGetAtom("WM_DELETE_WINDOW");
-
- /* Create the state and full screen atoms */
- fgDisplay.pDisplay.State = None;
- fgDisplay.pDisplay.StateFullScreen = None;
-
- if (fghNetWMSupported())
- {
- const Atom supported = fghGetAtom("_NET_SUPPORTED");
- const Atom state = fghGetAtom("_NET_WM_STATE");
-
- /* Check if the state hint is supported. */
- if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, state))
- {
- const Atom full_screen = fghGetAtom("_NET_WM_STATE_FULLSCREEN");
-
- fgDisplay.pDisplay.State = state;
-
- /* Check if the window manager supports full screen. */
- /** Check "_NET_WM_ALLOWED_ACTIONS" on our window instead? **/
- if (fgHintPresent(fgDisplay.pDisplay.RootWindow, supported, full_screen))
- {
- fgDisplay.pDisplay.StateFullScreen = full_screen;
- }
- }
- }
-
-
- fgState.Initialised = GL_TRUE;
-
- atexit(fgDeinitialize);
-
- /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */
- fgInitialiseInputDevices();
-}
-
-void fgPlatformDeinitialiseInputDevices ( void )
-{
- fghCloseInputDevices ();
-
- fgState.JoysticksInitialised = GL_FALSE;
- fgState.InputDevsInitialised = GL_FALSE;
-}
-
-
-void fgPlatformCloseDisplay ( void )
-{
- /*
- * Make sure all X-client data we have created will be destroyed on
- * display closing
- */
- XSetCloseDownMode( fgDisplay.pDisplay.Display, DestroyAll );
-
- /*
- * Close the display connection, destroying all windows we have
- * created so far
- */
- XCloseDisplay( fgDisplay.pDisplay.Display );
-}
-
-
-void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext )
-{
- /* Note that the MVisualInfo is not owned by the MenuContext! */
- glXDestroyContext( pDisplay.Display, MContext );
-}
+++ /dev/null
-/*
- * freeglut_input_devices_x11.c
- *
- * Handles miscellaneous input devices via direct serial-port access.
- * Proper X11 XInput device support is not yet supported.
- * Also lacks Mac support.
- *
- * Written by Joe Krahn <krahn@niehs.nih.gov> 2005
- *
- * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved.
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA OR STEPHEN J. BAKER BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <fcntl.h>
-
-struct _serialport {
- int fd;
- struct termios termio, termio_save;
-};
-
-typedef struct _serialport SERIALPORT;
-
-void serial_flush ( SERIALPORT *port );
-
-/* local variables */
-static SERIALPORT *dialbox_port=NULL;
-
-/*****************************************************************/
-
-/*
- * Try initializing the input device(s)
- */
-void fgPlatformRegisterDialDevice ( const char *dial_device )
-{
-}
-
-SERIALPORT *serial_open ( const char *device )
-{
- int fd;
- struct termios termio;
- SERIALPORT *port;
-
- fd = open(device, O_RDWR | O_NONBLOCK );
- if (fd <0) {
- perror(device);
- return NULL;
- }
-
- port = malloc(sizeof(SERIALPORT));
- memset(port, 0, sizeof(SERIALPORT));
- port->fd = fd;
-
- /* save current port settings */
- tcgetattr(fd,&port->termio_save);
-
- memset(&termio, 0, sizeof(termio));
- termio.c_cflag = CS8 | CREAD | HUPCL ;
- termio.c_iflag = IGNPAR | IGNBRK ;
- termio.c_cc[VTIME] = 0; /* inter-character timer */
- termio.c_cc[VMIN] = 1; /* block read until 1 chars received, when blocking I/O */
-
- cfsetispeed(&termio, B9600);
- cfsetospeed(&termio, B9600);
- tcsetattr(fd,TCSANOW,&termio);
-
- serial_flush(port);
- return port;
-}
-
-void serial_close(SERIALPORT *port)
-{
- if (port)
- {
- /* restore old port settings */
- tcsetattr(port->fd,TCSANOW,&port->termio_save);
- close(port->fd);
- free(port);
- }
-}
-
-int serial_getchar(SERIALPORT *port)
-{
- unsigned char ch;
- if (!port) return EOF;
- if (read(port->fd,&ch,1)) return ch;
- return EOF;
-}
-
-int serial_putchar(SERIALPORT *port, unsigned char ch)
-{
- if (!port) return 0;
- return write(port->fd,&ch,1);
-}
-
-void serial_flush ( SERIALPORT *port )
-{
- tcflush ( port->fd, TCIOFLUSH );
-}
+++ /dev/null
-/*
- * freeglut_internal_x11.h
- *
- * The freeglut library private include file.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by Diederick C. Niehorster, <dcnieho@gmail.com>
- * Creation date: Fri Jan 20, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef FREEGLUT_INTERNAL_X11_H
-#define FREEGLUT_INTERNAL_X11_H
-
-
-/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */
-#include <GL/glx.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XInput.h>
-#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
-# include <X11/extensions/xf86vmode.h>
-#endif
-#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
-# include <X11/extensions/Xrandr.h>
-#endif
-/* If GLX is too old, we will fail during runtime when multisampling
- is requested, but at least freeglut compiles. */
-#ifndef GLX_SAMPLE_BUFFERS
-# define GLX_SAMPLE_BUFFERS 0x80A8
-#endif
-#ifndef GLX_SAMPLES
-# define GLX_SAMPLES 0x80A9
-#endif
-
-
-
-/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */
-/* The structure used by display initialization in freeglut_init.c */
-typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay;
-struct tagSFG_PlatformDisplay
-{
- Display* Display; /* The display we are being run in. */
- int Screen; /* The screen we are about to use. */
- Window RootWindow; /* The screen's root window. */
- int Connection; /* The display's connection number */
- Atom DeleteWindow; /* The window deletion atom */
- Atom State; /* The state atom */
- Atom StateFullScreen; /* The full screen atom */
-
-#ifdef HAVE_X11_EXTENSIONS_XRANDR_H
- int prev_xsz, prev_ysz;
- int prev_refresh;
- int prev_size_valid;
-#endif /* HAVE_X11_EXTENSIONS_XRANDR_H */
-
-#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
- /*
- * XF86VidMode may be compilable even if it fails at runtime. Therefore,
- * the validity of the VidMode has to be tracked
- */
- int DisplayModeValid; /* Flag that indicates runtime status*/
- XF86VidModeModeLine DisplayMode; /* Current screen's display settings */
- int DisplayModeClock; /* The display mode's refresh rate */
- int DisplayViewPortX; /* saved X location of the viewport */
- int DisplayViewPortY; /* saved Y location of the viewport */
-#endif /* HAVE_X11_EXTENSIONS_XF86VMODE_H */
-
- int DisplayPointerX; /* saved X location of the pointer */
- int DisplayPointerY; /* saved Y location of the pointer */
-};
-
-
-/*
- * Make "freeglut" window handle and context types so that we don't need so
- * much conditionally-compiled code later in the library.
- */
-typedef Window SFG_WindowHandleType ;
-typedef GLXContext SFG_WindowContextType ;
-typedef struct tagSFG_PlatformContext SFG_PlatformContext;
-struct tagSFG_PlatformContext
-{
- GLXFBConfig* FBConfig; /* The window's FBConfig */
-};
-
-
-/* Window's state description. This structure should be kept portable. */
-typedef struct tagSFG_PlatformWindowState SFG_PlatformWindowState;
-struct tagSFG_PlatformWindowState
-{
- int OldWidth; /* Window width from before a resize */
- int OldHeight; /* " height " " " " */
-};
-
-
-/* -- JOYSTICK-SPECIFIC STRUCTURES AND TYPES ------------------------------- */
-/*
- * Initial defines from "js.h" starting around line 33 with the existing "freeglut_joystick.c"
- * interspersed
- */
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif
-# ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-# endif
-# ifdef HAVE_ERRNO_H
-# include <errno.h>
-# include <string.h>
-# endif
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
-/* XXX The below hack is done until freeglut's autoconf is updated. */
-# define HAVE_USB_JS 1
-
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-# include <sys/joystick.h>
-# else
-/*
- * XXX NetBSD/amd64 systems may find that they have to steal the
- * XXX /usr/include/machine/joystick.h from a NetBSD/i386 system.
- * XXX I cannot comment whether that works for the interface, but
- * XXX it lets you compile...(^& I do not think that we can do away
- * XXX with this header.
- */
-# include <machine/joystick.h> /* For analog joysticks */
-# endif
-# define JS_DATA_TYPE joystick
-# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
-# endif
-
-# if defined(__linux__)
-# include <linux/joystick.h>
-
-/* check the joystick driver version */
-# if defined(JS_VERSION) && JS_VERSION >= 0x010000
-# define JS_NEW
-# endif
-# else /* Not BSD or Linux */
-# ifndef JS_RETURN
-
- /*
- * We'll put these values in and that should
- * allow the code to at least compile when there is
- * no support. The JS open routine should error out
- * and shut off all the code downstream anyway and if
- * the application doesn't use a joystick we'll be fine.
- */
-
- struct JS_DATA_TYPE
- {
- int buttons;
- int x;
- int y;
- };
-
-# define JS_RETURN (sizeof(struct JS_DATA_TYPE))
-# endif
-# endif
-
-/* XXX It might be better to poll the operating system for the numbers of buttons and
- * XXX axes and then dynamically allocate the arrays.
- */
-# define _JS_MAX_AXES 16
-typedef struct tagSFG_PlatformJoystick SFG_PlatformJoystick;
-struct tagSFG_PlatformJoystick
-{
-# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
- struct os_specific_s *os;
-# endif
-
-# ifdef JS_NEW
- struct js_event js;
- int tmp_buttons;
- float tmp_axes [ _JS_MAX_AXES ];
-# else
- struct JS_DATA_TYPE js;
-# endif
-
- char fname [ 128 ];
- int fd;
-};
-
-
-/* Menu font and color definitions */
-#define FREEGLUT_MENU_FONT GLUT_BITMAP_HELVETICA_18
-
-#define FREEGLUT_MENU_PEN_FORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
-#define FREEGLUT_MENU_PEN_BACK_COLORS {0.70f, 0.70f, 0.70f, 1.0f}
-#define FREEGLUT_MENU_PEN_HFORE_COLORS {0.0f, 0.0f, 0.0f, 1.0f}
-#define FREEGLUT_MENU_PEN_HBACK_COLORS {1.0f, 1.0f, 1.0f, 1.0f}
-
-
-
-
-/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */
-/* spaceball device functions, defined in freeglut_spaceball.c */
-int fgIsSpaceballXEvent( const XEvent *ev );
-void fgSpaceballHandleXEvent( const XEvent *ev );
-
-/*
- * Check if "hint" is present in "property" for "window". See freeglut_init.c
- */
-int fgHintPresent(Window window, Atom property, Atom hint);
-
-/* Handler for X extension Events */
-#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
- void fgHandleExtensionEvents( XEvent * ev );
- void fgRegisterDevices( Display* dpy, Window* win );
-#endif
-
-
-#endif /* FREEGLUT_INTERNAL_X11_H */
+++ /dev/null
-/*
- * freeglut_joystick_x11.c
- *
- * Joystick handling code
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Steve Baker, <sjbaker1@airmail.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/*
- * FreeBSD port by Stephen Montgomery-Smith <stephen@math.missouri.edu>
- *
- * Redone by John Fay 2/4/04 with another look from the PLIB "js" library.
- * Many thanks for Steve Baker for permission to pull from that library.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-
-
-/*this should be defined in a header file */
-#define MAX_NUM_JOYSTICKS 2
-extern SFG_Joystick *fgJoystick [ MAX_NUM_JOYSTICKS ];
-
-void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )
-{
- int status;
-
- int i;
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
- int len;
-
- if ( joy->pJoystick.os->is_analog )
- {
- int status = read ( joy->pJoystick.os->fd, &joy->pJoystick.os->ajs, sizeof(joy->pJoystick.os->ajs) );
- if ( status != sizeof(joy->pJoystick.os->ajs) ) {
- perror ( joy->pJoystick.os->fname );
- joy->error = GL_TRUE;
- return;
- }
- if ( buttons != NULL )
- *buttons = ( joy->pJoystick.os->ajs.b1 ? 1 : 0 ) | ( joy->pJoystick.os->ajs.b2 ? 2 : 0 );
-
- if ( axes != NULL )
- {
- axes[0] = (float) joy->pJoystick.os->ajs.x;
- axes[1] = (float) joy->pJoystick.os->ajs.y;
- }
-
- return;
- }
-
-# ifdef HAVE_USB_JS
- while ( ( len = read ( joy->pJoystick.os->fd, joy->pJoystick.os->hid_data_buf, joy->pJoystick.os->hid_dlen ) ) == joy->pJoystick.os->hid_dlen )
- {
- struct hid_item *h;
-
- for ( h = joy->pJoystick.os->hids; h; h = h->next )
- {
- int d = hid_get_data ( joy->pJoystick.os->hid_data_buf, h );
-
- int page = HID_PAGE ( h->usage );
- int usage = HID_USAGE ( h->usage );
-
- if ( page == HUP_GENERIC_DESKTOP )
- {
- int i;
- for ( i = 0; i < joy->num_axes; i++ )
- if (joy->pJoystick.os->axes_usage[i] == usage)
- {
- if (usage == HUG_HAT_SWITCH)
- {
- if (d < 0 || d > 8)
- d = 0; /* safety */
- joy->pJoystick.os->cache_axes[i] = (float)hatmap_x[d];
- joy->pJoystick.os->cache_axes[i + 1] = (float)hatmap_y[d];
- }
- else
- {
- joy->pJoystick.os->cache_axes[i] = (float)d;
- }
- break;
- }
- }
- else if (page == HUP_BUTTON)
- {
- if (usage > 0 && usage < _JS_MAX_BUTTONS + 1)
- {
- if (d)
- joy->pJoystick.os->cache_buttons |= (1 << ( usage - 1 ));
- else
- joy->pJoystick.os->cache_buttons &= ~(1 << ( usage - 1 ));
- }
- }
- }
- }
-# ifdef HAVE_ERRNO_H
- if ( len < 0 && errno != EAGAIN )
-# else
- if ( len < 0 )
-# endif
- {
- perror( joy->pJoystick.os->fname );
- joy->error = 1;
- }
- if ( buttons != NULL ) *buttons = joy->pJoystick.os->cache_buttons;
- if ( axes != NULL )
- memcpy ( axes, joy->pJoystick.os->cache_axes, sizeof(float) * joy->num_axes );
-# endif
-#endif
-
-#ifdef JS_NEW
-
- while ( 1 )
- {
- status = read ( joy->pJoystick.fd, &joy->pJoystick.js, sizeof(struct js_event) );
-
- if ( status != sizeof( struct js_event ) )
- {
-# ifdef HAVE_ERRNO_H
- if ( errno == EAGAIN )
- {
- /* Use the old values */
- if ( buttons )
- *buttons = joy->pJoystick.tmp_buttons;
- if ( axes )
- memcpy( axes, joy->pJoystick.tmp_axes,
- sizeof( float ) * joy->num_axes );
- return;
- }
-# endif
-
- fgWarning ( "%s", joy->pJoystick.fname );
- joy->error = GL_TRUE;
- return;
- }
-
- switch ( joy->pJoystick.js.type & ~JS_EVENT_INIT )
- {
- case JS_EVENT_BUTTON:
- if( joy->pJoystick.js.value == 0 ) /* clear the flag */
- joy->pJoystick.tmp_buttons &= ~( 1 << joy->pJoystick.js.number );
- else
- joy->pJoystick.tmp_buttons |= ( 1 << joy->pJoystick.js.number );
- break;
-
- case JS_EVENT_AXIS:
- if ( joy->pJoystick.js.number < joy->num_axes )
- {
- joy->pJoystick.tmp_axes[ joy->pJoystick.js.number ] = ( float )joy->pJoystick.js.value;
-
- if( axes )
- memcpy( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes );
- }
- break;
-
- default:
- fgWarning ( "PLIB_JS: Unrecognised /dev/js return!?!" );
-
- /* use the old values */
-
- if ( buttons != NULL ) *buttons = joy->pJoystick.tmp_buttons;
- if ( axes != NULL )
- memcpy ( axes, joy->pJoystick.tmp_axes, sizeof(float) * joy->num_axes );
-
- return;
- }
-
- if( buttons )
- *buttons = joy->pJoystick.tmp_buttons;
- }
-#else
-
- status = read( joy->pJoystick.fd, &joy->pJoystick.js, JS_RETURN );
-
- if ( status != JS_RETURN )
- {
- fgWarning( "%s", joy->pJoystick.fname );
- joy->error = GL_TRUE;
- return;
- }
-
- if ( buttons )
-# if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
- *buttons = ( joy->pJoystick.js.b1 ? 1 : 0 ) | ( joy->pJoystick.js.b2 ? 2 : 0 ); /* XXX Should not be here -- BSD is handled earlier */
-# else
- *buttons = joy->pJoystick.js.buttons;
-# endif
-
- if ( axes )
- {
- axes[ 0 ] = (float) joy->pJoystick.js.x;
- axes[ 1 ] = (float) joy->pJoystick.js.y;
- }
-#endif
-}
-
-
-void fgPlatformJoystickOpen( SFG_Joystick* joy )
-{
-#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
- int i = 0;
- char *cp;
-#endif
-#ifdef JS_NEW
- unsigned char u;
- int i=0;
-#else
-# if defined( __linux__ ) || TARGET_HOST_SOLARIS
- int i = 0;
- int counter = 0;
-# endif
-#endif
-
-#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
- for( i = 0; i < _JS_MAX_AXES; i++ )
- joy->pJoystick.os->cache_axes[ i ] = 0.0f;
-
- joy->pJoystick.os->cache_buttons = 0;
-
- joy->pJoystick.os->fd = open( joy->pJoystick.os->fname, O_RDONLY | O_NONBLOCK);
-
-#ifdef HAVE_ERRNO_H
- if( joy->pJoystick.os->fd < 0 && errno == EACCES )
- fgWarning ( "%s exists but is not readable by you", joy->pJoystick.os->fname );
-#endif
-
- joy->error =( joy->pJoystick.os->fd < 0 );
-
- if( joy->error )
- return;
-
- joy->num_axes = 0;
- joy->num_buttons = 0;
- if( joy->pJoystick.os->is_analog )
- {
- FILE *joyfile;
- char joyfname[ 1024 ];
- int noargs, in_no_axes;
-
- float axes [ _JS_MAX_AXES ];
- int buttons[ _JS_MAX_AXES ];
-
- joy->num_axes = 2;
- joy->num_buttons = 32;
-
- fghJoystickRawRead( joy, buttons, axes );
- joy->error = axes[ 0 ] < -1000000000.0f;
- if( joy->error )
- return;
-
- snprintf( joyfname, sizeof(joyfname), "%s/.joy%drc", getenv( "HOME" ), joy->id );
-
- joyfile = fopen( joyfname, "r" );
- joy->error =( joyfile == NULL );
- if( joy->error )
- return;
-
- noargs = fscanf( joyfile, "%d%f%f%f%f%f%f", &in_no_axes,
- &joy->min[ 0 ], &joy->center[ 0 ], &joy->max[ 0 ],
- &joy->min[ 1 ], &joy->center[ 1 ], &joy->max[ 1 ] );
- joy->error = noargs != 7 || in_no_axes != _JS_MAX_AXES;
- fclose( joyfile );
- if( joy->error )
- return;
-
- for( i = 0; i < _JS_MAX_AXES; i++ )
- {
- joy->dead_band[ i ] = 0.0f;
- joy->saturate [ i ] = 1.0f;
- }
-
- return; /* End of analog code */
- }
-
-# ifdef HAVE_USB_JS
- if( ! fghJoystickInitializeHID( joy->pJoystick.os, &joy->num_axes,
- &joy->num_buttons ) )
- {
- close( joy->pJoystick.os->fd );
- joy->error = GL_TRUE;
- return;
- }
-
- cp = strrchr( joy->pJoystick.os->fname, '/' );
- if( cp )
- {
- if( fghJoystickFindUSBdev( &cp[1], joy->name, sizeof( joy->name ) ) ==
- 0 )
- strcpy( joy->name, &cp[1] );
- }
-
- if( joy->num_axes > _JS_MAX_AXES )
- joy->num_axes = _JS_MAX_AXES;
-
- for( i = 0; i < _JS_MAX_AXES; i++ )
- {
- /* We really should get this from the HID, but that data seems
- * to be quite unreliable for analog-to-USB converters. Punt for
- * now.
- */
- if( joy->pJoystick.os->axes_usage[ i ] == HUG_HAT_SWITCH )
- {
- joy->max [ i ] = 1.0f;
- joy->center[ i ] = 0.0f;
- joy->min [ i ] = -1.0f;
- }
- else
- {
- joy->max [ i ] = 255.0f;
- joy->center[ i ] = 127.0f;
- joy->min [ i ] = 0.0f;
- }
-
- joy->dead_band[ i ] = 0.0f;
- joy->saturate[ i ] = 1.0f;
- }
-# endif
-#endif
-
-#if defined( __linux__ ) || TARGET_HOST_SOLARIS
- /* Default for older Linux systems. */
- joy->num_axes = 2;
- joy->num_buttons = 32;
-
-# ifdef JS_NEW
- for( i = 0; i < _JS_MAX_AXES; i++ )
- joy->pJoystick.tmp_axes[ i ] = 0.0f;
-
- joy->pJoystick.tmp_buttons = 0;
-# endif
-
- joy->pJoystick.fd = open( joy->pJoystick.fname, O_RDONLY );
-
- joy->error =( joy->pJoystick.fd < 0 );
-
- if( joy->error )
- return;
-
- /* Set the correct number of axes for the linux driver */
-# ifdef JS_NEW
- /* Melchior Franz's fixes for big-endian Linuxes since writing
- * to the upper byte of an uninitialized word doesn't work.
- * 9 April 2003
- */
- ioctl( joy->pJoystick.fd, JSIOCGAXES, &u );
- joy->num_axes = u;
- ioctl( joy->pJoystick.fd, JSIOCGBUTTONS, &u );
- joy->num_buttons = u;
- ioctl( joy->pJoystick.fd, JSIOCGNAME( sizeof( joy->name ) ), joy->name );
- fcntl( joy->pJoystick.fd, F_SETFL, O_NONBLOCK );
-# endif
-
- /*
- * The Linux driver seems to return 512 for all axes
- * when no stick is present - but there is a chance
- * that could happen by accident - so it's gotta happen
- * on both axes for at least 100 attempts.
- *
- * PWO: shouldn't be that done somehow wiser on the kernel level?
- */
-# ifndef JS_NEW
- counter = 0;
-
- do
- {
- fghJoystickRawRead( joy, NULL, joy->center );
- counter++;
- } while( !joy->error &&
- counter < 100 &&
- joy->center[ 0 ] == 512.0f &&
- joy->center[ 1 ] == 512.0f );
-
- if ( counter >= 100 )
- joy->error = GL_TRUE;
-# endif
-
- for( i = 0; i < _JS_MAX_AXES; i++ )
- {
-# ifdef JS_NEW
- joy->max [ i ] = 32767.0f;
- joy->center[ i ] = 0.0f;
- joy->min [ i ] = -32767.0f;
-# else
- joy->max[ i ] = joy->center[ i ] * 2.0f;
- joy->min[ i ] = 0.0f;
-# endif
- joy->dead_band[ i ] = 0.0f;
- joy->saturate [ i ] = 1.0f;
- }
-#endif
-}
-
-
-void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )
-{
-#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
- fgJoystick[ ident ]->id = ident;
- fgJoystick[ ident ]->error = GL_FALSE;
-
- fgJoystick[ ident ]->pJoystick.os = calloc( 1, sizeof( struct os_specific_s ) );
- memset( fgJoystick[ ident ]->pJoystick.os, 0, sizeof( struct os_specific_s ) );
- if( ident < USB_IDENT_OFFSET )
- fgJoystick[ ident ]->pJoystick.os->is_analog = 1;
- if( fgJoystick[ ident ]->pJoystick.os->is_analog )
- snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", AJSDEV, ident );
- else
- snprintf( fgJoystick[ ident ]->pJoystick.os->fname, sizeof(fgJoystick[ ident ]->pJoystick.os->fname), "%s%d", UHIDDEV,
- ident - USB_IDENT_OFFSET );
-#elif defined( __linux__ )
- fgJoystick[ ident ]->id = ident;
- fgJoystick[ ident ]->error = GL_FALSE;
-
- snprintf( fgJoystick[ident]->pJoystick.fname, sizeof(fgJoystick[ident]->pJoystick.fname), "/dev/input/js%d", ident );
-
- if( access( fgJoystick[ ident ]->pJoystick.fname, F_OK ) != 0 )
- snprintf( fgJoystick[ ident ]->pJoystick.fname, sizeof(fgJoystick[ ident ]->pJoystick.fname), "/dev/js%d", ident );
-#endif
-}
-
-
-void fgPlatformJoystickClose ( int ident )
-{
-#if defined( __FreeBSD__ ) || defined(__FreeBSD_kernel__) || defined( __NetBSD__ )
- if( fgJoystick[ident]->pJoystick.os )
- {
- if( ! fgJoystick[ ident ]->error )
- close( fgJoystick[ ident ]->pJoystick.os->fd );
-#ifdef HAVE_USB_JS
- if( fgJoystick[ ident ]->pJoystick.os->hids )
- free (fgJoystick[ ident ]->pJoystick.os->hids);
- if( fgJoystick[ ident ]->pJoystick.os->hid_data_buf )
- free( fgJoystick[ ident ]->pJoystick.os->hid_data_buf );
-#endif
- free( fgJoystick[ident]->pJoystick.os );
- }
-#endif
-
- if( ! fgJoystick[ident]->error )
- close( fgJoystick[ ident ]->pJoystick.fd );
-}
-
+++ /dev/null
-/*
- * freeglut_main_x11.c
- *
- * The X11-specific windows message processing methods.
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
-#include <stdarg.h>
-#ifdef HAVE_VFPRINTF
-# define VFPRINTF(s,f,a) vfprintf((s),(f),(a))
-#elif defined(HAVE__DOPRNT)
-# define VFPRINTF(s,f,a) _doprnt((f),(a),(s))
-#else
-# define VFPRINTF(s,f,a)
-#endif
-
-/*
- * Try to get the maximum value allowed for ints, falling back to the minimum
- * guaranteed by ISO C99 if there is no suitable header.
- */
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-#ifndef INT_MAX
-# define INT_MAX 32767
-#endif
-
-#ifndef MIN
-# define MIN(a,b) (((a)<(b)) ? (a) : (b))
-#endif
-
-/*
- * TODO BEFORE THE STABLE RELEASE:
- *
- * There are some issues concerning window redrawing under X11, and maybe
- * some events are not handled. The Win32 version lacks some more features,
- * but seems acceptable for not demanding purposes.
- *
- * Need to investigate why the X11 version breaks out with an error when
- * closing a window (using the window manager, not glutDestroyWindow)...
- */
-
-
-/*
- * Handle a window configuration change. When no reshape
- * callback is hooked, the viewport size is updated to
- * match the new window size.
- */
-void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
-{
- XResizeWindow( fgDisplay.pDisplay.Display, window->Window.Handle,
- width, height );
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-
-/*
- * A static helper function to execute display callback for a window
- */
-void fgPlatformDisplayWindow ( SFG_Window *window )
-{
- fghRedrawWindow ( window ) ;
-}
-
-
-fg_time_t fgPlatformSystemTime ( void )
-{
-#ifdef CLOCK_MONOTONIC
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- return now.tv_nsec/1000000 + now.tv_sec*1000;
-#elif defined(HAVE_GETTIMEOFDAY)
- struct timeval now;
- gettimeofday( &now, NULL );
- return now.tv_usec/1000 + now.tv_sec*1000;
-#endif
-}
-
-/*
- * Does the magic required to relinquish the CPU until something interesting
- * happens.
- */
-
-void fgPlatformSleepForEvents( fg_time_t msec )
-{
- /*
- * Possibly due to aggressive use of XFlush() and friends,
- * 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 the event-reading loop, in any case, so we
- * need to allow that we may have an empty socket but non-
- * empty event queue.
- */
- if( ! XPending( fgDisplay.pDisplay.Display ) )
- {
- fd_set fdset;
- int err;
- int socket;
- struct timeval wait;
-
- socket = ConnectionNumber( fgDisplay.pDisplay.Display );
- FD_ZERO( &fdset );
- FD_SET( socket, &fdset );
- wait.tv_sec = msec / 1000;
- wait.tv_usec = (msec % 1000) * 1000;
- err = select( socket+1, &fdset, NULL, NULL, &wait );
-
-#ifdef HAVE_ERRNO_H
- if( ( -1 == err ) && ( errno != EINTR ) )
- fgWarning ( "freeglut select() error: %d", errno );
-#endif
- }
-}
-
-
-/*
- * Returns GLUT modifier mask for the state field of an X11 event.
- */
-int fgPlatformGetModifiers( int state )
-{
- int ret = 0;
-
- if( state & ( ShiftMask | LockMask ) )
- ret |= GLUT_ACTIVE_SHIFT;
- if( state & ControlMask )
- ret |= GLUT_ACTIVE_CTRL;
- if( state & Mod1Mask )
- ret |= GLUT_ACTIVE_ALT;
-
- return ret;
-}
-
-static const char* fghTypeToString( int type )
-{
- switch( type ) {
- case KeyPress: return "KeyPress";
- case KeyRelease: return "KeyRelease";
- case ButtonPress: return "ButtonPress";
- case ButtonRelease: return "ButtonRelease";
- case MotionNotify: return "MotionNotify";
- case EnterNotify: return "EnterNotify";
- case LeaveNotify: return "LeaveNotify";
- case FocusIn: return "FocusIn";
- case FocusOut: return "FocusOut";
- case KeymapNotify: return "KeymapNotify";
- case Expose: return "Expose";
- case GraphicsExpose: return "GraphicsExpose";
- case NoExpose: return "NoExpose";
- case VisibilityNotify: return "VisibilityNotify";
- case CreateNotify: return "CreateNotify";
- case DestroyNotify: return "DestroyNotify";
- case UnmapNotify: return "UnmapNotify";
- case MapNotify: return "MapNotify";
- case MapRequest: return "MapRequest";
- case ReparentNotify: return "ReparentNotify";
- case ConfigureNotify: return "ConfigureNotify";
- case ConfigureRequest: return "ConfigureRequest";
- case GravityNotify: return "GravityNotify";
- case ResizeRequest: return "ResizeRequest";
- case CirculateNotify: return "CirculateNotify";
- case CirculateRequest: return "CirculateRequest";
- case PropertyNotify: return "PropertyNotify";
- case SelectionClear: return "SelectionClear";
- case SelectionRequest: return "SelectionRequest";
- case SelectionNotify: return "SelectionNotify";
- case ColormapNotify: return "ColormapNotify";
- case ClientMessage: return "ClientMessage";
- case MappingNotify: return "MappingNotify";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghBoolToString( Bool b )
-{
- return b == False ? "False" : "True";
-}
-
-static const char* fghNotifyHintToString( char is_hint )
-{
- switch( is_hint ) {
- case NotifyNormal: return "NotifyNormal";
- case NotifyHint: return "NotifyHint";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghNotifyModeToString( int mode )
-{
- switch( mode ) {
- case NotifyNormal: return "NotifyNormal";
- case NotifyGrab: return "NotifyGrab";
- case NotifyUngrab: return "NotifyUngrab";
- case NotifyWhileGrabbed: return "NotifyWhileGrabbed";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghNotifyDetailToString( int detail )
-{
- switch( detail ) {
- case NotifyAncestor: return "NotifyAncestor";
- case NotifyVirtual: return "NotifyVirtual";
- case NotifyInferior: return "NotifyInferior";
- case NotifyNonlinear: return "NotifyNonlinear";
- case NotifyNonlinearVirtual: return "NotifyNonlinearVirtual";
- case NotifyPointer: return "NotifyPointer";
- case NotifyPointerRoot: return "NotifyPointerRoot";
- case NotifyDetailNone: return "NotifyDetailNone";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghVisibilityToString( int state ) {
- switch( state ) {
- case VisibilityUnobscured: return "VisibilityUnobscured";
- case VisibilityPartiallyObscured: return "VisibilityPartiallyObscured";
- case VisibilityFullyObscured: return "VisibilityFullyObscured";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghConfigureDetailToString( int detail )
-{
- switch( detail ) {
- case Above: return "Above";
- case Below: return "Below";
- case TopIf: return "TopIf";
- case BottomIf: return "BottomIf";
- case Opposite: return "Opposite";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghPlaceToString( int place )
-{
- switch( place ) {
- case PlaceOnTop: return "PlaceOnTop";
- case PlaceOnBottom: return "PlaceOnBottom";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghMappingRequestToString( int request )
-{
- switch( request ) {
- case MappingModifier: return "MappingModifier";
- case MappingKeyboard: return "MappingKeyboard";
- case MappingPointer: return "MappingPointer";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghPropertyStateToString( int state )
-{
- switch( state ) {
- case PropertyNewValue: return "PropertyNewValue";
- case PropertyDelete: return "PropertyDelete";
- default: return "UNKNOWN";
- }
-}
-
-static const char* fghColormapStateToString( int state )
-{
- switch( state ) {
- case ColormapUninstalled: return "ColormapUninstalled";
- case ColormapInstalled: return "ColormapInstalled";
- default: return "UNKNOWN";
- }
-}
-
-static void fghPrintEvent( XEvent *event )
-{
- switch( event->type ) {
-
- case KeyPress:
- case KeyRelease: {
- XKeyEvent *e = &event->xkey;
- fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
- "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, "
- "keycode=%u, same_screen=%s", fghTypeToString( e->type ),
- e->window, e->root, e->subwindow, (unsigned long)e->time,
- e->x, e->y, e->x_root, e->y_root, e->state, e->keycode,
- fghBoolToString( e->same_screen ) );
- break;
- }
-
- case ButtonPress:
- case ButtonRelease: {
- XButtonEvent *e = &event->xbutton;
- fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
- "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, "
- "button=%u, same_screen=%d", fghTypeToString( e->type ),
- e->window, e->root, e->subwindow, (unsigned long)e->time,
- e->x, e->y, e->x_root, e->y_root, e->state, e->button,
- fghBoolToString( e->same_screen ) );
- break;
- }
-
- case MotionNotify: {
- XMotionEvent *e = &event->xmotion;
- fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
- "(x,y)=(%d,%d), (x_root,y_root)=(%d,%d), state=0x%x, "
- "is_hint=%s, same_screen=%d", fghTypeToString( e->type ),
- e->window, e->root, e->subwindow, (unsigned long)e->time,
- e->x, e->y, e->x_root, e->y_root, e->state,
- fghNotifyHintToString( e->is_hint ),
- fghBoolToString( e->same_screen ) );
- break;
- }
-
- case EnterNotify:
- case LeaveNotify: {
- XCrossingEvent *e = &event->xcrossing;
- fgWarning( "%s: window=0x%x, root=0x%x, subwindow=0x%x, time=%lu, "
- "(x,y)=(%d,%d), mode=%s, detail=%s, same_screen=%d, "
- "focus=%d, state=0x%x", fghTypeToString( e->type ),
- e->window, e->root, e->subwindow, (unsigned long)e->time,
- e->x, e->y, fghNotifyModeToString( e->mode ),
- fghNotifyDetailToString( e->detail ), (int)e->same_screen,
- (int)e->focus, e->state );
- break;
- }
-
- case FocusIn:
- case FocusOut: {
- XFocusChangeEvent *e = &event->xfocus;
- fgWarning( "%s: window=0x%x, mode=%s, detail=%s",
- fghTypeToString( e->type ), e->window,
- fghNotifyModeToString( e->mode ),
- fghNotifyDetailToString( e->detail ) );
- break;
- }
-
- case KeymapNotify: {
- XKeymapEvent *e = &event->xkeymap;
- char buf[32 * 2 + 1];
- int i;
- for ( i = 0; i < 32; i++ ) {
- snprintf( &buf[ i * 2 ], sizeof( buf ) - i * 2,
- "%02x", e->key_vector[ i ] );
- }
- buf[ i ] = '\0';
- fgWarning( "%s: window=0x%x, %s", fghTypeToString( e->type ), e->window,
- buf );
- break;
- }
-
- case Expose: {
- XExposeEvent *e = &event->xexpose;
- fgWarning( "%s: window=0x%x, (x,y)=(%d,%d), (width,height)=(%d,%d), "
- "count=%d", fghTypeToString( e->type ), e->window, e->x,
- e->y, e->width, e->height, e->count );
- break;
- }
-
- case GraphicsExpose: {
- XGraphicsExposeEvent *e = &event->xgraphicsexpose;
- fgWarning( "%s: drawable=0x%x, (x,y)=(%d,%d), (width,height)=(%d,%d), "
- "count=%d, (major_code,minor_code)=(%d,%d)",
- fghTypeToString( e->type ), e->drawable, e->x, e->y,
- e->width, e->height, e->count, e->major_code,
- e->minor_code );
- break;
- }
-
- case NoExpose: {
- XNoExposeEvent *e = &event->xnoexpose;
- fgWarning( "%s: drawable=0x%x, (major_code,minor_code)=(%d,%d)",
- fghTypeToString( e->type ), e->drawable, e->major_code,
- e->minor_code );
- break;
- }
-
- case VisibilityNotify: {
- XVisibilityEvent *e = &event->xvisibility;
- fgWarning( "%s: window=0x%x, state=%s", fghTypeToString( e->type ),
- e->window, fghVisibilityToString( e->state) );
- break;
- }
-
- case CreateNotify: {
- XCreateWindowEvent *e = &event->xcreatewindow;
- fgWarning( "%s: (x,y)=(%d,%d), (width,height)=(%d,%d), border_width=%d, "
- "window=0x%x, override_redirect=%s",
- fghTypeToString( e->type ), e->x, e->y, e->width, e->height,
- e->border_width, e->window,
- fghBoolToString( e->override_redirect ) );
- break;
- }
-
- case DestroyNotify: {
- XDestroyWindowEvent *e = &event->xdestroywindow;
- fgWarning( "%s: event=0x%x, window=0x%x",
- fghTypeToString( e->type ), e->event, e->window );
- break;
- }
-
- case UnmapNotify: {
- XUnmapEvent *e = &event->xunmap;
- fgWarning( "%s: event=0x%x, window=0x%x, from_configure=%s",
- fghTypeToString( e->type ), e->event, e->window,
- fghBoolToString( e->from_configure ) );
- break;
- }
-
- case MapNotify: {
- XMapEvent *e = &event->xmap;
- fgWarning( "%s: event=0x%x, window=0x%x, override_redirect=%s",
- fghTypeToString( e->type ), e->event, e->window,
- fghBoolToString( e->override_redirect ) );
- break;
- }
-
- case MapRequest: {
- XMapRequestEvent *e = &event->xmaprequest;
- fgWarning( "%s: parent=0x%x, window=0x%x",
- fghTypeToString( event->type ), e->parent, e->window );
- break;
- }
-
- case ReparentNotify: {
- XReparentEvent *e = &event->xreparent;
- fgWarning( "%s: event=0x%x, window=0x%x, parent=0x%x, (x,y)=(%d,%d), "
- "override_redirect=%s", fghTypeToString( e->type ),
- e->event, e->window, e->parent, e->x, e->y,
- fghBoolToString( e->override_redirect ) );
- break;
- }
-
- case ConfigureNotify: {
- XConfigureEvent *e = &event->xconfigure;
- fgWarning( "%s: event=0x%x, window=0x%x, (x,y)=(%d,%d), "
- "(width,height)=(%d,%d), border_width=%d, above=0x%x, "
- "override_redirect=%s", fghTypeToString( e->type ), e->event,
- e->window, e->x, e->y, e->width, e->height, e->border_width,
- e->above, fghBoolToString( e->override_redirect ) );
- break;
- }
-
- case ConfigureRequest: {
- XConfigureRequestEvent *e = &event->xconfigurerequest;
- fgWarning( "%s: parent=0x%x, window=0x%x, (x,y)=(%d,%d), "
- "(width,height)=(%d,%d), border_width=%d, above=0x%x, "
- "detail=%s, value_mask=%lx", fghTypeToString( e->type ),
- e->parent, e->window, e->x, e->y, e->width, e->height,
- e->border_width, e->above,
- fghConfigureDetailToString( e->detail ), e->value_mask );
- break;
- }
-
- case GravityNotify: {
- XGravityEvent *e = &event->xgravity;
- fgWarning( "%s: event=0x%x, window=0x%x, (x,y)=(%d,%d)",
- fghTypeToString( e->type ), e->event, e->window, e->x, e->y );
- break;
- }
-
- case ResizeRequest: {
- XResizeRequestEvent *e = &event->xresizerequest;
- fgWarning( "%s: window=0x%x, (width,height)=(%d,%d)",
- fghTypeToString( e->type ), e->window, e->width, e->height );
- break;
- }
-
- case CirculateNotify: {
- XCirculateEvent *e = &event->xcirculate;
- fgWarning( "%s: event=0x%x, window=0x%x, place=%s",
- fghTypeToString( e->type ), e->event, e->window,
- fghPlaceToString( e->place ) );
- break;
- }
-
- case CirculateRequest: {
- XCirculateRequestEvent *e = &event->xcirculaterequest;
- fgWarning( "%s: parent=0x%x, window=0x%x, place=%s",
- fghTypeToString( e->type ), e->parent, e->window,
- fghPlaceToString( e->place ) );
- break;
- }
-
- case PropertyNotify: {
- XPropertyEvent *e = &event->xproperty;
- fgWarning( "%s: window=0x%x, atom=%lu, time=%lu, state=%s",
- fghTypeToString( e->type ), e->window,
- (unsigned long)e->atom, (unsigned long)e->time,
- fghPropertyStateToString( e->state ) );
- break;
- }
-
- case SelectionClear: {
- XSelectionClearEvent *e = &event->xselectionclear;
- fgWarning( "%s: window=0x%x, selection=%lu, time=%lu",
- fghTypeToString( e->type ), e->window,
- (unsigned long)e->selection, (unsigned long)e->time );
- break;
- }
-
- case SelectionRequest: {
- XSelectionRequestEvent *e = &event->xselectionrequest;
- fgWarning( "%s: owner=0x%x, requestor=0x%x, selection=0x%x, "
- "target=0x%x, property=%lu, time=%lu",
- fghTypeToString( e->type ), e->owner, e->requestor,
- (unsigned long)e->selection, (unsigned long)e->target,
- (unsigned long)e->property, (unsigned long)e->time );
- break;
- }
-
- case SelectionNotify: {
- XSelectionEvent *e = &event->xselection;
- fgWarning( "%s: requestor=0x%x, selection=0x%x, target=0x%x, "
- "property=%lu, time=%lu", fghTypeToString( e->type ),
- e->requestor, (unsigned long)e->selection,
- (unsigned long)e->target, (unsigned long)e->property,
- (unsigned long)e->time );
- break;
- }
-
- case ColormapNotify: {
- XColormapEvent *e = &event->xcolormap;
- fgWarning( "%s: window=0x%x, colormap=%lu, new=%s, state=%s",
- fghTypeToString( e->type ), e->window,
- (unsigned long)e->colormap, fghBoolToString( e->new ),
- fghColormapStateToString( e->state ) );
- break;
- }
-
- case ClientMessage: {
- XClientMessageEvent *e = &event->xclient;
- char buf[ 61 ];
- char* p = buf;
- char* end = buf + sizeof( buf );
- int i;
- switch( e->format ) {
- case 8:
- for ( i = 0; i < 20; i++, p += 3 ) {
- snprintf( p, end - p, " %02x", e->data.b[ i ] );
- }
- break;
- case 16:
- for ( i = 0; i < 10; i++, p += 5 ) {
- snprintf( p, end - p, " %04x", e->data.s[ i ] );
- }
- break;
- case 32:
- for ( i = 0; i < 5; i++, p += 9 ) {
- snprintf( p, end - p, " %08lx", e->data.l[ i ] );
- }
- break;
- }
- *p = '\0';
- fgWarning( "%s: window=0x%x, message_type=%lu, format=%d, data=(%s )",
- fghTypeToString( e->type ), e->window,
- (unsigned long)e->message_type, e->format, buf );
- break;
- }
-
- case MappingNotify: {
- XMappingEvent *e = &event->xmapping;
- fgWarning( "%s: window=0x%x, request=%s, first_keycode=%d, count=%d",
- fghTypeToString( e->type ), e->window,
- fghMappingRequestToString( e->request ), e->first_keycode,
- e->count );
- break;
- }
-
- default: {
- fgWarning( "%s", fghTypeToString( event->type ) );
- break;
- }
- }
-}
-
-
-void fgPlatformProcessSingleEvent ( void )
-{
- SFG_Window* window;
- XEvent event;
-
- /* This code was repeated constantly, so here it goes into a definition: */
-#define GETWINDOW(a) \
- window = fgWindowByHandle( event.a.window ); \
- if( window == NULL ) \
- break;
-
-#define GETMOUSE(a) \
- window->State.MouseX = event.a.x; \
- window->State.MouseY = event.a.y;
-
- FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
-
- while( XPending( fgDisplay.pDisplay.Display ) )
- {
- XNextEvent( fgDisplay.pDisplay.Display, &event );
-#if _DEBUG
- fghPrintEvent( &event );
-#endif
-
- switch( event.type )
- {
- case ClientMessage:
- if(fgIsSpaceballXEvent(&event)) {
- fgSpaceballHandleXEvent(&event);
- break;
- }
- /* Destroy the window when the WM_DELETE_WINDOW message arrives */
- if( (Atom) event.xclient.data.l[ 0 ] == fgDisplay.pDisplay.DeleteWindow )
- {
- GETWINDOW( xclient );
-
- fgDestroyWindow ( window );
-
- if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
- {
- fgDeinitialize( );
- exit( 0 );
- }
- else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
- fgState.ExecState = GLUT_EXEC_STATE_STOP;
-
- return;
- }
- break;
-
- /*
- * CreateNotify causes a configure-event so that sub-windows are
- * handled compatibly with GLUT. Otherwise, your sub-windows
- * (in freeglut only) will not get an initial reshape event,
- * which can break things.
- *
- * GLUT presumably does this because it generally tries to treat
- * sub-windows the same as windows.
- */
- case CreateNotify:
- case ConfigureNotify:
- {
- int width, height;
- if( event.type == CreateNotify ) {
- GETWINDOW( xcreatewindow );
- width = event.xcreatewindow.width;
- height = event.xcreatewindow.height;
- } else {
- GETWINDOW( xconfigure );
- width = event.xconfigure.width;
- height = event.xconfigure.height;
- }
-
- if( ( width != window->State.pWState.OldWidth ) ||
- ( height != window->State.pWState.OldHeight ) )
- {
- SFG_Window *current_window = fgStructure.CurrentWindow;
-
- window->State.pWState.OldWidth = width;
- window->State.pWState.OldHeight = height;
- if( FETCH_WCB( *window, Reshape ) )
- INVOKE_WCB( *window, Reshape, ( width, height ) );
- else
- {
- fgSetWindow( window );
- glViewport( 0, 0, width, height );
- }
- glutPostRedisplay( );
- if( window->IsMenu )
- fgSetWindow( current_window );
- }
- }
- break;
-
- case DestroyNotify:
- /*
- * This is sent to confirm the XDestroyWindow call.
- *
- * XXX WHY is this commented out? Should we re-enable it?
- */
- /* fgAddToWindowDestroyList ( window ); */
- break;
-
- case Expose:
- /*
- * We are too dumb to process partial exposes...
- *
- * XXX Well, we could do it. However, it seems to only
- * XXX be potentially useful for single-buffered (since
- * XXX double-buffered does not respect viewport when we
- * XXX do a buffer-swap).
- *
- */
- if( event.xexpose.count == 0 )
- {
- GETWINDOW( xexpose );
- window->State.Redisplay = GL_TRUE;
- }
- break;
-
- case MapNotify:
- break;
-
- case UnmapNotify:
- /* We get this when iconifying a window. */
- GETWINDOW( xunmap );
- INVOKE_WCB( *window, WindowStatus, ( GLUT_HIDDEN ) );
- window->State.Visible = GL_FALSE;
- break;
-
- case MappingNotify:
- /*
- * Have the client's keyboard knowledge updated (xlib.ps,
- * page 206, says that's a good thing to do)
- */
- XRefreshKeyboardMapping( (XMappingEvent *) &event );
- break;
-
- case VisibilityNotify:
- {
- /*
- * Sending this event, the X server can notify us that the window
- * has just acquired one of the three possible visibility states:
- * VisibilityUnobscured, VisibilityPartiallyObscured or
- * VisibilityFullyObscured. Note that we DO NOT receive a
- * VisibilityNotify event when iconifying a window, we only get an
- * UnmapNotify then.
- */
- GETWINDOW( xvisibility );
- switch( event.xvisibility.state )
- {
- case VisibilityUnobscured:
- INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) );
- window->State.Visible = GL_TRUE;
- break;
-
- case VisibilityPartiallyObscured:
- INVOKE_WCB( *window, WindowStatus,
- ( GLUT_PARTIALLY_RETAINED ) );
- window->State.Visible = GL_TRUE;
- break;
-
- case VisibilityFullyObscured:
- INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_COVERED ) );
- window->State.Visible = GL_FALSE;
- break;
-
- default:
- fgWarning( "Unknown X visibility state: %d",
- event.xvisibility.state );
- break;
- }
- }
- break;
-
- case EnterNotify:
- case LeaveNotify:
- GETWINDOW( xcrossing );
- GETMOUSE( xcrossing );
- if( ( event.type == LeaveNotify ) && window->IsMenu &&
- window->ActiveMenu && window->ActiveMenu->IsActive )
- fgUpdateMenuHighlight( window->ActiveMenu );
-
- INVOKE_WCB( *window, Entry, ( ( EnterNotify == event.type ) ?
- GLUT_ENTERED :
- GLUT_LEFT ) );
- break;
-
- case MotionNotify:
- {
- GETWINDOW( xmotion );
- GETMOUSE( xmotion );
-
- if( window->ActiveMenu )
- {
- if( window == window->ActiveMenu->ParentWindow )
- {
- window->ActiveMenu->Window->State.MouseX =
- event.xmotion.x_root - window->ActiveMenu->X;
- window->ActiveMenu->Window->State.MouseY =
- event.xmotion.y_root - window->ActiveMenu->Y;
- }
-
- fgUpdateMenuHighlight( window->ActiveMenu );
-
- break;
- }
-
- /*
- * XXX For more than 5 buttons, just check {event.xmotion.state},
- * XXX rather than a host of bit-masks? Or maybe we need to
- * XXX track ButtonPress/ButtonRelease events in our own
- * XXX bit-mask?
- */
- fgState.Modifiers = fgPlatformGetModifiers( event.xmotion.state );
- if ( event.xmotion.state & ( Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) ) {
- INVOKE_WCB( *window, Motion, ( event.xmotion.x,
- event.xmotion.y ) );
- } else {
- INVOKE_WCB( *window, Passive, ( event.xmotion.x,
- event.xmotion.y ) );
- }
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case ButtonRelease:
- case ButtonPress:
- {
- GLboolean pressed = GL_TRUE;
- int button;
-
- if( event.type == ButtonRelease )
- pressed = GL_FALSE ;
-
- /*
- * A mouse button has been pressed or released. Traditionally,
- * break if the window was found within the freeglut structures.
- */
- GETWINDOW( xbutton );
- GETMOUSE( xbutton );
-
- /*
- * An X button (at least in XFree86) is numbered from 1.
- * A GLUT button is numbered from 0.
- * Old GLUT passed through buttons other than just the first
- * three, though it only gave symbolic names and official
- * support to the first three.
- */
- button = event.xbutton.button - 1;
-
- /*
- * Do not execute the application's mouse callback if a menu
- * is hooked to this button. In that case an appropriate
- * private call should be generated.
- */
- if( fgCheckActiveMenu( window, button, pressed,
- event.xbutton.x_root, event.xbutton.y_root ) )
- break;
-
- /*
- * Check if there is a mouse or mouse wheel callback hooked to the
- * window
- */
- if( ! FETCH_WCB( *window, Mouse ) &&
- ! FETCH_WCB( *window, MouseWheel ) )
- break;
-
- fgState.Modifiers = fgPlatformGetModifiers( event.xbutton.state );
-
- /* Finally execute the mouse or mouse wheel callback */
- if( ( button < glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS ) ) || ( ! FETCH_WCB( *window, MouseWheel ) ) )
- INVOKE_WCB( *window, Mouse, ( button,
- pressed ? GLUT_DOWN : GLUT_UP,
- event.xbutton.x,
- event.xbutton.y )
- );
- else
- {
- /*
- * Map 4 and 5 to wheel zero; EVEN to +1, ODD to -1
- * " 6 and 7 " " one; ...
- *
- * XXX This *should* be behind some variables/macros,
- * XXX since the order and numbering isn't certain
- * XXX See XFree86 configuration docs (even back in the
- * XXX 3.x days, and especially with 4.x).
- *
- * XXX Note that {button} has already been decremented
- * XXX in mapping from X button numbering to GLUT.
- *
- * XXX Should add support for partial wheel turns as Windows does -- 5/27/11
- */
- int wheel_number = (button - glutDeviceGet ( GLUT_NUM_MOUSE_BUTTONS )) / 2;
- int direction = -1;
- if( button % 2 )
- direction = 1;
-
- if( pressed )
- INVOKE_WCB( *window, MouseWheel, ( wheel_number,
- direction,
- event.xbutton.x,
- event.xbutton.y )
- );
- }
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- break;
-
- case KeyRelease:
- case KeyPress:
- {
- FGCBKeyboard keyboard_cb;
- FGCBSpecial special_cb;
-
- GETWINDOW( xkey );
- GETMOUSE( xkey );
-
- /* Detect auto repeated keys, if configured globally or per-window */
-
- if ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE )
- {
- if (event.type==KeyRelease)
- {
- /*
- * Look at X11 keystate to detect repeat mode.
- * While X11 says the key is actually held down, we'll ignore KeyRelease/KeyPress pairs.
- */
-
- char keys[32];
- XQueryKeymap( fgDisplay.pDisplay.Display, keys ); /* Look at X11 keystate to detect repeat mode */
-
- 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
- window->State.KeyRepeating = GL_FALSE;
-
- /* Cease processing this event if it is auto repeated */
-
- if (window->State.KeyRepeating)
- {
- if (event.type == KeyPress) window->State.KeyRepeating = GL_FALSE;
- break;
- }
-
- if( event.type == KeyPress )
- {
- keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, Keyboard ));
- special_cb = (FGCBSpecial) ( FETCH_WCB( *window, Special ));
- }
- else
- {
- keyboard_cb = (FGCBKeyboard)( FETCH_WCB( *window, KeyboardUp ));
- special_cb = (FGCBSpecial) ( FETCH_WCB( *window, SpecialUp ));
- }
-
- /* Is there a keyboard/special callback hooked for this window? */
- if( keyboard_cb || special_cb )
- {
- XComposeStatus composeStatus;
- char asciiCode[ 32 ];
- KeySym keySym;
- int len;
-
- /* Check for the ASCII/KeySym codes associated with the event: */
- len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
- &keySym, &composeStatus
- );
-
- /* GLUT API tells us to have two separate callbacks... */
- if( len > 0 )
- {
- /* ...one for the ASCII translateable keypresses... */
- if( keyboard_cb )
- {
- fgSetWindow( window );
- fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
- keyboard_cb( asciiCode[ 0 ],
- event.xkey.x, event.xkey.y
- );
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- }
- else
- {
- int special = -1;
-
- /*
- * ...and one for all the others, which need to be
- * translated to GLUT_KEY_Xs...
- */
- switch( keySym )
- {
- case XK_F1: special = GLUT_KEY_F1; break;
- case XK_F2: special = GLUT_KEY_F2; break;
- case XK_F3: special = GLUT_KEY_F3; break;
- case XK_F4: special = GLUT_KEY_F4; break;
- case XK_F5: special = GLUT_KEY_F5; break;
- case XK_F6: special = GLUT_KEY_F6; break;
- case XK_F7: special = GLUT_KEY_F7; break;
- case XK_F8: special = GLUT_KEY_F8; break;
- case XK_F9: special = GLUT_KEY_F9; break;
- case XK_F10: special = GLUT_KEY_F10; break;
- case XK_F11: special = GLUT_KEY_F11; break;
- case XK_F12: special = GLUT_KEY_F12; break;
-
- case XK_KP_Left:
- case XK_Left: special = GLUT_KEY_LEFT; break;
- case XK_KP_Right:
- case XK_Right: special = GLUT_KEY_RIGHT; break;
- case XK_KP_Up:
- case XK_Up: special = GLUT_KEY_UP; break;
- case XK_KP_Down:
- case XK_Down: special = GLUT_KEY_DOWN; break;
-
- case XK_KP_Prior:
- case XK_Prior: special = GLUT_KEY_PAGE_UP; break;
- case XK_KP_Next:
- case XK_Next: special = GLUT_KEY_PAGE_DOWN; break;
- case XK_KP_Home:
- case XK_Home: special = GLUT_KEY_HOME; break;
- case XK_KP_End:
- case XK_End: special = GLUT_KEY_END; break;
- case XK_KP_Insert:
- case XK_Insert: special = GLUT_KEY_INSERT; break;
-
- case XK_Num_Lock : special = GLUT_KEY_NUM_LOCK; break;
- case XK_KP_Begin : special = GLUT_KEY_BEGIN; break;
- case XK_KP_Delete: special = GLUT_KEY_DELETE; break;
-
- case XK_Shift_L: special = GLUT_KEY_SHIFT_L; break;
- case XK_Shift_R: special = GLUT_KEY_SHIFT_R; break;
- case XK_Control_L: special = GLUT_KEY_CTRL_L; break;
- case XK_Control_R: special = GLUT_KEY_CTRL_R; break;
- case XK_Alt_L: special = GLUT_KEY_ALT_L; break;
- case XK_Alt_R: special = GLUT_KEY_ALT_R; break;
- }
-
- /*
- * Execute the callback (if one has been specified),
- * given that the special code seems to be valid...
- */
- if( special_cb && (special != -1) )
- {
- fgSetWindow( window );
- fgState.Modifiers = fgPlatformGetModifiers( event.xkey.state );
- special_cb( special, event.xkey.x, event.xkey.y );
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- }
- }
- }
- break;
-
- case ReparentNotify:
- break; /* XXX Should disable this event */
-
- /* Not handled */
- case GravityNotify:
- break;
-
- default:
- /* enter handling of Extension Events here */
- #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
- fgHandleExtensionEvents( &event );
- #endif
- break;
- }
- }
-}
-
-
-void fgPlatformMainLoopPreliminaryWork ( void )
-{
-}
-
+++ /dev/null
-/*
- * freeglut_menu_x11.c
- *
- * Pull-down menu creation and handling.
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Wed Feb 1, 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-/*
- * * Private function to get the virtual maximum screen extent
- * */
-GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y )
-{
- int wx, wy;
- Window w;
-
- XTranslateCoordinates(
- fgDisplay.pDisplay.Display,
- window->Window.Handle,
- fgDisplay.pDisplay.RootWindow,
- 0, 0, &wx, &wy, &w);
-
- *x = fgState.GameModeSize.X + wx;
- *y = fgState.GameModeSize.Y + wy;
-}
-
+++ /dev/null
-/* Spaceball support for Linux.
- * Written by John Tsiombikas <nuclear@member.fsf.org>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * This code supports 3Dconnexion's 6-dof space-whatever devices.
- * It can communicate with either the proprietary 3Dconnexion daemon (3dxsrv)
- * free spacenavd (http://spacenav.sourceforge.net), through the "standard"
- * magellan X-based protocol.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-#include <X11/Xlib.h>
-
-extern int sball_initialized;
-
-enum {
- SPNAV_EVENT_ANY, /* used by spnav_remove_events() */
- SPNAV_EVENT_MOTION,
- SPNAV_EVENT_BUTTON /* includes both press and release */
-};
-
-struct spnav_event_motion {
- int type;
- int x, y, z;
- int rx, ry, rz;
- unsigned int period;
- int *data;
-};
-
-struct spnav_event_button {
- int type;
- int press;
- int bnum;
-};
-
-typedef union spnav_event {
- int type;
- struct spnav_event_motion motion;
- struct spnav_event_button button;
-} spnav_event;
-
-
-static int spnav_x11_open(Display *dpy, Window win);
-static int spnav_x11_window(Window win);
-static int spnav_x11_event(const XEvent *xev, spnav_event *event);
-static int spnav_close(void);
-static int spnav_fd(void);
-static int spnav_remove_events(int type);
-
-static SFG_Window *spnav_win;
-
-void fgPlatformInitializeSpaceball(void)
-{
- Window w;
-
- sball_initialized = 1;
- if(!fgStructure.CurrentWindow)
- {
- sball_initialized = -1;
- return;
- }
-
- w = fgStructure.CurrentWindow->Window.Handle;
- if(spnav_x11_open(fgDisplay.pDisplay.Display, w) == -1)
- {
- sball_initialized = -1;
- return;
- }
-}
-
-void fgPlatformSpaceballClose(void)
-{
- spnav_close();
-}
-
-int fgPlatformHasSpaceball(void)
-{
- /* XXX this function should somehow query the driver if there's a device
- * plugged in, as opposed to just checking if there's a driver to talk to.
- */
- return spnav_fd() == -1 ? 0 : 1;
-}
-
-int fgPlatformSpaceballNumButtons(void) {
- return 2;
-}
-
-void fgPlatformSpaceballSetWindow(SFG_Window *window)
-{
- if(spnav_win != window) {
- spnav_x11_window(window->Window.Handle);
- spnav_win = window;
- }
-}
-
-int fgIsSpaceballXEvent(const XEvent *xev)
-{
- spnav_event sev;
-
- if(spnav_win != fgStructure.CurrentWindow) {
- /* this will also initialize spaceball if needed (first call) */
- fgSpaceballSetWindow(fgStructure.CurrentWindow);
- }
-
- if(sball_initialized != 1) {
- return 0;
- }
-
- return spnav_x11_event(xev, &sev);
-}
-
-void fgSpaceballHandleXEvent(const XEvent *xev)
-{
- spnav_event sev;
-
- if(sball_initialized == 0) {
- fgInitialiseSpaceball();
- if(sball_initialized != 1) {
- return;
- }
- }
-
- if(spnav_x11_event(xev, &sev)) {
- switch(sev.type) {
- case SPNAV_EVENT_MOTION:
- if(sev.motion.x | sev.motion.y | sev.motion.z) {
- INVOKE_WCB(*spnav_win, SpaceMotion, (sev.motion.x, sev.motion.y, sev.motion.z));
- }
- if(sev.motion.rx | sev.motion.ry | sev.motion.rz) {
- INVOKE_WCB(*spnav_win, SpaceRotation, (sev.motion.rx, sev.motion.ry, sev.motion.rz));
- }
- spnav_remove_events(SPNAV_EVENT_MOTION);
- break;
-
- case SPNAV_EVENT_BUTTON:
- INVOKE_WCB(*spnav_win, SpaceButton, (sev.button.bnum, sev.button.press ? GLUT_DOWN : GLUT_UP));
- break;
-
- default:
- break;
- }
- }
-}
-
-/*
-The following code is part of libspnav, part of the spacenav project (spacenav.sf.net)
-Copyright (C) 2007-2009 John Tsiombikas <nuclear@member.fsf.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-static Window get_daemon_window(Display *dpy);
-static int catch_badwin(Display *dpy, XErrorEvent *err);
-
-static Display *dpy;
-static Window app_win;
-static Atom motion_event, button_press_event, button_release_event, command_event;
-
-enum {
- CMD_APP_WINDOW = 27695,
- CMD_APP_SENS
-};
-
-#define IS_OPEN dpy
-
-struct event_node {
- spnav_event event;
- struct event_node *next;
-};
-
-static int spnav_x11_open(Display *display, Window win)
-{
- if(IS_OPEN) {
- return -1;
- }
-
- dpy = display;
-
- motion_event = XInternAtom(dpy, "MotionEvent", True);
- button_press_event = XInternAtom(dpy, "ButtonPressEvent", True);
- button_release_event = XInternAtom(dpy, "ButtonReleaseEvent", True);
- command_event = XInternAtom(dpy, "CommandEvent", True);
-
- if(!motion_event || !button_press_event || !button_release_event || !command_event) {
- dpy = 0;
- return -1; /* daemon not started */
- }
-
- if(spnav_x11_window(win) == -1) {
- dpy = 0;
- return -1; /* daemon not started */
- }
-
- app_win = win;
- return 0;
-}
-
-static int spnav_close(void)
-{
- if(dpy) {
- spnav_x11_window(DefaultRootWindow(dpy));
- app_win = 0;
- dpy = 0;
- return 0;
- }
- return -1;
-}
-
-static int spnav_x11_window(Window win)
-{
- int (*prev_xerr_handler)(Display*, XErrorEvent*);
- XEvent xev;
- Window daemon_win;
-
- if(!IS_OPEN) {
- return -1;
- }
-
- if(!(daemon_win = get_daemon_window(dpy))) {
- return -1;
- }
-
- prev_xerr_handler = XSetErrorHandler(catch_badwin);
-
- xev.type = ClientMessage;
- xev.xclient.send_event = False;
- xev.xclient.display = dpy;
- xev.xclient.window = win;
- xev.xclient.message_type = command_event;
- xev.xclient.format = 16;
- xev.xclient.data.s[0] = ((unsigned int)win & 0xffff0000) >> 16;
- xev.xclient.data.s[1] = (unsigned int)win & 0xffff;
- xev.xclient.data.s[2] = CMD_APP_WINDOW;
-
- XSendEvent(dpy, daemon_win, False, 0, &xev);
- XSync(dpy, False);
-
- XSetErrorHandler(prev_xerr_handler);
- return 0;
-}
-
-static int spnav_fd(void)
-{
- if(dpy) {
- return ConnectionNumber(dpy);
- }
- return -1;
-}
-
-/*static int spnav_wait_event(spnav_event *event)
-{
- if(dpy) {
- for(;;) {
- XEvent xev;
- XNextEvent(dpy, &xev);
-
- if(spnav_x11_event(&xev, event) > 0) {
- return event->type;
- }
- }
- }
- return 0;
-}
-
-static int spnav_poll_event(spnav_event *event)
-{
- if(dpy) {
- if(XPending(dpy)) {
- XEvent xev;
- XNextEvent(dpy, &xev);
-
- return spnav_x11_event(&xev, event);
- }
- }
- return 0;
-}*/
-
-static Bool match_events(Display *dpy, XEvent *xev, char *arg)
-{
- int evtype = *(int*)arg;
-
- if(xev->type != ClientMessage) {
- return False;
- }
-
- if(xev->xclient.message_type == motion_event) {
- return !evtype || evtype == SPNAV_EVENT_MOTION ? True : False;
- }
- if(xev->xclient.message_type == button_press_event ||
- xev->xclient.message_type == button_release_event) {
- return !evtype || evtype == SPNAV_EVENT_BUTTON ? True : False;
- }
- return False;
-}
-
-static int spnav_remove_events(int type)
-{
- int rm_count = 0;
-
- if(dpy) {
- XEvent xev;
-
- while(XCheckIfEvent(dpy, &xev, match_events, (char*)&type)) {
- rm_count++;
- }
- return rm_count;
- }
- return 0;
-}
-
-static int spnav_x11_event(const XEvent *xev, spnav_event *event)
-{
- int i;
- int xmsg_type;
-
- if(xev->type != ClientMessage) {
- return 0;
- }
-
- xmsg_type = xev->xclient.message_type;
-
- if(xmsg_type != motion_event && xmsg_type != button_press_event &&
- xmsg_type != button_release_event) {
- return 0;
- }
-
- if(xmsg_type == motion_event) {
- event->type = SPNAV_EVENT_MOTION;
- event->motion.data = &event->motion.x;
-
- for(i=0; i<6; i++) {
- event->motion.data[i] = xev->xclient.data.s[i + 2];
- }
- event->motion.period = xev->xclient.data.s[8];
- } else {
- event->type = SPNAV_EVENT_BUTTON;
- event->button.press = xmsg_type == button_press_event ? 1 : 0;
- event->button.bnum = xev->xclient.data.s[2];
- }
- return event->type;
-}
-
-
-static Window get_daemon_window(Display *dpy)
-{
- Window win, root_win;
- XTextProperty wname;
- Atom type;
- int fmt;
- unsigned long nitems, bytes_after;
- unsigned char *prop;
-
- root_win = DefaultRootWindow(dpy);
-
- XGetWindowProperty(dpy, root_win, command_event, 0, 1, False, AnyPropertyType, &type, &fmt, &nitems, &bytes_after, &prop);
- if(!prop) {
- return 0;
- }
-
- win = *(Window*)prop;
- XFree(prop);
-
- if(!XGetWMName(dpy, win, &wname) || strcmp("Magellan Window", (char*)wname.value) != 0) {
- return 0;
- }
-
- return win;
-}
-
-static int catch_badwin(Display *dpy, XErrorEvent *err)
-{
- char buf[256];
-
- if(err->error_code == BadWindow) {
- /* do nothing? */
- } else {
- XGetErrorText(dpy, err->error_code, buf, sizeof buf);
- fprintf(stderr, "Caught unexpected X error: %s\n", buf);
- }
- return 0;
-}
-
+++ /dev/null
-/*
- * freeglut_state_x11.c
- *
- * X11-specific freeglut state query methods.
- *
- * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
- * Written by John F. Fay, <fayjf@sourceforge.net>
- * Creation date: Sat Feb 4 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-/*
- * TODO BEFORE THE STABLE RELEASE:
- *
- * fgPlatformChooseFBConfig() -- OK, but what about glutInitDisplayString()?
- */
-
-/* A helper function to check if a display mode is possible to use */
-GLXFBConfig* fgPlatformChooseFBConfig( int* numcfgs );
-
-/*
- * Queries the GL context about some attributes
- */
-int fgPlatformGetConfig( int attribute )
-{
- int returnValue = 0;
- int result; /* Not checked */
-
- if( fgStructure.CurrentWindow )
- result = glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
- *(fgStructure.CurrentWindow->Window.pContext.FBConfig),
- attribute,
- &returnValue );
-
- return returnValue;
-}
-
-int fgPlatformGlutGet ( GLenum eWhat )
-{
- int nsamples = 0;
-
- switch( eWhat )
- {
- /*
- * The window/context specific queries are handled mostly by
- * fgPlatformGetConfig().
- */
- case GLUT_WINDOW_NUM_SAMPLES:
-#ifdef GLX_VERSION_1_3
- glGetIntegerv(GL_SAMPLES, &nsamples);
-#endif
- return nsamples;
-
- /*
- * The rest of GLX queries under X are general enough to use a macro to
- * check them
- */
-# define GLX_QUERY(a,b) case a: return fgPlatformGetConfig( b );
-
- GLX_QUERY( GLUT_WINDOW_RGBA, GLX_RGBA );
- GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER, GLX_DOUBLEBUFFER );
- GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE, GLX_BUFFER_SIZE );
- GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE, GLX_STENCIL_SIZE );
- GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE, GLX_DEPTH_SIZE );
- GLX_QUERY( GLUT_WINDOW_RED_SIZE, GLX_RED_SIZE );
- GLX_QUERY( GLUT_WINDOW_GREEN_SIZE, GLX_GREEN_SIZE );
- GLX_QUERY( GLUT_WINDOW_BLUE_SIZE, GLX_BLUE_SIZE );
- GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE, GLX_ALPHA_SIZE );
- GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE, GLX_ACCUM_RED_SIZE );
- GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE, GLX_ACCUM_GREEN_SIZE );
- GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE, GLX_ACCUM_BLUE_SIZE );
- GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE, GLX_ACCUM_ALPHA_SIZE );
- GLX_QUERY( GLUT_WINDOW_STEREO, GLX_STEREO );
-
-# undef GLX_QUERY
-
- /* Colormap size is handled in a bit different way than all the rest */
- case GLUT_WINDOW_COLORMAP_SIZE:
- if( (fgPlatformGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
- {
- /*
- * We've got a RGBA visual, so there is no colormap at all.
- * The other possibility is that we have no current window set.
- */
- return 0;
- }
- else
- {
- const GLXFBConfig * fbconfig =
- fgStructure.CurrentWindow->Window.pContext.FBConfig;
-
- XVisualInfo * visualInfo =
- glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display, *fbconfig );
-
- const int result = visualInfo->visual->map_entries;
-
- XFree(visualInfo);
-
- return result;
- }
-
- /*
- * Those calls are somewhat similiar, as they use XGetWindowAttributes()
- * function
- */
- case GLUT_WINDOW_X:
- case GLUT_WINDOW_Y:
- case GLUT_WINDOW_BORDER_WIDTH:
- case GLUT_WINDOW_HEADER_HEIGHT:
- {
- int x, y;
- Window w;
-
- if( fgStructure.CurrentWindow == NULL )
- return 0;
-
- XTranslateCoordinates(
- fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- fgDisplay.pDisplay.RootWindow,
- 0, 0, &x, &y, &w);
-
- switch ( eWhat )
- {
- case GLUT_WINDOW_X: return x;
- case GLUT_WINDOW_Y: return y;
- }
-
- if ( w == 0 )
- return 0;
- XTranslateCoordinates(
- fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- w, 0, 0, &x, &y, &w);
-
- switch ( eWhat )
- {
- case GLUT_WINDOW_BORDER_WIDTH: return x;
- case GLUT_WINDOW_HEADER_HEIGHT: return y;
- }
- }
-
- case GLUT_WINDOW_WIDTH:
- case GLUT_WINDOW_HEIGHT:
- {
- XWindowAttributes winAttributes;
-
- if( fgStructure.CurrentWindow == NULL )
- return 0;
- XGetWindowAttributes(
- fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- &winAttributes
- );
- switch ( eWhat )
- {
- case GLUT_WINDOW_WIDTH: return winAttributes.width ;
- case GLUT_WINDOW_HEIGHT: return winAttributes.height ;
- }
- }
-
- /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
- case GLUT_DISPLAY_MODE_POSSIBLE:
- {
- /* We should not have to call fgPlatformChooseFBConfig again here. */
- GLXFBConfig * fbconfig;
- int isPossible;
-
- fbconfig = fgPlatformChooseFBConfig(NULL);
-
- if (fbconfig == NULL)
- {
- isPossible = 0;
- }
- else
- {
- isPossible = 1;
- XFree(fbconfig);
- }
-
- return isPossible;
- }
-
- /* This is system-dependant */
- case GLUT_WINDOW_FORMAT_ID:
- if( fgStructure.CurrentWindow == NULL )
- return 0;
-
- return fgPlatformGetConfig( GLX_VISUAL_ID );
-
- default:
- fgWarning( "glutGet(): missing enum handle %d", eWhat );
- break;
- }
-
- return -1;
-}
-
-
-int fgPlatformGlutDeviceGet ( GLenum eWhat )
-{
- switch( eWhat )
- {
- case GLUT_HAS_KEYBOARD:
- /*
- * X11 has a core keyboard by definition, although it can
- * be present as a virtual/dummy keyboard. For now, there
- * is no reliable way to tell if a real keyboard is present.
- */
- return 1;
-
- /* X11 has a mouse by definition */
- case GLUT_HAS_MOUSE:
- return 1 ;
-
- case GLUT_NUM_MOUSE_BUTTONS:
- /* We should be able to pass NULL when the last argument is zero,
- * but at least one X server has a bug where this causes a segfault.
- *
- * In XFree86/Xorg servers, a mouse wheel is seen as two buttons
- * rather than an Axis; "freeglut_main.c" expects this when
- * checking for a wheel event.
- */
- {
- unsigned char map;
- int nbuttons = XGetPointerMapping(fgDisplay.pDisplay.Display, &map,0);
- return nbuttons;
- }
-
- default:
- fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
- break;
- }
-
- /* And now -- the failure. */
- return -1;
-}
-
-
-int *fgPlatformGlutGetModeValues(GLenum eWhat, int *size)
-{
- int *array;
-
- int attributes[9];
- GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
- int fbconfigArraySize; /* Number of FBConfigs in the array */
- int attribute_name = 0;
-
- array = NULL;
- *size = 0;
-
- switch (eWhat)
- {
- case GLUT_AUX:
- case GLUT_MULTISAMPLE:
-
- attributes[0] = GLX_BUFFER_SIZE;
- attributes[1] = GLX_DONT_CARE;
-
- switch (eWhat)
- {
- case GLUT_AUX:
- /*
- FBConfigs are now sorted by increasing number of auxiliary
- buffers. We want at least one buffer.
- */
- attributes[2] = GLX_AUX_BUFFERS;
- attributes[3] = 1;
- attributes[4] = None;
-
- attribute_name = GLX_AUX_BUFFERS;
-
- break;
-
-
- case GLUT_MULTISAMPLE:
- attributes[2] = GLX_AUX_BUFFERS;
- attributes[3] = GLX_DONT_CARE;
- attributes[4] = GLX_SAMPLE_BUFFERS;
- attributes[5] = 1;
- /*
- FBConfigs are now sorted by increasing number of samples per
- pixel. We want at least one sample.
- */
- attributes[6] = GLX_SAMPLES;
- attributes[7] = 1;
- attributes[8] = None;
-
- attribute_name = GLX_SAMPLES;
-
- break;
- }
-
- fbconfigArray = glXChooseFBConfig(fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- attributes,
- &fbconfigArraySize);
-
- if (fbconfigArray != NULL)
- {
- int * temp_array;
- int result; /* Returned by glXGetFBConfigAttrib. Not checked. */
- int previous_value;
- int i;
-
- temp_array = malloc(sizeof(int) * fbconfigArraySize);
- previous_value = 0;
-
- for (i = 0; i < fbconfigArraySize; i++)
- {
- int value;
-
- result = glXGetFBConfigAttrib(fgDisplay.pDisplay.Display,
- fbconfigArray[i],
- attribute_name,
- &value);
- if (value > previous_value)
- {
- temp_array[*size] = value;
- previous_value = value;
- (*size)++;
- }
- }
-
- array = malloc(sizeof(int) * (*size));
- for (i = 0; i < *size; i++)
- {
- array[i] = temp_array[i];
- }
-
- free(temp_array);
- XFree(fbconfigArray);
- }
-
- break;
-
- default:
- break;
- }
-
- return array;
-}
-
-
+++ /dev/null
-/*
- * freeglut_structure.c
- *
- * Windows and menus need tree structure
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <GL/freeglut.h>
-#include "../fg_internal.h"
-
-extern SFG_Structure fgStructure;
-
-void fgPlatformCreateWindow ( SFG_Window *window )
-{
- window->Window.pContext.FBConfig = NULL;
-
- window->State.pWState.OldHeight = window->State.pWState.OldWidth = -1;
-}
-
+++ /dev/null
-/*
- * freeglut_window_x11.c
- *
- * Window management methods for X11
- *
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>
- * Copied for Platform code by Evan Felix <karcaw at gmail.com>
- * Creation date: Thur Feb 2 2012
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define FREEGLUT_BUILDING_LIB
-#include <GL/freeglut.h>
-#include <limits.h> /* LONG_MAX */
-#include <unistd.h> /* usleep */
-#include "../fg_internal.h"
-
-/* pushing attribute/value pairs into an array */
-#define ATTRIB(a) attributes[where++]=(a)
-#define ATTRIB_VAL(a,v) {ATTRIB(a); ATTRIB(v);}
-
-
-#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
-#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
-#endif
-
-#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
-#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#endif
-
-#ifndef GLX_CONTEXT_MINOR_VERSION_ARB
-#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
-#endif
-
-#ifndef GLX_CONTEXT_FLAGS_ARB
-#define GLX_CONTEXT_FLAGS_ARB 0x2094
-#endif
-
-#ifndef GLX_CONTEXT_PROFILE_MASK_ARB
-#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
-#endif
-
-#ifndef GLX_CONTEXT_DEBUG_BIT_ARB
-#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
-#endif
-
-#ifndef GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
-#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
-#endif
-
-#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
-#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#endif
-
-#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
-#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#endif
-
-#ifndef GLX_RGBA_FLOAT_TYPE
-#define GLX_RGBA_FLOAT_TYPE 0x20B9
-#endif
-
-#ifndef GLX_RGBA_FLOAT_BIT
-#define GLX_RGBA_FLOAT_BIT 0x00000004
-#endif
-
-
-/*
- * Chooses a visual basing on the current display mode settings
- */
-
-GLXFBConfig* fgPlatformChooseFBConfig( int *numcfgs )
-{
- GLboolean wantIndexedMode = GL_FALSE;
- int attributes[ 100 ];
- int where = 0, numAuxBuffers;
-
- /* First we have to process the display mode settings... */
- if( fgState.DisplayMode & GLUT_INDEX ) {
- ATTRIB_VAL( GLX_BUFFER_SIZE, 8 );
- /* Buffer size is selected later. */
-
- ATTRIB_VAL( GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT );
- wantIndexedMode = GL_TRUE;
- } else {
- ATTRIB_VAL( GLX_RED_SIZE, 1 );
- ATTRIB_VAL( GLX_GREEN_SIZE, 1 );
- ATTRIB_VAL( GLX_BLUE_SIZE, 1 );
- if( fgState.DisplayMode & GLUT_ALPHA ) {
- ATTRIB_VAL( GLX_ALPHA_SIZE, 1 );
- }
- }
-
- if( fgState.DisplayMode & GLUT_DOUBLE ) {
- ATTRIB_VAL( GLX_DOUBLEBUFFER, True );
- }
-
- if( fgState.DisplayMode & GLUT_STEREO ) {
- ATTRIB_VAL( GLX_STEREO, True );
- }
-
- if( fgState.DisplayMode & GLUT_DEPTH ) {
- ATTRIB_VAL( GLX_DEPTH_SIZE, 1 );
- }
-
- if( fgState.DisplayMode & GLUT_STENCIL ) {
- ATTRIB_VAL( GLX_STENCIL_SIZE, 1 );
- }
-
- if( fgState.DisplayMode & GLUT_ACCUM ) {
- ATTRIB_VAL( GLX_ACCUM_RED_SIZE, 1 );
- ATTRIB_VAL( GLX_ACCUM_GREEN_SIZE, 1 );
- ATTRIB_VAL( GLX_ACCUM_BLUE_SIZE, 1 );
- if( fgState.DisplayMode & GLUT_ALPHA ) {
- ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
- }
- }
-
- numAuxBuffers = fghNumberOfAuxBuffersRequested();
- if ( numAuxBuffers > 0 ) {
- ATTRIB_VAL( GLX_AUX_BUFFERS, numAuxBuffers );
- }
-
- if( fgState.DisplayMode & GLUT_SRGB ) {
- ATTRIB_VAL( GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, True );
- }
-
- if (fgState.DisplayMode & GLUT_MULTISAMPLE) {
- ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1);
- ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber);
- }
-
- /* Push a terminator at the end of the list */
- ATTRIB( None );
-
- {
- GLXFBConfig * fbconfigArray; /* Array of FBConfigs */
- GLXFBConfig * fbconfig; /* The FBConfig we want */
- int fbconfigArraySize; /* Number of FBConfigs in the array */
-
-
- /* Get all FBConfigs that match "attributes". */
- fbconfigArray = glXChooseFBConfig( fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- attributes,
- &fbconfigArraySize );
-
- if (fbconfigArray != NULL)
- {
- int result; /* Returned by glXGetFBConfigAttrib, not checked. */
-
-
- if( wantIndexedMode )
- {
- /*
- * In index mode, we want the largest buffer size, i.e. visual
- * depth. Here, FBConfigs are sorted by increasing buffer size
- * first, so FBConfigs with the largest size come last.
- */
-
- int bufferSizeMin, bufferSizeMax;
-
- /* Get bufferSizeMin. */
- result =
- glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
- fbconfigArray[0],
- GLX_BUFFER_SIZE,
- &bufferSizeMin );
- /* Get bufferSizeMax. */
- result =
- glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
- fbconfigArray[fbconfigArraySize - 1],
- GLX_BUFFER_SIZE,
- &bufferSizeMax );
-
- if (bufferSizeMax > bufferSizeMin)
- {
- /*
- * Free and reallocate fbconfigArray, keeping only FBConfigs
- * with the largest buffer size.
- */
- XFree(fbconfigArray);
-
- /* Add buffer size token at the end of the list. */
- where--;
- ATTRIB_VAL( GLX_BUFFER_SIZE, bufferSizeMax );
- ATTRIB( None );
-
- fbconfigArray = glXChooseFBConfig( fgDisplay.pDisplay.Display,
- fgDisplay.pDisplay.Screen,
- attributes,
- &fbconfigArraySize );
- }
- }
-
- /*
- * We now have an array of FBConfigs, the first one being the "best"
- * one. So we should return only this FBConfig:
- *
- * int fbconfigXID;
- *
- * - pick the XID of the FBConfig we want
- * result = glXGetFBConfigAttrib( fgDisplay.pDisplay.Display,
- * fbconfigArray[0],
- * GLX_FBCONFIG_ID,
- * &fbconfigXID );
- *
- * - free the array
- * XFree(fbconfigArray);
- *
- * - reset "attributes" with the XID
- * where = 0;
- * ATTRIB_VAL( GLX_FBCONFIG_ID, fbconfigXID );
- * ATTRIB( None );
- *
- * - get our FBConfig only
- * fbconfig = glXChooseFBConfig( fgDisplay.pDisplay.Display,
- * fgDisplay.pDisplay.Screen,
- * attributes,
- * &fbconfigArraySize );
- *
- * However, for some configurations (for instance multisampling with
- * Mesa 6.5.2 and ATI drivers), this does not work:
- * glXChooseFBConfig returns NULL, whereas fbconfigXID is a valid
- * XID. Further investigation is needed.
- *
- * So, for now, we return the whole array of FBConfigs. This should
- * not produce any side effects elsewhere.
- */
- fbconfig = fbconfigArray;
- }
- else
- {
- fbconfig = NULL;
- }
-
- if (numcfgs)
- *numcfgs = fbconfigArraySize;
-
- return fbconfig;
- }
-}
-
-
-static void fghFillContextAttributes( int *attributes ) {
- int where = 0, contextFlags, contextProfile;
-
- if ( !fghIsLegacyContextVersionRequested() ) {
- ATTRIB_VAL( GLX_CONTEXT_MAJOR_VERSION_ARB, fgState.MajorVersion );
- ATTRIB_VAL( GLX_CONTEXT_MINOR_VERSION_ARB, fgState.MinorVersion );
- }
-
- contextFlags =
- fghMapBit( fgState.ContextFlags, GLUT_DEBUG, GLX_CONTEXT_DEBUG_BIT_ARB ) |
- fghMapBit( fgState.ContextFlags, GLUT_FORWARD_COMPATIBLE, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB );
- if ( contextFlags != 0 ) {
- ATTRIB_VAL( GLX_CONTEXT_FLAGS_ARB, contextFlags );
- }
-
- contextProfile =
- fghMapBit( fgState.ContextProfile, GLUT_CORE_PROFILE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB ) |
- fghMapBit( fgState.ContextProfile, GLUT_COMPATIBILITY_PROFILE, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB );
- if ( contextProfile != 0 ) {
- ATTRIB_VAL( GLX_CONTEXT_PROFILE_MASK_ARB, contextProfile );
- }
-
- ATTRIB( 0 );
-}
-
-typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config,
- GLXContext share_list, Bool direct,
- const int *attrib_list);
-
-static GLXContext fghCreateNewContext( SFG_Window* window )
-{
- /* for color model calculation */
- int menu = ( window->IsMenu && !fgStructure.MenuContext );
- int index_mode = ( fgState.DisplayMode & GLUT_INDEX );
-
- /* "classic" context creation */
- Display *dpy = fgDisplay.pDisplay.Display;
- GLXFBConfig config = *(window->Window.pContext.FBConfig);
- int render_type = ( !menu && index_mode ) ? GLX_COLOR_INDEX_TYPE : GLX_RGBA_TYPE;
- GLXContext share_list = NULL;
- Bool direct = ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT );
- GLXContext context;
-
- /* new context creation */
- int attributes[9];
- CreateContextAttribsProc createContextAttribs = (CreateContextAttribsProc) fgPlatformGetProcAddress( "glXCreateContextAttribsARB" );
-
- /* glXCreateContextAttribsARB not found, yet the user has requested the new context creation */
- if ( !createContextAttribs && !fghIsLegacyContextRequested() ) {
- fgWarning( "OpenGL >2.1 context requested but glXCreateContextAttribsARB is not available! Falling back to legacy context creation" );
- fgState.MajorVersion = 2;
- fgState.MinorVersion = 1;
- }
-
- /* If nothing fancy has been required, simply use the old context creation GLX API entry */
- if ( fghIsLegacyContextRequested() || !createContextAttribs )
- {
- context = glXCreateNewContext( dpy, config, render_type, share_list, direct );
- if ( context == NULL ) {
- fghContextCreationError();
- }
- return context;
- }
-
- /* color index mode is not available anymore with OpenGL 3.0 */
- if ( render_type == GLX_COLOR_INDEX_TYPE ) {
- fgWarning( "color index mode is deprecated, using RGBA mode" );
- }
-
- fghFillContextAttributes( attributes );
-
- context = createContextAttribs( dpy, config, share_list, direct, attributes );
- if ( context == NULL ) {
- fghContextCreationError();
- }
- return context;
-}
-
-
-#define _NET_WM_STATE_TOGGLE 2
-static int fghResizeFullscrToggle(void)
-{
- XWindowAttributes attributes;
-
- if(glutGet(GLUT_FULL_SCREEN)) {
- /* restore original window size */
- SFG_Window *win = fgStructure.CurrentWindow;
- fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
- fgStructure.CurrentWindow->State.Width = win->State.pWState.OldWidth;
- fgStructure.CurrentWindow->State.Height = win->State.pWState.OldHeight;
-
- } else {
- /* resize the window to cover the entire screen */
- XGetWindowAttributes(fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- &attributes);
-
- /*
- * The "x" and "y" members of "attributes" are the window's coordinates
- * relative to its parent, i.e. to the decoration window.
- */
- XMoveResizeWindow(fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- -attributes.x,
- -attributes.y,
- fgDisplay.ScreenWidth,
- fgDisplay.ScreenHeight);
- }
- return 0;
-}
-
-static int fghEwmhFullscrToggle(void)
-{
- XEvent xev;
- long evmask = SubstructureRedirectMask | SubstructureNotifyMask;
-
- if(!fgDisplay.pDisplay.State || !fgDisplay.pDisplay.StateFullScreen) {
- return -1;
- }
-
- xev.type = ClientMessage;
- xev.xclient.window = fgStructure.CurrentWindow->Window.Handle;
- xev.xclient.message_type = fgDisplay.pDisplay.State;
- xev.xclient.format = 32;
- xev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
- xev.xclient.data.l[1] = fgDisplay.pDisplay.StateFullScreen;
- xev.xclient.data.l[2] = 0; /* no second property to toggle */
- xev.xclient.data.l[3] = 1; /* source indication: application */
- xev.xclient.data.l[4] = 0; /* unused */
-
- if(!XSendEvent(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, 0, evmask, &xev)) {
- return -1;
- }
- return 0;
-}
-
-static int fghToggleFullscreen(void)
-{
- /* first try the EWMH (_NET_WM_STATE) method ... */
- if(fghEwmhFullscrToggle() != -1) {
- return 0;
- }
-
- /* fall back to resizing the window */
- if(fghResizeFullscrToggle() != -1) {
- return 0;
- }
- return -1;
-}
-
-void fgPlatformSetWindow ( SFG_Window *window )
-{
- if ( window )
- {
- glXMakeContextCurrent(
- fgDisplay.pDisplay.Display,
- window->Window.Handle,
- window->Window.Handle,
- window->Window.Context
- );
- }
-}
-
-static Bool fghWindowIsVisible( Display *display, XEvent *event, XPointer arg)
-{
- Window window = (Window)arg;
- return (event->type == MapNotify) && (event->xmap.window == window);
-}
-
-/*
- * Opens a window. Requires a SFG_Window object created and attached
- * to the freeglut structure. OpenGL context is created here.
- */
-void fgPlatformOpenWindow( SFG_Window* window, const char* title,
- GLboolean positionUse, int x, int y,
- GLboolean sizeUse, int w, int h,
- GLboolean gameMode, GLboolean isSubWindow )
-{
- XVisualInfo * visualInfo = NULL;
- XSetWindowAttributes winAttr;
- XTextProperty textProperty;
- XSizeHints sizeHints;
- XWMHints wmHints;
- XEvent eventReturnBuffer; /* return buffer required for a call */
- unsigned long mask;
- int num_FBConfigs, i;
- unsigned int current_DisplayMode = fgState.DisplayMode ;
-
- /* Save the display mode if we are creating a menu window */
- if( window->IsMenu && ( ! fgStructure.MenuContext ) )
- fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ;
-
- window->Window.pContext.FBConfig = fgPlatformChooseFBConfig( &num_FBConfigs );
-
- if( window->IsMenu && ( ! fgStructure.MenuContext ) )
- fgState.DisplayMode = current_DisplayMode ;
-
- if( ! window->Window.pContext.FBConfig )
- {
- /*
- * The "fgPlatformChooseFBConfig" returned a null meaning that the visual
- * context is not available.
- * Try a couple of variations to see if they will work.
- */
- if( !( fgState.DisplayMode & GLUT_DOUBLE ) )
- {
- fgState.DisplayMode |= GLUT_DOUBLE ;
- window->Window.pContext.FBConfig = fgPlatformChooseFBConfig( &num_FBConfigs );
- fgState.DisplayMode &= ~GLUT_DOUBLE;
- }
-
- if( fgState.DisplayMode & GLUT_MULTISAMPLE )
- {
- fgState.DisplayMode &= ~GLUT_MULTISAMPLE ;
- window->Window.pContext.FBConfig = fgPlatformChooseFBConfig( &num_FBConfigs );
- fgState.DisplayMode |= GLUT_MULTISAMPLE;
- }
- }
-
- FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.pContext.FBConfig != NULL,
- "FBConfig with necessary capabilities not found", "fgOpenWindow" );
-
- /* Get the X visual. */
- for (i = 0; i < num_FBConfigs; i++) {
- visualInfo = glXGetVisualFromFBConfig( fgDisplay.pDisplay.Display,
- window->Window.pContext.FBConfig[i] );
- if (visualInfo)
- break;
- }
-
- FREEGLUT_INTERNAL_ERROR_EXIT( visualInfo != NULL,
- "visualInfo could not be retrieved from FBConfig", "fgOpenWindow" );
-
- /*
- * XXX HINT: the masks should be updated when adding/removing callbacks.
- * XXX This might speed up message processing. Is that true?
- * XXX
- * XXX A: Not appreciably, but it WILL make it easier to debug.
- * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT
- * XXX turns off events that it doesn't need and is a whole lot
- * XXX more pleasant to trace. (Think mouse-motion! Tons of
- * XXX ``bonus'' GUI events stream in.)
- */
- winAttr.event_mask =
- StructureNotifyMask | SubstructureNotifyMask | ExposureMask |
- ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
- VisibilityChangeMask | EnterWindowMask | LeaveWindowMask |
- PointerMotionMask | ButtonMotionMask;
- winAttr.background_pixmap = None;
- winAttr.background_pixel = 0;
- winAttr.border_pixel = 0;
-
- winAttr.colormap = XCreateColormap(
- fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow,
- visualInfo->visual, AllocNone
- );
-
- mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
-
- if( window->IsMenu || ( gameMode == GL_TRUE ) )
- {
- winAttr.override_redirect = True;
- mask |= CWOverrideRedirect;
- }
-
- if( ! positionUse )
- x = y = -1; /* default window position */
- if( ! sizeUse )
- w = h = 300; /* default window size */
-
- window->Window.Handle = XCreateWindow(
- fgDisplay.pDisplay.Display,
- window->Parent == NULL ? fgDisplay.pDisplay.RootWindow :
- window->Parent->Window.Handle,
- x, y, w, h, 0,
- visualInfo->depth, InputOutput,
- visualInfo->visual, mask,
- &winAttr
- );
-
- /*
- * The GLX context creation, possibly trying the direct context rendering
- * or else use the current context if the user has so specified
- */
-
- if( window->IsMenu )
- {
- /*
- * If there isn't already an OpenGL rendering context for menu
- * windows, make one
- */
- if( !fgStructure.MenuContext )
- {
- fgStructure.MenuContext =
- (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
- fgStructure.MenuContext->MContext = fghCreateNewContext( window );
- }
-
- /* window->Window.Context = fgStructure.MenuContext->MContext; */
- window->Window.Context = fghCreateNewContext( window );
- }
- else if( fgState.UseCurrentContext )
- {
- window->Window.Context = glXGetCurrentContext( );
-
- if( ! window->Window.Context )
- window->Window.Context = fghCreateNewContext( window );
- }
- else
- window->Window.Context = fghCreateNewContext( window );
-
-#if !defined( __FreeBSD__ ) && !defined( __NetBSD__ )
- if( !glXIsDirect( fgDisplay.pDisplay.Display, window->Window.Context ) )
- {
- if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
- fgError( "Unable to force direct context rendering for window '%s'",
- title );
- }
-#endif
-
- /*
- * XXX Assume the new window is visible by default
- * XXX Is this a safe assumption?
- */
- window->State.Visible = GL_TRUE;
-
- sizeHints.flags = 0;
- if ( positionUse )
- sizeHints.flags |= USPosition;
- if ( sizeUse )
- sizeHints.flags |= USSize;
-
- /*
- * Fill in the size hints values now (the x, y, width and height
- * settings are obsolete, are there any more WMs that support them?)
- * Unless the X servers actually stop supporting these, we should
- * continue to fill them in. It is *not* our place to tell the user
- * that they should replace a window manager that they like, and which
- * works, just because *we* think that it's not "modern" enough.
- */
- sizeHints.x = x;
- sizeHints.y = y;
- sizeHints.width = w;
- sizeHints.height = h;
-
- wmHints.flags = StateHint;
- wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState;
- /* Prepare the window and iconified window names... */
- XStringListToTextProperty( (char **) &title, 1, &textProperty );
-
- XSetWMProperties(
- fgDisplay.pDisplay.Display,
- window->Window.Handle,
- &textProperty,
- &textProperty,
- 0,
- 0,
- &sizeHints,
- &wmHints,
- NULL
- );
- XFree( textProperty.value );
-
- XSetWMProtocols( fgDisplay.pDisplay.Display, window->Window.Handle,
- &fgDisplay.pDisplay.DeleteWindow, 1 );
-
- glXMakeContextCurrent(
- fgDisplay.pDisplay.Display,
- window->Window.Handle,
- window->Window.Handle,
- window->Window.Context
- );
-
- /* register extension events _before_ window is mapped */
- #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
- fgRegisterDevices( fgDisplay.pDisplay.Display, &(window->Window.Handle) );
- #endif
-
- XMapWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
-
- XFree(visualInfo);
-
- if( !isSubWindow)
- XPeekIfEvent( fgDisplay.pDisplay.Display, &eventReturnBuffer, &fghWindowIsVisible, (XPointer)(window->Window.Handle) );
-}
-
-
-/*
- * Closes a window, destroying the frame and OpenGL context
- */
-void fgPlatformCloseWindow( SFG_Window* window )
-{
- if( window->Window.Context )
- glXDestroyContext( fgDisplay.pDisplay.Display, window->Window.Context );
- XFree( window->Window.pContext.FBConfig );
-
- if( window->Window.Handle ) {
- XDestroyWindow( fgDisplay.pDisplay.Display, window->Window.Handle );
- }
- /* XFlush( fgDisplay.pDisplay.Display ); */ /* XXX Shouldn't need this */
-}
-
-
-/*
- * This function makes the current window visible
- */
-void fgPlatformGlutShowWindow( void )
-{
- XMapWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-/*
- * This function hides the current window
- */
-void fgPlatformGlutHideWindow( void )
-{
- if( fgStructure.CurrentWindow->Parent == NULL )
- XWithdrawWindow( fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- fgDisplay.pDisplay.Screen );
- else
- XUnmapWindow( fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle );
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-/*
- * Iconify the current window (top-level windows only)
- */
-void fgPlatformGlutIconifyWindow( void )
-{
- XIconifyWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
- fgDisplay.pDisplay.Screen );
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-/*
- * Set the current window's title
- */
-void fgPlatformGlutSetWindowTitle( const char* title )
-{
- XTextProperty text;
-
- text.value = (unsigned char *) title;
- text.encoding = XA_STRING;
- text.format = 8;
- text.nitems = strlen( title );
-
- XSetWMName(
- fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- &text
- );
-
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-/*
- * Set the current window's iconified title
- */
-void fgPlatformGlutSetIconTitle( const char* title )
-{
- XTextProperty text;
-
- text.value = (unsigned char *) title;
- text.encoding = XA_STRING;
- text.format = 8;
- text.nitems = strlen( title );
-
- XSetWMIconName(
- fgDisplay.pDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- &text
- );
-
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-/*
- * Change the current window's position
- */
-void fgPlatformGlutPositionWindow( int x, int y )
-{
- XMoveWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
- x, y );
- XFlush( fgDisplay.pDisplay.Display ); /* XXX Shouldn't need this */
-}
-
-/*
- * Lowers the current window (by Z order change)
- */
-void fgPlatformGlutPushWindow( void )
-{
- XLowerWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
-}
-
-/*
- * Raises the current window (by Z order change)
- */
-void fgPlatformGlutPopWindow( void )
-{
- XRaiseWindow( fgDisplay.pDisplay.Display, fgStructure.CurrentWindow->Window.Handle );
-}
-
-/*
- * Resize the current window so that it fits the whole screen
- */
-void fgPlatformGlutFullScreen( SFG_Window *win )
-{
- if(!glutGet(GLUT_FULL_SCREEN)) {
- if(fghToggleFullscreen() != -1) {
- win->State.IsFullscreen = GL_TRUE;
- }
- }
-}
-
-/*
- * If we are fullscreen, resize the current window back to its original size
- */
-void fgPlatformGlutLeaveFullScreen( SFG_Window *win )
-{
- if(glutGet(GLUT_FULL_SCREEN)) {
- if(fghToggleFullscreen() != -1) {
- win->State.IsFullscreen = GL_FALSE;
- }
- }
-}
-
-/*
- * Toggle the window's full screen state.
- */
-void fgPlatformGlutFullScreenToggle( SFG_Window *win )
-{
- if(fghToggleFullscreen() != -1) {
- win->State.IsFullscreen = !win->State.IsFullscreen;
- }
-}
-
+++ /dev/null
-/* Written for XI1 by Nikolas Doerfler <doerflen@in.tum.de> (c) 2008 *
- * Rewritten for XI2 by Florian Echtler <echtler@in.tum.de> (c) 2009 */
-
-#include <GL/freeglut.h>
-
-#include "../fg_internal.h"
-
-#if HAVE_X11_EXTENSIONS_XINPUT2_H
-
-#include <errno.h>
-#include <stdarg.h>
-
-#include <X11/Xlib.h>
-#include <X11/extensions/XInput2.h>
-
-/* import function from freeglut_main.c */
-extern int fgPlatformGetModifiers( int state );
-
-/* extension opcode for XInput */
-int xi_opcode = -1;
-
-/**
- * \brief Sets window up for XI2 events.
- */
-void fgRegisterDevices( Display* dpy, Window* win ) {
-
- XIEventMask mask;
- unsigned char flags[2] = { 0, 0 };
- int event, error;
-
- /*Display* dpy = fgDisplay.pDisplay.Display;
- Window* win = glutGetXWindow();*/
-
- /* get XInput extension opcode */
- if (!XQueryExtension( dpy, "XInputExtension", &xi_opcode, &event, &error )) { xi_opcode = -1; }
-
- /* Select for motion events */
- mask.deviceid = XIAllMasterDevices;
- mask.mask_len = 2;
- mask.mask = flags;
-
- XISetMask(mask.mask, XI_Enter);
- XISetMask(mask.mask, XI_Motion);
- XISetMask(mask.mask, XI_ButtonPress);
- XISetMask(mask.mask, XI_ButtonRelease);
- XISetMask(mask.mask, XI_Leave);
- /*XISetMask(mask.mask, XI_KeyPress);
- XISetMask(mask.mask, XI_KeyRelease);
- XISetMask(mask.mask, XI_DeviceChanged);
- XISetMask(mask.mask, XI_RawEvent);
- XISetMask(mask.mask, XI_FocusIn);
- XISetMask(mask.mask, XI_FocusOut);
- XISetMask(mask.mask, XI_HierarchyChanged);*/
-
- XISelectEvents( dpy, *win, &mask, 1 );
-}
-
-
-void fgPrintXILeaveEvent(XILeaveEvent* event)
-{
- char* mode = "";
- char* detail = "";
- int i;
-
- printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
- event->root, event->event, event->child);
- switch(event->mode)
- {
- case NotifyNormal: mode = "NotifyNormal"; break;
- case NotifyGrab: mode = "NotifyGrab"; break;
- case NotifyUngrab: mode = "NotifyUngrab"; break;
- case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
- }
- switch (event->detail)
- {
- case NotifyAncestor: detail = "NotifyAncestor"; break;
- case NotifyVirtual: detail = "NotifyVirtual"; break;
- case NotifyInferior: detail = "NotifyInferior"; break;
- case NotifyNonlinear: detail = "NotifyNonlinear"; break;
- case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
- case NotifyPointer: detail = "NotifyPointer"; break;
- case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
- case NotifyDetailNone: detail = "NotifyDetailNone"; break;
- }
- printf(" mode: %s (detail %s)\n", mode, detail);
- printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
- event->same_screen ? "[same screen]" : "");
- printf(" buttons:");
- for (i = 0; i < event->buttons.mask_len * 8; i++)
- if (XIMaskIsSet(event->buttons.mask, i))
- printf(" %d", i);
- printf("\n");
-
- printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
- event->mods.locked, event->mods.latched,
- event->mods.base);
- printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
- event->group.locked, event->group.latched,
- event->group.base);
-
- printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
- printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
-
-}
-
-
-void fgPrintXIDeviceEvent(XIDeviceEvent* event)
-{
- double *val;
- int i;
-
- printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
- printf(" detail: %d\n", event->detail);
- printf(" buttons:");
- for (i = 0; i < event->buttons.mask_len * 8; i++)
- if (XIMaskIsSet(event->buttons.mask, i))
- printf(" %d", i);
- printf("\n");
-
- printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
- event->mods.locked, event->mods.latched,
- event->mods.base);
- printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
- event->group.locked, event->group.latched,
- event->group.base);
- printf(" valuators:");
-
- val = event->valuators.values;
- for (i = 0; i < event->valuators.mask_len * 8; i++)
- if (XIMaskIsSet(event->valuators.mask, i))
- printf(" %d: %.2f", i, *val++);
- printf("\n");
-
- printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
- event->root, event->event, event->child);
- printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
- printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
-
-}
-
-
-/**
- * \brief This function is called when an Extension Event is received
- * and calls the corresponding callback functions for these events.
- */
-void fgHandleExtensionEvents( XEvent* base_ev ) {
-
- int i, button = 0;
- XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
-
- if ( XGetEventData( fgDisplay.pDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
-
- XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
- /*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
-
- SFG_Window* window = fgWindowByHandle( event->event );
- if (!window) return;
-
- switch (cookie->evtype) {
-
- case XI_Enter:
- case XI_Leave:
- fgState.Modifiers = fgPlatformGetModifiers( ((XIEnterEvent*)event)->mods.base );
- INVOKE_WCB( *window, MultiEntry, (
- event->deviceid,
- (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
- ));
- #if _DEBUG
- fgPrintXILeaveEvent((XILeaveEvent*)event);
- #endif
- break;
-
- case XI_ButtonPress:
- case XI_ButtonRelease:
- fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
- INVOKE_WCB( *window, MultiButton, (
- event->deviceid,
- event->event_x,
- event->event_y,
- (event->detail)-1,
- (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
- ));
- INVOKE_WCB( *window, Mouse, (
- (event->detail)-1,
- (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP),
- event->event_x,
- event->event_y
- ));
- break;
-
- case XI_Motion:
- fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
- for (i = 0; i < event->buttons.mask_len; i++) if (event->buttons.mask[i]) button = 1;
- if (button) {
- INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
- INVOKE_WCB( *window, Motion, ( event->event_x, event->event_y ) );
- } else {
- INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
- INVOKE_WCB( *window, Passive, ( event->event_x, event->event_y ) );
- }
- #if _DEBUG
- fgPrintXIDeviceEvent(event);
- #endif
- break;
-
- default:
- #if _DEBUG
- fgWarning( "Unknown XI2 device event:" );
- fgPrintXIDeviceEvent( event );
- #endif
- break;
- }
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- XFreeEventData( fgDisplay.pDisplay.Display, cookie );
-}
-
-#endif\r
-\r