diff --git a/freeglut/freeglut/CMakeLists.txt b/freeglut/freeglut/CMakeLists.txt index 28f8651..34873c1 100644 --- a/freeglut/freeglut/CMakeLists.txt +++ b/freeglut/freeglut/CMakeLists.txt @@ -52,8 +52,10 @@ ENDIF() # OpenGL ES support OPTION(FREEGLUT_GLES "Use OpenGL ES (requires EGL)" OFF) -# option to build either as "glut" (ON) or "freeglut" (OFF) IF(NOT WIN32) + # Wayland support + OPTION(FREEGLUT_WAYLAND "Use Wayland (no X11)" OFF) + # option to build either as "glut" (ON) or "freeglut" (OFF) OPTION(FREEGLUT_REPLACE_GLUT "Be a replacement for GLUT" ON) ENDIF() @@ -167,36 +169,60 @@ ELSEIF(ANDROID OR BLACKBERRY) src/blackberry/fg_window_blackberry.c ) ENDIF() + ELSE() - LIST(APPEND FREEGLUT_SRCS - src/x11/fg_cursor_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 - ) - IF(NOT(FREEGLUT_GLES)) + # UNIX (Wayland) + IF(FREEGLUT_WAYLAND) LIST(APPEND FREEGLUT_SRCS - src/x11/fg_internal_x11_glx.h - src/x11/fg_display_x11_glx.c - src/x11/fg_state_x11_glx.c - src/x11/fg_state_x11_glx.h - src/x11/fg_window_x11_glx.c - src/x11/fg_window_x11_glx.h + src/wayland/fg_cursor_wl.c + src/wayland/fg_ext_wl.c + src/wayland/fg_gamemode_wl.c + src/wayland/fg_init_wl.c + src/wayland/fg_internal_wl.h + src/wayland/fg_input_devices_wl.c + src/wayland/fg_main_wl.c + src/wayland/fg_state_wl.c + src/wayland/fg_structure_wl.c + src/wayland/fg_window_wl.c + # font, serial port & joystick code are agnostic + src/x11/fg_glutfont_definitions_x11.c + src/x11/fg_input_devices_x11.c + src/x11/fg_joystick_x11.c ) + # UNIX (X11) + ELSE() + LIST(APPEND FREEGLUT_SRCS + src/x11/fg_cursor_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 + ) + IF(NOT(FREEGLUT_GLES)) + LIST(APPEND FREEGLUT_SRCS + src/x11/fg_internal_x11_glx.h + src/x11/fg_display_x11_glx.c + src/x11/fg_state_x11_glx.c + src/x11/fg_state_x11_glx.h + src/x11/fg_window_x11_glx.c + src/x11/fg_window_x11_glx.h + ) + ENDIF() ENDIF() ENDIF() -IF(FREEGLUT_GLES) + +# OpenGL ES requires EGL, and so does Wayland +IF(FREEGLUT_GLES OR FREEGLUT_WAYLAND) LIST(APPEND FREEGLUT_SRCS src/egl/fg_internal_egl.h src/egl/fg_display_egl.c @@ -226,6 +252,12 @@ ELSE() INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}) ENDIF() +# For Wayland: compile with -DFREEGLUT_WAYLAND and pull EGL +IF(FREEGLUT_WAYLAND) + ADD_DEFINITIONS(-DFREEGLUT_WAYLAND) + LIST(APPEND LIBS wayland-client wayland-cursor wayland-egl EGL xkbcommon) +ENDIF() + # lib m for math, not needed on windows IF (NOT WIN32) # For compilation: @@ -248,14 +280,14 @@ ENDIF() IF(CMAKE_COMPILER_IS_GNUCC) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") - IF(NOT(ANDROID OR BLACKBERRY)) + IF(NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND)) # not setting -ansi as EGL/KHR headers doesn't support it SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic") ENDIF() ENDIF(CMAKE_COMPILER_IS_GNUCC) INCLUDE(CheckIncludeFiles) -IF(UNIX AND NOT(ANDROID OR BLACKBERRY)) +IF(UNIX AND NOT(ANDROID OR BLACKBERRY OR FREEGLUT_WAYLAND)) FIND_PACKAGE(X11 REQUIRED) INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR}) LIST(APPEND LIBS ${X11_LIBRARIES}) @@ -506,11 +538,17 @@ ELSEIF(FREEGLUT_GLES) ELSE() SET(PC_LIBS_PRIVATE "-lbps -lslog2 -lscreen -lGLESv2 -lGLESv1_CM -lEGL -lm") ENDIF() + ELSEIF(FREEGLUT_WAYLAND) + SET(PC_LIBS_PRIVATE "-lwayland-client -lwayland-cursor -lwayland-egl -lGLESv2 -lGLESv1_CM -lEGL -lxkbcommon -lm") ELSE() SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGLESv2 -lGLESv1_CM -lEGL -lm") ENDIF() ELSE() - SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGL -lm") + IF(FREEGLUT_WAYLAND) + SET(PC_LIBS_PRIVATE "-lwayland-client -lwayland-cursor -lwayland-egl -lGL -lxkbcommon -lm") + ELSE() + SET(PC_LIBS_PRIVATE "-lX11 -lXxf86vm -lXrandr -lGL -lm") + ENDIF() ENDIF() # Client applications need to define FreeGLUT GLES version to # bootstrap headers inclusion in freeglut_std.h: diff --git a/freeglut/freeglut/src/egl/fg_init_egl.c b/freeglut/freeglut/src/egl/fg_init_egl.c index f0889a6..3c83fb2 100644 --- a/freeglut/freeglut/src/egl/fg_init_egl.c +++ b/freeglut/freeglut/src/egl/fg_init_egl.c @@ -34,8 +34,13 @@ void fghPlatformInitializeEGL() { /* CreateDisplay */ /* Using EGL_DEFAULT_DISPLAY, or a specific native display */ +#ifdef FREEGLUT_WAYLAND + fgDisplay.pDisplay.egl.Display = eglGetDisplay( + (EGLNativeDisplayType)fgDisplay.pDisplay.display); +#else EGLNativeDisplayType nativeDisplay = EGL_DEFAULT_DISPLAY; fgDisplay.pDisplay.egl.Display = eglGetDisplay(nativeDisplay); +#endif FREEGLUT_INTERNAL_ERROR_EXIT(fgDisplay.pDisplay.egl.Display != EGL_NO_DISPLAY, "No display available", "fgPlatformInitialize"); diff --git a/freeglut/freeglut/src/fg_internal.h b/freeglut/freeglut/src/fg_internal.h index 3f0dc42..8006196 100644 --- a/freeglut/freeglut/src/fg_internal.h +++ b/freeglut/freeglut/src/fg_internal.h @@ -51,7 +51,11 @@ # define TARGET_HOST_BLACKBERRY 1 #elif defined(__posix__) || defined(__unix__) || defined(__linux__) || defined(__sun) -# define TARGET_HOST_POSIX_X11 1 +# if defined(FREEGLUT_WAYLAND) +# define TARGET_HOST_POSIX_WAYLAND 1 +# else +# define TARGET_HOST_POSIX_X11 1 +# endif #elif defined(__APPLE__) /* This is a placeholder until we get native OSX support ironed out -- JFF 11/18/09 */ @@ -70,32 +74,36 @@ #endif #ifndef TARGET_HOST_MS_WINDOWS -# define TARGET_HOST_MS_WINDOWS 0 +# define TARGET_HOST_MS_WINDOWS 0 #endif #ifndef TARGET_HOST_ANDROID -# define TARGET_HOST_ANDROID 0 +# define TARGET_HOST_ANDROID 0 #endif #ifndef TARGET_HOST_BLACKBERRY -# define TARGET_HOST_BLACKBERRY 0 +# define TARGET_HOST_BLACKBERRY 0 +#endif + +#ifndef TARGET_HOST_POSIX_WAYLAND +# define TARGET_HOST_POSIX_WAYLAND 0 #endif #ifndef TARGET_HOST_POSIX_X11 -# define TARGET_HOST_POSIX_X11 0 +# define TARGET_HOST_POSIX_X11 0 #endif #ifndef TARGET_HOST_MAC_OSX -# define TARGET_HOST_MAC_OSX 0 +# define TARGET_HOST_MAC_OSX 0 #endif #ifndef TARGET_HOST_SOLARIS -# define TARGET_HOST_SOLARIS 0 +# define TARGET_HOST_SOLARIS 0 #endif /* -- FIXED CONFIGURATION LIMITS ------------------------------------------- */ -#define FREEGLUT_MAX_MENUS 3 +#define FREEGLUT_MAX_MENUS 3 /* These files should be available on every platform. */ #include @@ -188,6 +196,9 @@ #endif /* Platform-specific includes */ +#if TARGET_HOST_POSIX_WAYLAND +#include "wayland/fg_internal_wl.h" +#endif #if TARGET_HOST_POSIX_X11 #include "x11/fg_internal_x11.h" #endif diff --git a/freeglut/freeglut/src/wayland/fg_cursor_wl.c b/freeglut/freeglut/src/wayland/fg_cursor_wl.c new file mode 100644 index 0000000..0543bcc --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_cursor_wl.c @@ -0,0 +1,137 @@ +/* + * fg_cursor_wl.c + * + * The Wayland-specific mouse cursor related stuff. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Thur Mar 19, 2015 + * + * 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 + * MANUEL BACHMANN 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 +#include "../fg_internal.h" + +/* + * Note: The arrangement of the table below depends on the fact that + * the "normal" GLUT_CURSOR_* values start a 0 and are consecutive. + */ +static char* cursorList[] = { + "UNSUPPORTED", /* GLUT_CURSOR_RIGHT_ARROW */ + "left_ptr", /* GLUT_CURSOR_LEFT_ARROW */ + "hand1", /* GLUT_CURSOR_INFO */ + "UNSUPPORTED", /* GLUT_CURSOR_DESTROY */ + "UNSUPPORTED", /* GLUT_CURSOR_HELP */ + "UNSUPPORTED", /* GLUT_CURSOR_CYCLE */ + "UNSUPPORTED", /* GLUT_CURSOR_SPRAY */ + "watch", /* GLUT_CURSOR_WAIT */ + "xterm", /* GLUT_CURSOR_TEXT */ + "grabbing", /* GLUT_CURSOR_CROSSHAIR */ + "UNSUPPORTED", /* GLUT_CURSOR_UP_DOWN */ + "UNSUPPORTED", /* GLUT_CURSOR_LEFT_RIGHT */ + "top_side", /* GLUT_CURSOR_TOP_SIDE */ + "bottom_side", /* GLUT_CURSOR_BOTTOM_SIDE */ + "left_side", /* GLUT_CURSOR_LEFT_SIDE */ + "right_side", /* GLUT_CURSOR_RIGHT_SIDE */ + "top_left_corner", /* GLUT_CURSOR_TOP_LEFT_CORNER */ + "top_right_corner", /* GLUT_CURSOR_TOP_RIGHT_CORNER */ + "bottom_right_corner", /* GLUT_CURSOR_BOTTOM_RIGHT_CORNER */ + "bottom_left_corner" /* GLUT_CURSOR_BOTTOM_LEFT_CORNER */ +}; + +void fgPlatformSetCursor ( SFG_Window *window, int cursorID ) +{ + /* + * 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; + + char* cursor; + + if( ( cursorIDToUse >= 0 ) && + ( cursorIDToUse < sizeof( cursorList ) / sizeof( cursorList[0] ) ) ) { + + cursor = cursorList[cursorIDToUse]; + + /* if the type is UNSUPPORTED, fall back to GLUT_CURSOR_LEFT_ARROW */ + if ( ! strcmp( cursor, "UNSUPPORTED" ) ) + { + fgWarning( "glutSetCursor(): cursor type unsupported under Wayland : %d", + cursorIDToUse ); + cursor = "left_ptr"; + } + } else { + switch( cursorIDToUse ) + { + case GLUT_CURSOR_NONE: + case GLUT_CURSOR_INHERIT: + cursor = NULL; + break; + + default: + fgError( "Unknown cursor type: %d", cursorIDToUse ); + return; + } + } + + if ( cursorIDToUse == GLUT_CURSOR_INHERIT ) { + if( window->Parent ) + window->Window.pContext.cursor = + window->Parent->Window.pContext.cursor; + } else { + window->Window.pContext.cursor = wl_cursor_theme_get_cursor( + fgDisplay.pDisplay.cursor_theme, + cursor ); + if ( ! window->Window.pContext.cursor ) + fgError( "Failed to create cursor" ); + } +} + + +void fgPlatformWarpPointer ( int x, int y ) +{ + /* unsupported under Wayland */ + fgWarning( "glutWarpPointer(): function unsupported under Wayland" ); +} + +void fghPlatformGetCursorPos(const SFG_Window *window, GLboolean client, SFG_XYUse *mouse_pos) +{ + /* Get current pointer location relative to top-left of client area of window (if client is true and window is not NULL) + * We cannot get current pointer location in screen coordinates under Wayland, so inform the user and return -1 is this case + */ + + if (client && window) + { + mouse_pos->X = window->State.MouseX; + mouse_pos->Y = window->State.MouseY; + } + else + { + fgWarning( "glutGetCursorPos(): cannot get screen position under Wayland" ); + mouse_pos->X = -1; + mouse_pos->Y = -1; + } + + mouse_pos->Use = GL_TRUE; +} + diff --git a/freeglut/freeglut/src/wayland/fg_ext_wl.c b/freeglut/freeglut/src/wayland/fg_ext_wl.c new file mode 100644 index 0000000..f32f325 --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_ext_wl.c @@ -0,0 +1,49 @@ +/* + * fg_ext_wl.c + * + * Wayland-specific functions related to OpenGL extensions. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Wed Mar 25 2015 + * + * 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 + * MANUEL BACHMANN 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 +#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; +} + diff --git a/freeglut/freeglut/src/wayland/fg_gamemode_wl.c b/freeglut/freeglut/src/wayland/fg_gamemode_wl.c new file mode 100644 index 0000000..293cf03 --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_gamemode_wl.c @@ -0,0 +1,161 @@ +/* + * fg_gamemode_wl.c + * + * The game mode handling code. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Sun Mar 23 2015 + * + * 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 + * MANUEL BACHMANN 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" + +/* Pointer locking is a Weston-specific WIP protocol (for now) + * + * #include "pointer-lock-client-protocol.h" + * #include "relative-pointer-client-protocol.h" + * + * static struct _wl_relative_pointer_manager* relative_pointer_manager; + * static struct _wl_pointer_lock* pointer_lock; + * + * static struct _wl_relative_pointer* relative_pointer; + * static struct _wl_locked_pointer* locked_pointer; + * + * + * static void fghRelativeMotion( void* data, struct _wl_relative_pointer + * pointer, uint32_t time, + * wl_fixed_t x_w, wl_fixed_t y_w, + * wl_fixed_t x_noacc, wl_fixed_t y_noacc ) + * { + * SFG_Window* win = fgStructure.CurrentWindow; + * win->State.MouseX = wl_fixed_to_int( x_w ); + * win->State.MouseY = wl_fixed_to_int( y_w ); + * INVOKE_WCB( *win, Passive, ( win->State.MouseX, + * win->State.MouseY ) ); + * } + * static const struct _wl_relative_pointer_listener + * fghRelativeListener = + * { + * fghRelativeMotion + * }; + * + * static void fghLockedLocked( void* data, struct _wl_locked_pointer + * pointer, uint32_t serial ) + * { + * fgPlatformRememberState(); + * fgPlatformSetCursor( win, GLUT_CURSOR_NONE ): + * } + * static void fghLockedUnlocked( void* data, struct _wl_locked_pointer + * pointer ) + * { + * fgPlatformRestoreState(); + * } + * static const struct _wl_locked_pointer_listener + * fghLockedListener = + * { + * fghLockedLocked, + * fghLockedUnlocked + * }; + */ + + +static struct wl_cursor* saved_cursor; + +/* + * Remembers the current visual settings, so that + * we can change them and restore later... + */ +void fgPlatformRememberState( void ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + saved_cursor = win->Window.pContext.cursor; +} + +/* + * Restores the previously remembered visual settings + */ +void fgPlatformRestoreState( void ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->Window.pContext.cursor = saved_cursor; +} + +/* + * * Private function to get the virtual maximum screen extent + * */ +GLvoid fgPlatformGetGameModeVMaxExtent( SFG_Window* window, int* x, int* y ) +{ + /* + * under Wayland, just return the size of the window, + * at least until we start messing with the outputs... + */ + *x = window->State.Width; + *y = window->State.Height; +} + +/* + * Changes the current display mode to match user's settings + */ +GLboolean fgPlatformChangeDisplayMode( GLboolean haveToTest ) +{ + /* Such a protocol is being studied in Wayland */ + return GL_FALSE; +} + + +void fgPlatformEnterGameMode( void ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + struct wl_region* region; + + region = wl_compositor_create_region ( + fgDisplay.pDisplay.compositor ); + wl_region_add( region, 0, 0, + win->State.Width, + win->State.Height ); + /* + * relative_pointer = + * _wl_relative_pointer_manager_get_relative_pointer ( + * relative_pointer_manager, + * fgDisplay.pDisplay.seat ); + * _wl_relative_pointer_add_listener( relative_pointer, + * &fghRelativeListener, + * NULL ); + * locked_pointer = _wl_pointer_lock_lock_pointer ( + * pointer_lock, + * win->Window.pContext.surface, + * fgDisplay.pDisplay.seat, + * NULL); + * _wl_locked_pointer_add_listener( locked_pointer, + * &fghLockedListener, + * NULL ); + */ + wl_region_destroy( region ); +} + +void fgPlatformLeaveGameMode( void ) +{ + /* + * _wl_locked_pointer_destroy( locked_pointer ); + * _wl_relative_pointer_release( relative_pointer ); + */ +} + diff --git a/freeglut/freeglut/src/wayland/fg_init_wl.c b/freeglut/freeglut/src/wayland/fg_init_wl.c new file mode 100644 index 0000000..7b7cd6a --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_init_wl.c @@ -0,0 +1,134 @@ +/* + * fg_init_wl.c + * + * Various freeglut Wayland initialization functions. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * 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 + * MANUEL BACHMANN 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 +#include "fg_internal.h" +#include "egl/fg_init_egl.h" + +void fgPlatformInitialiseInputDevices( void ); +void fgPlatformCloseInputDevices( void ); + + +static void fghRegistryGlobal( void* data, + struct wl_registry* registry, + uint32_t id, + const char* interface, + uint32_t version ) +{ + SFG_PlatformDisplay* pDisplay = data; + + if ( ! strcmp( interface, "wl_compositor" ) ) + pDisplay->compositor = wl_registry_bind ( registry, id, + &wl_compositor_interface, 1 ); + else if ( ! strcmp( interface, "wl_shell" ) ) + pDisplay->shell = wl_registry_bind ( registry, id, + &wl_shell_interface, 1 ); + else if ( ! strcmp( interface, "wl_seat" ) ) + pDisplay->seat = wl_registry_bind ( registry, id, + &wl_seat_interface, 1 ); + else if ( ! strcmp( interface, "wl_shm" ) ) + pDisplay->shm = wl_registry_bind ( registry, id, + &wl_shm_interface, 1 ); +} +static void fghRegistryGlobalRemove( void* data, + struct wl_registry* registry, + uint32_t id ) +{ +} +static const struct wl_registry_listener fghRegistryListener = +{ + fghRegistryGlobal, + fghRegistryGlobalRemove +}; + + +static void fghInitialiseCursorTheme(void) +{ + fgDisplay.pDisplay.cursor_theme = wl_cursor_theme_load ( + "default", 32, + fgDisplay.pDisplay.shm ); +}; + +void fgPlatformInitialize( const char* displayName ) +{ + fgDisplay.pDisplay.display = wl_display_connect( NULL ); + + if( fgDisplay.pDisplay.display == NULL ) + fgError( "failed to connect to a Wayland compositor" ); + + fgDisplay.pDisplay.registry = wl_display_get_registry( + fgDisplay.pDisplay.display ); + wl_registry_add_listener( fgDisplay.pDisplay.registry, + &fghRegistryListener, + &fgDisplay.pDisplay ); + wl_display_roundtrip( fgDisplay.pDisplay.display ); + + if( fgDisplay.pDisplay.compositor == NULL || + fgDisplay.pDisplay.shell == NULL || + fgDisplay.pDisplay.seat == NULL || + fgDisplay.pDisplay.shm == NULL ) + fgError( "failed to discover all needed compositor interfaces" ); + + fghInitialiseCursorTheme(); + + fghPlatformInitializeEGL(); + + /* Get start time */ + fgState.Time = fgSystemTime(); + + fgState.Initialised = GL_TRUE; + + atexit(fgDeinitialize); + + /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */ + fgPlatformInitialiseInputDevices(); +} + + +void fgPlatformDeinitialiseInputDevices ( void ) +{ + fgPlatformCloseInputDevices(); + + fgState.InputDevsInitialised = GL_FALSE; +} + + +void fgPlatformCloseDisplay ( void ) +{ + wl_cursor_theme_destroy( fgDisplay.pDisplay.cursor_theme ); + + wl_shm_destroy( fgDisplay.pDisplay.shm ); + wl_seat_destroy( fgDisplay.pDisplay.seat ); + wl_shell_destroy( fgDisplay.pDisplay.shell ); + wl_compositor_destroy( fgDisplay.pDisplay.compositor ); + wl_registry_destroy( fgDisplay.pDisplay.registry ); + + wl_display_disconnect( fgDisplay.pDisplay.display ); +} + diff --git a/freeglut/freeglut/src/wayland/fg_input_devices_wl.c b/freeglut/freeglut/src/wayland/fg_input_devices_wl.c new file mode 100644 index 0000000..0aaa91e --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_input_devices_wl.c @@ -0,0 +1,433 @@ +/* + * fg_input_devices_wl.c + * + * Handles Wayland input devices : keyboard, pointer, touchscreen. + * + * Written by Manuel Bachmann 2015 + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Creation date: Thur Mar 19 2015 + * + * 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 + * MANUEL BACHMANN 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 __linux__ +#include +#else +#define BTN_LEFT 0x110 +#define BTN_RIGHT 0x111 +#define BTN_MIDDLE 0x112 +#endif +#include +#include +#include "../fg_internal.h" + +/* + * This function will effectively set the pointer (mouse) cursor + * depending on the GLUT_CURSOR_* choice. + */ +void fghPointerSetCursor( SFG_Window* window, + struct wl_pointer* pointer, + uint32_t serial ) +{ + struct wl_cursor_image* image; + struct wl_buffer* buffer; + + image = window->Window.pContext.cursor->images[0]; + buffer = wl_cursor_image_get_buffer( image ); + + wl_surface_attach( window->Window.pContext.cursor_surface, buffer, + 0, 0 ); + wl_surface_damage( window->Window.pContext.cursor_surface, 0, 0, + image->width, image->height ); + wl_surface_commit( window->Window.pContext.cursor_surface ); + + wl_pointer_set_cursor( pointer, serial, + window->Window.pContext.cursor_surface, + image->hotspot_x, image->hotspot_y ); +} + +/* + * This function will interpret a keyboard keysym, and call the + * possible callbacks accordingly. + */ +void fghKeyboardInterpretKeysym( SFG_Window* window, + uint32_t key, + xkb_keysym_t sym, + uint32_t state ) +{ + FGCBKeyboard keyboard_cb; + FGCBSpecial special_cb; + char string[16]; + int special = -1; + + /* GLUT API tells us to have two separate callbacks, one for + * the ASCII translateable keypresses, and one for all the + * others, which need to be translated to GLUT_KEY_Xs... */ + if( state ) + { + 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 )); + } + + switch( sym ) + { + case XKB_KEY_F1: special = GLUT_KEY_F1; break; + case XKB_KEY_F2: special = GLUT_KEY_F2; break; + case XKB_KEY_F3: special = GLUT_KEY_F3; break; + case XKB_KEY_F4: special = GLUT_KEY_F4; break; + case XKB_KEY_F5: special = GLUT_KEY_F5; break; + case XKB_KEY_F6: special = GLUT_KEY_F6; break; + case XKB_KEY_F7: special = GLUT_KEY_F7; break; + case XKB_KEY_F8: special = GLUT_KEY_F8; break; + case XKB_KEY_F9: special = GLUT_KEY_F9; break; + case XKB_KEY_F10: special = GLUT_KEY_F10; break; + case XKB_KEY_F11: special = GLUT_KEY_F11; break; + case XKB_KEY_F12: special = GLUT_KEY_F12; break; + case XKB_KEY_Left: special = GLUT_KEY_LEFT; break; + case XKB_KEY_Right: special = GLUT_KEY_RIGHT; break; + case XKB_KEY_Up: special = GLUT_KEY_UP; break; + case XKB_KEY_Down: special = GLUT_KEY_DOWN; break; + case XKB_KEY_Page_Up: special = GLUT_KEY_PAGE_UP; break; + case XKB_KEY_Page_Down: special = GLUT_KEY_PAGE_DOWN; break; + case XKB_KEY_Home: special = GLUT_KEY_HOME; break; + case XKB_KEY_End: special = GLUT_KEY_END; break; + case XKB_KEY_Insert: special = GLUT_KEY_INSERT; break; + case XKB_KEY_Num_Lock: special = GLUT_KEY_NUM_LOCK; break; + case XKB_KEY_Begin: special = GLUT_KEY_BEGIN; break; + case XKB_KEY_Delete: special = GLUT_KEY_DELETE; break; + case XKB_KEY_Shift_L: special = GLUT_KEY_SHIFT_L; break; + case XKB_KEY_Shift_R: special = GLUT_KEY_SHIFT_R; break; + case XKB_KEY_Control_L: special = GLUT_KEY_CTRL_L; break; + case XKB_KEY_Control_R: special = GLUT_KEY_CTRL_R; break; + case XKB_KEY_Alt_L: special = GLUT_KEY_ALT_L; break; + case XKB_KEY_Alt_R: special = GLUT_KEY_ALT_R; break; + } + + if( special_cb && (special != -1) ) + { + fgSetWindow( window ); + special_cb( special, window->State.MouseX, window->State.MouseY ); + } + else if( keyboard_cb && (special == -1) ) + { + fgSetWindow( window ); + xkb_keysym_to_utf8( sym, string, sizeof( string ) ); + keyboard_cb( string[0], window->State.MouseX, window->State.MouseY ); + } +} + + +/* + * Touchscreen section + * For now, let us pretend it is a mouse with only one button + */ +static void fghTouchDown( void* data, struct wl_touch* touch, + uint32_t serial, uint32_t time, + struct wl_surface* surface, + int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + INVOKE_WCB( *win, Mouse, ( GLUT_LEFT_BUTTON, + GLUT_DOWN, + win->State.MouseX, + win->State.MouseY ) ); +} +static void fghTouchUp( void* data, struct wl_touch* touch, + uint32_t serial, uint32_t time, + int32_t id ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Mouse, ( GLUT_LEFT_BUTTON, + GLUT_UP, + win->State.MouseX, + win->State.MouseY ) ); +} +static void fghTouchMotion( void* data, struct wl_touch* touch, + uint32_t time, int32_t id, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + INVOKE_WCB( *win, Motion, ( win->State.MouseX, + win->State.MouseY ) ); +} +static void fghTouchFrame( void* data, struct wl_touch* touch ) +{ +} +static void fghTouchCancel( void* data, struct wl_touch* touch ) +{ +} +static const struct wl_touch_listener fghTouchListener = +{ + fghTouchDown, + fghTouchUp, + fghTouchMotion, + fghTouchFrame, + fghTouchCancel +}; + + +/* + * Pointer (mouse) section + */ +static void fghPointerEnter( void* data, struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + fghPointerSetCursor( win, pointer, serial ); + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + INVOKE_WCB( *win, Entry, ( GLUT_ENTERED ) ); +} +static void fghPointerLeave( void* data, struct wl_pointer* pointer, + uint32_t serial, + struct wl_surface* surface ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Entry, ( GLUT_LEFT ) ); +} +static void fghPointerMotion( void* data, struct wl_pointer* pointer, + uint32_t time, + wl_fixed_t x_w, wl_fixed_t y_w ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + win->State.MouseX = wl_fixed_to_int( x_w ); + win->State.MouseY = wl_fixed_to_int( y_w ); + + if ( win->Window.pContext.pointer_button_pressed ) + INVOKE_WCB( *win, Motion, ( win->State.MouseX, + win->State.MouseY ) ); + else + INVOKE_WCB( *win, Passive, ( win->State.MouseX, + win->State.MouseY ) ); +} +static void fghPointerButton( void* data, struct wl_pointer* pointer, + uint32_t serial, uint32_t time, + uint32_t button, uint32_t state ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + int button_f; + + switch( button ) + { + case BTN_LEFT: + button_f = GLUT_LEFT_BUTTON; + break; + case BTN_RIGHT: + button_f = GLUT_RIGHT_BUTTON; + break; + case BTN_MIDDLE: + button_f = GLUT_MIDDLE_BUTTON; + break; + } + + win->Window.pContext.pointer_button_pressed = + state ? GL_TRUE : GL_FALSE; + + INVOKE_WCB( *win, Mouse, ( button_f, + state ? GLUT_DOWN : GLUT_UP , + win->State.MouseX, + win->State.MouseY ) ); +} +static void fghPointerAxis( void* data, struct wl_pointer* pointer, + uint32_t time, uint32_t axis, + wl_fixed_t value ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + int direction = wl_fixed_to_int( value ); + + INVOKE_WCB( *win, MouseWheel, ( 0, + direction , + win->State.MouseX, + win->State.MouseY ) ); +} +static const struct wl_pointer_listener fghPointerListener = +{ + fghPointerEnter, + fghPointerLeave, + fghPointerMotion, + fghPointerButton, + fghPointerAxis +}; + + +/* + * Keyboard section + */ +static void fghKeyboardKeymap( void* data, struct wl_keyboard* keyboard, + uint32_t format, int fd, uint32_t size ) +{ + SFG_PlatformDisplay* pDisplay = data; + char* keymap_str; + struct xkb_keymap* keymap; + + keymap_str = mmap( NULL, size, PROT_READ, MAP_SHARED, fd, 0 ); + keymap = xkb_keymap_new_from_string( pDisplay->xkb_context, + keymap_str, + XKB_KEYMAP_FORMAT_TEXT_V1, + 0 ); + munmap( keymap_str, size ); + + if( pDisplay->xkb_state ) + xkb_state_unref( pDisplay->xkb_state ); + pDisplay->xkb_state = xkb_state_new( keymap ); +} +static void fghKeyboardEnter( void* data, struct wl_keyboard* keyboard, + uint32_t serial, struct wl_surface* surface, + struct wl_array* keys ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Entry, ( GLUT_ENTERED ) ); +} +static void fghKeyboardLeave( void* data, struct wl_keyboard* keyboard, + uint32_t serial, struct wl_surface* surface ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + INVOKE_WCB( *win, Entry, ( GLUT_LEFT ) ); +} +static void fghKeyboardKey( void* data, struct wl_keyboard* keyboard, + uint32_t serial, uint32_t time, + uint32_t key, uint32_t state ) +{ + SFG_PlatformDisplay* pDisplay = data; + SFG_Window* win = fgStructure.CurrentWindow; + const xkb_keysym_t* syms; + + xkb_state_key_get_syms( pDisplay->xkb_state, + key + 8, &syms ); + fghKeyboardInterpretKeysym( win, key, syms[0], state ); +} +static void fghKeyboardModifiers( void* data, struct wl_keyboard* keyboard, + uint32_t serial, uint32_t mods_depr, + uint32_t mods_latch, uint32_t mods_lock, + uint32_t group ) +{ +} +static const struct wl_keyboard_listener fghKeyboardListener = +{ + fghKeyboardKeymap, + fghKeyboardEnter, + fghKeyboardLeave, + fghKeyboardKey, + fghKeyboardModifiers +}; + + +/* + * Discover potential input device(s) (keyboard, pointer, touch) + */ +static void fghSeatCapabilities( void* data, + struct wl_seat* seat, + enum wl_seat_capability capabilities ) +{ + SFG_PlatformDisplay* pDisplay = data; + + if( capabilities & WL_SEAT_CAPABILITY_KEYBOARD ) + { + pDisplay->xkb_context = xkb_context_new ( 0 ); + pDisplay->keyboard = wl_seat_get_keyboard( seat ); + wl_keyboard_add_listener( pDisplay->keyboard, + &fghKeyboardListener, + pDisplay ); + } + + if( capabilities & WL_SEAT_CAPABILITY_POINTER ) + { + pDisplay->pointer = wl_seat_get_pointer( seat ); + wl_pointer_add_listener( pDisplay->pointer, + &fghPointerListener, + pDisplay ); + } + + if( capabilities & WL_SEAT_CAPABILITY_TOUCH ) + { + pDisplay->touch = wl_seat_get_touch( seat ); + wl_touch_add_listener( pDisplay->touch, + &fghTouchListener, + pDisplay ); + } +} +static const struct wl_seat_listener fghSeatListener = +{ + fghSeatCapabilities +}; + + +/* + * Try initializing the input device(s) + */ +void fgPlatformInitialiseInputDevices( void ) +{ + wl_seat_add_listener( fgDisplay.pDisplay.seat, + &fghSeatListener, + &fgDisplay.pDisplay ); + + wl_display_roundtrip( fgDisplay.pDisplay.display ); +} + +/* + * Try closing the input device(s) + */ +void fgPlatformCloseInputDevices( void ) +{ + if( fgDisplay.pDisplay.touch ) + wl_touch_destroy( fgDisplay.pDisplay.touch ); + if( fgDisplay.pDisplay.pointer ) + wl_pointer_destroy( fgDisplay.pDisplay.pointer ); + if( fgDisplay.pDisplay.keyboard ) + wl_keyboard_destroy( fgDisplay.pDisplay.keyboard ); + if( fgDisplay.pDisplay.xkb_state ) + xkb_state_unref( fgDisplay.pDisplay.xkb_state ); + if( fgDisplay.pDisplay.xkb_context ) + xkb_context_unref( fgDisplay.pDisplay.xkb_context ); +} + + +/* + * Wayland backend will not be implementing spaceball at all + */ +void fgPlatformInitializeSpaceball( void ) +{ +} +void fgPlatformSpaceballClose( void ) +{ +} +void fgPlatformSpaceballSetWindow( SFG_Window *window ) +{ +} +int fgPlatformHasSpaceball( void ) +{ + return 0; +} +int fgPlatformSpaceballNumButtons( void ) +{ + return 0; +} + diff --git a/freeglut/freeglut/src/wayland/fg_internal_wl.h b/freeglut/freeglut/src/wayland/fg_internal_wl.h new file mode 100644 index 0000000..81bd5bc --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_internal_wl.h @@ -0,0 +1,186 @@ +/* + * fg_internal_wl.h + * + * The freeglut library private include file. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * 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 + * MANUEL BACHMANN 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_WL_H +#define FREEGLUT_INTERNAL_WL_H + + +/* -- PLATFORM-SPECIFIC INCLUDES ------------------------------------------- */ +#include "egl/fg_internal_egl.h" +#include +#include +#include +#include + + +/* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ +/* The structure used by display initialization in fg_init.c */ +typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct tagSFG_PlatformDisplay +{ + struct tagSFG_PlatformDisplayEGL egl; + + struct wl_display* display; /* The display we are being run in */ + struct wl_registry* registry; /* The global interface registry */ + struct wl_compositor* compositor; /* The compositor */ + struct wl_shell* shell; /* The shell, AKA window manager */ + struct wl_seat* seat; /* The seat, references input devices */ + + struct xkb_context* xkb_context; /* The global XKB keyboard context */ + struct xkb_state* xkb_state; /* The current XKB keyboard state */ + struct wl_keyboard* keyboard; /* The keyboard input device */ + struct wl_pointer* pointer; /* The pointer input device (mouse) */ + struct wl_touch* touch; /* The touchscreen input device */ + + struct wl_shm* shm; /* The software rendering engine */ + struct wl_cursor_theme* cursor_theme; /* The pointer cursor theme */ +}; + + +/* The structure used by window creation in fg_window.c */ +typedef struct tagSFG_PlatformContext SFG_PlatformContext; +struct tagSFG_PlatformContext +{ + struct tagSFG_PlatformContextEGL egl; + GLboolean pointer_button_pressed; + + struct wl_surface* surface; /* The drawing surface */ + struct wl_shell_surface* shsurface; /* The shell surface, has states */ + struct wl_egl_window* egl_window; /* Binding between WL/EGL surfaces */ + + struct wl_cursor* cursor; /* The active cursor */ + struct wl_surface* cursor_surface; /* The active cursor surface */ +}; + + +/* The window 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 "fg_joystick.c" + * interspersed + */ +# ifdef HAVE_SYS_IOCTL_H +# include +# endif +# ifdef HAVE_FCNTL_H +# include +# endif + +#include +#include + +# 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} + + +#endif /* FREEGLUT_INTERNAL_WL_H */ diff --git a/freeglut/freeglut/src/wayland/fg_main_wl.c b/freeglut/freeglut/src/wayland/fg_main_wl.c new file mode 100644 index 0000000..f289c17 --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_main_wl.c @@ -0,0 +1,134 @@ +/* + * fg_main_wl.c + * + * The Wayland-specific windows message processing methods. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Sun Mar 22 2015 + * + * 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 + * MANUEL BACHMANN 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 + +void fgPlatformFullScreenToggle( SFG_Window *win ); +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ); +void fgPlatformReshapeWindow( SFG_Window *window, int width, int height ); +void fgPlatformPushWindow( SFG_Window *window ); +void fgPlatformPopWindow( SFG_Window *window ); +void fgPlatformHideWindow( SFG_Window *window ); +void fgPlatformIconifyWindow( SFG_Window *window ); +void fgPlatformShowWindow( SFG_Window *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 +} + +void fgPlatformSleepForEvents( fg_time_t msec ) +{ + struct pollfd pfd; + int err; + + pfd.fd = wl_display_get_fd( fgDisplay.pDisplay.display ); + pfd.events = POLLIN | POLLERR | POLLHUP; + + wl_display_dispatch_pending( fgDisplay.pDisplay.display ); + if ( ! wl_display_flush( fgDisplay.pDisplay.display ) ) + { + err = poll( &pfd, 1, msec ); + + if( ( -1 == err ) && ( errno != EINTR ) ) + fgWarning ( "freeglut poll() error: %d", errno ); + } +} + + +void fgPlatformProcessSingleEvent( void ) +{ + SFG_Window *win = fgStructure.CurrentWindow; + + wl_display_dispatch_pending( fgDisplay.pDisplay.display ); + INVOKE_WCB( *win, Display, ( ) ); +} + +void fgPlatformMainLoopPreliminaryWork( void ) +{ + /* Under Wayland, this is a no-op */ +} + +void fgPlatformInitWork( SFG_Window* window ) +{ + /* Under Wayland, all events happen relative to input handlers + * -> this is a no-op + */ + return; +} + +void fgPlatformPosResZordWork( SFG_Window* window, unsigned int workMask ) +{ + if( workMask & GLUT_FULL_SCREEN_WORK ) + fgPlatformFullScreenToggle( window ); + if( workMask & GLUT_POSITION_WORK ) + fgPlatformPositionWindow( window, window->State.DesiredXpos, window->State.DesiredYpos ); + if( workMask & GLUT_SIZE_WORK ) + fgPlatformReshapeWindow ( window, window->State.DesiredWidth, window->State.DesiredHeight ); + if( workMask & GLUT_ZORDER_WORK ) + { + if( window->State.DesiredZOrder < 0 ) + fgPlatformPushWindow( window ); + else + fgPlatformPopWindow( window ); + } +} + +void fgPlatformVisibilityWork( SFG_Window* window ) +{ + /* Visibility status of window gets updated in the window message handlers above + */ + SFG_Window *win = window; + switch (window->State.DesiredVisibility) + { + case DesireHiddenState: + fgPlatformHideWindow( window ); + break; + case DesireIconicState: + /* Call on top-level window */ + while (win->Parent) + win = win->Parent; + fgPlatformIconifyWindow( win ); + break; + case DesireNormalState: + fgPlatformShowWindow( window ); + break; + } +} + diff --git a/freeglut/freeglut/src/wayland/fg_state_wl.c b/freeglut/freeglut/src/wayland/fg_state_wl.c new file mode 100644 index 0000000..06b9906 --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_state_wl.c @@ -0,0 +1,150 @@ +/* + * fg_state_wl.c + * + * Wayland-specific freeglut state query methods. + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Sun Mar 23 2015 + * + * 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 + * MANUEL BACHMANN 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 "egl/fg_state_egl.h" + +int fgPlatformGlutDeviceGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + case GLUT_HAS_KEYBOARD: + if( fgDisplay.pDisplay.keyboard ) + return 1; + else + return 0; + + case GLUT_HAS_MOUSE: + /* we want the touchscreen to behave like a mouse, + * so let us pretend it is one. + */ + if( fgDisplay.pDisplay.pointer || + fgDisplay.pDisplay.touch ) + return 1; + else + return 0; + + case GLUT_NUM_MOUSE_BUTTONS: + /* Wayland has no way of telling us how much buttons + * a mouse has, unless the actual event gets sent to + * the client. As we are only handling 3 buttons + * currently, return this fixed number for now. + */ + if( fgDisplay.pDisplay.pointer ) + return 3; + /* touchscreen is considered as having one button */ + else if( fgDisplay.pDisplay.touch ) + return 1; + else + return 0; + + default: + fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat ); + return -1; + } +} + + +int fgPlatformGlutGet ( GLenum eWhat ) +{ + switch( eWhat ) + { + + /* + * Those calls are pointless under Wayland, so inform the user + */ + case GLUT_WINDOW_X: + case GLUT_WINDOW_Y: + { + if( fgStructure.CurrentWindow == NULL ) + { + return 0; + } + else + { + fgWarning( "glutGet(): GLUT_WINDOW_X/Y properties " + "unsupported under Wayland" ); + return -1; + } + } + + /* + * TODO : support this correctly once we will start drawing + * client-side decorations + */ + case GLUT_WINDOW_BORDER_WIDTH: + case GLUT_WINDOW_HEADER_HEIGHT: + { + if( fgStructure.CurrentWindow == NULL || + fgStructure.CurrentWindow->Parent ) + /* can't get widths/heights if no current window + * and child windows don't have borders */ + return 0; + + return 0; + } + + case GLUT_WINDOW_WIDTH: + case GLUT_WINDOW_HEIGHT: + { + if( fgStructure.CurrentWindow == NULL ) + return 0; + + switch ( eWhat ) + { + case GLUT_WINDOW_WIDTH: + return fgStructure.CurrentWindow->State.Width; + case GLUT_WINDOW_HEIGHT: + return fgStructure.CurrentWindow->State.Height; + } + } + + /* Colormap size is handled in a bit different way than all the rest */ + case GLUT_WINDOW_COLORMAP_SIZE: + { + if( fgStructure.CurrentWindow == NULL ) + { + return 0; + } + else + { + int result = 0; + if ( ! eglGetConfigAttrib( fgDisplay.pDisplay.egl.Display, + fgStructure.CurrentWindow->Window.pContext.egl.Config, + EGL_BUFFER_SIZE, &result ) ) + fgError( "eglGetConfigAttrib(EGL_BUFFER_SIZE) failed" ); + + return result; + } + } + + default: + return fghPlatformGlutGetEGL( eWhat ); + } +} + diff --git a/freeglut/freeglut/src/wayland/fg_structure_wl.c b/freeglut/freeglut/src/wayland/fg_structure_wl.c new file mode 100644 index 0000000..ad77cdd --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_structure_wl.c @@ -0,0 +1,40 @@ +/* + * fg_structure_wl.c + * + * Windows and menus need tree structure for Wayland + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * 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 + * MANUEL BACHMANN 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 "egl/fg_structure_egl.h" + +extern SFG_Structure fgStructure; + +void fgPlatformCreateWindow( SFG_Window *window ) +{ + fghPlatformCreateWindowEGL( window ); + + window->State.pWState.OldHeight = window->State.pWState.OldWidth = -1; +} + diff --git a/freeglut/freeglut/src/wayland/fg_window_wl.c b/freeglut/freeglut/src/wayland/fg_window_wl.c new file mode 100644 index 0000000..e4c3da4 --- /dev/null +++ b/freeglut/freeglut/src/wayland/fg_window_wl.c @@ -0,0 +1,310 @@ +/* + * fg_window_wl.c + * + * Window management methods for Wayland + * + * Copyright (c) 2015 Manuel Bachmann. All Rights Reserved. + * Written by Manuel Bachmann, + * Creation date: Tue Mar 17, 2015 + * + * 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 + * MANUEL BACHMANN 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" +#include "egl/fg_window_egl.h" +#define fghCreateNewContext fghCreateNewContextEGL + +extern void fghOnReshapeNotify( SFG_Window *window, int width, int height, GLboolean forceNotify ); +void fgPlatformReshapeWindow( SFG_Window *window, int width, int height ); +void fgPlatformIconifyWindow( SFG_Window *window ); + + +static void fghShSurfacePing( void* data, + struct wl_shell_surface* shsurface, + uint32_t serial ) +{ + wl_shell_surface_pong( shsurface, serial ); +} +static void fghShSurfaceConfigure( void* data, + struct wl_shell_surface* shsurface, + uint32_t edges, + int32_t width, int32_t height ) +{ + SFG_Window* window = data; + fgPlatformReshapeWindow( window, width, height ); +} +static const struct wl_shell_surface_listener fghShSurfaceListener = +{ + fghShSurfacePing, + fghShSurfaceConfigure, + NULL +}; + + +static int fghToggleFullscreen(void) +{ + SFG_Window* win = fgStructure.CurrentWindow; + + if ( ! win->State.IsFullscreen ) + { + win->State.pWState.OldWidth = win->State.Width; + win->State.pWState.OldHeight = win->State.Height; + wl_shell_surface_set_fullscreen( win->Window.pContext.shsurface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL ); + } + else + { + fgPlatformReshapeWindow( win, win->State.pWState.OldWidth, + win->State.pWState.OldHeight ); + wl_shell_surface_set_toplevel( win->Window.pContext.shsurface ); + } + + return 0; +} + +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ) +{ + /* Save the display mode if we are creating a menu window */ + if( window->IsMenu && ( ! fgStructure.MenuContext ) ) + fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB ; + + fghChooseConfig( &window->Window.pContext.egl.Config ); + + if( ! window->Window.pContext.egl.Config ) + { + /* + * The "fghChooseConfig" 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_MULTISAMPLE ) + { + fgState.DisplayMode &= ~GLUT_MULTISAMPLE ; + fghChooseConfig( &window->Window.pContext.egl.Config ); + fgState.DisplayMode |= GLUT_MULTISAMPLE; + } + } + + FREEGLUT_INTERNAL_ERROR_EXIT( window->Window.pContext.egl.Config != NULL, + "EGL configuration with necessary capabilities " + "not found", "fgOpenWindow" ); + + if( ! positionUse ) + x = y = -1; /* default window position */ + if( ! sizeUse ) + w = h = 300; /* default window size */ + + /* Create the cursor */ + window->Window.pContext.cursor = wl_cursor_theme_get_cursor( + fgDisplay.pDisplay.cursor_theme, + "left_ptr" ); + window->Window.pContext.cursor_surface = wl_compositor_create_surface( + fgDisplay.pDisplay.compositor ); + + /* Create the main surface */ + window->Window.pContext.surface = wl_compositor_create_surface( + fgDisplay.pDisplay.compositor ); + + /* Create the shell surface with respects to the parent/child tree */ + window->Window.pContext.shsurface = wl_shell_get_shell_surface( + fgDisplay.pDisplay.shell, + window->Window.pContext.surface ); + wl_shell_surface_add_listener( window->Window.pContext.shsurface, + &fghShSurfaceListener, window ); + + if( title) + wl_shell_surface_set_title( window->Window.pContext.shsurface, title ); + + if( gameMode ) + { + window->State.IsFullscreen = GL_TRUE; + wl_shell_surface_set_fullscreen( window->Window.pContext.shsurface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, NULL ); + } + else if( !isSubWindow && !window->IsMenu ) + { + wl_shell_surface_set_toplevel( window->Window.pContext.shsurface ); + } + else + { + wl_shell_surface_set_transient( window->Window.pContext.shsurface, + window->Parent->Window.pContext.surface, + x, y, 0 ); + } + + /* Create the Wl_EGL_Window */ + window->Window.Context = fghCreateNewContext( window ); + window->Window.pContext.egl_window = wl_egl_window_create( + window->Window.pContext.surface, + w, h); + window->Window.pContext.egl.Surface = eglCreateWindowSurface( + fgDisplay.pDisplay.egl.Display, + window->Window.pContext.egl.Config, + (EGLNativeWindowType)window->Window.pContext.egl_window, + NULL ); + eglMakeCurrent( fgDisplay.pDisplay.egl.Display, window->Window.pContext.egl.Surface, + window->Window.pContext.egl.Surface, window->Window.Context ); + + window->Window.pContext.pointer_button_pressed = GL_FALSE; +} + + +/* + * Request a window resize + */ +void fgPlatformReshapeWindow( SFG_Window *window, int width, int height ) +{ + fghOnReshapeNotify(window, width, height, GL_FALSE); + + if( window->Window.pContext.egl_window ) + wl_egl_window_resize( window->Window.pContext.egl_window, + width, height, 0, 0 ); +} + + +/* + * Closes a window, destroying the frame and OpenGL context + */ +void fgPlatformCloseWindow( SFG_Window* window ) +{ + fghPlatformCloseWindowEGL(window); + + if ( window->Window.pContext.egl_window ) + wl_egl_window_destroy( window->Window.pContext.egl_window ); + if ( window->Window.pContext.shsurface ) + wl_shell_surface_destroy( window->Window.pContext.shsurface ); + if ( window->Window.pContext.surface ) + wl_surface_destroy( window->Window.pContext.surface ); + if ( window->Window.pContext.cursor_surface ) + wl_surface_destroy( window->Window.pContext.cursor_surface ); +} + + +/* + * This function re-creates the window assets if they + * have been destroyed + */ +void fgPlatformShowWindow( SFG_Window *window ) +{ + if ( ! window->Window.pContext.egl_window || + ! window->Window.pContext.shsurface || + ! window->Window.pContext.surface) + { + fgPlatformCloseWindow( window ); + fgPlatformOpenWindow( window, "", /* TODO : save the title for further use */ + GL_TRUE, window->State.Xpos, window->State.Ypos, + GL_TRUE, window->State.Width, window->State.Height, + (GLboolean)(window->State.IsFullscreen ? GL_TRUE : GL_FALSE), + (GLboolean)(window->Parent ? GL_TRUE : GL_FALSE) ); + } + else + { + /* TODO : support this once we start using xdg-shell + * + * xdg_surface_present( window->Window.pContext.shsurface, 0 ); + * INVOKE_WCB( *window, WindowStatus, ( GLUT_FULLY_RETAINED ) ); + * window->State.Visible = GL_TRUE; + */ + fgWarning( "glutShownWindow(): function unsupported for an already existing" + " window under Wayland" ); + } +} + +/* + * This function hides the specified window + */ +void fgPlatformHideWindow( SFG_Window *window ) +{ + fgPlatformIconifyWindow( window ); +} + +/* + * Iconify the specified window (top-level windows only) + */ +void fgPlatformIconifyWindow( SFG_Window *window ) +{ + /* TODO : support this once we start using xdg-shell + * + * xdg_surface_set_minimized( window->Window.pContext.shsurface ); + * INVOKE_WCB( *window, WindowStatus, ( GLUT_HIDDEN ) ); + * window->State.Visible = GL_FALSE; + */ + fgWarning( "glutIconifyWindow(): function unsupported under Wayland" ); +} + +/* + * Set the current window's title + */ +void fgPlatformGlutSetWindowTitle( const char* title ) +{ + SFG_Window* win = fgStructure.CurrentWindow; + wl_shell_surface_set_title( win->Window.pContext.shsurface, title ); +} + +/* + * Set the current window's iconified title + */ +void fgPlatformGlutSetIconTitle( const char* title ) +{ + fgPlatformGlutSetWindowTitle( title ); +} + +/* + * Change the specified window's position + */ +void fgPlatformPositionWindow( SFG_Window *window, int x, int y ) +{ + /* pointless under Wayland */ + fgWarning( "glutPositionWindow(): function unsupported under Wayland" ); +} + +/* + * Lowers the specified window (by Z order change) + */ +void fgPlatformPushWindow( SFG_Window *window ) +{ + /* pointless under Wayland */ + fgWarning( "glutPushWindow(): function unsupported under Wayland" ); +} + +/* + * Raises the specified window (by Z order change) + */ +void fgPlatformPopWindow( SFG_Window *window ) +{ + /* pointless under Wayland */ + fgWarning( "glutPopWindow(): function unsupported under Wayland" ); +} + +/* + * Toggle the window's full screen state. + */ +void fgPlatformFullScreenToggle( SFG_Window *win ) +{ + if(fghToggleFullscreen() != -1) { + win->State.IsFullscreen = !win->State.IsFullscreen; + } +} +