diff --git a/.gitignore b/.gitignore index 53b8f785..ff40c17e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,30 @@ -*.a +.DS_Store CMakeCache.txt CMakeFiles cmake_install.cmake cmake_uninstall.cmake -.DS_Store -src/config.h -src/libglfw.pc -src/libglfw.so -src/libglfw.a -src/libglfw.dylib -src/libglfw.lib -src/libglfwdll.lib -src/libglfw.dll +docs/Doxyfile +examples/*.app +examples/*.exe examples/boing examples/gears examples/heightmap examples/splitview examples/triangle examples/wave -examples/*.app -examples/*.exe +src/config.h +src/glfw.dll +src/glfw.lib +src/glfwdll.lib +src/libglfw.a +src/libglfw.dll +src/libglfw.dylib +src/libglfw.lib +src/libglfw.pc +src/libglfw.so +src/libglfwdll.lib +tests/*.app +tests/*.exe tests/accuracy tests/defaults tests/dynamic @@ -30,12 +35,10 @@ tests/gamma tests/glfwinfo tests/iconify tests/joysticks -tests/listmodes tests/peter tests/reopen tests/sharing tests/tearing +tests/title tests/version tests/windows -tests/*.app -tests/*.exe diff --git a/CMake/CheckX11Extensions.cmake b/CMake/CheckX11Extensions.cmake deleted file mode 100644 index a6f9b18b..00000000 --- a/CMake/CheckX11Extensions.cmake +++ /dev/null @@ -1,88 +0,0 @@ -# - Check if X11 RandR extension is available -# Check if the X11 extension RandR is available. -# This macro defines : -# - X11_RANDR_FOUND, If set to NO RandR is not available. -# - X11_RANDR_INCLUDE_DIR, includes directory containing the RandR header. -# - X11_RANDR_LIBRARIES, libraries to link in the library to use RandR. -# -# Created by Olivier Delannoy. -macro(CHECK_X11_XRANDR) - message(STATUS "Checking for X11 extension XRandR") - set(X11_XRANDR_FOUND "NO") - find_path(X11_XRANDR_INCLUDE_DIR "X11/extensions/Xrandr.h" - PATHS - /usr/local/include - /usr/local/X11/include - /usr/local/X11R6/include - /usr/include - /usr/X11/include - /usr/X11R6/include) - - find_library(X11_XRANDR_LIBRARIES NAMES Xrandr - PATHS - /usr/local/lib - /usr/local/X11/lib - /usr/local/X11R6/lib - /usr/lib - /usr/X11/lib - /usr/X11R6/lib) - # Create check if file compiles with randr - - if (X11_XRANDR_LIBRARIES AND X11_XRANDR_INCLUDE_DIR) - set(X11_XRANDR_FOUND "YES") - endif (X11_XRANDR_LIBRARIES AND X11_XRANDR_INCLUDE_DIR) - - if (X11_XRANDR_FOUND) - message(STATUS "Checking for X11 extension XRandR -- found") - else (X11_XRANDR_FOUND) - message(STATUS "Checking for X11 extension XRandR -- not found") - endif (X11_XRANDR_FOUND) - - mark_as_advanced(X11_XRANDR_LIBRARIES X11_XRANDR_INCLUDE_DIR) -endmacro(CHECK_X11_XRANDR) - - -# - Check if X11 VidMod extension is available -# Check if the X11 extension VidMod is available. -# This macro defines : -# - X11_VIDMOD_FOUND, If set to NO VidMod is not available. -# - X11_VIDMOD_INCLUDE_DIR, includes directory containing the headers. -# - X11_VIDMOD_LIBRARIES, libraries to link in the libraries. -# -# Created by Olivier Delannoy. -macro(CHECK_X11_XF86VIDMODE) - message(STATUS "Checking for X11 extension xf86vidmode") - set(X11_XF86VIDMODE_FOUND "NO") - find_path(X11_XF86VIDMODE_INCLUDE_DIR "X11/extensions/xf86vmode.h" - PATHS - /usr/local/include - /usr/local/X11/include - /usr/local/X11R6/include - /usr/include - /usr/X11/include - /usr/X11R6/include) - - find_library(X11_XF86VIDMODE_LIBRARIES NAMES Xxf86vm PATHS - /usr/local/lib - /usr/local/X11/lib - /usr/local/X11R6/lib - /usr/lib - /usr/X11/lib - /usr/X11R6/lib) - # Add a test case here - if (X11_XF86VIDMODE_LIBRARIES AND X11_XF86VIDMODE_INCLUDE_DIR) - set(X11_XF86VIDMODE_FOUND "YES") - endif (X11_XF86VIDMODE_LIBRARIES AND X11_XF86VIDMODE_INCLUDE_DIR) - - if (X11_XF86VIDMODE_FOUND) - message(STATUS "Checking for X11 extension xf86vidmode -- found") - else (X11_XF86VIDMODE_FOUND) - message(STATUS "Checking for X11 extension xf86vidmode -- not found") - endif(X11_XF86VIDMODE_FOUND) - - mark_as_advanced( - X11_XF86VIDMODE_LIBRARIES - X11_XF86VIDMODE_INCLUDE_DIR - ) - -endmacro(CHECK_X11_XF86VIDMODE) diff --git a/CMake/README.txt b/CMake/README.txt index d24854ed..9581f832 100644 --- a/CMake/README.txt +++ b/CMake/README.txt @@ -1,10 +1,19 @@ -This folder contains a collection of toolchains definition in order to -support cross compilation. The naming scheme is the following: +This directory contains a collection of toolchain definitions for cross +compilation, currently limited to compiling Win32 binaries on Linux. + +The toolchain file naming scheme is as follows: + host-system-compiler.cmake -to use this at the time you run the initial cmake command use the -following parameter - -DCMAKE_TOOLCHAIN_FILE=./toolchains/XXX-XXX-XXX.cmake - which maps to file in this folder. +To use these files you add a special parameter when configuring the source tree: + + cmake -DCMAKE_TOOLCHAIN_FILE= . + +For example, to use the Debian GNU/Linux MinGW package, run CMake like this: + + cmake -DCMAKE_TOOLCHAIN_FILE=CMake/linux-i586-mingw32msvc.cmake . + +For more details see this article: + + http://www.paraview.org/Wiki/CMake_Cross_Compiling -For more details see: http://www.paraview.org/Wiki/CMake_Cross_Compiling diff --git a/CMake/cygwin-i686-w64-mingw32.cmake b/CMake/cygwin-i686-w64-mingw32.cmake new file mode 100644 index 00000000..9bd60936 --- /dev/null +++ b/CMake/cygwin-i686-w64-mingw32.cmake @@ -0,0 +1,13 @@ +# Define the environment for cross compiling from Linux to Win32 +SET(CMAKE_SYSTEM_NAME Windows) # Target system name +SET(CMAKE_SYSTEM_VERSION 1) +SET(CMAKE_C_COMPILER "i686-w64-mingw32-gcc") +SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++") +SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres") +SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib") + +# Configure the behaviour of the find commands +SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32") +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/CMake/cygwin-x86_64-w64-mingw32.cmake b/CMake/cygwin-x86_64-w64-mingw32.cmake new file mode 100644 index 00000000..84b2c701 --- /dev/null +++ b/CMake/cygwin-x86_64-w64-mingw32.cmake @@ -0,0 +1,13 @@ +# Define the environment for cross compiling from Linux to Win32 +SET(CMAKE_SYSTEM_NAME Windows) # Target system name +SET(CMAKE_SYSTEM_VERSION 1) +SET(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc") +SET(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++") +SET(CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres") +SET(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib") + +# Configure the behaviour of the find commands +SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32") +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/CMake/linux-amd64-mingw32msvc.cmake b/CMake/linux-amd64-mingw32msvc.cmake new file mode 100644 index 00000000..705e251d --- /dev/null +++ b/CMake/linux-amd64-mingw32msvc.cmake @@ -0,0 +1,13 @@ +# Define the environment for cross compiling from Linux to Win64 +SET(CMAKE_SYSTEM_NAME Windows) +SET(CMAKE_SYSTEM_VERSION 1) +SET(CMAKE_C_COMPILER "amd64-mingw32msvc-gcc") +SET(CMAKE_CXX_COMPILER "amd64-mingw32msvc-g++") +SET(CMAKE_RC_COMPILER "amd64-mingw32msvc-windres") +SET(CMAKE_RANLIB "amd64-mingw32msvc-ranlib") + +# Configure the behaviour of the find commands +SET(CMAKE_FIND_ROOT_PATH "/usr/amd64-mingw32msvc") +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/CMake/linux-mingw32msvc.cmake b/CMake/linux-i586-mingw32msvc.cmake similarity index 51% rename from CMake/linux-mingw32msvc.cmake rename to CMake/linux-i586-mingw32msvc.cmake index 4131bc92..393ddbda 100644 --- a/CMake/linux-mingw32msvc.cmake +++ b/CMake/linux-i586-mingw32msvc.cmake @@ -1,14 +1,12 @@ -# Define the cross compilation environment for cross compiling from linux -# to win32 it is to be used when debian cross compilation toolchain is -# available. -SET(CMAKE_SYSTEM_NAME Windows) # Target system name -SET(CMAKE_SYSTEM_VERSION 1) # Not really used. +# Define the environment for cross compiling from Linux to Win32 +SET(CMAKE_SYSTEM_NAME Windows) +SET(CMAKE_SYSTEM_VERSION 1) SET(CMAKE_C_COMPILER "i586-mingw32msvc-gcc") SET(CMAKE_CXX_COMPILER "i586-mingw32msvc-g++") +SET(CMAKE_RC_COMPILER "i586-mingw32msvc-windres") SET(CMAKE_RANLIB "i586-mingw32msvc-ranlib") - -#Configure the behaviour of the find commands +# Configure the behaviour of the find commands SET(CMAKE_FIND_ROOT_PATH "/usr/i586-mingw32msvc") SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) diff --git a/CMake/linux-i686-pc-mingw32.cmake b/CMake/linux-i686-pc-mingw32.cmake index 62dc8675..9a46aef7 100644 --- a/CMake/linux-i686-pc-mingw32.cmake +++ b/CMake/linux-i686-pc-mingw32.cmake @@ -1,9 +1,9 @@ -# Define the cross compilation environment for cross compiling from linux -# to win32 +# Define the environment for cross compiling from Linux to Win32 SET(CMAKE_SYSTEM_NAME Windows) # Target system name SET(CMAKE_SYSTEM_VERSION 1) SET(CMAKE_C_COMPILER "i686-pc-mingw32-gcc") SET(CMAKE_CXX_COMPILER "i686-pc-mingw32-g++") +SET(CMAKE_RC_COMPILER "i686-pc-mingw32-windres") SET(CMAKE_RANLIB "i686-pc-mingw32-ranlib") #Configure the behaviour of the find commands diff --git a/CMakeLists.txt b/CMakeLists.txt index 57967600..44dcb4d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ project(GLFW C) -cmake_minimum_required(VERSION 2.4) -cmake_policy(VERSION 2.4) +cmake_minimum_required(VERSION 2.8) set(GLFW_VERSION_MAJOR "3") set(GLFW_VERSION_MINOR "0") @@ -12,105 +11,166 @@ set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON) option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON) +option(BUILD_SHARED_LIBS "Build shared libraries" OFF) find_package(OpenGL REQUIRED) #-------------------------------------------------------------------- -# Set up GLFW for Win32 and WGL on Windows +# Enable all warnings on GCC, regardless of OS +#-------------------------------------------------------------------- +if (CMAKE_COMPILER_IS_GNUCC) + add_definitions(-Wall) +endif() + +#-------------------------------------------------------------------- +# Export shared library / dynamic library / DLL build option +#-------------------------------------------------------------------- +if (BUILD_SHARED_LIBS) + set(_GLFW_BUILD_DLL 1) +endif() + +#-------------------------------------------------------------------- +# Detect and select target platform #-------------------------------------------------------------------- if (WIN32) - message(STATUS "Building GLFW for WGL on a Win32 system") - - # Define the platform identifier set(_GLFW_WIN32_WGL 1) + message(STATUS "Building GLFW for WGL on a Win32 system") +elseif (UNIX AND APPLE) + set(_GLFW_COCOA_NSGL 1) + message(STATUS "Building GLFW for Cocoa and NSOpenGL on Mac OS X") +elseif (UNIX AND NOT APPLE) + set(_GLFW_X11_GLX 1) + message(STATUS "Building GLFW for X11 and GLX on a Unix-like system") +else() + message(FATAL_ERROR "No supported platform was detected") +endif() + +#-------------------------------------------------------------------- +# Set up GLFW for Win32 and WGL on Windows +#-------------------------------------------------------------------- +if (_GLFW_WIN32_WGL) # Set up library and include paths - list(APPEND GLFW_INCLUDE_DIR ${OPENGL_INCLUDE_DIR}) - list(APPEND GLFW_LIBRARIES ${OPENGL_gl_LIBRARY}) -endif (WIN32) + list(APPEND glfw_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR}) + list(APPEND glfw_LIBRARIES ${OPENGL_gl_LIBRARY}) + + set(_GLFW_NO_DLOAD_WINMM ${BUILD_SHARED_LIBS}) + + if (BUILD_SHARED_LIBS) + list(APPEND glfw_LIBRARIES winmm) + endif() +endif() #-------------------------------------------------------------------- # Set up GLFW for Xlib and GLX on Unix-like systems with X Windows #-------------------------------------------------------------------- -if (UNIX AND NOT APPLE) - message(STATUS "Building GLFW for X11 and GLX on a Unix-like system") +if (_GLFW_X11_GLX) - # Define the platform identifier - set(_GLFW_X11_GLX 1) + find_package(X11 REQUIRED) # Set up library and include paths - list(APPEND GLFW_INCLUDE_DIR ${X11_X11_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR}) - list(APPEND GLFW_LIBRARIES ${X11_X11_LIB} ${OPENGL_gl_LIBRARY}) + list(APPEND glfw_INCLUDE_DIRS ${X11_X11_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR}) + list(APPEND glfw_LIBRARIES ${X11_X11_LIB} ${OPENGL_gl_LIBRARY}) - find_library(MATH_LIBRARY m) - if (MATH_LIBRARY) - list(APPEND GLFW_LIBRARIES ${MATH_LIBRARY}) - endif(MATH_LIBRARY) - - find_library(RT_LIBRARY rt) - if (RT_LIBRARY) - list(APPEND GLFW_LIBRARIES ${RT_LIBRARY}) - endif(RT_LIBRARY) + set(GLFW_PKG_DEPS "gl x11") + set(GLFW_PKG_LIBS "") include(CheckFunctionExists) - include(CheckSymbolExists) - include(${GLFW_SOURCE_DIR}/CMake/CheckX11Extensions.cmake) - set(CMAKE_REQUIRED_LIBRARIES ${GLFW_LIBRARIES}) - # Check for XRandR (modern resolution switching extension) - check_x11_xrandr() - if (X11_XRANDR_FOUND) + if (X11_Xrandr_FOUND) set(_GLFW_HAS_XRANDR 1) - list(APPEND GLFW_INCLUDE_DIR ${X11_XRANDR_INCLUDE_DIR}) - list(APPEND GLFW_LIBRARIES ${X11_XRANDR_LIBRARIES}) - endif(X11_XRANDR_FOUND) + list(APPEND glfw_INCLUDE_DIRS ${X11_Xrandr_INCLUDE_PATH}) + list(APPEND glfw_LIBRARIES ${X11_Xrandr_LIB}) + set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} xrandr") + endif() # Check for Xf86VidMode (fallback legacy resolution switching extension) - check_x11_xf86vidmode() - if (X11_XF86VIDMODE_FOUND) + if (X11_xf86vmode_FOUND) set(_GLFW_HAS_XF86VIDMODE 1) - list(APPEND GLFW_INCLUDE_DIR ${X11_XF86VIDMODE_INCLUDE_DIR}) - list(APPEND GLFW_LIBRARIES ${X11_XF86VIDMODE_LIBRARIES}) - endif(X11_XF86VIDMODE_FOUND) + list(APPEND glfw_INCLUDE_DIRS ${X11_xf86vmode_INCLUDE_PATH}) + + # NOTE: This is a workaround for CMake bug 0006976 (missing + # X11_xf86vmode_LIB variable) + if (X11_xf86vmode_LIB) + list(APPEND glfw_LIBRARIES ${X11_xf86vmode_LIB}) + else() + list(APPEND glfw_LIBRARIES Xxf86vm) + endif() + + set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} xxf86vm") + endif() # Check for Xkb (X keyboard extension) - check_function_exists(XkbQueryExtension _GLFW_HAS_XKB) + if (X11_Xkb_FOUND) + set(_GLFW_HAS_XKB 1) + list(APPEND glfw_INCLUDE_DIR ${X11_Xkb_INCLUDE_PATH}) + endif() + + find_library(RT_LIBRARY rt) + mark_as_advanced(RT_LIBRARY) + if (RT_LIBRARY) + list(APPEND glfw_LIBRARIES ${RT_LIBRARY}) + set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} -lrt") + endif() + + find_library(MATH_LIBRARY m) + mark_as_advanced(MATH_LIBRARY) + if (MATH_LIBRARY) + list(APPEND glfw_LIBRARIES ${MATH_LIBRARY}) + set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} -lm") + endif() + + set(CMAKE_REQUIRED_LIBRARIES ${OPENGL_gl_LIBRARY}) - # Check for glXGetProcAddress check_function_exists(glXGetProcAddress _GLFW_HAS_GLXGETPROCADDRESS) if (NOT _GLFW_HAS_GLXGETPROCADDRESS) check_function_exists(glXGetProcAddressARB _GLFW_HAS_GLXGETPROCADDRESSARB) - endif (NOT _GLFW_HAS_GLXGETPROCADDRESS) + endif() if (NOT _GLFW_HAS_GLXGETPROCADDRESS AND NOT _GLFW_HAS_GLXGETPROCADDRESSARB) check_function_exists(glXGetProcAddressEXT _GLFW_HAS_GLXGETPROCADDRESSEXT) - endif (NOT _GLFW_HAS_GLXGETPROCADDRESS AND NOT _GLFW_HAS_GLXGETPROCADDRESSARB) + endif() if (NOT _GLFW_HAS_GLXGETPROCADDRESS AND NOT _GLFW_HAS_GLXGETPROCADDRESSARB AND NOT _GLFW_HAS_GLXGETPROCADDRESSEXT) message(WARNING "No glXGetProcAddressXXX variant found") - endif (NOT _GLFW_HAS_GLXGETPROCADDRESS AND - NOT _GLFW_HAS_GLXGETPROCADDRESSARB AND - NOT _GLFW_HAS_GLXGETPROCADDRESSEXT) + + # Check for dlopen support as a fallback + + find_library(DL_LIBRARY dl) + mark_as_advanced(DL_LIBRARY) + if (DL_LIBRARY) + set(CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARY}) + else() + set(CMAKE_REQUIRED_LIBRARIES "") + endif() + + check_function_exists(dlopen _GLFW_HAS_DLOPEN) + + if (NOT _GLFW_HAS_DLOPEN) + message(FATAL_ERROR "No entry point retrieval mechanism found") + endif() + + if (DL_LIBRARY) + list(APPEND glfw_LIBRARIES ${DL_LIBRARY}) + set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} -ldl") + endif() + endif() if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(_GLFW_USE_LINUX_JOYSTICKS 1) - endif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") -endif(UNIX AND NOT APPLE) + endif() +endif() #-------------------------------------------------------------------- # Set up GLFW for Cocoa and NSOpenGL on Mac OS X #-------------------------------------------------------------------- -if (UNIX AND APPLE) - message(STATUS "Building GLFW for Cocoa and NSOpenGL on Mac OS X") +if (_GLFW_COCOA_NSGL) - # Define the platform identifier - set(_GLFW_COCOA_NSGL 1) - - option(GLFW_BUILD_UNIVERSAL "Build the GLFW library and examples as Universal Binaries" FALSE) + option(GLFW_BUILD_UNIVERSAL "Build GLFW as a Universal Binary" OFF) # Universal build if (GLFW_BUILD_UNIVERSAL) @@ -120,17 +180,25 @@ if (UNIX AND APPLE) set(CMAKE_C_FLAGS "-mmacosx-version-min=10.5") else(GLFW_BUILD_UNIVERSAL) message(STATUS "Building GLFW only for the native architecture") - endif(GLFW_BUILD_UNIVERSAL) + endif() # Set up library and include paths find_library(COCOA_FRAMEWORK Cocoa) find_library(IOKIT_FRAMEWORK IOKit) find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation) - list(APPEND GLFW_LIBRARIES ${COCOA_FRAMEWORK}) - list(APPEND GLFW_LIBRARIES ${OPENGL_gl_LIBRARY}) - list(APPEND GLFW_LIBRARIES ${IOKIT_FRAMEWORK}) - list(APPEND GLFW_LIBRARIES ${CORE_FOUNDATION_FRAMEWORK}) -endif(UNIX AND APPLE) + list(APPEND glfw_LIBRARIES ${COCOA_FRAMEWORK} + ${OPENGL_gl_LIBRARY} + ${IOKIT_FRAMEWORK} + ${CORE_FOUNDATION_FRAMEWORK}) + + set(GLFW_PKG_DEPS "") + set(GLFW_PKG_LIBS "-framework Cocoa -framework OpenGL -framework IOKit -framework CoreFoundation") +endif() + +#-------------------------------------------------------------------- +# Export GLFW library dependencies +#-------------------------------------------------------------------- +set(GLFW_LIBRARIES ${glfw_LIBRARIES} CACHE STRING "Dependencies of GLFW") #-------------------------------------------------------------------- # Add subdirectories @@ -139,42 +207,47 @@ add_subdirectory(src) if (GLFW_BUILD_EXAMPLES) add_subdirectory(examples) -endif(GLFW_BUILD_EXAMPLES) +endif() if (GLFW_BUILD_TESTS) add_subdirectory(tests) -endif(GLFW_BUILD_TESTS) +endif() #-------------------------------------------------------------------- -# Create shared configuration header +# Create generated files #-------------------------------------------------------------------- +configure_file(${GLFW_SOURCE_DIR}/docs/Doxyfile.in + ${GLFW_BINARY_DIR}/docs/Doxyfile @ONLY) + configure_file(${GLFW_SOURCE_DIR}/src/config.h.in ${GLFW_BINARY_DIR}/src/config.h @ONLY) #-------------------------------------------------------------------- -# Install standard files +# Install header and documentation +# The src directory's CMakeLists.txt file installs the library #-------------------------------------------------------------------- - install(DIRECTORY include/GL DESTINATION include FILES_MATCHING PATTERN glfw3.h) install(FILES COPYING.txt readme.html - DESTINATION share/doc/glfw-${GLFW_VERSION_FULL}/) - -# The respective port's CMakeLists.txt file installs the library + DESTINATION share/doc/glfw-${GLFW_VERSION_FULL}) #-------------------------------------------------------------------- -# -- Documentation generation +# Create and install pkg-config file on supported platforms #-------------------------------------------------------------------- -configure_file("${GLFW_SOURCE_DIR}/docs/Doxyfile.in" - "${GLFW_BINARY_DIR}/docs/Doxyfile" - @ONLY) +if (_GLFW_X11_GLX OR _GLFW_COCOA_NSGL) + configure_file(${GLFW_SOURCE_DIR}/src/libglfw.pc.in + ${GLFW_BINARY_DIR}/src/libglfw.pc @ONLY) + + install(FILES ${GLFW_BINARY_DIR}/src/libglfw.pc + DESTINATION lib/pkgconfig) +endif() #-------------------------------------------------------------------- # Uninstall operation # Don't generate this target if a higher-level project already has #-------------------------------------------------------------------- -if(NOT TARGET uninstall) +if (NOT TARGET uninstall) configure_file(${GLFW_SOURCE_DIR}/cmake_uninstall.cmake.in ${GLFW_BINARY_DIR}/cmake_uninstall.cmake IMMEDIATE @ONLY) diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index 6bc7da29..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -########################################################################## -# Makefile for the GLFW documentation. -########################################################################## - -PDFDOCS = glfwrm.pdf glfwug.pdf -DVIDOCS = glfwrm.dvi glfwug.dvi - - -########################################################################## -# Build macros -########################################################################## -default: pdf -pdf: $(PDFDOCS) -dvi: $(DVIDOCS) - - -########################################################################## -# Clean macros -########################################################################## -clean: - rm -f glfwrm.dvi glfwrm.aux glfwrm.log glfwrm.out glfwrm.pdf glfwrm.toc glfwrm.lot - rm -f glfwug.dvi glfwug.aux glfwug.log glfwug.out glfwug.pdf glfwug.toc - -clean-win: - @.\\cleanup.bat - - -########################################################################## -# Rules for building the GLFW Reference Manual -########################################################################## - -glfwrm.pdf: glfwrm.tex glfwrm.toc glfwrm.lot glfwdoc.sty - pdflatex glfwrm.tex - -glfwrm.dvi: glfwrm.tex glfwrm.toc glfwrm.lot glfwdoc.sty - latex glfwrm.tex - -glfwrm.toc: glfwrm.tex glfwdoc.sty - latex glfwrm.tex - -glfwrm.lot: glfwrm.tex glfwdoc.sty - latex glfwrm.tex - - -########################################################################## -# Rules for building the GLFW Users Guide -########################################################################## - -glfwug.pdf: glfwug.tex glfwug.toc glfwdoc.sty - pdflatex glfwug.tex - -glfwug.dvi: glfwug.tex glfwug.toc glfwdoc.sty - latex glfwug.tex - -glfwug.toc: glfwug.tex glfwdoc.sty - latex glfwug.tex - diff --git a/docs/cleanup.bat b/docs/cleanup.bat deleted file mode 100644 index 268a27b6..00000000 --- a/docs/cleanup.bat +++ /dev/null @@ -1,22 +0,0 @@ -@echo off - -REM ---------------------------------------------------------------------- -REM Windows cleanup batch file for the GLFW documentation. -REM ---------------------------------------------------------------------- - -REM GLFW Reference Manual -if exist glfwrm.dvi del glfwrm.dvi -if exist glfwrm.aux del glfwrm.aux -if exist glfwrm.log del glfwrm.log -if exist glfwrm.out del glfwrm.out -if exist glfwrm.pdf del glfwrm.pdf -if exist glfwrm.toc del glfwrm.toc -if exist glfwrm.lot del glfwrm.lot - -REM GLFW Users Guide -if exist glfwug.dvi del glfwug.dvi -if exist glfwug.aux del glfwug.aux -if exist glfwug.log del glfwug.log -if exist glfwug.out del glfwug.out -if exist glfwug.pdf del glfwug.pdf -if exist glfwug.toc del glfwug.toc diff --git a/docs/glfwdoc.sty b/docs/glfwdoc.sty deleted file mode 100644 index e415570e..00000000 --- a/docs/glfwdoc.sty +++ /dev/null @@ -1,81 +0,0 @@ -%------------------------------------------------------------------------- -% Common document formatting and macros for GLFW manuals -%------------------------------------------------------------------------- - -% Misc. document info -\date{\today} - -% Packages -\usepackage{fancyhdr} -\usepackage{titling} -\usepackage{lastpage} -\usepackage{listings} -\usepackage{color} -\usepackage[overload]{textcase} -\usepackage{needspace} -\usepackage{times} - -% Logo macros -\newcommand{\OpenGL}[1][0]{OpenGL\textsuperscript{\textregistered}} -\newcommand{\GLFW}[1][0]{GLFW} - -% Encoding -\usepackage[latin1]{inputenc} -\usepackage[T1]{fontenc} - -% Page formatting -\usepackage[hmargin=2.5cm]{geometry} -\raggedright -\raggedbottom -\sloppy -\usepackage{parskip} - -% Header and footer -\pagestyle{fancy} -%\lhead{\textit{GLFW Reference Manual}} -\lhead{\textit{GLFW \glfwdoctype}} -\chead{API version \glfwapiver} -\rhead{Page \thepage/\pageref{LastPage}} -\lfoot{} -\cfoot{} -\rfoot{} -\renewcommand{\headrulewidth}{0.4pt} -\renewcommand{\footrulewidth}{0.0pt} - -% Titlepage -\newcommand{\glfwmaketitle}{\begin{titlepage}\ \\% - \begin{center}% - \vspace{7.0cm}{\Huge\textbf{GLFW}}\\% - \rule{10.0cm}{0.5pt}\\% - \vspace{0.5cm}{\LARGE\textbf{\glfwdoctype}}\\% - \vspace{0.8cm}{\large\textbf{API version \glfwapiver}}\\% - \textit{\today}\\% - \vspace{1.5cm}\textbf{\textcopyright2002-2006 Marcus Geelnard}\\ - \textbf{\textcopyright2006-2010 Camilla Berglund}\\% - \end{center}\end{titlepage}\newpage} - -% Colors -\definecolor{code}{rgb}{0.9,0.9,1.0} -\definecolor{link}{rgb}{0.6,0.0,0.0} -\definecolor{codeA}{rgb}{0.9,1.0,0.9} -\definecolor{codeB}{rgb}{1.0,0.9,0.9} - -% Code listings -\lstset{frame=single,frameround=tttt,backgroundcolor=\color{code},% - language=C,basicstyle={\ttfamily},% - breaklines,breakindent=0pt,postbreak=\space\space\space\space} - - -% A simple hack for keeping lines together -\newenvironment{mysamepage}[1][2]{\begin{samepage}\needspace{#1\baselineskip}}{\end{samepage}} - -% Macros for automating function reference entries -\newenvironment{refparameters}[1][0]{\begin{mysamepage}\textbf{Parameters}\\}{\end{mysamepage}\bigskip} -\newenvironment{refreturn}[1][0]{\begin{mysamepage}\textbf{Return values}\\}{\end{mysamepage}\bigskip} -\newenvironment{refdescription}[1][0]{\begin{mysamepage}\textbf{Description}\\}{\end{mysamepage}\bigskip} -\newenvironment{refnotes}[1][0]{\begin{mysamepage}\textbf{Notes}\\}{\end{mysamepage}\bigskip} - -% hyperref (bookmarks, links etc) - use this package last -\usepackage[colorlinks=true,linkcolor=link,bookmarks=true,bookmarksopen=true,% - pdfhighlight=/N,bookmarksnumbered=true,bookmarksopenlevel=1,% - pdfview=FitH,pdfstartview=FitH]{hyperref} diff --git a/docs/glfwrm.tex b/docs/glfwrm.tex deleted file mode 100644 index 48c80b42..00000000 --- a/docs/glfwrm.tex +++ /dev/null @@ -1,2364 +0,0 @@ -%------------------------------------------------------------------------- -% GLFW Reference Manual -% API Version: 3.0 -%------------------------------------------------------------------------- - -% Document class -\documentclass[a4paper,11pt,oneside]{report} - -% Document title and API version -\newcommand{\glfwdoctype}[1][0]{Reference Manual} -\newcommand{\glfwapiver}[1][0]{3.0} - -% Common document settings and macros -\input{glfwdoc.sty} - -% PDF specific document settings -\hypersetup{pdftitle={GLFW Reference Manual}} -\hypersetup{pdfauthor={Camilla Berglund}} -\hypersetup{pdfkeywords={GLFW,OpenGL,reference,manual}} - - -%------------------------------------------------------------------------- -% Document body -%------------------------------------------------------------------------- - -\begin{document} - -\pagestyle{plain} - -% Title page -\glfwmaketitle - -% Summary, trademarks and table of contents -\pagenumbering{roman} -\setcounter{page}{1} - -%------------------------------------------------------------------------- -% Summary and Trademarks -%------------------------------------------------------------------------- -\chapter*{Summary} - -This document is primarily a function reference manual for the \GLFW\ API. -For a description of how to use \GLFW\ you should refer to the -\textit{GLFW Users Guide}. -\vspace{5cm} - -\large -Trademarks - -\small -OpenGL and IRIX are registered trademarks of Silicon Graphics, Inc.\linebreak -Microsoft and Windows are registered trademarks of Microsoft Corporation.\linebreak -Mac OS is a registered trademark of Apple Computer, Inc.\linebreak -Linux is a registered trademark of Linus Torvalds.\linebreak -FreeBSD is a registered trademark of Wind River Systems, Inc.\linebreak -Solaris is a trademark of Sun Microsystems, Inc.\linebreak -UNIX is a registered trademark of The Open Group.\linebreak -X Window System is a trademark of The Open Group.\linebreak -POSIX is a trademark of IEEE.\linebreak -Truevision, TARGA and TGA are registered trademarks of Truevision, Inc.\linebreak - -All other trademarks mentioned in this document are the property of their respective owners. -\normalsize - - -%------------------------------------------------------------------------- -% Table of contents -%------------------------------------------------------------------------- -\tableofcontents - -%------------------------------------------------------------------------- -% List of tables -%------------------------------------------------------------------------- -\listoftables -\pagebreak - - -% Document chapters starts here... -\pagenumbering{arabic} -\setcounter{page}{1} - -\pagestyle{fancy} - - -%------------------------------------------------------------------------- -% Introduction -%------------------------------------------------------------------------- -\chapter{Introduction} -\thispagestyle{fancy} - -\GLFW\ is a portable API (Application Program Interface) that handles -operating system specific tasks related to \OpenGL\ programming. While -\OpenGL\ in general is portable, easy to use and often results in tidy and -compact code, the operating system specific mechanisms that are required -to set up and manage an \OpenGL\ window are quite the opposite. \GLFW\ tries -to remedy this by providing the following functionality: - -\begin{itemize} -\item Opening and managing an \OpenGL\ context and its associated window. -\item Keyboard, mouse and joystick input. -\item A high precision timer. -\item Support for querying and using \OpenGL\ extensions. -\end{itemize} - -All this functionality is implemented as a set of easy-to-use functions, -which makes it possible to write an \OpenGL\ application framework in just a -few lines of code. The \GLFW\ API looks and behaves the same on all supported -platforms, making it very simple to port \GLFW\ based \OpenGL\ applications to -a variety of platforms. - -Currently supported platforms are: -\begin{itemize} -\item Microsoft Windows\textsuperscript{\textregistered} (32-bit only). -\item Unix\textsuperscript{\textregistered} or Unix­-like systems running -resonably a modern version of the X Window -System\texttrademark\footnote{X11.app on Mac OS X is not supported due to its -incomplete implementation of GLXFBConfigs} e.g. -Linux\textsuperscript{\textregistered}, -FreeBSD\textsuperscript{\textregistered} and Solaris\texttrademark (32- and -64-bit). -\item Mac OS\textsuperscript{\textregistered} X, using Cocoa\footnote{Joystick -input is not yet supported on Mac OS X.} (32- and 64-bit). -\end{itemize} - - - -%------------------------------------------------------------------------- -% GLFW Operation -%------------------------------------------------------------------------- -\chapter{GLFW Operation Overview} -\thispagestyle{fancy} - - -%------------------------------------------------------------------------- -\section{The GLFW Window} -\GLFW\ only supports having one window open at a time. The window can be either -a normal desktop window or a fullscreen window. The latter is completely -undecorated, without window borders, and covers the entire monitor. With a -fullscreen window, it is also possible to select which video mode to use. - -When a window is opened, an \OpenGL\ rendering context is created and -attached to the entire client area of the window. When the window is closed, -the \OpenGL\ rendering context is detached and destroyed. - -Through a window it is possible to receive user input in the form of -keyboard and mouse input. User input is exposed through the \GLFW\ API -primarily via a set of callback functions. Also, \GLFW\ stores most user input -as internal state that can be queried through different \GLFW\ API functions -(for instance it is possible to query the position of the mouse cursor with the -\textbf{glfwGetMousePos} function). - -As for user input, it is possible to receive information about window -state changes, such as window resize or close events, through callback -functions. It is also possible to query some kinds of information about the -window information using \GLFW\ API functions. - - -%------------------------------------------------------------------------- -\section{The GLFW Event Loop} -The \GLFW\ event loop is an open loop, which means that it is up to the -programmer to design the loop. Events are processed by calling specific -\GLFW\ functions, which in turn query the system for new input and window -events and reports these events back to the program through callback -functions. - -The programmer decides when to call the event processing functions and -when to abort the event loop. - -In pseudo language, a typical event loop might look like this: - -\begin{lstlisting} - repeat until window is closed - { - poll events - draw OpenGL graphics - } -\end{lstlisting} - -There are two ways to handle events in \GLFW : - -\begin{itemize} - \item Block the event loop while waiting for new events. - \item Poll for new events and continue the loop regardless of whether there - are any new events or not. -\end{itemize} - -The first method is useful for interactive applications that do not -need to refresh the \OpenGL\ display unless the user interacts with the -application through user input. Typical applications are CAD software -and other kinds of editors. - -The second method is useful for applications that need to refresh the -\OpenGL\ display constantly, regardless of user input, such as games, -demos, 3D animations, screen savers and so on. - - -%------------------------------------------------------------------------- -\section{Callback Functions} -Using callback functions can be a good method for receiving up to date -information about window state and user input. When a window has been -opened, it is possible to register custom callback functions that will -be called when certain events occur. - -Callback functions are called from any of the event polling functions -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or -\textbf{glfwSwapBuffers}. - -Callback functions should \emph{only} be used to gather information. Since -the callback functions are called from within the internal \GLFW\ event -polling loops, they should not call any \GLFW\ functions that might -result in considerable \GLFW\ state changes, nor stall the event polling -loop for a lengthy period of time. - -In other words, most or all \OpenGL\ rendering should be called from the -main application event loop, not from any of the \GLFW\ callback -functions. Also, the only \GLFW\ functions that may be safely called from -callback functions are the different Get functions (e.g. -\textbf{glfwGetKey}, \textbf{glfwGetTime}, \textbf{glfwGetWindowParam} -etc.). - - -%------------------------------------------------------------------------- -% Function Reference -%------------------------------------------------------------------------- -\chapter{Function Reference} -\thispagestyle{fancy} - -%------------------------------------------------------------------------- -\section{GLFW Initialization and Termination} -Before any other \GLFW\ functions can be used, \GLFW\ must be initialized to -ensure proper functionality, and before a program terminates \GLFW\ should be -terminated in order to free allocated resources, memory, etc. - - -%------------------------------------------------------------------------- -\subsection{glfwInit} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwInit(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -If the function succeeds, GL\_TRUE is returned.\\ -If the function fails, GL\_FALSE is returned. -\end{refreturn} - -\begin{refdescription} -The glfwInit function initializes \GLFW. No other \GLFW\ functions may be -called before this function has succeeded. -\end{refdescription} - -\begin{refnotes} -This function may take several seconds to complete on some systems, while -on other systems it may take only a fraction of a second to complete. - -This function registers a function calling \textbf{glfwTerminate} with the -atexit facility of the C library. - -On Mac OS X, this function will change the current directory of the application -to the \textbf{Contents/Resources} subdirectory of the application's bundle, if -present. For more information on bundles, see the Bundle Programming Guide -provided by Apple. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwTerminate} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwTerminate(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function terminates \GLFW. Among other things it closes the window, if -open. This function should be called before a program exits. -\end{refdescription} - - -%------------------------------------------------------------------------- -\subsection{glfwGetVersion} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwGetVersion(int* major, int* minor, int* rev) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{major}]\ \\ - Pointer to an integer that will hold the major version number. -\item [\textit{minor}]\ \\ - Pointer to an integer that will hold the minor version number. -\item [\textit{rev}]\ \\ - Pointer to an integer that will hold the revision. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the major and minor version numbers and the revision -for the currently linked \GLFW\ library. -\end{refreturn} - -\begin{refdescription} -This function returns the \GLFW\ library version. -\end{refdescription} - - -%------------------------------------------------------------------------- -\pagebreak -\section{Window Handling} -The primary purpose of \GLFW\ is to provide a simple interface to -\OpenGL\ context creation and window management. \GLFW\ supports one window at -a time, which can be either a normal desktop window or a fullscreen window. - - -%------------------------------------------------------------------------- -\subsection{glfwOpenWindow} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwOpenWindow(int width, int height, - int redbits, int greenbits, int bluebits, - int alphabits, int depthbits, int stencilbits, - int mode) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{width}]\ \\ - The width of the window. If \textit{width} is zero, it will be - calculated as ${width=\frac{4}{3}height}$, if \textit{height} is not - zero. If both \textit{width} and \textit{height} are zero, - \textit{width} will be set to 640. -\item [\textit{height}]\ \\ - The height of the window. If \textit{height} is zero, it will be - calculated as ${height=\frac{3}{4}width}$, if \textit{width} is not - zero. If both \textit{width} and \textit{height} are zero, - \textit{height} will be set to 480. -\item [\textit{redbits, greenbits, bluebits}]\ \\ - The number of bits to use for each color component of the color buffer - (0 means default color depth). For instance, setting \textit{redbits=5, - greenbits=6 and bluebits=5} will create a 16-­bit color buffer, if - possible. -\item [\textit{alphabits}]\ \\ - The number of bits to use for the alpha channel of the color buffer (0 means - no alpha channel). -\item [\textit{depthbits}]\ \\ - The number of bits to use for the depth buffer (0 means no depth - buffer). -\item [\textit{stencilbits}]\ \\ - The number of bits to use for the stencil buffer (0 means no stencil - buffer). -\item [\textit{mode}]\ \\ - Selects which type of \OpenGL\ window to use. \textit{mode} must be - either GLFW\_WINDOW, which will generate a normal desktop window, or - GLFW\_FULLSCREEN, which will generate a window which covers the entire - screen. When GLFW\_FULLSCREEN is selected, the video mode will be - changed to the resolution that closest matches the \textit{width} and - \textit{height} parameters. -\end{description} -\end{refparameters} - -\begin{refreturn} -If the function succeeds, GL\_TRUE is returned.\\ -If the function fails, GL\_FALSE is returned. -\end{refreturn} - -\begin{refdescription} -This function opens a window that best matches the parameters given to the -function. How well the resulting window matches the desired window depends -mostly on the available hardware and \OpenGL\ drivers. In general, -selecting a fullscreen mode has better chances of generating a close match -of buffers and channel sizes than does a normal desktop window, since \GLFW\ -can freely select from all the available video modes. A desktop window is -normally restricted to the video mode of the desktop. -\end{refdescription} - -\begin{refnotes} -For additional control of window properties, see -\textbf{glfwOpenWindowHint}. - -In fullscreen mode the mouse cursor is hidden by default and the -screensaver is prohibited from starting. In windowed mode the mouse -cursor is visible and screensavers are allowed to start. To change the -visibility of the mouse cursor, use \textbf{glfwEnable} or -\textbf{glfwDisable} with the argument GLFW\_MOUSE\_CURSOR. - -In order to determine the actual properties of an opened window, use -\textbf{glfwGetWindowParam} and \textbf{glfwGetWindowSize} (or -\textbf{glfwSetWindowSizeCallback}). - -On Microsoft Windows, if the executable has an icon resource named -\textbf{GLFW\_ICON}, it will be set as the icon for the window. If no such -icon is present, the \textbf{IDI\_WINLOGO} icon will be used instead. - -On Mac OS X the \GLFW\ window has no icon, but programs using \GLFW\ will use -the application bundle's icon. For more information on bundles, see the Bundle -Programming Guide provided by Apple. - -For information on how the availability of different platform-specific -extensions affect the behavior of this function, see appendix -\ref{chap:compatibility}. -\end{refnotes} - - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|l|p{7.0cm}|} \hline \raggedright -\textbf{Name} & \textbf{Default} & \textbf{Description} \\ \hline -GLFW\_REFRESH\_RATE & 0 & Vertical monitor refresh rate in Hz (only used for fullscreen windows). Zero means system default.\\ \hline -GLFW\_ACCUM\_RED\_BITS & 0 & Number of bits for the red channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_GREEN\_BITS & 0 & Number of bits for the green channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_BLUE\_BITS & 0 & Number of bits for the blue channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_ALPHA\_BITS & 0 & Number of bits for the alpha channel of the accumulation buffer.\\ \hline -GLFW\_AUX\_BUFFERS & 0 & Number of auxiliary buffers.\\ \hline -GLFW\_STEREO & GL\_FALSE & Specify if stereo rendering should be supported (can be GL\_TRUE or GL\_FALSE).\\ \hline -GLFW\_WINDOW\_NO\_RESIZE & GL\_FALSE & Specify whether the window can be resized by the user (not used for fullscreen windows).\\ \hline -GLFW\_FSAA\_SAMPLES & 0 & Number of samples to use for the multisampling buffer. Zero disables multisampling.\\ \hline -GLFW\_OPENGL\_VERSION\_MAJOR & 1 & Major number of the desired minimum \OpenGL\ version.\\ \hline -GLFW\_OPENGL\_VERSION\_MINOR & 1 & Minor number of the desired minimum \OpenGL\ version.\\ \hline -GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_FALSE & Specify whether the \OpenGL\ context should be forward-compatible (i.e. disallow legacy functionality). - This should only be used when requesting \OpenGL\ version 3.0 or above.\\ \hline -GLFW\_OPENGL\_DEBUG\_CONTEXT & GL\_FALSE & Specify whether a debug context should be created.\\ \hline -GLFW\_OPENGL\_PROFILE & 0 & The \OpenGL\ profile the context should implement, or zero to let the system choose. - Available profiles are GLFW\_OPENGL\_CORE\_PROFILE and GLFW\_OPENGL\_COMPAT\_PROFILE.\\ \hline -\end{tabular} -\end{center} -\caption{Targets for \textbf{glfwOpenWindowHint}} -\label{tab:winhints} -\end{table} - - -%------------------------------------------------------------------------- -\subsection{glfwOpenWindowHint} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwOpenWindowHint(int target, int hint) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{target}]\ \\ - Can be any of the tokens in the table \ref{tab:winhints}. -\item [\textit{hint}]\ \\ - An integer giving the value of the corresponding token (see table - \ref{tab:winhints}). -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets additional properties for a window that is to be opened. -For a hint to be registered, the function must be called before calling -\textbf{glfwOpenWindow}. When the \textbf{glfwOpenWindow} function is -called, any hints that were registered with the \textbf{glfwOpenWindowHint} -function are used for setting the corresponding window properties, and -then all hints are reset to their default values. -\end{refdescription} - -\begin{refnotes} -In order to determine the actual properties of an opened window, use -\textbf{glfwGetWindowParam} (after the window has been opened). - -GLFW\_STEREO is a hard constraint. If stereo rendering is requested, but no -stereo rendering capable pixel formats / framebuffer configs are available, -\textbf{glfwOpenWindow} will fail. - -The GLFW\_REFRESH\_RATE hint should be used with caution. Most -systems have default values for monitor refresh rates that are optimal -for the specific system. Specifying the refresh rate can override these -settings, which can result in suboptimal operation. The monitor may be -unable to display the resulting video signal, or in the worst case it may -even be damaged! - -The GLFW\_WINDOW\_NO\_RESIZE hint applies only to manual resizing by the user. -A window created with this hint enabled can still be resized by the application -by calling \textbf{glfwSetWindowSize}. - -The GLFW\_OPENGL\_VERSION\_MAJOR and GLFW\_OPENGL\_VERSION\_MINOR hints specify -the \OpenGL\ version that the created context must be compatible with, -\emph{not} the exact version to use. It is therefore perfectly safe to use the -default of version 1.1 for legacy code and you will still get -backwards-compatible contexts of version 3.0 and above when available. - -To make the behavior of the above version hints consistent across both modern -and legacy drivers, \textbf{glfwOpenWindow} will fail if the modern creation -mechanism (as specified in \textbf{WGL\_ARB\_create\_context} -and \textbf{GLX\_ARB\_create\_context}) is unavailable \emph{and} the created -context is of a version lower than the one that was requested. - -At the time of release, the exact meaning of what a "debug context" is (as -created using the GLFW\_OPENGL\_DEBUG\_CONTEXT hint) has yet to be defined by -the Khronos ARB WG. - -For information on how the availability of different extensions affect the -behavior of this function, see appendix \ref{chap:compatibility}. - -For full details on the workings of the \OpenGL\ version, forward-compatibility -and debug hints, see the specifications for \textbf{WGL\_ARB\_create\_context} -and \textbf{GLX\_ARB\_create\_context}, respectively. The relevant \GLFW\ -hints map very closely to their platform-specific counterparts. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwCloseWindow} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwCloseWindow(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function closes an opened window and destroys the associated \OpenGL\ -context. -\end{refdescription} - - -%------------------------------------------------------------------------- -\subsection{glfwSetWindowCloseCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetWindowCloseCallback(GLFWwindowclosefun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called when a user requests - that the window should be closed, typically by clicking the window close - icon (e.g. the cross in the upper right corner of a window under - Microsoft Windows), and on Mac OS X also when selecting \textbf{Quit} from - the application menu. The function should have the following C language - prototype: - - \texttt{int functionname(void);} - - Where \textit{functionname} is the name of the callback function. The - return value of the callback function indicates wether or not the window - close action should continue. If the function returns GL\_TRUE, the - window will be closed. If the function returns GL\_FALSE, the window - will not be closed. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for window close events. - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Window close events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. - -The \OpenGL\ context is still valid when this function is called. - -Note that the window close callback function is not called when -\textbf{glfwCloseWindow} is called, but only when the close request -comes from the window manager. - -Do \emph{not} call \textbf{glfwCloseWindow} from a window close -callback function. Close the window by returning GL\_TRUE from the -function. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetWindowTitle} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetWindowTitle(const char* title) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{title}]\ \\ - Pointer to a null terminated ISO~8859-1 (8-bit Latin~1) string that - holds the title of the window. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function changes the title of the opened window. -\end{refdescription} - -\begin{refnotes} -The title property of a window is often used in situations other than for -the window title, such as the title of an application icon when it is in -iconified state. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetWindowSize} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetWindowSize(int width, int height) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{width}]\ \\ - Width of the window. -\item [\textit{height}]\ \\ - Height of the window. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function changes the size of an opened window. The \textit{width} and -\textit{height} parameters denote the size of the client area of the -window (i.e. excluding any window borders and decorations). - -If the window is in fullscreen mode, the video mode will be changed to a -resolution that closest matches the width and height parameters (the -number of color bits will not be changed). -\end{refdescription} - -\begin{refnotes} -This function has no effect if the window is iconified. - -The \OpenGL\ context is guaranteed to be preserved after calling -\textbf{glfwSetWindowSize}, even if the video mode is changed. - -This function is not affected by the value of the GLFW\_WINDOW\_NO\_RESIZE -hint. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetWindowPos} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetWindowPos(int x, int y) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{x}]\ \\ - Horizontal position of the window, relative to the upper left corner - of the desktop. -\item [\textit{y}]\ \\ - Vertical position of the window, relative to the upper left corner of - the desktop. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function changes the position of an opened window. It does not have -any effect on a fullscreen window. -\end{refdescription} - -\begin{refnotes} -This function has no effect if the window is iconified. - -The behaviour of this function on multi-monitor systems is ill-defined. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetWindowSize} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwGetWindowSize(int* width, int* height) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{width}]\ \\ - Pointer to an integer that will hold the width of the window. -\item [\textit{height}]\ \\ - Pointer to an integer that will hold the height of the window. -\end{description} -\end{refparameters} - -\begin{refreturn} -The current width and height of the opened window is returned in the -\textit{width} and \textit{height} parameters, respectively. -\end{refreturn} - -\begin{refdescription} -This function is used for determining the size of an opened window. -The returned values are dimensions of the client area of the window -(i.e. excluding any window borders and decorations). -\end{refdescription} - -\begin{refnotes} -Even if the size of a fullscreen window does not change once the window -has been opened, it does not necessarily have to be the same as the size -that was requested using \textbf{glfwOpenWindow}. Therefor it is wise to -use this function to determine the true size of the window once it has -been opened. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetWindowSizeCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetWindowSizeCallback(GLFWwindowsizefun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called every time the - window size changes. The function should have the following C language - prototype: - - \texttt{void functionname(int width, int height);} - - Where \textit{functionname} is the name of the callback function, and - \textit{width} and \textit{height} are the dimensions of the window - client area. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for window size change events. - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Window size changes are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. - -When a callback function is set, it will be called with the current window -size before this function returns. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwIconifyWindow} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwIconifyWindow(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -Iconify a window. If the window is in fullscreen mode, then the desktop -video mode will be restored. -\end{refdescription} - - -%------------------------------------------------------------------------- -\subsection{glfwRestoreWindow} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwRestoreWindow(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -Restore an iconified window. If the window that is restored is in -fullscreen mode, then the fullscreen video mode will be restored. -\end{refdescription} - - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|p{9.5cm}|} \hline \raggedright -\textbf{Name} & \textbf{Description} \\ \hline -GLFW\_OPENED & GL\_TRUE if window is opened, else GL\_FALSE.\\ \hline -GLFW\_ACTIVE & GL\_TRUE if window has focus, else GL\_FALSE.\\ \hline -GLFW\_ICONIFIED & GL\_TRUE if window is iconified, else GL\_FALSE.\\ \hline -GLFW\_ACCELERATED & GL\_TRUE if window is hardware accelerated, else GL\_FALSE.\\ \hline -GLFW\_RED\_BITS & Number of bits for the red color component.\\ \hline -GLFW\_GREEN\_BITS & Number of bits for the green color component.\\ \hline -GLFW\_BLUE\_BITS & Number of bits for the blue color component.\\ \hline -GLFW\_ALPHA\_BITS & Number of bits for the alpha buffer.\\ \hline -GLFW\_DEPTH\_BITS & Number of bits for the depth buffer.\\ \hline -GLFW\_STENCIL\_BITS & Number of bits for the stencil buffer.\\ \hline -GLFW\_REFRESH\_RATE & Vertical monitor refresh rate in Hz. Zero indicates an unknown or a default refresh rate.\\ \hline -GLFW\_ACCUM\_RED\_BITS & Number of bits for the red channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_GREEN\_BITS & Number of bits for the green channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_BLUE\_BITS & Number of bits for the blue channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_ALPHA\_BITS & Number of bits for the alpha channel of the accumulation buffer.\\ \hline -GLFW\_AUX\_BUFFERS & Number of auxiliary buffers.\\ \hline -GLFW\_STEREO & GL\_TRUE if stereo rendering is supported, else GL\_FALSE.\\ \hline -GLFW\_WINDOW\_NO\_RESIZE & GL\_TRUE if the window cannot be resized by the user, else GL\_FALSE.\\ \hline -GLFW\_FSAA\_SAMPLES & Number of multisampling buffer samples. Zero indicated multisampling is disabled.\\ \hline -GLFW\_OPENGL\_VERSION\_MAJOR & Major number of the actual version of the context.\\ \hline -GLFW\_OPENGL\_VERSION\_MINOR & Minor number of the actual version of the context.\\ \hline -GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_TRUE if the context is forward-compatible, else GL\_FALSE.\\ \hline -GLFW\_OPENGL\_DEBUG\_CONTEXT & GL\_TRUE if the context is a debug context.\\ \hline -GLFW\_OPENGL\_PROFILE & The profile implemented by the context, or zero.\\ \hline -\end{tabular} -\end{center} -\caption{Window parameters for \textbf{glfwGetWindowParam}} -\label{tab:winparams} -\end{table} - - -%------------------------------------------------------------------------- -\subsection{glfwGetWindowParam} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetWindowParam(int param) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{param}]\ \\ - A token selecting which parameter the function should return (see - table \ref{tab:winparams}). -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the value the window parameter corresponding to the token -\textit{param}. Table \ref{tab:winparams} lists the available tokens. -\end{refreturn} - -\begin{refdescription} -This function is used for acquiring various properties of an opened window. -\end{refdescription} - -\begin{refnotes} -GLFW\_ACCELERATED is only supported under Windows. Other systems will -always return GL\_TRUE. Under Windows, GLFW\_ACCELERATED means that the -\OpenGL\ renderer is a 3rd party renderer, rather than the fallback -Microsoft software \OpenGL\ renderer. In other words, it is not a real -guarantee that the \OpenGL\ renderer is actually hardware accelerated. - -GLFW\_OPENGL\_VERSION\_MAJOR and GLFW\_OPENGL\_VERSION\_MINOR always return the -same values as those returned by \textbf{glfwGetGLVersion}. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSwapBuffers} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSwapBuffers(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function swaps the back and front color buffers of the window. If -GLFW\_AUTO\_POLL\_EVENTS is enabled (which is the default), -\textbf{glfwPollEvents} is called after swapping the front and back -buffers. -\end{refdescription} - -\begin{refnotes} -In previous versions of \GLFW , \textbf{glfwPollEvents} was called -\emph{before} buffer swap. This was changed in order to decrease input -lag but may affect code that relied on the former behavior. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSwapInterval} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSwapInterval(int interval) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{interval}]\ \\ - Minimum number of monitor vertical retraces between each buffer swap - performed by \textbf{glfwSwapBuffers}. If \textit{interval} is zero, - buffer swaps will not be synchronized to the vertical refresh of the - monitor (also known as 'VSync off'). -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function selects the minimum number of monitor vertical retraces that -should occur between two buffer swaps. If the selected swap interval is -one, the rate of buffer swaps will never be higher than the vertical -refresh rate of the monitor. If the selected swap interval is zero, the -rate of buffer swaps is only limited by the speed of the software and -the hardware. -\end{refdescription} - -\begin{refnotes} -This function will only have an effect on hardware and drivers that support -user selection of the swap interval. ATI drivers in particular have been known -to ignore this setting. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetWindowRefreshCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetWindowRefreshCallback(GLFWwindowrefreshfun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called when the window client - area needs to be refreshed. The function should have the following C - language prototype: - - \texttt{void functionname(void);} - - Where \textit{functionname} is the name of the callback function. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for window refresh events, which occurs when -any part of the window client area has been damaged, and needs to be repainted -(for instance, if a part of the window that was previously occluded by another -window has become visible). - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Window refresh events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. - -Modern windowing systems using hardware compositing, such as Aqua, Aero and -Compiz, very rarely need to refresh the contents of windows, so the specified -callback will very rarely be called on such systems. -\end{refnotes} - - -%------------------------------------------------------------------------- -\pagebreak -\section{Video Modes} -Since \GLFW\ supports video mode changes when using a fullscreen window, -it also provides functionality for querying which video modes are -supported on a system. - - -%------------------------------------------------------------------------- -\subsection{glfwGetVideoModes} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetVideoModes(GLFWvidmode* list, int maxcount) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{list}]\ \\ - A vector of \textit{GLFWvidmode} structures, which will be filled out - by the function. -\item [\textit{maxcount}]\ \\ - Maximum number of video modes that \textit{list} vector can hold. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the number of detected video modes (this number -will never exceed \textit{maxcount}). The \textit{list} vector is -filled out with the video modes that are supported by the system. -\end{refreturn} - -\begin{refdescription} -This function returns a list of supported video modes. Each video mode is -represented by a \textit{GLFWvidmode} structure, which has the following -definition: - -\begin{lstlisting} -typedef struct { - int Width, Height; // Video resolution - int RedBits; // Number of red bits - int GreenBits; // Number of green bits - int BlueBits; // Number of blue bits -} GLFWvidmode; -\end{lstlisting} -\end{refdescription} - -\begin{refnotes} -The returned list is sorted, first by color depth ($RedBits + GreenBits + -BlueBits$), and then by resolution ($Width \times Height$), with the -lowest resolution, fewest bits per pixel mode first. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetDesktopMode} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwGetDesktopMode(GLFWvidmode* mode) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{mode}]\ \\ - Pointer to a \textit{GLFWvidmode} structure, which will be filled out - by the function. -\end{description} -\end{refparameters} - -\begin{refreturn} -The \textit{GLFWvidmode} structure pointed to by \textit{mode} is filled -out with the desktop video mode. -\end{refreturn} - -\begin{refdescription} -This function returns the desktop video mode in a \textit{GLFWvidmode} -structure. See \textbf{glfwGetVideoModes} for a definition of the -\textit{GLFWvidmode} structure. -\end{refdescription} - -\begin{refnotes} -The color depth of the desktop display is always reported as the number -of bits for each individual color component (red, green and blue), even -if the desktop is not using an RGB or RGBA color format. For instance, an -indexed 256 color display may report \textit{RedBits} = 3, -\textit{GreenBits} = 3 and \textit{BlueBits} = 2, which adds up to 8 bits -in total. - -The desktop video mode is the video mode used by the desktop at the time -the \GLFW\ window was opened, \textit{not} the current video mode (which -may differ from the desktop video mode if the \GLFW\ window is a -fullscreen window). -\end{refnotes} - - -%------------------------------------------------------------------------- -\pagebreak -\section{Input Handling} -\GLFW\ supports three channels of user input: keyboard input, mouse input -and joystick input. - -Keyboard and mouse input can be treated either as events, using callback -functions, or as state, using functions for polling specific keyboard and -mouse states. Regardless of which method is used, all keyboard and mouse -input is collected using window event polling. - -Joystick input is asynchronous to the keyboard and mouse input, and does -not require event polling for keeping up to date joystick information. -Also, joystick input is independent of any window, so a window does not -have to be opened for joystick input to be used. - - -%------------------------------------------------------------------------- -\subsection{glfwPollEvents} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwPollEvents(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function is used for polling for events, such as user input and -window resize events. Upon calling this function, all window states, -keyboard states and mouse states are updated. If any related callback -functions are registered, these are called during the call to -\textbf{glfwPollEvents}. -\end{refdescription} - -\begin{refnotes} -\textbf{glfwPollEvents} is called implicitly from \textbf{glfwSwapBuffers} -if GLFW\_AUTO\_POLL\_EVENTS is enabled (as it is by default). Thus, if -\textbf{glfwSwapBuffers} is called frequently, which is normally the case, -there is no need to call \textbf{glfwPollEvents}. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwWaitEvents} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwWaitEvents(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function is used for waiting for events, such as user input and -window resize events. Upon calling this function, the calling thread will -be put to sleep until any event appears in the event queue. When events -are available, they will be processed just as they are processed by -\textbf{glfwPollEvents}. - -If there are any events in the queue when the function is called, the -function will behave exactly like \textbf{glfwPollEvents} (i.e. process -all messages and then return, without blocking the calling thread). -\end{refdescription} - -\begin{refnotes} -It is guaranteed that \textbf{glfwWaitEvents} will wake up on any event that -can be processed by \textbf{glfwPollEvents}. However, \GLFW\ receives many -events that are only processed internally and the function may behave -differently on different systems. Do not make any assumptions about when or why -\textbf{glfwWaitEvents} will return. -\end{refnotes} - - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|l|} \hline \raggedright -\textbf{Name} & \textbf{Description} \\ \hline -GLFW\_KEY\_\textit{X} & Letter (\textit{X} can be in the range A..Z)\\ \hline -GLFW\_KEY\_\textit{n} & Number (\textit{n} can be in the range 0..9)\\ \hline -GLFW\_KEY\_SPACE & Space\\ \hline -GLFW\_KEY\_MINUS & Minus (-)\\ \hline -GLFW\_KEY\_EQUAL & Equal (=)\\ \hline -GLFW\_KEY\_LEFT\_BRACKET & Left bracket ([)\\ \hline -GLFW\_KEY\_RIGHT\_BRACKET & Right bracket (])\\ \hline -GLFW\_KEY\_GRAVE\_ACCENT & Grave accent (`)\\ \hline -GLFW\_KEY\_APOSTROPHE & Apostrophe (')\\ \hline -GLFW\_KEY\_COMMA & Comma (,)\\ \hline -GLFW\_KEY\_PERIOD & Period (.)\\ \hline -GLFW\_KEY\_SEMICOLON & Semicolon (;)\\ \hline -GLFW\_KEY\_SLASH & Slash ($/$)\\ \hline -GLFW\_KEY\_BACKSLASH & Backslash ($\backslash$)\\ \hline -GLFW\_KEY\_WORLD\_1 & Non-US character no. 1\\ \hline -GLFW\_KEY\_WORLD\_2 & Non-US character no. 2\\ \hline -\end{tabular} -\end{center} -\caption[Key codes for printable keys]{Key codes for printable keys. The keys are named according to the US keyboard layout, but represent physical keys (so for instance, GLFW\_KEY\_Z represents the same physical key, regardless of the system input language).} -\label{tab:keys1} -\end{table} - -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|l|} \hline \raggedright -\textbf{Name} & \textbf{Description} \\ \hline -GLFW\_KEY\_ESCAPE & Escape\\ \hline -GLFW\_KEY\_F\textit{n} & Function key \textit{n} (\textit{n} can be in the range 1..25)\\ \hline -GLFW\_KEY\_UP & Cursor up\\ \hline -GLFW\_KEY\_DOWN & Cursor down\\ \hline -GLFW\_KEY\_LEFT & Cursor left\\ \hline -GLFW\_KEY\_RIGHT & Cursor right\\ \hline -GLFW\_KEY\_LEFT\_SHIFT & Left shift key\\ \hline -GLFW\_KEY\_RIGHT\_SHIFT & Right shift key\\ \hline -GLFW\_KEY\_LEFT\_CTRL & Left control key\\ \hline -GLFW\_KEY\_RIGHT\_CTRL & Right control key\\ \hline -GLFW\_KEY\_LEFT\_ALT & Left alternate function key\\ \hline -GLFW\_KEY\_RIGHT\_ALT & Right alternate function key\\ \hline -GLFW\_KEY\_LEFT\_SUPER & Left super key, WinKey, or command key\\ \hline -GLFW\_KEY\_RIGHT\_SUPER & Right super key, WinKey, or command key\\ \hline -GLFW\_KEY\_TAB & Tabulator\\ \hline -GLFW\_KEY\_ENTER & Enter\\ \hline -GLFW\_KEY\_BACKSPACE & Backspace\\ \hline -GLFW\_KEY\_INSERT & Insert\\ \hline -GLFW\_KEY\_DELETE & Delete\\ \hline -GLFW\_KEY\_PAGE\_UP & Page up\\ \hline -GLFW\_KEY\_PAGE\_DOWN & Page down\\ \hline -GLFW\_KEY\_HOME & Home\\ \hline -GLFW\_KEY\_END & End\\ \hline -GLFW\_KEY\_KP\_\textit{n} & Keypad numeric key \textit{n} (\textit{n} can be in the range 0..9)\\ \hline -GLFW\_KEY\_KP\_DIVIDE & Keypad divide ($\div$)\\ \hline -GLFW\_KEY\_KP\_MULTIPLY & Keypad multiply ($\times$)\\ \hline -GLFW\_KEY\_KP\_SUBTRACT & Keypad subtract ($-$)\\ \hline -GLFW\_KEY\_KP\_ADD & Keypad add ($+$)\\ \hline -GLFW\_KEY\_KP\_DECIMAL & Keypad decimal (. or ,)\\ \hline -GLFW\_KEY\_KP\_EQUAL & Keypad equal (=)\\ \hline -GLFW\_KEY\_KP\_ENTER & Keypad enter\\ \hline -GLFW\_KEY\_NUM\_LOCK & Num lock\\ \hline -GLFW\_KEY\_CAPS\_LOCK & Caps lock\\ \hline -GLFW\_KEY\_SCROLL\_LOCK & Scroll lock\\ \hline -GLFW\_KEY\_PAUSE & Pause key\\ \hline -GLFW\_KEY\_MENU & Menu key\\ \hline -\end{tabular} -\end{center} -\caption{Key codes for function keys} -\label{tab:keys2} -\end{table} - - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|l|} \hline \raggedright -\textbf{Name} & \textbf{Description} \\ \hline -GLFW\_MOUSE\_BUTTON\_LEFT & Left mouse button (button 1) \\ \hline -GLFW\_MOUSE\_BUTTON\_RIGHT & Right mouse button (button 2) \\ \hline -GLFW\_MOUSE\_BUTTON\_MIDDLE & Middle mouse button (button 3) \\ \hline -GLFW\_MOUSE\_BUTTON\_\textit{n} & Mouse button \textit{n} (\textit{n} can be in the range 1..8)\\ \hline -\end{tabular} -\end{center} -\caption{Valid mouse button identifiers} -\label{tab:mousebuttons} -\end{table} - - -%------------------------------------------------------------------------- -\subsection{glfwGetKey} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetKey(int key) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{key}]\ \\ - A keyboard key identifier, which can be any of the key codes in tables - \ref{tab:keys1} and \ref{tab:keys2}. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns GLFW\_PRESS if the key is held down, or GLFW\_RELEASE -if the key is not held down. -\end{refreturn} - -\begin{refdescription} -This function queries the current state of a specific keyboard key. The -physical location of each key depends on the system keyboard layout -setting. -\end{refdescription} - -\begin{refnotes} -The constant GLFW\_KEY\_SPACE is equal to 32, which is the ISO~8859-1 code -for space. This is the only named \GLFW\ key identifier with a value in the -ISO~8859-1 range. - -Not all key codes are supported on all systems. Also, while some keys are -available on some keyboard layouts, they may not be available on other -keyboard layouts. - -For systems that do not distinguish between left and right versions of -modifier keys (shift, alt and control), the left version is used (e.g. -GLFW\_KEY\_LSHIFT). - -A window must be opened for the function to have any effect, and -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) must be called before any keyboard -events are recorded and reported by \textbf{glfwGetKey}. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetMouseButton} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetMouseButton(int button) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{button}]\ \\ - A mouse button identifier, which can be one of the mouse button - identifiers listed in table \ref{tab:mousebuttons}. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns GLFW\_PRESS if the mouse button is held down, or -GLFW\_RELEASE if the mouse button is not held down. -\end{refreturn} - -\begin{refdescription} -This function queries the current state of a specific mouse button. -\end{refdescription} - -\begin{refnotes} -A window must be opened for the function to have any effect, and -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) must be called before any mouse button -events are recorded and reported by \textbf{glfwGetMouseButton}. - -GLFW\_MOUSE\_BUTTON\_LEFT is equal to GLFW\_MOUSE\_BUTTON\_1. -GLFW\_MOUSE\_BUTTON\_RIGHT is equal to GLFW\_MOUSE\_BUTTON\_2. -GLFW\_MOUSE\_BUTTON\_MIDDLE is equal to GLFW\_MOUSE\_BUTTON\_3. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetMousePos} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwGetMousePos(int* xpos, int* ypos) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{xpos}]\ \\ - Pointer to an integer that will be set to the horizontal position of the - mouse cursor. -\item [\textit{ypos}]\ \\ - Pointer to an integer that will be set to the vertical position of the mouse cursor. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the current mouse cursor position in \textit{xpos} and -\textit{ypos}. -\end{refreturn} - -\begin{refdescription} -This function returns the current mouse position. If the cursor is not -hidden, the mouse position is the cursor position, relative to the upper -left corner of the window and with the Y-axis down. If the cursor is hidden, -the mouse position is a virtual absolute position, not limited to any -boundaries except to those implied by the maximum number that can be -represented by a signed integer. -\end{refdescription} - -\begin{refnotes} -A window must be opened for the function to have any effect, and -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) must be called before any mouse -movements are recorded and reported by \textbf{glfwGetMousePos}. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetMousePos} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetMousePos(int xpos, int ypos) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{xpos}]\ \\ - Horizontal position of the mouse. -\item [\textit{ypos}]\ \\ - Vertical position of the mouse. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function changes the position of the mouse. If the cursor is visible (not -disabled), the cursor will be moved to the specified position, relative to the -upper left corner of the window client area and with the Y-axis down. If the -cursor is hidden (disabled), only the mouse position that is reported by \GLFW\ -is changed. -\end{refdescription} - - -%------------------------------------------------------------------------- -\subsection{glfwGetMouseWheel} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetMouseWheel(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -The function returns the current mouse wheel position. -\end{refreturn} - -\begin{refdescription} -This function returns the current mouse wheel position. The mouse wheel can -be thought of as a third mouse axis, which is available as a separate -wheel or up/down stick on some mice. -\end{refdescription} - -\begin{refnotes} -A window must be opened for the function to have any effect, and -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) must be called before any mouse wheel -movements are recorded and reported by \textbf{glfwGetMouseWheel}. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetMouseWheel} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetMouseWheel(int pos) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{pos}]\ \\ - Position of the mouse wheel. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function changes the position of the mouse wheel. -\end{refdescription} - - -%------------------------------------------------------------------------- -\subsection{glfwSetKeyCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetKeyCallback(GLFWkeyfun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called every time a key is - pressed or released. The function should have the following C language - prototype: - - \texttt{void functionname(int key, int action);} - - Where \textit{functionname} is the name of the callback function, - \textit{key} is a key code (see tables \ref{tab:keys1} and \ref{tab:keys2}), - and \textit{action} is either GLFW\_PRESS or GLFW\_RELEASE. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for keyboard key events. The callback function -is called every time the state of a single key is changed (from released to -pressed or vice versa). The reported keys are unaffected by any modifiers (such -as shift or alt) and each modifier is reported as a separate key. - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Keyboard key events are not intended for text input and many languages -will not be able to be input using it. Use Unicode character events for -text input instead. - -Keyboard events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetCharCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetCharCallback(GLFWcharfun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called every time a - printable character is generated by the keyboard. The function should - have the following C language prototype: - - \texttt{void functionname(int character, int action);} - - Where \textit{functionname} is the name of the callback function, - \textit{character} is a Unicode (ISO~10646) character, and - \textit{action} is either GLFW\_PRESS or GLFW\_RELEASE. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for keyboard character events. The callback -function is called every time a key that results in a printable Unicode -character is pressed or released. Characters are affected by modifiers (such -as shift or alt). - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Character events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. - -Control characters such as tab and carriage return are not reported to -the character callback function, since they are not part of the Unicode -character set. Use the key callback function for such events (see -\textbf{glfwSetKeyCallback}). - -The Unicode character set supports character codes above 255, so never -cast a Unicode character to an eight bit data type (e.g. the C language -'char' type) without first checking that the character code is less than -256. Also note that Unicode character codes 0 to 255 are equal to -ISO~8859-1 (Latin~1). -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetMouseButtonCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetMouseButtonCallback(GLFWmousebuttonfun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called every time a mouse - button is pressed or released. The function should have the following C - language prototype: - - \texttt{void functionname(int button, int action);} - - Where \textit{functionname} is the name of the callback function, - \textit{button} is a mouse button identifier (see table - \ref{tab:mousebuttons} on page \pageref{tab:mousebuttons}), and - \textit{action} is either GLFW\_PRESS or GLFW\_RELEASE. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for mouse button events. - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Mouse button events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. - -GLFW\_MOUSE\_BUTTON\_LEFT is equal to GLFW\_MOUSE\_BUTTON\_1. -GLFW\_MOUSE\_BUTTON\_RIGHT is equal to GLFW\_MOUSE\_BUTTON\_2. -GLFW\_MOUSE\_BUTTON\_MIDDLE is equal to GLFW\_MOUSE\_BUTTON\_3. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetMousePosCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetMousePosCallback(GLFWmouseposfun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called every time the mouse - is moved. The function should have the following C language prototype: - - \texttt{void functionname(int x, int y);} - - Where \textit{functionname} is the name of the callback function, and - \textit{x} and \textit{y} are the mouse coordinates (see - \textbf{glfwGetMousePos} for more information on mouse coordinates). - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for mouse motion events. - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Mouse motion events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetMouseWheelCallback} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetMouseWheelCallback(GLFWmousewheelfun cbfun) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{cbfun}]\ \\ - Pointer to a callback function that will be called every time the mouse - wheel is moved. The function should have the following C language - prototype: - - \texttt{void functionname(int pos);} - - Where \textit{functionname} is the name of the callback function, and - \textit{pos} is the mouse wheel position. - - If \textit{cbfun} is NULL, any previously set callback function - will be unset. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the callback for mouse wheel events. - -A window has to be opened for this function to have any effect. -\end{refdescription} - -\begin{refnotes} -Mouse wheel events are recorded continuously, but only reported when -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled) is called. -\end{refnotes} - - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|l|}\hline \raggedright -\textbf{Name} & \textbf{Return value}\\ \hline -GLFW\_PRESENT & GL\_TRUE if the joystick is connected, else GL\_FALSE.\\ \hline -GLFW\_AXES & Number of axes supported by the joystick.\\ \hline -GLFW\_BUTTONS & Number of buttons supported by the joystick.\\ \hline -\end{tabular} -\end{center} -\caption{Joystick parameters for \textbf{glfwGetJoystickParam}} -\label{tab:joyparams} -\end{table} - - -%------------------------------------------------------------------------- -\subsection{glfwGetJoystickParam} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetJoystickParam(int joy, int param) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{joy}]\ \\ - A joystick identifier, which should be GLFW\_JOYSTICK\_\textit{n}, where - \textit{n} is in the range 1 to 16. -\item [\textit{param}]\ \\ - A token selecting which parameter the function should return (see table - \ref{tab:joyparams}). -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns different parameters depending on the value of -\textit{param}. Table \ref{tab:joyparams} lists valid \textit{param} -values, and their corresponding return values. -\end{refreturn} - -\begin{refdescription} -This function is used for acquiring various properties of a joystick. -\end{refdescription} - -\begin{refnotes} -The joystick information is updated every time the function is called. - -No window has to be opened for joystick information to be available. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetJoystickPos} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetJoystickPos(int joy, float* pos, int numaxes) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{joy}]\ \\ - A joystick identifier, which should be GLFW\_JOYSTICK\_\textit{n}, where - \textit{n} is in the range 1 to 16. -\item [\textit{pos}]\ \\ - An array that will hold the positional values for all requested axes. -\item [\textit{numaxes}]\ \\ - Specifies how many axes should be returned. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the number of actually returned axes. This is the -minimum of \textit{numaxes} and the number of axes supported by the -joystick. If the joystick is not supported or connected, the function will -return 0 (zero). -\end{refreturn} - -\begin{refdescription} -This function queries the current position of one or more axes of a -joystick. The positional values are returned in an array, where the first -element represents the first axis of the joystick (normally the X axis). -Each position is in the range -1.0 to 1.0. Where applicable, the positive -direction of an axis is right, forward or up, and the negative direction -is left, back or down. - -If \textit{numaxes} exceeds the number of axes supported by the joystick, -or if the joystick is not available, the unused elements in the -\textit{pos} array will be set to 0.0 (zero). -\end{refdescription} - -\begin{refnotes} -The joystick state is updated every time the function is called, so there -is no need to call \textbf{glfwPollEvents} or \textbf{glfwWaitEvents} for -joystick state to be updated. - -Use \textbf{glfwGetJoystickParam} to retrieve joystick capabilities, such -as joystick availability and number of supported axes. - -No window has to be opened for joystick input to be available. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetJoystickButtons} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwGetJoystickButtons(int joy, unsigned char* buttons, - int numbuttons) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{joy}]\ \\ - A joystick identifier, which should be GLFW\_JOYSTICK\_\textit{n}, where - \textit{n} is in the range 1 to 16. -\item [\textit{buttons}]\ \\ - An array that will hold the button states for all requested buttons. -\item [\textit{numbuttons}]\ \\ - Specifies how many buttons should be returned. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the number of actually returned buttons. This is the -minimum of \textit{numbuttons} and the number of buttons supported by the -joystick. If the joystick is not supported or connected, the function will -return 0 (zero). -\end{refreturn} - -\begin{refdescription} -This function queries the current state of one or more buttons of a -joystick. The button states are returned in an array, where the first -element represents the first button of the joystick. Each state can be -either GLFW\_PRESS or GLFW\_RELEASE. - -If \textit{numbuttons} exceeds the number of buttons supported by the -joystick, or if the joystick is not available, the unused elements in the -\textit{buttons} array will be set to GLFW\_RELEASE. -\end{refdescription} - -\begin{refnotes} -The joystick state is updated every time the function is called, so there -is no need to call \textbf{glfwPollEvents} or \textbf{glfwWaitEvents} for -joystick state to be updated. - -Use \textbf{glfwGetJoystickParam} to retrieve joystick capabilities, such -as joystick availability and number of supported buttons. - -No window has to be opened for joystick input to be available. -\end{refnotes} - - -%------------------------------------------------------------------------- -\pagebreak -\section{Timing} - -%------------------------------------------------------------------------- -\subsection{glfwGetTime} - -\textbf{C language syntax} -\begin{lstlisting} -double glfwGetTime(void) -\end{lstlisting} - -\begin{refparameters} -none -\end{refparameters} - -\begin{refreturn} -The function returns the value of the high precision timer. The time is -measured in seconds, and is returned as a double precision floating point -value. -\end{refreturn} - -\begin{refdescription} -This function returns the state of a high precision timer. Unless the timer -has been set by the \textbf{glfwSetTime} function, the time is measured as -the number of seconds that have passed since \textbf{glfwInit} was called. -\end{refdescription} - -\begin{refnotes} -The resolution of the timer depends on which system the program is running -on. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwSetTime} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwSetTime(double time) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{time}]\ \\ - Time (in seconds) that the timer should be set to. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -This function sets the current time of the high precision timer to the -specified time. Subsequent calls to \textbf{glfwGetTime} will be relative -to this time. The time is given in seconds. -\end{refdescription} - - -%------------------------------------------------------------------------- -\pagebreak -\section{OpenGL Extension Support} -One of the great features of \OpenGL\ is its support for extensions, which -allow independent vendors to supply non-standard functionality in their -\OpenGL\ implementations. As the mechanism for querying extensions varies -among systems, \GLFW\ provides an operating system independent interface for -querying \OpenGL\ version, extensions and entry points. - - -%------------------------------------------------------------------------- -\subsection{glfwExtensionSupported} - -\textbf{C language syntax} -\begin{lstlisting} -int glfwExtensionSupported(const char* extension) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{extension}]\ \\ - A null terminated ISO~8859-1 string containing the name of an \OpenGL\ - extension. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns GL\_TRUE if the extension is supported. Otherwise it -returns GL\_FALSE. -\end{refreturn} - -\begin{refdescription} -This function does a string search in the list of supported \OpenGL\ -extensions to find if the specified extension is listed. -\end{refdescription} - -\begin{refnotes} -An \OpenGL\ context must be created before this function can be called -(i.e. an \OpenGL\ window must have been opened with -\textbf{glfwOpenWindow}). - -In addition to checking for \OpenGL\ extensions, \GLFW\ also checks for -extensions in the operating system ``glue API'', such as WGL extensions -under Microsoft Windows and GLX extensions under the X Window System. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetProcAddress} - -\textbf{C language syntax} -\begin{lstlisting} -void* glfwGetProcAddress(const char* procname) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{procname}]\ \\ - A null terminated ISO~8859-1 string containing the name of an \OpenGL\ - extension function. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the address of the specified \OpenGL\ function, if it -is available. Otherwise NULL is returned. -\end{refreturn} - -\begin{refdescription} -This function acquires the pointer to an \OpenGL\ extension function. Some -(but not all) \OpenGL\ extensions define new API functions, which are -usually not available through normal linking. It is therefore necessary to -get access to those API functions at runtime. -\end{refdescription} - -\begin{refnotes} -An \OpenGL\ context must be created before this function can be called -(i.e. an \OpenGL\ window must have been opened with -\textbf{glfwOpenWindow}). - -Some systems do not support dynamic function pointer retrieval, in which -case \textbf{glfwGetProcAddress} will always return NULL. -\end{refnotes} - - -%------------------------------------------------------------------------- -\subsection{glfwGetGLVersion} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwGetGLVersion(int* major, int* minor, int* rev) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{major}]\ \\ - Pointer to an integer that will hold the major version number. -\item [\textit{minor}]\ \\ - Pointer to an integer that will hold the minor version number. -\item [\textit{rev}]\ \\ - Pointer to an integer that will hold the revision. -\end{description} -\end{refparameters} - -\begin{refreturn} -The function returns the major and minor version numbers and the revision -for the currently used \OpenGL\ implementation. -\end{refreturn} - -\begin{refdescription} -This function returns the \OpenGL\ implementation version. This is a -convenient function that parses the version number information at the beginning -of the string returned by calling \texttt{glGetString(~GL\_VERSION~)}. The -\OpenGL\ version information can be used to determine what functionality is -supported by the used \OpenGL\ implementation. -\end{refdescription} - -\begin{refnotes} -An \OpenGL\ context must be created before this function can be called -(i.e. an \OpenGL\ window must have been opened with -\textbf{glfwOpenWindow}). -\end{refnotes} - - -%------------------------------------------------------------------------- -\pagebreak -\section{Miscellaneous} - - -%------------------------------------------------------------------------- -\subsection{glfwEnable/glfwDisable} - -\textbf{C language syntax} -\begin{lstlisting} -void glfwEnable(int token) -void glfwDisable(int token) -\end{lstlisting} - -\begin{refparameters} -\begin{description} -\item [\textit{token}]\ \\ - A value specifying a feature to enable or disable. Valid tokens are - listed in table \ref{tab:enable}. -\end{description} -\end{refparameters} - -\begin{refreturn} -none -\end{refreturn} - -\begin{refdescription} -\textbf{glfwEnable} is used to enable a certain feature, while -\textbf{glfwDisable} is used to disable it. Below follows a description of -each feature. -\end{refdescription} - - -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|p{5.0cm}|p{3.0cm}|} \hline \raggedright -\textbf{Name} & \textbf{Controls} & \textbf{Default}\\ \hline -\hyperlink{lnk:autopollevents}{GLFW\_AUTO\_POLL\_EVENTS} & Automatic event polling when \textbf{glfwSwapBuffers} is called & Enabled\\ \hline -\hyperlink{lnk:keyrepeat}{GLFW\_KEY\_REPEAT} & Keyboard key repeat & Disabled\\ \hline -\hyperlink{lnk:mousecursor}{GLFW\_MOUSE\_CURSOR} & Mouse cursor visibility & Enabled in windowed mode. Disabled in fullscreen mode.\\ \hline -\hyperlink{lnk:stickykeys}{GLFW\_STICKY\_KEYS} & Keyboard key ``stickiness'' & Disabled\\ \hline -\hyperlink{lnk:stickymousebuttons}{GLFW\_STICKY\_MOUSE\_BUTTONS} & Mouse button ``stickiness'' & Disabled\\ \hline -\hyperlink{lnk:systemkeys}{GLFW\_SYSTEM\_KEYS} & Special system key actions & Enabled\\ \hline -\end{tabular} -\end{center} -\caption{Tokens for \textbf{glfwEnable}/\textbf{glfwDisable}} -\label{tab:enable} -\end{table} - - -\bigskip\begin{mysamepage}\hypertarget{lnk:autopollevents}{} -\textbf{GLFW\_AUTO\_POLL\_EVENTS}\\ -When GLFW\_AUTO\_POLL\_EVENTS is enabled, \textbf{glfwPollEvents} is -automatically called each time that \textbf{glfwSwapBuffers} is called, -immediately after the buffer swap itself. - -When GLFW\_AUTO\_POLL\_EVENTS is disabled, calling -\textbf{glfwSwapBuffers} will not result in a call to -\textbf{glfwPollEvents}. This can be useful if for example \textbf{glfwSwapBuffers} -needs to be called from within a callback function, since calling -\textbf{glfwPollEvents} from a callback function is not allowed. -\end{mysamepage} - - -\bigskip\begin{mysamepage}\hypertarget{lnk:keyrepeat}{} -\textbf{GLFW\_KEY\_REPEAT}\\ -When GLFW\_KEY\_REPEAT is enabled, the key and character callback -functions are called repeatedly when a key is held down long enough -(according to the system key repeat configuration). - -When GLFW\_KEY\_REPEAT is disabled, the key and character callback -functions are only called once when a key is pressed (and once when it is -released). -\end{mysamepage} - - -\bigskip\begin{mysamepage}\hypertarget{lnk:mousecursor}{} -\textbf{GLFW\_MOUSE\_CURSOR}\\ -When GLFW\_MOUSE\_CURSOR is enabled, the mouse cursor is visible, and -mouse coordinates are relative to the upper left corner of the client area -of the \GLFW\ window. The coordinates are limited to the client area of -the window. - -When GLFW\_MOUSE\_CURSOR is disabled, the mouse cursor is invisible, and -mouse coordinates are not limited to the drawing area of the window. It is -as if the mouse coordinates are received directly from the mouse, without -being restricted or manipulated by the windowing system. -\end{mysamepage} - - -\bigskip\begin{mysamepage}\hypertarget{lnk:stickykeys}{} -\textbf{GLFW\_STICKY\_KEYS}\\ -When GLFW\_STICKY\_KEYS is enabled, keys which are pressed will not be -released until they are physically released and checked with -\textbf{glfwGetKey}. This behavior makes it possible to catch keys that -were pressed and then released again between two calls to -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or -\textbf{glfwSwapBuffers}, which would otherwise have been reported as -released. Care should be taken when using this mode, since keys that are -not checked with \textbf{glfwGetKey} will never be released. Note also -that enabling GLFW\_STICKY\_KEYS does not affect the behavior of the -keyboard callback functionality. - -When GLFW\_STICKY\_KEYS is disabled, the status of a key that is reported -by \textbf{glfwGetKey} is always the physical state of the key. Disabling -GLFW\_STICKY\_KEYS also clears the sticky information for all keys. -\end{mysamepage} - - -\bigskip\begin{mysamepage}\hypertarget{lnk:stickymousebuttons}{} -\textbf{GLFW\_STICKY\_MOUSE\_BUTTONS}\\ -When GLFW\_STICKY\_MOUSE\_BUTTONS is enabled, mouse buttons that are pressed -will not be released until they are physically released and checked with -\textbf{glfwGetMouseButton}. This behavior makes it possible to catch mouse -buttons which were pressed and then released again between two calls to -\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or \textbf{glfwSwapBuffers} -(with GLFW\_AUTO\_POLL\_EVENTS enabled), which would otherwise have been -reported as released. Care should be taken when using this mode, since mouse -buttons that are not checked with \textbf{glfwGetMouseButton} will never be -released. Note also that enabling GLFW\_STICKY\_MOUSE\_BUTTONS does not affect -the behavior of the mouse button callback functionality. - -When GLFW\_STICKY\_MOUSE\_BUTTONS is disabled, the status of a mouse -button that is reported by \textbf{glfwGetMouseButton} is always the -physical state of the mouse button. Disabling GLFW\_STICKY\_MOUSE\_BUTTONS -also clears the sticky information for all mouse buttons. -\end{mysamepage} - - -\bigskip\begin{mysamepage}\hypertarget{lnk:systemkeys}{} -\textbf{GLFW\_SYSTEM\_KEYS}\\ -When GLFW\_SYSTEM\_KEYS is enabled, pressing standard system key -combinations, such as \texttt{Alt+Tab} under Windows, will give the normal -behavior. Note that when \texttt{Alt+Tab} is issued under Windows in this -mode so that the \GLFW\ application is deselected when \GLFW\ is operating -in fullscreen mode, the \GLFW\ application window will be minimized and -the video mode will be set to the original desktop mode. When the \GLFW\ -application is re-selected, the video mode will be set to the \GLFW\ video -mode again. - -When GLFW\_SYSTEM\_KEYS is disabled, pressing standard system key -combinations will have no effect, since those key combinations are blocked -by \GLFW . This mode can be useful in situations when the \GLFW\ program -must not be interrupted (normally for games in fullscreen mode). -\end{mysamepage} - - -%------------------------------------------------------------------------- -% GLFW Standards Conformance -%------------------------------------------------------------------------- -\appendix -\chapter{GLFW Compatibility} -\label{chap:compatibility} -\thispagestyle{fancy} - -This chapter describes the various API extensions used by this version of -\GLFW . It lists what are essentially implementation details, but which are -nonetheless vital knowledge for developers wishing to deploy their applications -on machines with varied specifications. - -Note that the information in this appendix is not a part of the API -specification but merely list some of the preconditions for certain parts of -the API to function on a given machine. As such, any part of it may change in -future versions without this being considered a breaking API change. - -%------------------------------------------------------------------------- -\section{ICCCM and EWMH Conformance} - -As \GLFW\ uses \textbf{Xlib}, directly, without any intervening toolkit -library, it has sole responsibility for interacting well with the many and -varied window managers in use on Unix-like systems. In order for applications -and window managers to work well together, a number of standards and -conventions have been developed that regulate behavior outside the scope of the -X11 API; most importantly the \textbf{Inter-Client Communication Conventions -Manual} (ICCCM) and \textbf{Extended Window Manager Hints} (EWMH) standards. - -\GLFW\ uses the ICCCM \textbf{WM\_DELETE\_WINDOW} protocol to intercept the user -attempting to close the \GLFW\ window. If the running window manager does not -support this protocol, the close callback will never be called. - -\GLFW\ uses the EWMH \textbf{\_NET\_WM\_PING} protocol, allowing the window -manager notify the user when the application has stopped responding, i.e. when -it has ceased to process events. If the running window manager does not -support this protocol, the user will not be notified if the application locks -up. - -\GLFW\ uses the EWMH \textbf{\_NET\_WM\_STATE} protocol to tell the window -manager to make the \GLFW\ window fullscreen. If the running window manager -does not support this protocol, fullscreen windows may not work properly. -\GLFW\ has a fallback code path in case this protocol is unavailable, but every -window manager behaves slightly differently in this regard. - -%------------------------------------------------------------------------- -\section{GLX Extensions} - -The \textbf{GLX} API is used to create \OpenGL\ contexts on Unix-like systems -using the X Window System. - -\GLFW\ uses the \textbf{GLXFBConfig} API to enumerate and select framebuffer -pixel formats. This requires either \textbf{GLX} 1.3 or greater, or the -\textbf{GLX\_SGIX\_fbconfig} extension. Where both are available, the SGIX -extension is preferred. If neither is available, \GLFW\ will be unable to open -windows. - -% This paragraph repeated almost verbatim below -\GLFW\ uses the \textbf{GLX\_SGI\_swap\_control} extension to provide vertical -retrace synchronization (or ``vsync''). Where this extension is unavailable, -calling \textbf{glfwSwapInterval} will have no effect. - -% This paragraph repeated almost verbatim below -\GLFW\ uses the \textbf{GLX\_ARB\_multisample} extension to create contexts -with multisampling anti-aliasing. Where this extension is unavailable, the -GLFW\_FSAA\_SAMPLES hint will have no effect. - -% This paragraph repeated almost verbatim below -\GLFW\ uses the \textbf{GLX\_ARB\_create\_context} extension when available, -even when creating \OpenGL\ contexts of version 2.1 and below. Where this -extension is unavailable, the GLFW\_OPENGL\_VERSION\_MAJOR and -GLFW\_OPENGL\_VERSION\_MINOR hints will only be partially supported, the -GLFW\_OPENGL\_DEBUG\_CONTEXT hint will have no effect, and setting the -GLFW\_OPENGL\_PROFILE or GLFW\_FORWARD\_COMPAT hints to a non-zero value will -cause \textbf{glfwOpenWindow} to fail. - -% This paragraph repeated almost verbatim below -\GLFW\ uses the \textbf{GLX\_ARB\_create\_context\_profile} extension to -provide support for context profiles. Where this extension is unavailable, -setting the GLFW\_OPENGL\_PROFILE hint to anything but zero will cause -\textbf{glfwOpenWindow} to fail. - -%------------------------------------------------------------------------- -\section{WGL Extensions} - -The \textbf{WGL} API is used to create \OpenGL\ contexts on Microsoft Windows -and other implementations of the Win32 API, such as Wine. - -\GLFW\ uses either the \textbf{WGL\_EXT\_extension\_string} or the -\textbf{WGL\_ARB\_extension\_string} extension to check for the presence of all -other \textbf{WGL} extensions listed below. If both are available, the EXT one -is preferred. If neither is available, no other extensions are used and many -\GLFW\ features related to context creation will have no effect or cause errors -when used. - -% This paragraph repeated almost verbatim above -\GLFW\ uses the \textbf{WGL\_EXT\_swap\_control} extension to provide vertical -retrace synchronization (or ``vsync''). Where this extension is unavailable, -calling \textbf{glfwSwapInterval} will have no effect. - -% This paragraph repeated almost verbatim above -\GLFW\ uses the \textbf{WGL\_ARB\_pixel\_format} and -\textbf{WGL\_ARB\_multisample} extensions to create contexts with multisampling -anti-aliasing. Where these extensions are unavailable, the GLFW\_FSAA\_SAMPLES -hint will have no effect. - -% This paragraph repeated almost verbatim above -\GLFW\ uses the \textbf{WGL\_ARB\_create\_context} extension when available, -even when creating \OpenGL\ contexts of version 2.1 and below. Where this -extension is unavailable, the GLFW\_OPENGL\_VERSION\_MAJOR and -GLFW\_OPENGL\_VERSION\_MINOR hints will only be partially supported, the -GLFW\_OPENGL\_DEBUG\_CONTEXT hint will have no effect, and setting the -GLFW\_OPENGL\_PROFILE or GLFW\_FORWARD\_COMPAT hints to a non-zero value will -cause \textbf{glfwOpenWindow} to fail. - -% This paragraph repeated almost verbatim above -\GLFW\ uses the \textbf{WGL\_ARB\_create\_context\_profile} extension to -provide support for context profiles. Where this extension is unavailable, -setting the GLFW\_OPENGL\_PROFILE hint to anything but zero will cause -\textbf{glfwOpenWindow} to fail. - -%------------------------------------------------------------------------- -\section{OpenGL 3.0+ on Mac OS X} - -At the time of writing, Mac OS X does not support OpenGL 3.0 or above. -Because of this, the GLFW\_OPENGL\_VERSION\_MAJOR and -GLFW\_OPENGL\_VERSION\_MINOR hints will fail if given a version above 2.1, the -GLFW\_OPENGL\_DEBUG\_CONTEXT hint will have no effect, and setting the -GLFW\_OPENGL\_PROFILE or GLFW\_FORWARD\_COMPAT hints to a non-zero value will -cause \textbf{glfwOpenWindow} to fail. - - -\end{document} diff --git a/docs/glfwug.tex b/docs/glfwug.tex deleted file mode 100644 index 4f769a2c..00000000 --- a/docs/glfwug.tex +++ /dev/null @@ -1,1313 +0,0 @@ -%------------------------------------------------------------------------- -% GLFW Users Guide -% API Version: 3.0 -%------------------------------------------------------------------------- - -% Document class -\documentclass[a4paper,11pt,oneside]{report} - -% Document title and API version -\newcommand{\glfwdoctype}[1][0]{Users Guide} -\newcommand{\glfwapiver}[1][0]{3.0} - -% Common document settings and macros -\input{glfwdoc.sty} - -% PDF specific document settings -\hypersetup{pdftitle={GLFW Users Guide}} -\hypersetup{pdfauthor={Marcus Geelnard}} -\hypersetup{pdfkeywords={GLFW,OpenGL,guide,manual}} - - -%------------------------------------------------------------------------- -% Document body -%------------------------------------------------------------------------- - -\begin{document} - -\pagestyle{plain} - -% Title page -\glfwmaketitle - -% Summary, trademarks and table of contents -\pagenumbering{roman} -\setcounter{page}{1} - -%------------------------------------------------------------------------- -% Summary and Trademarks -%------------------------------------------------------------------------- -\chapter*{Summary} - -This document is a users guide for the \GLFW\ API that gives a practical -introduction to using \GLFW . For a more detailed description of the -\GLFW\ API you should refer to the \textit{GLFW Reference Manual}. -\vspace{5cm} - -\large -Trademarks - -\small -OpenGL and IRIX are registered trademarks of Silicon Graphics, Inc.\linebreak -Microsoft and Windows are registered trademarks of Microsoft Corporation.\linebreak -Mac OS is a registered trademark of Apple Computer, Inc.\linebreak -Linux is a registered trademark of Linus Torvalds.\linebreak -FreeBSD is a registered trademark of Wind River Systems, Inc.\linebreak -Solaris is a trademark of Sun Microsystems, Inc.\linebreak -UNIX is a registered trademark of The Open Group.\linebreak -X Window System is a trademark of The Open Group.\linebreak -POSIX is a trademark of IEEE.\linebreak -Truevision, TARGA and TGA are registered trademarks of Truevision, Inc.\linebreak -IBM is a registered trademark of IBM Corporation.\linebreak - -All other trademarks mentioned in this document are the property of their respective owners. -\normalsize - - -%------------------------------------------------------------------------- -% Table of contents -%------------------------------------------------------------------------- -\tableofcontents -\pagebreak - - -% Document chapters starts here... -\pagenumbering{arabic} -\setcounter{page}{1} - -\pagestyle{fancy} - - -%------------------------------------------------------------------------- -% Introduction -%------------------------------------------------------------------------- -\chapter{Introduction} -\thispagestyle{fancy} -\GLFW\ is a portable API (Application Program Interface) that handles -operating system specific tasks related to \OpenGL\ programming. While -\OpenGL\ in general is portable, easy to use and often results in tidy and -compact code, the operating system specific mechanisms that are required -to set up and manage an \OpenGL\ window are quite the opposite. \GLFW\ tries -to remedy this by providing the following functionality: - -\begin{itemize} -\item Opening and managing an \OpenGL\ window. -\item Keyboard, mouse and joystick input. -\item High precision time input. -\item Support for querying and using \OpenGL\ extensions. -\end{itemize} -\vspace{18pt} - -All this functionality is implemented as a set of easy-to-use functions, -which makes it possible to write an \OpenGL\ application framework in just a -few lines of code. The \GLFW\ API is operating system and platform independent, -making it very simple to port \GLFW\ based \OpenGL\ applications between the -supported platforms. - -Currently supported platforms are: -\begin{itemize} -\item Microsoft Windows\textsuperscript{\textregistered} -\item Unix\textsuperscript{\textregistered} or Unix­-like systems running the -X Window System\texttrademark with GLX version 1.3 or later -\item Mac OS X\textsuperscript{\textregistered} 10.5 and later, using Cocoa\footnote{Support for joysticks missing at the time of writing.} -\end{itemize} - -There is also deprecated support for Mac OS X versions 10.3 and 10.4, using the Carbon API. - - -%------------------------------------------------------------------------- -% Getting Started -%------------------------------------------------------------------------- -\chapter{Getting Started} -\thispagestyle{fancy} -In this chapter you will learn how to write a simple \OpenGL\ application -using \GLFW . We start by initializing \GLFW , then we open a window and -read some user keyboard input. - - -%------------------------------------------------------------------------- -\section{Initializing GLFW} -Before using any of the \GLFW\ functions, it is necessary to call -\textbf{glfwInit}. It initializes the parts of \GLFW\ that are not dependent on -a window, such as time and joystick input. The C syntax is: - -\begin{lstlisting} -int glfwInit(void) -\end{lstlisting} - -\textbf{glfwInit} returns GL\_TRUE if initialization succeeded, or -GL\_FALSE if it failed. - -When your application is done using \GLFW , typically at the very end of -the program, you should call \textbf{glfwTerminate}. The C syntax is: - -\begin{lstlisting} -void glfwTerminate(void) -\end{lstlisting} - -This releases any resources allocated by GLFW and closes the window if it is -open. After this call, you must call \textbf{glfwInit} again before using any -\GLFW\ functions). - -%------------------------------------------------------------------------- -\section{Opening An OpenGL Window} -Opening an \OpenGL\ window is done with the \textbf{glfwOpenWindow} function. -The function takes nine arguments, which are used to describe the following -properties of the requested window: - -\begin{itemize} -\item Window dimensions (width and height) in pixels. -\item Color and alpha buffer bit depth. -\item Depth buffer (Z-buffer) bit depth. -\item Stencil buffer bit depth. -\item Whether to use fullscreen or windowed mode. -\end{itemize} - -The C language syntax for \textbf{glfwOpenWindow} is: -\begin{lstlisting} -int glfwOpenWindow(int width, int height, - int redbits, int greenbits, int bluebits, - int alphabits, int depthbits, int stencilbits, - int mode) -\end{lstlisting} - -\textbf{glfwOpenWindow} returns GL\_TRUE if the window was opened -correctly, or GL\_FALSE if \GLFW\ failed to open the window. - -\GLFW\ tries to open a window that best matches the requested parameters. -Some parameters may be omitted by setting them to zero, which will result -in \GLFW\ either using a default value, or the related functionality to be -disabled. For instance, if \textit{width} and \textit{height} are both -zero, \GLFW\ will use a window resolution of 640x480. If -\textit{depthbits} is zero, the opened window may not have a depth buffer. - -The \textit{mode} argument is used to specify if the window is to be a -fullscreen window or a regular window. - -If \textit{mode} is GLFW\_FULLSCREEN, the window will cover the entire -screen and no window border or decorations will be visible. If possible, the -video mode will be changed to the mode that closest matches the \textit{width}, -\textit{height}, \textit{redbits}, \textit{greenbits}, \textit{bluebits} and -\textit{alphabits} arguments. Furthermore, the mouse pointer will be hidden, -and screensavers are prohibited. This is usually the best mode for games and -demos. - -If \textit{mode} is GLFW\_WINDOW, the window will be opened as a normal, -decorated window on the desktop. The mouse pointer will not be hidden and -screensavers are allowed to be activated. - -To close the window, you can either use \textbf{glfwTerminate}, as -described earlier, or you can use the more explicit approach by calling -\textbf{glfwCloseWindow}, which has the C syntax: - -\begin{lstlisting} -void glfwCloseWindow(void) -\end{lstlisting} - -Note that you do not need to call \textbf{glfwTerminate} and \textbf{glfwInit} -before opening a new window after having closed the current one using -\textbf{glfwCloseWindow}. - - -%------------------------------------------------------------------------- -\section{Using Keyboard Input} -\GLFW\ provides several means for receiving user input, which will be -discussed in more detail in chapter \ref{par:inputhandling}. One of the -simplest ways of checking for keyboard input is to use the function -\textbf{glfwGetKey}: - -\begin{lstlisting} -int glfwGetKey(int key) -\end{lstlisting} - -It queries the current status of individual keyboard keys. The argument -\textit{key} specifies which key to check, and it must be a valid GLFW key code -(see the \textit{GLFW Reference Manual} for a list of key codes). -\textbf{glfwGetKey} returns GLFW\_PRESS if the key is currently held down, or -GLFW\_RELEASE if the key is not being held down. For example: - -\begin{lstlisting} -A_pressed = glfwGetKey(GLFW_KEY_A); -esc_pressed = glfwGetKey(GLFW_KEY_ESCAPE); -\end{lstlisting} - -In order for \textbf{glfwGetKey} to have any effect, you need to poll for -input events on a regular basis. This can be done in one of two ways: - -\begin{enumerate} -\item Implicitly by calling \textbf{glfwSwapBuffers} often. -\item Explicitly by calling \textbf{glfwPollEvents} often. -\end{enumerate} - -In general you do not have to care about this, since you will normally -call \textbf{glfwSwapBuffers} to swap front and back rendering buffers -every animation frame anyway. If, however, this is not the case, you -should call \textbf{glfwPollEvents} in the order of 10-100 times per -second in order for \GLFW\ to maintain an up to date input state. - - -%------------------------------------------------------------------------- -\section{Putting It Together: A Minimal GLFW Application} -Now that you know how to initialize \GLFW , open a window and poll for -keyboard input, let us exemplify this with a simple \OpenGL\ program: - -\begin{lstlisting} -#include -#include - -int main(void) -{ - int running = GL_TRUE; - - // Initialize GLFW - if (!glfwInit()) - exit(EXIT_FAILURE); - - // Open an OpenGL window - if (!glfwOpenWindow(300,300, 0,0,0,0,0,0, GLFW_WINDOW)) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - // Main loop - while (running) - { - // OpenGL rendering goes here... - glClear(GL_COLOR_BUFFER_BIT); - - // Swap front and back rendering buffers - glfwSwapBuffers(); - - // Check if ESC key was pressed or window was closed - running = !glfwGetKey(GLFW_KEY_ESCAPE) && - glfwGetWindowParam(GLFW_OPENED); - } - - // Close window and terminate GLFW - glfwTerminate(); - - // Exit program - exit(EXIT_SUCCESS); -} -\end{lstlisting} - -The program opens a 300x300 window and runs in a loop until the escape key -is pressed, or the window was closed. All the \OpenGL\ ``rendering'' that -is done in this example is to clear the window. - - -%------------------------------------------------------------------------- -% Window Operations -%------------------------------------------------------------------------- -\chapter{Window Operations} -\thispagestyle{fancy} -In this chapter, you will learn more about window related \GLFW\ -functionality, including setting and getting window properties, buffer -swap control and video mode querying. - - -%------------------------------------------------------------------------- -\section{Setting Window Properties} -In the previous chapter the \textbf{glfwOpenWindow} function was -described, which specifies the sizes of the color, alpha, depth and -stencil buffers. It is also possible to request a specific minimum OpenGL -version, multisampling anti-aliasing, an accumulation buffer, stereo -rendering and more by using the \textbf{glfwOpenWindowHint} function: - -\begin{lstlisting} -void glfwOpenWindowHint(int target, int hint) -\end{lstlisting} - -The \textit{target} argument can be one of the constants listed in table~ -\ref{tab:winhints}, and \textit{hint} is the value to assign to the -specified target. - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|l|p{7.0cm}|} \hline \raggedright -\textbf{Name} & \textbf{Default} & \textbf{Description} \\ \hline -GLFW\_REFRESH\_RATE & 0 & Vertical monitor refresh rate in Hz (only used for fullscreen windows). Zero means system default.\\ \hline -GLFW\_ACCUM\_RED\_BITS & 0 & Number of bits for the red channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_GREEN\_BITS & 0 & Number of bits for the green channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_BLUE\_BITS & 0 & Number of bits for the blue channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_ALPHA\_BITS & 0 & Number of bits for the alpha channel of the accumulation buffer.\\ \hline -GLFW\_AUX\_BUFFERS & 0 & Number of auxiliary buffers.\\ \hline -GLFW\_STEREO & GL\_FALSE & Specify if stereo rendering should be supported (can be GL\_TRUE or GL\_FALSE).\\ \hline -GLFW\_WINDOW\_NO\_RESIZE & GL\_FALSE & Specify whether the window can be resized by the user (not used for fullscreen windows).\\ \hline -GLFW\_FSAA\_SAMPLES & 0 & Number of samples to use for the multisampling buffer. Zero disables multisampling.\\ \hline -GLFW\_OPENGL\_VERSION\_MAJOR & 1 & Major number of the desired minimum OpenGL version.\\ \hline -GLFW\_OPENGL\_VERSION\_MINOR & 1 & Minor number of the desired minimum OpenGL version.\\ \hline -GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_FALSE & Specify whether the OpenGL context should be forward-compatible (i.e. disallow legacy functionality). - This should only be used when requesting OpenGL version 3.0 or above.\\ \hline -GLFW\_OPENGL\_DEBUG\_CONTEXT & GL\_FALSE & Specify whether a debug context should be created.\\ \hline -GLFW\_OPENGL\_PROFILE & 0 & The OpenGL profile the context should implement, or zero to let the system choose. - Available profiles are GLFW\_OPENGL\_CORE\_PROFILE and GLFW\_OPENGL\_COMPAT\_PROFILE.\\ \hline -\end{tabular} -\end{center} -\caption{Targets for \textbf{glfwOpenWindowHint}} -\label{tab:winhints} -\end{table} -%------------------------------------------------------------------------- - -For a hint to have any effect, the \textbf{glfwOpenWindowHint} function -must be called before opening the window with the \textbf{glfwOpenWindow} -function. - -To request an accumulation buffer, set the GLFW\_ACCUM\_x\_BITS targets to -values greater than zero (usually eight or sixteen bits per component). -To request auxiliary buffers, set the GLFW\_AUX\_BUFFERS target to a value -greater than zero. To request a stereo rendering capable window, set the -GLFW\_STEREO target to GL\_TRUE. - -If you want to enable fullscreen antialiasing, set the GLFW\_FSAA\_SAMPLES -target to a value greater than zero. If the windowing system is unable to -fulfil the request, \GLFW\ will degrade gracefully and disable FSAA if necessary. - -The GLFW\_REFRESH\_RATE target should be used with caution, since it may -result in suboptimal operation, or even a blank or damaged screen. - -If you want to create a forward-compatible \OpenGL\ context, set the -GLFW\_OPENGL\_FORWARD\_COMPAT hint to GL\_TRUE. Note that such contexts are -only available for \OpenGL\ version 3.0 and above, so you will need to specify -a valid minimum version using the GLFW\_OPENGL\_VERSION\_MAJOR and -GLFW\_OPENGL\_VERSION\_MINOR hints. - -If you want to create a context using the core profile as available in \OpenGL\ -version 3.2 and above, set the GLFW\_OPENGL\_PROFILE hint accordingly. Note that -as above you have to set a valid minimum version for this to work. - -Also note that at the time of this release, Mac OS X did not support \OpenGL\ -version 3.0 or above; thus GLFW cannot create contexts of versions above 2.1 -on that platform. - -Besides the parameters that are given with the \textbf{glfwOpenWindow} and -\textbf{glfwOpenWindowHint} functions, a few more properties of a window -can be changed after the window has been opened, namely the window title, -window size, and window position. - -To change the window title of an open window, use the -\textbf{glfwSetWindowTitle} function: - -\begin{lstlisting} -void glfwSetWindowTitle(const char* title) -\end{lstlisting} - -\textit{title} is a null terminated ISO~8859-1 (8-bit Latin~1) string that -will be used as the window title. It will also be used as the application -name (for instance in the application list when using \texttt{Alt+Tab} -under Windows, or as the icon name when the window is iconified under -the X Window System). The default window name is ``GLFW Window'', which -will be used unless \textbf{glfwSetWindowTitle} is called after the window -has been opened. - -To change the size of a window, call \textbf{glfwSetWindowSize}: - -\begin{lstlisting} -void glfwSetWindowSize(int width, int height) -\end{lstlisting} - -Where \textit{width} and \textit{height} are the new dimensions of the -window. - -To change the position of a window, call \textbf{glfwSetWindowPos}: - -\begin{lstlisting} -void glfwSetWindowPos(int x, int y) -\end{lstlisting} - -Where \textit{x} and \textit{y} are the new desktop coordinates of the -window. This function does not have any effect when in fullscreen mode. - - -%------------------------------------------------------------------------- -\section{Getting Window Properties} -When opening a window, the opened window will not necessarily have the -requested properties, so you should always check the parameters that your -application relies on (e.g. number of stencil bits) using -\textbf{glfwGetWindowParam}, which has the C syntax: - -\begin{lstlisting} -int glfwGetWindowParam(int param) -\end{lstlisting} - -The argument \textit{param} can be one of the tokens listed in table -\ref{tab:winparams}, and the return value is an integer holding the -requested value. - -%------------------------------------------------------------------------- -\begin{table}[p] -\begin{center} -\begin{tabular}{|l|p{9.5cm}|} \hline \raggedright -\textbf{Name} & \textbf{Description} \\ \hline -GLFW\_OPENED & GL\_TRUE if window is opened, else GL\_FALSE.\\ \hline -GLFW\_ACTIVE & GL\_TRUE if window has focus, else GL\_FALSE.\\ \hline -GLFW\_ICONIFIED & GL\_TRUE if window is iconified, else GL\_FALSE.\\ \hline -GLFW\_ACCELERATED & GL\_TRUE if window is hardware accelerated, else GL\_FALSE.\\ \hline -GLFW\_RED\_BITS & Number of bits for the red color component.\\ \hline -GLFW\_GREEN\_BITS & Number of bits for the green color component.\\ \hline -GLFW\_BLUE\_BITS & Number of bits for the blue color component.\\ \hline -GLFW\_ALPHA\_BITS & Number of bits for the alpha buffer.\\ \hline -GLFW\_DEPTH\_BITS & Number of bits for the depth buffer.\\ \hline -GLFW\_STENCIL\_BITS & Number of bits for the stencil buffer.\\ \hline -GLFW\_REFRESH\_RATE & Vertical monitor refresh rate in Hz. Zero indicates an unknown or a default refresh rate.\\ \hline -GLFW\_ACCUM\_RED\_BITS & Number of bits for the red channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_GREEN\_BITS & Number of bits for the green channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_BLUE\_BITS & Number of bits for the blue channel of the accumulation buffer.\\ \hline -GLFW\_ACCUM\_ALPHA\_BITS & Number of bits for the alpha channel of the accumulation buffer.\\ \hline -GLFW\_AUX\_BUFFERS & Number of auxiliary buffers.\\ \hline -GLFW\_STEREO & GL\_TRUE if stereo rendering is supported, else GL\_FALSE.\\ \hline -GLFW\_WINDOW\_NO\_RESIZE & GL\_TRUE if the window cannot be resized by the user, else GL\_FALSE.\\ \hline -GLFW\_FSAA\_SAMPLES & Number of multisampling buffer samples. Zero indicated multisampling is disabled.\\ \hline -GLFW\_OPENGL\_VERSION\_MAJOR & Major number of the actual version of the context.\\ \hline -GLFW\_OPENGL\_VERSION\_MINOR & Minor number of the actual version of the context.\\ \hline -GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_TRUE if the context is forward-compatible, else GL\_FALSE.\\ \hline -GLFW\_OPENGL\_DEBUG\_CONTEXT & GL\_TRUE if the context is a debug context.\\ \hline -GLFW\_OPENGL\_PROFILE & The profile implemented by the context, or zero.\\ \hline -\end{tabular} -\end{center} -\caption{Window parameters for \textbf{glfwGetWindowParam}} -\label{tab:winparams} -\end{table} -%------------------------------------------------------------------------- - -Another useful function is \textbf{glfwSetWindowSizeCallback}, which -specifies a user function that will be called every time the window size -has changed. The C syntax is: - -\begin{lstlisting} -void glfwSetWindowSizeCallback(GLFWwindowsizefun cbfun) -\end{lstlisting} - -The user function \textit{fun} should be of the type: - -\begin{lstlisting} -void fun(int width, int height) -\end{lstlisting} - -The first argument passed to the user function is the width of the window, -and the second argument is the height of the window. Here is an example -of how to use a window size callback function: - -\begin{lstlisting} -int windowWidth, windowHeight; - -void WindowResize(int width, int height) -{ - windowWidth = width; - windowHeight = height; -} - -int main(void) -{ - ... - glfwSetWindowSizeCallback(WindowResize); - ... -} -\end{lstlisting} - -Using a callback function for getting the window size is mostly useful for -windowed applications, since the window size may be changed at any time by -the user. It can also be used to determine the actual fullscreen -resolution. - -An alternative to using a callback function for getting the window size, -is to use the function \textbf{glfwGetWindowSize}: - -\begin{lstlisting} -void glfwGetWindowSize(int* width, int* height) -\end{lstlisting} - -The variables pointed to by \textit{width} and \textit{height} are set to the -current window dimensions. Note that either of these may be NULL; that -argument is then ignored. - - -%------------------------------------------------------------------------- -\section{Buffer Swapping} -\GLFW\ windows are always double buffered. That means that you have two -rendering buffers; a front buffer and a back buffer. The front buffer is -the buffer that is being displayed, and the back buffer is not displayed. -\OpenGL\ lets you select which of these two buffers you want to render to -(with the \textbf{glDrawBuffer} command), but the default (and preferred) -rendering buffer is the back buffer. This way you will avoid flickering -and artifacts caused by graphics being only partly drawn at the same time -as the video raster beam is displaying the graphics on the monitor. - -When an entire frame has been rendered to the back buffer, it is time to -swap the back and the front buffers in order to display the rendered -frame, and begin rendering a new frame. This is done with the command -\textbf{glfwSwapBuffers}. The C syntax is: - -\begin{lstlisting} -void glfwSwapBuffers(void) -\end{lstlisting} - -After swapping the front and back rendering buffers, \textbf{glfwSwapBuffers} -by default calls \textbf{glfwPollEvents}\footnote{This behavior can be disabled -by calling \textbf{glfwDisable} with the argument GLFW\_AUTO\_POLL\_EVENTS.}. -This is to ensure frequent polling of events, such as keyboard and mouse input, -and window reshaping events. Even if a given application does not use input -events, without frequent polling of events (at \emph{least} once every few -seconds), most modern window systems will flag the application as unresponsive -and may suggest that the user terminate it. - -Sometimes it can be useful to select when the buffer swap will occur. With -the function \textbf{glfwSwapInterval} it is possible to select the -minimum number of vertical retraces the video raster line should do before -swapping the buffers: - -\begin{lstlisting} -void glfwSwapInterval(int interval) -\end{lstlisting} - -If \textit{interval} is zero, the swap will take place immediately when -\textbf{glfwSwapBuffers} is called, without waiting for a vertical retrace -(also known as ``vsync off''). Otherwise at least \textit{interval} -retraces will pass between each buffer swap (also known as ``vsync on''). -Using a swap interval of zero can be useful for benchmarking purposes, -when it is not desirable to measure the time it takes to wait for the -vertical retrace. However, a swap interval of 1 generally gives better -visual quality. - -It should be noted that not all \OpenGL\ implementations and hardware support -this function, in which case \textbf{glfwSwapInterval} will have no effect. ATI -Radeon cards under Microsoft Windows are especially notorious in this regard. -Sometimes it is only possible to affect the swap interval through driver -settings (e.g. the display settings under Windows, or as an environment -variable setting under Unix). - - -%------------------------------------------------------------------------- -\section{Querying Video Modes} -Although \GLFW\ generally does a good job at selecting a suitable video -mode for you when you open a fullscreen window, it is sometimes useful to -know exactly which modes are available on a certain system. For example, -you may want to present the user with a list of video modes to select -from. To get a list of available video modes, you can use the function -\textbf{glfwGetVideoModes}: - -\begin{lstlisting} -int glfwGetVideoModes(GLFWvidmode* list, int maxcount) -\end{lstlisting} - -The argument \textit{list} is a vector of GLFWvidmode structures, and -\textit{maxcount} is the maximum number of video modes that your vector can -hold. \textbf{glfwGetVideoModes} will return the number of video modes detected -on the system, up to \textit{maxcount}. - -The GLFWvidmode structure looks like this: - -\begin{lstlisting} -typedef struct { - int Width, Height; // Video resolution - int RedBits; // Red bits per pixel - int GreenBits; // Green bits per pixel - int BlueBits; // Blue bits per pixel -} GLFWvidmode; -\end{lstlisting} - -Here is an example of retrieving all available video modes: - -\begin{lstlisting} -int nummodes; -GLFWvidmode list[200]; -nummodes = glfwGetVideoModes(list, 200); -\end{lstlisting} - -The returned list is sorted, first by color depth ($RedBits + GreenBits + -BlueBits$), and then by resolution ($Width\times Height$), with the -lowest resolution, fewest bits per pixel mode first. - -To get the desktop video mode, use the function -\textbf{glfwGetDesktopMode}: - -\begin{lstlisting} -void glfwGetDesktopMode(GLFWvidmode* mode) -\end{lstlisting} - -The function returns the resolution and color depth of the user desktop in -the mode structure. Note that the user desktop mode is independent of the -current video mode if a \GLFW\ fullscreen window has been opened. - - -%------------------------------------------------------------------------- -% Input Handling -%------------------------------------------------------------------------- -\chapter{Input Handling} -\label{par:inputhandling} -\thispagestyle{fancy} -In this chapter you will learn how to use keyboard, mouse and joystick -input, using either polling or callback functions. - - -%------------------------------------------------------------------------- -\section{Event Polling} -The first thing to know about input handling in \GLFW\ is that all -keyboard and mouse input is collected by checking for input events. This -has do be done manually by calling either \textbf{glfwPollEvents} or -\textbf{glfwSwapBuffers} (which implicitly calls \textbf{glfwPollEvents} -for you). Normally this is not a cause for concern, as -\textbf{glfwSwapBuffers} is called every frame, which should be often -enough (about 10-100 times per second for a normal \OpenGL\ application) that -the window will feel responsive. - -One exception is when an application is updating its view only in response to input. -In this case the \textbf{glfwWaitEvents} is useful, as it blocks the calling -thread until an event arrives. The refresh callback, set with -\textbf{glfwSetWindowRefreshCallback}, may also be useful for such -applications, especially on unbuffered window systems. - -If it is not desirable that \textbf{glfwPollEvents is} called implicitly -from \textbf{glfwSwapBuffers}, call \textbf{glfwDisable} with the argument -GLFW\_AUTO\_POLL\_EVENTS. - -Note that event polling is not needed for joystick input, since all -relevant joystick state is gathered every time a joystick function is -called. - - -%------------------------------------------------------------------------- -\section{Keyboard Input} -\GLFW\ provides three mechanisms for getting keyboard input: - -\begin{itemize} -\item Manually polling the state of individual keys. -\item Automatically receive new key state for any key, using a callback - function. -\item Automatically receive characters, using a callback function. -\end{itemize} - -Depending on what the keyboard input will be used for, different methods may be -preferred. The main difference between the two last methods is that while -characters are affected by modifier keys (such as shift), key state is -independent of any modifier keys. Also, special keys (such as function keys, -cursor keys and modifier keys) are not reported to the character callback -function. - -%------------------------------------------------------------------------- -\subsection{Key state} -To check if a key is held down or not at any given moment, use the -function \textbf{glfwGetKey}: - -\begin{lstlisting} -int glfwGetKey(int key) -\end{lstlisting} - -It queries the current status of individual keyboard keys. The argument -\textit{key} specifies which key to check, which must be a valid GLFW key code. -\textbf{glfwGetKey} returns GLFW\_PRESS (or 1) if the key is currently -held down, or GLFW\_RELEASE (or 0) if the key is not being held down. - -In most situations, it may be useful to know if a key has been pressed and -released between two calls to \textbf{glfwGetKey} (especially if the -animation is fairly slow, which may allow the user to press and release a -key between two calls to \textbf{glfwGetKey}). This can be accomplished by -enabling sticky keys, which is done by calling \textbf{glfwEnable} with -the argument GLFW\_STICKY\_KEYS, as in the following example: - -\begin{lstlisting} -glfwEnable(GLFW_STICKY_KEYS); -\end{lstlisting} - -When sticky keys are enabled, a key will not be released until it is -checked with \textbf{glfwGetKey}. To disable sticky keys, call -\textbf{glfwDisable} witht the argument GLFW\_STICKY\_KEYS. Then all keys -that are not currently held down will be released and future key releases -will take place immediately when the user releases the key without -waiting for \textbf{glfwGetKey} to check the key. By default sticky keys -are disabled. - -Sticky keys are often very useful and should be used in most cases where -\textbf{glfwGetKey} is used. There is however a danger involved with -enabling sticky keys, and that is that keys that are pressed by the user -but are not checked with \textbf{glfwGetKey}, may remain ``pressed'' for a -very long time. A typical situation where this may be dangerous is in a -program that consists of two or more sections (e.g. a menu section and a -game section). If the first section enables sticky keys but does not check -for keys which the second section checks for, there is a potential of -recording many key presses in the first section that will be detected in -the second section. To avoid this problem, always disable sticky keys -before leaving a section of a program. - -A usually better alternative to using \textbf{glfwGetKey} is to register a -keyboard input callback function with \textbf{glfwSetKeyCallback}: - -\begin{lstlisting} -void glfwSetKeyCallback(GLFWkeyfun cbfun) -\end{lstlisting} - -The argument \textit{fun} is a pointer to a callback function. The -callback function shall take two integer arguments. The first is the key -identifier, and the second is the new key state, which can be GLFW\_PRESS -or GLFW\_RELEASE. To unregister a callback function, call -\textbf{glfwSetKeyCallback} with \textit{fun} = NULL. - -Using the callback function, you can be sure not to miss any key press or -release events, regardless of how many may have occurred during the last frame. -It also encourages event-based design, where the application responds only to -actual events instead of having to poll for every supported event. - -%------------------------------------------------------------------------- -\subsection{Character input} -If the keyboard is to be used as a text input device (e.g. in a user -dialog) rather than as a set of independent buttons, a character callback -function is more suitable. To register a character callback function, use -\textbf{glfwSetCharCallback}: - -\begin{lstlisting} -void glfwSetCharCallback(GLFWcharfun cbfun) -\end{lstlisting} - -The argument \textit{fun} is a pointer to a callback function. The -callback function shall take two integer arguments. The first is a Unicode -code point, and the second is GLFW\_PRESS if the key that generated -the character was pressed, or GLFW\_RELEASE if it was released. To -unregister a callback function, call \textbf{glfwSetCharCallback} with -\textit{fun} = NULL. - -The Unicode character set is an international standard for encoding -characters. It is much more comprehensive than seven or eight bit -character sets (e.g. US-ASCII and Latin~1), and includes characters for -most written languages in the world. It should be noted that Unicode -character codes 0 to 255 are the same as for ISO~8859-1 (Latin~1), so as -long as a proper range check is performed on the Unicode character code, -it can be used just as an eight bit Latin~1 character code (which can be -useful if full Unicode support is not possible). - - -%------------------------------------------------------------------------- -\subsection{Key repeat} -By default, \GLFW\ does not report key repeats when a key is held down. -To activate key repeat, call \textbf{glfwEnable} with the argument -GLFW\_KEY\_REPEAT: - -\begin{lstlisting} -glfwEnable(GLFW_KEY_REPEAT); -\end{lstlisting} - -This will let a registered key or character callback function receive key -repeat events when a key is held down. - - -%------------------------------------------------------------------------- -\subsection{Special system keys} -On most systems there are some special system keys that are normally not -intercepted by an application. For instance, under Windows it is possible -to switch programs by pressing \texttt{ALT+TAB}, which brings up a list of -running programs to select from. In certain situations it can be desirable -to prevent such special system keys from interfering with the program. -With \GLFW\ it is possible to do by calling \textbf{glfwDisable} with the -argument GLFW\_SYSTEM\_KEYS: - -\begin{lstlisting} -glfwDisable(GLFW_SYSTEM_KEYS); -\end{lstlisting} - -By doing so, most system keys will have no effect and will not interfere -with your program. System keys can be re-enabled by calling -\textbf{glfwEnable} with the argument GLFW\_SYSTEM\_KEYS. By default, -system keys are enabled. - - -%------------------------------------------------------------------------- -\section{Mouse Input} -Just like for keyboard input, mouse input can be realized with either -polling or callback functions. - - -%------------------------------------------------------------------------- -\subsection{Mouse position} -To query the position of the mouse cursor, call \textbf{glfwGetMousePos}: - -\begin{lstlisting} -void glfwGetMousePos(int* x, int* y) -\end{lstlisting} - -The variables pointed to by \textit{x} and \textit{y} will be updated with the -current position of the mouse cursor relative to the upper-left corner of the -client area of the \GLFW\ window. - -An alternative is to use a callback function, which can be set with -\textbf{glfwSetMousePosCallback}: - -\begin{lstlisting} -void glfwSetMousePosCallback(GLFWmouseposfun cbfun) -\end{lstlisting} - -The function that \textit{fun} points to will be called every time the -mouse cursor moves. The first argument to the callback function is -the cursor x-coordinate and the second the cursor y-coordinate, both relative -to the upper-left corner of the client area of the \GLFW\ window. - -Note that while the \textbf{glfwGetMousePos} function only reports the final -position after cursor movement events have been processed, using a callback -function lets the application see each and every such event. - - -%------------------------------------------------------------------------- -\subsection{Mouse buttons} -To query the state of a mouse button, call \textbf{glfwGetMouseButton}: - -\begin{lstlisting} -int glfwGetMouseButton(int button) -\end{lstlisting} - -The argument \textit{button} can be any \GLFW\ mouse button token, i.e. -GLFW\_MOUSE\_BUTTON\_1 through GLFW\_MOUSE\_BUTTON\_8 or one of -GLFW\_MOUSE\_BUTTON\_LEFT, GLFW\_MOUSE\_BUTTON\_RIGHT or -GLFW\_MOUSE\_BUTTON\_MIDDLE. \textbf{glfwGetMouseButton} will return -GLFW\_PRESS (which is a non-zero value) if the corresponding mouse button is -held down, otherwise it will return GLFW\_RELEASE (which is equal to zero). - -Just as it is possible to make keys ``sticky'', it is also possible to make -each mouse button appear as held down until it is checked with -\textbf{glfwGetMouseButton}. To enable sticky mouse buttons, call -\textbf{glfwEnable} with the argument GLFW\_STICKY\_MOUSE\_BUTTONS. - -When sticky mouse buttons are enabled, a mouse button will not be released -until it is checked with \textbf{glfwGetMouseButton}. To disable sticky -mouse buttons, call \textbf{glfwDisable} with the argument -GLFW\_STICKY\_MOUSE\_BUTTONS. Then all mouse buttons that are not -currently held down will be released and future mouse button releases -will take place immediately when the user releases the mouse button -without waiting for \textbf{glfwGetMouseButton} to check for the mouse -button. By default sticky mouse buttons are disabled. - -There is also a callback function for mouse button activities, which can -be set with \textbf{glfwSetMouseButtonCallback}: - -\begin{lstlisting} -void glfwSetMouseButtonCallback(GLFWmousebuttonfun fun) -\end{lstlisting} - -The argument \textit{fun} specifies a function that will be called -whenever a mouse button is pressed or released, or NULL to unregister a -callback function. The first argument to the callback function is a mouse -button identifier, and the second is either GLFW\_PRESS or GLFW\_RELEASE, -depending on the new state of the corresponding mouse button. - - -%------------------------------------------------------------------------- -\subsection{Mouse wheel} -Some mice have a mouse wheel, most commonly used for vertical scrolling. Also, -most modern touchpads allow the user to scroll at least vertically, either by -reserving an area for scrolling or through multi-finger gestures. To get the -position of the mouse wheel, call \textbf{glfwGetMouseWheel}: - -\begin{lstlisting} -int glfwGetMouseWheel(void) -\end{lstlisting} - -The function returns an integer that represents the position of the mouse -wheel. When the user turns the wheel, the wheel position will increase or -decrease. Note that since scrolling hardware has no absolute position, \GLFW\ -simply sets the position to zero when the window is opened. - -It is also possible to register a callback function for mouse wheel events -with the \textbf{glfwSetMouseWheelCallback} function: - -\begin{lstlisting} -void glfwSetMouseWheelCallback(GLFWmousewheelfun fun) -\end{lstlisting} - -The argument \textit{fun} specifies a function that will be called -whenever the mouse wheel is moved, or NULL to unregister a callback -function. The argument to the callback function is the position of the -mouse wheel. - - -%------------------------------------------------------------------------- -\subsection{Hiding the mouse cursor} -It is possible to hide the mouse cursor with the function call: - -\begin{lstlisting} -glfwDisable(GLFW_MOUSE_CURSOR); -\end{lstlisting} - -Hiding the mouse cursor has three effects: - -\begin{enumerate} -\item The cursor becomes invisible. -\item The cursor is guaranteed to be confined to the window. -\item Mouse coordinates are not limited to the window size. -\end{enumerate} - -To show the mouse cursor again, call \textbf{glfwEnable} with the -argument GLFW\_MOUSE\_CURSOR: - -\begin{lstlisting} -glfwEnable(GLFW_MOUSE_CURSOR); -\end{lstlisting} - -By default the mouse cursor is hidden if a window is opened in fullscreen -mode, otherwise it is not hidden. - - -%------------------------------------------------------------------------- -\section{Joystick Input} -\GLFW\ has support for up to sixteen joysticks, and an infinite\footnote{% -There are of course actual limitations posed by the underlying hardware, -drivers and operation system.} number of axes and buttons per joystick. -Unlike keyboard and mouse input, joystick input does not need an opened -window, and \textbf{glfwPollEvents} or \textbf{glfwSwapBuffers} does not -have to be called in order for joystick state to be updated. - - -%------------------------------------------------------------------------- -\subsection{Joystick capabilities} -First, it is often necessary to determine if a joystick is connected and -what its capabilities are. To get this information the function -\textbf{glfwGetJoystickParam} can be used: - -\begin{lstlisting} -int glfwGetJoystickParam(int joy, int param) -\end{lstlisting} - -The \textit{joy} argument specifies which joystick to retrieve the -parameter from, and it should be GLFW\_JOYSTICK\_\textit{n}, where -\textit{n} is in the range 1 to 16. The \textit{param} argument specifies -which parameter to retrieve. To determine if a joystick is connected, -\textit{param} should be GLFW\_PRESENT, which will cause the function to -return GL\_TRUE if the joystick is connected, or GL\_FALSE if it is not. -To determine the number of axes or buttons that are supported by the -joystick, \textit{param} should be GLFW\_AXES or GLFW\_BUTTONS, -respectively. - -Note that \GLFW\ supports both D-pads and POVs, even though they are not -explicitly mentioned in the API. D-pads are exposed as a set of four buttons -and POVs are as two axes. - - -%------------------------------------------------------------------------- -\subsection{Joystick position} -To get the current axis positions of the joystick, the -\textbf{glfwGetJoystickPos} is used: - -\begin{lstlisting} -int glfwGetJoystickPos(int joy, float* pos, int numaxes) -\end{lstlisting} - -As with \textbf{glfwGetJoystickParam}, the \textit{joy} argument -specifies which joystick to retrieve information from. The -\textit{numaxes} argument specifies how many axes to return positions for and the -\textit{pos} argument specifies an array in which they -are stored. The function returns the actual number of axes that were -returned, which could be less than \textit{numaxes} if the joystick does -not support all the requested axes, or if the joystick is not connected. - -For instance, to get the position of the first two axes (the X and Y axes) -of joystick 1, the following code can be used: - -\begin{lstlisting} -float position[2]; - -glfwGetJoystickPos(GLFW_JOYSTICK_1, position, 2); -\end{lstlisting} - -After this call, the first element of the \textit{position} array will -hold the X axis position of the joystick, and the second element will hold -the Y axis position. In this example we do not use the information about -how many axes were really returned. - -The position of an axis can be in the range -1.0 to 1.0, where positive -values represent right, forward or up directions, while negative values -represent left, back or down directions. If a requested axis is not -supported by the joystick, the corresponding array element will be set -to zero. The same goes for the situation when the joystick is not -connected (all axes are treated as unsupported). - - -%------------------------------------------------------------------------- -\subsection{Joystick buttons} -A function similar to the \textbf{glfwGetJoystickPos} function is -available for querying the state of joystick buttons, namely the -\textbf{glfwGetJoystickButtons} function: - -\begin{lstlisting} -int glfwGetJoystickButtons(int joy, unsigned char* buttons, - int numbuttons) -\end{lstlisting} - -The function works just like the \textbf{glfwGetJoystickAxis} function, except -that it returns the state of joystick buttons instead of axis positions. Each -button in the array specified by the \textit{buttons} argument can be either -GLFW\_PRESS or GLFW\_RELEASE, indicating whether the corresponding button is -currently held down or not. Unsupported buttons will have the value -GLFW\_RELEASE. - - -%------------------------------------------------------------------------- -% Timing -%------------------------------------------------------------------------- -\chapter{Timing} -\thispagestyle{fancy} - -%------------------------------------------------------------------------- -\section{High Resolution Timer} -In most applications, it is useful to know exactly how much time has -passed between point $A$ and point $B$ in a program. A typical situation -is in a game, where you need to know how much time has passed between two -rendered frames in order to calculate the correct movement and physics -etc. Another example is when you want to benchmark a certain piece of -code. - -\GLFW\ provides a high-resolution timer, which reports a double precision -floating point value representing the number of seconds that have passed -since \textbf{glfwInit} was called. The timer is accessed with the -function \textbf{glfwGetTime}: - -\begin{lstlisting} -double glfwGetTime(void) -\end{lstlisting} - -The precision of the timer depends on which computer and operating -system you are running, but it is almost guaranteed to be better than -$10~ms$, and in most cases it is much better than $1~ms$ (on a modern PC -you can get resolutions in the order of $1~ns$). - -It is possible to set the value of the high precision timer using the -\textbf{glfwSetTime} function: - -\begin{lstlisting} -void glfwSetTime(double time) -\end{lstlisting} - -The argument \textit{time} is the time, in seconds, that the timer should -be set to. - - -%------------------------------------------------------------------------- -% OpenGL Extension Support -%------------------------------------------------------------------------- -\chapter{OpenGL Extension Support} -\thispagestyle{fancy} -One of the benefits of \OpenGL\ is that it is extensible. Independent -hardware vendors (IHVs) may include functionality in their \OpenGL\ -implementations that exceed that of the \OpenGL\ standard. - -An extension is defined by: - -\begin{enumerate} -\item An extension name (e.g. GL\_ARB\_multitexture). -\item New OpenGL tokens (e.g. GL\_TEXTURE1\_ARB). -\item New OpenGL functions (e.g. \textbf{glActiveTextureARB}). -\end{enumerate} - -A list of official extensions, together with their definitions, can be -found at the \textit{OpenGL Registry} -(\url{http://www.opengl.org/registry/}). - -To use a certain extension, the following steps must be performed: - -\begin{enumerate} -\item A compile time check for the support of the extension. -\item A run time check for the support of the extension. -\item Fetch function pointers for the extended \OpenGL\ functions (done at - run time). -\end{enumerate} - -How this is done using \GLFW\ is described in the following sections. -Please note that this chapter covers some advanced topics, and is quite -specific to the C programming language. - -For a much easier way to get access to \OpenGL\ extensions, you should probably -use a dedicated extension loading library such as GLEW or GLee. This kind of -library greatly reduces the amount of work necessary to use \OpenGL\ -extensions. GLEW in particular has been extensively tested with and works well -with \GLFW . - - -%------------------------------------------------------------------------- -\section{Compile Time Check} -The compile time check is necessary to perform in order to know if the -compiler include files have defined the necessary tokens. It is very easy -to do. The include file \texttt{GL/gl.h} will define a constant with the -same name as the extension, if all the extension tokens are defined. Here -is an example of how to check for the extension GL\_ARB\_multitexture: - -\begin{lstlisting} -#ifdef GL_ARB_multitexture - // Extension is supported by the include files -#else - // Extension is not supported by the include files - // Get a more up-to-date file! -#endif -\end{lstlisting} - - -%------------------------------------------------------------------------- -\section{Runtime Check} -Even if the compiler include files have defined all the necessary tokens, a -given machine may not actually support the extension (it may have a graphics -card with a different \OpenGL\ implementation, or an older driver). That is why -it is necessary to do a run time check for the extension support as well. This -is done with the \GLFW\ function \textbf{glfwExtensionSupported}, which has the -C syntax: - -\begin{lstlisting} -int glfwExtensionSupported(const char* extension) -\end{lstlisting} - -The argument \textit{extension} is a null terminated ASCII string -with the extension name. \textbf{glfwExtensionSupported} returns GL\_TRUE -if the extension is supported, otherwise it returns GL\_FALSE. - -Let us extend the previous example of checking for support of the -extension GL\_ARB\_multitexture. This time we add a run time check, and a -variable which we set to GL\_TRUE if the extension is supported, or -GL\_FALSE if it is not supported. - -\begin{lstlisting} -int multitexture_supported; - -#ifdef GL_ARB_multitexture - // Check if extension is supported at run time - multitexture_supported = glfwExtensionSupported("GL_ARB_multitexture"); -#else - // Extension is not supported by the include files - // Get a more up-to-date file! - multitexture_supported = GL_FALSE; -#endif -\end{lstlisting} - -Now it is easy to check for the extension within the program, simply do: - -\begin{lstlisting} - if (multitexture_supported) - { - // Use multi texturing - } - else - { - // Use some other solution (or fail) - } -\end{lstlisting} - - -%------------------------------------------------------------------------- -\section{Fetching Function Pointers} -Some extensions, though not all, require the use of new \OpenGL\ functions. -These entry points are not necessarily exposed by your link libraries, making -it necessary to find them dynamically at run time. You can retrieve these -entry points using the \textbf{glfwGetProcAddress} function: - -\begin{lstlisting} -void* glfwGetProcAddress(const char* procname) -\end{lstlisting} - -The argument \textit{procname} is a null terminated ASCII string -holding the name of the \OpenGL\ function. \textbf{glfwGetProcAddress} -returns the address to the function if the function is available, -otherwise NULL is returned. - -Obviously, fetching the function pointer is trivial. For instance, if we -want to obtain the pointer to \textbf{glActiveTextureARB}, we simply call: - -\begin{lstlisting} -glActiveTextureARB = glfwGetProcAddress("glActiveTextureARB"); -\end{lstlisting} - -However, there are many possible naming and type definition conflicts -involved with such an operation, which may result in compiler warnings or -errors. My proposed solution is the following: - -\begin{itemize} -\item Do not use the function name for the variable name. Use something - similar, perhaps by adding a prefix or suffix, and then use - \texttt{\#define} to map the function name to your variable. -\item The standard type definition naming convention for function pointers - is \texttt{PFN\textit{xxxx}PROC}, where \texttt{\textit{xxxx}} is - the uppercase version of the function name (e.g. - \texttt{PFNGLACTIVETEXTUREARBPROC}). Either make sure your compiler uses - a compatible \texttt{gl.h} and/or \texttt{glext.h} file and rely on it to - define these types, or use define the types yourself using a different - naming convention (for example \texttt{\textit{xxxx}\_T}) and do the - type definitions yourself. -\end{itemize} - -Here is a slightly longer example of how to use an extension, this time using -our own function pointer type definition): - -\begin{lstlisting} -// Type definition of the function pointer -typedef void (APIENTRY * GLACTIVETEXTUREARB_T) (GLenum texture); - -// Function pointer -GLACTIVETEXTUREARB_T _ActiveTextureARB; -#define glActiveTextureARB _ActiveTextureARB - -// Extension availability flag -int multitexture_supported; - -#ifdef GL_ARB_multitexture - // Check if extension is supported at run time - if (glfwExtensionSupported("GL_ARB_multitexture")) - { - // Get the function pointer - glActiveTextureARB = (GLACTIVETEXTUREARB_T) - glfwGetProcAddress("glActiveTextureARB"); - - multitexture_supported = GL_TRUE; - } - else - { - multitexture_supported = GL_FALSE; - } -#else - // Extension is not supported by the include files - multitexture_supported = GL_FALSE; -#endif -\end{lstlisting} - -Even this example leaves some things to be desired. First of all, the -GL\_ARB\_multitexture extension defines many more functions than the single -function used above. Secondly, checking if an extension is supported using -\textbf{glfwExtensionSupported} is not enough to ensure that the corresponding -functions will be valid. You also need to check that the all function pointers -returned by \textbf{glfwGetProcAddress} are non-NULL. - - -%------------------------------------------------------------------------- -\subsection{Function pointer type definitions} -To make a function pointer type definition, you need to know the function -prototype. This can often be found in the extension definitions (e.g. at -the \textit{OpenGL Registry}). All the entry points that are defined by an -extension are listed with their C prototype definitions under the section -\textit{New Procedures and Functions} in the extension definition. - -For instance, if we look at the definition of the -GL\_ARB\_texture\_compression extension, we find a list of new functions. -One of these is declared like this: - -\begin{lstlisting} -void GetCompressedTexImageARB(enum target, int lod, void* img); -\end{lstlisting} - -Like in most official \OpenGL\ documentation, all the \texttt{GL} and -\texttt{gl} prefixes have been left out. In other words, the real function -prototype would look like this: - -\begin{lstlisting} -void glGetCompressedTexImageARB(GLenum target, GLint lod, void* img); -\end{lstlisting} - -All we have to do to turn this prototype definition into a function -pointer type definition, is to replace the function name with -\texttt{(APIENTRY * \textit{xxxx}\_T)}, where \textit{xxxx} is the -uppercase version of the name (according to the proposed naming -convention). The keyword \texttt{APIENTRY} is needed to be compatible -between different platforms. The \GLFW\ header file \texttt{GL/glfw.h} -ensures that \texttt{APIENTRY} is properly defined on all supported platforms. - -In other words, for the function \textbf{glGetCompressedTexImageARB} we -get: - -\begin{lstlisting} -typedef void (APIENTRY * GLGETCOMPRESSEDTEXIMAGEARB_T) - (GLenum target, GLint level, void* img); -\end{lstlisting} - - -\end{document} diff --git a/docs/readme.txt b/docs/readme.txt deleted file mode 100644 index f34521a2..00000000 --- a/docs/readme.txt +++ /dev/null @@ -1,52 +0,0 @@ -Introduction ------------- - -The GLFW documentation is written in LaTeX. Besides being powerful, LaTeX is -also very attractive since all the necessary tools for dealing with LaTeX -documentation are both free and ported to a wide variety of platforms. Another -advantage is that the LaTeX files are written in plain text, which means that -version control systems such as CVS handle them perfectly without having to -treat the documents as binary files. - - -The documents -------------- - -There are two main documents: - - glfwrm.tex - The GLFW Reference Manual - glfwug.tex - The GLFW Users Guide - -In addition, there is a common LaTeX style file that sets up things -such as page formatting and useful macros: - - glfwdoc.sty - Common GLFW document styles and macros - - -Requirements ------------- - -Of course you need LaTeX installed on your system in order to compile the GLFW -documentation. If you are using a Unix-like operating system, then your -package system most likely has a version of LaTeX adapted for your system. If -not, the easiest way to get a full LaTeX system is to download/get the TeXLive -CD from http://www.tug.org/texlive/. It has all the necessary software for -Windows, Mac OS X and most popular Unix-like operating systems. - -A number of LaTeX packages have to be installed in order to compile the -GLFW documentation successfully: - - color - fancyhdr - hyperref - lastpage - listings - needspace - textcase - times - titling - -These packages are all available on the TeXLive CD. Just make sure that -you have checked all these packages when installing TeXLive, or get them -in some other way if you do not have the TeXLive CD. - diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e850a312..3e7065c6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,34 +1,53 @@ -# This line is used to link with static libraries -# Note that the library list should be updated to be obtained from -# the main CMakeLists.txt -link_libraries(libglfwStatic ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY}) + +link_libraries(glfw ${OPENGL_glu_LIBRARY}) + +if (BUILD_SHARED_LIBS) + add_definitions(-DGLFW_DLL) + link_libraries(${OPENGL_gl_LIBRARY} ${MATH_LIBRARY}) +else() + link_libraries(${glfw_LIBRARIES}) +endif() include_directories(${GLFW_SOURCE_DIR}/include ${GLFW_SOURCE_DIR}/support ${OPENGL_INCLUDE_DIR}) -if(APPLE) - # Set fancy names for bundles - add_executable(Boing MACOSX_BUNDLE boing.c) - add_executable(Gears MACOSX_BUNDLE gears.c) - add_executable("Split View" MACOSX_BUNDLE splitview.c) - add_executable(Triangle MACOSX_BUNDLE triangle.c) - add_executable(Wave MACOSX_BUNDLE wave.c) -else(APPLE) - # Set boring names for executables - add_executable(boing WIN32 boing.c) - add_executable(gears WIN32 gears.c) - add_executable(heightmap WIN32 heightmap.c getopt.c) - add_executable(splitview WIN32 splitview.c) - add_executable(triangle WIN32 triangle.c) - add_executable(wave WIN32 wave.c) -endif(APPLE) +if (APPLE) + # Set fancy names for bundles + add_executable(Boing MACOSX_BUNDLE boing.c) + add_executable(Gears MACOSX_BUNDLE gears.c) + add_executable("Split View" MACOSX_BUNDLE splitview.c) + add_executable(Triangle MACOSX_BUNDLE triangle.c) + add_executable(Wave MACOSX_BUNDLE wave.c) -set(WINDOWS_BINARIES boing gears heightmap splitview triangle wave) + set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing") + set_target_properties(Gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears") + set_target_properties("Split View" PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View") + set_target_properties(Triangle PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Triangle") + set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave") +else() + # Set boring names for executables + add_executable(boing WIN32 boing.c) + add_executable(gears WIN32 gears.c) + add_executable(heightmap WIN32 heightmap.c getopt.c) + add_executable(splitview WIN32 splitview.c) + add_executable(triangle WIN32 triangle.c) + add_executable(wave WIN32 wave.c) +endif() -if(MSVC) - # Tell MSVC to use main instead of WinMain for Windows subsystem executables - set_target_properties(${WINDOWS_BINARIES} PROPERTIES - LINK_FLAGS "/ENTRY:mainCRTStartup") -endif(MSVC) +if (MSVC) + set(WINDOWS_BINARIES boing gears heightmap splitview triangle wave) + + # Tell MSVC to use main instead of WinMain for Windows subsystem executables + set_target_properties(${WINDOWS_BINARIES} PROPERTIES + LINK_FLAGS "/ENTRY:mainCRTStartup") +endif() + +if (APPLE) + set(BUNDLE_BINARIES Boing Gears "Split View" Triangle Wave) + + set_target_properties(${BUNDLE_BINARIES} PROPERTIES + MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} + MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}) +endif() diff --git a/examples/boing.c b/examples/boing.c index 8cf5b1dc..49d602ca 100644 --- a/examples/boing.c +++ b/examples/boing.c @@ -30,6 +30,8 @@ #include #include #include + +#define GLFW_INCLUDE_GLU #include @@ -569,7 +571,7 @@ int main( void ) GLFWwindow window; /* Init GLFW */ - if( !glfwInit(NULL) ) + if( !glfwInit() ) { fprintf( stderr, "Failed to initialize GLFW\n" ); exit( EXIT_FAILURE ); diff --git a/examples/gears.c b/examples/gears.c index cbf9eab9..53d601f3 100644 --- a/examples/gears.c +++ b/examples/gears.c @@ -323,7 +323,7 @@ int main(int argc, char *argv[]) { GLFWwindow window; - if( !glfwInit(NULL) ) + if( !glfwInit() ) { fprintf( stderr, "Failed to initialize GLFW\n" ); exit( EXIT_FAILURE ); diff --git a/examples/heightmap.c b/examples/heightmap.c index a55df291..e926581a 100644 --- a/examples/heightmap.c +++ b/examples/heightmap.c @@ -32,8 +32,6 @@ #include #include "getopt.h" - -#define GLFW_NO_GLU 1 #include #include @@ -84,7 +82,7 @@ static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer = NULL; #define RESOLVE_GL_FCN(type, var, name) \ if (status == GL_TRUE) \ {\ - var = glfwGetProcAddress((name));\ + var = (type) glfwGetProcAddress((name));\ if ((var) == NULL)\ {\ status = GL_FALSE;\ @@ -95,31 +93,31 @@ static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer = NULL; static GLboolean init_opengl(void) { GLboolean status = GL_TRUE; - RESOLVE_GL_FCN(PFN_glCreateShader, pglCreateShader, "glCreateShader"); - RESOLVE_GL_FCN(PFN_glShaderSource, pglShaderSource, "glShaderSource"); - RESOLVE_GL_FCN(PFN_glCompileShader, pglCompileShader, "glCompileShader"); - RESOLVE_GL_FCN(PFN_glGetShaderiv, pglGetShaderiv, "glGetShaderiv"); - RESOLVE_GL_FCN(PFN_glGetShaderInfoLog, pglGetShaderInfoLog, "glGetShaderInfoLog"); - RESOLVE_GL_FCN(PFN_glDeleteShader, pglDeleteShader, "glDeleteShader"); - RESOLVE_GL_FCN(PFN_glCreateProgram, pglCreateProgram, "glCreateProgram"); - RESOLVE_GL_FCN(PFN_glAttachShader, pglAttachShader, "glAttachShader"); - RESOLVE_GL_FCN(PFN_glLinkProgram, pglLinkProgram, "glLinkProgram"); - RESOLVE_GL_FCN(PFN_glUseProgram, pglUseProgram, "glUseProgram"); - RESOLVE_GL_FCN(PFN_glGetProgramiv, pglGetProgramiv, "glGetProgramiv"); - RESOLVE_GL_FCN(PFN_glGetProgramInfoLog, pglGetProgramInfoLog, "glGetProgramInfoLog"); - RESOLVE_GL_FCN(PFN_glDeleteProgram, pglDeleteProgram, "glDeleteProgram"); - RESOLVE_GL_FCN(PFN_glGetUniformLocation, pglGetUniformLocation, "glGetUniformLocation"); - RESOLVE_GL_FCN(PFN_glUniformMatrix4fv, pglUniformMatrix4fv, "glUniformMatrix4fv"); - RESOLVE_GL_FCN(PFN_glGetAttribLocation, pglGetAttribLocation, "glGetAttribLocation"); - RESOLVE_GL_FCN(PFN_glGenVertexArrays, pglGenVertexArrays, "glGenVertexArrays"); - RESOLVE_GL_FCN(PFN_glDeleteVertexArrays, pglDeleteVertexArrays, "glDeleteVertexArrays"); - RESOLVE_GL_FCN(PFN_glBindVertexArray, pglBindVertexArray, "glBindVertexArray"); - RESOLVE_GL_FCN(PFN_glGenBuffers, pglGenBuffers, "glGenBuffers"); - RESOLVE_GL_FCN(PFN_glBindBuffer, pglBindBuffer, "glBindBuffer"); - RESOLVE_GL_FCN(PFN_glBufferData, pglBufferData, "glBufferData"); - RESOLVE_GL_FCN(PFN_glBufferSubData, pglBufferSubData, "glBufferSubData"); - RESOLVE_GL_FCN(PFN_glEnableVertexAttribArray, pglEnableVertexAttribArray, "glEnableVertexAttribArray"); - RESOLVE_GL_FCN(PFN_glVertexAttribPointer, pglVertexAttribPointer, "glVertexAttribPointer"); + RESOLVE_GL_FCN(PFNGLCREATESHADERPROC, pglCreateShader, "glCreateShader"); + RESOLVE_GL_FCN(PFNGLSHADERSOURCEPROC, pglShaderSource, "glShaderSource"); + RESOLVE_GL_FCN(PFNGLCOMPILESHADERPROC, pglCompileShader, "glCompileShader"); + RESOLVE_GL_FCN(PFNGLGETSHADERIVPROC, pglGetShaderiv, "glGetShaderiv"); + RESOLVE_GL_FCN(PFNGLGETSHADERINFOLOGPROC, pglGetShaderInfoLog, "glGetShaderInfoLog"); + RESOLVE_GL_FCN(PFNGLDELETESHADERPROC, pglDeleteShader, "glDeleteShader"); + RESOLVE_GL_FCN(PFNGLCREATEPROGRAMPROC, pglCreateProgram, "glCreateProgram"); + RESOLVE_GL_FCN(PFNGLATTACHSHADERPROC, pglAttachShader, "glAttachShader"); + RESOLVE_GL_FCN(PFNGLLINKPROGRAMPROC, pglLinkProgram, "glLinkProgram"); + RESOLVE_GL_FCN(PFNGLUSEPROGRAMPROC, pglUseProgram, "glUseProgram"); + RESOLVE_GL_FCN(PFNGLGETPROGRAMIVPROC, pglGetProgramiv, "glGetProgramiv"); + RESOLVE_GL_FCN(PFNGLGETPROGRAMINFOLOGPROC, pglGetProgramInfoLog, "glGetProgramInfoLog"); + RESOLVE_GL_FCN(PFNGLDELETEPROGRAMPROC, pglDeleteProgram, "glDeleteProgram"); + RESOLVE_GL_FCN(PFNGLGETUNIFORMLOCATIONPROC, pglGetUniformLocation, "glGetUniformLocation"); + RESOLVE_GL_FCN(PFNGLUNIFORMMATRIX4FVPROC, pglUniformMatrix4fv, "glUniformMatrix4fv"); + RESOLVE_GL_FCN(PFNGLGETATTRIBLOCATIONPROC, pglGetAttribLocation, "glGetAttribLocation"); + RESOLVE_GL_FCN(PFNGLGENVERTEXARRAYSPROC, pglGenVertexArrays, "glGenVertexArrays"); + RESOLVE_GL_FCN(PFNGLDELETEVERTEXARRAYSPROC, pglDeleteVertexArrays, "glDeleteVertexArrays"); + RESOLVE_GL_FCN(PFNGLBINDVERTEXARRAYPROC, pglBindVertexArray, "glBindVertexArray"); + RESOLVE_GL_FCN(PFNGLGENBUFFERSPROC, pglGenBuffers, "glGenBuffers"); + RESOLVE_GL_FCN(PFNGLBINDBUFFERPROC, pglBindBuffer, "glBindBuffer"); + RESOLVE_GL_FCN(PFNGLBUFFERDATAPROC, pglBufferData, "glBufferData"); + RESOLVE_GL_FCN(PFNGLBUFFERSUBDATAPROC, pglBufferSubData, "glBufferSubData"); + RESOLVE_GL_FCN(PFNGLENABLEVERTEXATTRIBARRAYPROC, pglEnableVertexAttribArray, "glEnableVertexAttribArray"); + RESOLVE_GL_FCN(PFNGLVERTEXATTRIBPOINTERPROC, pglVertexAttribPointer, "glVertexAttribPointer"); return status; } /********************************************************************** @@ -573,7 +571,7 @@ int main(int argc, char** argv) } } - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "ERROR: Unable to initialize GLFW\n"); usage(); diff --git a/examples/splitview.c b/examples/splitview.c index 3fcdd1d8..c584f9af 100644 --- a/examples/splitview.c +++ b/examples/splitview.c @@ -10,7 +10,9 @@ // because I am not a friend of orthogonal projections) //======================================================================== +#define GLFW_INCLUDE_GLU #include + #include #include #include @@ -377,7 +379,7 @@ static void windowRefreshFun(GLFWwindow window) // Mouse position callback function //======================================================================== -static void mousePosFun(GLFWwindow window, int x, int y) +static void cursorPosFun(GLFWwindow window, int x, int y) { // Depending on which view was selected, rotate around different axes switch (active_view) @@ -402,7 +404,7 @@ static void mousePosFun(GLFWwindow window, int x, int y) break; } - // Remember mouse position + // Remember cursor position xpos = x; ypos = y; } @@ -442,7 +444,7 @@ int main(void) GLFWwindow window; // Initialise GLFW - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); exit(EXIT_FAILURE); @@ -470,7 +472,7 @@ int main(void) // Set callback functions glfwSetWindowSizeCallback(windowSizeFun); glfwSetWindowRefreshCallback(windowRefreshFun); - glfwSetMousePosCallback(mousePosFun); + glfwSetCursorPosCallback(cursorPosFun); glfwSetMouseButtonCallback(mouseButtonFun); // Main loop diff --git a/examples/triangle.c b/examples/triangle.c index e952cc70..ee340496 100644 --- a/examples/triangle.c +++ b/examples/triangle.c @@ -7,6 +7,7 @@ #include #include +#define GLFW_INCLUDE_GLU #include int main(void) @@ -15,7 +16,7 @@ int main(void) GLFWwindow window; // Initialise GLFW - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); exit(EXIT_FAILURE); @@ -38,7 +39,7 @@ int main(void) do { double t = glfwGetTime(); - glfwGetMousePos(window, &x, NULL); + glfwGetCursorPos(window, &x, NULL); // Get window size (may be different than the requested size) glfwGetWindowSize(window, &width, &height); diff --git a/examples/wave.c b/examples/wave.c index 9ffcd3f7..54574839 100644 --- a/examples/wave.c +++ b/examples/wave.c @@ -11,6 +11,8 @@ #include #include #include + +#define GLFW_INCLUDE_GLU #include #ifndef M_PI @@ -321,10 +323,10 @@ void mouse_button_callback(GLFWwindow window, int button, int action) //======================================================================== -// Callback function for mouse motion events +// Callback function for cursor motion events //======================================================================== -void mouse_position_callback(GLFWwindow window, int x, int y) +void cursor_position_callback(GLFWwindow window, int x, int y) { if (locked) { @@ -341,9 +343,9 @@ void mouse_position_callback(GLFWwindow window, int x, int y) // Callback function for scroll events //======================================================================== -void scroll_callback(GLFWwindow window, int x, int y) +void scroll_callback(GLFWwindow window, double x, double y) { - zoom += y / 4.f; + zoom += (float) y / 4.f; if (zoom < 0) zoom = 0; } @@ -379,7 +381,7 @@ int main(int argc, char* argv[]) GLFWwindow window; double t, dt_total, t_old; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "GLFW initialization failed\n"); exit(EXIT_FAILURE); @@ -401,7 +403,7 @@ int main(int argc, char* argv[]) // Window resize handler glfwSetWindowSizeCallback(window_resize_callback); glfwSetMouseButtonCallback(mouse_button_callback); - glfwSetMousePosCallback(mouse_position_callback); + glfwSetCursorPosCallback(cursor_position_callback); glfwSetScrollCallback(scroll_callback); // Initialize OpenGL diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 82a2f89c..b7ea88c5 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -67,6 +67,12 @@ extern "C" { #endif #endif /* APIENTRY */ +/* TEMPORARY MinGW-w64 hacks. + */ +#if __MINGW64__ + #define WINAPI +#include +#endif /* The following three defines are here solely to make some Windows-based * files happy. Theoretically we could include , but @@ -113,7 +119,11 @@ extern "C" { /* ---------------- GLFW related system specific defines ----------------- */ -#if defined(_WIN32) && defined(GLFW_BUILD_DLL) +#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) + #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined" +#endif + +#if defined(_WIN32) && defined(_GLFW_BUILD_DLL) /* We are building a Win32 DLL */ #define GLFWAPI __declspec(dllexport) @@ -136,15 +146,7 @@ extern "C" { /* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ -/* Include the declaration of the size_t type used below. - */ -#include - -/* Include standard OpenGL headers: GLFW uses GL_FALSE/GL_TRUE, and it is - * convenient for the user to only have to include . This also - * solves the problem with Windows and needing some - * special defines which normally requires the user to include - * (which is not a nice solution for portable programs). +/* Include the chosen OpenGL header and, optionally, the GLU header. */ #if defined(__APPLE_CC__) #if defined(GLFW_INCLUDE_GL3) @@ -153,7 +155,7 @@ extern "C" { #define GL_GLEXT_LEGACY #include #endif - #ifndef GLFW_NO_GLU + #if defined(GLFW_INCLUDE_GLU) #include #endif #else @@ -162,7 +164,7 @@ extern "C" { #else #include #endif - #ifndef GLFW_NO_GLU + #if defined(GLFW_INCLUDE_GLU) #include #endif #endif @@ -455,6 +457,7 @@ extern "C" { #define GLFW_VERSION_UNAVAILABLE 0x00070007 #define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_WINDOW_NOT_ACTIVE 0x00070009 +#define GLFW_FORMAT_UNAVAILABLE 0x0007000A /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 @@ -475,6 +478,9 @@ extern "C" { /* Monitor handle type */ typedef void* GLFWmonitor; +/* OpenGL function pointer type */ +typedef void (*GLFWglproc)(void); + /* Window handle type */ typedef void* GLFWwindow; @@ -486,12 +492,11 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow); typedef void (* GLFWwindowfocusfun)(GLFWwindow,int); typedef void (* GLFWwindowiconifyfun)(GLFWwindow,int); typedef void (* GLFWmousebuttonfun)(GLFWwindow,int,int); -typedef void (* GLFWmouseposfun)(GLFWwindow,int,int); -typedef void (* GLFWscrollfun)(GLFWwindow,int,int); +typedef void (* GLFWcursorposfun)(GLFWwindow,int,int); +typedef void (* GLFWcursorenterfun)(GLFWwindow,int); +typedef void (* GLFWscrollfun)(GLFWwindow,double,double); typedef void (* GLFWkeyfun)(GLFWwindow,int,int); typedef void (* GLFWcharfun)(GLFWwindow,int); -typedef void* (* GLFWmallocfun)(size_t); -typedef void (* GLFWfreefun)(void*); typedef void (* GLFWmonitordevicefun)(GLFWmonitor,int); /* The video mode structure used by glfwGetVideoModes */ @@ -512,20 +517,13 @@ typedef struct unsigned short blue[GLFW_GAMMA_RAMP_SIZE]; } GLFWgammaramp; -/* Custom memory allocator interface */ -typedef struct -{ - GLFWmallocfun malloc; - GLFWfreefun free; -} GLFWallocator; - /************************************************************************* * Prototypes *************************************************************************/ /* Initialization, termination and version querying */ -GLFWAPI int glfwInit(GLFWallocator* allocator); +GLFWAPI int glfwInit(void); GLFWAPI void glfwTerminate(void); GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); GLFWAPI const char* glfwGetVersionString(void); @@ -586,13 +584,14 @@ GLFWAPI int glfwGetInputMode(GLFWwindow window, int mode); GLFWAPI void glfwSetInputMode(GLFWwindow window, int mode, int value); GLFWAPI int glfwGetKey(GLFWwindow window, int key); GLFWAPI int glfwGetMouseButton(GLFWwindow window, int button); -GLFWAPI void glfwGetMousePos(GLFWwindow window, int* xpos, int* ypos); -GLFWAPI void glfwSetMousePos(GLFWwindow window, int xpos, int ypos); -GLFWAPI void glfwGetScrollOffset(GLFWwindow window, int* xoffset, int* yoffset); +GLFWAPI void glfwGetCursorPos(GLFWwindow window, int* xpos, int* ypos); +GLFWAPI void glfwSetCursorPos(GLFWwindow window, int xpos, int ypos); +GLFWAPI void glfwGetScrollOffset(GLFWwindow window, double* xoffset, double* yoffset); GLFWAPI void glfwSetKeyCallback(GLFWkeyfun cbfun); GLFWAPI void glfwSetCharCallback(GLFWcharfun cbfun); GLFWAPI void glfwSetMouseButtonCallback(GLFWmousebuttonfun cbfun); -GLFWAPI void glfwSetMousePosCallback(GLFWmouseposfun cbfun); +GLFWAPI void glfwSetCursorPosCallback(GLFWcursorposfun cbfun); +GLFWAPI void glfwSetCursorEnterCallback(GLFWcursorenterfun cbfun); GLFWAPI void glfwSetScrollCallback(GLFWscrollfun cbfun); /* Joystick input */ @@ -600,6 +599,10 @@ GLFWAPI int glfwGetJoystickParam(int joy, int param); GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); +/* Clipboard */ +GLFWAPI void glfwSetClipboardString(GLFWwindow window, const char* string); +GLFWAPI const char* glfwGetClipboardString(GLFWwindow window); + /* Time */ GLFWAPI double glfwGetTime(void); GLFWAPI void glfwSetTime(double time); @@ -610,7 +613,7 @@ GLFWAPI GLFWwindow glfwGetCurrentContext(void); GLFWAPI void glfwSwapBuffers(void); GLFWAPI void glfwSwapInterval(int interval); GLFWAPI int glfwExtensionSupported(const char* extension); -GLFWAPI void* glfwGetProcAddress(const char* procname); +GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); GLFWAPI void glfwCopyContext(GLFWwindow src, GLFWwindow dst, unsigned long mask); diff --git a/readme.html b/readme.html index b14945e8..3ef85423 100644 --- a/readme.html +++ b/readme.html @@ -20,7 +20,8 @@
  • Acknowledgements
  • - + +

    1. Introduction

    Welcome to version 3.0 of the GLFW library. GLFW is a free, open source, @@ -34,19 +35,22 @@ settle.

    Note that the threading and image loading APIs from the 2.x series have been removed.

    - + +

    2. Compiling GLFW and the example programs

    To compile GLFW and the accompanying example programs, you will need the CMake build system.

    - + +

    3. Installing GLFW

    A rudimentary installation target is provided for all supported platforms via the CMake build system.

    - + +

    4. Using GLFW

    There are two aspects to using GLFW:

    @@ -66,12 +70,13 @@ GLFW API.

    A few rules for successfully designing GLFW-based programs are presented in the following sections.

    +

    4.1 Include the GLFW header file

    In the files of your program where you use OpenGL or GLFW, you should -include the GL/glfw.h header file, i.e.:

    +include the GL/glfw3.h header file, i.e.:

    -
    #include <GL/glfw.h>
    +
    #include <GL/glfw3.h>

    This defines all the constants, types and function prototypes of the GLFW API. It also includes the gl.h and GL/glu.h header @@ -95,7 +100,7 @@ it. This way, the namespace won't be cluttered by the entire Windows API.

  • Do not include windows.h unless you actually need direct access to the Windows API
  • If you do need to include windows.h, do it - before including GL/glfw.h and the GLFW header will + before including GL/glfw3.h and the GLFW header will detect this.

    @@ -106,9 +111,9 @@ disable any gl.h that the GLFW header includes and GLEW will work as expected.

    -

    4.2 Link with the right libraries

    +

    4.2.1 Windows static library

    If you link with the static version of GLFW, it is also necessary to @@ -219,7 +224,6 @@ by compile.sh at compile time.

    -lGLU to your link flags.

    -

    4.2.5 Mac OS X static library

    When compiling and linking a program under Mac OS X that uses GLFW, you @@ -256,9 +260,11 @@ that even though your machine may have Unix-style OpenGL libraries, they are for use with the X Window System, and will not work with the Mac OS X native version of GLFW.

    - + +

    5. Version history

    +

    v3.0

    • Added GLFWwindow window handle type and updated window-related functions and callbacks to take a window handle
    • @@ -271,8 +277,8 @@ version of GLFW.

    • Added glfwGetWindowPos function for querying the position of the specified window
    • Added glfwSetWindowFocusCallback function and GLFWwindowfocusfun type for receiving window focus events
    • Added glfwSetWindowIconifyCallback function and GLFWwindowiconifyfun type for receiving window iconification events
    • +
    • Added glfwGetClipboardString and glfwSetClipboardString functions for interacting with the system clipboard
    • Added glfwGetCurrentContext function for retrieving the window whose OpenGL context is current
    • -
    • Added GLFWallocator type and glfwInit parameter for pluggable memory allocator
    • Added glfwCopyContext function for copying OpenGL state categories between contexts
    • Added GLFW_OPENGL_ES2_PROFILE profile for creating OpenGL ES 2.0 contexts using the GLX_EXT_create_context_es2_profile and WGL_EXT_create_context_es2_profile extensions
    • Added GLFW_OPENGL_ROBUSTNESS window hint and associated strategy tokens for GL_ARB_robustness support
    • @@ -280,20 +286,25 @@ version of GLFW.

    • Added GLFW_INCLUDE_GL3 macro for telling the GLFW header to include gl3.h header instead of gl.h
    • Added windows simple multi-window test program
    • Added sharing simple OpenGL object sharing test program
    • -
    • Added dynamic simple dynamic linking test program
    • +
    • Added modes video mode enumeration and setting test program
    • Added a parameter to glfwOpenWindow for specifying a context the new window's context will share objects with
    • Added initial window title parameter to glfwOpenWindow
    • Added glfwSetGamma, glfwSetGammaRamp and glfwGetGammaRamp functions and GLFWgammaramp type for monitor gamma ramp control
    • Changed buffer bit depth parameters of glfwOpenWindow to window hints
    • Changed glfwOpenWindow and glfwSetWindowTitle to use UTF-8 encoded strings
    • +
    • Changed glfwGetProcAddress to return a (generic) function pointer
    • Renamed glfw.h to glfw3.h to avoid conflicts with 2.x series
    • Renamed GLFW_WINDOW token to GLFW_WINDOWED
    • Renamed GLFW_WINDOW_NO_RESIZE to GLFW_WINDOW_RESIZABLE
    • +
    • Renamed GLFW_BUILD_DLL to _GLFW_BUILD_DLL
    • Renamed version test to glfwinfo
    • +
    • Renamed GLFW_NO_GLU to GLFW_INCLUDE_GLU and made it disabled by default
    • +
    • Renamed mouse position functions to cursor position equivalents
    • Replaced ad hoc build system with CMake
    • Replaced layout-dependent key codes with single, platform-independent set based on US layout
    • -
    • Replaced mouse wheel interface with two-dimensional scrolling interface
    • +
    • Replaced mouse wheel interface with two-dimensional, floating point scrolling interface
    • Replaced glfwEnable and glfwDisable with glfwGetInputMode and glfwSetInputMode
    • +
    • Replaced joystick test with graphical version
    • Made Unicode character input unaffected by GLFW_KEY_REPEAT
    • Removed event auto-polling and the GLFW_AUTO_POLL_EVENTS window enable
    • Removed the Win32 port .def files
    • @@ -309,10 +320,21 @@ version of GLFW.

    • Bugfix: The default OpenGL version in the glfwinfo test was set to 1.1
    • Bugfix: The OpenGL profile and forward-compatibility window parameters were not saved after context creation
    • Bugfix: The FSAA test did not check for the availability of GL_ARB_multisample
    • +
    • Bugfix: Cursor centering upon leaving captured cursor mode was reported before the mode was changed to non-captured
    • [Cocoa] Added support for OpenGL 3.2 core profile in 10.7 Lion and above
    • [Cocoa] Added support for joysticks
    • +
    • [Cocoa] Postponed menu creation to first window creation
    • +
    • [Cocoa] Replaced NSDate time source with mach_absolute_time
    • +
    • [Cocoa] Replaced all deprecated CoreGraphics calls with non-deprecated counterparts
    • +
    • [Cocoa] Bugfix: The NSOpenGLPFAFullScreen pixel format attribute caused creation to fail on some machines
    • +
    • [Cocoa] Bugfix: glfwOpenWindow did not properly enforce the forward-compatible and context profile hints
    • [Cocoa] Bugfix: The loop condition for saving video modes used the wrong index variable
    • [Cocoa] Bugfix: The OpenGL framework was not retrieved, making glfwGetProcAddress crash
    • +
    • [Cocoa] Bugfix: glfwInit changed the current directory for unbundled executables
    • +
    • [Cocoa] Bugfix: The GLFW_WINDOW_NO_RESIZE window parameter was always zero
    • +
    • [Cocoa] Bugfix: The cursor position incorrectly rounded during conversion
    • +
    • [Cocoa] Bugfix: Cursor positioning led to nonsensical results for fullscreen windows
    • +
    • [Cocoa] Bugfix: The GLFW window was flagged as restorable
    • [X11] Added support for the GLX_EXT_swap_control extension as an alternative to GLX_SGI_swap_control
    • [X11] Added the POSIX CLOCK_MONOTONIC time source as the preferred method
    • [X11] Added dependency on libm, where present
    • @@ -325,6 +347,9 @@ version of GLFW.

    • [Win32] Bugfix: Window activation and iconification did not work as expected
    • [Win32] Bugfix: Software rasterizer pixel formats were not discarded by the WGL_ARB_pixel_format code path
    • [Win32] Bugfix: The array for WGL context attributes was too small and could overflow
    • +
    • [Win32] Bugfix: Alt+F4 hot key was not translated into WM_CLOSE
    • +
    • [Win32] Bugfix: The GLFW_WINDOW_NO_RESIZE window parameter was always zero
    • +
    • [Win32] Bugfix: A test was missing for whether all available pixel formats had been disqualified

    v2.7

    @@ -759,7 +784,7 @@ version of GLFW.

    - +

    6. Directory structure of the GLFW distribution

    Here is an overview of the directory structure of the GLFW distribution: @@ -782,7 +807,7 @@ version of GLFW.

    - +

    7. Contacting the project

    The official website for GLFW is glfw.org. @@ -806,7 +831,7 @@ GLFW or porting it to your favorite platform, we have a or you could join us on #glfw. - +

    8. Acknowledgements

    GLFW exists because people around the world donated their time and lent @@ -814,12 +839,16 @@ their skills. Special thanks go out to:

      +
    • artblanc, for a patch replacing a deprecated Core Graphics call
    • +
    • Bobyshev Alexander and Martins Mozeiko, for the original proposal of an FSAA hint and their work on the Win32 implementation of FSAA
    • Keith Bauer, for his invaluable help with porting and maintaining GLFW on Mac OS X, and for his many ideas
    • +
    • Lambert Clara, for a bug fix for the modes test
    • +
    • Jarrod Davis, for the Delphi port of GLFW
    • Olivier Delannoy, for the initial implementation of FSAA support on @@ -833,7 +862,10 @@ their skills. Special thanks go out to:

      adding logic for the GLFW_ICON resource
    • Ralph Eastwood, for the initial design and implementation of the gamma - correction API
    • + correction and clipboard APIs + +
    • GeO4d, for the implementation of cursor enter/leave notifications on + Win32.
    • Gerald Franz, who made GLFW compile under IRIX, and supplied patches for the X11 keyboard translation routine
    • @@ -864,9 +896,14 @@ their skills. Special thanks go out to:

    • Glenn Lewis, for helping out with support for the D programming language
    • +
    • Shane Liesegang, for providing a bug fix relating to Cocoa window + restoration
    • +
    • Tristam MacDonald, for his bug reports and feedback on the Cocoa port
    • -
    • Hans 'Hanmac' Mackowiak, for adding UTF-8 window title support on X11
    • +
    • Hans 'Hanmac' Mackowiak, for the initial implementation of cursor + enter/leave callbacks on X11, adding UTF-8 window title support on X11 and + a fix for the Xkb support
    • David Medlock, for doing the initial Lua port
    • @@ -889,7 +926,7 @@ their skills. Special thanks go out to:

    • Steve Sexton, for reporting an input bug in the Carbon port
    • -
    • Dmitri Shuralyov, for support, bug reports and testing
    • +
    • Dmitri Shuralyov, for support, bug reports, bug fixes and testing
    • Daniel Skorupski, for reporting a bug in the Win32 DEF file
    • diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a399678..ee9241a7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,72 +1,57 @@ -if(WIN32) - add_definitions(-DWINVER=0x0501) -endif(WIN32) - -if(UNIX) - if(_GLFW_HAS_XRANDR) - set(GLFW_PKGLIBS "${GLFW_PKGLIBS} xrandr") - endif(_GLFW_HAS_XRANDR) - if(_GLFW_HAS_XF86VIDMODE) - set(GLFW_PKGLIBS "${GLFW_PKGLIBS} xxf86vm") - endif(_GLFW_HAS_XF86VIDMODE) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libglfw.pc.cmake - ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc DESTINATION lib/pkgconfig) -endif(UNIX) - include_directories(${GLFW_SOURCE_DIR}/src ${GLFW_BINARY_DIR}/src - ${GLFW_INCLUDE_DIR}) + ${glfw_INCLUDE_DIRS}) -set(common_SOURCES error.c fullscreen.c gamma.c init.c input.c +set(common_HEADERS ${GLFW_SOURCE_DIR}/include/GL/glfw3.h internal.h) +set(common_SOURCES clipboard.c error.c fullscreen.c gamma.c init.c input.c joystick.c monitor.c opengl.c time.c window.c) -if(_GLFW_COCOA_NSGL) - set(libglfw_SOURCES ${common_SOURCES} cocoa_fullscreen.m cocoa_gamma.m - cocoa_init.m cocoa_input.m cocoa_joystick.m - cocoa_opengl.m cocoa_time.m cocoa_window.m) +if (_GLFW_COCOA_NSGL) + set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h) + set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_fullscreen.m + cocoa_gamma.c cocoa_init.m cocoa_input.m cocoa_joystick.m + cocoa_opengl.m cocoa_time.c cocoa_window.m) # For some reason, CMake doesn't know about .m - set_source_files_properties(${libglfw_SOURCES} PROPERTIES LANGUAGE C) -elseif(_GLFW_WIN32_WGL) - set(libglfw_SOURCES ${common_SOURCES} win32_fullscreen.c win32_gamma.c - win32_init.c win32_input.c win32_joystick.c - win32_opengl.c win32_time.c win32_window.c - win32_dllmain.c win32_monitor.c) -elseif(_GLFW_X11_GLX) - set(libglfw_SOURCES ${common_SOURCES} x11_fullscreen.c x11_gamma.c - x11_init.c x11_input.c x11_joystick.c - x11_keysym2unicode.c x11_monitor.c x11_opengl.c - x11_time.c x11_window.c) -else() - message(FATAL_ERROR "No supported platform was selected") -endif(_GLFW_COCOA_NSGL) + set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C) +elseif (_GLFW_WIN32_WGL) + set(glfw_HEADERS ${common_HEADERS} win32_platform.h) + set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_dllmain.c + win32_fullscreen.c win32_gamma.c win32_init.c win32_input.c + win32_joystick.c win32_monitor.c win32_opengl.c + win32_time.c win32_window.c) +elseif (_GLFW_X11_GLX) + set(glfw_HEADERS ${common_HEADERS} x11_platform.h) + set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c + x11_gamma.c x11_init.c x11_input.c x11_joystick.c + x11_keysym2unicode.c x11_monitor.c x11_opengl.c x11_time.c + x11_window.c) +endif() -add_library(libglfwStatic STATIC ${libglfw_SOURCES}) -add_library(libglfwShared SHARED ${libglfw_SOURCES}) -target_link_libraries(libglfwShared ${GLFW_LIBRARIES}) -set_target_properties(libglfwStatic libglfwShared PROPERTIES - CLEAN_DIRECT_OUTPUT 1 - OUTPUT_NAME glfw) +add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS}) -if(WIN32) - # The GLFW DLL needs a special compile-time macro and import library name - set_target_properties(libglfwShared PROPERTIES - DEFINE_SYMBOL GLFW_BUILD_DLL - PREFIX "" - IMPORT_PREFIX "" - IMPORT_SUFFIX "dll.lib") -endif(WIN32) +if (BUILD_SHARED_LIBS) -if(APPLE) - # Append -fno-common to the compile flags to work around a bug in the Apple GCC - get_target_property(CFLAGS libglfwShared COMPILE_FLAGS) - if(NOT CFLAGS) - set(CFLAGS "") - endif(NOT CFLAGS) - set_target_properties(libglfwShared PROPERTIES COMPILE_FLAGS "${CFLAGS} -fno-common") -endif(APPLE) + if (_GLFW_WIN32_WGL) + # The GLFW DLL needs a special compile-time macro and import library name + set_target_properties(glfw PROPERTIES + PREFIX "" + IMPORT_PREFIX "" + IMPORT_SUFFIX "dll.lib") + elseif (_GLFW_COCOA_NSGL) + # Append -fno-common to the compile flags to work around a bug in the Apple GCC + get_target_property(glfw_CFLAGS glfw COMPILE_FLAGS) + if (NOT glfw_CFLAGS) + set(glfw_CFLAGS "") + endif() + set_target_properties(glfw PROPERTIES + COMPILE_FLAGS "${glfw_CFLAGS} -fno-common") + endif() -install(TARGETS libglfwStatic libglfwShared DESTINATION lib) + target_link_libraries(glfw ${glfw_LIBRARIES}) + target_link_libraries(glfw LINK_INTERFACE_LIBRARIES) +endif() + +install(TARGETS glfw DESTINATION lib) diff --git a/src/cocoa_time.m b/src/clipboard.c similarity index 66% rename from src/cocoa_time.m rename to src/clipboard.c index d7e7d2b8..0bdea5b4 100644 --- a/src/cocoa_time.m +++ b/src/clipboard.c @@ -1,10 +1,10 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL -// API Version: 3.0 +// Platform: Any +// API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ -// Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2010 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -29,28 +29,46 @@ #include "internal.h" +#include +#include + ////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// +////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// //======================================================================== -// Return timer value in seconds +// Set the clipboard contents //======================================================================== -double _glfwPlatformGetTime(void) +GLFWAPI void glfwSetClipboardString(GLFWwindow handle, const char* string) { - return [NSDate timeIntervalSinceReferenceDate] - - _glfwLibrary.NS.timer.t0; + _GLFWwindow* window = (_GLFWwindow*) handle; + + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return; + } + + _glfwPlatformSetClipboardString(window, string); } + //======================================================================== -// Set timer value in seconds +// Return the current clipboard contents //======================================================================== -void _glfwPlatformSetTime(double time) +GLFWAPI const char* glfwGetClipboardString(GLFWwindow handle) { - _glfwLibrary.NS.timer.t0 = - [NSDate timeIntervalSinceReferenceDate] - time; + _GLFWwindow* window = (_GLFWwindow*) handle; + + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return NULL; + } + + return _glfwPlatformGetClipboardString(window); } diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m new file mode 100644 index 00000000..56b98437 --- /dev/null +++ b/src/cocoa_clipboard.m @@ -0,0 +1,82 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: Cocoa/NSOpenGL +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) +{ + NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil]; + + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard declareTypes:types owner:nil]; + [pasteboard setString:[NSString stringWithUTF8String:string] + forType:NSStringPboardType]; +} + + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) +{ + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + + if (![[pasteboard types] containsObject:NSStringPboardType]) + { + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, NULL); + return NULL; + } + + NSString* object = [pasteboard stringForType:NSStringPboardType]; + if (!object) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Cocoa/NSGL: Failed to retrieve object from pasteboard"); + return NULL; + } + + free(_glfwLibrary.NS.clipboardString); + _glfwLibrary.NS.clipboardString = strdup([object UTF8String]); + + return _glfwLibrary.NS.clipboardString; +} + diff --git a/src/cocoa_fullscreen.m b/src/cocoa_fullscreen.m index 370296b8..147913fb 100644 --- a/src/cocoa_fullscreen.m +++ b/src/cocoa_fullscreen.m @@ -29,47 +29,166 @@ #include "internal.h" +#include +#include + //======================================================================== // Check whether the display mode should be included in enumeration //======================================================================== -static BOOL modeIsGood(NSDictionary* mode) +static GLboolean modeIsGood(CGDisplayModeRef mode) { - // This is a bit controversial, if you've got something other than an - // LCD computer monitor as an output device you might not want these - // checks. You might also want to reject modes which are interlaced, - // or TV out. There is no one-size-fits-all policy that can work here. - // This seems like a decent compromise, but certain applications may - // wish to patch this... - return [[mode objectForKey:(id)kCGDisplayBitsPerPixel] intValue] >= 15 && - [mode objectForKey:(id)kCGDisplayModeIsSafeForHardware] != nil && - [mode objectForKey:(id)kCGDisplayModeIsStretched] == nil; + uint32_t flags = CGDisplayModeGetIOFlags(mode); + if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag)) + return GL_FALSE; + + if (flags & kDisplayModeInterlacedFlag) + return GL_FALSE; + + if (flags & kDisplayModeTelevisionFlag) + return GL_FALSE; + + if (flags & kDisplayModeStretchedFlag) + return GL_FALSE; + + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && + CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) + { + CFRelease(format); + return GL_FALSE; + } + + CFRelease(format); + return GL_TRUE; } + //======================================================================== // Convert Core Graphics display mode to GLFW video mode //======================================================================== -static GLFWvidmode vidmodeFromCGDisplayMode(NSDictionary* mode) +static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode) { - unsigned int width = - [[mode objectForKey:(id)kCGDisplayWidth] unsignedIntValue]; - unsigned int height = - [[mode objectForKey:(id)kCGDisplayHeight] unsignedIntValue]; - unsigned int bps = - [[mode objectForKey:(id)kCGDisplayBitsPerSample] unsignedIntValue]; - GLFWvidmode result; - result.width = width; - result.height = height; - result.redBits = bps; - result.greenBits = bps; - result.blueBits = bps; + result.width = CGDisplayModeGetWidth(mode); + result.height = CGDisplayModeGetHeight(mode); + + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) + { + result.redBits = 5; + result.greenBits = 5; + result.blueBits = 5; + } + else + { + result.redBits = 8; + result.greenBits = 8; + result.blueBits = 8; + } + + CFRelease(format); return result; } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Change the current video mode +//======================================================================== + +GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate) +{ + CGDisplayModeRef bestMode = NULL; + CFArrayRef modes; + CFIndex count, i; + unsigned int leastSizeDiff = UINT_MAX; + double leastRateDiff = DBL_MAX; + + modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); + count = CFArrayGetCount(modes); + + for (i = 0; i < count; i++) + { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (!modeIsGood(mode)) + continue; + + int modeBPP; + + // Identify display mode pixel encoding + { + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) + modeBPP = 16; + else + modeBPP = 32; + + CFRelease(format); + } + + int modeWidth = (int) CGDisplayModeGetWidth(mode); + int modeHeight = (int) CGDisplayModeGetHeight(mode); + + unsigned int sizeDiff = (abs(modeBPP - *bpp) << 25) | + ((modeWidth - *width) * (modeWidth - *width) + + (modeHeight - *height) * (modeHeight - *height)); + + double rateDiff; + + if (*refreshRate > 0) + rateDiff = fabs(CGDisplayModeGetRefreshRate(mode) - *refreshRate); + else + { + // If no refresh rate was specified, then they're all the same + rateDiff = 0; + } + + if ((sizeDiff < leastSizeDiff) || + (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff))) + { + bestMode = mode; + + leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; + } + } + + if (!bestMode) + { + CFRelease(modes); + return GL_FALSE; + } + + CGDisplayCapture(CGMainDisplayID()); + CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL); + + CFRelease(modes); + return GL_TRUE; +} + + +//======================================================================== +// Restore the previously saved (original) video mode +//======================================================================== + +void _glfwRestoreVideoMode(void) +{ + CGDisplaySetDisplayMode(CGMainDisplayID(), + _glfwLibrary.NS.desktopMode, + NULL); + + CGDisplayRelease(CGMainDisplayID()); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -80,19 +199,26 @@ static GLFWvidmode vidmodeFromCGDisplayMode(NSDictionary* mode) int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount) { - NSArray* modes = (NSArray*) CGDisplayAvailableModes(CGMainDisplayID()); - unsigned int i, j = 0, n = [modes count]; + CGDisplayModeRef mode; + CFArrayRef modes; + CFIndex count, i; + int stored = 0; - for (i = 0; i < n && j < (unsigned)maxcount; i++) + modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); + count = CFArrayGetCount(modes); + + for (i = 0; i < count && stored < maxcount; i++) { - NSDictionary *mode = [modes objectAtIndex:i]; + mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); if (modeIsGood(mode)) - list[j++] = vidmodeFromCGDisplayMode(mode); + list[stored++] = vidmodeFromCGDisplayMode(mode); } - return j; + CFRelease(modes); + return stored; } + //======================================================================== // Get the desktop video mode //======================================================================== diff --git a/src/cocoa_gamma.m b/src/cocoa_gamma.c similarity index 98% rename from src/cocoa_gamma.m rename to src/cocoa_gamma.c index eb291082..53c47a89 100644 --- a/src/cocoa_gamma.m +++ b/src/cocoa_gamma.c @@ -32,6 +32,8 @@ #include #include +#include + //************************************************************************ //**** GLFW internal functions **** diff --git a/src/cocoa_init.m b/src/cocoa_init.m index bf4f7c2e..7c208b90 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -27,162 +27,45 @@ // //======================================================================== -// Needed for _NSGetProgname -#include - #include "internal.h" - +#include // For MAXPATHLEN //======================================================================== -// GLFW application class +// Change to our application bundle's resources directory, if present //======================================================================== -@interface GLFWApplication : NSApplication -@end - -@implementation GLFWApplication - -// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost -// This works around an AppKit bug, where key up events while holding -// down the command key don't get sent to the key window. -- (void)sendEvent:(NSEvent *)event +static void changeToResourcesDirectory(void) { - if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) - [[self keyWindow] sendEvent:event]; - else - [super sendEvent:event]; -} + char resourcesPath[MAXPATHLEN]; -@end + CFBundleRef bundle = CFBundleGetMainBundle(); + if (!bundle) + return; + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle); -// Prior to Snow Leopard, we need to use this oddly-named semi-private API -// to get the application menu working properly. Need to be careful in -// case it goes away in a future OS update. -@interface NSApplication (NSAppleMenu) -- (void)setAppleMenu:(NSMenu*)m; -@end - -// Keys to search for as potential application names -NSString* GLFWNameKeys[] = -{ - @"CFBundleDisplayName", - @"CFBundleName", - @"CFBundleExecutable", -}; - - -//======================================================================== -// Try to figure out what the calling application is called -//======================================================================== -static NSString* findAppName(void) -{ - unsigned int i; - NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary]; - - for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++) + CFStringRef last = CFURLCopyLastPathComponent(resourcesURL); + if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo) { - id name = [infoDictionary objectForKey:GLFWNameKeys[i]]; - if (name && - [name isKindOfClass:[NSString class]] && - ![@"" isEqualToString:name]) - { - return name; - } + CFRelease(last); + CFRelease(resourcesURL); + return; } - // If we get here, we're unbundled - if (!_glfwLibrary.NS.unbundled) + CFRelease(last); + + if (!CFURLGetFileSystemRepresentation(resourcesURL, + true, + (UInt8*) resourcesPath, + MAXPATHLEN)) { - // Could do this only if we discover we're unbundled, but it should - // do no harm... - ProcessSerialNumber psn = { 0, kCurrentProcess }; - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - - // Having the app in front of the terminal window is also generally - // handy. There is an NSApplication API to do this, but... - SetFrontProcess(&psn); - - _glfwLibrary.NS.unbundled = GL_TRUE; + CFRelease(resourcesURL); + return; } - char** progname = _NSGetProgname(); - if (progname && *progname) - { - // TODO: UTF-8? - return [NSString stringWithUTF8String:*progname]; - } + CFRelease(resourcesURL); - // Really shouldn't get here - return @"GLFW Application"; -} - -//======================================================================== -// Set up the menu bar (manually) -// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that -// could go away at any moment, lots of stuff that really should be -// localize(d|able), etc. Loading a nib would save us this horror, but that -// doesn't seem like a good thing to require of GLFW's clients. -//======================================================================== -static void setUpMenuBar(void) -{ - NSString* appName = findAppName(); - - NSMenu* bar = [[NSMenu alloc] init]; - [NSApp setMainMenu:bar]; - - NSMenuItem* appMenuItem = - [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""]; - NSMenu* appMenu = [[NSMenu alloc] init]; - [appMenuItem setSubmenu:appMenu]; - - [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName] - action:@selector(orderFrontStandardAboutPanel:) - keyEquivalent:@""]; - [appMenu addItem:[NSMenuItem separatorItem]]; - NSMenu* servicesMenu = [[NSMenu alloc] init]; - [NSApp setServicesMenu:servicesMenu]; - [[appMenu addItemWithTitle:@"Services" - action:NULL - keyEquivalent:@""] setSubmenu:servicesMenu]; - [appMenu addItem:[NSMenuItem separatorItem]]; - [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName] - action:@selector(hide:) - keyEquivalent:@"h"]; - [[appMenu addItemWithTitle:@"Hide Others" - action:@selector(hideOtherApplications:) - keyEquivalent:@"h"] - setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask]; - [appMenu addItemWithTitle:@"Show All" - action:@selector(unhideAllApplications:) - keyEquivalent:@""]; - [appMenu addItem:[NSMenuItem separatorItem]]; - [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName] - action:@selector(terminate:) - keyEquivalent:@"q"]; - - NSMenuItem* windowMenuItem = - [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""]; - NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - [NSApp setWindowsMenu:windowMenu]; - [windowMenuItem setSubmenu:windowMenu]; - - [windowMenu addItemWithTitle:@"Miniaturize" - action:@selector(performMiniaturize:) - keyEquivalent:@"m"]; - [windowMenu addItemWithTitle:@"Zoom" - action:@selector(performZoom:) - keyEquivalent:@""]; - [windowMenu addItem:[NSMenuItem separatorItem]]; - [windowMenu addItemWithTitle:@"Bring All to Front" - action:@selector(arrangeInFront:) - keyEquivalent:@""]; - - // At least guard the call to private API to avoid an exception if it - // goes away. Hopefully that means the worst we'll break in future is to - // look ugly... - if ([NSApp respondsToSelector:@selector(setAppleMenu:)]) - [NSApp setAppleMenu:appMenu]; + chdir(resourcesPath); } @@ -198,43 +81,39 @@ int _glfwPlatformInit(void) { _glfwLibrary.NS.autoreleasePool = [[NSAutoreleasePool alloc] init]; - // Implicitly create shared NSApplication instance - [GLFWApplication sharedApplication]; - - _glfwLibrary.NS.OpenGLFramework = + _glfwLibrary.NSGL.framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); - if (_glfwLibrary.NS.OpenGLFramework == NULL) + if (_glfwLibrary.NSGL.framework == NULL) { _glfwSetError(GLFW_PLATFORM_ERROR, "glfwInit: Failed to locate OpenGL framework"); return GL_FALSE; } - NSString* resourcePath = [[NSBundle mainBundle] resourcePath]; + changeToResourcesDirectory(); - if (access([resourcePath cStringUsingEncoding:NSUTF8StringEncoding], R_OK) == 0) - chdir([resourcePath cStringUsingEncoding:NSUTF8StringEncoding]); - - // Setting up menu bar must go exactly here else weirdness ensues - setUpMenuBar(); - - [NSApp finishLaunching]; - - _glfwPlatformSetTime(0.0); - - _glfwLibrary.NS.desktopMode = - (NSDictionary*) CGDisplayCurrentMode(CGMainDisplayID()); + _glfwLibrary.NS.desktopMode = CGDisplayCopyDisplayMode(CGMainDisplayID()); // Save the original gamma ramp _glfwLibrary.originalRampSize = CGDisplayGammaTableCapacity(CGMainDisplayID()); _glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp); _glfwLibrary.currentRamp = _glfwLibrary.originalRamp; + _glfwInitTimer(); + _glfwInitJoysticks(); + _glfwLibrary.NS.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + if (!_glfwLibrary.NS.eventSource) + return GL_FALSE; + + CGEventSourceSetLocalEventsSuppressionInterval(_glfwLibrary.NS.eventSource, + 0.0); + return GL_TRUE; } + //======================================================================== // Close window, if open, and shut down GLFW //======================================================================== @@ -243,8 +122,17 @@ int _glfwPlatformTerminate(void) { // TODO: Probably other cleanup + if (_glfwLibrary.NS.eventSource) + { + CFRelease(_glfwLibrary.NS.eventSource); + _glfwLibrary.NS.eventSource = NULL; + } + // Restore the original gamma ramp - _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); + if (_glfwLibrary.rampChanged) + _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); + + CGDisplayModeRelease(_glfwLibrary.NS.desktopMode); [NSApp setDelegate:nil]; [_glfwLibrary.NS.delegate release]; @@ -265,7 +153,11 @@ int _glfwPlatformTerminate(void) const char* _glfwPlatformGetVersionString(void) { - const char* version = _GLFW_VERSION_FULL " Cocoa"; + const char* version = _GLFW_VERSION_FULL +#if defined(_GLFW_BUILD_DLL) + " dynamic" +#endif + ; return version; } diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index 0aa10a4a..97510fdf 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -152,7 +152,7 @@ static void addJoystickElement(_glfwJoystick* joystick, CFTypeRef refElement) long number; CFTypeRef refType; - _glfwJoystickElement* element = (_glfwJoystickElement*) _glfwMalloc(sizeof(_glfwJoystickElement)); + _glfwJoystickElement* element = (_glfwJoystickElement*) malloc(sizeof(_glfwJoystickElement)); CFArrayAppendValue(elementsArray, element); @@ -242,7 +242,7 @@ static void removeJoystick(_glfwJoystick* joystick) { _glfwJoystickElement* axes = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick->axes, i); - _glfwFree(axes); + free(axes); } CFArrayRemoveAllValues(joystick->axes); joystick->numAxes = 0; @@ -251,7 +251,7 @@ static void removeJoystick(_glfwJoystick* joystick) { _glfwJoystickElement* button = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick->buttons, i); - _glfwFree(button); + free(button); } CFArrayRemoveAllValues(joystick->buttons); joystick->numButtons = 0; @@ -260,7 +260,7 @@ static void removeJoystick(_glfwJoystick* joystick) { _glfwJoystickElement* hat = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick->hats, i); - _glfwFree(hat); + free(hat); } CFArrayRemoveAllValues(joystick->hats); joystick->hats = 0; @@ -311,6 +311,13 @@ static void pollJoystickEvents(void) (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick->axes, j); axes->value = getElementValue(joystick, axes); } + + for (j = 0; j < joystick->numHats; j++) + { + _glfwJoystickElement* hat = + (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick->hats, j); + hat->value = getElementValue(joystick, hat); + } } } } @@ -336,7 +343,12 @@ void _glfwInitJoysticks(void) result = IOMasterPort(bootstrap_port, &masterPort); hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); if (kIOReturnSuccess != result || !hidMatchDictionary) + { + if (hidMatchDictionary) + CFRelease(hidMatchDictionary); + return; + } result = IOServiceGetMatchingServices(masterPort, hidMatchDictionary, @@ -370,19 +382,27 @@ void _glfwInitJoysticks(void) /* Check device type */ refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (refCF) + { CFNumberGetValue(refCF, kCFNumberLongType, &usagePage); + if (usagePage != kHIDPage_GenericDesktop) + { + /* We are not interested in this device */ + continue; + } + } refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); if (refCF) - CFNumberGetValue(refCF, kCFNumberLongType, &usage); - - if ((usagePage != kHIDPage_GenericDesktop) || - (usage != kHIDUsage_GD_Joystick && - usage != kHIDUsage_GD_GamePad && - usage != kHIDUsage_GD_MultiAxisController)) { - /* We don't interested in this device */ - continue; + CFNumberGetValue(refCF, kCFNumberLongType, &usage); + + if ((usage != kHIDUsage_GD_Joystick && + usage != kHIDUsage_GD_GamePad && + usage != kHIDUsage_GD_MultiAxisController)) + { + /* We are not interested in this device */ + continue; + } } _glfwJoystick* joystick = &_glfwJoysticks[deviceCounter]; @@ -489,7 +509,7 @@ int _glfwPlatformGetJoystickParam(int joy, int param) return (int) CFArrayGetCount(_glfwJoysticks[joy].axes); case GLFW_BUTTONS: - return (int) CFArrayGetCount(_glfwJoysticks[joy].buttons); + return (int) CFArrayGetCount(_glfwJoysticks[joy].buttons) + ((int) CFArrayGetCount(_glfwJoysticks[joy].hats)) * 4; default: break; @@ -552,7 +572,7 @@ int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons) { - int i; + int i, j, button; if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST) return 0; @@ -565,18 +585,31 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, return 0; } - numbuttons = numbuttons < joystick.numButtons ? numbuttons : joystick.numButtons; - // Update joystick state pollJoystickEvents(); - for (i = 0; i < numbuttons; i++) + for (button = 0; button < numbuttons && button < joystick.numButtons; button++) { - _glfwJoystickElement* button = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick.buttons, i); - buttons[i] = button->value ? GLFW_PRESS : GLFW_RELEASE; + _glfwJoystickElement* element = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick.buttons, button); + buttons[button] = element->value ? GLFW_PRESS : GLFW_RELEASE; } - return numbuttons; + // Virtual buttons - Inject data from hats + // Each hat is exposed as 4 buttons which exposes 8 directions with concurrent button presses + + const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; // Bit fields of button presses for each direction, including nil + + for (i = 0; i < joystick.numHats; i++) + { + _glfwJoystickElement* hat = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick.hats, i); + int value = hat->value; + if (value < 0 || value > 8) value = 8; + + for (j = 0; j < 4 && button < numbuttons; j++) + { + buttons[button++] = directions[value] & (1 << j) ? GLFW_PRESS : GLFW_RELEASE; + } + } + + return button; } - - diff --git a/src/cocoa_opengl.m b/src/cocoa_opengl.m index bd3827fc..b04efaee 100644 --- a/src/cocoa_opengl.m +++ b/src/cocoa_opengl.m @@ -59,6 +59,7 @@ void _glfwPlatformSwapBuffers(void) [window->NSGL.context flushBuffer]; } + //======================================================================== // Set double buffering swap interval //======================================================================== @@ -71,6 +72,7 @@ void _glfwPlatformSwapInterval(int interval) [window->NSGL.context setValues:&sync forParameter:NSOpenGLCPSwapInterval]; } + //======================================================================== // Check if an OpenGL extension is available at runtime //======================================================================== @@ -81,24 +83,26 @@ int _glfwPlatformExtensionSupported(const char* extension) return GL_FALSE; } + //======================================================================== // Get the function pointer to an OpenGL function //======================================================================== -void* _glfwPlatformGetProcAddress(const char* procname) +GLFWglproc _glfwPlatformGetProcAddress(const char* procname) { CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII); - void* symbol = CFBundleGetFunctionPointerForName(_glfwLibrary.NS.OpenGLFramework, - symbolName); + GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfwLibrary.NSGL.framework, + symbolName); CFRelease(symbolName); return symbol; } + //======================================================================== // Copies the specified OpenGL state categories from src to dst //======================================================================== diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index d5daf775..97e903d7 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -37,13 +37,15 @@ #if defined(__OBJC__) #import #else +#include typedef void* id; #endif #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS NS -#define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryNS NS #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL NSGL +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS NS +#define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryNSGL NSGL //======================================================================== @@ -71,39 +73,55 @@ typedef struct _GLFWcontextNSGL //------------------------------------------------------------------------ typedef struct _GLFWwindowNS { - id window; + id object; id delegate; + id view; unsigned int modifierFlags; - double fracScrollX; - double fracScrollY; } _GLFWwindowNS; //------------------------------------------------------------------------ -// Platform-specific library global data +// Platform-specific library global data for Cocoa //------------------------------------------------------------------------ typedef struct _GLFWlibraryNS { struct { - double t0; + double base; + double resolution; } timer; - // dlopen handle for dynamically loading OpenGL extension entry points - void* OpenGLFramework; - GLboolean unbundled; - id desktopMode; - id delegate; - id autoreleasePool; + CGDisplayModeRef desktopMode; + CGEventSourceRef eventSource; + id delegate; + id autoreleasePool; + + char* clipboardString; } _GLFWlibraryNS; +//------------------------------------------------------------------------ +// Platform-specific library global data for NSGL +//------------------------------------------------------------------------ +typedef struct _GLFWlibraryNSGL +{ + // dlopen handle for dynamically loading OpenGL extension entry points + void* framework; +} _GLFWlibraryNSGL; + + //======================================================================== // Prototypes for platform specific internal functions //======================================================================== +// Time +void _glfwInitTimer(void); + // Joystick input void _glfwInitJoysticks(void); void _glfwTerminateJoysticks(void); +// Fullscreen +GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate); +void _glfwRestoreVideoMode(void); #endif // _platform_h_ diff --git a/src/cocoa_time.c b/src/cocoa_time.c new file mode 100644 index 00000000..745b4239 --- /dev/null +++ b/src/cocoa_time.c @@ -0,0 +1,87 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: Cocoa/NSOpenGL +// API Version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2009-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include + + +//======================================================================== +// Return raw time +//======================================================================== + +static uint64_t getRawTime(void) +{ + return mach_absolute_time(); +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Initialise timer +//======================================================================== + +void _glfwInitTimer(void) +{ + mach_timebase_info_data_t info; + mach_timebase_info(&info); + + _glfwLibrary.NS.timer.resolution = (double) info.numer / (info.denom * 1.0e9); + _glfwLibrary.NS.timer.base = getRawTime(); +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Return timer value in seconds +//======================================================================== + +double _glfwPlatformGetTime(void) +{ + return (double) (getRawTime() - _glfwLibrary.NS.timer.base) * + _glfwLibrary.NS.timer.resolution; +} + + +//======================================================================== +// Set timer value in seconds +//======================================================================== + +void _glfwPlatformSetTime(double time) +{ + _glfwLibrary.NS.timer.base = getRawTime() - + (uint64_t) (time / _glfwLibrary.NS.timer.resolution); +} + diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 264ba6ef..3523806a 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -29,6 +29,9 @@ #include "internal.h" +// Needed for _NSGetProgname +#include + //======================================================================== // Delegate for window related notifications @@ -66,7 +69,7 @@ [window->NSGL.context update]; NSRect contentRect = - [window->NS.window contentRectForFrameRect:[window->NS.window frame]]; + [window->NS.object contentRectForFrameRect:[window->NS.object frame]]; _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height); } @@ -76,7 +79,7 @@ [window->NSGL.context update]; NSRect contentRect = - [window->NS.window contentRectForFrameRect:[window->NS.window frame]]; + [window->NS.object contentRectForFrameRect:[window->NS.object frame]]; CGPoint mainScreenOrigin = CGDisplayBounds(CGMainDisplayID()).origin; double mainScreenHeight = CGDisplayBounds(CGMainDisplayID()).size.height; @@ -109,6 +112,7 @@ @end + //======================================================================== // Delegate for application related notifications //======================================================================== @@ -130,142 +134,6 @@ @end -//======================================================================== -// Keyboard symbol translation table -//======================================================================== - -// TODO: Need to find mappings for F13-F15, volume down/up/mute, and eject. -static const unsigned int MAC_TO_GLFW_KEYCODE_MAPPING[128] = -{ - /* 00 */ GLFW_KEY_A, - /* 01 */ GLFW_KEY_S, - /* 02 */ GLFW_KEY_D, - /* 03 */ GLFW_KEY_F, - /* 04 */ GLFW_KEY_H, - /* 05 */ GLFW_KEY_G, - /* 06 */ GLFW_KEY_Z, - /* 07 */ GLFW_KEY_X, - /* 08 */ GLFW_KEY_C, - /* 09 */ GLFW_KEY_V, - /* 0a */ GLFW_KEY_GRAVE_ACCENT, - /* 0b */ GLFW_KEY_B, - /* 0c */ GLFW_KEY_Q, - /* 0d */ GLFW_KEY_W, - /* 0e */ GLFW_KEY_E, - /* 0f */ GLFW_KEY_R, - /* 10 */ GLFW_KEY_Y, - /* 11 */ GLFW_KEY_T, - /* 12 */ GLFW_KEY_1, - /* 13 */ GLFW_KEY_2, - /* 14 */ GLFW_KEY_3, - /* 15 */ GLFW_KEY_4, - /* 16 */ GLFW_KEY_6, - /* 17 */ GLFW_KEY_5, - /* 18 */ GLFW_KEY_EQUAL, - /* 19 */ GLFW_KEY_9, - /* 1a */ GLFW_KEY_7, - /* 1b */ GLFW_KEY_MINUS, - /* 1c */ GLFW_KEY_8, - /* 1d */ GLFW_KEY_0, - /* 1e */ GLFW_KEY_RIGHT_BRACKET, - /* 1f */ GLFW_KEY_O, - /* 20 */ GLFW_KEY_U, - /* 21 */ GLFW_KEY_LEFT_BRACKET, - /* 22 */ GLFW_KEY_I, - /* 23 */ GLFW_KEY_P, - /* 24 */ GLFW_KEY_ENTER, - /* 25 */ GLFW_KEY_L, - /* 26 */ GLFW_KEY_J, - /* 27 */ GLFW_KEY_APOSTROPHE, - /* 28 */ GLFW_KEY_K, - /* 29 */ GLFW_KEY_SEMICOLON, - /* 2a */ GLFW_KEY_BACKSLASH, - /* 2b */ GLFW_KEY_COMMA, - /* 2c */ GLFW_KEY_SLASH, - /* 2d */ GLFW_KEY_N, - /* 2e */ GLFW_KEY_M, - /* 2f */ GLFW_KEY_PERIOD, - /* 30 */ GLFW_KEY_TAB, - /* 31 */ GLFW_KEY_SPACE, - /* 32 */ GLFW_KEY_WORLD_1, - /* 33 */ GLFW_KEY_BACKSPACE, - /* 34 */ -1, - /* 35 */ GLFW_KEY_ESCAPE, - /* 36 */ GLFW_KEY_RIGHT_SUPER, - /* 37 */ GLFW_KEY_LEFT_SUPER, - /* 38 */ GLFW_KEY_LEFT_SHIFT, - /* 39 */ GLFW_KEY_CAPS_LOCK, - /* 3a */ GLFW_KEY_LEFT_ALT, - /* 3b */ GLFW_KEY_LEFT_CONTROL, - /* 3c */ GLFW_KEY_RIGHT_SHIFT, - /* 3d */ GLFW_KEY_RIGHT_ALT, - /* 3e */ GLFW_KEY_RIGHT_CONTROL, - /* 3f */ -1, /* Function */ - /* 40 */ GLFW_KEY_F17, - /* 41 */ GLFW_KEY_KP_DECIMAL, - /* 42 */ -1, - /* 43 */ GLFW_KEY_KP_MULTIPLY, - /* 44 */ -1, - /* 45 */ GLFW_KEY_KP_ADD, - /* 46 */ -1, - /* 47 */ GLFW_KEY_NUM_LOCK, /* Really KeypadClear... */ - /* 48 */ -1, /* VolumeUp */ - /* 49 */ -1, /* VolumeDown */ - /* 4a */ -1, /* Mute */ - /* 4b */ GLFW_KEY_KP_DIVIDE, - /* 4c */ GLFW_KEY_KP_ENTER, - /* 4d */ -1, - /* 4e */ GLFW_KEY_KP_SUBTRACT, - /* 4f */ GLFW_KEY_F18, - /* 50 */ GLFW_KEY_F19, - /* 51 */ GLFW_KEY_KP_EQUAL, - /* 52 */ GLFW_KEY_KP_0, - /* 53 */ GLFW_KEY_KP_1, - /* 54 */ GLFW_KEY_KP_2, - /* 55 */ GLFW_KEY_KP_3, - /* 56 */ GLFW_KEY_KP_4, - /* 57 */ GLFW_KEY_KP_5, - /* 58 */ GLFW_KEY_KP_6, - /* 59 */ GLFW_KEY_KP_7, - /* 5a */ GLFW_KEY_F20, - /* 5b */ GLFW_KEY_KP_8, - /* 5c */ GLFW_KEY_KP_9, - /* 5d */ -1, - /* 5e */ -1, - /* 5f */ -1, - /* 60 */ GLFW_KEY_F5, - /* 61 */ GLFW_KEY_F6, - /* 62 */ GLFW_KEY_F7, - /* 63 */ GLFW_KEY_F3, - /* 64 */ GLFW_KEY_F8, - /* 65 */ GLFW_KEY_F9, - /* 66 */ -1, - /* 67 */ GLFW_KEY_F11, - /* 68 */ -1, - /* 69 */ GLFW_KEY_F13, - /* 6a */ GLFW_KEY_F16, - /* 6b */ GLFW_KEY_F14, - /* 6c */ -1, - /* 6d */ GLFW_KEY_F10, - /* 6e */ -1, - /* 6f */ GLFW_KEY_F12, - /* 70 */ -1, - /* 71 */ GLFW_KEY_F15, - /* 72 */ GLFW_KEY_INSERT, /* Really Help... */ - /* 73 */ GLFW_KEY_HOME, - /* 74 */ GLFW_KEY_PAGE_UP, - /* 75 */ GLFW_KEY_DELETE, - /* 76 */ GLFW_KEY_F4, - /* 77 */ GLFW_KEY_END, - /* 78 */ GLFW_KEY_F2, - /* 79 */ GLFW_KEY_PAGE_DOWN, - /* 7a */ GLFW_KEY_F1, - /* 7b */ GLFW_KEY_LEFT, - /* 7c */ GLFW_KEY_RIGHT, - /* 7d */ GLFW_KEY_DOWN, - /* 7e */ GLFW_KEY_UP, - /* 7f */ -1, -}; //======================================================================== // Converts a Mac OS X keycode to a GLFW keycode @@ -273,15 +141,150 @@ static const unsigned int MAC_TO_GLFW_KEYCODE_MAPPING[128] = static int convertMacKeyCode(unsigned int macKeyCode) { + // Keyboard symbol translation table + // TODO: Need to find mappings for F13-F15, volume down/up/mute, and eject. + static const unsigned int table[128] = + { + /* 00 */ GLFW_KEY_A, + /* 01 */ GLFW_KEY_S, + /* 02 */ GLFW_KEY_D, + /* 03 */ GLFW_KEY_F, + /* 04 */ GLFW_KEY_H, + /* 05 */ GLFW_KEY_G, + /* 06 */ GLFW_KEY_Z, + /* 07 */ GLFW_KEY_X, + /* 08 */ GLFW_KEY_C, + /* 09 */ GLFW_KEY_V, + /* 0a */ GLFW_KEY_GRAVE_ACCENT, + /* 0b */ GLFW_KEY_B, + /* 0c */ GLFW_KEY_Q, + /* 0d */ GLFW_KEY_W, + /* 0e */ GLFW_KEY_E, + /* 0f */ GLFW_KEY_R, + /* 10 */ GLFW_KEY_Y, + /* 11 */ GLFW_KEY_T, + /* 12 */ GLFW_KEY_1, + /* 13 */ GLFW_KEY_2, + /* 14 */ GLFW_KEY_3, + /* 15 */ GLFW_KEY_4, + /* 16 */ GLFW_KEY_6, + /* 17 */ GLFW_KEY_5, + /* 18 */ GLFW_KEY_EQUAL, + /* 19 */ GLFW_KEY_9, + /* 1a */ GLFW_KEY_7, + /* 1b */ GLFW_KEY_MINUS, + /* 1c */ GLFW_KEY_8, + /* 1d */ GLFW_KEY_0, + /* 1e */ GLFW_KEY_RIGHT_BRACKET, + /* 1f */ GLFW_KEY_O, + /* 20 */ GLFW_KEY_U, + /* 21 */ GLFW_KEY_LEFT_BRACKET, + /* 22 */ GLFW_KEY_I, + /* 23 */ GLFW_KEY_P, + /* 24 */ GLFW_KEY_ENTER, + /* 25 */ GLFW_KEY_L, + /* 26 */ GLFW_KEY_J, + /* 27 */ GLFW_KEY_APOSTROPHE, + /* 28 */ GLFW_KEY_K, + /* 29 */ GLFW_KEY_SEMICOLON, + /* 2a */ GLFW_KEY_BACKSLASH, + /* 2b */ GLFW_KEY_COMMA, + /* 2c */ GLFW_KEY_SLASH, + /* 2d */ GLFW_KEY_N, + /* 2e */ GLFW_KEY_M, + /* 2f */ GLFW_KEY_PERIOD, + /* 30 */ GLFW_KEY_TAB, + /* 31 */ GLFW_KEY_SPACE, + /* 32 */ GLFW_KEY_WORLD_1, + /* 33 */ GLFW_KEY_BACKSPACE, + /* 34 */ -1, + /* 35 */ GLFW_KEY_ESCAPE, + /* 36 */ GLFW_KEY_RIGHT_SUPER, + /* 37 */ GLFW_KEY_LEFT_SUPER, + /* 38 */ GLFW_KEY_LEFT_SHIFT, + /* 39 */ GLFW_KEY_CAPS_LOCK, + /* 3a */ GLFW_KEY_LEFT_ALT, + /* 3b */ GLFW_KEY_LEFT_CONTROL, + /* 3c */ GLFW_KEY_RIGHT_SHIFT, + /* 3d */ GLFW_KEY_RIGHT_ALT, + /* 3e */ GLFW_KEY_RIGHT_CONTROL, + /* 3f */ -1, /* Function */ + /* 40 */ GLFW_KEY_F17, + /* 41 */ GLFW_KEY_KP_DECIMAL, + /* 42 */ -1, + /* 43 */ GLFW_KEY_KP_MULTIPLY, + /* 44 */ -1, + /* 45 */ GLFW_KEY_KP_ADD, + /* 46 */ -1, + /* 47 */ GLFW_KEY_NUM_LOCK, /* Really KeypadClear... */ + /* 48 */ -1, /* VolumeUp */ + /* 49 */ -1, /* VolumeDown */ + /* 4a */ -1, /* Mute */ + /* 4b */ GLFW_KEY_KP_DIVIDE, + /* 4c */ GLFW_KEY_KP_ENTER, + /* 4d */ -1, + /* 4e */ GLFW_KEY_KP_SUBTRACT, + /* 4f */ GLFW_KEY_F18, + /* 50 */ GLFW_KEY_F19, + /* 51 */ GLFW_KEY_KP_EQUAL, + /* 52 */ GLFW_KEY_KP_0, + /* 53 */ GLFW_KEY_KP_1, + /* 54 */ GLFW_KEY_KP_2, + /* 55 */ GLFW_KEY_KP_3, + /* 56 */ GLFW_KEY_KP_4, + /* 57 */ GLFW_KEY_KP_5, + /* 58 */ GLFW_KEY_KP_6, + /* 59 */ GLFW_KEY_KP_7, + /* 5a */ GLFW_KEY_F20, + /* 5b */ GLFW_KEY_KP_8, + /* 5c */ GLFW_KEY_KP_9, + /* 5d */ -1, + /* 5e */ -1, + /* 5f */ -1, + /* 60 */ GLFW_KEY_F5, + /* 61 */ GLFW_KEY_F6, + /* 62 */ GLFW_KEY_F7, + /* 63 */ GLFW_KEY_F3, + /* 64 */ GLFW_KEY_F8, + /* 65 */ GLFW_KEY_F9, + /* 66 */ -1, + /* 67 */ GLFW_KEY_F11, + /* 68 */ -1, + /* 69 */ GLFW_KEY_F13, + /* 6a */ GLFW_KEY_F16, + /* 6b */ GLFW_KEY_F14, + /* 6c */ -1, + /* 6d */ GLFW_KEY_F10, + /* 6e */ -1, + /* 6f */ GLFW_KEY_F12, + /* 70 */ -1, + /* 71 */ GLFW_KEY_F15, + /* 72 */ GLFW_KEY_INSERT, /* Really Help... */ + /* 73 */ GLFW_KEY_HOME, + /* 74 */ GLFW_KEY_PAGE_UP, + /* 75 */ GLFW_KEY_DELETE, + /* 76 */ GLFW_KEY_F4, + /* 77 */ GLFW_KEY_END, + /* 78 */ GLFW_KEY_F2, + /* 79 */ GLFW_KEY_PAGE_DOWN, + /* 7a */ GLFW_KEY_F1, + /* 7b */ GLFW_KEY_LEFT, + /* 7c */ GLFW_KEY_RIGHT, + /* 7d */ GLFW_KEY_DOWN, + /* 7e */ GLFW_KEY_UP, + /* 7f */ -1, + }; + if (macKeyCode >= 128) return -1; // This treats keycodes as *positional*; that is, we'll return 'a' // for the key left of 's', even on an AZERTY keyboard. The charInput // function should still get 'q' though. - return MAC_TO_GLFW_KEYCODE_MAPPING[macKeyCode]; + return table[macKeyCode]; } + //======================================================================== // Content view class for the GLFW window //======================================================================== @@ -289,6 +292,7 @@ static int convertMacKeyCode(unsigned int macKeyCode) @interface GLFWContentView : NSView { _GLFWwindow* window; + NSTrackingArea* trackingArea; } - (id)initWithGlfwWindow:(_GLFWwindow *)initWindow; @@ -301,11 +305,22 @@ static int convertMacKeyCode(unsigned int macKeyCode) { self = [super init]; if (self != nil) + { window = initWindow; + trackingArea = nil; + + [self updateTrackingAreas]; + } return self; } +-(void)dealloc +{ + [trackingArea release]; + [super dealloc]; +} + - (BOOL)isOpaque { return YES; @@ -342,12 +357,13 @@ static int convertMacKeyCode(unsigned int macKeyCode) _glfwInputCursorMotion(window, [event deltaX], [event deltaY]); else { - NSPoint p = [event locationInWindow]; + const NSPoint p = [event locationInWindow]; // Cocoa coordinate system has origin at lower left - p.y = [[window->NS.window contentView] bounds].size.height - p.y; + const int x = lround(floor(p.x)); + const int y = window->height - lround(ceil(p.y)); - _glfwInputCursorMotion(window, p.x, p.y); + _glfwInputCursorMotion(window, x, y); } } @@ -381,15 +397,45 @@ static int convertMacKeyCode(unsigned int macKeyCode) _glfwInputMouseClick(window, [event buttonNumber], GLFW_RELEASE); } +- (void)mouseExited:(NSEvent *)event +{ + _glfwInputCursorEnter(window, GL_FALSE); +} + +- (void)mouseEntered:(NSEvent *)event +{ + _glfwInputCursorEnter(window, GL_TRUE); +} + +- (void)updateTrackingAreas +{ + if (trackingArea != nil) + { + [self removeTrackingArea:trackingArea]; + [trackingArea release]; + } + + NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | + NSTrackingActiveAlways | + NSTrackingInVisibleRect; + + trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] + options:options + owner:self + userInfo:nil]; + + [self addTrackingArea:trackingArea]; +} + - (void)keyDown:(NSEvent *)event { NSUInteger i, length; NSString* characters; - int code = convertMacKeyCode([event keyCode]); + int key = convertMacKeyCode([event keyCode]); - if (code != -1) + if (key != -1) { - _glfwInputKey(window, code, GLFW_PRESS); + _glfwInputKey(window, key, GLFW_PRESS); if ([event modifierFlags] & NSCommandKeyMask) { @@ -409,7 +455,7 @@ static int convertMacKeyCode(unsigned int macKeyCode) - (void)flagsChanged:(NSEvent *)event { - int mode; + int mode, key; unsigned int newModifierFlags = [event modifierFlags] | NSDeviceIndependentModifierFlagsMask; @@ -419,30 +465,193 @@ static int convertMacKeyCode(unsigned int macKeyCode) mode = GLFW_RELEASE; window->NS.modifierFlags = newModifierFlags; - _glfwInputKey(window, MAC_TO_GLFW_KEYCODE_MAPPING[[event keyCode]], mode); + + key = convertMacKeyCode([event keyCode]); + if (key != -1) + _glfwInputKey(window, key, mode); } - (void)keyUp:(NSEvent *)event { - int code = convertMacKeyCode([event keyCode]); - if (code != -1) - _glfwInputKey(window, code, GLFW_RELEASE); + int key = convertMacKeyCode([event keyCode]); + if (key != -1) + _glfwInputKey(window, key, GLFW_RELEASE); } - (void)scrollWheel:(NSEvent *)event { - double deltaX = window->NS.fracScrollX + [event deltaX]; - double deltaY = window->NS.fracScrollY + [event deltaY]; + double deltaX = [event deltaX]; + double deltaY = [event deltaY]; - if ((int) deltaX || (int) deltaY) - _glfwInputScroll(window, (int) deltaX, (int) deltaY); - - window->NS.fracScrollX = (int) (deltaX - floor(deltaX)); - window->NS.fracScrollY = (int) (deltaY - floor(deltaY)); + if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0) + _glfwInputScroll(window, deltaX, deltaY); } @end + +//======================================================================== +// GLFW application class +//======================================================================== + +@interface GLFWApplication : NSApplication +@end + +@implementation GLFWApplication + +// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost +// This works around an AppKit bug, where key up events while holding +// down the command key don't get sent to the key window. +- (void)sendEvent:(NSEvent *)event +{ + if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) + [[self keyWindow] sendEvent:event]; + else + [super sendEvent:event]; +} + +@end + + +//======================================================================== +// Try to figure out what the calling application is called +//======================================================================== + +static NSString* findAppName(void) +{ + unsigned int i; + NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary]; + + // Keys to search for as potential application names + NSString* GLFWNameKeys[] = + { + @"CFBundleDisplayName", + @"CFBundleName", + @"CFBundleExecutable", + }; + + for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++) + { + id name = [infoDictionary objectForKey:GLFWNameKeys[i]]; + if (name && + [name isKindOfClass:[NSString class]] && + ![@"" isEqualToString:name]) + { + return name; + } + } + + // If we get here, we're unbundled + ProcessSerialNumber psn = { 0, kCurrentProcess }; + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + + // Having the app in front of the terminal window is also generally + // handy. There is an NSApplication API to do this, but... + SetFrontProcess(&psn); + + char** progname = _NSGetProgname(); + if (progname && *progname) + { + // TODO: UTF-8? + return [NSString stringWithUTF8String:*progname]; + } + + // Really shouldn't get here + return @"GLFW Application"; +} + + +//======================================================================== +// Set up the menu bar (manually) +// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that +// could go away at any moment, lots of stuff that really should be +// localize(d|able), etc. Loading a nib would save us this horror, but that +// doesn't seem like a good thing to require of GLFW's clients. +//======================================================================== + +static void createMenuBar(void) +{ + NSString* appName = findAppName(); + + NSMenu* bar = [[NSMenu alloc] init]; + [NSApp setMainMenu:bar]; + + NSMenuItem* appMenuItem = + [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""]; + NSMenu* appMenu = [[NSMenu alloc] init]; + [appMenuItem setSubmenu:appMenu]; + + [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName] + action:@selector(orderFrontStandardAboutPanel:) + keyEquivalent:@""]; + [appMenu addItem:[NSMenuItem separatorItem]]; + NSMenu* servicesMenu = [[NSMenu alloc] init]; + [NSApp setServicesMenu:servicesMenu]; + [[appMenu addItemWithTitle:@"Services" + action:NULL + keyEquivalent:@""] setSubmenu:servicesMenu]; + [appMenu addItem:[NSMenuItem separatorItem]]; + [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName] + action:@selector(hide:) + keyEquivalent:@"h"]; + [[appMenu addItemWithTitle:@"Hide Others" + action:@selector(hideOtherApplications:) + keyEquivalent:@"h"] + setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask]; + [appMenu addItemWithTitle:@"Show All" + action:@selector(unhideAllApplications:) + keyEquivalent:@""]; + [appMenu addItem:[NSMenuItem separatorItem]]; + [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName] + action:@selector(terminate:) + keyEquivalent:@"q"]; + + NSMenuItem* windowMenuItem = + [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""]; + NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + [NSApp setWindowsMenu:windowMenu]; + [windowMenuItem setSubmenu:windowMenu]; + + [windowMenu addItemWithTitle:@"Miniaturize" + action:@selector(performMiniaturize:) + keyEquivalent:@"m"]; + [windowMenu addItemWithTitle:@"Zoom" + action:@selector(performZoom:) + keyEquivalent:@""]; + [windowMenu addItem:[NSMenuItem separatorItem]]; + [windowMenu addItemWithTitle:@"Bring All to Front" + action:@selector(arrangeInFront:) + keyEquivalent:@""]; + + // Prior to Snow Leopard, we need to use this oddly-named semi-private API + // to get the application menu working properly. + [NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; +} + + +//======================================================================== +// Initialize the Cocoa Application Kit +//======================================================================== + +static GLboolean initializeAppKit(void) +{ + if (NSApp) + return GL_TRUE; + + // Implicitly create shared NSApplication instance + [GLFWApplication sharedApplication]; + + // Setting up the menu bar must go between sharedApplication + // above and finishLaunching below, in order to properly emulate the + // behavior of NSApplicationMain + createMenuBar(); + + [NSApp finishLaunching]; + + return GL_TRUE; +} + + //======================================================================== // Create the Cocoa window //======================================================================== @@ -463,29 +672,34 @@ static GLboolean createWindow(_GLFWwindow* window, else styleMask = NSBorderlessWindowMask; - window->NS.window = [[NSWindow alloc] + window->NS.object = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, window->width, window->height) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; - if (window->NS.window == nil) + if (window->NS.object == nil) { _glfwSetError(GLFW_PLATFORM_ERROR, "Cocoa/NSOpenGL: Failed to create window"); return GL_FALSE; } - [window->NS.window setTitle:[NSString stringWithUTF8String:wndconfig->title]]; - [window->NS.window setContentView:[[GLFWContentView alloc] - initWithGlfwWindow:window]]; - [window->NS.window setDelegate:window->NS.delegate]; - [window->NS.window setAcceptsMouseMovedEvents:YES]; - [window->NS.window center]; + window->NS.view = [[GLFWContentView alloc] initWithGlfwWindow:window]; + + [window->NS.object setTitle:[NSString stringWithUTF8String:wndconfig->title]]; + [window->NS.object setContentView:window->NS.view]; + [window->NS.object setDelegate:window->NS.delegate]; + [window->NS.object setAcceptsMouseMovedEvents:YES]; + [window->NS.object center]; + + if ([window->NS.object respondsToSelector:@selector(setRestorable)]) + [window->NS.object setRestorable:NO]; return GL_TRUE; } + //======================================================================== // Create the OpenGL context //======================================================================== @@ -514,14 +728,23 @@ static GLboolean createContext(_GLFWwindow* window, return GL_FALSE; } - if (wndconfig->glProfile) + if (wndconfig->glMajor > 2) { - // Fail if a profile other than core was explicitly selected + if (!wndconfig->glForward) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "Cocoa/NSOpenGL: The targeted version of Mac OS X " + "only supports OpenGL 3.2 contexts if they are " + "forward-compatible"); + return GL_FALSE; + } + if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, "Cocoa/NSOpenGL: The targeted version of Mac OS X " - "only supports the OpenGL core profile"); + "only supports OpenGL 3.2 contexts if they use the " + "core profile"); return GL_FALSE; } } @@ -549,13 +772,12 @@ static GLboolean createContext(_GLFWwindow* window, #define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); } // Arbitrary array size here - NSOpenGLPixelFormatAttribute attributes[24]; + NSOpenGLPixelFormatAttribute attributes[40]; ADD_ATTR(NSOpenGLPFADoubleBuffer); if (wndconfig->mode == GLFW_FULLSCREEN) { - ADD_ATTR(NSOpenGLPFAFullScreen); ADD_ATTR(NSOpenGLPFANoRecovery); ADD_ATTR2(NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID())); @@ -587,7 +809,7 @@ static GLboolean createContext(_GLFWwindow* window, ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); if (fbconfig->stereo) - ADD_ATTR(NSOpenGLPFAStereo ); + ADD_ATTR(NSOpenGLPFAStereo); if (fbconfig->samples > 0) { @@ -605,7 +827,7 @@ static GLboolean createContext(_GLFWwindow* window, if (window->NSGL.pixelFormat == nil) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSOpenGL: Failed to create pixel format"); + "Cocoa/NSOpenGL: Failed to create OpenGL pixel format"); return GL_FALSE; } @@ -638,9 +860,14 @@ static GLboolean createContext(_GLFWwindow* window, //======================================================================== int _glfwPlatformOpenWindow(_GLFWwindow* window, - const _GLFWwndconfig *wndconfig, - const _GLFWfbconfig *fbconfig) + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { + if (!initializeAppKit()) + return GL_FALSE; + + window->resizable = wndconfig->resizable; + // We can only have one application delegate, but we only allocate it the // first time we create a window to keep all window code in this file if (_glfwLibrary.NS.delegate == nil) @@ -672,56 +899,31 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, else if (colorBits < 15) colorBits = 15; - // Ignored hints: - // OpenGLMajor, OpenGLMinor, OpenGLForward: - // pending Mac OS X support for OpenGL 3.x - // OpenGLDebug - // pending it meaning anything on Mac OS X - // Don't use accumulation buffer support; it's not accelerated // Aux buffers probably aren't accelerated either - CFDictionaryRef fullscreenMode = NULL; - if (wndconfig->mode == GLFW_FULLSCREEN) - { - // I think it's safe to pass 0 to the refresh rate for this function - // rather than conditionalizing the code to call the version which - // doesn't specify refresh... - fullscreenMode = - CGDisplayBestModeForParametersAndRefreshRateWithProperty( - CGMainDisplayID(), - colorBits + fbconfig->alphaBits, - window->width, window->height, - wndconfig->refreshRate, - // Controversial, see macosx_fullscreen.m for discussion - kCGDisplayModeIsSafeForHardware, - NULL); - - window->width = - [[(id)fullscreenMode objectForKey:(id)kCGDisplayWidth] intValue]; - window->height = - [[(id)fullscreenMode objectForKey:(id)kCGDisplayHeight] intValue]; - } - if (!createWindow(window, wndconfig)) return GL_FALSE; if (!createContext(window, wndconfig, fbconfig)) return GL_FALSE; - [window->NS.window makeKeyAndOrderFront:nil]; - [window->NSGL.context setView:[window->NS.window contentView]]; + [window->NS.object makeKeyAndOrderFront:nil]; + [window->NSGL.context setView:[window->NS.object contentView]]; if (wndconfig->mode == GLFW_FULLSCREEN) { - CGCaptureAllDisplays(); - CGDisplaySwitchToMode(CGMainDisplayID(), fullscreenMode); - } + int bpp = colorBits + fbconfig->alphaBits; - if (wndconfig->mode == GLFW_FULLSCREEN) - { - // TODO: Make this work on pre-Leopard systems - [[window->NS.window contentView] enterFullScreenMode:[NSScreen mainScreen] + if (!_glfwSetVideoMode(&window->width, + &window->height, + &bpp, + &window->refreshRate)) + { + return GL_FALSE; + } + + [[window->NS.object contentView] enterFullScreenMode:[NSScreen mainScreen] withOptions:nil]; } @@ -743,15 +945,13 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, void _glfwPlatformCloseWindow(_GLFWwindow* window) { - [window->NS.window orderOut:nil]; + [window->NS.object orderOut:nil]; if (window->mode == GLFW_FULLSCREEN) { - [[window->NS.window contentView] exitFullScreenModeWithOptions:nil]; + [[window->NS.object contentView] exitFullScreenModeWithOptions:nil]; - CGDisplaySwitchToMode(CGMainDisplayID(), - (CFDictionaryRef) _glfwLibrary.NS.desktopMode); - CGReleaseAllDisplays(); + _glfwRestoreVideoMode(); } [window->NSGL.pixelFormat release]; @@ -761,34 +961,40 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) [window->NSGL.context release]; window->NSGL.context = nil; - [window->NS.window setDelegate:nil]; + [window->NS.object setDelegate:nil]; [window->NS.delegate release]; window->NS.delegate = nil; - [window->NS.window close]; - window->NS.window = nil; + [window->NS.view release]; + window->NS.view = nil; + + [window->NS.object close]; + window->NS.object = nil; // TODO: Probably more cleanup } + //======================================================================== // Set the window title //======================================================================== void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title) { - [window->NS.window setTitle:[NSString stringWithUTF8String:title]]; + [window->NS.object setTitle:[NSString stringWithUTF8String:title]]; } + //======================================================================== // Set the window size //======================================================================== void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { - [window->NS.window setContentSize:NSMakeSize(width, height)]; + [window->NS.object setContentSize:NSMakeSize(width, height)]; } + //======================================================================== // Set the window position //======================================================================== @@ -796,37 +1002,40 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y) { NSRect contentRect = - [window->NS.window contentRectForFrameRect:[window->NS.window frame]]; + [window->NS.object contentRectForFrameRect:[window->NS.object frame]]; // We assume here that the client code wants to position the window within the // screen the window currently occupies - NSRect screenRect = [[window->NS.window screen] visibleFrame]; + NSRect screenRect = [[window->NS.object screen] visibleFrame]; contentRect.origin = NSMakePoint(screenRect.origin.x + x, screenRect.origin.y + screenRect.size.height - y - contentRect.size.height); - [window->NS.window setFrame:[window->NS.window frameRectForContentRect:contentRect] + [window->NS.object setFrame:[window->NS.object frameRectForContentRect:contentRect] display:YES]; } + //======================================================================== // Iconify the window //======================================================================== void _glfwPlatformIconifyWindow(_GLFWwindow* window) { - [window->NS.window miniaturize:nil]; + [window->NS.object miniaturize:nil]; } + //======================================================================== // Restore (un-iconify) the window //======================================================================== void _glfwPlatformRestoreWindow(_GLFWwindow* window) { - [window->NS.window deminiaturize:nil]; + [window->NS.object deminiaturize:nil]; } + //======================================================================== // Write back window parameters into GLFW window structure //======================================================================== @@ -901,6 +1110,7 @@ void _glfwPlatformRefreshWindowParams(void) window->glDebug = GL_FALSE; } + //======================================================================== // Poll for new window and input events //======================================================================== @@ -925,6 +1135,7 @@ void _glfwPlatformPollEvents(void) _glfwLibrary.NS.autoreleasePool = [[NSAutoreleasePool alloc] init]; } + //======================================================================== // Wait for new window and input events //======================================================================== @@ -943,38 +1154,32 @@ void _glfwPlatformWaitEvents( void ) _glfwPlatformPollEvents(); } + //======================================================================== -// Set physical mouse cursor position +// Set physical cursor position //======================================================================== -void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y) +void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y) { - // The library seems to assume that after calling this the mouse won't move, - // but obviously it will, and escape the app's window, and activate other apps, - // and other badness in pain. I think the API's just silly, but maybe I'm - // misunderstanding it... - - // Also, (x, y) are window coords... - - // Also, it doesn't seem possible to write this robustly without - // calculating the maximum y coordinate of all screens, since Cocoa's - // "global coordinates" are upside down from CG's... - - // Without this (once per app run, but it's convenient to do it here) - // events will be suppressed for a default of 0.25 seconds after we - // move the cursor. - CGSetLocalEventsSuppressionInterval(0.0); - - NSPoint localPoint = NSMakePoint(x, y); - NSPoint globalPoint = [window->NS.window convertBaseToScreen:localPoint]; - CGPoint mainScreenOrigin = CGDisplayBounds(CGMainDisplayID()).origin; - double mainScreenHeight = CGDisplayBounds(CGMainDisplayID()).size.height; - CGPoint targetPoint = CGPointMake(globalPoint.x - mainScreenOrigin.x, - mainScreenHeight - globalPoint.y - - mainScreenOrigin.y); - CGDisplayMoveCursorToPoint(CGMainDisplayID(), targetPoint); + if (window->mode == GLFW_FULLSCREEN) + { + NSPoint globalPoint = NSMakePoint(x, y); + CGDisplayMoveCursorToPoint(CGMainDisplayID(), globalPoint); + } + else + { + NSPoint localPoint = NSMakePoint(x, window->height - y - 1); + NSPoint globalPoint = [window->NS.object convertBaseToScreen:localPoint]; + CGPoint mainScreenOrigin = CGDisplayBounds(CGMainDisplayID()).origin; + double mainScreenHeight = CGDisplayBounds(CGMainDisplayID()).size.height; + CGPoint targetPoint = CGPointMake(globalPoint.x - mainScreenOrigin.x, + mainScreenHeight - globalPoint.y - + mainScreenOrigin.y); + CGDisplayMoveCursorToPoint(CGMainDisplayID(), targetPoint); + } } + //======================================================================== // Set physical mouse cursor mode //======================================================================== diff --git a/src/config.h.in b/src/config.h.in index f966356c..01d541a2 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -42,28 +42,29 @@ // Define this to 1 if building GLFW for Cocoa/NSOpenGL #cmakedefine _GLFW_COCOA_NSGL +// Define this to 1 if building as a shared library / dynamic library / DLL +#cmakedefine _GLFW_BUILD_DLL + +// Define this to 1 to disable dynamic loading of winmm +#cmakedefine _GLFW_NO_DLOAD_WINMM + // Define this to 1 if XRandR is available -#cmakedefine _GLFW_HAS_XRANDR 1 +#cmakedefine _GLFW_HAS_XRANDR // Define this to 1 if Xf86VidMode is available -#cmakedefine _GLFW_HAS_XF86VIDMODE 1 +#cmakedefine _GLFW_HAS_XF86VIDMODE // Define this to 1 if Xkb is available -#cmakedefine _GLFW_HAS_XKB 1 +#cmakedefine _GLFW_HAS_XKB // Define this to 1 if glXGetProcAddress is available -#cmakedefine _GLFW_HAS_GLXGETPROCADDRESS 1 +#cmakedefine _GLFW_HAS_GLXGETPROCADDRESS // Define this to 1 if glXGetProcAddressARB is available -#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSARB 1 +#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSARB // Define this to 1 if glXGetProcAddressEXT is available -#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT 1 +#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT // Define this to 1 if the Linux joystick API is available -#cmakedefine _GLFW_USE_LINUX_JOYSTICKS 1 - -// Define this to 1 to not load gdi32.dll dynamically -#cmakedefine _GLFW_NO_DLOAD_GDI32 1 -// Define this to 1 to not load winmm.dll dynamically -#cmakedefine _GLFW_NO_DLOAD_WINMM 1 +#cmakedefine _GLFW_USE_LINUX_JOYSTICKS // The GLFW version as used by glfwGetVersionString #define _GLFW_VERSION_FULL "@GLFW_VERSION_FULL@" diff --git a/src/error.c b/src/error.c index 2b46a72c..062fb76a 100644 --- a/src/error.c +++ b/src/error.c @@ -109,6 +109,8 @@ GLFWAPI const char* glfwErrorString(int error) return "A platform-specific error occurred"; case GLFW_WINDOW_NOT_ACTIVE: return "The specified window is not active"; + case GLFW_FORMAT_UNAVAILABLE: + return "The requested format is unavailable"; } return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; diff --git a/src/gamma.c b/src/gamma.c index 34cb22f5..21940b0e 100644 --- a/src/gamma.c +++ b/src/gamma.c @@ -112,5 +112,6 @@ GLFWAPI void glfwSetGammaRamp(const GLFWgammaramp* ramp) _glfwPlatformSetGammaRamp(ramp); _glfwLibrary.currentRamp = *ramp; + _glfwLibrary.rampChanged = GL_TRUE; } diff --git a/src/init.c b/src/init.c index 8a28b5cc..336cfe25 100644 --- a/src/init.c +++ b/src/init.c @@ -35,30 +35,6 @@ #include -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Allocate memory using the allocator -//======================================================================== - -void* _glfwMalloc(size_t size) -{ - return _glfwLibrary.allocator.malloc(size); -} - - -//======================================================================== -// Free memory using the allocator -//======================================================================== - -void _glfwFree(void* ptr) -{ - _glfwLibrary.allocator.free(ptr); -} - - ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// @@ -67,31 +43,13 @@ void _glfwFree(void* ptr) // Initialize various GLFW state //======================================================================== -GLFWAPI int glfwInit(GLFWallocator* allocator) +GLFWAPI int glfwInit(void) { if (_glfwInitialized) return GL_TRUE; memset(&_glfwLibrary, 0, sizeof(_glfwLibrary)); - if (allocator) - { - // Verify that the specified model is complete - if (!allocator->malloc || !allocator->free) - { - _glfwSetError(GLFW_INVALID_VALUE, NULL); - return GL_FALSE; - } - - _glfwLibrary.allocator = *allocator; - } - else - { - // Use the libc malloc and free - _glfwLibrary.allocator.malloc = malloc; - _glfwLibrary.allocator.free = free; - } - // Not all window hints have zero as their default value, so this // needs to be here despite the memset above _glfwSetDefaultWindowHints(); diff --git a/src/input.c b/src/input.c index 0ad3c1b8..37da571a 100644 --- a/src/input.c +++ b/src/input.c @@ -35,37 +35,33 @@ // Sets the cursor mode for the specified window //======================================================================== -static void setCursorMode(_GLFWwindow* window, int mode) +static void setCursorMode(_GLFWwindow* window, int newMode) { - int centerPosX, centerPosY; + int oldMode, centerPosX, centerPosY; - if (mode != GLFW_CURSOR_NORMAL && - mode != GLFW_CURSOR_HIDDEN && - mode != GLFW_CURSOR_CAPTURED) + if (newMode != GLFW_CURSOR_NORMAL && + newMode != GLFW_CURSOR_HIDDEN && + newMode != GLFW_CURSOR_CAPTURED) { _glfwSetError(GLFW_INVALID_ENUM, NULL); return; } - if (window->cursorMode == mode) + oldMode = window->cursorMode; + if (oldMode == newMode) return; centerPosX = window->width / 2; centerPosY = window->height / 2; - if (mode == GLFW_CURSOR_CAPTURED) - _glfwPlatformSetMouseCursorPos(window, centerPosX, centerPosY); - else if (window->cursorMode == GLFW_CURSOR_CAPTURED) - { - _glfwPlatformSetMouseCursorPos(window, centerPosX, centerPosY); - _glfwInputCursorMotion(window, - centerPosX - window->cursorPosX, - centerPosY - window->cursorPosY); - } + if (oldMode == GLFW_CURSOR_CAPTURED || newMode == GLFW_CURSOR_CAPTURED) + _glfwPlatformSetCursorPos(window, centerPosX, centerPosY); - _glfwPlatformSetCursorMode(window, mode); + _glfwPlatformSetCursorMode(window, newMode); + window->cursorMode = newMode; - window->cursorMode = mode; + if (oldMode == GLFW_CURSOR_CAPTURED) + _glfwInputCursorMotion(window, window->cursorPosX, window->cursorPosY); } @@ -167,7 +163,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int action) return; // Register key action - if(action == GLFW_RELEASE && window->stickyKeys) + if (action == GLFW_RELEASE && window->stickyKeys) window->key[key] = GLFW_STICK; else { @@ -200,7 +196,7 @@ void _glfwInputChar(_GLFWwindow* window, int character) // Register scroll events //======================================================================== -void _glfwInputScroll(_GLFWwindow* window, int xoffset, int yoffset) +void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) { window->scrollX += xoffset; window->scrollY += yoffset; @@ -253,15 +249,26 @@ void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y) window->cursorPosY = y; } - if (_glfwLibrary.mousePosCallback) + if (_glfwLibrary.cursorPosCallback) { - _glfwLibrary.mousePosCallback(window, - window->cursorPosX, - window->cursorPosY); + _glfwLibrary.cursorPosCallback(window, + window->cursorPosX, + window->cursorPosY); } } +//======================================================================== +// Register cursor enter/leave events +//======================================================================== + +void _glfwInputCursorEnter(_GLFWwindow* window, int entered) +{ + if (_glfwLibrary.cursorEnterCallback) + _glfwLibrary.cursorEnterCallback(window, entered); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// @@ -351,10 +358,8 @@ GLFWAPI int glfwGetKey(GLFWwindow handle, int key) return GLFW_RELEASE; } - // Is it a valid key? if (key < 0 || key > GLFW_KEY_LAST) { - // TODO: Decide whether key is a value or enum _glfwSetError(GLFW_INVALID_ENUM, "glfwGetKey: The specified key is invalid"); return GLFW_RELEASE; @@ -385,7 +390,6 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow handle, int button) return GLFW_RELEASE; } - // Is it a valid mouse button? if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) { _glfwSetError(GLFW_INVALID_ENUM, @@ -408,7 +412,7 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow handle, int button) // Returns the last reported cursor position for the specified window //======================================================================== -GLFWAPI void glfwGetMousePos(GLFWwindow handle, int* xpos, int* ypos) +GLFWAPI void glfwGetCursorPos(GLFWwindow handle, int* xpos, int* ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -418,7 +422,6 @@ GLFWAPI void glfwGetMousePos(GLFWwindow handle, int* xpos, int* ypos) return; } - // Return mouse position if (xpos != NULL) *xpos = window->cursorPosX; @@ -432,7 +435,7 @@ GLFWAPI void glfwGetMousePos(GLFWwindow handle, int* xpos, int* ypos) // the specified window //======================================================================== -GLFWAPI void glfwSetMousePos(GLFWwindow handle, int xpos, int ypos) +GLFWAPI void glfwSetCursorPos(GLFWwindow handle, int xpos, int ypos) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -448,11 +451,11 @@ GLFWAPI void glfwSetMousePos(GLFWwindow handle, int xpos, int ypos) return; } - // Don't do anything if the mouse position did not change + // Don't do anything if the cursor position did not change if (xpos == window->cursorPosX && ypos == window->cursorPosY) return; - // Set GLFW mouse position + // Set GLFW cursor position window->cursorPosX = xpos; window->cursorPosY = ypos; @@ -461,7 +464,7 @@ GLFWAPI void glfwSetMousePos(GLFWwindow handle, int xpos, int ypos) return; // Update physical cursor position - _glfwPlatformSetMouseCursorPos(window, xpos, ypos); + _glfwPlatformSetCursorPos(window, xpos, ypos); } @@ -469,7 +472,7 @@ GLFWAPI void glfwSetMousePos(GLFWwindow handle, int xpos, int ypos) // Returns the scroll offset for the specified window //======================================================================== -GLFWAPI void glfwGetScrollOffset(GLFWwindow handle, int* xoffset, int* yoffset) +GLFWAPI void glfwGetScrollOffset(GLFWwindow handle, double* xoffset, double* yoffset) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -539,7 +542,7 @@ GLFWAPI void glfwSetMouseButtonCallback(GLFWmousebuttonfun cbfun) // Set callback function for mouse moves //======================================================================== -GLFWAPI void glfwSetMousePosCallback(GLFWmouseposfun cbfun) +GLFWAPI void glfwSetCursorPosCallback(GLFWcursorposfun cbfun) { if (!_glfwInitialized) { @@ -547,11 +550,10 @@ GLFWAPI void glfwSetMousePosCallback(GLFWmouseposfun cbfun) return; } - // Set callback function - _glfwLibrary.mousePosCallback = cbfun; + _glfwLibrary.cursorPosCallback = cbfun; // Call the callback function to let the application know the current - // mouse position + // cursor position if (cbfun) { _GLFWwindow* window; @@ -562,6 +564,22 @@ GLFWAPI void glfwSetMousePosCallback(GLFWmouseposfun cbfun) } +//======================================================================== +// Set callback function for cursor enter/leave events +//======================================================================== + +GLFWAPI void glfwSetCursorEnterCallback(GLFWcursorenterfun cbfun) +{ + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return; + } + + _glfwLibrary.cursorEnterCallback = cbfun; +} + + //======================================================================== // Set callback function for scroll events //======================================================================== @@ -574,7 +592,6 @@ GLFWAPI void glfwSetScrollCallback(GLFWscrollfun cbfun) return; } - // Set callback function _glfwLibrary.scrollCallback = cbfun; } diff --git a/src/internal.h b/src/internal.h index 16485b0e..54c16d39 100644 --- a/src/internal.h +++ b/src/internal.h @@ -37,9 +37,9 @@ //======================================================================== #if defined(_init_c_) -#define GLFWGLOBAL + #define GLFWGLOBAL #else -#define GLFWGLOBAL extern + #define GLFWGLOBAL extern #endif @@ -51,6 +51,17 @@ #define GLFW_STICK 2 +//======================================================================== +// Internal type declarations +//======================================================================== + +typedef struct _GLFWhints _GLFWhints; +typedef struct _GLFWwndconfig _GLFWwndconfig; +typedef struct _GLFWfbconfig _GLFWfbconfig; +typedef struct _GLFWwindow _GLFWwindow; +typedef struct _GLFWlibrary _GLFWlibrary; + + //------------------------------------------------------------------------ // Platform specific definitions goes in platform.h (which also includes // glfw.h) @@ -73,15 +84,16 @@ typedef struct _GLFWlibrary _GLFWlibrary; typedef struct _GLFWmonitor _GLFWmonitor; #if defined(_GLFW_COCOA_NSGL) -#include "cocoa_platform.h" + #include "cocoa_platform.h" #elif defined(_GLFW_WIN32_WGL) -#include "win32_platform.h" + #include "win32_platform.h" #elif defined(_GLFW_X11_GLX) -#include "x11_platform.h" + #include "x11_platform.h" #else -#error "No supported platform selected" + #error "No supported platform selected" #endif + //------------------------------------------------------------------------ // Window hints, set by glfwOpenWindowHint and consumed by glfwOpenWindow // A bucket of semi-random stuff lumped together for historical reasons @@ -186,7 +198,7 @@ struct _GLFWwindow GLboolean systemKeys; // system keys enabled flag int cursorPosX, cursorPosY; int cursorMode; - int scrollX, scrollY; + double scrollX, scrollY; char mouseButton[GLFW_MOUSE_BUTTON_LAST + 1]; char key[GLFW_KEY_LAST + 1]; @@ -259,20 +271,21 @@ struct _GLFWlibrary GLFWwindowfocusfun windowFocusCallback; GLFWwindowiconifyfun windowIconifyCallback; GLFWmousebuttonfun mouseButtonCallback; - GLFWmouseposfun mousePosCallback; + GLFWcursorposfun cursorPosCallback; + GLFWcursorenterfun cursorEnterCallback; GLFWscrollfun scrollCallback; GLFWkeyfun keyCallback; GLFWcharfun charCallback; GLFWmonitordevicefun monitorCallback; - GLFWallocator allocator; - GLFWgammaramp currentRamp; GLFWgammaramp originalRamp; int originalRampSize; + GLboolean rampChanged; // This is defined in the current port's platform.h - _GLFW_PLATFORM_LIBRARY_STATE; + _GLFW_PLATFORM_LIBRARY_WINDOW_STATE; + _GLFW_PLATFORM_LIBRARY_OPENGL_STATE; }; @@ -302,6 +315,8 @@ const char* _glfwPlatformGetVersionString(void); // Input void _glfwPlatformEnableSystemKeys(_GLFWwindow* window); void _glfwPlatformDisableSystemKeys(_GLFWwindow* window); +void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y); +void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); // Fullscreen int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int maxcount); @@ -311,6 +326,10 @@ void _glfwPlatformGetDesktopMode(GLFWvidmode* mode); void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp); void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp); +// Clipboard +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string); +const char* _glfwPlatformGetClipboardString(_GLFWwindow* window); + // Joystick int _glfwPlatformGetJoystickParam(int joy, int param); int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes); @@ -328,8 +347,6 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y); void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window); -void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y); -void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); // Event management void _glfwPlatformPollEvents(void); @@ -341,7 +358,7 @@ void _glfwPlatformSwapBuffers(void); void _glfwPlatformSwapInterval(int interval); void _glfwPlatformRefreshWindowParams(void); int _glfwPlatformExtensionSupported(const char* extension); -void* _glfwPlatformGetProcAddress(const char* procname); +GLFWglproc _glfwPlatformGetProcAddress(const char* procname); void _glfwPlatformCopyContext(_GLFWwindow* src, _GLFWwindow* dst, unsigned long mask); @@ -349,10 +366,6 @@ void _glfwPlatformCopyContext(_GLFWwindow* src, _GLFWwindow* dst, unsigned long // Prototypes for platform independent internal functions //======================================================================== -// Memory management (init.c) -void* _glfwMalloc(size_t size); -void _glfwFree(void* ptr); - // Fullscren management (fullscreen.c) void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); int _glfwCompareVideoModes(const void* firstPtr, const void* secondPtr); @@ -373,9 +386,10 @@ void _glfwInputWindowDamage(_GLFWwindow* window); // Input event notification (input.c) void _glfwInputKey(_GLFWwindow* window, int key, int action); void _glfwInputChar(_GLFWwindow* window, int character); -void _glfwInputScroll(_GLFWwindow* window, int x, int y); +void _glfwInputScroll(_GLFWwindow* window, double x, double y); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action); void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y); +void _glfwInputCursorEnter(_GLFWwindow* window, int entered); // OpenGL context helpers (opengl.c) int _glfwStringInExtensionString(const char* string, const GLubyte* extensions); diff --git a/src/libglfw.pc.cmake b/src/libglfw.pc.in similarity index 66% rename from src/libglfw.pc.cmake rename to src/libglfw.pc.in index 47cfb4f5..be6275aa 100644 --- a/src/libglfw.pc.cmake +++ b/src/libglfw.pc.in @@ -5,8 +5,9 @@ libdir=${exec_prefix}/lib Name: GLFW Description: A portable library for OpenGL, window and input -Version: 3.0.0 +Version: @GLFW_VERSION_FULL@ URL: http://www.glfw.org/ -Requires.private: gl x11 @GLFW_PKGLIBS@ -Libs: -L${libdir} -lglfw +Requires.private: @GLFW_PKG_DEPS@ +Libs: -L${libdir} -lglfw +Libs.private: @GLFW_PKG_LIBS@ Cflags: -I${includedir} diff --git a/src/monitor.c b/src/monitor.c index 0cc8f511..021afd19 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -30,6 +30,8 @@ #include "internal.h" +#include + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// diff --git a/src/opengl.c b/src/opengl.c index f4c6984c..67b5e728 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -517,8 +517,7 @@ GLFWAPI void glfwSwapBuffers(void) return; } - if (_glfwLibrary.currentWindow) - _glfwPlatformSwapBuffers(); + _glfwPlatformSwapBuffers(); } @@ -614,7 +613,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension) // This function can be used to get access to extended OpenGL functions. //======================================================================== -GLFWAPI void* glfwGetProcAddress(const char* procname) +GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) { if (!_glfwInitialized) { diff --git a/src/win32_clipboard.c b/src/win32_clipboard.c new file mode 100644 index 00000000..2b8742ce --- /dev/null +++ b/src/win32_clipboard.c @@ -0,0 +1,140 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: Win32/WGL +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) +{ + WCHAR* wideString; + HANDLE stringHandle; + size_t wideSize; + + wideString = _glfwCreateWideStringFromUTF8(string); + if (!wideString) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to convert clipboard string to " + "wide string"); + return; + } + + wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR); + + stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize); + if (!stringHandle) + { + free(wideString); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to allocate global handle for clipboard"); + return; + } + + memcpy(GlobalLock(stringHandle), wideString, wideSize); + GlobalUnlock(stringHandle); + + if (!OpenClipboard(window->Win32.handle)) + { + GlobalFree(stringHandle); + free(wideString); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to open clipboard"); + return; + } + + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, stringHandle); + CloseClipboard(); + + free(wideString); +} + + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) +{ + HANDLE stringHandle; + + if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) + { + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, NULL); + return NULL; + } + + if (!OpenClipboard(window->Win32.handle)) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to open clipboard"); + return NULL; + } + + stringHandle = GetClipboardData(CF_UNICODETEXT); + if (!stringHandle) + { + CloseClipboard(); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to retrieve clipboard data"); + return NULL; + } + + free(_glfwLibrary.Win32.clipboardString); + _glfwLibrary.Win32.clipboardString = + _glfwCreateUTF8FromWideString(GlobalLock(stringHandle)); + + GlobalUnlock(stringHandle); + CloseClipboard(); + + if (!_glfwLibrary.Win32.clipboardString) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to convert wide string to UTF-8"); + return NULL; + } + + return _glfwLibrary.Win32.clipboardString; +} + diff --git a/src/win32_dllmain.c b/src/win32_dllmain.c index a999af0e..95258ccc 100644 --- a/src/win32_dllmain.c +++ b/src/win32_dllmain.c @@ -31,7 +31,7 @@ #include "internal.h" -#if defined(GLFW_BUILD_DLL) +#if defined(_GLFW_BUILD_DLL) //======================================================================== // GLFW DLL entry point @@ -45,5 +45,5 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) return TRUE; } -#endif // GLFW_BUILD_DLL +#endif // _GLFW_BUILD_DLL diff --git a/src/win32_gamma.c b/src/win32_gamma.c index f131c3bd..36fbd3a4 100644 --- a/src/win32_gamma.c +++ b/src/win32_gamma.c @@ -42,7 +42,7 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) { - _glfw_GetDeviceGammaRamp(GetDC(GetDesktopWindow()), (WORD*) ramp); + GetDeviceGammaRamp(GetDC(GetDesktopWindow()), (WORD*) ramp); } @@ -52,6 +52,6 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp) { - _glfw_SetDeviceGammaRamp(GetDC(GetDesktopWindow()), (WORD*) ramp); + SetDeviceGammaRamp(GetDC(GetDesktopWindow()), (WORD*) ramp); } diff --git a/src/win32_init.c b/src/win32_init.c index dfed24e4..6865851d 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -44,40 +44,6 @@ static GLboolean initLibraries(void) { -#ifndef _GLFW_NO_DLOAD_GDI32 - // gdi32.dll (OpenGL pixel format functions & SwapBuffers) - - _glfwLibrary.Win32.gdi.instance = LoadLibrary(L"gdi32.dll"); - if (!_glfwLibrary.Win32.gdi.instance) - return GL_FALSE; - - _glfwLibrary.Win32.gdi.ChoosePixelFormat = (CHOOSEPIXELFORMAT_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "ChoosePixelFormat"); - _glfwLibrary.Win32.gdi.DescribePixelFormat = (DESCRIBEPIXELFORMAT_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "DescribePixelFormat"); - _glfwLibrary.Win32.gdi.GetPixelFormat = (GETPIXELFORMAT_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "GetPixelFormat"); - _glfwLibrary.Win32.gdi.SetPixelFormat = (SETPIXELFORMAT_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "SetPixelFormat"); - _glfwLibrary.Win32.gdi.SwapBuffers = (SWAPBUFFERS_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "SwapBuffers"); - _glfwLibrary.Win32.gdi.GetDeviceGammaRamp = (GETDEVICEGAMMARAMP_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "GetDeviceGammaRamp"); - _glfwLibrary.Win32.gdi.SetDeviceGammaRamp = (SETDEVICEGAMMARAMP_T) - GetProcAddress(_glfwLibrary.Win32.gdi.instance, "SetDeviceGammaRamp"); - - if (!_glfwLibrary.Win32.gdi.ChoosePixelFormat || - !_glfwLibrary.Win32.gdi.DescribePixelFormat || - !_glfwLibrary.Win32.gdi.GetPixelFormat || - !_glfwLibrary.Win32.gdi.SetPixelFormat || - !_glfwLibrary.Win32.gdi.SwapBuffers || - !_glfwLibrary.Win32.gdi.GetDeviceGammaRamp || - !_glfwLibrary.Win32.gdi.SetDeviceGammaRamp) - { - return GL_FALSE; - } -#endif // _GLFW_NO_DLOAD_GDI32 - #ifndef _GLFW_NO_DLOAD_WINMM // winmm.dll (for joystick and timer support) @@ -113,14 +79,6 @@ static GLboolean initLibraries(void) static void freeLibraries(void) { -#ifndef _GLFW_NO_DLOAD_GDI32 - if (_glfwLibrary.Win32.gdi.instance != NULL) - { - FreeLibrary(_glfwLibrary.Win32.gdi.instance); - _glfwLibrary.Win32.gdi.instance = NULL; - } -#endif // _GLFW_NO_DLOAD_GDI32 - #ifndef _GLFW_NO_DLOAD_WINMM if (_glfwLibrary.Win32.winmm.instance != NULL) { @@ -131,6 +89,60 @@ static void freeLibraries(void) } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Returns a wide string version of the specified UTF-8 string +//======================================================================== + +WCHAR* _glfwCreateWideStringFromUTF8(const char* source) +{ + WCHAR* target; + int length; + + length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); + if (!length) + return NULL; + + target = (WCHAR*) malloc(sizeof(WCHAR) * (length + 1)); + + if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length + 1)) + { + free(target); + return NULL; + } + + return target; +} + + +//======================================================================== +// Returns a UTF-8 string version of the specified wide string +//======================================================================== + +char* _glfwCreateUTF8FromWideString(const WCHAR* source) +{ + char* target; + int length; + + length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); + if (!length) + return NULL; + + target = (char*) malloc(length + 1); + + if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length + 1, NULL, NULL)) + { + free(target); + return NULL; + } + + return target; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -146,7 +158,7 @@ int _glfwPlatformInit(void) // as possible in the hope of still being the foreground process) SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &_glfwLibrary.Win32.foregroundLockTimeout, 0); - SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID) 0, + SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0), SPIF_SENDCHANGE); if (!initLibraries()) @@ -180,7 +192,8 @@ int _glfwPlatformInit(void) int _glfwPlatformTerminate(void) { // Restore the original gamma ramp - _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); + if (_glfwLibrary.rampChanged) + _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); _glfwTerminateMonitors(); @@ -196,7 +209,7 @@ int _glfwPlatformTerminate(void) // Restore previous FOREGROUNDLOCKTIMEOUT system setting SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, - (LPVOID) _glfwLibrary.Win32.foregroundLockTimeout, + UIntToPtr(_glfwLibrary.Win32.foregroundLockTimeout), SPIF_SENDCHANGE); return GL_TRUE; @@ -212,8 +225,6 @@ const char* _glfwPlatformGetVersionString(void) const char* version = _GLFW_VERSION_FULL #if defined(__MINGW32__) " MinGW" -#elif defined(__CYGWIN__) - " Cygwin" #elif defined(_MSC_VER) " Visual C++ " #elif defined(__BORLANDC__) @@ -221,12 +232,9 @@ const char* _glfwPlatformGetVersionString(void) #else " (unknown compiler)" #endif -#if defined(GLFW_BUILD_DLL) +#if defined(_GLFW_BUILD_DLL) " DLL" #endif -#if !defined(_GLFW_NO_DLOAD_GDI32) - " load(gdi32)" -#endif #if !defined(_GLFW_NO_DLOAD_WINMM) " load(winmm)" #endif diff --git a/src/win32_joystick.c b/src/win32_joystick.c index 0ab84aaf..c27218db 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -80,6 +80,7 @@ static float calcJoystickPos(DWORD pos, DWORD min, DWORD max) int _glfwPlatformGetJoystickParam(int joy, int param) { JOYCAPS jc; + int hats; if (!isJoystickPresent(joy)) return 0; @@ -91,6 +92,8 @@ int _glfwPlatformGetJoystickParam(int joy, int param) // Get joystick capabilities _glfw_joyGetDevCaps(joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS)); + hats = (jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR) ? 1 : 0; + switch (param) { case GLFW_AXES: @@ -98,8 +101,8 @@ int _glfwPlatformGetJoystickParam(int joy, int param) return jc.wNumAxes; case GLFW_BUTTONS: - // Return number of joystick axes - return jc.wNumButtons; + // Return number of joystick buttons + return jc.wNumButtons + hats * 4; default: break; @@ -164,7 +167,10 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, { JOYCAPS jc; JOYINFOEX ji; - int button; + int button, hats; + + // Bit fields of button presses for each direction, including nil + const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; if (!isJoystickPresent(joy)) return 0; @@ -174,7 +180,7 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, // Get joystick state ji.dwSize = sizeof(JOYINFOEX); - ji.dwFlags = JOY_RETURNBUTTONS; + ji.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV; _glfw_joyGetPosEx(joy - GLFW_JOYSTICK_1, &ji); // Get states of all requested buttons @@ -184,6 +190,24 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, (ji.dwButtons & (1UL << button) ? GLFW_PRESS : GLFW_RELEASE); } + // Virtual buttons - Inject data from hats + // Each hat is exposed as 4 buttons which exposes 8 directions with + // concurrent button presses + // NOTE: this API exposes only one hat + + hats = (jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR) ? 1 : 0; + + if (hats > 0) + { + int j; + int value = ji.dwPOV / 100 / 45; + if (value < 0 || value > 8) value = 8; + + for (j = 0; j < 4 && button < numbuttons; j++) + { + buttons[button++] = directions[value] & (1 << j) ? GLFW_PRESS : GLFW_RELEASE; + } + } + return button; } - diff --git a/src/win32_opengl.c b/src/win32_opengl.c index 0ffd594c..5e94d7da 100644 --- a/src/win32_opengl.c +++ b/src/win32_opengl.c @@ -56,7 +56,7 @@ void _glfwPlatformSwapBuffers(void) { _GLFWwindow* window = _glfwLibrary.currentWindow; - _glfw_SwapBuffers(window->WGL.DC); + SwapBuffers(window->WGL.DC); } @@ -111,9 +111,9 @@ int _glfwPlatformExtensionSupported(const char* extension) // Get the function pointer to an OpenGL function //======================================================================== -void* _glfwPlatformGetProcAddress(const char* procname) +GLFWglproc _glfwPlatformGetProcAddress(const char* procname) { - return (void*) wglGetProcAddress(procname); + return (GLFWglproc) wglGetProcAddress(procname); } diff --git a/src/win32_platform.h b/src/win32_platform.h index 6c2f207d..aa3305ef 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -33,8 +33,13 @@ // We don't need all the fancy stuff -#define NOMINMAX -#define VC_EXTRALEAN +#ifndef NOMINMAX + #define NOMINMAX +#endif + +#ifndef VC_EXTRALEAN + #define VC_EXTRALEAN +#endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN @@ -45,7 +50,15 @@ // thinks it is the only one that gets to do so #undef APIENTRY -#define UNICODE +// GLFW on Windows is Unicode only and does not work in MBCS mode +#ifndef UNICODE + #define UNICODE +#endif + +// GLFW requires Windows XP +#ifndef WINVER + #define WINVER 0x0501 +#endif #include #include @@ -61,90 +74,8 @@ // Hack: Define things that some windows.h variants don't //======================================================================== -// Some old versions of w32api (used by MinGW and Cygwin) define -// WH_KEYBOARD_LL without typedef:ing KBDLLHOOKSTRUCT (!) -#if defined(__MINGW32__) || defined(__CYGWIN__) -#include -#if defined(WH_KEYBOARD_LL) && (__W32API_MAJOR_VERSION == 1) && (__W32API_MINOR_VERSION <= 2) -#undef WH_KEYBOARD_LL -#endif -#endif - -//------------------------------------------------------------------------ -// ** NOTE ** If this gives you compiler errors and you are using MinGW -// (or Dev-C++), update to w32api version 1.3 or later: -// http://sourceforge.net/project/showfiles.php?group_id=2435 -//------------------------------------------------------------------------ -#ifndef WH_KEYBOARD_LL -#define WH_KEYBOARD_LL 13 -typedef struct tagKBDLLHOOKSTRUCT { - DWORD vkCode; - DWORD scanCode; - DWORD flags; - DWORD time; - DWORD dwExtraInfo; -} KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT; -#endif // WH_KEYBOARD_LL - -#ifndef LLKHF_ALTDOWN -#define LLKHF_ALTDOWN 0x00000020 -#endif - -#ifndef SPI_SETSCREENSAVERRUNNING -#define SPI_SETSCREENSAVERRUNNING 97 -#endif -#ifndef SPI_GETANIMATION -#define SPI_GETANIMATION 72 -#endif -#ifndef SPI_SETANIMATION -#define SPI_SETANIMATION 73 -#endif -#ifndef SPI_GETFOREGROUNDLOCKTIMEOUT -#define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000 -#endif -#ifndef SPI_SETFOREGROUNDLOCKTIMEOUT -#define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001 -#endif - -#ifndef CDS_FULLSCREEN -#define CDS_FULLSCREEN 4 -#endif - -#ifndef PFD_GENERIC_ACCELERATED -#define PFD_GENERIC_ACCELERATED 0x00001000 -#endif -#ifndef PFD_DEPTH_DONTCARE -#define PFD_DEPTH_DONTCARE 0x20000000 -#endif - -#ifndef ENUM_CURRENT_SETTINGS -#define ENUM_CURRENT_SETTINGS -1 -#endif -#ifndef ENUM_REGISTRY_SETTINGS -#define ENUM_REGISTRY_SETTINGS -2 -#endif - -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A -#endif -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 -#endif #ifndef WM_MOUSEHWHEEL -#define WM_MOUSEHWHEEL 0x020E -#endif - -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 0x020B -#endif -#ifndef WM_XBUTTONUP -#define WM_XBUTTONUP 0x020C -#endif -#ifndef XBUTTON1 -#define XBUTTON1 1 -#endif -#ifndef XBUTTON2 -#define XBUTTON2 2 + #define WM_MOUSEHWHEEL 0x020E #endif @@ -152,17 +83,6 @@ typedef struct tagKBDLLHOOKSTRUCT { // DLLs that are loaded at glfwInit() //======================================================================== -// gdi32.dll function pointer typedefs -#ifndef _GLFW_NO_DLOAD_GDI32 -typedef int (WINAPI * CHOOSEPIXELFORMAT_T) (HDC,CONST PIXELFORMATDESCRIPTOR*); -typedef int (WINAPI * DESCRIBEPIXELFORMAT_T) (HDC,int,UINT,LPPIXELFORMATDESCRIPTOR); -typedef int (WINAPI * GETPIXELFORMAT_T) (HDC); -typedef BOOL (WINAPI * SETPIXELFORMAT_T) (HDC,int,const PIXELFORMATDESCRIPTOR*); -typedef BOOL (WINAPI * SWAPBUFFERS_T) (HDC); -typedef BOOL (WINAPI * GETDEVICEGAMMARAMP_T) (HDC,PVOID); -typedef BOOL (WINAPI * SETDEVICEGAMMARAMP_T) (HDC,PVOID); -#endif // _GLFW_NO_DLOAD_GDI32 - // winmm.dll function pointer typedefs #ifndef _GLFW_NO_DLOAD_WINMM typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T) (UINT,LPJOYCAPS,UINT); @@ -172,36 +92,17 @@ typedef DWORD (WINAPI * TIMEGETTIME_T) (void); #endif // _GLFW_NO_DLOAD_WINMM -// gdi32.dll shortcuts -#ifndef _GLFW_NO_DLOAD_GDI32 -#define _glfw_ChoosePixelFormat _glfwLibrary.Win32.gdi.ChoosePixelFormat -#define _glfw_DescribePixelFormat _glfwLibrary.Win32.gdi.DescribePixelFormat -#define _glfw_GetPixelFormat _glfwLibrary.Win32.gdi.GetPixelFormat -#define _glfw_SetPixelFormat _glfwLibrary.Win32.gdi.SetPixelFormat -#define _glfw_SwapBuffers _glfwLibrary.Win32.gdi.SwapBuffers -#define _glfw_GetDeviceGammaRamp _glfwLibrary.Win32.gdi.GetDeviceGammaRamp -#define _glfw_SetDeviceGammaRamp _glfwLibrary.Win32.gdi.SetDeviceGammaRamp -#else -#define _glfw_ChoosePixelFormat ChoosePixelFormat -#define _glfw_DescribePixelFormat DescribePixelFormat -#define _glfw_GetPixelFormat GetPixelFormat -#define _glfw_SetPixelFormat SetPixelFormat -#define _glfw_SwapBuffers SwapBuffers -#define _glfw_GetDeviceGammaRamp GetDeviceGammaRamp -#define _glfw_SetDeviceGammaRamp SetDeviceGammaRamp -#endif // _GLFW_NO_DLOAD_GDI32 - // winmm.dll shortcuts #ifndef _GLFW_NO_DLOAD_WINMM -#define _glfw_joyGetDevCaps _glfwLibrary.Win32.winmm.joyGetDevCaps -#define _glfw_joyGetPos _glfwLibrary.Win32.winmm.joyGetPos -#define _glfw_joyGetPosEx _glfwLibrary.Win32.winmm.joyGetPosEx -#define _glfw_timeGetTime _glfwLibrary.Win32.winmm.timeGetTime + #define _glfw_joyGetDevCaps _glfwLibrary.Win32.winmm.joyGetDevCaps + #define _glfw_joyGetPos _glfwLibrary.Win32.winmm.joyGetPos + #define _glfw_joyGetPosEx _glfwLibrary.Win32.winmm.joyGetPosEx + #define _glfw_timeGetTime _glfwLibrary.Win32.winmm.timeGetTime #else -#define _glfw_joyGetDevCaps joyGetDevCaps -#define _glfw_joyGetPos joyGetPos -#define _glfw_joyGetPosEx joyGetPosEx -#define _glfw_timeGetTime timeGetTime + #define _glfw_joyGetDevCaps joyGetDevCaps + #define _glfw_joyGetPos joyGetPos + #define _glfw_joyGetPosEx joyGetPosEx + #define _glfw_timeGetTime timeGetTime #endif // _GLFW_NO_DLOAD_WINMM @@ -211,10 +112,13 @@ typedef DWORD (WINAPI * TIMEGETTIME_T) (void); #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 Win32 -#define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryWin32 Win32 #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL WGL + #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 Win32 +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 Win32 +#define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryWGL WGL + //======================================================================== // GLFW platform specific types @@ -264,12 +168,13 @@ typedef struct _GLFWwindowWin32 // Various platform specific internal variables int desiredRefreshRate; // Desired vertical monitor refresh rate GLboolean cursorCentered; - int oldMouseX, oldMouseY; + GLboolean cursorInside; + int oldCursorX, oldCursorY; } _GLFWwindowWin32; //------------------------------------------------------------------------ -// Platform-specific library global data +// Platform-specific library global data for Win32 //------------------------------------------------------------------------ typedef struct _GLFWlibraryWin32 { @@ -277,6 +182,7 @@ typedef struct _GLFWlibraryWin32 ATOM classAtom; // Window class atom HHOOK keyboardHook; // Keyboard hook handle DWORD foregroundLockTimeout; + char* clipboardString; // Default monitor struct { @@ -295,20 +201,6 @@ typedef struct _GLFWlibraryWin32 __int64 t0_64; } timer; -#ifndef _GLFW_NO_DLOAD_GDI32 - // gdi32.dll - struct { - HINSTANCE instance; - CHOOSEPIXELFORMAT_T ChoosePixelFormat; - DESCRIBEPIXELFORMAT_T DescribePixelFormat; - GETPIXELFORMAT_T GetPixelFormat; - SETPIXELFORMAT_T SetPixelFormat; - SWAPBUFFERS_T SwapBuffers; - GETDEVICEGAMMARAMP_T GetDeviceGammaRamp; - SETDEVICEGAMMARAMP_T SetDeviceGammaRamp; - } gdi; -#endif // _GLFW_NO_DLOAD_GDI32 - #ifndef _GLFW_NO_DLOAD_WINMM // winmm.dll struct { @@ -331,10 +223,24 @@ typedef struct _GLFWmonitorWin32 } _GLFWmonitorWin32; +//------------------------------------------------------------------------ +// Platform-specific library global data for WGL +//------------------------------------------------------------------------ +typedef struct _GLFWlibraryWGL +{ + int dummy; + +} _GLFWlibraryWGL; + + //======================================================================== // Prototypes for platform specific internal functions //======================================================================== +// Wide strings +WCHAR* _glfwCreateWideStringFromUTF8(const char* source); +char* _glfwCreateUTF8FromWideString(const WCHAR* source); + // Time void _glfwInitTimer(void); diff --git a/src/win32_window.c b/src/win32_window.c old mode 100644 new mode 100755 index 7f9e37a1..dd14a77f --- a/src/win32_window.c +++ b/src/win32_window.c @@ -33,55 +33,6 @@ #include -//======================================================================== -// Convert the specified UTF-8 string to a wide string -//======================================================================== - -static WCHAR* createWideStringFromUTF8(const char* source) -{ - WCHAR* target; - int length; - - length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); - if (!length) - return NULL; - - target = (WCHAR*) _glfwMalloc(sizeof(WCHAR) * (length + 1)); - - if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length + 1)) - { - _glfwFree(target); - return NULL; - } - - return target; -} - - -//======================================================================== -// Convert BPP to RGB bits based on "best guess" -//======================================================================== - -static void bpp2rgb(int bpp, int* r, int* g, int* b) -{ - int delta; - - // We assume that by 32 they really meant 24 - if (bpp == 32) - bpp = 24; - - // Convert "bits per pixel" to red, green & blue sizes - - *r = *g = *b = bpp / 3; - delta = bpp - (*r * 3); - if (delta >= 1) - *g = *g + 1; - - if (delta == 2) - *r = *r + 1; -} - - //======================================================================== // Enable/disable minimize/restore animations //======================================================================== @@ -197,38 +148,44 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) { - _GLFWfbconfig* result; + _GLFWfbconfig* fbconfigs; PIXELFORMATDESCRIPTOR pfd; - int i, count; + int i, available; *found = 0; if (window->WGL.ARB_pixel_format) - count = getPixelFormatAttrib(window, 1, WGL_NUMBER_PIXEL_FORMATS_ARB); + { + available = getPixelFormatAttrib(window, + 1, + WGL_NUMBER_PIXEL_FORMATS_ARB); + } else { - count = _glfw_DescribePixelFormat(window->WGL.DC, - 1, - sizeof(PIXELFORMATDESCRIPTOR), - NULL); + available = DescribePixelFormat(window->WGL.DC, + 1, + sizeof(PIXELFORMATDESCRIPTOR), + NULL); } - if (!count) + if (!available) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "Win32/WGL: No pixel formats found"); return NULL; } - result = (_GLFWfbconfig*) _glfwMalloc(sizeof(_GLFWfbconfig) * count); - if (!result) + fbconfigs = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * available); + if (!fbconfigs) { _glfwSetError(GLFW_OUT_OF_MEMORY, "Win32/WGL: Failed to allocate _GLFWfbconfig array"); return NULL; } - for (i = 1; i <= count; i++) + for (i = 1; i <= available; i++) { + _GLFWfbconfig* f = fbconfigs + *found; + if (window->WGL.ARB_pixel_format) { // Get pixel format attributes through WGL_ARB_pixel_format @@ -251,50 +208,35 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) continue; } - result[*found].redBits = - getPixelFormatAttrib(window, i, WGL_RED_BITS_ARB); - result[*found].greenBits = - getPixelFormatAttrib(window, i, WGL_GREEN_BITS_ARB); - result[*found].blueBits = - getPixelFormatAttrib(window, i, WGL_BLUE_BITS_ARB); - result[*found].alphaBits = - getPixelFormatAttrib(window, i, WGL_ALPHA_BITS_ARB); + f->redBits = getPixelFormatAttrib(window, i, WGL_RED_BITS_ARB); + f->greenBits = getPixelFormatAttrib(window, i, WGL_GREEN_BITS_ARB); + f->blueBits = getPixelFormatAttrib(window, i, WGL_BLUE_BITS_ARB); + f->alphaBits = getPixelFormatAttrib(window, i, WGL_ALPHA_BITS_ARB); - result[*found].depthBits = - getPixelFormatAttrib(window, i, WGL_DEPTH_BITS_ARB); - result[*found].stencilBits = - getPixelFormatAttrib(window, i, WGL_STENCIL_BITS_ARB); + f->depthBits = getPixelFormatAttrib(window, i, WGL_DEPTH_BITS_ARB); + f->stencilBits = getPixelFormatAttrib(window, i, WGL_STENCIL_BITS_ARB); - result[*found].accumRedBits = - getPixelFormatAttrib(window, i, WGL_ACCUM_RED_BITS_ARB); - result[*found].accumGreenBits = - getPixelFormatAttrib(window, i, WGL_ACCUM_GREEN_BITS_ARB); - result[*found].accumBlueBits = - getPixelFormatAttrib(window, i, WGL_ACCUM_BLUE_BITS_ARB); - result[*found].accumAlphaBits = - getPixelFormatAttrib(window, i, WGL_ACCUM_ALPHA_BITS_ARB); + f->accumRedBits = getPixelFormatAttrib(window, i, WGL_ACCUM_RED_BITS_ARB); + f->accumGreenBits = getPixelFormatAttrib(window, i, WGL_ACCUM_GREEN_BITS_ARB); + f->accumBlueBits = getPixelFormatAttrib(window, i, WGL_ACCUM_BLUE_BITS_ARB); + f->accumAlphaBits = getPixelFormatAttrib(window, i, WGL_ACCUM_ALPHA_BITS_ARB); - result[*found].auxBuffers = - getPixelFormatAttrib(window, i, WGL_AUX_BUFFERS_ARB); - result[*found].stereo = - getPixelFormatAttrib(window, i, WGL_STEREO_ARB); + f->auxBuffers = getPixelFormatAttrib(window, i, WGL_AUX_BUFFERS_ARB); + f->stereo = getPixelFormatAttrib(window, i, WGL_STEREO_ARB); if (window->WGL.ARB_multisample) - { - result[*found].samples = - getPixelFormatAttrib(window, i, WGL_SAMPLES_ARB); - } + f->samples = getPixelFormatAttrib(window, i, WGL_SAMPLES_ARB); else - result[*found].samples = 0; + f->samples = 0; } else { // Get pixel format attributes through old-fashioned PFDs - if (!_glfw_DescribePixelFormat(window->WGL.DC, - i, - sizeof(PIXELFORMATDESCRIPTOR), - &pfd)) + if (!DescribePixelFormat(window->WGL.DC, + i, + sizeof(PIXELFORMATDESCRIPTOR), + &pfd)) { continue; } @@ -315,32 +257,38 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (pfd.iPixelType != PFD_TYPE_RGBA) continue; - result[*found].redBits = pfd.cRedBits; - result[*found].greenBits = pfd.cGreenBits; - result[*found].blueBits = pfd.cBlueBits; - result[*found].alphaBits = pfd.cAlphaBits; + f->redBits = pfd.cRedBits; + f->greenBits = pfd.cGreenBits; + f->blueBits = pfd.cBlueBits; + f->alphaBits = pfd.cAlphaBits; - result[*found].depthBits = pfd.cDepthBits; - result[*found].stencilBits = pfd.cStencilBits; + f->depthBits = pfd.cDepthBits; + f->stencilBits = pfd.cStencilBits; - result[*found].accumRedBits = pfd.cAccumRedBits; - result[*found].accumGreenBits = pfd.cAccumGreenBits; - result[*found].accumBlueBits = pfd.cAccumBlueBits; - result[*found].accumAlphaBits = pfd.cAccumAlphaBits; + f->accumRedBits = pfd.cAccumRedBits; + f->accumGreenBits = pfd.cAccumGreenBits; + f->accumBlueBits = pfd.cAccumBlueBits; + f->accumAlphaBits = pfd.cAccumAlphaBits; - result[*found].auxBuffers = pfd.cAuxBuffers; - result[*found].stereo = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE; + f->auxBuffers = pfd.cAuxBuffers; + f->stereo = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE; // PFD pixel formats do not support FSAA - result[*found].samples = 0; + f->samples = 0; } - result[*found].platformID = i; + f->platformID = i; (*found)++; } - return result; + if (*found == 0) + { + free(fbconfigs); + return NULL; + } + + return fbconfigs; } @@ -359,14 +307,14 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->share) share = wndconfig->share->WGL.context; - if (!_glfw_DescribePixelFormat(window->WGL.DC, pixelFormat, sizeof(pfd), &pfd)) + if (!DescribePixelFormat(window->WGL.DC, pixelFormat, sizeof(pfd), &pfd)) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "Win32/WGL: Failed to retrieve PFD for selected pixel format"); return GL_FALSE; } - if (!_glfw_SetPixelFormat(window->WGL.DC, pixelFormat, &pfd)) + if (!SetPixelFormat(window->WGL.DC, pixelFormat, &pfd)) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "Win32/WGL: Failed to set selected pixel format"); @@ -500,7 +448,7 @@ static GLboolean createContext(_GLFWwindow* window, // Hide mouse cursor //======================================================================== -static void hideMouseCursor(_GLFWwindow* window) +static void hideCursor(_GLFWwindow* window) { } @@ -509,7 +457,7 @@ static void hideMouseCursor(_GLFWwindow* window) // Capture mouse cursor //======================================================================== -static void captureMouseCursor(_GLFWwindow* window) +static void captureCursor(_GLFWwindow* window) { RECT ClipWindowRect; @@ -528,7 +476,7 @@ static void captureMouseCursor(_GLFWwindow* window) // Show mouse cursor //======================================================================== -static void showMouseCursor(_GLFWwindow* window) +static void showCursor(_GLFWwindow* window) { // Un-capture cursor ReleaseCapture(); @@ -835,7 +783,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // The window was deactivated (or iconified, see above) if (window->cursorMode == GLFW_CURSOR_CAPTURED) - showMouseCursor(window); + showCursor(window); if (window->mode == GLFW_FULLSCREEN) { @@ -858,7 +806,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, // The window was activated if (window->cursorMode == GLFW_CURSOR_CAPTURED) - captureMouseCursor(window); + captureCursor(window); if (window->mode == GLFW_FULLSCREEN) { @@ -919,7 +867,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, if (_glfwLibrary.charCallback) translateChar(window, (DWORD) wParam, (DWORD) lParam); - return 0; + break; } case WM_KEYUP: @@ -934,7 +882,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, else _glfwInputKey(window, translateKey(wParam, lParam), GLFW_RELEASE); - return 0; + break; } case WM_LBUTTONDOWN: @@ -1013,14 +961,14 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_MOUSEMOVE: { - int newMouseX, newMouseY; + int newCursorX, newCursorY; - // Get signed (!) mouse position - newMouseX = (int)((short)LOWORD(lParam)); - newMouseY = (int)((short)HIWORD(lParam)); + // Get signed (!) cursor position + newCursorX = (int)((short)LOWORD(lParam)); + newCursorY = (int)((short)HIWORD(lParam)); - if (newMouseX != window->Win32.oldMouseX || - newMouseY != window->Win32.oldMouseY) + if (newCursorX != window->Win32.oldCursorX || + newCursorY != window->Win32.oldCursorY) { int x, y; @@ -1029,28 +977,48 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, if (_glfwLibrary.activeWindow != window) return 0; - x = newMouseX - window->Win32.oldMouseX; - y = newMouseY - window->Win32.oldMouseY; + x = newCursorX - window->Win32.oldCursorX; + y = newCursorY - window->Win32.oldCursorY; } else { - x = newMouseX; - y = newMouseY; + x = newCursorX; + y = newCursorY; } - window->Win32.oldMouseX = newMouseX; - window->Win32.oldMouseY = newMouseY; + window->Win32.oldCursorX = newCursorX; + window->Win32.oldCursorY = newCursorY; window->Win32.cursorCentered = GL_FALSE; _glfwInputCursorMotion(window, x, y); } + if (!window->Win32.cursorInside) + { + TRACKMOUSEEVENT tme; + ZeroMemory(&tme, sizeof(tme)); + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = window->Win32.handle; + TrackMouseEvent(&tme); + + window->Win32.cursorInside = GL_TRUE; + _glfwInputCursorEnter(window, GL_TRUE); + } + + return 0; + } + + case WM_MOUSELEAVE: + { + window->Win32.cursorInside = GL_FALSE; + _glfwInputCursorEnter(window, GL_FALSE); return 0; } case WM_MOUSEWHEEL: { - _glfwInputScroll(window, 0, (((int) wParam) >> 16) / WHEEL_DELTA); + _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA); return 0; } @@ -1058,7 +1026,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, { // This message is only sent on Windows Vista and later - _glfwInputScroll(window, (((int) wParam) >> 16) / WHEEL_DELTA, 0); + _glfwInputScroll(window, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA, 0.0); return 0; } @@ -1291,13 +1259,13 @@ static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* fbconfig) closest = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); if (!closest) { - _glfwFree(fbconfigs); + free(fbconfigs); return 0; } pixelFormat = (int) closest->platformID; - _glfwFree(fbconfigs); + free(fbconfigs); fbconfigs = NULL; closest = NULL; @@ -1314,7 +1282,7 @@ static int createWindow(_GLFWwindow* window, const _GLFWfbconfig* fbconfig) { DWORD dwStyle, dwExStyle; - int length, pixelFormat, fullWidth, fullHeight; + int pixelFormat, fullWidth, fullHeight; RECT wa; POINT pos; WCHAR* wideTitle; @@ -1366,12 +1334,12 @@ static int createWindow(_GLFWwindow* window, else SystemParametersInfo(SPI_GETWORKAREA, 0, &wa, 0); - wideTitle = createWideStringFromUTF8(wndconfig->title); + wideTitle = _glfwCreateWideStringFromUTF8(wndconfig->title); if (!wideTitle) { _glfwSetError(GLFW_PLATFORM_ERROR, "glfwOpenWindow: Failed to convert title to wide string"); - return; + return GL_FALSE; } window->Win32.handle = CreateWindowEx(window->Win32.dwExStyle, @@ -1392,7 +1360,7 @@ static int createWindow(_GLFWwindow* window, return GL_FALSE; } - _glfwFree(wideTitle); + free(wideTitle); window->WGL.DC = GetDC(window->Win32.handle); if (!window->WGL.DC) @@ -1413,11 +1381,11 @@ static int createWindow(_GLFWwindow* window, initWGLExtensions(window); - // Initialize mouse position data + // Initialize cursor position data GetCursorPos(&pos); ScreenToClient(window->Win32.handle, &pos); - window->Win32.oldMouseX = window->cursorPosX = pos.x; - window->Win32.oldMouseY = window->cursorPosY = pos.y; + window->Win32.oldCursorX = window->cursorPosX = pos.x; + window->Win32.oldCursorY = window->cursorPosY = pos.y; return GL_TRUE; } @@ -1475,6 +1443,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, GLboolean recreateContext = GL_FALSE; window->Win32.desiredRefreshRate = wndconfig->refreshRate; + window->resizable = wndconfig->resizable; if (!_glfwLibrary.Win32.classAtom) { @@ -1613,7 +1582,7 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) { - WCHAR* wideTitle = createWideStringFromUTF8(title); + WCHAR* wideTitle = _glfwCreateWideStringFromUTF8(title); if (!wideTitle) { _glfwSetError(GLFW_PLATFORM_ERROR, @@ -1623,7 +1592,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) SetWindowText(window->Win32.handle, wideTitle); - _glfwFree(wideTitle); + free(wideTitle); } @@ -1633,29 +1602,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { - //int bpp, refresh; - int newMode = 0; GLboolean sizeChanged = GL_FALSE; if (window->mode == GLFW_FULLSCREEN) { - // Get some info about the current mode - - DEVMODE dm; - - dm.dmSize = sizeof(DEVMODE); - //if (EnumDisplaySettings(NULL, window->Win32.modeID, &dm)) - //{ - // We need to keep BPP the same for the OpenGL context to keep working - //bpp = dm.dmBitsPerPel; - - // Get closest match for target video mode - //refresh = window->Win32.desiredRefreshRate; - //newMode = _glfwGetClosestVideoModeBPP(&width, &height, &bpp, &refresh); - //} - //else - //newMode = window->Win32.modeID; - if (width > window->width || height > window->height) { // The new video mode is larger than the current one, so we resize @@ -1667,8 +1617,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) sizeChanged = GL_TRUE; } - //if (newMode != window->Win32.modeID) - //_glfwSetVideoModeMODE(newMode); + // TODO: Change video mode } else { @@ -1692,7 +1641,13 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y) { - SetWindowPos(window->Win32.handle, HWND_TOP, x, y, 0, 0, + RECT rect; + + GetClientRect(window->Win32.handle, &rect); + AdjustWindowRectEx(&rect, window->Win32.dwStyle, FALSE, window->Win32.dwExStyle); + + SetWindowPos(window->Win32.handle, HWND_TOP, + x + rect.left, y + rect.top, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER); } @@ -1730,7 +1685,7 @@ void _glfwPlatformRefreshWindowParams(void) _GLFWwindow* window = _glfwLibrary.currentWindow; // Obtain a detailed description of current pixel format - pixelFormat = _glfw_GetPixelFormat(window->WGL.DC); + pixelFormat = GetPixelFormat(window->WGL.DC); if (window->WGL.ARB_pixel_format) { @@ -1784,8 +1739,8 @@ void _glfwPlatformRefreshWindowParams(void) } else { - _glfw_DescribePixelFormat(window->WGL.DC, pixelFormat, - sizeof(PIXELFORMATDESCRIPTOR), &pfd); + DescribePixelFormat(window->WGL.DC, pixelFormat, + sizeof(PIXELFORMATDESCRIPTOR), &pfd); // Is current OpenGL context accelerated? window->accelerated = (pfd.dwFlags & PFD_GENERIC_ACCELERATED) || @@ -1835,14 +1790,14 @@ void _glfwPlatformPollEvents(void) window = _glfwLibrary.activeWindow; if (window) { - window->Win32.cursorCentered = GL_TRUE; - window->Win32.oldMouseX = window->width / 2; - window->Win32.oldMouseY = window->height / 2; + window->Win32.cursorCentered = GL_FALSE; + window->Win32.oldCursorX = window->width / 2; + window->Win32.oldCursorY = window->height / 2; } else { - //window->Win32.oldMouseX = window->cursorPosX; - //window->Win32.oldMouseY = window->cursorPosY; + //window->Win32.oldCursorX = window->cursorPosX; + //window->Win32.oldCursorY = window->cursorPosY; } while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) @@ -1899,9 +1854,9 @@ void _glfwPlatformPollEvents(void) if (window->cursorMode == GLFW_CURSOR_CAPTURED && !window->Win32.cursorCentered) { - _glfwPlatformSetMouseCursorPos(window, - window->width / 2, - window->height / 2); + _glfwPlatformSetCursorPos(window, + window->width / 2, + window->height / 2); window->Win32.cursorCentered = GL_TRUE; } } @@ -1921,10 +1876,10 @@ void _glfwPlatformWaitEvents(void) //======================================================================== -// Set physical mouse cursor position +// Set physical cursor position //======================================================================== -void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y) +void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y) { POINT pos; @@ -1946,13 +1901,13 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) switch (mode) { case GLFW_CURSOR_NORMAL: - showMouseCursor(window); + showCursor(window); break; case GLFW_CURSOR_HIDDEN: - hideMouseCursor(window); + hideCursor(window); break; case GLFW_CURSOR_CAPTURED: - captureMouseCursor(window); + captureCursor(window); break; } } diff --git a/src/window.c b/src/window.c index de89b069..f8939e37 100644 --- a/src/window.c +++ b/src/window.c @@ -291,7 +291,7 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, height = 480; } - window = (_GLFWwindow*) _glfwMalloc(sizeof(_GLFWwindow)); + window = (_GLFWwindow*) malloc(sizeof(_GLFWwindow)); if (!window) { _glfwSetError(GLFW_OUT_OF_MEMORY, @@ -492,7 +492,7 @@ GLFWAPI void glfwCloseWindow(GLFWwindow handle) *prev = window->next; } - _glfwFree(window); + free(window); } @@ -655,7 +655,6 @@ GLFWAPI void glfwRestoreWindow(GLFWwindow handle) if (!window->iconified) return; - // Restore iconified window _glfwPlatformRestoreWindow(window); if (window->mode == GLFW_FULLSCREEN) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c new file mode 100644 index 00000000..a833ed1f --- /dev/null +++ b/src/x11_clipboard.c @@ -0,0 +1,191 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: X11/GLX +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Save the contents of the specified property +//======================================================================== + +GLboolean _glfwReadSelection(XSelectionEvent* request) +{ + Atom actualType; + int actualFormat; + unsigned long itemCount, bytesAfter; + char* data; + + if (request->property == None) + return GL_FALSE; + + XGetWindowProperty(_glfwLibrary.X11.display, + request->requestor, + request->property, + 0, LONG_MAX, + False, + request->target, + &actualType, + &actualFormat, + &itemCount, + &bytesAfter, + (unsigned char**) &data); + + if (actualType == None) + return GL_FALSE; + + free(_glfwLibrary.X11.selection.string); + _glfwLibrary.X11.selection.string = strdup(data); + + XFree(data); + return GL_TRUE; +} + + +//======================================================================== +// Set the specified property to the contents of the requested selection +//======================================================================== + +Atom _glfwWriteSelection(XSelectionRequestEvent* request) +{ + int i; + Atom property = request->property; + + if (property == None) + property = _glfwLibrary.X11.selection.property; + + if (request->target == _glfwLibrary.X11.selection.targets) + { + // The list of supported targets was requested + + XChangeProperty(_glfwLibrary.X11.display, + request->requestor, + property, + XA_ATOM, + 32, + PropModeReplace, + (unsigned char*) _glfwLibrary.X11.selection.formats, + _GLFW_CLIPBOARD_FORMAT_COUNT); + + return property; + } + + for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++) + { + if (request->target == _glfwLibrary.X11.selection.formats[i]) + { + // The requested target is one we support + + XChangeProperty(_glfwLibrary.X11.display, + request->requestor, + property, + request->target, + 8, + PropModeReplace, + (unsigned char*) _glfwLibrary.X11.selection.string, + strlen(_glfwLibrary.X11.selection.string)); + + return property; + } + } + + return None; +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) +{ + // Store the new string in preparation for a selection request event + free(_glfwLibrary.X11.selection.string); + _glfwLibrary.X11.selection.string = strdup(string); + + // Set the specified window as owner of the selection + XSetSelectionOwner(_glfwLibrary.X11.display, + _glfwLibrary.X11.selection.atom, + window->X11.handle, CurrentTime); +} + + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) +{ + int i; + + _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_INACTIVE; + + for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++) + { + // Request conversion to the selected format + _glfwLibrary.X11.selection.target = + _glfwLibrary.X11.selection.formats[i]; + + XConvertSelection(_glfwLibrary.X11.display, + _glfwLibrary.X11.selection.atom, + _glfwLibrary.X11.selection.target, + _glfwLibrary.X11.selection.property, + window->X11.handle, CurrentTime); + + // Process the resulting SelectionNotify event + XSync(_glfwLibrary.X11.display, False); + while (_glfwLibrary.X11.selection.status == _GLFW_CONVERSION_INACTIVE) + _glfwPlatformWaitEvents(); + + if (_glfwLibrary.X11.selection.status == _GLFW_CONVERSION_SUCCEEDED) + break; + } + + if (_glfwLibrary.X11.selection.status == _GLFW_CONVERSION_FAILED) + { + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, + "X11/GLX: Failed to convert selection to string"); + return NULL; + } + + return _glfwLibrary.X11.selection.string; +} + diff --git a/src/x11_fullscreen.c b/src/x11_fullscreen.c index f0a3f194..2ff8a731 100644 --- a/src/x11_fullscreen.c +++ b/src/x11_fullscreen.c @@ -42,7 +42,7 @@ // Finds the video mode closest in size to the specified desired size //======================================================================== -int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate) +int _glfwGetClosestVideoMode(int* width, int* height, int* rate) { int i, match, bestmatch; @@ -55,8 +55,7 @@ int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate) XRRScreenConfiguration* sc; XRRScreenSize* sizelist; - sc = XRRGetScreenInfo(_glfwLibrary.X11.display, - RootWindow(_glfwLibrary.X11.display, screen)); + sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); sizelist = XRRConfigSizes(sc, &sizecount); @@ -116,7 +115,8 @@ int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate) int bestmode, modecount; // Get a list of all available display modes - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, screen, + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, &modecount, &modelist); // Find the best matching mode @@ -150,8 +150,8 @@ int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate) } // Default: Simply use the screen resolution - *width = DisplayWidth(_glfwLibrary.X11.display, screen); - *height = DisplayHeight(_glfwLibrary.X11.display, screen); + *width = DisplayWidth(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); + *height = DisplayHeight(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); return 0; } @@ -161,7 +161,7 @@ int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate) // Change the current video mode //======================================================================== -void _glfwSetVideoModeMODE(int screen, int mode, int rate) +void _glfwSetVideoModeMODE(int mode, int rate) { if (_glfwLibrary.X11.RandR.available) { @@ -169,15 +169,17 @@ void _glfwSetVideoModeMODE(int screen, int mode, int rate) XRRScreenConfiguration* sc; Window root; - root = RootWindow(_glfwLibrary.X11.display, screen); + root = _glfwLibrary.X11.root; sc = XRRGetScreenInfo(_glfwLibrary.X11.display, root); // Remember old size and flag that we have changed the mode if (!_glfwLibrary.X11.FS.modeChanged) { _glfwLibrary.X11.FS.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfwLibrary.X11.FS.oldRotation); - _glfwLibrary.X11.FS.oldWidth = DisplayWidth(_glfwLibrary.X11.display, screen); - _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display, screen); + _glfwLibrary.X11.FS.oldWidth = DisplayWidth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); _glfwLibrary.X11.FS.modeChanged = GL_TRUE; } @@ -214,21 +216,32 @@ void _glfwSetVideoModeMODE(int screen, int mode, int rate) int modecount; // Get a list of all available display modes - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, screen, + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, &modecount, &modelist); // Unlock mode switch if necessary if (_glfwLibrary.X11.FS.modeChanged) - XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, screen, 0); + { + XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 0); + } // Change the video mode to the desired mode - XF86VidModeSwitchToMode(_glfwLibrary.X11.display, screen, modelist[mode]); + XF86VidModeSwitchToMode(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + modelist[mode]); // Set viewport to upper left corner (where our window will be) - XF86VidModeSetViewPort(_glfwLibrary.X11.display, screen, 0, 0); + XF86VidModeSetViewPort(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 0, 0); // Lock mode switch - XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, screen, 1); + XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 1); // Remember old mode and flag that we have changed the mode if (!_glfwLibrary.X11.FS.modeChanged) @@ -247,15 +260,15 @@ void _glfwSetVideoModeMODE(int screen, int mode, int rate) // Change the current video mode //======================================================================== -void _glfwSetVideoMode(int screen, int* width, int* height, int* rate) +void _glfwSetVideoMode(int* width, int* height, int* rate) { int bestmode; // Find a best match mode - bestmode = _glfwGetClosestVideoMode(screen, width, height, rate); + bestmode = _glfwGetClosestVideoMode(width, height, rate); // Change mode - _glfwSetVideoModeMODE(screen, bestmode, *rate); + _glfwSetVideoModeMODE(bestmode, *rate); } @@ -263,7 +276,7 @@ void _glfwSetVideoMode(int screen, int* width, int* height, int* rate) // Restore the previously saved (original) video mode //======================================================================== -void _glfwRestoreVideoMode(int screen) +void _glfwRestoreVideoMode(void) { if (_glfwLibrary.X11.FS.modeChanged) { @@ -292,11 +305,13 @@ void _glfwRestoreVideoMode(int screen) { #if defined(_GLFW_HAS_XF86VIDMODE) // Unlock mode switch - XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, screen, 0); + XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + 0); // Change the video mode back to the old mode XF86VidModeSwitchToMode(_glfwLibrary.X11.display, - screen, + _glfwLibrary.X11.screen, &_glfwLibrary.X11.FS.oldMode); #endif /*_GLFW_HAS_XF86VIDMODE*/ } @@ -338,7 +353,7 @@ int _glfwCompareResolution(const void* left, const void* right) int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int maxcount) { int count, k, l, r, g, b, rgba, gl; - int depth, screen; + int depth; XVisualInfo* vislist; XVisualInfo dummy; int viscount, rgbcount, rescount; @@ -354,7 +369,7 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int max return 0; } - rgbarray = (int*) _glfwMalloc(sizeof(int) * viscount); + rgbarray = (int*) malloc(sizeof(int) * viscount); rgbcount = 0; // Build RGB array @@ -387,6 +402,8 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int max } } + XFree(vislist); + rescount = 0; resarray = NULL; @@ -399,7 +416,7 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int max unsigned int a; resource = XRRGetScreenResources(_glfwLibrary.X11.display, _glfwLibrary.X11.root); - resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * monitor->X11.output->nmode); + resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * monitor->X11.output->nmode); for (k = 0; k < monitor->X11.output->nmode; k++) { @@ -434,9 +451,11 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int max XF86VidModeModeInfo** modelist; int modecount, width, height; - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, screen, &modecount, &modelist); + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &modecount, &modelist); - resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * modecount); + resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * modecount); for (k = 0; k < modecount; k++) { @@ -465,10 +484,12 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int max if (!resarray) { rescount = 1; - resarray = (struct _glfwResolution*) _glfwMalloc(sizeof(struct _glfwResolution) * rescount); + resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * rescount); - resarray[0].width = DisplayWidth(_glfwLibrary.X11.display, screen); - resarray[0].height = DisplayHeight(_glfwLibrary.X11.display, screen); + resarray[0].width = DisplayWidth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + resarray[0].height = DisplayHeight(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); } // Build permutations of colors and resolutions @@ -486,10 +507,8 @@ int _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, GLFWvidmode* list, int max } } - XFree(vislist); - - _glfwFree(resarray); - _glfwFree(rgbarray); + free(resarray); + free(rgbarray); return count; } diff --git a/src/x11_gamma.c b/src/x11_gamma.c index fe02a939..44cd1139 100644 --- a/src/x11_gamma.c +++ b/src/x11_gamma.c @@ -33,6 +33,74 @@ #include +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Detect gamma ramp support and save original gamma ramp, if available +//======================================================================== + +void _glfwInitGammaRamp(void) +{ +#ifdef _GLFW_HAS_XRANDR + // RandR gamma support is only available with version 1.2 and above + if (_glfwLibrary.X11.RandR.available && + (_glfwLibrary.X11.RandR.majorVersion > 1 || + (_glfwLibrary.X11.RandR.majorVersion == 1 && + _glfwLibrary.X11.RandR.minorVersion >= 2))) + { + // FIXME: Assumes that all monitors have the same size gamma tables + // This is reasonable as I suspect the that if they did differ, it + // would imply that setting the gamma size to an arbitary size is + // possible as well. + XRRScreenResources* rr = XRRGetScreenResources(_glfwLibrary.X11.display, + _glfwLibrary.X11.root); + + _glfwLibrary.originalRampSize = XRRGetCrtcGammaSize(_glfwLibrary.X11.display, + rr->crtcs[0]); + if (!_glfwLibrary.originalRampSize) + { + // This is probably Nvidia RandR with broken gamma support + // Flag it as useless and try Xf86VidMode below, if available + _glfwLibrary.X11.RandR.gammaBroken = GL_TRUE; + } + + XRRFreeScreenResources(rr); + } +#endif /*_GLFW_HAS_XRANDR*/ + +#if defined(_GLFW_HAS_XF86VIDMODE) + if (_glfwLibrary.X11.VidMode.available && + !_glfwLibrary.originalRampSize) + { + // Get the gamma size using XF86VidMode + XF86VidModeGetGammaRampSize(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &_glfwLibrary.originalRampSize); + } +#endif /*_GLFW_HAS_XF86VIDMODE*/ + + if (_glfwLibrary.originalRampSize) + { + // Save the original gamma ramp + _glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp); + _glfwLibrary.currentRamp = _glfwLibrary.originalRamp; + } +} + + +//======================================================================== +// Restore original gamma ramp if necessary +//======================================================================== + +void _glfwTerminateGammaRamp(void) +{ + if (_glfwLibrary.originalRampSize && _glfwLibrary.rampChanged) + _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -43,6 +111,15 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) { + // For now, don't support anything that is not GLFW_GAMMA_RAMP_SIZE + if (_glfwLibrary.originalRampSize != GLFW_GAMMA_RAMP_SIZE) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to get gamma ramp due to size " + "incompatibility"); + return; + } + if (_glfwLibrary.X11.RandR.available && !_glfwLibrary.X11.RandR.gammaBroken) { @@ -85,6 +162,15 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp) { + // For now, don't support anything that is not GLFW_GAMMA_RAMP_SIZE + if (_glfwLibrary.originalRampSize != GLFW_GAMMA_RAMP_SIZE) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to set gamma ramp due to size " + "incompatibility"); + return; + } + if (_glfwLibrary.X11.RandR.available && !_glfwLibrary.X11.RandR.gammaBroken) { diff --git a/src/x11_init.c b/src/x11_init.c index 5697eb37..654e9fc9 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -30,37 +30,9 @@ #include "internal.h" -#include #include #include - - -//======================================================================== -// Dynamically load libraries -//======================================================================== - -static void initLibraries(void) -{ -#ifdef _GLFW_DLOPEN_LIBGL - int i; - char* libGL_names[ ] = - { - "libGL.so", - "libGL.so.1", - "/usr/lib/libGL.so", - "/usr/lib/libGL.so.1", - NULL - }; - - _glfwLibrary.X11.libGL = NULL; - for (i = 0; libGL_names[i] != NULL; i++) - { - _glfwLibrary.X11.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); - if (_glfwLibrary.X11.libGL) - break; - } -#endif -} +#include //======================================================================== @@ -79,7 +51,11 @@ static int keyCodeToGLFWKeyCode(int keyCode) // Note: This way we always force "NumLock = ON", which is intentional // since the returned key code should correspond to a physical // location. +#if defined(_GLFW_HAS_XKB) + keySym = XkbKeycodeToKeysym(_glfwLibrary.X11.display, keyCode, 1, 0); +#else keySym = XKeycodeToKeysym(_glfwLibrary.X11.display, keyCode, 1); +#endif switch (keySym) { case XK_KP_0: return GLFW_KEY_KP_0; @@ -102,7 +78,12 @@ static int keyCodeToGLFWKeyCode(int keyCode) // Now try pimary keysym for function keys (non-printable keys). These // should not be layout dependent (i.e. US layout and international // layouts should give the same result). +#if defined(_GLFW_HAS_XKB) + keySym = XkbKeycodeToKeysym(_glfwLibrary.X11.display, keyCode, 0, 0); +#else keySym = XKeycodeToKeysym(_glfwLibrary.X11.display, keyCode, 0); +#endif + switch (keySym) { case XK_Escape: return GLFW_KEY_ESCAPE; @@ -252,10 +233,8 @@ static void updateKeyCodeLUT(void) int keyCode; // Clear the LUT - for (keyCode = 0; keyCode < 256; ++keyCode) - { + for (keyCode = 0; keyCode < 256; keyCode++) _glfwLibrary.X11.keyCodeLUT[keyCode] = -1; - } #if defined(_GLFW_HAS_XKB) // If the Xkb extension is available, use it to determine physical key @@ -263,7 +242,7 @@ static void updateKeyCodeLUT(void) if (_glfwLibrary.X11.Xkb.available) { int i, keyCodeGLFW; - char name[XkbKeyNameLength+1]; + char name[XkbKeyNameLength + 1]; XkbDescPtr descr; // Get keyboard description @@ -275,10 +254,9 @@ static void updateKeyCodeLUT(void) for (keyCode = descr->min_key_code; keyCode <= descr->max_key_code; ++keyCode) { // Get the key name - for (i = 0; i < XkbKeyNameLength; ++i) - { + for (i = 0; i < XkbKeyNameLength; i++) name[i] = descr->names->keys[keyCode].name[i]; - } + name[XkbKeyNameLength] = 0; // Map the key name to a GLFW key code. Note: We only map printable @@ -337,9 +315,7 @@ static void updateKeyCodeLUT(void) // Update the key code LUT if ((keyCode >= 0) && (keyCode < 256)) - { _glfwLibrary.X11.keyCodeLUT[keyCode] = keyCodeGLFW; - } } // Free the keyboard description @@ -349,7 +325,7 @@ static void updateKeyCodeLUT(void) // Translate the un-translated key codes using traditional X11 KeySym // lookups - for (keyCode = 0; keyCode < 256; ++keyCode) + for (keyCode = 0; keyCode < 256; keyCode++) { if (_glfwLibrary.X11.keyCodeLUT[keyCode] < 0) { @@ -360,6 +336,152 @@ static void updateKeyCodeLUT(void) } +//======================================================================== +// Retrieve a single window property of the specified type +// Inspired by fghGetWindowProperty from freeglut +//======================================================================== + +static unsigned long getWindowProperty(Window window, + Atom property, + Atom type, + unsigned char** value) +{ + Atom actualType; + int actualFormat; + unsigned long itemCount, bytesAfter; + + XGetWindowProperty(_glfwLibrary.X11.display, + window, + property, + 0, + LONG_MAX, + False, + type, + &actualType, + &actualFormat, + &itemCount, + &bytesAfter, + value); + + if (actualType != type) + return 0; + + return itemCount; +} + + +//======================================================================== +// Check whether the specified atom is supported +//======================================================================== + +static Atom getSupportedAtom(Atom* supportedAtoms, + unsigned long atomCount, + const char* atomName) +{ + Atom atom = XInternAtom(_glfwLibrary.X11.display, atomName, True); + if (atom != None) + { + unsigned long i; + + for (i = 0; i < atomCount; i++) + { + if (supportedAtoms[i] == atom) + return atom; + } + } + + return None; +} + + +//======================================================================== +// Check whether the running window manager is EWMH-compliant +//======================================================================== + +static void initEWMH(void) +{ + Window* windowFromRoot = NULL; + Window* windowFromChild = NULL; + + // First we need a couple of atoms, which should already be there + Atom supportingWmCheck = + XInternAtom(_glfwLibrary.X11.display, "_NET_SUPPORTING_WM_CHECK", True); + Atom wmSupported = + XInternAtom(_glfwLibrary.X11.display, "_NET_SUPPORTED", True); + if (supportingWmCheck == None || wmSupported == None) + return; + + // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window + if (getWindowProperty(_glfwLibrary.X11.root, + supportingWmCheck, + XA_WINDOW, + (unsigned char**) &windowFromRoot) != 1) + { + XFree(windowFromRoot); + return; + } + + // It should be the ID of a child window (of the root) + // Then we look for the same property on the child window + if (getWindowProperty(*windowFromRoot, + supportingWmCheck, + XA_WINDOW, + (unsigned char**) &windowFromChild) != 1) + { + XFree(windowFromRoot); + XFree(windowFromChild); + return; + } + + // It should be the ID of that same child window + if (*windowFromRoot != *windowFromChild) + { + XFree(windowFromRoot); + XFree(windowFromChild); + return; + } + + XFree(windowFromRoot); + XFree(windowFromChild); + + // We are now fairly sure that an EWMH-compliant window manager is running + + Atom* supportedAtoms; + unsigned long atomCount; + + // Now we need to check the _NET_SUPPORTED property of the root window + // It should be a list of supported WM protocol and state atoms + atomCount = getWindowProperty(_glfwLibrary.X11.root, + wmSupported, + XA_ATOM, + (unsigned char**) &supportedAtoms); + + // See which of the atoms we support that are supported by the WM + + _glfwLibrary.X11.wmState = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE"); + + _glfwLibrary.X11.wmStateFullscreen = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN"); + + _glfwLibrary.X11.wmName = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_NAME"); + + _glfwLibrary.X11.wmIconName = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_ICON_NAME"); + + _glfwLibrary.X11.wmPing = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_PING"); + + _glfwLibrary.X11.wmActiveWindow = + getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW"); + + XFree(supportedAtoms); + + _glfwLibrary.X11.hasEWMH = GL_TRUE; +} + + //======================================================================== // Initialize X11 display and look for supported X11 extensions //======================================================================== @@ -411,22 +533,6 @@ static GLboolean initDisplay(void) _glfwLibrary.X11.RandR.available = GL_FALSE; #endif /*_GLFW_HAS_XRANDR*/ - // Check if GLX is supported on this display - if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); - return GL_FALSE; - } - - if (!glXQueryVersion(_glfwLibrary.X11.display, - &_glfwLibrary.X11.glxMajor, - &_glfwLibrary.X11.glxMinor)) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: Failed to query GLX version"); - return GL_FALSE; - } - // Check if Xkb is supported on this display #if defined(_GLFW_HAS_XKB) _glfwLibrary.X11.Xkb.majorVersion = 1; @@ -447,65 +553,30 @@ static GLboolean initDisplay(void) // the keyboard mapping. updateKeyCodeLUT(); + // Find or create selection property atom + _glfwLibrary.X11.selection.property = + XInternAtom(_glfwLibrary.X11.display, "GLFW_SELECTION", False); + + // Find or create clipboard atom + _glfwLibrary.X11.selection.atom = + XInternAtom(_glfwLibrary.X11.display, "CLIPBOARD", False); + + // Find or create selection target atoms + _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_UTF8] = + XInternAtom(_glfwLibrary.X11.display, "UTF8_STRING", False); + _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] = + XInternAtom(_glfwLibrary.X11.display, "COMPOUND_STRING", False); + _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_STRING] = + XA_STRING; + + _glfwLibrary.X11.selection.targets = XInternAtom(_glfwLibrary.X11.display, + "TARGETS", + False); + return GL_TRUE; } -//======================================================================== -// Detect gamma ramp support and save original gamma ramp, if available -//======================================================================== - -static void initGammaRamp(void) -{ -#ifdef _GLFW_HAS_XRANDR - // RandR gamma support is only available with version 1.2 and above - if (_glfwLibrary.X11.RandR.available && - (_glfwLibrary.X11.RandR.majorVersion > 1 || - _glfwLibrary.X11.RandR.majorVersion == 1 && - _glfwLibrary.X11.RandR.minorVersion >= 2)) - { - // FIXME: Assumes that all monitors have the same size gamma tables - // This is reasonable as I suspect the that if they did differ, it - // would imply that setting the gamma size to an arbitary size is - // possible as well. - XRRScreenResources* rr = XRRGetScreenResources(_glfwLibrary.X11.display, - _glfwLibrary.X11.root); - - _glfwLibrary.originalRampSize = XRRGetCrtcGammaSize(_glfwLibrary.X11.display, - rr->crtcs[0]); - if (!_glfwLibrary.originalRampSize) - { - // This is probably Nvidia RandR with broken gamma support - // Flag it as useless and try Xf86VidMode below, if available - _glfwLibrary.X11.RandR.gammaBroken = GL_TRUE; - fprintf(stderr, - "Ignoring broken nVidia implementation of RandR 1.2+ gamma\n"); - } - - XRRFreeScreenResources(rr); - } -#endif /*_GLFW_HAS_XRANDR*/ - -#if defined(_GLFW_HAS_XF86VIDMODE) - if (_glfwLibrary.X11.VidMode.available && - !_glfwLibrary.originalRampSize) - { - // Get the gamma size using XF86VidMode - XF86VidModeGetGammaRampSize(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &_glfwLibrary.originalRampSize); - } -#endif /*_GLFW_HAS_XF86VIDMODE*/ - - if (!_glfwLibrary.originalRampSize) - fprintf(stderr, "No supported gamma ramp API found\n"); - - // Save the original gamma ramp - _glfwPlatformGetGammaRamp(&_glfwLibrary.originalRamp); - _glfwLibrary.currentRamp = _glfwLibrary.originalRamp; -} - - //======================================================================== // Create a blank cursor (for locked mouse mode) //======================================================================== @@ -545,9 +616,6 @@ static Cursor createNULLCursor(void) static void terminateDisplay(void) { - if (_glfwLibrary.originalRampSize) - _glfwPlatformSetGammaRamp(&_glfwLibrary.originalRamp); - if (_glfwLibrary.X11.display) { XCloseDisplay(_glfwLibrary.X11.display); @@ -569,13 +637,15 @@ int _glfwPlatformInit(void) if (!initDisplay()) return GL_FALSE; - initGammaRamp(); + _glfwInitGammaRamp(); + + if (!_glfwInitOpenGL()) + return GL_FALSE; + + initEWMH(); _glfwLibrary.X11.cursor = createNULLCursor(); - // Try to load libGL.so if necessary - initLibraries(); - _glfwInitJoysticks(); _glfwInitMonitors(); @@ -599,20 +669,19 @@ int _glfwPlatformTerminate(void) _glfwLibrary.X11.cursor = (Cursor) 0; } + _glfwTerminateGammaRamp(); + terminateDisplay(); _glfwTerminateMonitors(); _glfwTerminateJoysticks(); - // Unload libGL.so if necessary -#ifdef _GLFW_DLOPEN_LIBGL - if (_glfwLibrary.X11.libGL != NULL) - { - dlclose(_glfwLibrary.X11.libGL); - _glfwLibrary.X11.libGL = NULL; - } -#endif + _glfwTerminateOpenGL(); + + // Free clipboard memory + if (_glfwLibrary.X11.selection.string) + free(_glfwLibrary.X11.selection.string); return GL_TRUE; } @@ -655,6 +724,9 @@ const char* _glfwPlatformGetVersionString(void) " Linux-joystick-API" #else " no-joystick-support" +#endif +#if defined(_GLFW_BUILD_DLL) + " shared" #endif ; diff --git a/src/x11_monitor.c b/src/x11_monitor.c index d22bcda7..d22c1c59 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -43,13 +43,13 @@ _GLFWmonitor** _glfwCreateMonitor(_GLFWmonitor** current, XRROutputInfo* outputInfo, XRRCrtcInfo* crtcInfo) { - *current = _glfwMalloc(sizeof(_GLFWmonitor)); + *current = malloc(sizeof(_GLFWmonitor)); memset(*current, 0, sizeof(_GLFWmonitor)); (*current)->physicalWidth = outputInfo->mm_width; (*current)->physicalHeight = outputInfo->mm_height; - (*current)->name = _glfwMalloc(strlen(outputInfo->name) + 1); + (*current)->name = malloc(strlen(outputInfo->name) + 1); memcpy((*current)->name, outputInfo->name, strlen(outputInfo->name) + 1); (*current)->name[strlen(outputInfo->name)] = '\0'; @@ -71,8 +71,8 @@ _GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor) XRRFreeOutputInfo(monitor->X11.output); #endif /*_GLFW_HAS_XRANDR*/ - _glfwFree(monitor->name); - _glfwFree(monitor); + free(monitor->name); + free(monitor); return result; } diff --git a/src/x11_opengl.c b/src/x11_opengl.c index fd8bd313..dc2788c8 100644 --- a/src/x11_opengl.c +++ b/src/x11_opengl.c @@ -30,15 +30,656 @@ #include "internal.h" +#include +#include + // This is the only glXGetProcAddress variant not declared by glxext.h void (*glXGetProcAddressEXT(const GLubyte* procName))(); +//======================================================================== +// Returns the specified attribute of the specified GLXFBConfig +// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig +//======================================================================== + +static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) +{ + int value; + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + _glfwLibrary.GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, + fbconfig, attrib, &value); + } + else + glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); + + return value; +} + + +//======================================================================== +// Return a list of available and usable framebuffer configs +//======================================================================== + +static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) +{ + GLXFBConfig* fbconfigs; + _GLFWfbconfig* result; + int i, count = 0; + const char* vendor; + GLboolean trustWindowBit = GL_TRUE; + + *found = 0; + + if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) + { + if (!_glfwLibrary.GLX.SGIX_fbconfig) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: GLXFBConfig support not found"); + return NULL; + } + } + + vendor = glXGetClientString(_glfwLibrary.X11.display, GLX_VENDOR); + + if (strcmp(vendor, "Chromium") == 0) + { + // This is a (hopefully temporary) workaround for Chromium (VirtualBox + // GL) not setting the window bit on any GLXFBConfigs + trustWindowBit = GL_FALSE; + } + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + fbconfigs = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + NULL, + &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: No GLXFBConfigs returned"); + return NULL; + } + } + else + { + fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: No GLXFBConfigs returned"); + return NULL; + } + } + + result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); + if (!result) + { + _glfwSetError(GLFW_OUT_OF_MEMORY, + "X11/GLX: Failed to allocate _GLFWfbconfig array"); + return NULL; + } + + for (i = 0; i < count; i++) + { + _GLFWfbconfig* f = result + *found; + + if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || + !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) + { + // Only consider double-buffered GLXFBConfigs with associated visuals + continue; + } + + if (!(getFBConfigAttrib(window, + fbconfigs[i], + GLX_RENDER_TYPE) & GLX_RGBA_BIT)) + { + // Only consider RGBA GLXFBConfigs + continue; + } + + if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) + { + if (trustWindowBit) + { + // Only consider window GLXFBConfigs + continue; + } + } + + f->redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); + f->greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); + f->blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); + + f->alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); + f->depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); + f->stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); + + f->accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); + f->accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); + f->accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); + f->accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); + + f->auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); + f->stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); + + if (_glfwLibrary.GLX.ARB_multisample) + f->samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); + else + f->samples = 0; + + f->platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); + + (*found)++; + } + + XFree(fbconfigs); + + return result; +} + + +//======================================================================== +// Error handler for BadMatch errors when requesting context with +// unavailable OpenGL versions using the GLX_ARB_create_context extension +//======================================================================== + +static int errorHandler(Display *display, XErrorEvent* event) +{ + return 0; +} + + +//======================================================================== +// Read back framebuffer parameters from the context +//======================================================================== + +static void refreshContextParams(_GLFWwindow* window, GLXFBConfigID fbconfigID) +{ + int dummy; + GLXFBConfig* fbconfig; + + int attribs[] = { GLX_FBCONFIG_ID, fbconfigID, None }; + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + else + { + fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + + if (fbconfig == NULL) + { + // This should never ever happen + // TODO: Flag this as an error and propagate up + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Cannot find known " + "GLXFBConfig by ID. This cannot " + "happen. Have a nice day.\n"); + abort(); + } + + // There is no clear definition of an "accelerated" context on X11/GLX, and + // true sounds better than false, so we hardcode true here + window->accelerated = GL_TRUE; + + window->redBits = getFBConfigAttrib(window, *fbconfig, GLX_RED_SIZE); + window->greenBits = getFBConfigAttrib(window, *fbconfig, GLX_GREEN_SIZE); + window->blueBits = getFBConfigAttrib(window, *fbconfig, GLX_BLUE_SIZE); + + window->alphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ALPHA_SIZE); + window->depthBits = getFBConfigAttrib(window, *fbconfig, GLX_DEPTH_SIZE); + window->stencilBits = getFBConfigAttrib(window, *fbconfig, GLX_STENCIL_SIZE); + + window->accumRedBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_RED_SIZE); + window->accumGreenBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_GREEN_SIZE); + window->accumBlueBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_BLUE_SIZE); + window->accumAlphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_ALPHA_SIZE); + + window->auxBuffers = getFBConfigAttrib(window, *fbconfig, GLX_AUX_BUFFERS); + window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; + + // Get FSAA buffer sample count + if (_glfwLibrary.GLX.ARB_multisample) + window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); + else + window->samples = 0; + + XFree(fbconfig); +} + + +//======================================================================== +// Create the actual OpenGL context +//======================================================================== + +#define setGLXattrib(attribs, index, attribName, attribValue) \ + attribs[index++] = attribName; \ + attribs[index++] = attribValue; + +static int createContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + GLXFBConfigID fbconfigID) +{ + int attribs[40]; + int dummy, index; + GLXFBConfig* fbconfig; + GLXContext share = NULL; + + if (wndconfig->share) + share = wndconfig->share->GLX.context; + + // Retrieve the previously selected GLXFBConfig + { + index = 0; + + setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); + setGLXattrib(attribs, index, None, None); + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + else + { + fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + + if (fbconfig == NULL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve the selected GLXFBConfig"); + return GL_FALSE; + } + } + + // Retrieve the corresponding visual + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + window->GLX.visual = _glfwLibrary.GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, + *fbconfig); + } + else + { + window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, + *fbconfig); + } + + if (window->GLX.visual == NULL) + { + XFree(fbconfig); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve visual for GLXFBConfig"); + return GL_FALSE; + } + + if (_glfwLibrary.GLX.ARB_create_context) + { + index = 0; + + if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) + { + // Request an explicitly versioned context + + setGLXattrib(attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); + setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); + } + + if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) + { + int flags = 0; + + if (wndconfig->glForward) + flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + + if (wndconfig->glDebug) + flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + + if (wndconfig->glRobustness) + flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + + setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); + } + + if (wndconfig->glProfile) + { + int flags = 0; + + if (!_glfwLibrary.GLX.ARB_create_context_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: An OpenGL profile requested but " + "GLX_ARB_create_context_profile is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && + !_glfwLibrary.GLX.EXT_create_context_es2_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: OpenGL ES 2.x profile requested but " + "GLX_EXT_create_context_es2_profile is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) + flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) + flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) + flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + + setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); + } + + if (wndconfig->glRobustness) + { + int strategy; + + if (!_glfwLibrary.GLX.ARB_create_context_robustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: An OpenGL robustness strategy was " + "requested but GLX_ARB_create_context_robustness " + "is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) + strategy = GLX_NO_RESET_NOTIFICATION_ARB; + else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) + strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; + + setGLXattrib(attribs, + index, + GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + strategy); + } + + setGLXattrib(attribs, index, None, None); + + // This is the only place we set an Xlib error handler, and we only do + // it because glXCreateContextAttribsARB generates a BadMatch error if + // the requested OpenGL version is unavailable (instead of a civilized + // response like returning NULL) + XSetErrorHandler(errorHandler); + + window->GLX.context = + _glfwLibrary.GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, + *fbconfig, + share, + True, + attribs); + + // We are done, so unset the error handler again (see above) + XSetErrorHandler(NULL); + } + else + { + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + window->GLX.context = + _glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + else + { + window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + } + + XFree(fbconfig); + + if (window->GLX.context == NULL) + { + // TODO: Handle all the various error codes here + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to create OpenGL context"); + return GL_FALSE; + } + + refreshContextParams(window, fbconfigID); + + return GL_TRUE; +} + +#undef setGLXattrib + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +//======================================================================== +// Initialize GLX +//======================================================================== + +int _glfwInitOpenGL(void) +{ +#ifdef _GLFW_DLOPEN_LIBGL + int i; + char* libGL_names[ ] = + { + "libGL.so", + "libGL.so.1", + "/usr/lib/libGL.so", + "/usr/lib/libGL.so.1", + NULL + }; + + for (i = 0; libGL_names[i] != NULL; i++) + { + _glfwLibrary.GLX.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfwLibrary.GLX.libGL) + break; + } + + if (!_glfwLibrary.GLX.libGL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Failed to find libGL"); + return GL_FALSE; + } +#endif + + // Check if GLX is supported on this display + if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); + return GL_FALSE; + } + + if (!glXQueryVersion(_glfwLibrary.X11.display, + &_glfwLibrary.GLX.majorVersion, + &_glfwLibrary.GLX.minorVersion)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: Failed to query GLX version"); + return GL_FALSE; + } + + if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) + { + _glfwLibrary.GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); + + if (_glfwLibrary.GLX.SwapIntervalEXT) + _glfwLibrary.GLX.EXT_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) + { + _glfwLibrary.GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); + + if (_glfwLibrary.GLX.SwapIntervalSGI) + _glfwLibrary.GLX.SGI_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) + { + _glfwLibrary.GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) + _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); + _glfwLibrary.GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); + _glfwLibrary.GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); + _glfwLibrary.GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); + + if (_glfwLibrary.GLX.GetFBConfigAttribSGIX && + _glfwLibrary.GLX.ChooseFBConfigSGIX && + _glfwLibrary.GLX.CreateContextWithConfigSGIX && + _glfwLibrary.GLX.GetVisualFromFBConfigSGIX) + { + _glfwLibrary.GLX.SGIX_fbconfig = GL_TRUE; + } + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) + _glfwLibrary.GLX.ARB_multisample = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) + { + _glfwLibrary.GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) + _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); + + if (_glfwLibrary.GLX.CreateContextAttribsARB) + _glfwLibrary.GLX.ARB_create_context = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + _glfwLibrary.GLX.ARB_create_context_robustness = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + _glfwLibrary.GLX.ARB_create_context_profile = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + _glfwLibrary.GLX.EXT_create_context_es2_profile = GL_TRUE; + + return GL_TRUE; +} + + +//======================================================================== +// Terminate GLX +//======================================================================== + +void _glfwTerminateOpenGL(void) +{ + // Unload libGL.so if necessary +#ifdef _GLFW_DLOPEN_LIBGL + if (_glfwLibrary.GLX.libGL != NULL) + { + dlclose(_glfwLibrary.GLX.libGL); + _glfwLibrary.GLX.libGL = NULL; + } +#endif +} + + +//======================================================================== +// Prepare for creation of the OpenGL context +//======================================================================== + +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + _GLFWfbconfig closest; + + // Choose the best available fbconfig + { + unsigned int fbcount; + _GLFWfbconfig* fbconfigs; + const _GLFWfbconfig* result; + + fbconfigs = getFBConfigs(window, &fbcount); + if (!fbconfigs) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: No usable GLXFBConfigs found"); + return GL_FALSE; + } + + result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); + if (!result) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: No GLXFBConfig matched the criteria"); + + free(fbconfigs); + return GL_FALSE; + } + + closest = *result; + free(fbconfigs); + } + + return createContext(window, wndconfig, closest.platformID); +} + + +//======================================================================== +// Destroy the OpenGL context +//======================================================================== + +void _glfwDestroyContext(_GLFWwindow* window) +{ + if (window->GLX.visual) + { + XFree(window->GLX.visual); + window->GLX.visual = NULL; + } + + if (window->GLX.context) + { + // Release and destroy the context + glXMakeCurrent(_glfwLibrary.X11.display, None, NULL); + glXDestroyContext(_glfwLibrary.X11.display, window->GLX.context); + window->GLX.context = NULL; + } +} + + +//======================================================================== +// Return the X visual associated with the specified context +//======================================================================== + +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window) +{ + return window->GLX.visual; +} + + //======================================================================== // Make the OpenGL context associated with the specified window current //======================================================================== @@ -75,14 +716,14 @@ void _glfwPlatformSwapInterval(int interval) { _GLFWwindow* window = _glfwLibrary.currentWindow; - if (window->GLX.EXT_swap_control) + if (_glfwLibrary.GLX.EXT_swap_control) { - window->GLX.SwapIntervalEXT(_glfwLibrary.X11.display, - window->X11.handle, - interval); + _glfwLibrary.GLX.SwapIntervalEXT(_glfwLibrary.X11.display, + window->X11.handle, + interval); } - else if (window->GLX.SGI_swap_control) - window->GLX.SwapIntervalSGI(interval); + else if (_glfwLibrary.GLX.SGI_swap_control) + _glfwLibrary.GLX.SwapIntervalSGI(interval); } @@ -111,9 +752,9 @@ int _glfwPlatformExtensionSupported(const char* extension) // Get the function pointer to an OpenGL function //======================================================================== -void* _glfwPlatformGetProcAddress(const char* procname) +GLFWglproc _glfwPlatformGetProcAddress(const char* procname) { - return (void*) _glfw_glXGetProcAddress((const GLubyte*) procname); + return _glfw_glXGetProcAddress((const GLubyte*) procname); } diff --git a/src/x11_platform.h b/src/x11_platform.h index 1163a53f..69192993 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -75,17 +75,31 @@ #elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT) #define _glfw_glXGetProcAddress(x) glXGetProcAddressEXT(x) #elif defined(_GLFW_HAS_DLOPEN) - #define _glfw_glXGetProcAddress(x) dlsym(_glfwLibrary.X11.libGL, x) + #define _glfw_glXGetProcAddress(x) dlsym(_glfwLibrary.GLX.libGL, x) #define _GLFW_DLOPEN_LIBGL #else #error "No OpenGL entry point retrieval mechanism was enabled" #endif #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 X11 -#define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11 #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX + #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 X11 +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 X11 +#define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryGLX GLX + +// Clipboard format atom indices +#define _GLFW_CLIPBOARD_FORMAT_UTF8 0 +#define _GLFW_CLIPBOARD_FORMAT_COMPOUND 1 +#define _GLFW_CLIPBOARD_FORMAT_STRING 2 +#define _GLFW_CLIPBOARD_FORMAT_COUNT 3 + +// Clipboard conversion status tokens +#define _GLFW_CONVERSION_INACTIVE 0 +#define _GLFW_CONVERSION_SUCCEEDED 1 +#define _GLFW_CONVERSION_FAILED 2 + //======================================================================== // GLFW platform specific types @@ -102,27 +116,9 @@ typedef intptr_t GLFWintptr; //------------------------------------------------------------------------ typedef struct _GLFWcontextGLX { - GLXFBConfigID fbconfigID; // ID of selected GLXFBConfig GLXContext context; // OpenGL rendering context XVisualInfo* visual; // Visual for selected GLXFBConfig - // GLX extensions - PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; - PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX; - PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX; - PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX; - PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX; - PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; - GLboolean SGIX_fbconfig; - GLboolean SGI_swap_control; - GLboolean EXT_swap_control; - GLboolean ARB_multisample; - GLboolean ARB_create_context; - GLboolean ARB_create_context_profile; - GLboolean ARB_create_context_robustness; - GLboolean EXT_create_context_es2_profile; - } _GLFWcontextGLX; @@ -134,16 +130,8 @@ typedef struct _GLFWwindowX11 // Platform specific window resources Colormap colormap; // Window colormap Window handle; // Window handle - Atom wmDeleteWindow; // WM_DELETE_WINDOW atom - Atom wmName; // _NET_WM_NAME atom - Atom wmIconName; // _NET_WM_ICON_NAME atom - Atom wmPing; // _NET_WM_PING atom - Atom wmState; // _NET_WM_STATE atom - Atom wmStateFullscreen; // _NET_WM_STATE_FULLSCREEN atom - Atom wmActiveWindow; // _NET_ACTIVE_WINDOW atom // Various platform specific internal variables - GLboolean hasEWMH; // True if window manager supports EWMH GLboolean overrideRedirect; // True if window is OverrideRedirect GLboolean keyboardGrabbed; // True if keyboard is currently grabbed GLboolean cursorGrabbed; // True if cursor is currently grabbed @@ -155,7 +143,7 @@ typedef struct _GLFWwindowX11 //------------------------------------------------------------------------ -// Platform-specific library global data +// Platform-specific library global data for X11 //------------------------------------------------------------------------ typedef struct _GLFWlibraryX11 { @@ -164,8 +152,16 @@ typedef struct _GLFWlibraryX11 Window root; Cursor cursor; // Invisible cursor for hidden cursor - // Server-side GLX version - int glxMajor, glxMinor; + Atom wmDeleteWindow; // WM_DELETE_WINDOW atom + Atom wmName; // _NET_WM_NAME atom + Atom wmIconName; // _NET_WM_ICON_NAME atom + Atom wmPing; // _NET_WM_PING atom + Atom wmState; // _NET_WM_STATE atom + Atom wmStateFullscreen; // _NET_WM_STATE_FULLSCREEN atom + Atom wmActiveWindow; // _NET_ACTIVE_WINDOW atom + + // True if window manager supports EWMH + GLboolean hasEWMH; struct { GLboolean available; @@ -224,10 +220,49 @@ typedef struct _GLFWlibraryX11 uint64_t base; } timer; + // Selection data + struct { + Atom atom; + Atom formats[_GLFW_CLIPBOARD_FORMAT_COUNT]; + char* string; + Atom target; + Atom targets; + Atom property; + int status; + } selection; + +} _GLFWlibraryX11; + + +//------------------------------------------------------------------------ +// Platform-specific library global data for GLX +//------------------------------------------------------------------------ +typedef struct _GLFWlibraryGLX +{ + // Server-side GLX version + int majorVersion, minorVersion; + + // GLX extensions + PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; + PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; + PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX; + PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX; + PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX; + PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX; + PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; + GLboolean SGIX_fbconfig; + GLboolean SGI_swap_control; + GLboolean EXT_swap_control; + GLboolean ARB_multisample; + GLboolean ARB_create_context; + GLboolean ARB_create_context_profile; + GLboolean ARB_create_context_robustness; + GLboolean EXT_create_context_es2_profile; + #if defined(_GLFW_DLOPEN_LIBGL) void* libGL; // dlopen handle for libGL.so #endif -} _GLFWlibraryX11; +} _GLFWlibraryGLX; //------------------------------------------------------------------------ @@ -264,11 +299,24 @@ typedef struct _GLFWmonitorX11 // Time void _glfwInitTimer(void); +// Gamma +void _glfwInitGammaRamp(void); +void _glfwTerminateGammaRamp(void); + +// OpenGL support +int _glfwInitOpenGL(void); +void _glfwTerminateOpenGL(void); +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContext(_GLFWwindow* window); +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window); + // Fullscreen support -int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate); -void _glfwSetVideoModeMODE(int screen, int mode, int rate); -void _glfwSetVideoMode(int screen, int* width, int* height, int* rate); -void _glfwRestoreVideoMode(int screen); +int _glfwGetClosestVideoMode(int* width, int* height, int* rate); +void _glfwSetVideoModeMODE(int mode, int rate); +void _glfwSetVideoMode(int* width, int* height, int* rate); +void _glfwRestoreVideoMode(void); // Joystick input void _glfwInitJoysticks(void); @@ -281,5 +329,11 @@ _GLFWmonitor* _glfwDestroyMonitor(_GLFWmonitor* monitor); // Unicode support long _glfwKeySym2Unicode(KeySym keysym); +// Clipboard handling +GLboolean _glfwReadSelection(XSelectionEvent* request); +Atom _glfwWriteSelection(XSelectionRequestEvent* request); + +// Event processing +void _glfwProcessPendingEvents(void); #endif // _platform_h_ diff --git a/src/x11_time.c b/src/x11_time.c index e2203941..f1445233 100644 --- a/src/x11_time.c +++ b/src/x11_time.c @@ -30,6 +30,7 @@ #include "internal.h" +#include #include @@ -39,7 +40,7 @@ static uint64_t getRawTime(void) { -#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) +#if defined(CLOCK_MONOTONIC) if (_glfwLibrary.X11.timer.monotonic) { struct timespec ts; @@ -64,7 +65,7 @@ static uint64_t getRawTime(void) void _glfwInitTimer(void) { -#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) +#if defined(CLOCK_MONOTONIC) struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) diff --git a/src/x11_window.c b/src/x11_window.c index 9eb315fd..5cc7f6f4 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -30,7 +30,6 @@ #include "internal.h" -#include #include #include #include @@ -41,19 +40,8 @@ #define _NET_WM_STATE_TOGGLE 2 // Additional mouse button names for XButtonEvent -#define Button6 6 -#define Button7 7 - -//======================================================================== -// Error handler for BadMatch errors when requesting context with -// unavailable OpenGL versions using the GLX_ARB_create_context extension -//======================================================================== - -static int errorHandler(Display *display, XErrorEvent* event) -{ - return 0; -} - +#define Button6 6 +#define Button7 7 //======================================================================== // Checks whether the event is a MapNotify for the specified window @@ -65,154 +53,6 @@ static Bool isMapNotify(Display* d, XEvent* e, char* arg) } -//======================================================================== -// Retrieve a single window property of the specified type -// Inspired by fghGetWindowProperty from freeglut -//======================================================================== - -static unsigned long getWindowProperty(Window window, - Atom property, - Atom type, - unsigned char** value) -{ - Atom actualType; - int actualFormat; - unsigned long itemCount, bytesAfter; - - XGetWindowProperty(_glfwLibrary.X11.display, - window, - property, - 0, - LONG_MAX, - False, - type, - &actualType, - &actualFormat, - &itemCount, - &bytesAfter, - value); - - if (actualType != type) - return 0; - - return itemCount; -} - - -//======================================================================== -// Check whether the specified atom is supported -//======================================================================== - -static Atom getSupportedAtom(Atom* supportedAtoms, - unsigned long atomCount, - const char* atomName) -{ - Atom atom = XInternAtom(_glfwLibrary.X11.display, atomName, True); - if (atom != None) - { - unsigned long i; - - for (i = 0; i < atomCount; i++) - { - if (supportedAtoms[i] == atom) - return atom; - } - } - - return None; -} - - -//======================================================================== -// Check whether the running window manager is EWMH-compliant -//======================================================================== - -static GLboolean hasEWMH(_GLFWwindow* window) -{ - Window* windowFromRoot = NULL; - Window* windowFromChild = NULL; - - // Hey kids; let's see if the window manager supports EWMH! - - // First we need a couple of atoms, which should already be there - Atom supportingWmCheck = - XInternAtom(_glfwLibrary.X11.display, "_NET_SUPPORTING_WM_CHECK", True); - Atom wmSupported = - XInternAtom(_glfwLibrary.X11.display, "_NET_SUPPORTED", True); - if (supportingWmCheck == None || wmSupported == None) - return GL_FALSE; - - // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window - if (getWindowProperty(_glfwLibrary.X11.root, - supportingWmCheck, - XA_WINDOW, - (unsigned char**) &windowFromRoot) != 1) - { - XFree(windowFromRoot); - return GL_FALSE; - } - - // It should be the ID of a child window (of the root) - // Then we look for the same property on the child window - if (getWindowProperty(*windowFromRoot, - supportingWmCheck, - XA_WINDOW, - (unsigned char**) &windowFromChild) != 1) - { - XFree(windowFromRoot); - XFree(windowFromChild); - return GL_FALSE; - } - - // It should be the ID of that same child window - if (*windowFromRoot != *windowFromChild) - { - XFree(windowFromRoot); - XFree(windowFromChild); - return GL_FALSE; - } - - XFree(windowFromRoot); - XFree(windowFromChild); - - // We are now fairly sure that an EWMH-compliant window manager is running - - Atom* supportedAtoms; - unsigned long atomCount; - - // Now we need to check the _NET_SUPPORTED property of the root window - // It should be a list of supported WM protocol and state atoms - atomCount = getWindowProperty(_glfwLibrary.X11.root, - wmSupported, - XA_ATOM, - (unsigned char**) &supportedAtoms); - - // See which of the atoms we support that are supported by the WM - - window->X11.wmState = - getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE"); - - window->X11.wmStateFullscreen = - getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN"); - - window->X11.wmName = - getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_NAME"); - - window->X11.wmIconName = - getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_ICON_NAME"); - - window->X11.wmPing = - getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_PING"); - - window->X11.wmActiveWindow = - getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW"); - - XFree(supportedAtoms); - - return GL_TRUE; -} - - //======================================================================== // Translates an X Window key to internal coding //======================================================================== @@ -247,417 +87,6 @@ static int translateChar(XKeyEvent* event) } -//======================================================================== -// Returns the specified attribute of the specified GLXFBConfig -// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig -//======================================================================== - -static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) -{ - int value; - - if (window->GLX.SGIX_fbconfig) - { - window->GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, - fbconfig, attrib, &value); - } - else - glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); - - return value; -} - - -//======================================================================== -// Return a list of available and usable framebuffer configs -//======================================================================== - -static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) -{ - GLXFBConfig* fbconfigs; - _GLFWfbconfig* result; - int i, count = 0; - - *found = 0; - - if (_glfwLibrary.X11.glxMajor == 1 && _glfwLibrary.X11.glxMinor < 3) - { - if (!window->GLX.SGIX_fbconfig) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: GLXFBConfig support not found"); - return NULL; - } - } - - if (window->GLX.SGIX_fbconfig) - { - fbconfigs = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - NULL, - &count); - if (!count) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); - return NULL; - } - } - else - { - fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &count); - if (!count) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); - return NULL; - } - } - - result = (_GLFWfbconfig*) _glfwMalloc(sizeof(_GLFWfbconfig) * count); - if (!result) - { - _glfwSetError(GLFW_OUT_OF_MEMORY, - "X11/GLX: Failed to allocate _GLFWfbconfig array"); - return NULL; - } - - for (i = 0; i < count; i++) - { - if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || - !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) - { - // Only consider double-buffered GLXFBConfigs with associated visuals - continue; - } - - if (!(getFBConfigAttrib(window, - fbconfigs[i], - GLX_RENDER_TYPE) & GLX_RGBA_BIT)) - { - // Only consider RGBA GLXFBConfigs - continue; - } - - if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) - { - // Only consider window GLXFBConfigs - continue; - } - - result[*found].redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); - result[*found].greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); - result[*found].blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); - - result[*found].alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); - result[*found].depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); - result[*found].stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); - - result[*found].accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); - result[*found].accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); - result[*found].accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); - result[*found].accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); - - result[*found].auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); - result[*found].stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); - - if (window->GLX.ARB_multisample) - result[*found].samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); - else - result[*found].samples = 0; - - result[*found].platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); - - (*found)++; - } - - XFree(fbconfigs); - - return result; -} - - -//======================================================================== -// Create the OpenGL context -//======================================================================== - -#define setGLXattrib(attribs, index, attribName, attribValue) \ - attribs[index++] = attribName; \ - attribs[index++] = attribValue; - -static int createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - GLXFBConfigID fbconfigID) -{ - int attribs[40]; - int dummy, index; - GLXFBConfig* fbconfig; - GLXContext share = NULL; - - if (wndconfig->share) - share = wndconfig->share->GLX.context; - - // Retrieve the previously selected GLXFBConfig - { - index = 0; - - setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); - setGLXattrib(attribs, index, None, None); - - if (window->GLX.SGIX_fbconfig) - { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - else - { - fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - - if (fbconfig == NULL) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve the selected GLXFBConfig"); - return GL_FALSE; - } - } - - // Retrieve the corresponding visual - if (window->GLX.SGIX_fbconfig) - { - window->GLX.visual = window->GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, - *fbconfig); - } - else - { - window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, - *fbconfig); - } - - if (window->GLX.visual == NULL) - { - XFree(fbconfig); - - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve visual for GLXFBConfig"); - return GL_FALSE; - } - - if (window->GLX.ARB_create_context) - { - index = 0; - - if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) - { - // Request an explicitly versioned context - - setGLXattrib(attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); - setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); - } - - if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) - { - int flags = 0; - - if (wndconfig->glForward) - flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - - if (wndconfig->glDebug) - flags |= GLX_CONTEXT_DEBUG_BIT_ARB; - - if (wndconfig->glRobustness) - flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; - - setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); - } - - if (wndconfig->glProfile) - { - int flags = 0; - - if (!window->GLX.ARB_create_context_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL profile requested but " - "GLX_ARB_create_context_profile is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !window->GLX.EXT_create_context_es2_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: OpenGL ES 2.x profile requested but " - "GLX_EXT_create_context_es2_profile is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) - flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) - flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) - flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; - - setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); - } - - if (wndconfig->glRobustness) - { - int strategy; - - if (!window->GLX.ARB_create_context_robustness) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL robustness strategy was " - "requested but GLX_ARB_create_context_robustness " - "is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) - strategy = GLX_NO_RESET_NOTIFICATION_ARB; - else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) - strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; - - setGLXattrib(attribs, - index, - GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - strategy); - } - - setGLXattrib(attribs, index, None, None); - - // This is the only place we set an Xlib error handler, and we only do - // it because glXCreateContextAttribsARB generates a BadMatch error if - // the requested OpenGL version is unavailable (instead of a civilized - // response like returning NULL) - XSetErrorHandler(errorHandler); - - window->GLX.context = - window->GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, - *fbconfig, - share, - True, - attribs); - - // We are done, so unset the error handler again (see above) - XSetErrorHandler(NULL); - } - else - { - if (window->GLX.SGIX_fbconfig) - { - window->GLX.context = - window->GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - else - { - window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - } - - XFree(fbconfig); - - if (window->GLX.context == NULL) - { - // TODO: Handle all the various error codes here - - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to create OpenGL context"); - return GL_FALSE; - } - - window->GLX.fbconfigID = fbconfigID; - - return GL_TRUE; -} - -#undef setGLXattrib - - -//======================================================================== -// Initialize GLX-specific extensions -//======================================================================== - -static void initGLXExtensions(_GLFWwindow* window) -{ - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) - { - window->GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); - - if (window->GLX.SwapIntervalEXT) - window->GLX.EXT_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) - { - window->GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); - - if (window->GLX.SwapIntervalSGI) - window->GLX.SGI_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) - { - window->GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) - _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); - window->GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); - window->GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); - window->GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); - - if (window->GLX.GetFBConfigAttribSGIX && - window->GLX.ChooseFBConfigSGIX && - window->GLX.CreateContextWithConfigSGIX && - window->GLX.GetVisualFromFBConfigSGIX) - { - window->GLX.SGIX_fbconfig = GL_TRUE; - } - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) - window->GLX.ARB_multisample = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) - { - window->GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) - _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); - - if (window->GLX.CreateContextAttribsARB) - window->GLX.ARB_create_context = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) - window->GLX.ARB_create_context_robustness = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) - window->GLX.ARB_create_context_profile = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) - window->GLX.EXT_create_context_es2_profile = GL_TRUE; -} - - //======================================================================== // Create the X11 window (and its colormap) //======================================================================== @@ -668,13 +97,14 @@ static GLboolean createWindow(_GLFWwindow* window, XEvent event; unsigned long wamask; XSetWindowAttributes wa; + XVisualInfo* visual = _glfwGetContextVisual(window); // Every window needs a colormap // Create one based on the visual used by the current context window->X11.colormap = XCreateColormap(_glfwLibrary.X11.display, _glfwLibrary.X11.root, - window->GLX.visual->visual, + visual->visual, AllocNone); // Create the actual window @@ -685,7 +115,8 @@ static GLboolean createWindow(_GLFWwindow* window, wa.border_pixel = 0; wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | - ExposureMask | FocusChangeMask | VisibilityChangeMask; + ExposureMask | FocusChangeMask | VisibilityChangeMask | + EnterWindowMask | LeaveWindowMask; if (wndconfig->mode == GLFW_WINDOWED) { @@ -703,9 +134,9 @@ static GLboolean createWindow(_GLFWwindow* window, 0, 0, // Upper left corner of this window on root window->width, window->height, 0, // Border width - window->GLX.visual->depth, // Color depth + visual->depth, // Color depth InputOutput, - window->GLX.visual->visual, + visual->visual, wamask, &wa ); @@ -720,10 +151,7 @@ static GLboolean createWindow(_GLFWwindow* window, } } - // Check whether an EWMH-compliant window manager is running - window->X11.hasEWMH = hasEWMH(window); - - if (window->mode == GLFW_FULLSCREEN && !window->X11.hasEWMH) + if (window->mode == GLFW_FULLSCREEN && !_glfwLibrary.X11.hasEWMH) { // This is the butcher's way of removing window decorations // Setting the override-redirect attribute on a window makes the window @@ -744,9 +172,9 @@ static GLboolean createWindow(_GLFWwindow* window, } // Find or create the protocol atom for window close notifications - window->X11.wmDeleteWindow = XInternAtom(_glfwLibrary.X11.display, - "WM_DELETE_WINDOW", - False); + _glfwLibrary.X11.wmDeleteWindow = XInternAtom(_glfwLibrary.X11.display, + "WM_DELETE_WINDOW", + False); // Declare the WM protocols we support { @@ -755,14 +183,14 @@ static GLboolean createWindow(_GLFWwindow* window, // The WM_DELETE_WINDOW ICCCM protocol // Basic window close notification protocol - if (window->X11.wmDeleteWindow != None) - protocols[count++] = window->X11.wmDeleteWindow; + if (_glfwLibrary.X11.wmDeleteWindow != None) + protocols[count++] = _glfwLibrary.X11.wmDeleteWindow; // The _NET_WM_PING EWMH protocol // Tells the WM to ping our window and flag us as unresponsive if we // don't reply within a few seconds - if (window->X11.wmPing != None) - protocols[count++] = window->X11.wmPing; + if (_glfwLibrary.X11.wmPing != None) + protocols[count++] = _glfwLibrary.X11.wmPing; if (count > 0) { @@ -823,10 +251,10 @@ static GLboolean createWindow(_GLFWwindow* window, //======================================================================== -// Hide mouse cursor +// Hide cursor //======================================================================== -static void hideMouseCursor(_GLFWwindow* window) +static void hideCursor(_GLFWwindow* window) { if (!window->X11.cursorHidden) { @@ -839,12 +267,12 @@ static void hideMouseCursor(_GLFWwindow* window) //======================================================================== -// Capture mouse cursor +// Capture cursor //======================================================================== -static void captureMouseCursor(_GLFWwindow* window) +static void captureCursor(_GLFWwindow* window) { - hideMouseCursor(window); + hideCursor(window); if (!window->X11.cursorGrabbed) { @@ -862,13 +290,13 @@ static void captureMouseCursor(_GLFWwindow* window) //======================================================================== -// Show mouse cursor +// Show cursor //======================================================================== -static void showMouseCursor(_GLFWwindow* window) +static void showCursor(_GLFWwindow* window) { // Un-grab cursor (only in windowed mode: in fullscreen mode we still - // want the mouse grabbed in order to confine the cursor to the window + // want the cursor grabbed in order to confine the cursor to the window // area) if (window->X11.cursorGrabbed) { @@ -907,15 +335,14 @@ static void enterFullscreenMode(_GLFWwindow* window) _glfwLibrary.X11.saver.changed = GL_TRUE; } - _glfwSetVideoMode(_glfwLibrary.X11.screen, - &window->width, &window->height, + _glfwSetVideoMode(&window->width, &window->height, &window->refreshRate); - if (window->X11.hasEWMH && - window->X11.wmState != None && - window->X11.wmStateFullscreen != None) + if (_glfwLibrary.X11.hasEWMH && + _glfwLibrary.X11.wmState != None && + _glfwLibrary.X11.wmStateFullscreen != None) { - if (window->X11.wmActiveWindow != None) + if (_glfwLibrary.X11.wmActiveWindow != None) { // Ask the window manager to raise and focus the GLFW window // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end @@ -927,7 +354,7 @@ static void enterFullscreenMode(_GLFWwindow* window) event.type = ClientMessage; event.xclient.window = window->X11.handle; event.xclient.format = 32; // Data is 32-bit longs - event.xclient.message_type = window->X11.wmActiveWindow; + event.xclient.message_type = _glfwLibrary.X11.wmActiveWindow; event.xclient.data.l[0] = 1; // Sender is a normal application event.xclient.data.l[1] = 0; // We don't really know the timestamp @@ -948,9 +375,9 @@ static void enterFullscreenMode(_GLFWwindow* window) event.type = ClientMessage; event.xclient.window = window->X11.handle; event.xclient.format = 32; // Data is 32-bit longs - event.xclient.message_type = window->X11.wmState; + event.xclient.message_type = _glfwLibrary.X11.wmState; event.xclient.data.l[0] = _NET_WM_STATE_ADD; - event.xclient.data.l[1] = window->X11.wmStateFullscreen; + event.xclient.data.l[1] = _glfwLibrary.X11.wmStateFullscreen; event.xclient.data.l[2] = 0; // No secondary property event.xclient.data.l[3] = 1; // Sender is a normal application @@ -974,7 +401,7 @@ static void enterFullscreenMode(_GLFWwindow* window) } // HACK: Try to get window inside viewport (for virtual displays) by moving - // the mouse cursor to the upper left corner (and then to the center) + // the cursor to the upper left corner (and then to the center) // This hack should be harmless on saner systems as well XWarpPointer(_glfwLibrary.X11.display, None, window->X11.handle, 0,0,0,0, 0,0); XWarpPointer(_glfwLibrary.X11.display, None, window->X11.handle, 0,0,0,0, @@ -988,7 +415,7 @@ static void enterFullscreenMode(_GLFWwindow* window) static void leaveFullscreenMode(_GLFWwindow* window) { - _glfwRestoreVideoMode(_glfwLibrary.X11.screen); + _glfwRestoreVideoMode(); // Did we change the screen saver setting? if (_glfwLibrary.X11.saver.changed) @@ -1003,9 +430,9 @@ static void leaveFullscreenMode(_GLFWwindow* window) _glfwLibrary.X11.saver.changed = GL_FALSE; } - if (window->X11.hasEWMH && - window->X11.wmState != None && - window->X11.wmStateFullscreen != None) + if (_glfwLibrary.X11.hasEWMH && + _glfwLibrary.X11.wmState != None && + _glfwLibrary.X11.wmStateFullscreen != None) { // Ask the window manager to make the GLFW window a normal window // Normal windows usually have frames and other decorations @@ -1016,9 +443,9 @@ static void leaveFullscreenMode(_GLFWwindow* window) event.type = ClientMessage; event.xclient.window = window->X11.handle; event.xclient.format = 32; // Data is 32-bit longs - event.xclient.message_type = window->X11.wmState; + event.xclient.message_type = _glfwLibrary.X11.wmState; event.xclient.data.l[0] = _NET_WM_STATE_REMOVE; - event.xclient.data.l[1] = window->X11.wmStateFullscreen; + event.xclient.data.l[1] = _glfwLibrary.X11.wmStateFullscreen; event.xclient.data.l[2] = 0; // No secondary property event.xclient.data.l[3] = 1; // Sender is a normal application @@ -1143,14 +570,14 @@ static void processSingleEvent(void) // XFree86 3.3.2 and later translates mouse wheel up/down into // mouse button 4 & 5 presses else if (event.xbutton.button == Button4) - _glfwInputScroll(window, 0, 1); + _glfwInputScroll(window, 0.0, 1.0); else if (event.xbutton.button == Button5) - _glfwInputScroll(window, 0, -1); + _glfwInputScroll(window, 0.0, -1.0); else if (event.xbutton.button == Button6) - _glfwInputScroll(window, -1, 0); + _glfwInputScroll(window, -1.0, 0.0); else if (event.xbutton.button == Button7) - _glfwInputScroll(window, 1, 0); + _glfwInputScroll(window, 1.0, 0.0); break; } @@ -1186,9 +613,43 @@ static void processSingleEvent(void) break; } + case EnterNotify: + { + // The cursor entered the window + window = findWindow(event.xcrossing.window); + if (window == NULL) + { + fprintf(stderr, "Cannot find GLFW window structure for EnterNotify event\n"); + return; + } + + if (window->cursorMode == GLFW_CURSOR_HIDDEN) + hideCursor(window); + + _glfwInputCursorEnter(window, GL_TRUE); + break; + } + + case LeaveNotify: + { + // The cursor left the window + window = findWindow(event.xcrossing.window); + if (window == NULL) + { + fprintf(stderr, "Cannot find GLFW window structure for LeaveNotify event\n"); + return; + } + + if (window->cursorMode == GLFW_CURSOR_HIDDEN) + showCursor(window); + + _glfwInputCursorEnter(window, GL_FALSE); + break; + } + case MotionNotify: { - // The mouse cursor was moved + // The cursor was moved window = findWindow(event.xmotion.window); if (window == NULL) { @@ -1199,7 +660,7 @@ static void processSingleEvent(void) if (event.xmotion.x != window->X11.cursorPosX || event.xmotion.y != window->X11.cursorPosY) { - // The mouse cursor was moved and we didn't do it + // The cursor was moved and we didn't do it int x, y; if (window->cursorMode == GLFW_CURSOR_CAPTURED) @@ -1257,15 +718,15 @@ static void processSingleEvent(void) return; } - if ((Atom) event.xclient.data.l[0] == window->X11.wmDeleteWindow) + if ((Atom) event.xclient.data.l[0] == _glfwLibrary.X11.wmDeleteWindow) { // The window manager was asked to close the window, for example by // the user pressing a 'close' window decoration button window->closeRequested = GL_TRUE; } - else if (window->X11.wmPing != None && - (Atom) event.xclient.data.l[0] == window->X11.wmPing) + else if (_glfwLibrary.X11.wmPing != None && + (Atom) event.xclient.data.l[0] == _glfwLibrary.X11.wmPing) { // The window manager is pinging us to make sure we are still // responding to events @@ -1322,7 +783,7 @@ static void processSingleEvent(void) _glfwInputWindowFocus(window, GL_TRUE); if (window->cursorMode == GLFW_CURSOR_CAPTURED) - captureMouseCursor(window); + captureCursor(window); break; } @@ -1340,7 +801,7 @@ static void processSingleEvent(void) _glfwInputWindowFocus(window, GL_FALSE); if (window->cursorMode == GLFW_CURSOR_CAPTURED) - showMouseCursor(window); + showCursor(window); break; } @@ -1359,7 +820,52 @@ static void processSingleEvent(void) break; } - // Was the window destroyed? + case SelectionClear: + { + // The ownership of the selection was lost + + free(_glfwLibrary.X11.selection.string); + _glfwLibrary.X11.selection.string = NULL; + break; + } + + case SelectionNotify: + { + // The selection conversion status is available + + XSelectionEvent* request = &event.xselection; + + if (_glfwReadSelection(request)) + _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_SUCCEEDED; + else + _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_FAILED; + + break; + } + + case SelectionRequest: + { + // The contents of the selection was requested + + XSelectionRequestEvent* request = &event.xselectionrequest; + + XEvent response; + memset(&response, 0, sizeof(response)); + + response.xselection.property = _glfwWriteSelection(request); + response.xselection.type = SelectionNotify; + response.xselection.display = request->display; + response.xselection.requestor = request->requestor; + response.xselection.selection = request->selection; + response.xselection.target = request->target; + response.xselection.time = request->time; + + XSendEvent(_glfwLibrary.X11.display, + request->requestor, + False, 0, &response); + break; + } + case DestroyNotify: return; @@ -1383,6 +889,23 @@ static void processSingleEvent(void) } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Processes all pending events +//======================================================================== + +void _glfwProcessPendingEvents(void) +{ + int i, count = XPending(_glfwLibrary.X11.display); + + for (i = 0; i < count; i++) + processSingleEvent(); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -1396,35 +919,10 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig) { - _GLFWfbconfig closest; - window->refreshRate = wndconfig->refreshRate; window->resizable = wndconfig->resizable; - initGLXExtensions(window); - - // Choose the best available fbconfig - { - unsigned int fbcount; - _GLFWfbconfig* fbconfigs; - const _GLFWfbconfig* result; - - fbconfigs = getFBConfigs(window, &fbcount); - if (!fbconfigs) - return GL_FALSE; - - result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); - if (!result) - { - _glfwFree(fbconfigs); - return GL_FALSE; - } - - closest = *result; - _glfwFree(fbconfigs); - } - - if (!createContext(window, wndconfig, (GLXFBConfigID) closest.platformID)) + if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; if (!createWindow(window, wndconfig)) @@ -1446,7 +944,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, } // Process the window map event and any other that may have arrived - _glfwPlatformPollEvents(); + _glfwProcessPendingEvents(); // Retrieve and set initial cursor position { @@ -1481,19 +979,7 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) if (window->mode == GLFW_FULLSCREEN) leaveFullscreenMode(window); - if (window->GLX.context) - { - // Release and destroy the context - glXMakeCurrent(_glfwLibrary.X11.display, None, NULL); - glXDestroyContext(_glfwLibrary.X11.display, window->GLX.context); - window->GLX.context = NULL; - } - - if (window->GLX.visual) - { - XFree(window->GLX.visual); - window->GLX.visual = NULL; - } + _glfwDestroyContext(window); if (window->X11.handle) { @@ -1534,18 +1020,18 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) NULL, NULL, NULL); #endif - if (window->X11.wmName != None) + if (_glfwLibrary.X11.wmName != None) { XChangeProperty(_glfwLibrary.X11.display, window->X11.handle, - window->X11.wmName, type, 8, + _glfwLibrary.X11.wmName, type, 8, PropModeReplace, (unsigned char*) title, strlen(title)); } - if (window->X11.wmIconName != None) + if (_glfwLibrary.X11.wmIconName != None) { XChangeProperty(_glfwLibrary.X11.display, window->X11.handle, - window->X11.wmIconName, type, 8, + _glfwLibrary.X11.wmIconName, type, 8, PropModeReplace, (unsigned char*) title, strlen(title)); } @@ -1566,8 +1052,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) if (window->mode == GLFW_FULLSCREEN) { // Get the closest matching video mode for the specified window size - mode = _glfwGetClosestVideoMode(_glfwLibrary.X11.screen, - &width, &height, &rate); + mode = _glfwGetClosestVideoMode(&width, &height, &rate); } if (!window->resizable) @@ -1594,7 +1079,7 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) if (window->mode == GLFW_FULLSCREEN) { // Change video mode, keeping current refresh rate - _glfwSetVideoModeMODE(_glfwLibrary.X11.screen, mode, window->refreshRate); + _glfwSetVideoModeMODE(mode, window->refreshRate); } // Set window size (if not already changed) @@ -1655,8 +1140,6 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformRefreshWindowParams(void) { - int dummy; - GLXFBConfig* fbconfig; #if defined(_GLFW_HAS_XRANDR) XRRScreenConfiguration* sc; #endif /*_GLFW_HAS_XRANDR*/ @@ -1667,58 +1150,6 @@ void _glfwPlatformRefreshWindowParams(void) #endif /*_GLFW_HAS_XF86VIDMODE*/ _GLFWwindow* window = _glfwLibrary.currentWindow; - int attribs[] = { GLX_FBCONFIG_ID, window->GLX.fbconfigID, None }; - - if (window->GLX.SGIX_fbconfig) - { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - else - { - fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - - if (fbconfig == NULL) - { - // This should never ever happen - // TODO: Flag this as an error and propagate up - fprintf(stderr, "Cannot find known GLXFBConfig by ID. " - "This cannot happen. Have a nice day.\n"); - abort(); - } - - // There is no clear definition of an "accelerated" context on X11/GLX, and - // true sounds better than false, so we hardcode true here - window->accelerated = GL_TRUE; - - window->redBits = getFBConfigAttrib(window, *fbconfig, GLX_RED_SIZE); - window->greenBits = getFBConfigAttrib(window, *fbconfig, GLX_GREEN_SIZE); - window->blueBits = getFBConfigAttrib(window, *fbconfig, GLX_BLUE_SIZE); - - window->alphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ALPHA_SIZE); - window->depthBits = getFBConfigAttrib(window, *fbconfig, GLX_DEPTH_SIZE); - window->stencilBits = getFBConfigAttrib(window, *fbconfig, GLX_STENCIL_SIZE); - - window->accumRedBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_RED_SIZE); - window->accumGreenBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_GREEN_SIZE); - window->accumBlueBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_BLUE_SIZE); - window->accumAlphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_ALPHA_SIZE); - - window->auxBuffers = getFBConfigAttrib(window, *fbconfig, GLX_AUX_BUFFERS); - window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; - - // Get FSAA buffer sample count - if (window->GLX.ARB_multisample) - window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); - else - window->samples = 0; - // Retrieve refresh rate if possible if (_glfwLibrary.X11.RandR.available) { @@ -1745,8 +1176,6 @@ void _glfwPlatformRefreshWindowParams(void) // Zero means unknown according to the GLFW spec window->refreshRate = 0; } - - XFree(fbconfig); } @@ -1769,9 +1198,9 @@ void _glfwPlatformPollEvents(void) if (window->cursorMode == GLFW_CURSOR_CAPTURED && !window->X11.cursorCentered) { - _glfwPlatformSetMouseCursorPos(window, - window->width / 2, - window->height / 2); + _glfwPlatformSetCursorPos(window, + window->width / 2, + window->height / 2); window->X11.cursorCentered = GL_TRUE; // NOTE: This is a temporary fix. It works as long as you use @@ -1800,10 +1229,10 @@ void _glfwPlatformWaitEvents(void) //======================================================================== -// Set physical mouse cursor position +// Set physical cursor position //======================================================================== -void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y) +void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y) { // Store the new position so we can recognise it later window->X11.cursorPosX = x; @@ -1814,7 +1243,7 @@ void _glfwPlatformSetMouseCursorPos(_GLFWwindow* window, int x, int y) //======================================================================== -// Set physical mouse cursor mode +// Set physical cursor mode //======================================================================== void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) @@ -1822,13 +1251,13 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) switch (mode) { case GLFW_CURSOR_NORMAL: - showMouseCursor(window); + showCursor(window); break; case GLFW_CURSOR_HIDDEN: - hideMouseCursor(window); + hideCursor(window); break; case GLFW_CURSOR_CAPTURED: - captureMouseCursor(window); + captureCursor(window); break; } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d7ac0954..55862fac 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,69 +1,58 @@ -set(STATIC_DEPS libglfwStatic ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY}) -set(SHARED_DEPS libglfwShared ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY}) +link_libraries(glfw ${OPENGL_glu_LIBRARY}) + +if (BUILD_SHARED_LIBS) + add_definitions(-DGLFW_DLL) + link_libraries(${OPENGL_gl_LIBRARY} ${MATH_LIBRARY}) +else() + link_libraries(${glfw_LIBRARIES}) +endif() include_directories(${GLFW_SOURCE_DIR}/include ${GLFW_SOURCE_DIR}/support ${OPENGL_INCLUDE_DIR}) +add_executable(clipboard clipboard.c getopt.c) add_executable(defaults defaults.c) -target_link_libraries(defaults ${STATIC_DEPS}) - -add_executable(dynamic dynamic.c) -target_link_libraries(dynamic ${SHARED_DEPS}) - add_executable(events events.c) -target_link_libraries(events ${STATIC_DEPS}) - add_executable(fsaa fsaa.c getopt.c) -target_link_libraries(fsaa ${STATIC_DEPS}) - add_executable(fsfocus fsfocus.c) -target_link_libraries(fsfocus ${STATIC_DEPS}) - add_executable(gamma gamma.c getopt.c) -target_link_libraries(gamma ${STATIC_DEPS}) - add_executable(glfwinfo glfwinfo.c getopt.c) -target_link_libraries(glfwinfo ${STATIC_DEPS}) - add_executable(iconify iconify.c getopt.c) -target_link_libraries(iconify ${STATIC_DEPS}) - add_executable(joysticks joysticks.c) -target_link_libraries(joysticks ${STATIC_DEPS}) - -add_executable(listmodes listmodes.c) -target_link_libraries(listmodes ${STATIC_DEPS}) - +add_executable(modes modes.c getopt.c) add_executable(peter peter.c) -target_link_libraries(peter ${STATIC_DEPS}) - add_executable(reopen reopen.c) -target_link_libraries(reopen ${STATIC_DEPS}) add_executable(accuracy WIN32 MACOSX_BUNDLE accuracy.c) -target_link_libraries(accuracy ${STATIC_DEPS}) +set_target_properties(accuracy PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Accuracy") add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c) -target_link_libraries(sharing ${STATIC_DEPS}) +set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing") add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c) -target_link_libraries(tearing ${STATIC_DEPS}) +set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing") add_executable(title WIN32 MACOSX_BUNDLE title.c) -target_link_libraries(title ${STATIC_DEPS}) +set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title") add_executable(windows WIN32 MACOSX_BUNDLE windows.c) -target_link_libraries(windows ${STATIC_DEPS}) +set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows") set(WINDOWS_BINARIES accuracy sharing tearing title windows) -set(CONSOLE_BINARIES defaults events fsaa fsfocus gamma glfwinfo iconify - joysticks listmodes peter reopen) +set(CONSOLE_BINARIES clipboard defaults events fsaa fsfocus gamma glfwinfo + iconify joysticks modes peter reopen) -if(MSVC) - # Tell MSVC to use main instead of WinMain for Windows subsystem executables - set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES - LINK_FLAGS "/ENTRY:mainCRTStartup") -endif(MSVC) +if (MSVC) + # Tell MSVC to use main instead of WinMain for Windows subsystem executables + set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES + LINK_FLAGS "/ENTRY:mainCRTStartup") +endif() + +if (APPLE) + set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES + MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} + MACOSX_BUNDLE_LONG_VERSION_STRING ${GLFW_VERSION_FULL}) +endif() diff --git a/tests/accuracy.c b/tests/accuracy.c index 38f1374e..cfb70271 100644 --- a/tests/accuracy.c +++ b/tests/accuracy.c @@ -29,6 +29,7 @@ // //======================================================================== +#define GLFW_INCLUDE_GLU #include #include @@ -49,7 +50,7 @@ static void window_size_callback(GLFWwindow window, int width, int height) gluOrtho2D(0.f, window_width, 0.f, window_height); } -static void mouse_position_callback(GLFWwindow window, int x, int y) +static void cursor_position_callback(GLFWwindow window, int x, int y) { cursor_x = x; cursor_y = y; @@ -59,7 +60,7 @@ int main(void) { GLFWwindow window; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); @@ -74,7 +75,7 @@ int main(void) exit(EXIT_FAILURE); } - glfwSetMousePosCallback(mouse_position_callback); + glfwSetCursorPosCallback(cursor_position_callback); glfwSetWindowSizeCallback(window_size_callback); glfwSwapInterval(1); diff --git a/tests/clipboard.c b/tests/clipboard.c new file mode 100644 index 00000000..3b732290 --- /dev/null +++ b/tests/clipboard.c @@ -0,0 +1,153 @@ +//======================================================================== +// Clipboard test program +// Copyright (c) Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// +// This program is used to test the clipboard functionality. +// +//======================================================================== + +#include + +#include +#include + +#include "getopt.h" + +static void usage(void) +{ + printf("Usage: clipboard [-h]\n"); +} + +static GLboolean control_is_down(GLFWwindow window) +{ + return glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) || + glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL); +} + +static void key_callback(GLFWwindow window, int key, int action) +{ + if (action != GLFW_PRESS) + return; + + switch (key) + { + case GLFW_KEY_ESCAPE: + glfwCloseWindow(window); + break; + + case GLFW_KEY_V: + if (control_is_down(window)) + { + const char* string; + + string = glfwGetClipboardString(window); + if (string) + printf("Clipboard contains \"%s\"\n", string); + else + printf("Clipboard does not contain a string\n"); + } + break; + + case GLFW_KEY_C: + if (control_is_down(window)) + { + const char* string = "Hello GLFW World!"; + glfwSetClipboardString(window, string); + printf("Setting clipboard to \"%s\"\n", string); + } + break; + } +} + +static void size_callback(GLFWwindow window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error in %s\n", description); +} + +int main(int argc, char** argv) +{ + int ch; + GLFWwindow window; + + while ((ch = getopt(argc, argv, "h")) != -1) + { + switch (ch) + { + case 'h': + usage(); + exit(EXIT_SUCCESS); + + default: + usage(); + exit(EXIT_FAILURE); + } + } + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + { + fprintf(stderr, "Failed to initialize GLFW\n"); + exit(EXIT_FAILURE); + } + + window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Clipboard Test", NULL); + if (!window) + { + glfwTerminate(); + + fprintf(stderr, "Failed to open GLFW window\n"); + exit(EXIT_FAILURE); + } + + glfwSwapInterval(1); + glfwSetKeyCallback(key_callback); + glfwSetWindowSizeCallback(size_callback); + + glMatrixMode(GL_PROJECTION); + glOrtho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f); + glMatrixMode(GL_MODELVIEW); + + glClearColor(0.5f, 0.5f, 0.5f, 0); + + while (glfwIsWindow(window)) + { + glClear(GL_COLOR_BUFFER_BIT); + + glColor3f(0.8f, 0.2f, 0.4f); + glRectf(-0.5f, -0.5f, 0.5f, 0.5f); + + glfwSwapBuffers(); + glfwWaitEvents(); + } + + glfwTerminate(); + exit(EXIT_SUCCESS); +} + diff --git a/tests/defaults.c b/tests/defaults.c index b50abaaa..d7c5a02c 100644 --- a/tests/defaults.c +++ b/tests/defaults.c @@ -69,7 +69,7 @@ int main(void) int i, width, height; GLFWwindow window; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); diff --git a/tests/dynamic.c b/tests/dynamic.c deleted file mode 100644 index b4257271..00000000 --- a/tests/dynamic.c +++ /dev/null @@ -1,91 +0,0 @@ -//======================================================================== -// Dynamic linking test -// Copyright (c) Camilla Berglund -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== -// -// This test came about as the result of bug #3060461 -// -//======================================================================== - -#define GLFW_DLL -#include - -#include -#include - -static void window_size_callback(GLFWwindow window, int width, int height) -{ - glViewport(0, 0, width, height); -} - -int main(void) -{ - GLFWwindow window; - int major, minor, rev; - glfwGetVersion(&major, &minor, &rev); - - printf("GLFW header version: %i.%i.%i\n", - GLFW_VERSION_MAJOR, - GLFW_VERSION_MINOR, - GLFW_VERSION_REVISION); - printf("GLFW library version: %i.%i.%i\n", major, minor, rev); - printf("GLFW library version string: %s\n", glfwGetVersionString()); - - if (major != GLFW_VERSION_MAJOR || - minor != GLFW_VERSION_MINOR || - rev != GLFW_VERSION_REVISION) - { - fprintf(stderr, "GLFW library version mismatch\n"); - exit(EXIT_FAILURE); - } - - if (!glfwInit(NULL)) - { - fprintf(stderr, "Failed to initialize GLFW\n"); - exit(EXIT_FAILURE); - } - - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Dynamic Linking Test", NULL); - if (!window) - { - glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window\n"); - exit(EXIT_FAILURE); - } - - glfwSetWindowSizeCallback(window_size_callback); - glfwSwapInterval(1); - - while (glfwIsWindow(window)) - { - glClear(GL_COLOR_BUFFER_BIT); - - glfwSwapBuffers(); - glfwPollEvents(); - } - - glfwTerminate(); - exit(EXIT_SUCCESS); -} - diff --git a/tests/events.c b/tests/events.c index a5a7bfa6..4e85c086 100644 --- a/tests/events.c +++ b/tests/events.c @@ -40,8 +40,9 @@ #include #include -static GLboolean keyrepeat = 0; -static GLboolean systemkeys = 1; +static GLboolean keyrepeat = GL_FALSE; +static GLboolean systemkeys = GL_TRUE; +static GLboolean closeable = GL_TRUE; static unsigned int counter = 0; static const char* get_key_name(int key) @@ -243,7 +244,7 @@ static void window_size_callback(GLFWwindow window, int width, int height) static int window_close_callback(GLFWwindow window) { printf("%08x at %0.3f: Window close\n", counter++, glfwGetTime()); - return 1; + return closeable; } static void window_refresh_callback(GLFWwindow window) @@ -282,14 +283,22 @@ static void mouse_button_callback(GLFWwindow window, int button, int action) printf(" was %s\n", get_action_name(action)); } -static void mouse_position_callback(GLFWwindow window, int x, int y) +static void cursor_position_callback(GLFWwindow window, int x, int y) { - printf("%08x at %0.3f: Mouse position: %i %i\n", counter++, glfwGetTime(), x, y); + printf("%08x at %0.3f: Cursor position: %i %i\n", counter++, glfwGetTime(), x, y); } -static void scroll_callback(GLFWwindow window, int x, int y) +static void cursor_enter_callback(GLFWwindow window, int entered) { - printf("%08x at %0.3f: Scroll: %i %i\n", counter++, glfwGetTime(), x, y); + printf("%08x at %0.3f: Cursor %s window\n", + counter++, + glfwGetTime(), + entered ? "entered" : "left"); +} + +static void scroll_callback(GLFWwindow window, double x, double y) +{ + printf("%08x at %0.3f: Scroll: %0.3f %0.3f\n", counter++, glfwGetTime(), x, y); } static void key_callback(GLFWwindow window, int key, int action) @@ -325,6 +334,14 @@ static void key_callback(GLFWwindow window, int key, int action) printf("(( system keys %s ))\n", systemkeys ? "enabled" : "disabled"); break; } + + case GLFW_KEY_C: + { + closeable = !closeable; + + printf("(( closing %s ))\n", closeable ? "enabled" : "disabled"); + break; + } } } @@ -353,7 +370,7 @@ int main(void) setlocale(LC_ALL, ""); - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); @@ -367,7 +384,8 @@ int main(void) glfwSetWindowFocusCallback(window_focus_callback); glfwSetWindowIconifyCallback(window_iconify_callback); glfwSetMouseButtonCallback(mouse_button_callback); - glfwSetMousePosCallback(mouse_position_callback); + glfwSetCursorPosCallback(cursor_position_callback); + glfwSetCursorEnterCallback(cursor_enter_callback); glfwSetScrollCallback(scroll_callback); glfwSetKeyCallback(key_callback); glfwSetCharCallback(char_callback); diff --git a/tests/fsaa.c b/tests/fsaa.c index e2fcf387..9c45ddcc 100644 --- a/tests/fsaa.c +++ b/tests/fsaa.c @@ -29,6 +29,7 @@ // //======================================================================== +#define GLFW_INCLUDE_GLU #include #include @@ -81,7 +82,7 @@ int main(int argc, char** argv) } } - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); diff --git a/tests/fsfocus.c b/tests/fsfocus.c index bf634d54..951409a6 100644 --- a/tests/fsfocus.c +++ b/tests/fsfocus.c @@ -75,7 +75,7 @@ int main(void) { GLFWwindow window; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); diff --git a/tests/gamma.c b/tests/gamma.c index dd10784e..b8ec6c45 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -35,11 +35,20 @@ #include "getopt.h" +#define STEP_SIZE 0.1f + static GLfloat gamma = 1.0f; static void usage(void) { - printf("Usage: gammatest [-h] [-f]\n"); + printf("Usage: gamma [-h] [-f]\n"); +} + +static void set_gamma(float value) +{ + gamma = value; + printf("Gamma: %f\n", gamma); + glfwSetGamma(gamma); } static void key_callback(GLFWwindow window, int key, int action) @@ -50,20 +59,26 @@ static void key_callback(GLFWwindow window, int key, int action) switch (key) { case GLFW_KEY_ESCAPE: + { glfwCloseWindow(window); break; + } + case GLFW_KEY_KP_ADD: case GLFW_KEY_Q: - gamma += 0.1f; - printf("Gamma: %f\n", gamma); - glfwSetGamma(gamma); + { + set_gamma(gamma + STEP_SIZE); break; + } + case GLFW_KEY_KP_SUBTRACT: case GLFW_KEY_W: - gamma -= 0.1f; - printf("Gamma: %f\n", gamma); - glfwSetGamma(gamma); + { + if (gamma - STEP_SIZE > 0.f) + set_gamma(gamma - STEP_SIZE); + break; + } } } @@ -96,7 +111,7 @@ int main(int argc, char** argv) } } - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); @@ -124,7 +139,7 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } - printf("Gamma: %f\n", gamma); + set_gamma(1.f); glfwSwapInterval(1); glfwSetKeyCallback(key_callback); diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index efaff6b9..45cb8616 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -51,7 +51,7 @@ static void usage(void) { - printf("Usage: version [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\n"); + printf("Usage: glfwinfo [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\n"); printf("available profiles: " PROFILE_NAME_CORE " " PROFILE_NAME_COMPAT " " PROFILE_NAME_ES2 "\n"); printf("available strategies: " STRATEGY_NAME_NONE " " STRATEGY_NAME_LOSE "\n"); } @@ -183,7 +183,7 @@ int main(int argc, char** argv) glfwSetErrorCallback(error_callback); - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); @@ -263,7 +263,7 @@ int main(int argc, char** argv) if (major > 3 || (major == 3 && minor >= 2)) { glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); - printf("OpenGL profile mask: 0x%08x (%s)\n", mask, get_profile_name(mask)); + printf("OpenGL profile mask: %s (0x%08x)\n", get_profile_name(mask), mask); printf("OpenGL profile parsed by GLFW: %s\n", get_glfw_profile_name(glfwGetWindowParam(window, GLFW_OPENGL_PROFILE))); diff --git a/tests/iconify.c b/tests/iconify.c index 1ee235f1..dbc4d9cf 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -62,6 +62,8 @@ static void key_callback(GLFWwindow window, int key, int action) static void size_callback(GLFWwindow window, int width, int height) { + printf("%0.2f Size %ix%i\n", glfwGetTime(), width, height); + glViewport(0, 0, width, height); } @@ -90,7 +92,7 @@ int main(int argc, char** argv) } } - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); diff --git a/tests/joysticks.c b/tests/joysticks.c index d777d431..2f208d2b 100644 --- a/tests/joysticks.c +++ b/tests/joysticks.c @@ -1,142 +1,216 @@ -/*======================================================================== - * This is a small test application for GLFW. - * joystick input test. - *========================================================================*/ +//======================================================================== +// Joystick input test +// Copyright (c) Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// +// This test displays the state of every button and axis of every connected +// joystick and/or gamepad +// +//======================================================================== #include #include +#include #include -#include -#define MAX_AXES 10 -#define MAX_BUTTONS 30 - -struct JoystickState +typedef struct Joystick { - int present; - int num_axes; - int num_buttons; - float axes[MAX_AXES]; - unsigned char buttons[MAX_BUTTONS]; -}; + GLboolean present; + float* axes; + unsigned char* buttons; + int axis_count; + int button_count; +} Joystick; -static struct JoystickState states[GLFW_JOYSTICK_LAST + 1]; +static Joystick joysticks[GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1 + 1]; -int running; -int keyrepeat = 0; -int systemkeys = 1; +static int joystick_count = 0; - -/*======================================================================== - * Retrieve joystick states - *========================================================================*/ -static void updateJoysticksState(void) +static void window_size_callback(GLFWwindow window, int width, int height) { - int joy; + glViewport(0, 0, width, height); +} - for (joy = GLFW_JOYSTICK_1; joy < GLFW_JOYSTICK_LAST + 1; joy++) +static void draw_joystick(Joystick* j, int x, int y, int width, int height) +{ + int i; + int axis_width, axis_height; + int button_width, button_height; + + axis_width = width / j->axis_count; + axis_height = 3 * height / 4; + + button_width = width / j->button_count; + button_height = height / 4; + + for (i = 0; i < j->axis_count; i++) { - printf("Updating information for joystick %d\n", joy); - states[joy].present = glfwGetJoystickParam(joy, GLFW_PRESENT); - if (states[joy].present == GL_TRUE) + float value = j->axes[i] / 2.f + 0.5f; + + glColor3f(0.3f, 0.3f, 0.3f); + glRecti(x + i * axis_width, + y, + x + (i + 1) * axis_width, + y + axis_height); + + glColor3f(1.f, 1.f, 1.f); + glRecti(x + i * axis_width, + y + (int) (value * (axis_height - 5)), + x + (i + 1) * axis_width, + y + 5 + (int) (value * (axis_height - 5))); + } + + for (i = 0; i < j->button_count; i++) + { + if (j->buttons[i]) + glColor3f(1.f, 1.f, 1.f); + else + glColor3f(0.3f, 0.3f, 0.3f); + + glRecti(x + i * button_width, + y + axis_height, + x + (i + 1) * button_width, + y + axis_height + button_height); + } +} + +static void draw_joysticks(void) +{ + int i, width, height; + + glfwGetWindowSize(glfwGetCurrentContext(), &width, &height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.f, width, height, 0.f, 1.f, -1.f); + glMatrixMode(GL_MODELVIEW); + + for (i = 0; i < sizeof(joysticks) / sizeof(Joystick); i++) + { + Joystick* j = joysticks + i; + + if (j->present) { - states[joy].num_axes = glfwGetJoystickPos(joy, states[joy].axes, MAX_AXES); - states[joy].num_buttons = glfwGetJoystickButtons(joy, states[joy].buttons, MAX_BUTTONS); + draw_joystick(j, + 0, i * height / joystick_count, + width, height / joystick_count); } } } -/*======================================================================== - * Print out the state of all joysticks on the standard output - *========================================================================*/ -static void displayJoysticksState(void) +static void refresh_joysticks(void) { - int joy; int i; - for (joy = GLFW_JOYSTICK_1; joy < GLFW_JOYSTICK_LAST + 1; joy++) + for (i = 0; i < sizeof(joysticks) / sizeof(Joystick); i++) { - printf("Joystick %d: %s\n", joy, (states[joy].present == GL_TRUE ? "present" : "not connected")); + Joystick* j = joysticks + i; - if (states[joy].present == GL_TRUE) + if (glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_PRESENT)) { - if (states[joy].num_axes > 0) + int axis_count, button_count; + + axis_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_AXES); + if (axis_count != j->axis_count) { - printf(" axes: %.3f", states[joy].axes[0]); - for (i = 1; i < states[joy].num_axes; i++) - printf(", %.3f", states[joy].axes[i]); - - printf("\n"); + j->axis_count = axis_count; + j->axes = realloc(j->axes, j->axis_count * sizeof(float)); } - else - printf(" axes: none\n"); - if (states[joy].num_buttons > 0) + glfwGetJoystickPos(GLFW_JOYSTICK_1 + i, j->axes, j->axis_count); + + button_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_BUTTONS); + if (button_count != j->button_count) { - printf(" buttons: 00 => %c", ((states[joy].buttons[0] == GLFW_PRESS) ? 'P' : 'R')); - - for (i = 1; i < states[joy].num_buttons; i++) - printf(", %02d => %c", i, ((states[joy].buttons[i] == GLFW_PRESS) ? 'P' : 'R')); - - printf("\n"); + j->button_count = button_count; + j->buttons = realloc(j->buttons, j->button_count); + } + + glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, j->buttons, j->button_count); + + if (!j->present) + { + printf("Found joystick %i with %i axes, %i buttons\n", + i + 1, j->axis_count, j->button_count); + + joystick_count++; + } + + j->present = GL_TRUE; + } + else + { + if (j->present) + { + free(j->axes); + free(j->buttons); + memset(j, 0, sizeof(Joystick)); + + printf("Lost joystick %i\n", i + 1); + + joystick_count--; } - else - printf(" buttons: none\n"); } } } int main(void) { - double start; - double t; - double update; + GLFWwindow window; - /* Initialise GLFW */ - if (!glfwInit(NULL)) + memset(joysticks, 0, sizeof(joysticks)); + + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } - printf("The program will work for 20 seconds and display every seconds the state of the joysticks\n"); - printf("Your computer is going to be very slow as the program is doing an active loop .....\n"); - - start = glfwGetTime(); - update = start; - - /* print the initial state of all joysticks */ - updateJoysticksState(); - printf("\n"); - displayJoysticksState(); - - running = GL_TRUE; - - /* Main loop */ - while (running) + window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Joystick Test", NULL); + if (!window) { - /* Get time */ - t = glfwGetTime(); + glfwTerminate(); - /* Display the state of all connected joysticks every secons */ - if ((t - update) > 1.0) - { - update = t; - printf("\n"); - updateJoysticksState(); - printf("\n"); - displayJoysticksState(); - } - - /* Check if the window was closed */ - if ((t - start) > 20.0) - running = GL_FALSE; + fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); + exit(EXIT_FAILURE); } - /* Close OpenGL window and terminate GLFW */ - glfwTerminate(); + glfwSetWindowSizeCallback(window_size_callback); + glfwSwapInterval(1); - return 0; + while (glfwIsWindow(window)) + { + glClear(GL_COLOR_BUFFER_BIT); + + refresh_joysticks(); + draw_joysticks(); + + glfwSwapBuffers(); + glfwPollEvents(); + } + + glfwTerminate(); + exit(EXIT_SUCCESS); } diff --git a/tests/listmodes.c b/tests/listmodes.c deleted file mode 100644 index 5f2d53a6..00000000 --- a/tests/listmodes.c +++ /dev/null @@ -1,62 +0,0 @@ -//======================================================================== -// This is a small test application for GLFW. -// The program lists all available fullscreen video modes. -//======================================================================== - -#include - -#include -#include - -static void print_mode(GLFWvidmode* mode) -{ - printf("%i x %i x %i (%i %i %i)\n", - mode->width, mode->height, - mode->redBits + mode->greenBits + mode->blueBits, - mode->redBits, mode->greenBits, mode->blueBits); -} - -int main(void) -{ - GLFWmonitor monitor; - GLFWvidmode dtmode, modes[400]; - int modecount, i; - - if (!glfwInit(NULL)) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); - exit(EXIT_FAILURE); - } - - // Show desktop video mode - glfwGetDesktopMode(&dtmode); - printf("Desktop mode: "); - print_mode(&dtmode); - - monitor = NULL; - - while ((monitor = glfwGetNextMonitor(monitor))) - { - printf("Monitor name: %s\n" - "Physical dimensions: %dmm x %dmm\n" - "Logical position: (%d,%d)\n", - glfwGetMonitorString(monitor, GLFW_MONITOR_NAME), - glfwGetMonitorParam(monitor, GLFW_MONITOR_PHYSICAL_WIDTH), - glfwGetMonitorParam(monitor, GLFW_MONITOR_PHYSICAL_HEIGHT), - glfwGetMonitorParam(monitor, GLFW_MONITOR_SCREEN_POS_X), - glfwGetMonitorParam(monitor, GLFW_MONITOR_SCREEN_POS_Y)); - - // List available video modes - modecount = glfwGetVideoModes(monitor, modes, sizeof(modes) / sizeof(GLFWvidmode)); - printf("Available modes:\n"); - - for (i = 0; i < modecount; i++) - { - printf("%3i: ", i); - print_mode(modes + i); - } - } - - exit(EXIT_SUCCESS); -} - diff --git a/tests/modes.c b/tests/modes.c new file mode 100644 index 00000000..d7ae0bfb --- /dev/null +++ b/tests/modes.c @@ -0,0 +1,257 @@ +//======================================================================== +// Video mode test +// Copyright (c) Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== +// +// This test enumerates or verifies video modes +// +//======================================================================== + +#include + +#include +#include +#include + +#include "getopt.h" + +static GLFWwindow window = NULL; + +enum Mode +{ + LIST_MODE, + TEST_MODE +}; + +static void usage(void) +{ + printf("Usage: modes [-t]\n"); + printf(" modes -h\n"); +} + +static const char* format_mode(GLFWvidmode* mode) +{ + static char buffer[512]; + + snprintf(buffer, sizeof(buffer), + "%i x %i x %i (%i %i %i)", + mode->width, mode->height, + mode->redBits + mode->greenBits + mode->blueBits, + mode->redBits, mode->greenBits, mode->blueBits); + + buffer[sizeof(buffer) - 1] = '\0'; + return buffer; +} + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + +static void window_size_callback(GLFWwindow window, int width, int height) +{ + printf("Window resized to %ix%i\n", width, height); + + glViewport(0, 0, width, height); +} + +static int window_close_callback(GLFWwindow dummy) +{ + window = NULL; + return GL_TRUE; +} + +static void key_callback(GLFWwindow dummy, int key, int action) +{ + if (key == GLFW_KEY_ESCAPE) + { + glfwCloseWindow(window); + window = NULL; + } +} + +static GLFWvidmode* get_video_modes(GLFWmonitor monitor, size_t* found) +{ + size_t count = 0; + GLFWvidmode* modes = NULL; + + for (;;) + { + count += 256; + modes = realloc(modes, sizeof(GLFWvidmode) * count); + + *found = glfwGetVideoModes(monitor, modes, count); + if (*found < count) + break; + } + + return modes; +} + +static void list_modes(GLFWmonitor monitor) +{ + size_t count, i; + GLFWvidmode desktop_mode; + + glfwGetDesktopMode(&desktop_mode); + printf("Desktop mode: %s\n", format_mode(&desktop_mode)); + + GLFWvidmode* modes = get_video_modes(monitor, &count); + + printf("Monitor %s:\n", glfwGetMonitorString(monitor, GLFW_MONITOR_NAME)); + + for (i = 0; i < count; i++) + { + printf("%3u: %s", (unsigned int) i, format_mode(modes + i)); + + if (memcmp(&desktop_mode, modes + i, sizeof(GLFWvidmode)) == 0) + printf(" (desktop mode)"); + + putchar('\n'); + } + + free(modes); +} + +static void test_modes(GLFWmonitor monitor) +{ + int width, height; + size_t i, count; + GLFWvidmode* modes = get_video_modes(monitor, &count); + + glfwSetWindowSizeCallback(window_size_callback); + glfwSetWindowCloseCallback(window_close_callback); + glfwSetKeyCallback(key_callback); + + for (i = 0; i < count; i++) + { + GLFWvidmode* mode = modes + i; + + glfwOpenWindowHint(GLFW_RED_BITS, mode->redBits); + glfwOpenWindowHint(GLFW_GREEN_BITS, mode->greenBits); + glfwOpenWindowHint(GLFW_BLUE_BITS, mode->blueBits); + + printf("Testing mode %u on monitor %s: %s", + (unsigned int) i, + glfwGetMonitorString(monitor, GLFW_MONITOR_NAME), + format_mode(mode)); + + window = glfwOpenWindow(mode->width, mode->height, + GLFW_FULLSCREEN, "Video Mode Test", + NULL); + if (!window) + { + printf("Failed to enter mode %u: %s\n", + (unsigned int) i, + format_mode(mode)); + continue; + } + + glfwSetTime(0.0); + glfwSwapInterval(1); + + while (glfwGetTime() < 5.0) + { + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(); + glfwPollEvents(); + + if (!window) + { + printf("User terminated program\n"); + exit(EXIT_SUCCESS); + } + } + + if (glfwGetWindowParam(window, GLFW_RED_BITS) != mode->redBits || + glfwGetWindowParam(window, GLFW_GREEN_BITS) != mode->greenBits || + glfwGetWindowParam(window, GLFW_BLUE_BITS) != mode->blueBits) + { + printf("*** Color bit mismatch: (%i %i %i) instead of (%i %i %i)\n", + glfwGetWindowParam(window, GLFW_RED_BITS), + glfwGetWindowParam(window, GLFW_GREEN_BITS), + glfwGetWindowParam(window, GLFW_BLUE_BITS), + mode->redBits, + mode->greenBits, + mode->blueBits); + } + + glfwGetWindowSize(window, &width, &height); + + if (width != mode->width || height != mode->height) + { + printf("*** Size mismatch: %ix%i instead of %ix%i\n", + width, height, + mode->width, mode->height); + } + + printf("Closing window\n"); + + glfwCloseWindow(window); + glfwPollEvents(); + window = NULL; + } + + free(modes); +} + +int main(int argc, char** argv) +{ + int ch, mode = LIST_MODE; + GLFWmonitor monitor = NULL; + + while ((ch = getopt(argc, argv, "th")) != -1) + { + switch (ch) + { + case 'h': + usage(); + exit(EXIT_SUCCESS); + case 't': + mode = TEST_MODE; + break; + default: + usage(); + exit(EXIT_FAILURE); + } + } + + argc -= optind; + argv += optind; + + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + + while ((monitor = glfwGetNextMonitor(monitor))) + { + if (mode == LIST_MODE) + list_modes(monitor); + else if (mode == TEST_MODE) + test_modes(monitor); + } + + exit(EXIT_SUCCESS); +} + diff --git a/tests/peter.c b/tests/peter.c index 7c808229..b9f21f22 100644 --- a/tests/peter.c +++ b/tests/peter.c @@ -1,5 +1,5 @@ //======================================================================== -// Mouse cursor bug test +// Cursor input bug test // Copyright (c) Camilla Berglund // // This software is provided 'as-is', without any express or implied @@ -41,7 +41,7 @@ static int cursor_y; static GLboolean open_window(void); -static void toggle_mouse_cursor(GLFWwindow window) +static void toggle_cursor(GLFWwindow window) { if (glfwGetInputMode(window, GLFW_CURSOR_MODE) == GLFW_CURSOR_CAPTURED) { @@ -55,9 +55,9 @@ static void toggle_mouse_cursor(GLFWwindow window) } } -static void mouse_position_callback(GLFWwindow window, int x, int y) +static void cursor_position_callback(GLFWwindow window, int x, int y) { - printf("Mouse moved to: %i %i (%i %i)\n", x, y, x - cursor_x, y - cursor_y); + printf("Cursor moved to: %i %i (%i %i)\n", x, y, x - cursor_x, y - cursor_y); cursor_x = x; cursor_y = y; } @@ -69,7 +69,7 @@ static void key_callback(GLFWwindow window, int key, int action) case GLFW_KEY_SPACE: { if (action == GLFW_PRESS) - toggle_mouse_cursor(window); + toggle_cursor(window); break; } @@ -98,11 +98,11 @@ static GLboolean open_window(void) if (!window_handle) return GL_FALSE; - glfwGetMousePos(window_handle, &cursor_x, &cursor_y); - printf("Mouse position: %i %i\n", cursor_x, cursor_y); + glfwGetCursorPos(window_handle, &cursor_x, &cursor_y); + printf("Cursor position: %i %i\n", cursor_x, cursor_y); glfwSetWindowSizeCallback(window_size_callback); - glfwSetMousePosCallback(mouse_position_callback); + glfwSetCursorPosCallback(cursor_position_callback); glfwSetKeyCallback(key_callback); glfwSwapInterval(1); @@ -111,7 +111,7 @@ static GLboolean open_window(void) int main(void) { - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); diff --git a/tests/reopen.c b/tests/reopen.c index 484be996..2922cb84 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -84,7 +84,7 @@ static GLboolean open_window(int width, int height, int mode) { double base; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); return GL_FALSE; diff --git a/tests/sharing.c b/tests/sharing.c index 8be0e30b..6f1df980 100644 --- a/tests/sharing.c +++ b/tests/sharing.c @@ -27,6 +27,7 @@ // //======================================================================== +#define GLFW_INCLUDE_GLU #include #include @@ -92,8 +93,6 @@ static void draw_quad(GLuint texture) glBindTexture(GL_TEXTURE_2D, texture); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor3f(0.6f, 0.f, 0.6f); - glBegin(GL_QUADS); glTexCoord2f(0.f, 0.f); @@ -117,7 +116,7 @@ int main(int argc, char** argv) GLuint texture; int x, y; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); @@ -142,6 +141,11 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } + // Set drawing color for the first context and copy it to the second + glfwMakeContextCurrent(windows[0]); + glColor3f(0.6f, 0.f, 0.6f); + glfwCopyContext(windows[0], windows[1], GL_CURRENT_BIT); + // Put the second window to the right of the first one glfwGetWindowPos(windows[0], &x, &y); glfwSetWindowPos(windows[1], x + WIDTH + 50, y); diff --git a/tests/tearing.c b/tests/tearing.c index 044f8ecc..1eab454e 100644 --- a/tests/tearing.c +++ b/tests/tearing.c @@ -34,23 +34,42 @@ #include #include +static int swap_interval; + +static void set_swap_interval(int value) +{ + char title[256]; + + swap_interval = value; + glfwSwapInterval(swap_interval); + + sprintf(title, "Tearing detector (interval %i)", swap_interval); + glfwSetWindowTitle(glfwGetCurrentContext(), title); +} + static void window_size_callback(GLFWwindow window, int width, int height) { glViewport(0, 0, width, height); } +static void key_callback(GLFWwindow window, int key, int action) +{ + if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) + set_swap_interval(!swap_interval); +} + int main(void) { float position; GLFWwindow window; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Tearing Detector", NULL); + window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "", NULL); if (!window) { glfwTerminate(); @@ -59,8 +78,10 @@ int main(void) exit(EXIT_FAILURE); } + set_swap_interval(1); + glfwSetWindowSizeCallback(window_size_callback); - glfwSwapInterval(1); + glfwSetKeyCallback(key_callback); glMatrixMode(GL_PROJECTION); glOrtho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f); diff --git a/tests/title.c b/tests/title.c index 35344a04..7b342d94 100644 --- a/tests/title.c +++ b/tests/title.c @@ -41,7 +41,7 @@ int main(void) { GLFWwindow window; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); diff --git a/tests/windows.c b/tests/windows.c index f5844762..c7ff32b2 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -46,7 +46,7 @@ int main(void) GLboolean running = GL_TRUE; GLFWwindow windows[4]; - if (!glfwInit(NULL)) + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError()));