diff --git a/FL/glut.H b/FL/glut.H index 2d4a196c2..6ddf27016 100644 --- a/FL/glut.H +++ b/FL/glut.H @@ -26,6 +26,17 @@ // Commented out lines indicate parts of GLUT that are not emulated. +// Notes: as pointed out in STR #3458 the current GLUT window, +// i.e. the global static variable 'glut_window' can be NULL ... +// (a) if not (yet) initialized +// (b) if the current GLUT window is deleted at any time. +// The FLTK implementation silently ignores function calls if the current +// window is NULL to avoid dereferencing a NULL pointer. This is obviously +// compatible with GLUT version 3.7 according to comment #5 on STR #3458. +// According to the same comment FreeGLUT 3.0 would issue an error message +// and quit. +// Albrecht-S, Oct 2023 + #ifndef _FL_glut_H_ # define _FL_glut_H_ @@ -81,18 +92,18 @@ FL_EXPORT void glutInit(int *argcp, char **argv); // creates first window FL_EXPORT void glutInitDisplayMode(unsigned int mode); // the FL_ symbols have the same value as the GLUT ones: -# define GLUT_RGB FL_RGB -# define GLUT_RGBA FL_RGB -# define GLUT_INDEX FL_INDEX -# define GLUT_SINGLE FL_SINGLE -# define GLUT_DOUBLE FL_DOUBLE -# define GLUT_ACCUM FL_ACCUM -# define GLUT_ALPHA FL_ALPHA -# define GLUT_DEPTH FL_DEPTH -# define GLUT_STENCIL FL_STENCIL -# define GLUT_MULTISAMPLE FL_MULTISAMPLE -# define GLUT_STEREO FL_STEREO -// # define GLUT_LUMINANCE 512 +# define GLUT_RGB FL_RGB +# define GLUT_RGBA FL_RGB +# define GLUT_INDEX FL_INDEX +# define GLUT_SINGLE FL_SINGLE +# define GLUT_DOUBLE FL_DOUBLE +# define GLUT_ACCUM FL_ACCUM +# define GLUT_ALPHA FL_ALPHA +# define GLUT_DEPTH FL_DEPTH +# define GLUT_STENCIL FL_STENCIL +# define GLUT_MULTISAMPLE FL_MULTISAMPLE +# define GLUT_STEREO FL_STEREO +// # define GLUT_LUMINANCE 512 FL_EXPORT void glutInitWindowPosition(int x, int y); @@ -107,37 +118,62 @@ FL_EXPORT int glutCreateSubWindow(int win, int x, int y, int width, int height); FL_EXPORT void glutDestroyWindow(int win); -inline void glutPostRedisplay() {glut_window->redraw();} +inline void glutPostRedisplay() { + if (glut_window) glut_window->redraw(); +} FL_EXPORT void glutPostWindowRedisplay(int win); FL_EXPORT void glutSwapBuffers(); -inline int glutGetWindow() {return glut_window->number;} +inline int glutGetWindow() { + return glut_window ? glut_window->number : 0; +} FL_EXPORT void glutSetWindow(int win); -inline void glutSetWindowTitle(char *t) {glut_window->label(t);} +inline void glutSetWindowTitle(char *t) { + if (glut_window) glut_window->label(t); +} -inline void glutSetIconTitle(char *t) {glut_window->iconlabel(t);} +inline void glutSetIconTitle(char *t) { + if (glut_window) glut_window->iconlabel(t); +} -inline void glutPositionWindow(int x, int y) {glut_window->position(x,y);} +inline void glutPositionWindow(int x, int y) { + if (glut_window) glut_window->position(x,y); +} -inline void glutReshapeWindow(int w, int h) {glut_window->size(w,h);} +inline void glutReshapeWindow(int w, int h) { + if (glut_window) glut_window->size(w,h); +} -inline void glutPopWindow() {glut_window->show();} +inline void glutPopWindow() { + if (glut_window) glut_window->show(); +} inline void glutPushWindow() { /* do nothing */ } -inline void glutIconifyWindow() {glut_window->iconize();} +inline void glutIconifyWindow() { + if (glut_window) glut_window->iconize(); +} -inline void glutShowWindow() {glut_window->show();} +inline void glutShowWindow() { + if (glut_window) glut_window->show(); +} -inline void glutHideWindow() {glut_window->hide();} +inline void glutHideWindow() { + if (glut_window) glut_window->hide(); +} -inline void glutFullScreen() {glut_window->fullscreen();} +inline void glutFullScreen() { + if (glut_window) glut_window->fullscreen(); +} + +inline void glutSetCursor(Fl_Cursor cursor) { + if (glut_window) glut_window->cursor(cursor); +} -inline void glutSetCursor(Fl_Cursor cursor) {glut_window->cursor(cursor);} // notice that the numeric values are different than glut: # define GLUT_CURSOR_RIGHT_ARROW ((Fl_Cursor)2) # define GLUT_CURSOR_LEFT_ARROW ((Fl_Cursor)67) @@ -165,19 +201,33 @@ inline void glutSetCursor(Fl_Cursor cursor) {glut_window->cursor(cursor);} inline void glutWarpPointer(int, int) { /* do nothing */ } -inline void glutEstablishOverlay() {glut_window->make_overlay_current();} +inline void glutEstablishOverlay() { + if (glut_window) glut_window->make_overlay_current(); +} -inline void glutRemoveOverlay() {glut_window->hide_overlay();} +inline void glutRemoveOverlay() { + if (glut_window) glut_window->hide_overlay(); +} inline void glutUseLayer(GLenum layer) { - layer ? glut_window->make_overlay_current() : glut_window->make_current();} + if (!glut_window) + return; + layer ? glut_window->make_overlay_current() : glut_window->make_current(); +} + enum {GLUT_NORMAL, GLUT_OVERLAY}; -inline void glutPostOverlayRedisplay() {glut_window->redraw_overlay();} +inline void glutPostOverlayRedisplay() { + if (glut_window) glut_window->redraw_overlay(); +} -inline void glutShowOverlay() {glut_window->redraw_overlay();} +inline void glutShowOverlay() { + if (glut_window) glut_window->redraw_overlay(); +} -inline void glutHideOverlay() {glut_window->hide_overlay();} +inline void glutHideOverlay() { + if (glut_window) glut_window->hide_overlay(); +} FL_EXPORT int glutCreateMenu(void (*)(int)); @@ -197,34 +247,53 @@ FL_EXPORT void glutChangeToSubMenu(int item, char *label, int submenu); FL_EXPORT void glutRemoveMenuItem(int item); -inline void glutAttachMenu(int b) {glut_window->menu[b] = glut_menu;} +inline void glutAttachMenu(int b) { + if (glut_window) glut_window->menu[b] = glut_menu; +} -inline void glutDetachMenu(int b) {glut_window->menu[b] = 0;} +inline void glutDetachMenu(int b) { + if (glut_window) glut_window->menu[b] = 0; +} -inline void glutDisplayFunc(void (*f)()) {glut_window->display = f;} +inline void glutDisplayFunc(void (*f)()) { + if (glut_window) glut_window->display = f; +} -inline void glutReshapeFunc(void (*f)(int w, int h)) {glut_window->reshape=f;} +inline void glutReshapeFunc(void (*f)(int w, int h)) { + if (glut_window) glut_window->reshape = f; +} inline void glutKeyboardFunc(void (*f)(uchar key, int x, int y)) { - glut_window->keyboard = f;} + if (glut_window) glut_window->keyboard = f; +} inline void glutMouseFunc(void (*f)(int b, int state, int x, int y)) { - glut_window->mouse = f;} + if (glut_window) glut_window->mouse = f; +} + # define GLUT_LEFT_BUTTON 0 # define GLUT_MIDDLE_BUTTON 1 # define GLUT_RIGHT_BUTTON 2 # define GLUT_DOWN 0 # define GLUT_UP 1 -inline void glutMotionFunc(void (*f)(int x, int y)) {glut_window->motion= f;} +inline void glutMotionFunc(void (*f)(int x, int y)) { + if (glut_window) glut_window->motion = f; +} inline void glutPassiveMotionFunc(void (*f)(int x, int y)) { - glut_window->passivemotion= f;} + if (glut_window) glut_window->passivemotion = f; +} + +inline void glutEntryFunc(void (*f)(int s)) { + if (glut_window) glut_window->entry = f; +} -inline void glutEntryFunc(void (*f)(int s)) {glut_window->entry = f;} enum {GLUT_LEFT, GLUT_ENTERED}; -inline void glutVisibilityFunc(void (*f)(int s)) {glut_window->visibility=f;} +inline void glutVisibilityFunc(void (*f)(int s)) { + if (glut_window) glut_window->visibility = f; +} enum {GLUT_NOT_VISIBLE, GLUT_VISIBLE}; FL_EXPORT void glutIdleFunc(void (*f)()); @@ -241,7 +310,9 @@ inline void glutMenuStatusFunc(void (*f)(int status, int x, int y)) { enum {GLUT_MENU_NOT_IN_USE, GLUT_MENU_IN_USE}; inline void glutSpecialFunc(void (*f)(int key, int x, int y)) { - glut_window->special = f;} + if (glut_window) glut_window->special = f; +} + # define GLUT_KEY_F1 1 # define GLUT_KEY_F2 2 # define GLUT_KEY_F3 3 @@ -265,35 +336,36 @@ inline void glutSpecialFunc(void (*f)(int key, int x, int y)) { # define GLUT_KEY_END FL_End # define GLUT_KEY_INSERT FL_Insert -//inline void glutSpaceballMotionFunc(void (*)(int x, int y, int z)); +// inline void glutSpaceballMotionFunc(void (*)(int x, int y, int z)); -//inline void glutSpaceballRotateFunc(void (*)(int x, int y, int z)); +// inline void glutSpaceballRotateFunc(void (*)(int x, int y, int z)); -//inline void glutSpaceballButtonFunc(void (*)(int button, int state)); +// inline void glutSpaceballButtonFunc(void (*)(int button, int state)); -//inline void glutButtonBoxFunc(void (*)(int button, int state)); +// inline void glutButtonBoxFunc(void (*)(int button, int state)); -//inline void glutDialsFunc(void (*)(int dial, int value)); +// inline void glutDialsFunc(void (*)(int dial, int value)); -//inline void glutTabletMotionFunc(void (*)(int x, int y)); +// inline void glutTabletMotionFunc(void (*)(int x, int y)); -//inline void glutTabletButtonFunc(void (*)(int button, int state, int x, int y)); +// inline void glutTabletButtonFunc(void (*)(int button, int state, int x, int y)); inline void glutOverlayDisplayFunc(void (*f)()) { - glut_window->overlaydisplay = f;} + if (glut_window) glut_window->overlaydisplay = f; +} -//inline void glutWindowStatusFunc(void (*)(int state)); -//enum {GLUT_HIDDEN, GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED, -// GLUT_FULLY_COVERED}; +// inline void glutWindowStatusFunc(void (*)(int state)); +// enum {GLUT_HIDDEN, GLUT_FULLY_RETAINED, GLUT_PARTIALLY_RETAINED, +// GLUT_FULLY_COVERED}; -//inline void glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +// inline void glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); -//inline GLfloat glutGetColor(int ndx, int component); -//#define GLUT_RED 0 -//#define GLUT_GREEN 1 -//#define GLUT_BLUE 2 +// inline GLfloat glutGetColor(int ndx, int component); +// #define GLUT_RED 0 +// #define GLUT_GREEN 1 +// #define GLUT_BLUE 2 -//inline void glutCopyColormap(int win); +// inline void glutCopyColormap(int win); // Warning: values are changed from GLUT! // Also relies on the GL_ symbols having values greater than 100 @@ -359,13 +431,16 @@ FL_EXPORT int glutDeviceGet(GLenum type); # define GLUT_ACTIVE_SHIFT FL_SHIFT # define GLUT_ACTIVE_CTRL FL_CTRL # define GLUT_ACTIVE_ALT FL_ALT -inline int glutGetModifiers() {return Fl::event_state() & (GLUT_ACTIVE_SHIFT | GLUT_ACTIVE_CTRL | GLUT_ACTIVE_ALT);} + +inline int glutGetModifiers() { + return Fl::event_state() & (GLUT_ACTIVE_SHIFT | GLUT_ACTIVE_CTRL | GLUT_ACTIVE_ALT); +} FL_EXPORT int glutLayerGet(GLenum); # define GLUT_OVERLAY_POSSIBLE 800 //#define GLUT_LAYER_IN_USE 801 //#define GLUT_HAS_OVERLAY 802 -# define GLUT_TRANSPARENT_INDEX 803 +# define GLUT_TRANSPARENT_INDEX 803 # define GLUT_NORMAL_DAMAGED 804 # define GLUT_OVERLAY_DAMAGED 805 @@ -375,25 +450,25 @@ typedef void (*GLUTproc)(); FL_EXPORT GLUTproc glutGetProcAddress(const char *procName); -//inline int glutVideoResizeGet(GLenum param); -//#define GLUT_VIDEO_RESIZE_POSSIBLE 900 -//#define GLUT_VIDEO_RESIZE_IN_USE 901 -//#define GLUT_VIDEO_RESIZE_X_DELTA 902 -//#define GLUT_VIDEO_RESIZE_Y_DELTA 903 -//#define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 -//#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 -//#define GLUT_VIDEO_RESIZE_X 906 -//#define GLUT_VIDEO_RESIZE_Y 907 -//#define GLUT_VIDEO_RESIZE_WIDTH 908 -//#define GLUT_VIDEO_RESIZE_HEIGHT 909 +// inline int glutVideoResizeGet(GLenum param); +// #define GLUT_VIDEO_RESIZE_POSSIBLE 900 +// #define GLUT_VIDEO_RESIZE_IN_USE 901 +// #define GLUT_VIDEO_RESIZE_X_DELTA 902 +// #define GLUT_VIDEO_RESIZE_Y_DELTA 903 +// #define GLUT_VIDEO_RESIZE_WIDTH_DELTA 904 +// #define GLUT_VIDEO_RESIZE_HEIGHT_DELTA 905 +// #define GLUT_VIDEO_RESIZE_X 906 +// #define GLUT_VIDEO_RESIZE_Y 907 +// #define GLUT_VIDEO_RESIZE_WIDTH 908 +// #define GLUT_VIDEO_RESIZE_HEIGHT 909 -//inline void glutSetupVideoResizing(); +// inline void glutSetupVideoResizing(); -//inline void glutStopVideoResizing(); +// inline void glutStopVideoResizing(); -//inline void glutVideoResize(int x, int y, int width, int height); +// inline void glutVideoResize(int x, int y, int width, int height); -//inline void glutVideoPan(int x, int y, int width, int height); +// inline void glutVideoPan(int x, int y, int width, int height); // Font argument must be a void* for compatibility, so... /** fltk glut font/size attributes used in the glutXXX functions */ diff --git a/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx index bbcebbd84..3f09edae2 100644 --- a/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Gl_Window_Driver.cxx @@ -388,6 +388,8 @@ int Fl_X11_Gl_Window_Driver::mode_(int m, const int *a) { } void Fl_X11_Gl_Window_Driver::swap_buffers() { + if (!fl_xid(pWindow)) // window not shown + return; glXSwapBuffers(fl_display, fl_xid(pWindow)); } diff --git a/src/glut_compatibility.cxx b/src/glut_compatibility.cxx index adcac1b7a..df25c456b 100644 --- a/src/glut_compatibility.cxx +++ b/src/glut_compatibility.cxx @@ -1,7 +1,7 @@ // // GLUT emulation routines for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2016 by Bill Spitzak and others. +// Copyright 1998-2023 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -14,11 +14,11 @@ // https://www.fltk.org/bugs.php // -// Emulation of Glut using fltk. +// Emulation of Glut using FLTK. // GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. -// "This program is freely distributable without licensing fees and is -// provided without guarantee or warrantee expressed or implied. This +// "This program is freely distributable without licensing fees and is +// provided without guarantee or warrantee expressed or implied. This // program is -not- in the public domain." // Although I have copied the GLUT API, none of my code is based on @@ -35,6 +35,7 @@ static Fl_Glut_Window *windows[MAXWINDOWS+1]; static void (*glut_idle_func)() = 0; // global glut idle function +// The current GLUT window, may be NULL. See also STR #3458. Fl_Glut_Window *glut_window; int glut_menu; void (*glut_menustate_function)(int); @@ -61,7 +62,8 @@ void Fl_Glut_Window::draw() { } void glutSwapBuffers() { - if (!indraw) glut_window->swap_buffers(); + if (!indraw && glut_window) + glut_window->swap_buffers(); } void Fl_Glut_Window::draw_overlay() { @@ -389,12 +391,12 @@ void glutRemoveMenuItem(int item) { int glutGet(GLenum type) { switch (type) { case GLUT_RETURN_ZERO: return 0; - case GLUT_WINDOW_X: return glut_window->x(); - case GLUT_WINDOW_Y: return glut_window->y(); - case GLUT_WINDOW_WIDTH: return glut_window->pixel_w(); - case GLUT_WINDOW_HEIGHT: return glut_window->pixel_h(); + case GLUT_WINDOW_X: return glut_window ? glut_window->x() : 0; + case GLUT_WINDOW_Y: return glut_window ? glut_window->y() : 0; + case GLUT_WINDOW_WIDTH: return glut_window ? glut_window->pixel_w() : 0; + case GLUT_WINDOW_HEIGHT: return glut_window ? glut_window->pixel_h() : 0; case GLUT_WINDOW_PARENT: - if (glut_window->parent()) + if (glut_window && glut_window->parent()) return ((Fl_Glut_Window *)(glut_window->parent()))->number; else return 0; @@ -432,11 +434,11 @@ int glutGet(GLenum type) { int glutLayerGet(GLenum type) { switch (type) { - case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay(); + case GLUT_OVERLAY_POSSIBLE: return glut_window ? glut_window->can_do_overlay() : 0; //case GLUT_LAYER_IN_USE: //case GLUT_HAS_OVERLAY: case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI - case GLUT_NORMAL_DAMAGED: return glut_window->damage(); + case GLUT_NORMAL_DAMAGED: return glut_window ? glut_window->damage() : 0; case GLUT_OVERLAY_DAMAGED: return 1; // kind of works... default: return 0; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 1687ebfb8..a44498c4d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -87,11 +87,17 @@ CREATE_EXAMPLE (flex_login flex_login.cxx fltk) CREATE_EXAMPLE (fltk-versions fltk-versions.cxx fltk) CREATE_EXAMPLE (fonts fonts.cxx fltk) CREATE_EXAMPLE (forms forms.cxx "fltk_forms;fltk") + +if (OPENGL_FOUND) + CREATE_EXAMPLE (glut_test glut_test.cxx "fltk_gl;fltk") +endif() + if (OPENGL_FOUND) CREATE_EXAMPLE (handle_events handle_events.cxx "fltk_gl;fltk") # opt. Fl_Gl_Window else() CREATE_EXAMPLE (handle_events handle_events.cxx fltk) # w/o Fl_Gl_Window endif() + CREATE_EXAMPLE (hello hello.cxx fltk) CREATE_EXAMPLE (help_dialog help_dialog.cxx "fltk_images;fltk") CREATE_EXAMPLE (icon icon.cxx fltk) diff --git a/test/Makefile b/test/Makefile index b79a9f766..e73431b03 100644 --- a/test/Makefile +++ b/test/Makefile @@ -75,6 +75,7 @@ CPPFILES =\ fullscreen.cxx \ gl_overlay.cxx \ glpuzzle.cxx \ + glut_test.cxx \ hello.cxx \ help_dialog.cxx \ icon.cxx \ @@ -226,6 +227,7 @@ GLALL = \ fullscreen$(EXEEXT) \ gl_overlay$(EXEEXT) \ glpuzzle$(EXEEXT) \ + glut_test$(EXEEXT) \ shape$(EXEEXT) \ unittests$(EXEEXT) @@ -661,6 +663,11 @@ gl_overlay$(EXEEXT): gl_overlay.o $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ gl_overlay.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) $(OSX_ONLY) ../fltk-config --post $@ +glut_test$(EXEEXT): glut_test.o + echo Linking $@... + $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ glut_test.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) + $(OSX_ONLY) ../fltk-config --post $@ + unittests$(EXEEXT): $(OBJUNITTEST) echo Linking $@... $(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJUNITTEST) $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS) diff --git a/test/glut_test.cxx b/test/glut_test.cxx new file mode 100644 index 000000000..0a7facc86 --- /dev/null +++ b/test/glut_test.cxx @@ -0,0 +1,172 @@ +// +// GLUT test program for the Fast Light Tool Kit (FLTK). +// +// Provided by Brian Schack (STR #3458, see "big.cxx"). +// Copyright 2023 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +// Thanks to the original author Brian Schack for this test program. +// This program has been extended to test several GLUT functions with +// (1) a valid and (2) an invalid (destroyed) GLUT window. +// The test program opens two GLUT windows, runs the tests, prints +// diagnostics on stdout, and exits immediately. This is intended. + +// To compile (examples with different GLUT implementations) +// as of Apr 03, 2018 provided Brian Schack, slightly modified +// +// macOS GLUT: +// g++ -o glut_test glut_test.cxx -framework OpenGL -framework GLUT +// +// FreeGLUT (on macOS, with Macport's FreeGLUT): +// g++ -o glut_test glut_test.cxx -framework OpenGL -I/opt/local/include -L/opt/local/lib -lglut +// +// FLTK +// fltk-config --use-gl --compile glut_test.cxx + +// Enable one of the following two #include's depending on the GLUT implementation + +// #include // GLUT and FreeGLUT version +#include // FLTK version + +#include + +// Empty callback functions for testing. +void displayFunc() {} +void reshapeFunc(int w, int h) {} +void keyboardFunc(unsigned char key, int x, int y) {} +void mouseFunc(int b, int state, int x, int y) {} +void motionFunc(int x, int y) {} +void passiveMotionFunc(int x, int y) {} +void entryFunc(int s) {} +void visibilityFunc(int s) {} +void idleFunc() {} +void timerFunc(int value) {} +void menuStateFunc(int state) {} +void menuStatusFunc(int status, int x, int y) {} +void specialFunc(int key, int x, int y) {} +void overlayDisplayFunc() {} + +int main(int argc, char **argv) { + glutInit(&argc, argv); + + // Create 2 windows. + int win1 = glutCreateWindow("Window 1"); + int win2 = glutCreateWindow("Window 2"); + printf("Window 1 created, number = %d\n", win1); + printf("Window 2 created, number = %d\n", win2); + + // Run tests twice, with (1) a valid and (2) an invalid current window + + for (int i = 0; i < 2; i++) { + + // Find out which window is current. + int current = glutGetWindow(); + printf("Window %d is current\n", current); + + // Ask GLUT to redisplay things. + glutPostRedisplay(); + + // Set window title + glutSetWindowTitle((char *)"Non-existent"); + + // Set icon title + glutSetIconTitle((char *)"Non-existent"); + + // Position window + glutPositionWindow(10, 20); + + // Reshape window + glutReshapeWindow(100, 200); + + // Pop window + glutPopWindow(); + + // Iconify window + glutIconifyWindow(); + + // Show window + glutShowWindow(); + + // Hide window + glutHideWindow(); + + // Go to full screen mode + glutFullScreen(); + + // Set the cursor + glutSetCursor(GLUT_CURSOR_INFO); + + // Establish an overlay + glutEstablishOverlay(); + + // Remove overlay + glutRemoveOverlay(); + + // Choose a layer + glutUseLayer(GLUT_NORMAL); + glutUseLayer(GLUT_OVERLAY); + + // Post display on a layer + glutPostOverlayRedisplay(); + + // Show overlay + glutShowOverlay(); + + // Hide overlay + glutHideOverlay(); + + // Attach a menu + glutAttachMenu(0); + + // Detach a menu + glutDetachMenu(0); + + // Specify callbacks + glutDisplayFunc(displayFunc); + glutReshapeFunc(reshapeFunc); + glutKeyboardFunc(keyboardFunc); + glutMouseFunc(mouseFunc); + glutMotionFunc(motionFunc); + glutPassiveMotionFunc(passiveMotionFunc); + glutEntryFunc(entryFunc); + glutVisibilityFunc(visibilityFunc); + glutIdleFunc(idleFunc); + glutTimerFunc(1000, timerFunc, 42); + glutMenuStateFunc(menuStateFunc); + glutMenuStatusFunc(menuStatusFunc); + glutSpecialFunc(specialFunc); + glutOverlayDisplayFunc(overlayDisplayFunc); + + // Swap buffers + glutSwapBuffers(); + + // GLUT gets + printf("GLUT_WINDOW_X = %d\n", glutGet(GLUT_WINDOW_X)); + printf("GLUT_WINDOW_Y = %d\n", glutGet(GLUT_WINDOW_Y)); + printf("GLUT_WINDOW_WIDTH = %d\n", glutGet(GLUT_WINDOW_WIDTH)); + printf("GLUT_WINDOW_HEIGHT = %d\n", glutGet(GLUT_WINDOW_HEIGHT)); + printf("GLUT_WINDOW_PARENT = %d\n", glutGet(GLUT_WINDOW_PARENT)); + + // GLUT layer gets + printf("GLUT_OVERLAY_POSSIBLE = %d\n", glutLayerGet(GLUT_OVERLAY_POSSIBLE)); + printf("GLUT_NORMAL_DAMAGED = %d\n", glutLayerGet(GLUT_NORMAL_DAMAGED)); + + // Destroy the current window - this sets glut_window to NULL + printf("Destroy the current window (%d)\n\n", glutGetWindow()); + glutDestroyWindow(current); + + } // loop with current window + + printf("All tests done, exiting.\n"); + return 0; +}