From 5b3d339481bac6dbaeb599bffc1325f716585bfe Mon Sep 17 00:00:00 2001 From: Diederick Niehorster Date: Sun, 11 Mar 2012 15:14:33 +0000 Subject: [PATCH] and some more renames git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1112 7f0cb862-5218-0410-a997-914c9d46530a --- CMakeLists.txt | 146 ++-- src/mswin/fg_cursor_mswin.c | 115 +++ src/mswin/fg_display_mswin.c | 37 + src/mswin/fg_ext_mswin.c | 56 ++ src/mswin/fg_gamemode_mswin.c | 153 ++++ src/mswin/fg_init_mswin.c | 176 +++++ src/mswin/fg_input_devices_mswin.c | 127 +++ src/mswin/fg_internal_mswin.h | 126 +++ src/mswin/fg_joystick_mswin.c | 264 +++++++ src/mswin/fg_main_mswin.c | 1131 +++++++++++++++++++++++++++ src/mswin/fg_menu_mswin.c | 48 ++ src/mswin/fg_spaceball_mswin.c | 58 ++ src/mswin/fg_state_mswin.c | 306 ++++++++ src/mswin/fg_structure_mswin.c | 34 + src/mswin/fg_window_mswin.c | 1078 +++++++++++++++++++++++++ src/mswin/freeglut_cursor_mswin.c | 115 --- src/mswin/freeglut_display_mswin.c | 37 - src/mswin/freeglut_ext_mswin.c | 56 -- src/mswin/freeglut_gamemode_mswin.c | 153 ---- src/mswin/freeglut_init_mswin.c | 176 ----- src/mswin/freeglut_input_devices_mswin.c | 127 --- src/mswin/freeglut_internal_mswin.h | 126 --- src/mswin/freeglut_joystick_mswin.c | 264 ------- src/mswin/freeglut_main_mswin.c | 1131 --------------------------- src/mswin/freeglut_menu_mswin.c | 48 -- src/mswin/freeglut_spaceball_mswin.c | 58 -- src/mswin/freeglut_state_mswin.c | 306 -------- src/mswin/freeglut_structure_mswin.c | 34 - src/mswin/freeglut_window_mswin.c | 1078 ------------------------- src/x11/fg_cursor_x11.c | 151 ++++ src/x11/fg_display_x11.c | 36 + src/x11/fg_ext_x11.c | 60 ++ src/x11/fg_gamemode_x11.c | 571 ++++++++++++++ src/x11/fg_glutfont_definitions_x11.c | 104 +++ src/x11/fg_init_x11.c | 273 +++++++ src/x11/fg_input_devices_x11.c | 132 ++++ src/x11/fg_internal_x11.h | 229 ++++++ src/x11/fg_joystick_x11.c | 465 +++++++++++ src/x11/fg_main_x11.c | 1083 +++++++++++++++++++++++++ src/x11/fg_menu_x11.c | 49 ++ src/x11/fg_spaceball_x11.c | 415 ++++++++++ src/x11/fg_state_x11.c | 363 +++++++++ src/x11/fg_structure_x11.c | 40 + src/x11/fg_window_x11.c | 800 +++++++++++++++++++ src/x11/fg_xinput_x11.c | 219 ++++++ src/x11/freeglut_cursor_x11.c | 151 ---- src/x11/freeglut_display_x11.c | 36 - src/x11/freeglut_ext_x11.c | 60 -- src/x11/freeglut_gamemode_x11.c | 571 -------------- src/x11/freeglut_glutfont_definitions_x11.c | 104 --- src/x11/freeglut_init_x11.c | 273 ------- src/x11/freeglut_input_devices_x11.c | 132 ---- src/x11/freeglut_internal_x11.h | 229 ------ src/x11/freeglut_joystick_x11.c | 465 ----------- src/x11/freeglut_main_x11.c | 1083 ------------------------- src/x11/freeglut_menu_x11.c | 49 -- src/x11/freeglut_spaceball_x11.c | 415 ---------- src/x11/freeglut_state_x11.c | 363 --------- src/x11/freeglut_structure_x11.c | 40 - src/x11/freeglut_window_x11.c | 800 ------------------- src/x11/freeglut_xinput_x11.c | 219 ------ 61 files changed, 8772 insertions(+), 8772 deletions(-) create mode 100644 src/mswin/fg_cursor_mswin.c create mode 100644 src/mswin/fg_display_mswin.c create mode 100644 src/mswin/fg_ext_mswin.c create mode 100644 src/mswin/fg_gamemode_mswin.c create mode 100644 src/mswin/fg_init_mswin.c create mode 100644 src/mswin/fg_input_devices_mswin.c create mode 100644 src/mswin/fg_internal_mswin.h create mode 100644 src/mswin/fg_joystick_mswin.c create mode 100644 src/mswin/fg_main_mswin.c create mode 100644 src/mswin/fg_menu_mswin.c create mode 100644 src/mswin/fg_spaceball_mswin.c create mode 100644 src/mswin/fg_state_mswin.c create mode 100644 src/mswin/fg_structure_mswin.c create mode 100644 src/mswin/fg_window_mswin.c delete mode 100644 src/mswin/freeglut_cursor_mswin.c delete mode 100644 src/mswin/freeglut_display_mswin.c delete mode 100644 src/mswin/freeglut_ext_mswin.c delete mode 100644 src/mswin/freeglut_gamemode_mswin.c delete mode 100644 src/mswin/freeglut_init_mswin.c delete mode 100644 src/mswin/freeglut_input_devices_mswin.c delete mode 100644 src/mswin/freeglut_internal_mswin.h delete mode 100644 src/mswin/freeglut_joystick_mswin.c delete mode 100644 src/mswin/freeglut_main_mswin.c delete mode 100644 src/mswin/freeglut_menu_mswin.c delete mode 100644 src/mswin/freeglut_spaceball_mswin.c delete mode 100644 src/mswin/freeglut_state_mswin.c delete mode 100644 src/mswin/freeglut_structure_mswin.c delete mode 100644 src/mswin/freeglut_window_mswin.c create mode 100644 src/x11/fg_cursor_x11.c create mode 100644 src/x11/fg_display_x11.c create mode 100644 src/x11/fg_ext_x11.c create mode 100644 src/x11/fg_gamemode_x11.c create mode 100644 src/x11/fg_glutfont_definitions_x11.c create mode 100644 src/x11/fg_init_x11.c create mode 100644 src/x11/fg_input_devices_x11.c create mode 100644 src/x11/fg_internal_x11.h create mode 100644 src/x11/fg_joystick_x11.c create mode 100644 src/x11/fg_main_x11.c create mode 100644 src/x11/fg_menu_x11.c create mode 100644 src/x11/fg_spaceball_x11.c create mode 100644 src/x11/fg_state_x11.c create mode 100644 src/x11/fg_structure_x11.c create mode 100644 src/x11/fg_window_x11.c create mode 100644 src/x11/fg_xinput_x11.c delete mode 100644 src/x11/freeglut_cursor_x11.c delete mode 100644 src/x11/freeglut_display_x11.c delete mode 100644 src/x11/freeglut_ext_x11.c delete mode 100644 src/x11/freeglut_gamemode_x11.c delete mode 100644 src/x11/freeglut_glutfont_definitions_x11.c delete mode 100644 src/x11/freeglut_init_x11.c delete mode 100644 src/x11/freeglut_input_devices_x11.c delete mode 100644 src/x11/freeglut_internal_x11.h delete mode 100644 src/x11/freeglut_joystick_x11.c delete mode 100644 src/x11/freeglut_main_x11.c delete mode 100644 src/x11/freeglut_menu_x11.c delete mode 100644 src/x11/freeglut_spaceball_x11.c delete mode 100644 src/x11/freeglut_state_x11.c delete mode 100644 src/x11/freeglut_structure_x11.c delete mode 100644 src/x11/freeglut_window_x11.c delete mode 100644 src/x11/freeglut_xinput_x11.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b9d568..08ef46a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,97 +9,97 @@ SET(FREEGLUT_HEADERS ) 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 ) diff --git a/src/mswin/fg_cursor_mswin.c b/src/mswin/fg_cursor_mswin.c new file mode 100644 index 0000000..b0eda70 --- /dev/null +++ b/src/mswin/fg_cursor_mswin.c @@ -0,0 +1,115 @@ +/* + * 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, + * 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 +#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 ); +} + + diff --git a/src/mswin/fg_display_mswin.c b/src/mswin/fg_display_mswin.c new file mode 100644 index 0000000..6a58412 --- /dev/null +++ b/src/mswin/fg_display_mswin.c @@ -0,0 +1,37 @@ +/* + * 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, + * 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 +#include "../fg_internal.h" + + + + +void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) +{ + SwapBuffers( CurrentWindow->Window.pContext.Device ); +} diff --git a/src/mswin/fg_ext_mswin.c b/src/mswin/fg_ext_mswin.c new file mode 100644 index 0000000..efc2fa9 --- /dev/null +++ b/src/mswin/fg_ext_mswin.c @@ -0,0 +1,56 @@ +/* + * 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, + * 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 +#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 ); +} diff --git a/src/mswin/fg_gamemode_mswin.c b/src/mswin/fg_gamemode_mswin.c new file mode 100644 index 0000000..3e5228d --- /dev/null +++ b/src/mswin/fg_gamemode_mswin.c @@ -0,0 +1,153 @@ +/* + * 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, + * 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 +#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 ) +{ +} diff --git a/src/mswin/fg_init_mswin.c b/src/mswin/fg_init_mswin.c new file mode 100644 index 0000000..f80fe78 --- /dev/null +++ b/src/mswin/fg_init_mswin.c @@ -0,0 +1,176 @@ +/* + * 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, + * 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 +#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); +} + diff --git a/src/mswin/fg_input_devices_mswin.c b/src/mswin/fg_input_devices_mswin.c new file mode 100644 index 0000000..ba230d4 --- /dev/null +++ b/src/mswin/fg_input_devices_mswin.c @@ -0,0 +1,127 @@ +/* + * 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, + * 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 +#include "../fg_internal.h" + +#include +#include + +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); +} + diff --git a/src/mswin/fg_internal_mswin.h b/src/mswin/fg_internal_mswin.h new file mode 100644 index 0000000..571db40 --- /dev/null +++ b/src/mswin/fg_internal_mswin.h @@ -0,0 +1,126 @@ +/* + * freeglut_internal_mswin.h + * + * The freeglut library private include file. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * 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 +# include +# include +/* CYGWIN does not have tchar.h, but has TEXT(x), defined in winnt.h. */ +# ifndef __CYGWIN__ +# include +# 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 */ diff --git a/src/mswin/fg_joystick_mswin.c b/src/mswin/fg_joystick_mswin.c new file mode 100644 index 0000000..aefa192 --- /dev/null +++ b/src/mswin/fg_joystick_mswin.c @@ -0,0 +1,264 @@ +/* + * 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, + * 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 +#include "../fg_internal.h" + + +#if !defined(_WIN32_WCE) +# include +# include +# include + + + + +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 + diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c new file mode 100644 index 0000000..d84940f --- /dev/null +++ b/src/mswin/fg_main_mswin.c @@ -0,0 +1,1131 @@ +/* + * 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, + * 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 +#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 + +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; +} diff --git a/src/mswin/fg_menu_mswin.c b/src/mswin/fg_menu_mswin.c new file mode 100644 index 0000000..d198cca --- /dev/null +++ b/src/mswin/fg_menu_mswin.c @@ -0,0 +1,48 @@ +/* + * 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, + * 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 +#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 ); +} + diff --git a/src/mswin/fg_spaceball_mswin.c b/src/mswin/fg_spaceball_mswin.c new file mode 100644 index 0000000..3a7af46 --- /dev/null +++ b/src/mswin/fg_spaceball_mswin.c @@ -0,0 +1,58 @@ +/* + * freeglut_spaceball_mswin.c + * + * Spaceball support for Windows + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by Evan Felix + * 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 +#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; +} diff --git a/src/mswin/fg_state_mswin.c b/src/mswin/fg_state_mswin.c new file mode 100644 index 0000000..07ffdb1 --- /dev/null +++ b/src/mswin/fg_state_mswin.c @@ -0,0 +1,306 @@ +/* + * freeglut_state_mswin.c + * + * The Windows-specific state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * 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 +#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 + * So we copy the necessary parts out of it to support the multisampling query + */ +#define WGL_SAMPLES_ARB 0x2042 + +#if defined(_WIN32_WCE) +# include +# 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 diff --git a/src/mswin/fg_structure_mswin.c b/src/mswin/fg_structure_mswin.c new file mode 100644 index 0000000..8ccb33d --- /dev/null +++ b/src/mswin/fg_structure_mswin.c @@ -0,0 +1,34 @@ +/* + * 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, + * 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 +#include "../fg_internal.h" + + +void fgPlatformCreateWindow ( SFG_Window *window ) +{ +} diff --git a/src/mswin/fg_window_mswin.c b/src/mswin/fg_window_mswin.c new file mode 100644 index 0000000..6515063 --- /dev/null +++ b/src/mswin/fg_window_mswin.c @@ -0,0 +1,1078 @@ +/* + * 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, + * 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 +#include "../fg_internal.h" + + +/* The following include file is available from SGI but is not standard: + * #include + * 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; iWindow.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 ); +} + diff --git a/src/mswin/freeglut_cursor_mswin.c b/src/mswin/freeglut_cursor_mswin.c deleted file mode 100644 index b0eda70..0000000 --- a/src/mswin/freeglut_cursor_mswin.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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, - * 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 -#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 ); -} - - diff --git a/src/mswin/freeglut_display_mswin.c b/src/mswin/freeglut_display_mswin.c deleted file mode 100644 index 6a58412..0000000 --- a/src/mswin/freeglut_display_mswin.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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, - * 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 -#include "../fg_internal.h" - - - - -void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) -{ - SwapBuffers( CurrentWindow->Window.pContext.Device ); -} diff --git a/src/mswin/freeglut_ext_mswin.c b/src/mswin/freeglut_ext_mswin.c deleted file mode 100644 index efc2fa9..0000000 --- a/src/mswin/freeglut_ext_mswin.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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, - * 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 -#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 ); -} diff --git a/src/mswin/freeglut_gamemode_mswin.c b/src/mswin/freeglut_gamemode_mswin.c deleted file mode 100644 index 3e5228d..0000000 --- a/src/mswin/freeglut_gamemode_mswin.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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, - * 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 -#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 ) -{ -} diff --git a/src/mswin/freeglut_init_mswin.c b/src/mswin/freeglut_init_mswin.c deleted file mode 100644 index f80fe78..0000000 --- a/src/mswin/freeglut_init_mswin.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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, - * 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 -#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); -} - diff --git a/src/mswin/freeglut_input_devices_mswin.c b/src/mswin/freeglut_input_devices_mswin.c deleted file mode 100644 index ba230d4..0000000 --- a/src/mswin/freeglut_input_devices_mswin.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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, - * 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 -#include "../fg_internal.h" - -#include -#include - -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); -} - diff --git a/src/mswin/freeglut_internal_mswin.h b/src/mswin/freeglut_internal_mswin.h deleted file mode 100644 index 571db40..0000000 --- a/src/mswin/freeglut_internal_mswin.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * freeglut_internal_mswin.h - * - * The freeglut library private include file. - * - * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. - * Written by John F. Fay, - * 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 -# include -# include -/* CYGWIN does not have tchar.h, but has TEXT(x), defined in winnt.h. */ -# ifndef __CYGWIN__ -# include -# 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 */ diff --git a/src/mswin/freeglut_joystick_mswin.c b/src/mswin/freeglut_joystick_mswin.c deleted file mode 100644 index aefa192..0000000 --- a/src/mswin/freeglut_joystick_mswin.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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, - * 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 -#include "../fg_internal.h" - - -#if !defined(_WIN32_WCE) -# include -# include -# include - - - - -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 - diff --git a/src/mswin/freeglut_main_mswin.c b/src/mswin/freeglut_main_mswin.c deleted file mode 100644 index a1c5c8c..0000000 --- a/src/mswin/freeglut_main_mswin.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * 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, - * 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 -#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 - -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; -} diff --git a/src/mswin/freeglut_menu_mswin.c b/src/mswin/freeglut_menu_mswin.c deleted file mode 100644 index d198cca..0000000 --- a/src/mswin/freeglut_menu_mswin.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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, - * 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 -#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 ); -} - diff --git a/src/mswin/freeglut_spaceball_mswin.c b/src/mswin/freeglut_spaceball_mswin.c deleted file mode 100644 index 3a7af46..0000000 --- a/src/mswin/freeglut_spaceball_mswin.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * freeglut_spaceball_mswin.c - * - * Spaceball support for Windows - * - * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. - * Written by Evan Felix - * 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 -#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; -} diff --git a/src/mswin/freeglut_state_mswin.c b/src/mswin/freeglut_state_mswin.c deleted file mode 100644 index 07ffdb1..0000000 --- a/src/mswin/freeglut_state_mswin.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * freeglut_state_mswin.c - * - * The Windows-specific state query methods. - * - * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. - * Written by John F. Fay, - * 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 -#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 - * So we copy the necessary parts out of it to support the multisampling query - */ -#define WGL_SAMPLES_ARB 0x2042 - -#if defined(_WIN32_WCE) -# include -# 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 diff --git a/src/mswin/freeglut_structure_mswin.c b/src/mswin/freeglut_structure_mswin.c deleted file mode 100644 index 8ccb33d..0000000 --- a/src/mswin/freeglut_structure_mswin.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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, - * 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 -#include "../fg_internal.h" - - -void fgPlatformCreateWindow ( SFG_Window *window ) -{ -} diff --git a/src/mswin/freeglut_window_mswin.c b/src/mswin/freeglut_window_mswin.c deleted file mode 100644 index 6515063..0000000 --- a/src/mswin/freeglut_window_mswin.c +++ /dev/null @@ -1,1078 +0,0 @@ -/* - * 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, - * 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 -#include "../fg_internal.h" - - -/* The following include file is available from SGI but is not standard: - * #include - * 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; iWindow.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 ); -} - diff --git a/src/x11/fg_cursor_x11.c b/src/x11/fg_cursor_x11.c new file mode 100644 index 0000000..3098e53 --- /dev/null +++ b/src/x11/fg_cursor_x11.c @@ -0,0 +1,151 @@ +/* + * 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, + * 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 +#include "../fg_internal.h" + +/* This code is for Posix/X11, Solaris, and OSX */ +#include + +/* + * 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 ); +} + diff --git a/src/x11/fg_display_x11.c b/src/x11/fg_display_x11.c new file mode 100644 index 0000000..bbf9061 --- /dev/null +++ b/src/x11/fg_display_x11.c @@ -0,0 +1,36 @@ +/* + * 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, + * Copied for Platform code by Evan Felix + * 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 +#include "../fg_internal.h" + +void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) +{ + glXSwapBuffers( pDisplayPtr->Display, CurrentWindow->Window.Handle ); +} + diff --git a/src/x11/fg_ext_x11.c b/src/x11/fg_ext_x11.c new file mode 100644 index 0000000..d243cfd --- /dev/null +++ b/src/x11/fg_ext_x11.c @@ -0,0 +1,60 @@ +/* + * freeglut_ext.c + * + * Functions related to OpenGL extensions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * 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 +#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 +} + diff --git a/src/x11/fg_gamemode_x11.c b/src/x11/fg_gamemode_x11.c new file mode 100644 index 0000000..6130aeb --- /dev/null +++ b/src/x11/fg_gamemode_x11.c @@ -0,0 +1,571 @@ +/* + * freeglut_gamemode_x11.c + * + * The game mode handling code. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * 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 +#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= 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= 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 ); +} + diff --git a/src/x11/fg_glutfont_definitions_x11.c b/src/x11/fg_glutfont_definitions_x11.c new file mode 100644 index 0000000..f2519c5 --- /dev/null +++ b/src/x11/fg_glutfont_definitions_x11.c @@ -0,0 +1,104 @@ +/* + * 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 , 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 + +#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 ; + diff --git a/src/x11/fg_init_x11.c b/src/x11/fg_init_x11.c new file mode 100644 index 0000000..83fe287 --- /dev/null +++ b/src/x11/fg_init_x11.c @@ -0,0 +1,273 @@ +/* + * freeglut_init_x11.c + * + * Various freeglut initialization functions. + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * 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 /* LONG_MAX */ +#include +#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 ); +} diff --git a/src/x11/fg_input_devices_x11.c b/src/x11/fg_input_devices_x11.c new file mode 100644 index 0000000..a94e52a --- /dev/null +++ b/src/x11/fg_input_devices_x11.c @@ -0,0 +1,132 @@ +/* + * 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 2005 + * + * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved. + * Copied for Platform code by Evan Felix + * 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 +#include "../fg_internal.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#include +#include +#include +#include +#include + +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 ); +} diff --git a/src/x11/fg_internal_x11.h b/src/x11/fg_internal_x11.h new file mode 100644 index 0000000..8a8e197 --- /dev/null +++ b/src/x11/fg_internal_x11.h @@ -0,0 +1,229 @@ +/* + * freeglut_internal_x11.h + * + * The freeglut library private include file. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by Diederick C. Niehorster, + * 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 +#include +#include +#include +#include +#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H +# include +#endif +#ifdef HAVE_X11_EXTENSIONS_XRANDR_H +# include +#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 +# endif +# ifdef HAVE_FCNTL_H +# include +# endif +# ifdef HAVE_ERRNO_H +# include +# include +# 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 +# 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 /* For analog joysticks */ +# endif +# define JS_DATA_TYPE joystick +# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) +# endif + +# if defined(__linux__) +# include + +/* 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 */ diff --git a/src/x11/fg_joystick_x11.c b/src/x11/fg_joystick_x11.c new file mode 100644 index 0000000..5d686b5 --- /dev/null +++ b/src/x11/fg_joystick_x11.c @@ -0,0 +1,465 @@ +/* + * freeglut_joystick_x11.c + * + * Joystick handling code + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Steve Baker, + * Copied for Platform code by Evan Felix + * 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 + * + * 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 +#include "../fg_internal.h" +#ifdef HAVE_SYS_PARAM_H +# include +#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 ); +} + diff --git a/src/x11/fg_main_x11.c b/src/x11/fg_main_x11.c new file mode 100644 index 0000000..e72db37 --- /dev/null +++ b/src/x11/fg_main_x11.c @@ -0,0 +1,1083 @@ +/* + * 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, + * Copied for Platform code by Evan Felix + * 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 +#include "../fg_internal.h" +#ifdef HAVE_ERRNO_H +# include +#endif +#include +#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 +#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 ) +{ +} + diff --git a/src/x11/fg_menu_x11.c b/src/x11/fg_menu_x11.c new file mode 100644 index 0000000..0443dcd --- /dev/null +++ b/src/x11/fg_menu_x11.c @@ -0,0 +1,49 @@ +/* + * 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, + * Copied for Platform code by Evan Felix + * 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 +#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; +} + diff --git a/src/x11/fg_spaceball_x11.c b/src/x11/fg_spaceball_x11.c new file mode 100644 index 0000000..582a926 --- /dev/null +++ b/src/x11/fg_spaceball_x11.c @@ -0,0 +1,415 @@ +/* Spaceball support for Linux. + * Written by John Tsiombikas + * Copied for Platform code by Evan Felix + * 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 +#include "../fg_internal.h" + +#include + +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 + +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 +#include +#include + +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include + +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; +} + diff --git a/src/x11/fg_state_x11.c b/src/x11/fg_state_x11.c new file mode 100644 index 0000000..3523477 --- /dev/null +++ b/src/x11/fg_state_x11.c @@ -0,0 +1,363 @@ +/* + * freeglut_state_x11.c + * + * X11-specific freeglut state query methods. + * + * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. + * Written by John F. Fay, + * 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 +#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; +} + + diff --git a/src/x11/fg_structure_x11.c b/src/x11/fg_structure_x11.c new file mode 100644 index 0000000..cbc9129 --- /dev/null +++ b/src/x11/fg_structure_x11.c @@ -0,0 +1,40 @@ +/* + * freeglut_structure.c + * + * Windows and menus need tree structure + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * 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 +#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; +} + diff --git a/src/x11/fg_window_x11.c b/src/x11/fg_window_x11.c new file mode 100644 index 0000000..44c9952 --- /dev/null +++ b/src/x11/fg_window_x11.c @@ -0,0 +1,800 @@ +/* + * freeglut_window_x11.c + * + * Window management methods for X11 + * + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, + * Copied for Platform code by Evan Felix + * 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 +#include /* LONG_MAX */ +#include /* 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; + } +} + diff --git a/src/x11/fg_xinput_x11.c b/src/x11/fg_xinput_x11.c new file mode 100644 index 0000000..fac1bf7 --- /dev/null +++ b/src/x11/fg_xinput_x11.c @@ -0,0 +1,219 @@ +/* Written for XI1 by Nikolas Doerfler (c) 2008 * + * Rewritten for XI2 by Florian Echtler (c) 2009 */ + +#include + +#include "../fg_internal.h" + +#if HAVE_X11_EXTENSIONS_XINPUT2_H + +#include +#include + +#include +#include + +/* 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 + diff --git a/src/x11/freeglut_cursor_x11.c b/src/x11/freeglut_cursor_x11.c deleted file mode 100644 index 3098e53..0000000 --- a/src/x11/freeglut_cursor_x11.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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, - * 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 -#include "../fg_internal.h" - -/* This code is for Posix/X11, Solaris, and OSX */ -#include - -/* - * 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 ); -} - diff --git a/src/x11/freeglut_display_x11.c b/src/x11/freeglut_display_x11.c deleted file mode 100644 index bbf9061..0000000 --- a/src/x11/freeglut_display_x11.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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, - * Copied for Platform code by Evan Felix - * 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 -#include "../fg_internal.h" - -void fgPlatformGlutSwapBuffers( SFG_PlatformDisplay *pDisplayPtr, SFG_Window* CurrentWindow ) -{ - glXSwapBuffers( pDisplayPtr->Display, CurrentWindow->Window.Handle ); -} - diff --git a/src/x11/freeglut_ext_x11.c b/src/x11/freeglut_ext_x11.c deleted file mode 100644 index d243cfd..0000000 --- a/src/x11/freeglut_ext_x11.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * freeglut_ext.c - * - * Functions related to OpenGL extensions. - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Copied for Platform code by Evan Felix - * 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 -#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 -} - diff --git a/src/x11/freeglut_gamemode_x11.c b/src/x11/freeglut_gamemode_x11.c deleted file mode 100644 index 6130aeb..0000000 --- a/src/x11/freeglut_gamemode_x11.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * freeglut_gamemode_x11.c - * - * The game mode handling code. - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Copied for Platform code by Evan Felix - * 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 -#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= 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= 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 ); -} - diff --git a/src/x11/freeglut_glutfont_definitions_x11.c b/src/x11/freeglut_glutfont_definitions_x11.c deleted file mode 100644 index f2519c5..0000000 --- a/src/x11/freeglut_glutfont_definitions_x11.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 , 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 - -#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 ; - diff --git a/src/x11/freeglut_init_x11.c b/src/x11/freeglut_init_x11.c deleted file mode 100644 index 83fe287..0000000 --- a/src/x11/freeglut_init_x11.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * freeglut_init_x11.c - * - * Various freeglut initialization functions. - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Copied for Platform code by Evan Felix - * 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 /* LONG_MAX */ -#include -#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 ); -} diff --git a/src/x11/freeglut_input_devices_x11.c b/src/x11/freeglut_input_devices_x11.c deleted file mode 100644 index a94e52a..0000000 --- a/src/x11/freeglut_input_devices_x11.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 2005 - * - * Copyright (c) 2005 Stephen J. Baker. All Rights Reserved. - * Copied for Platform code by Evan Felix - * 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 -#include "../fg_internal.h" - -#ifdef HAVE_ERRNO_H -#include -#endif -#include -#include -#include -#include -#include -#include - -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 ); -} diff --git a/src/x11/freeglut_internal_x11.h b/src/x11/freeglut_internal_x11.h deleted file mode 100644 index 8a8e197..0000000 --- a/src/x11/freeglut_internal_x11.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * freeglut_internal_x11.h - * - * The freeglut library private include file. - * - * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. - * Written by Diederick C. Niehorster, - * 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 -#include -#include -#include -#include -#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H -# include -#endif -#ifdef HAVE_X11_EXTENSIONS_XRANDR_H -# include -#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 -# endif -# ifdef HAVE_FCNTL_H -# include -# endif -# ifdef HAVE_ERRNO_H -# include -# include -# 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 -# 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 /* For analog joysticks */ -# endif -# define JS_DATA_TYPE joystick -# define JS_RETURN (sizeof(struct JS_DATA_TYPE)) -# endif - -# if defined(__linux__) -# include - -/* 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 */ diff --git a/src/x11/freeglut_joystick_x11.c b/src/x11/freeglut_joystick_x11.c deleted file mode 100644 index 5d686b5..0000000 --- a/src/x11/freeglut_joystick_x11.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * freeglut_joystick_x11.c - * - * Joystick handling code - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Steve Baker, - * Copied for Platform code by Evan Felix - * 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 - * - * 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 -#include "../fg_internal.h" -#ifdef HAVE_SYS_PARAM_H -# include -#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 ); -} - diff --git a/src/x11/freeglut_main_x11.c b/src/x11/freeglut_main_x11.c deleted file mode 100644 index e72db37..0000000 --- a/src/x11/freeglut_main_x11.c +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * 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, - * Copied for Platform code by Evan Felix - * 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 -#include "../fg_internal.h" -#ifdef HAVE_ERRNO_H -# include -#endif -#include -#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 -#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 ) -{ -} - diff --git a/src/x11/freeglut_menu_x11.c b/src/x11/freeglut_menu_x11.c deleted file mode 100644 index 0443dcd..0000000 --- a/src/x11/freeglut_menu_x11.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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, - * Copied for Platform code by Evan Felix - * 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 -#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; -} - diff --git a/src/x11/freeglut_spaceball_x11.c b/src/x11/freeglut_spaceball_x11.c deleted file mode 100644 index 582a926..0000000 --- a/src/x11/freeglut_spaceball_x11.c +++ /dev/null @@ -1,415 +0,0 @@ -/* Spaceball support for Linux. - * Written by John Tsiombikas - * Copied for Platform code by Evan Felix - * 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 -#include "../fg_internal.h" - -#include - -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 - -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 -#include -#include - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include - -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; -} - diff --git a/src/x11/freeglut_state_x11.c b/src/x11/freeglut_state_x11.c deleted file mode 100644 index 3523477..0000000 --- a/src/x11/freeglut_state_x11.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * freeglut_state_x11.c - * - * X11-specific freeglut state query methods. - * - * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. - * Written by John F. Fay, - * 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 -#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; -} - - diff --git a/src/x11/freeglut_structure_x11.c b/src/x11/freeglut_structure_x11.c deleted file mode 100644 index cbc9129..0000000 --- a/src/x11/freeglut_structure_x11.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * freeglut_structure.c - * - * Windows and menus need tree structure - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Copied for Platform code by Evan Felix - * 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 -#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; -} - diff --git a/src/x11/freeglut_window_x11.c b/src/x11/freeglut_window_x11.c deleted file mode 100644 index 44c9952..0000000 --- a/src/x11/freeglut_window_x11.c +++ /dev/null @@ -1,800 +0,0 @@ -/* - * freeglut_window_x11.c - * - * Window management methods for X11 - * - * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. - * Written by Pawel W. Olszta, - * Copied for Platform code by Evan Felix - * 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 -#include /* LONG_MAX */ -#include /* 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; - } -} - diff --git a/src/x11/freeglut_xinput_x11.c b/src/x11/freeglut_xinput_x11.c deleted file mode 100644 index fac1bf7..0000000 --- a/src/x11/freeglut_xinput_x11.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Written for XI1 by Nikolas Doerfler (c) 2008 * - * Rewritten for XI2 by Florian Echtler (c) 2009 */ - -#include - -#include "../fg_internal.h" - -#if HAVE_X11_EXTENSIONS_XINPUT2_H - -#include -#include - -#include -#include - -/* 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 - -- 1.7.10.4